C# 静态成员“继承” - 为什么会存在?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2281775/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C# static member "inheritance" - why does this exist at all?
提问by Eamon Nerbonne
In C#, a superclass's static members are "inherited" into the subclasses scope. For instance:
在 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()
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.
现在,你不能继承静态类,我能想象到静态继承可能很重要的唯一地方完全忽略它:虽然你可以创建一个需要类型参数T
是 的子类的泛型约束A
,你仍然不能调用T.M()
(哪个可能会简化 VM 的事情),更不用说M
在子类中编写不同的实现并使用它了。
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.
所以,静态成员的“继承”只是命名空间污染;即使您明确限定名称(即B.M
)A
的版本仍然被解析。
Editcompare 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"...
在N1.N2.N3
这是有道理的,如果我使用X
无资质它指的是N1.N2.X
。但是,如果我明确提到N1.N2.N3.X
- 并且不存在这样的类 - 我不希望它找到N2
的版本;如果您尝试这样做,确实编译器会报告错误。相比之下,如果我明确引用B.M()
,为什么编译器不报告错误?毕竟,“B”中没有“M”方法......
What purpose does this inheritance have? Can this feature be used constructively somehow?
这个继承有什么目的?可以以某种方式建设性地使用此功能吗?
采纳答案by Daniel Earwicker
So, the "inheritance" of static members merely looks like namespace pollution
所以,静态成员的“继承”只是看起来像命名空间污染
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.)
我认为 Martin Fowler 在他关于 DSL 的工作中建议以这种方式使用继承来方便地访问静态方法,允许在没有类名限定的情况下使用这些方法。因此,调用代码必须位于继承定义方法的类的类中。(我认为这是一个烂主意。)
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 mutabledata 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:
在其他“实例”类的实现中隐藏私有静态可变数据特别可怕。但是还有静态方法,它们是更糟糕的混合器。这是混合到类中的静态方法的典型用法:
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();
}
}
It's the static factory method pattern. It's pointless most of the time, but even worse is that now we have this:
这是静态工厂方法模式。大多数时候这是毫无意义的,但更糟糕的是,现在我们有了:
public class AnotherThing : Thing { }
This now has a static Make
method which returns a Thing
, not a AnotherThing
.
这现在有一个静态Make
方法,它返回 a Thing
,而不是 a AnotherThing
。
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.
但这只是那些为时已晚的事情之一。所有真正的工作语言(以及库和产品)都有其中的一些。C# 的数量非常少。
回答by Filip Ekberg
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.
这就是它的工作原理,在大多数情况下可能只是一个愚蠢的答案。但在这种情况下,它是如何工作的;因为你是从 A 派生出来的,所以你说你是 A + 你添加的额外功能。
Therefore you need to be able to access the same variables that you would through an instance of A.
因此,您需要能够访问与通过 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:
一个例子如下:
internal class BaseUser
{
public static string DefaultUserPool { get; set; }
}
internal class User : BaseUser
{
public int Id { get; set; }
public string Name { get; set; }
public User Parent { get; set; }
}
Where the test looks like this:
测试如下所示:
User.DefaultUserPool = "Test";
BaseUser.DefaultUserPool = "Second Test";
Console.WriteLine(User.DefaultUserPool);
Console.WriteLine(BaseUser.DefaultUserPool);
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.
两个 WriteLines 输出“第二次测试”,这是因为 BaseUser 和 User 都应该使用 DefaultUserPool,按设计。并且覆盖静态实现的方法没有意义,因为它只是子类中的访问器。
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".
只可以有一个人。覆盖它意味着该子类有一个新的实现,这将杀死术语“静态”。
回答by ChrisBD
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.
一个使用示例是一个计数器值,它将保持超类子类的所有实例的实时计数(每个子类在构造时增加静态计数值)。该计数值对于子类的所有实例都可用且相等。
回答by TrueWill
I think it's for accessing protected static members of the base class.
我认为它用于访问基类的受保护静态成员。
class Base
{
protected static void Helper(string s)
{
Console.WriteLine(s);
}
}
class Subclass : Base
{
public void Run()
{
Helper("From the subclass");
}
}
回答by Vilx-
Actually, as I understand it, this is just a shortcut provided by the compiler. Syntax sugar. B.M()
will just compile to A.M()
since B does not have a static M()
and A does. It's for easier writing, nothing else. There is no "static inheritance".
实际上,据我了解,这只是编译器提供的快捷方式。语法糖。B.M()
只会编译为,A.M()
因为 B 没有 astatic M()
而 A 有。这是为了更容易写作,没有别的。没有“静态继承”。
Added:And the requirement for new
when "redefining" is just so that you don't accidentally shoot yourself in the foot.
补充:new
“重新定义”的要求只是为了你不会不小心射到自己的脚上。
回答by Luis Filipe
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.
使用 Intellisense 时,您可以自动了解该类可用的每个静态成员。
Of course, they are not inherited, it's just a shortcut
当然,它们不是继承的,只是一个捷径
回答by kervin
So... What's the alternative?
那么......有什么选择?
The question mentions...
问题提到...
why doesn't the compiler report an error? After all, there's no "M" method in "B"...
为什么编译器不报错?毕竟,“B”中没有“M”方法......
But there isa derived "M"method in "B"class.
但是派生“M”在方法“B”类。
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...
维基百科...
Subtype polymorphism, almost universally called just polymorphism in the context of object-oriented programming, is the ability of one type, A, to appear as and be used like another type, B....
In strongly typed languages, polymorphism usually means that type A somehow derives from type B, or type C implements an interface that represents type B.
子类型多态性,在面向对象编程的上下文中几乎普遍称为多态性,是一种类型 A 可以像另一种类型 B 一样出现和使用的能力。
在强类型语言中,多态通常意味着类型 A 以某种方式从类型 B 派生,或者类型 C 实现了表示类型 B 的接口。