为什么我不能inheritance静态类?
我有几个不需要任何状态的类。 从组织的angular度来看,我想把它们分层次。
但似乎我不能声明静态类的inheritance。
类似的东西:
public static class Base { } public static class Inherited : Base { }
不pipe用。
为什么这个语言的devise者closures了这种可能性呢?
从这里引用:
这实际上是通过devise。 inheritance一个静态类似乎没有什么好的理由。 它有公共的静态成员,你可以随时通过类名自己访问。 我见过的inheritance静态东西的唯一原因是坏的,比如保存了一些打字的字符。
可能有理由考虑将静态成员直接带入范围的机制(实际上我们将在Orcas产品周期之后考虑这一点),但是静态类inheritance并不是一个可行的方法:这是一个错误的机制,仅适用于发生在静态类中的静态成员。
(Mads Torgersen,C#语言PM)
来自channel9的其他意见
.NET中的inheritance只适用于实例库。 静态方法是在types级别而不是在实例级别上定义的。 这就是为什么重写不适用于静态方法/属性/事件…
静态方法只在内存中保存一次。 没有为他们创build的虚拟表等。
如果你在.NET中调用一个实例方法,你总是给它当前的实例。 这是隐藏的.NET运行时,但它发生。 每个实例方法都有一个指向运行该方法的对象的指针(引用)作为第一个参数。 这不会发生静态方法 (因为它们是在types级别上定义的)。 编译器应该如何决定select调用的方法?
(littleguru)
作为一个有价值的想法, littleguru在这个问题上有一个部分“解决方法”: Singleton模式。
你不能inheritance静态类的主要原因是它们是抽象的和封闭的(这也阻止了它们的任何实例被创build)。
所以这:
static class Foo { }
编译到这个IL:
.class private abstract auto ansi sealed beforefieldinit Foo extends [mscorlib]System.Object { }
这样想一下:通过types名称访问静态成员,如下所示:
MyStaticType.MyStaticMember();
如果您要从该类inheritance,则必须通过新的types名称来访问它:
MyNewType.MyStaticMember();
因此,在代码中使用新项目时与原始项目没有任何关系。 没有办法像多态性那样利用任何inheritance关系。
也许你认为你只是想扩展原始类的一些项目。 在这种情况下,没有任何东西可以阻止你使用全新types的原件。
也许你想添加方法到现有的静态types。 你可以通过扩展方法来做到这一点。
也许你希望能够在运行时将一个静态Type
传递给一个函数,并且调用这个types的方法,而不知道这个方法是干什么的。 在这种情况下,你可以使用一个接口。
所以,最终你并没有从inheritance静态类获得任何东西。
你想通过使用类层次结构来实现,只能通过命名空间来实现。 所以支持名称空间的语言(如C#)将不能使用静态类的类层次结构。 既然你不能实例化任何类,你只需要一个层次结构的类定义,你可以通过命名空间
您可以使用组合来代替…这将允许您从静态types访问类对象。 但仍然不能实现接口或抽象类
虽然可以通过inheritance的类名访问“inheritance的”静态成员,但静态成员并不是真正的inheritance。 这部分地是为什么他们不能是虚拟的或抽象的,不能被覆盖。 在你的例子中,如果你声明了一个Base.Method(),编译器会将一个调用映射到Base.Method()。 你也可以直接调用Base.Method()。 您可以编写一个小testing,并用Reflector查看结果。
所以…如果你不能inheritance静态成员,并且静态类只能包含静态成员,那么inheritance一个静态类会有什么好处呢?
嗯…如果你只是有非静态类填充静态方法会有很大的不同..?
你可以做一些看起来像静态inheritance的东西。
诀窍是:
public abstract class StaticBase<TSuccessor> where TSuccessor : StaticBase<TSuccessor>, new() { protected static readonly TSuccessor Instance = new TSuccessor(); }
那么你可以这样做:
public class Base : StaticBase<Base> { public Base() { } public void MethodA() { } } public class Inherited : Base { private Inherited() { } public new static void MethodA() { Instance.MethodA(); } }
Inherited
类本身不是静态的,但我们不允许创build它。 它实际上已经inheritance了构buildBase
静态构造函数,并且Base
所有属性和方法都是静态的。 现在唯一需要做的事情是为每个需要暴露给静态上下文的方法和属性制作静态包装器。
有需要手动创build静态包装方法和new
关键字的缺点。 但是这种方法有助于支持与静态inheritance类似的东西。
PS我们使用这个来创build编译查询,这实际上可以用ConcurrentDictionary来替代,但静态只读字段的线程安全性已经足够好了。
静态类和类成员用于创build可以访问的数据和函数,而无需创build类的实例。 静态类成员可以用来分离独立于任何对象标识的数据和行为:不pipe对象发生什么,数据和函数都不会改变。 当类中没有依赖于对象标识的数据或行为时,可以使用静态类。
一个类可以被声明为静态,这表明它只包含静态成员。 使用new关键字创build静态类的实例是不可能的。 当加载包含类的程序或名称空间时,静态类将由.NET Framework公共语言运行库(CLR)自动加载。
使用静态类来包含不与特定对象关联的方法。 例如,创build一组不会影响实例数据并且不与代码中的特定对象关联的方法是常见的要求。 你可以使用静态类来保存这些方法。
以下是静态类的主要特点:
-
他们只包含静态成员。
-
他们不能被实例化。
-
他们被密封。
-
它们不能包含实例构造函数(C#编程指南)。
因此,创build静态类基本上与创build仅包含静态成员和私有构造函数的类相同。 私有构造函数阻止类被实例化。
使用静态类的优点是编译器可以检查以确保没有实例成员被意外添加。 编译器将保证不能创build这个类的实例。
静态类是封闭的,因此不能被inheritance。 它们不能从Object以外的任何类inheritance。 静态类不能包含实例构造函数; 不过,他们可以有一个静态的构造函数。 有关更多信息,请参阅静态构造函数(C#编程指南)。
你可以做的解决方法是不使用静态类,但隐藏构造函数,因此类静态成员是唯一可以在类之外访问的东西。 结果是一个可inheritance的“静态”类本质上:
public class TestClass<T> { protected TestClass() { } public static T Add(T x, T y) { return (dynamic)x + (dynamic)y; } } public class TestClass : TestClass<double> { // Inherited classes will also need to have protected constructors to prevent people from creating instances of them. protected TestClass() { } } TestClass.Add(3.0, 4.0) TestClass<int>.Add(3, 4) // Creating a class instance is not allowed because the constructors are inaccessible. // new TestClass(); // new TestClass<int>();
不幸的是,由于“devise”的语言限制,我们不能这样做:
public static class TestClass<T> { public static T Add(T x, T y) { return (dynamic)x + (dynamic)y; } } public static class TestClass : TestClass<double> { }
当我们创build一个只包含静态成员和一个私有构造函数的静态类时,唯一的原因是静态构造函数阻止了该类被实例化,因为我们不能inheritance一个静态类。访问成员的唯一方法是静态类通过使用类名本身。尝试inheritance静态类不是一个好主意。