一尘不染

C#静态成员“继承”-为什么这根本存在?

c#

在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在子类中编写其他实现并使用它了。

因此,静态成员的“继承”仅看起来像名称空间污染;即使您明确限定了名称(即B.MA的版本,仍然可以解决。

编辑 与名称空间比较:

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”方法。

这种继承有什么目的?可以以某种方式建设性地使用此功能吗?


阅读 526

收藏
2020-05-19

共1个答案

一尘不染

因此,静态成员的“继承”仅看起来像命名空间污染

没错,只是一个人的污染是另一个人的辛辣味。

我认为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

这种不匹配强烈暗示着任何带有静态方法的东西都应该密封。静态成员无法很好地与继承集成。让它们遗传是没有意义的。因此,我将静态事物保存在单独的静态类中,当我已经说过该类是静态的时,我不得不冗余地将每个成员声明为静态。

但这只是那些太迟了的事情之一。所有实际的工作语言(以及库和产品)都有其中一些。C#很少。

2020-05-19