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
的子类,您仍然无法调用 TM()
(这可能会简化 VM 的操作),更不用说编写不同的 M
在子类中实现并使用它。
因此,静态成员的“继承”看起来只是命名空间污染;即使您明确限定名称(即 BM
),A
的版本仍然可以解析。
编辑与命名空间比较:
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
的版本;如果您尝试这样做,编译器确实会报告错误。相比之下,如果我显式引用 BM()
,为什么编译器不报告错误?毕竟,“B”中没有“M”方法……
这个继承有什么目的呢?这个功能可以以某种方式建设性地使用吗?
In C#, a superclass's static members are "inherited" into the subclasses scope. For instance:
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()
Now, you can't inherit static classes, and the only place I can imagine that static inheritance might matter ignores it entirely: although you can make a generic constraint that requires a type parameter T
to be a subclass of A
, you still cannot call T.M()
(which probably simplifies things for the VM), let alone write a different M
implementation in a subclass and use that.
So, the "inheritance" of static members merely looks like namespace pollution; even if you explicitly qualify the name (i.e. B.M
) A
's version is still resolved.
Edit compare with namespaces:
namespace N1{ class X(); }
namespace N1.N2 { class X(); }
namespace N1.N2.N3 { [...] }
Within N1.N2.N3
It makes sense that if I use X
without qualification it refers to N1.N2.X
. But if I explicitly refer to N1.N2.N3.X
- and no such class exists - I don't expect it to find N2
's version; and indeed to compiler reports an error if you try this. By contrast, if I explicitly refer to B.M()
, why doesn't the compiler report an error? After all, there's no "M" method in "B"...
What purpose does this inheritance have? Can this feature be used constructively somehow?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
没错,只是一个人的污染是另一个人添加了辛辣调味品。
我认为 Martin Fowler 在他的 DSL 工作中建议以这种方式使用继承,以便方便地访问静态方法,从而允许在没有类名限定的情况下使用这些方法。因此,调用代码必须位于继承定义方法的类的类中。 (我认为这是一个糟糕的想法。)
在我看来,静态成员不应该混合到具有非静态目的的类中,并且您在这里提出的问题是不混合它们很重要的部分原因。
在“实例”类的实现中隐藏私有静态可变数据是特别可怕的。但还有静态方法,它们是更糟糕的混合器。这是混合到类中的静态方法的典型用法:
它是静态工厂方法模式。大多数时候这是毫无意义的,但更糟糕的是现在我们有了这个:
现在有一个静态
Make
方法,它返回一个Thing
,而不是AnotherThing< /代码>。
这种不匹配强烈意味着任何具有静态方法的东西都应该被密封。静态成员无法与继承很好地集成。让它们遗传是没有意义的。因此,我将静态的东西保存在单独的静态类中,并且当我已经说过该类是静态的时,我抱怨必须将每个成员声明为静态。
但这只是现在为时已晚的事情之一。所有真实的工作语言(以及库和产品)都有其中的一些。 C# 的数量非常少。
That's right, except that one guy's pollution is another guy's added spicy flavouring.
I think Martin Fowler, in his work on DSLs, has suggested using inheritance in this way to allow convenient access to static methods, allowing those methods to be used without class name qualification. So the calling code has to be in a class that inherits the class in which the methods are defined. (I think it's a rotten idea.)
In my opinion, static members should not be mixed into a class with a non-static purpose, and the issue you raise here is part of the reason why it's important not to mix them.
Hiding private static mutable data inside the implementation of an otherwise "instancey" class is particularly horrible. But then there are static methods, which are even worse mixers. Here's a typical use of static methods mixed into a class:
It's the static factory method pattern. It's pointless most of the time, but even worse is that now we have this:
This now has a static
Make
method which returns aThing
, not aAnotherThing
.This kind of mismatch strongly implies that anything with static methods should be sealed. Static members fail to integrate well with inheritance. It makes no sense to have them heritable. So I keep static things in separate static classes, and I gripe about redundantly having to declare every member static when I've already said that the class is static.
But it's just one of those too-late-now things. All real, working languages (and libraries, and products) have a few of them. C# has remarkably few.
我宁愿访问派生类中所有基于静态的成员。
否则我需要确切地知道静态成员的定义位置并显式调用它。
使用智能感知时,您可以自动知道该类可用的每个静态成员。
当然,它们不是继承的,只是一个捷径
I rather have access to all my based static members in derived classes.
Otherwise i would need to know exactly where the static member was defined and call it explicitly.
When using Intellisense you can automatically know every static member available to that kind of class.
Of course, they are not inherited, it's just a shortcut
这就是它的工作原理,在大多数情况下可能只是一个愚蠢的答案。但在这种情况下,它就是这样运作的;因为你从 A 派生,所以你说你是 A + 你添加的额外功能。
因此,您需要能够访问与通过 A 实例访问相同的变量。
但是,继承静态类没有任何意义,而访问静态成员/字段/方法则有意义。
示例如下:
测试如下所示:
两个 WriteLines 都输出“Second Test”,这是因为 BaseUser 和 User 都应使用 DefaultUserPool,按设计。并且重写静态实现的方法没有多大意义,因为它只是子类中的访问器。
只能有一个。覆盖它意味着该子类有一个新的实现,这将消除术语“静态”。
That's how it works, would probably just be a stupid answer in most cases. But in this case, it is how it works; since you derive from A you say that you are A + the extra features you add.
Therefore you need to be able to access the same variables that you would through an instance of A.
However, inheriting a static class makes no sense while access to the static members / fields / methods does.
An example of this is the following:
Where the test looks like this:
Both of the WriteLines outputs "Second Test", this is because both BaseUser and User should use DefaultUserPool, by design. And overriding static implemented methods wouldn't make mucn sense since it's just an accessor in the child-class.
There can be only one. Overriding it would mean that there's a new implementation for that sub-class, which would kill the term "static".
实际上,据我了解,这只是编译器提供的一个快捷方式。语法糖。
BM()
只会编译为AM()
,因为 B 没有static M()
而 A 有。就是为了方便写,没有别的。不存在“静态继承”。补充:“重新定义”时对
new
的要求只是为了避免你不小心搬起石头砸自己的脚。Actually, as I understand it, this is just a shortcut provided by the compiler. Syntax sugar.
B.M()
will just compile toA.M()
since B does not have astatic M()
and A does. It's for easier writing, nothing else. There is no "static inheritance".Added: And the requirement for
new
when "redefining" is just so that you don't accidentally shoot yourself in the foot.我认为它用于访问基类的受保护静态成员。
I think it's for accessing protected static members of the base class.
那么...还有什么选择呢?
问题提到...
但是“B”中有派生的“M”方法班级。
如果编译器没有为程序员提供用于基本情况的统一虚拟表,那么程序员将不得不遍历基本类型来查找静态方法。这会破坏多态性。
维基百科...
So... What's the alternative?
The question mentions...
But there is a derived "M" method in "B" class.
If the compiler did not present the programmer a unified virtual table for base cases, then the programmer would have to go hunting through base types to find static methods. This would break polymorphism.
Wikipedia...
我总是认为这是一种通过继承类来防止您希望为所有子类保留相同功能的项目的任何形式的多态性的方法。
出于某种原因忽略上述内容,我正在考虑密封而不是静态
我想您会使用静态成员变量和函数以确保任何数据或功能都是不依赖于类实例,因为它只会实例化一次。
使用的一个例子是一个计数器值,它将保留超类的子类的所有实例的实时计数(每个子类在构造时递增静态计数值)。该计数值对于子类的所有实例都是可用且相等的。
I always see it a means of preventing any form of polymorphism by the inheriting class on those items that you wish to retain the same function for all child classes.
ignore the above for some reason I was thinking of sealed instead of static
I suppose that you'd use static member variables and functions in order to ensure that any data or functionallity is not dependent on the a class instance as it would be instantiated only the once.
An example of use would be say a counter value that would keep a live count of all instances of a superclass's subclasses (each subclass increments the static count value on construction). This count value would be available and equal for all instances of the subclass.