这是不可能从一个C#结构继承。这不是明显对我来说这是为什么:
It's not possible to inherit from a C# struct. It's not obvious to me why this is:
显然,你不能有继承值类型引用类型;这将无法正常工作 这听起来并不合理地从一个继承原始类型(的Int32,双人间,字符等) 您就需要能够调用(非虚拟)使用派生的实例的基础上的方法。可以投从派生结构的基础上,因为它们将重叠相同的存储器。我猜从基地派生是行不通的,因为你不可能不知道派生结构在运行时的类型转换。 在我看得出来你无法实现你的类层次结构中的虚拟方法,因为值类型不能有虚成员我不知道这是在CLR的技术限制,或者一些C#编译器阻止你在干什么?
I wonder if this is a technical limitation in the CLR, or something that the C# compiler stops you from doing?
编辑:值类型不能有虚方法,我意识到这个限制排除了大多数情况下,您会希望使用继承。这仍然留下遗产,为聚集,虽然。想象一下,一个图形
结构与颜色
字段:我可以写code,它接受来自图形,并访问其颜色字段,即使我不能写一个虚拟的 Shape.Draw
方法。
Value types can't have virtual methods, and I realise this limitation rules out most scenarios in which you'd want to use inheritance. That still leaves inheritance-as-aggregation, though. Imagine a Shape
struct with a Colour
field: I can write code that accepts any struct derived from Shape
, and access its Colour
field, even if I can never write a virtual Shape.Draw
method.
我能想到一个场景,将获得由非密封值类型破碎。值类型都应该实施等于
和 GetHash code
正确;即使在 System.Object的
这两种方法都是虚拟的,他们得到所谓的非无形中就值类型。即使值类型是不密封的,写的人从另一个衍生的结构不能写自己的实现这两种方法,并希望让他们正确调用。
I can think of one scenario that would get broken by non-sealed value types. Value types are supposed to implement Equals
and GetHashCode
correctly; even though these two methods on System.Object
are virtual, they get called non-virtually on value types. Even if value types weren't sealed, someone writing a struct derived from another one couldn't write their own implementation of these two methods and expect to have them called correctly.
我要指出的是,我并不是说我应该能够从结构继承自己的code。我试图做的,虽然是猜测,为什么这个特殊的code气味是由.NET禁止的。
I should point out that I'm not suggesting I should be able to inherit from structs in my own code. What I am trying to do, though, is to guess why this particular code smell is forbidden by .NET.
编辑2:我只是看上此非常类似的问题,答案是有效的,因为这样的价值类型的数组是行不通的。
Edit 2: I just spotted this very similar question, the answer to which is effectively "because then arrays of value types wouldn't work".
的原因是,大多数遗传技术涉及到运行时多态性(虚拟函数)和那些没有价值类型的工作:为运行时多态性有任何意义,对象需要被当作参考 - 这是不是专门针对.NET或者,它只是功能如何虚拟实现技术细节
The reason is that most inheritance techniques relate to runtime polymorphism (virtual functions) and those don’t work on value types: for runtime polymorphism to have any meaning, objects need to be treated as references – this isn’t specific to .NET either, it’s simply a technical detail of how virtual functions are implemented.
值类型形成一个例外。NET的规则,precisely让轻的物体不通过引用需要间接。所以运行时多态性不为他们工作和继承的许多方面变得毫无意义。
Value types form an exception to .NET’s rule, precisely to allow lightweight objects that don’t require indirection via references. So runtime polymorphism doesn’t work for them and most aspects of inheritance become meaningless.
(这里有一个例外:数值类型的对象可以盒装,它允许从 System.Object的
继承了被称为虚拟方法)
(There’s an exception: a value type object can be boxed, which allows for virtual methods inherited from System.Object
to be called.)
要解决的要点之一:
您可以投从派生结构的基础上,因为它们将重叠相同的存储器。没有,这是不可能的 - 铸件值类型会的复制的它的价值。我们不处理此引用,所以在内存中没有重叠。铸造一个值类型其基本类型,因此意义(同样,除非我们在谈论转化为对象
这实际上引擎盖下进行拳击,和也的操作上的复制的值)。
No, this would not be possible – casting a value type would copy its value. We’re not dealing with references here, so no overlap in memory. Casting a value type to its base type is therefore meaningless (again, unless we’re talking about conversion to object
which actually performs boxing under the hood, and also operates on a copy of the value).
还不清楚?让我们来看一个例子。
Still not clear? Let’s look at an example.
比方说,我们已经得到了假想结构形状
,然后从它继承,在结构圆
。 图形
定义了一个虚拟的绘图
方法(它接受一个图形
目的)。现在,让我们说,我们要画的形状的画布上。这当然,工作得很好:
Let’s say we’ve got the hypothetical struct Shape
and, inheriting from it, the struct Circle
. Shape
defines a virtual Draw
method (which accepts a Graphics
object). Now, let’s say we want to draw a shape on a canvas. This, of course, works perfectly well:
var circle = new Circle(new Point(10, 10), 20);
circle.Draw(e.Graphics); // e.Graphics = graphics object of our form.
- 但在这里,我们实际上并不使用继承的。要使用继承,而不是想象以下 DrawObject
helper方法:
– But here we don’t actually use inheritance at all. To make use of inheritance, imagine instead the following DrawObject
helper method:
void DrawObject(Shape shape, Graphics g) {
// Do some preparation on g.
shape.Draw(g);
}
和我们称之为外地与圆
:
var circle = new Circle(new Point(10, 10), 20);
DrawObject(circle, e.Graphics);
- 和 KA-BLAM - 这code不画了一个圈。为什么?因为当我们通过圈内的 DrawObject
方法,我们做两件事情:
– And, ka-blam – this code doesn’t draw a circle. Why? Because when we pass the circle to the DrawObject
method, we do two things:
形状
对象实际上不再是圆
- 既不是原来的,也不是一个副本。相反,它的圆
部分被切走在复制,只有图形
部分保持。 shape.Draw
现在调用 图形
的画
的方法,没有的圆
。
We copy it.
We slice it, i.e. the object shape
object is really no longer a Circle
– neither the original one nor a copy. Instead, its Circle
portion was "sliced" away during copying and only the Shape
portion remains. shape.Draw
now calls the Draw
method of Shape
, not of Circle
.
在C ++中,你实际上可以导致此行为。因此,面向对象的C ++仅适用于指针和引用,而不是直接值类型。而对于同样的原因,.NET只允许引用类型的继承,因为你无法使用它的值类型反正。
In C++, you can actually cause this behaviour. For that reason, OOP in C++ only works on pointers and references, not on value types directly. And for that same reason, .NET only allows inheritance of reference types because you couldn’t use it for value types anyway.
请注意,上面的code的确实的工作,.NET,如果图形
是一个接口。换句话说,一个的引用的类型。现在情况不同了:你的圆
对象会的还是的被复制,但它也将被装箱为基准
Notice that the above code does work in .NET if Shape
is an interface. In other words, a reference type. Now the situation is different: your circle
object will still be copied but it will also be boxed into a reference.
现在,.NET的可以的理论让你继承结构
从类
。接着上面的code将工作一样好,如果图形
是一个接口。但随后,其全优势结构
在首位消失:为所有意图和目的(除了本地变量其中的永远的获得通过另一种方法,继承因此没有效用)的结构
将表现为一个不可变的引用类型而不是值类型。
Now, .NET could theoretically allow you to inherit a struct
from a class
. Then the above code would work just as well as if Shape
were an interface. But then, the whole advantage of having a struct
in the first place vanishes: for all intents and purposes (except for local variables which never get passed to another method, hence no utility of inheritance) your struct
would behave as an immutable reference type instead of a value type.