我有一个C#的类,它同时有一个静态和一个非静态接口。是否可以在一个类中有一个静态和一个非静态方法,并且具有相同的名称和签名?当我尝试这样做的时候,我得到了一个编译器错误,但是出于某种原因,我认为有一种方法可以做到这一点。是我错了还是没有办法在同一个类中同时拥有静态和非静态方法?如果这是不可能的,有没有一个好的方法来实现这样的东西,可以普遍适用于任何情况?
编辑
从我收到的回复来看,很明显没有办法做到这一点。我将使用一个不同的命名系统来解决这个问题。
dy1byipe1#
不,你不能。限制的原因是静态方法也可以从非静态上下文中调用,而不需要在类名之前添加(所以是MyStaticMethod()而不是MyClass.MyStaticMethod())。如果你有两个方法,编译器无法分辨你在找哪个方法。你可以有静态和非静态方法,它们的名字相同,但是不同的参数遵循与方法重载相同的规则,只是它们不能有完全相同的签名。
g52tjvyc2#
实际上,有一种方法可以通过显式实现接口来实现这一点。这不是一个完美的解决方案,但在某些情况下可以工作。
interface IFoo{ void Bar();}class Foo : IFoo{ static void Bar() { } void IFoo.Bar() { Bar(); }}
interface IFoo
{
void Bar();
}
class Foo : IFoo
static void Bar()
void IFoo.Bar()
Bar();
字符串当我为P/Pockerke调用创建 Package 器类时,我有时会遇到这种情况。
ijxebb2r3#
您可以从示例方法调用静态方法,而无需指定类型名称:
class Foo{ static void Bar() { } void Fizz() { Bar(); }}
class Foo
void Fizz()
字符串.所以不允许静态方法和示例方法具有相同的签名是有道理的。你想达到什么目的?在不知道细节的情况下很难提出解决方案。我只会重命名其中一个方法。
pjngdqdw4#
C#在这方面设计得不好。虽然你可能想要全局或非全局,但默认情况下它应该选择一个,如果你想要另一个,那么你只需更多地限定它。
class Logger { public static Logger instance; public static void Log(string message) { instance.Log(message); // currently the compiler thinks this is ambiguous, but really its not at all. Clearly we want the non-static method } public void Log(string message) { } public void DoStuff() { Log("doing instance stuff"); // this could be ambiguous, but in my opinion it should default to a call to this.Log() Logger.Log("doing global stuff"); // if you want the global qualify it explicitly }}
class Logger {
public static Logger instance;
public static void Log(string message) {
instance.Log(message); // currently the compiler thinks this is ambiguous, but really its not at all. Clearly we want the non-static method
public void Log(string message) {
public void DoStuff() {
Log("doing instance stuff"); // this could be ambiguous, but in my opinion it should default to a call to this.Log()
Logger.Log("doing global stuff"); // if you want the global qualify it explicitly
字符串
sdnqo3pr5#
你可以让静态方法和示例方法具有相同的名称,只要它们的声明在参数的数量或类型上不同。这与你如何在一个类中拥有两个同名的示例方法是一样的。虽然从技术上讲,在静态方法和示例方法的情况下,它们已经在示例方法中隐式this参数的存在方面有所不同,但这种差异不足以让编译器确定您想要调用两者中的哪一个。
更新:我弄错了,返回值不足以有不同的签名。
roqulrg36#
您可以添加可选参数
public class Logger{ public static Logger logger = new Logger(); public void Log(string? message) { Console.WriteLine(message); } public void LogStatic(string? message) { Log(message, null); } public static void Log(string? message, object? _ = null) { logger.Log(message); }}
public class Logger
public static Logger logger = new Logger();
public void Log(string? message)
Console.WriteLine(message);
public void LogStatic(string? message)
Log(message, null);
public static void Log(string? message, object? _ = null)
logger.Log(message);
字符串。
static void Main(string[] args){ Logger.logger.Log("..."); Logger.logger.LogStatic("..."); Logger.Log("...");}
static void Main(string[] args)
Logger.logger.Log("...");
Logger.logger.LogStatic("...");
Logger.Log("...");
型
z18hc3ub7#
可以使用扩展方法:
public class Foo{ public static void DoSomething(int parameter) { Console.WriteLine(parameter.ToString()); }}public static class FooExtensions{ public static void DoSomething(this Foo foo, int parameter) { Foo.DoSomething(parameter); }}
public class Foo
public static void DoSomething(int parameter)
Console.WriteLine(parameter.ToString());
public static class FooExtensions
public static void DoSomething(this Foo foo, int parameter)
Foo.DoSomething(parameter);
字符串如果它们没有使用包含扩展方法的名称空间,那么它就不起作用,但扩展方法总是如此,所以它并不完美。
7条答案
按热度按时间dy1byipe1#
不,你不能。限制的原因是静态方法也可以从非静态上下文中调用,而不需要在类名之前添加(所以是MyStaticMethod()而不是MyClass.MyStaticMethod())。如果你有两个方法,编译器无法分辨你在找哪个方法。
你可以有静态和非静态方法,它们的名字相同,但是不同的参数遵循与方法重载相同的规则,只是它们不能有完全相同的签名。
g52tjvyc2#
实际上,有一种方法可以通过显式实现接口来实现这一点。这不是一个完美的解决方案,但在某些情况下可以工作。
字符串
当我为P/Pockerke调用创建 Package 器类时,我有时会遇到这种情况。
ijxebb2r3#
您可以从示例方法调用静态方法,而无需指定类型名称:
字符串
.所以不允许静态方法和示例方法具有相同的签名是有道理的。
你想达到什么目的?在不知道细节的情况下很难提出解决方案。我只会重命名其中一个方法。
pjngdqdw4#
C#在这方面设计得不好。
虽然你可能想要全局或非全局,但默认情况下它应该选择一个,如果你想要另一个,那么你只需更多地限定它。
字符串
sdnqo3pr5#
你可以让静态方法和示例方法具有相同的名称,只要它们的声明在参数的数量或类型上不同。这与你如何在一个类中拥有两个同名的示例方法是一样的。
虽然从技术上讲,在静态方法和示例方法的情况下,它们已经在示例方法中隐式this参数的存在方面有所不同,但这种差异不足以让编译器确定您想要调用两者中的哪一个。
更新:我弄错了,返回值不足以有不同的签名。
roqulrg36#
您可以添加可选参数
字符串
。
型
z18hc3ub7#
可以使用扩展方法:
字符串
如果它们没有使用包含扩展方法的名称空间,那么它就不起作用,但扩展方法总是如此,所以它并不完美。