use*_*292 17 .net c# inheritance struct
我试着弄明白我的代码有什么问题.我有这个代码:
public struct MyStructA
{
public MyStructA(string str)
{
myString= str;
}
public string myString;
}
public struct MyStructB: MyStructA
{
public string myReversString;
}
Run Code Online (Sandbox Code Playgroud)
我得到这个错误:
Error at compile time: Type 'MyStructA' in interface list is not an interface
Run Code Online (Sandbox Code Playgroud)
我不明白为什么?.net不像类那样实现struct?
One*_*rew 31
结构是隐式密封的
根据这个链接:
C#中的每个结构,无论是用户定义的还是在.NET Framework中定义的,都是密封的 - 这意味着您无法继承它.结构被密封,因为它是一个值类型,并且所有值类型都是密封的.
struct可以实现一个接口,因此可以在结构名称之后看到冒号后面的另一个类型名称.
在下面的示例中,当我们尝试定义从上面定义的继承的新结构时,我们得到编译时错误.
public struct PersonName
{
public PersonName(string first, string last)
{
First = first;
Last = last;
}
public string First;
public string Last;
}
// Error at compile time: Type 'PersonName' in interface list is not an interface
public struct AngryPersonName : PersonName
{
public string AngryNickname;
}
Run Code Online (Sandbox Code Playgroud)
.NET 中的值类型很奇怪,因为它们定义为从称为 .NET 的特殊类派生的类ValueType。对于每个值类型,都有一个堆对象类型,其行为类似于派生自 的类对象ValueType,但值类型存储位置保存一个字节集合,该集合要么表示原始值,要么表示保存所有值所需的字节的串联。它的公共和私人领域。
由于值类型存储位置仅保存表示其值所需的字节,并且既不保存类型信息,也不保存对保存类型信息的对象的任何引用,因此使用值类型存储位置的代码必须确切地知道它是什么。
传统的继承要求对象保存有关其自身类型的信息,但没有规定值类型可以通过哪些方式来做到这一点。
从概念上讲,.NET 允许使用某些特殊规则进行某些有限形式的值类型继承是可能的(并且很有用),例如,虽然变量BaseStructure只能保存 aBaseStructure而不能保存DerivedStructure. 人们可以定义一个StructureUser<T> where T:BaseStructure,并且这样的类或方法可以接受 的任何派生BaseStructure基类型所共有的任何成员并使用这些成员(包括字段)。
不幸的是,很难为泛型定义规则,使其在允许的情况下表现一致,但又不破坏任何现有代码。
例如,在类中,Foo<T,U> where T:U始终可以将 a 存储T到类型 的变量U,即使U是值类型(即因为值类型是密封的,T并且U保证是相同的类型)。如果U可以是可继承的值类型并且T可以是派生类型,则这样的保证将不成立。
考虑到与此类继承相关的困难,更有用的替代方案是提供一种安全(即使有限)的方法,通过该方法属性可以公开 byref 或 const-byref(byref 是参数使用时传递的内容)预选赛ref)。
这样的功能将消除字段和属性之间不可避免的语义区别,并且根据其实现方式,即使与类一起使用也可以提供一些主要优势(例如,它可以允许不可变和可变类型的有效混合)。
其实有几个很好的理由:
结构没有“类型”
...除非它们被“装箱”到一个物体中。
object另一方面,An在普通 CLR 中有两个“标头”字段,用于存储类型(以及一些 GC 和锁定信息)。添加这会改变结构的大小,并使它们的大小不可预测(因为某些运行时可能会选择以不同的方式添加该信息,例如,mono 运行时向其对象添加比 .net 框架运行时更多的“标头”信息,或者在过去至少这样做过)
当您尝试将结构分配给它实现的接口字段时,实际上会发生这种装箱。因此,理论上这是可能的,但是所有的结构都会被装箱,出于性能原因,这真的很糟糕。
打字和固定尺寸
为了说明为什么专门继承结构会是一个大问题,让我们举一个简单的例子。
考虑两个结构:struct MyBaseStruct { public int A; }和一个假设的
struct MyDerivedStruct : MyBaseStruct { public int B; }.
现在当我打电话时会发生什么var array = new MyBaseStruct[10];?运行时会为此分配多少大小?
分配array[0] = new MyDerivedStruct();会很麻烦,在 32 位系统上它可能也会写入第一个和第二个插槽。
即使您尝试“收集”所有派生类型也是行不通的,如果您加载另一个定义了从基本结构派生的另一个结构的 dll 会怎样?
我个人认为首先了解可能导致设计师做出决定的实际问题非常重要。但当然,人们也可以只是说“因为语言的设计者做到了这一点!” 或“因为 C# 语言规范就是这么说的” :P