为什么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;
    }

    ....

 }

当前回答

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

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

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

其他回答

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

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

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

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

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

例如:

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

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

Regarding static methods used in non-generic contexts I agree that it doesn't make much sense to allow them in interfaces, since you wouldn't be able to call them if you had a reference to the interface anyway. However there is a fundamental hole in the language design created by using interfaces NOT in a polymorphic context, but in a generic one. In this case the interface is not an interface at all but rather a constraint. Because C# has no concept of a constraint outside of an interface it is missing substantial functionality. Case in point:

T SumElements<T>(T initVal, T[] values)
{
    foreach (var v in values)
    {
        initVal += v;
    }
}

这里没有多态性,泛型使用对象的实际类型并调用+=操作符,但这失败了,因为它不能确定该操作符是否存在。简单的解决方案是在约束中指定它;简单的解决方案是不可能的,因为操作符是静态的,静态方法不能在接口中,(这就是问题所在)约束被表示为接口。

c#需要的是一个真正的约束类型,所有的接口都是约束,但不是所有的约束都是接口,然后你可以这样做:

constraint CHasPlusEquals
{
    static CHasPlusEquals operator + (CHasPlusEquals a, CHasPlusEquals b);
}

T SumElements<T>(T initVal, T[] values) where T : CHasPlusEquals
{
    foreach (var v in values)
    {
        initVal += v;
    }
}

已经有很多关于为所有数字类型创建i算术来实现的讨论,但是存在效率问题,因为约束不是多态构造,所以创建算术约束可以解决这个问题。

I think the question is getting at the fact that C# needs another keyword, for precisely this sort of situation. You want a method whose return value depends only on the type on which it is called. You can't call it "static" if said type is unknown. But once the type becomes known, it will become static. "Unresolved static" is the idea -- it's not static yet, but once we know the receiving type, it will be. This is a perfectly good concept, which is why programmers keep asking for it. But it didn't quite fit into the way the designers thought about the language.

因为它不可用,所以我采用如下所示的方式使用非静态方法。虽然不太理想,但至少对我来说,我找不到比这更有意义的方法了。

public interface IZeroWrapper<TNumber> {
  TNumber Zero {get;}
}

public class DoubleWrapper: IZeroWrapper<double> {
  public double Zero { get { return 0; } }
}

静态类应该能够做到这一点,这样它们就可以被通用地使用。我不得不实现一个Singleton来实现预期的结果。

我有一堆静态业务层类,实现了CRUD方法,如“创建”,“读取”,“更新”,“删除”的每个实体类型,如“用户”,“团队”等。然后,我为实现CRUD方法的业务层类创建了一个具有抽象属性的基本控件。这让我可以自动从基类中执行“创建”、“读取”、“更新”、“删除”操作。由于静态限制,我不得不使用单例。