CSharp - 为何C#不允许静态方法实现一个Interface?

  显示原文与译文双语对照的内容

为什么 C# 是这样设计的?

就像我所理解的那样,接口只描述行为,它用于描述实现接口的类,该类实现了某些行为。

如果类希望在共享方法中实现该 behavour,为什么它们不应该?

下面是我所想到的一个例子:


//These items will be displayed in a list on the screen.
public interface IListItem {
 string ScreenName();
. . .
}

public class Animal: IListItem {
//All animals will be called"Animal".
 public static string ScreenName() {
 return"Animal";
 }
....
}

public class Person: IListItem {

 private string name;

//All persons will be called by their individual names.
 public string ScreenName() {
 return name;
 }

. . ..

 }

时间:

假设你正在询问为什么不能这样做:


public interface IFoo {
 void Bar();
}

public class Foo: IFoo {
 public static void Bar() {}
}

这对我来说毫无意义。 在接口上指定的方法应用于指定与对象交互的协定。 静态方法不允许你与对象交互- 如果你发现自己的实现可以成为静态的,那么你可能需要问自己该方法是否真的属于接口。


为了实现你的示例,我将给动物一个const属性,它仍然允许从静态上下文访问它,并在实现中返回该值。

public class Animal: IListItem {
/* Can be tough to come up with a different, yet meaningful name!
 * A different casing convention, like Java has, would help here.
 */
 public const string AnimalScreenName ="Animal";
 public string ScreenName(){ return AnimalScreenName; }
}

对于更复杂的情况,你可以总是声明另一个静态方法并委托给。 在尝试想出一个例子中,我想不出任何理由你会做一些non-trivial静态和实例上下文中,我将让你foobarblob,把它作为一个迹象表明,它可能不是一个好主意。

这里的大多数答案似乎漏掉了整个点。 多态不仅可以在实例之间使用,也可以在类型之间使用。 当我们使用泛型时,这通常是需要的。

假设泛型方法中有类型参数,我们需要执行一些操作。 我们不想 instantinate,因为我们不知道构造函数。

例如:


Repository GetRepository<T>()
{
//need to call T.IsQueryable, but can't!!!
//need to call T.RowCount
//need to call T.DoSomeStaticMath(int param)
}

...
var r = GetRepository<Customer>()

不幸的是,我只能使用"ugly"选项:

  • 使用反射 Ugly丑陋的界面和多态性。

  • 创建完全独立的工厂类

    这可能会大大增加代码的复杂性。 例如如果我们试图建模域对象,每个对象都需要另一个存储库类。

  • 实例化,然后调用所需的接口方法

    这可能很难实现,即使我们控制类的源代码,用作泛型参数。 原因是,我们可能需要只在已知的"连接到数据库"状态中使用实例。

例如:


public class Customer 
{
//create new customer
 public Customer(Transaction t) {.. . }

//open existing customer
 public Customer(Transaction t, int id) {.. . }

 void SomeOtherMethod() 
 { 
//do work...
 }
}

为了使用instantination来解决静态接口问题,我们需要做以下事情:


public class Customer: IDoSomeStaticMath
{
//create new customer
 public Customer(Transaction t) {.. . }

//open existing customer
 public Customer(Transaction t, int id) {.. . }

//dummy instance
 public Customer() { IsDummy = true; }

 int DoSomeStaticMath(int a) { }

 void SomeOtherMethod() 
 { 
 if(!IsDummy) 
 {
//do work...
 }
 }
}

这显然是丑陋的,而且也不需要其他方法的代码复杂。 显然,不是一个优雅的解决方案 !

因为接口的目的是允许多态性,所以能够传递任意数量定义的类的实例,这些定义的类都已经定义为实现定义的接口。 确保在多态调用中,代码能够找到你正在调用的方法。 允许静态方法实现接口没有意义,

你怎么称呼它?



public interface MyInterface { void MyMethod(); }
public class MyClass: MyInterface
{
 public static void MyMethod() {//Do Something; }
}

//inside of some other class.. . 
//How would you call the method on the interface???
 MyClass.MyMethod();//this calls the method normally 
//not through the interface...

//This next fails you can't cast a classname to a different type... 
//Only instances can be Cast to a different type...
 MyInterface myItf = MyClass as MyInterface; 

Short-sightedness,我猜。

最初设计时,接口只用于类的实例


IMyInterface val = GetObjectImplementingIMyInterface();
val.SomeThingDefinedinInterface();

它仅仅是将接口引入到泛型的约束中,将静态方法添加到接口有一个实际的使用。

( 回应评论:) 我认为现在更改它需要对CLR进行更改,这将导致与现有程序集不兼容。

...