23

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

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はクラスのようなimplemnet構造体ではありませんか?

4

7 に答える 7

39

構造体は暗黙的に封印されています

このリンクによると:

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

構造体はインターフェースを実装できるため、構造体の名前の後に、コロンの後に別の型名を表示することができます。

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

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;
}
于 2013-03-14T12:01:35.957 に答える
4

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

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

于 2013-03-14T12:00:59.820 に答える
4

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

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

従来の継承では、オブジェクトが自身の型に関する情報を保持する必要がありますが、値型がそれを行うためのプロビジョニングはありません。

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

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

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

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

このような機能は、フィールドとプロパティの間の避けられない意味上の違いを取り除き、実装方法によっては、クラスで使用した場合でもいくつかの大きな利点を提供できます(たとえば、不変型と可変型の効率的な混合が可能になります)。

于 2013-03-14T19:33:24.473 に答える
2

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

于 2013-03-14T12:01:50.103 に答える
2

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

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

    ...オブジェクトに「ボックス化」されていない限り。

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

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

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

    構造体を具体的に継承することが大きな問題になる理由を示すために、簡単な例を見てみましょう。

    2つの構造体を考えてみましょう:struct MyBaseStruct { public int A; }と架空の struct MyDerivedStruct : MyBaseStruct { public int B; }

    今、私が電話するとどうなりますvar array = new MyBaseStruct[10];か?ランタイムはそれにどのくらいのサイズを割り当てますか?

    割り当てarray[0] = new MyDerivedStruct();は面倒です。32ビットシステムではおそらく最初のスロットと2番目のスロットにも書き込みます。

    すべての派生型を「収集」しようとしても機能しませんが、base-structから派生したさらに別の構造体を定義する別のdllをロードするとどうなりますか?

個人的には、デザイナーが最初に決断を下した原因となった実際の問題を知ることが非常に重要だと思います。しかしもちろん、「言語の設計者がそうしてくれたからです!」と言うこともできます。または「それがC#言語仕様の内容だからです」:P

于 2019-06-07T03:02:48.657 に答える
1

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

于 2013-03-14T12:05:27.697 に答える
0

からMSDN;

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

ただし、構造体は値型であり、継承するため、覚えておいてくださいSystem.ValueType

于 2013-03-14T12:02:21.663 に答える