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

根据我的理解,一个接口只描述行为,并且服务于描述实现接口的类的契约义务。

如果类希望在共享方法中实现这种行为,为什么不应该呢?

以下是我想到的一个例子:

// 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;
    }

    ....

 }

当前回答

这里的大多数答案似乎都没有抓住重点。多态性不仅可以在实例之间使用,还可以在类型之间使用。当我们使用泛型时,这是经常需要的。

假设我们在泛型方法中有类型参数,我们需要对它做一些操作。我们不想实例化,因为我们不知道构造函数。

例如:

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>()

不幸的是,我只能想出一些“丑陋”的选择:

Use reflection Ugly and beats the idea of interfaces and polymorphism. Create completely separate factory class This might greatly increase the complexity of the code. For example, if we are trying to model domain objects, each object would need another repository class. Instantiate and then call the desired interface method This can be hard to implement even if we control the source for the classes, used as generic parameters. The reason is that, for example we might need the instances to be only in well-known, "connected to DB" state.

例子:

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

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

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

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

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...
    }
  }
}

这显然是丑陋的,也是不必要的,会使所有其他方法的代码复杂化。显然,这也不是一个优雅的解决方案!

其他回答

从概念上讲,接口没有理由不能定义包含静态方法的契约。

对于当前的c#语言实现,限制是由于允许继承基类和接口。如果“类SomeBaseClass”实现了“接口ISomeInterface”和“类SomeDerivedClass: SomeBaseClass, ISomeInterface”也实现了接口,实现接口方法的静态方法将会编译失败,因为静态方法不能与实例方法具有相同的签名(实例方法将出现在实现接口的基类中)。

静态类在功能上与单例类相同,并且具有与单例类相同的目的,只是语法更简洁。因为单例可以实现接口,所以静态的接口实现在概念上是有效的。

因此,这可以简单地归结为c#的实例名称冲突和跨继承的同名静态方法的限制。c#没有理由不能“升级”以支持静态方法契约(接口)。

接口是已定义可用功能的抽象集合。

该接口中的方法是否表现为静态行为是应该隐藏在接口后面的实现细节。将接口方法定义为静态是错误的,因为您将不必要地强制该方法以某种方式实现。

如果方法被定义为静态的,那么实现接口的类就不会像它应该的那样被封装。在面向对象设计中,封装是一件值得努力的事情(我不会详细说明原因,你可以在这里阅读:http://en.wikipedia.org/wiki/Object-oriented)。因此,在接口中不允许使用静态方法。

当类实现接口时,它是在为接口成员创建实例。虽然静态类型没有实例,但在接口中使用静态签名是没有意义的。

您可以将类的静态方法和非静态方法看作是不同的接口。调用时,静态方法解析为单例静态类对象,而非静态方法解析为所处理的类的实例。所以,如果你在一个接口中使用静态和非静态方法,你实际上是在声明两个接口,而实际上我们想要接口被用来访问一个内聚的东西。

我认为简单的答案是“因为它毫无用处”。 要调用接口方法,需要该类型的实例。从实例方法中,您可以调用任何您想要的静态方法。