为什么 C# 不允许静态方法实现接口?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/259026/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 20:16:58  来源:igfitidea点击:

Why Doesn't C# Allow Static Methods to Implement an Interface?

c#ooplanguage-features

提问by Kramii

Why was C# designed this way?

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

As I understand it, an interface only describes behaviour, and serves the purpose of describing a contractual obligation for classes implementing the interface that certain behaviour is implemented.

据我了解,接口仅描述行为,并且用于描述实现特定行为的接口的类的契约义务。

If classes wish to implement that behavour in a shared method, why shouldn't they?

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

Here is an example of what I have in mind:

这是我想到的一个例子:

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

    ....

 }

采纳答案by Chris Marasti-Georg

Assuming you are asking why you can't do this:

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

public interface IFoo {
    void Bar();
}

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

This doesn't make sense to me, semantically. Methods specified on an interface should be there to specify the contract for interacting with an object. Static methods do not allow you to interact with an object - if you find yourself in the position where your implementation could be made static, you may need to ask yourself if that method really belongs in the interface.

从语义上讲,这对我来说没有意义。接口上指定的方法应该在那里指定与对象交互的契约。静态方法不允许您与对象交互 - 如果您发现自己处于可以使实现静态化的位置,您可能需要问自己该方法是否真的属于接口。



为了实现您的示例,我会给 Animal 一个 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; }
}

For a more complicated situation, you could always declare another static method and delegate to that. In trying come up with an example, I couldn't think of any reason you would do something non-trivial in both a static and instance context, so I'll spare you a FooBar blob, and take it as an indication that it might not be a good idea.

对于更复杂的情况,您始终可以声明另一个静态方法并委托给它。在尝试提出一个例子时,我想不出有什么理由让你在静态和实例上下文中做一些重要的事情,所以我会给你一个 FooBar blob,并把它作为它可能的指示不是一个好主意。

回答by Joel Coehoorn

Because interfaces are in inheritance structure, and static methods don't inherit well.

因为接口是继承结构,静态方法继承不好。

回答by James Curran

Short-sightedness, I'd guess.

我猜是近视。

When originally designed, interfaces were intended only to be used with instances of class

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

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

It was only with the introduction of interfaces as constraints for generics did adding a static method to an interface have a practical use.

只有引入了接口作为泛型的约束,才能向接口添加静态方法才有实际用途。

(responding to comment:) I believe changing it now would require a change to the CLR, which would lead to incompatibilities with existing assemblies.

(回应评论:)我相信现在更改它需要更改 CLR,这将导致与现有程序集的不兼容。

回答by John Kraft

Interfaces specify behavior of an object.

接口指定对象的行为。

Static methods do not specify a behavior of an object, but behavior that affects an object in some way.

静态方法不指定对象的行为,而是以某种方式影响对象的行为。

回答by AnthonyWJones

What you seem to want would allow for a static method to be called via both the Type or any instance of that type. This would at very least result in ambiguity which is not a desirable trait.

您似乎想要的是允许通过 Type 或该类型的任何实例调用静态方法。这至少会导致模棱两可,这不是理想的特征。

There would be endless debates about whether it mattered, which is best practice and whether there are performance issues doing it one way or another. By simply not supporting it C# saves us having to worry about it.

关于它是否重要,哪种是最佳实践以及是否存在性能问题,会有无休止的争论。通过简单地不支持它,C# 使我们不必担心它。

Its also likely that a compilier that conformed to this desire would lose some optimisations that may come with a more strict separation between instance and static methods.

符合这种愿望的编译器也可能会失去一些优化,这些优化可能会在实例方法和静态方法之间进行更严格的分离。

回答by Scott Langham

Interfaces are abstract sets of defined available functionality.

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

Whether or not a method in that interface behaves as static or not is an implementation detail that should be hidden behind the interface. It would be wrong to define an interface method as static because you would be unnecessarily forcing the method to be implemented in a certain way.

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

If methods were defined as static, the class implementing the interface wouldn't be as encapsulated as it could be. Encapsulation is a good thing to strive for in object oriented design (I won't go into why, you can read that here: http://en.wikipedia.org/wiki/Object-oriented). For this reason, static methods aren't permitted in interfaces.

如果方法被定义为静态的,那么实现接口的类就不会像它本来的那样封装。在面向对象的设计中,封装是一件好事(我不会解释为什么,你可以在这里阅读:http: //en.wikipedia.org/wiki/Object-oriented)。因此,接口中不允许使用静态方法。

回答by Daniel Auger

FYI: You could get a similar behavior to what you want by creating extension methods for the interface. The extension method would be a shared, non overridable static behavior. However, unfortunately, this static method would not be part of the contract.

仅供参考:通过为接口创建扩展方法,您可以获得与您想要的类似的行为。扩展方法将是一个共享的、不可覆盖的静态行为。然而,不幸的是,这种静态方法不会成为合同的一部分。

回答by Scott Langham

You can think of the static methods and non-static methods of a class as being different interfaces. When called, static methods resolve to the singleton static class object, and non-static methods resolve to the instance of the class you deal with. So, if you use static and non-static methods in an interface, you'd effectively be declaring two interfaces when really we want interfaces to be used to access one cohesive thing.

您可以将类的静态方法和非静态方法视为不同的接口。调用时,静态方法解析为单例静态类对象,非静态方法解析为您处理的类的实例。因此,如果您在接口中使用静态和非静态方法,当我们真的希望使用接口来访问一个内聚的事物时,您实际上是在声明两个接口。

回答by mackenir

I think the short answer is "because it is of zero usefulness". To call an interface method, you need an instance of the type. From instance methods you can call any static methods you want to.

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

回答by Mark Brackett

My (simplified) technical reason is that static methods are not in the vtable, and the call site is chosen at compile time. It's the same reason you can't have override or virtual static members. For more details, you'd need a CS grad or compiler wonk - of which I'm neither.

我的(简化的)技术原因是静态方法不在vtable 中,并且在编译时选择调用站点。这与您不能拥有覆盖或虚拟静态成员的原因相同。有关更多详细信息,您需要 CS 毕业生或编译器专家 - 我两者都不是。

For the political reason, I'll quote Eric Lippert(who is a compiler wonk, and holds a Bachelor of Mathematics, Computer science and Applied Mathematics from University of Waterloo (source: LinkedIn):

出于政治原因,我将引用 Eric Lippert(他是一名编译器专家,拥有滑铁卢大学数学、计算机科学和应用数学学士学位(来源:LinkedIn):

...the core design principle of static methods, the principle that gives them their name...[is]...it can always be determined exactly, at compile time, what method will be called. That is, the method can be resolved solely by static analysis of the code.

...静态方法的核心设计原则,给它们命名的原则...[是]...总是可以准确地确定,在编译时,将调用什么方法。也就是说,该方法可以仅通过代码的静态分析来解决。

Note that Lippert does leave room for a so-called type method:

请注意,Lippert 确实为所谓的类型方法留出了空间:

That is, a method associated with a type (like a static), which does not take a non-nullable “this” argument (unlike an instance or virtual), but one where the method called would depend on the constructed type of T (unlike a static, which must be determinable at compile time).

也就是说,一种与类型(如静态)相关联的方法,它不接受不可为空的“this”参数(与实例或虚拟不同),但调用的方法将取决于 T 的构造类型(与静态不同,静态必须在编译时确定)。

but is yet to be convinced of its usefulness.

但尚未确信其有用性。