簡體   English   中英

繼承自struct

[英]Inherit from struct

我試着弄明白我的代碼有什么問題。 我有這個代碼:

public struct MyStructA
{
    public MyStructA(string str)
    {
        myString= str;
    }

    public string myString;
}

public struct MyStructB: MyStructA
{
    public string myReversString;
}

我得到這個錯誤:

Error at compile time: Type 'MyStructA' in interface list is not an interface

我不明白為什么? .net不像類那樣實現struct?

結構是隱式密封的

根據這個鏈接

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;
}

.NET中的值類型很奇怪,因為它們是定義的,雖然它們是從名為ValueType的特殊類派生的類。 對於每種值類型,都有一個堆對象類型,其行為類似於從ValueType派生的類對象,但值類型存儲位置包含一個字節集合,這些字節表示原始值,或者是保存所有字節所需的字節串聯其公共和私人領域。

由於值類型存儲位置只保存表示其值所需的字節,並且既不保存類型信息也不保存對包含類型信息的對象的任何引用,因此使用值類型存儲位置的代碼必須確切地知道它是什么。

傳統的繼承要求對象保存有關其自身類型的信息,但是沒有提供值類型可以這樣做的規定。

.NET在概念上可能(並且有用)允許一些有限形式的值類型繼承和一些特殊規則,這樣,雖然BaseStructure變量只能容納BaseStructure並且不能保存DerivedStructure 可以定義一個StructureUser<T> where T:BaseStructure ,這樣的類或方法可以接受BaseStructure任何衍生物,並使用那些基本類型共有的成員 - 包括字段。

不幸的是,很難定義泛型規則,以便在允許的場景中表現一致,但不會破壞任何現有代碼。

例如,在類Foo<T,U> where T:U總是可以將T存儲到U類型的變量,即使U是值類型(即因為值類型被密封, TU被保證是相同的類型)。 如果U可以是可繼承的值類型而T可以是衍生的,那么這種保證就不會成立。

鑒於與此類繼承相關的困難,更有用的替代方法是提供一種安全(即使是有限的)方法,通過該方法,屬性可以公開byref或const-byref(byref是參數使用時傳遞的東西) ref資格賽)。

這樣的特征將消除字段和屬性之間不可避免的語義區別,並且取決於它的實現方式即使在與類一起使用時也可以提供一些主要優點(例如,它可以允許有效混合不可變類型和可變類型)。

Struct不支持繼承,如果你需要使用class,請參閱msdn

結構沒有繼承,就像類一樣。 結構不能從另一個結構或類繼承,也不能作為類的基礎。 但是,結構繼承自基類Object。 結構可以實現接口,它就像類一樣完成。

結構之間不允許繼承,但結構可以實現接口。

結構可以實現接口,但它們不能從另一個結構繼承。 因此,不能將struct成員聲明為protected。

來自MSDN ;

結構沒有繼承,就像類一樣 結構不能從另一個結構或類繼承,也不能作為類的基礎。 但是,結構繼承自基類Object。 結構可以實現接口,它就像類一樣完成。

但請記住,因為結構是一種值類型 ,它們繼承System.ValueType

實際上有幾個很好的理由:

  1. 結構沒有“類型”

    ......除非他們被“盒裝”成一個物體。

    另一方面, object在普通CLR中有兩個“標題”字段,其中存儲了類型(以及一些GC和鎖定信息)。 添加它會改變結構的大小,並使它們的大小不可預測(因為某些運行時可能選擇以不同方式添加該信息,例如單聲道運行時向其對象添加比.net框架運行時更多的“標題”信息,或者過去最少這樣做了)

    實際上,當您嘗試將結構分配給它實現的接口字段時,會出現這種情況。 所以在理論上它是可能的,但是然后你的所有結構都會被裝箱,而且出於性能原因這真的很糟糕。

  2. 打字和固定大小

    為了說明為什么專門繼承結構將是一個巨大的問題,讓我們舉一個簡單的例子。

    考慮兩個結構: struct MyBaseStruct { public int A; } struct MyBaseStruct { public int A; }和一個假設的struct MyDerivedStruct : MyBaseStruct { public int B; } struct MyDerivedStruct : MyBaseStruct { public int B; }

    現在當我調用var array = new MyBaseStruct[10];時會發生什么var array = new MyBaseStruct[10]; ?? 運行時為此分配多少大小?

    賦值array[0] = new MyDerivedStruct(); 會很麻煩,在32位系統上,它可能寫入第一個第二個插槽。

    即使你試圖“收集”所有派生類型它也行不通,如果你加載另一個定義了另一個從你的base-struct派生的結構的dll呢?

我個人認為,了解可能導致設計人員首先做出決定的實際問題非常重要。 但當然一個人也可以說“因為語言的設計者就是這么做的!” 或者“因為這就是C#語言規范所說的” :P

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM