为什么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;
}
....
}
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算术来实现的讨论,但是存在效率问题,因为约束不是多态构造,所以创建算术约束可以解决这个问题。
我的(简化的)技术原因是静态方法不在虚表中,调用站点是在编译时选择的。这和你不能有覆盖或虚拟静态成员的原因是一样的。要了解更多细节,你需要一个计算机专业毕业生或编译专家——而我两者都不是。
出于政治原因,我将引用Eric Lippert(他是一名编译器专家,拥有滑铁卢大学的数学、计算机科学和应用数学学士学位)的话:
...静态方法的核心设计原则,给它们命名的原则是…在编译时,总是可以准确地确定将调用什么方法。也就是说,可以仅通过对代码的静态分析来解析该方法。
请注意,Lippert确实为所谓的类型方法留出了空间:
也就是说,与类型相关联的方法(如静态方法),它不接受不可空的“this”参数(与实例或虚拟方法不同),而是调用的方法依赖于T的构造类型(与静态方法不同,它必须在编译时确定)。
但还没有被它的实用性所说服。
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; } }
}