C# 结构体的限制。为什么它们是密封的?

4

我有点难以理解结构体的概念,而且没有人能回答我的问题。我知道它“像”一个对象,你可以有方法和字段。但我不明白为什么它们是密封的。为什么缺乏继承和多态性,这限制了它们的能力。在现实世界中真的有很多使用结构体的情况吗?我知道它们比对象小,只是我找不到任何真正的例子来帮助我理解其优点。谢谢。


2个回答

19

因为struct是一个值;包含float的结构体正好长4个字节。没有对象头指示具体类型是什么:知道类型的是编译器(以及生成的IL)-类型信息不是自包含在值中的。因此,常规多态性无法工作。如果你这样做:

MyType type = new MySubType(); // if this was a struct and if this compiled

从编译器的角度来看,这个类型是MyType。在赋值后,没有概念表明它是或曾经是MySubType。实际上,您可以使用unsafe代码将一个值类型的位强制转换为另一个。

此外,结构体的这个特性意味着您无法在子类型中添加字段:大小必须固定,这使得这种操作不可能。

基本上,如果您想到继承,那么您正在错误地使用struct;实际上,大多数时候我看到人们使用struct时都是在错误地使用它们。 struct应该表示(最好是不可变等)。


结构体真的有很多现实世界的用途吗?

是的,例如表示值的ComplexNumber类型;还有一些高度优化的场景,其中GC是禁止的,但这仅影响少数开发人员。这里有一个例子;另一个常见的例子是“游戏”,但是:在classstruct之间切换比更改关键字要复杂得多。您需要知道自己在做什么以及为什么这样做。

您不应该做的事情包括:

// ***BAD CODE: DO NOT DO***
public struct Customer
{ // I don't need inheritance; a struct will be faster and smaller
  // yay me, I'm awesome

    public int Id;
    public string Name;
}

上述内容最好表示为一个“类”。另外:属性。
引用:“我知道它们比对象小”。
在某些方面,这并不是真的;例如,大多数有用的“结构体”比引用更大——如果您在堆栈上传递超大型的“结构体”,而没有考虑到正在做什么,可能会出现问题。

+1 "在类和结构体之间切换比更改关键字要复杂得多"。来自游戏开发-完全同意。 - Engineer

1
这很简单。它是一个值类型,所有值类型都是密封的。虽然你可以从接口继承它。

3
这并未解答问题的“为什么”部分。 - David Heffernan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接