web-dev-qa-db-ja.com

構造体から継承

私は私のコードの何が問題なのかを理解しようとしています。私はこのコードを持っています:

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はクラスのような構造体を実装していませんか?

18
user2110292

構造体は暗黙的にシールされています

これによると link

C#のすべての構造体は、ユーザー定義であるか、.NET Frameworkで定義されているかに関係なく、シールされています。つまり、それらから継承することはできません。構造体は値型であり、すべての値型がシールされているため、シールされています。

構造体はインターフェースを実装できるため、構造体の名前の後にコロンの後に別の型名が表示される可能性があります。

以下の例では、上記で定義されたものから継承する新しい構造体を定義しようとすると、コンパイルエラーが発生します。

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;
}
29
One Man Crew

.NETの値型は、ValueTypeという特別なクラスから派生したクラスですが、定義されているという点で奇妙です。すべての値型について、ValueTypeから派生するクラスオブジェクトのように動作するヒープオブジェクト型がありますが、値型の格納場所には、プリミティブ値を表すバイトのコレクション、またはすべてを保持するために必要なバイトの連結のいずれかが保持されますパブリックおよびプライベートフィールドの。

値型の格納場所は、それらの値を表すために必要なバイトを保持し、型情報も、型情報を保持するオブジェクトへの参照も保持しないため、値型の格納場所を使用するコードは、それが何であるかを正確に知る必要があります。

従来の継承では、オブジェクトが自身のタイプに関する情報を保持する必要がありますが、値タイプがそれを行うための規定はありません。

.NETは、BaseStructure変数がBaseStructureしか保持できず、DerivedStructureを保持できないなど、いくつかの特別なルールを使用して、値タイプの継承のいくつかの制限された形式を許可することは、概念的に可能(かつ便利)です。 StructureUser<T> where T:BaseStructure、およびそのようなクラスまたはメソッドは、BaseStructureの派生物を受け入れて、基本型に共通のメンバー(フィールドを含む)を使用できます。

残念ながら、許可されたシナリオで一貫して動作し、しかも既存のコードを壊さないようにジェネリックのルールを定義することは困難です。

たとえば、クラス内でFoo<T,U> where T:UTが値型であっても、Uを型Uの変数に格納することは常に可能です(つまり、値型がシールされているため、TU同じ型であることが保証されています)。 Uが継承可能な値の型であり、Tが派生物である可能性がある場合、そのような保証は成り立ちません。

そのような継承に関連する困難を考えると、より有用な代替手段は、プロパティがbyrefまたはconst-byrefを公開できる安全な(制限されている場合でも)手段を提供することです(byrefは、パラメーターが使用されるときに渡されるものです) ref修飾子)。

このような機能は、フィールドとプロパティの不可避なセマンティックの違いを取り除き、実装方法によっては、クラスで使用した場合でもいくつかの主要な利点を提供できます(たとえば、不変タイプと可変タイプの効率的な混合を可能にします)。

4
supercat

Structは継承をサポートしていません。クラスを使用する必要がある場合は、 msdn を参照してください。

クラスのように構造体の継承はありません。構造体は別の構造体またはクラスから継承できず、クラスのベースになることはできません。ただし、構造体は基本クラスのオブジェクトを継承します。構造体はインターフェースを実装でき、クラスとまったく同じようにそれを行います。

3
Adil

構造体間での継承は許可されていませんが、構造体はインターフェイスを実装できます。

1
boli

構造体はインターフェイスを実装できますが、別の構造体から継承することはできません。そのため、構造体メンバーは保護されていると宣言できません。

1
user2110287

実際にはいくつかの理由があります。

  1. 構造には「タイプ」がありません

    ...それらがオブジェクトに「ボックス化」されている場合を除きます。

    一方、objectには、タイプが格納される通常のCLRに2つの「ヘッダー」フィールド(およびいくつかのGCおよびロック情報)があります。これを追加すると、構造体のサイズが変更され、そのサイズが予測不能になります(一部のランタイムはその情報を別の方法で追加することを選択した可能性があるため、たとえば、モノラルランタイムは.netフレームワークランタイムよりも「ヘッダー」情報をオブジェクトに追加するため、または過去に少なくともそうした)

    このボクシングは、構造体を実装するインターフェイスフィールドに構造体を割り当てようとしたときに実際に何が起こるかです。したがって、理論的には可能ですが、すべての構造体がボックス化され、パフォーマンス上の理由からそれは非常に悪いことになります。

  2. タイピングと固定サイズ

    構造体の継承が大きな問題になる理由を示すために、簡単な例を挙げましょう。

    _struct MyBaseStruct { public int A; }_と架空の_struct MyDerivedStruct : MyBaseStruct { public int B; }_の2つの構造体を考えます。

    ここで、_var array = new MyBaseStruct[10];_を呼び出すとどうなりますか?ランタイムはそのためにどのくらいのサイズを割り当てますか?

    割り当てarray[0] = new MyDerivedStruct();は厄介ですが、32ビットシステムでは、おそらく最初の[〜#〜]および[〜#〜] 2番目のスロットも同様です。

    すべての派生型を「収集」しようとしても機能しませんが、ベース構造から派生したさらに別の構造を定義する別のdllをロードするとどうなるでしょうか。

私は個人的に、おそらくデザイナーを最初に決定に導いた実際の問題を知ることはかなり重要だと思います。しかしもちろん、「言語の設計者が作ったので、単に(== --- ==)」と言うこともできます!」または "それはC#言語仕様が言っていることだからです」:P

0
Riki

から MSDN ;

クラスのように構造体の継承はありません。構造体は別の構造体またはクラスから継承できず、クラスのベースになることもできません。ただし、構造体は基本クラスのオブジェクトを継承します。構造体はインターフェースを実装でき、クラスとまったく同じようにそれを行います。

ただし、構造体は値タイプであり、それらは System.ValueType

0
Soner Gönül