在C#中,超类的静态成员被“继承”到子类范围内。例如:
class A { public static int M() { return 1; } } class B : A {} class C : A { public new static int M() { return 2; } } [...] A.M(); //returns 1 B.M(); //returns 1 - this is equivalent to A.M() C.M(); //returns 2 - this is not equivalent to A.M()
现在,您无法继承静态类,而我能想象的唯一静态继承可能会完全忽略它:尽管您可以创建一个通用约束,该约束要求类型参数T是的子类A,但是您仍然无法调用T.M()(可能简化了VM的工作),更不用说M在子类中编写其他实现并使用它了。
T
A
T.M()
M
因此,静态成员的“继承”仅看起来像名称空间污染;即使您明确限定了名称(即B.M)A的版本,仍然可以解决。
B.M
编辑 与名称空间比较:
namespace N1{ class X(); } namespace N1.N2 { class X(); } namespace N1.N2.N3 { [...] }
内在N1.N2.N3是有意义的,如果我X不加限定地使用它指的是N1.N2.X。但是,如果我明确提到N1.N2.N3.X-并且不存在这样的类- 我不希望它找到N2的版本;如果您尝试这样做,确实会向编译器报告错误。相比之下,如果我明确引用B.M(),为什么编译器不报告错误?毕竟,“ B”中没有“ M”方法。
N1.N2.N3
X
N1.N2.X
N1.N2.N3.X
N2
B.M()
这种继承有什么目的?可以以某种方式建设性地使用此功能吗?
因此,静态成员的“继承”仅看起来像命名空间污染
没错,只是一个人的污染是另一个人的辛辣味。
我认为Martin Fowler在有关DSL的工作中曾建议以这种方式使用继承,以允许方便地访问静态方法,从而允许使用这些方法而无需类名限定。因此,调用代码必须在继承定义方法的类的类中。(我认为这是一个烂主意。)
我认为,不应将静态成员混合到具有非静态目的的类中,并且您在此处提出的问题是不混合它们的重要性的部分原因。
将私有静态 可变 数据隐藏在否则为“ instancey”类的实现内部特别可怕。但是,还有静态方法,甚至是更差的混频器。这是混合使用静态方法的典型用法:
public class Thing { // typical per-instance stuff int _member1; protected virtual void Foo() { ... } public void Bar() { ... } // factory method public static Thing Make() { return new Thing(); } }
这是静态工厂方法模式。在大多数时候,这毫无意义,但是更糟糕的是,现在我们有了这个:
public class AnotherThing : Thing { }
现在,它具有一个静态Make方法,该方法返回a Thing而不是a AnotherThing。
Make
Thing
AnotherThing
这种不匹配强烈暗示着任何带有静态方法的东西都应该密封。静态成员无法很好地与继承集成。让它们遗传是没有意义的。因此,我将静态事物保存在单独的静态类中,当我已经说过该类是静态的时,我不得不冗余地将每个成员声明为静态。
但这只是那些太迟了的事情之一。所有实际的工作语言(以及库和产品)都有其中一些。C#很少。