3

私は、インターフェース、ジェネリックを使用し、実際の環境で継承を使用してそれらを開発することに慣れていますが、これを使用して、今後のプロジェクトの1つで新しいアーキテクチャに実装しようとしていますが、ジェネリックについて質問があります。

.NETでこれが許可されない理由が理解できないため、これは私にとっては教育的な質問です。

ジェネリッククラスがある場合(Of T As IA, T2 As A)、次のインターフェイスと基本インターフェイスを実装するクラスがあります

Public Interface IA
  Property A As String
End Interface
Public Interface IB
  inherits IA
  Property B As String
End Interface

Public Class GenericClass(Of T As IA, T2 As A)
  'Should be list of IA?
  Public list As New List(Of T)
  Public Sub Add()
  End Sub
End Class

私がT as IAaddメソッドでなぜDim foo4 As T = New A()合法ではないのかを作ったので

Dim foo1 As IA = New A()
Dim foo2 As T
Dim foo3 = Activator.CreateInstance(Of T2)()
Dim x As IA = foo2
Dim y As IA = foo3
list.Add(x)
list.Add(y)

上記のすべては?これはジェネリック医薬品などの学習曲線になりつつありますが、論理的にこれができない理由と非常に混乱しています。

編集:申し訳ありませんが忘れClass Aてエラーメッセージは以下を参照してください

Public Class A
  Implements IA
  Public Property A As String Implements IA.A
End Class

編集2:エラーが間違って入力されました

「型クラスaの値をTに変換できません」

4

2 に答える 2

3

あなたが何をしようとしているのかは明確ではありませんが、私が気付いた問題の 1 つは、 aList<TypeThatImplementsIA>が何らかの形で a と交換可能であると想定しているように見えることですList<IA>。そうではありません。Aが飛ぶ鳥のクラスであり、飛ぶIAことができるクリーチャーによって実装され、誰かが を作成したと想像してくださいGenericClass<Airplane, BlueJay)AirplaneとはどちらもBlueJay飛ぶことができますが、 に を追加することはできませBlueJayList<Airplane>GenericType<DerivedType>フレームワークで a を aとして使用できる一般的な状況の 1 つGenericType<BaseType>は、IEnumerable<T>です。その理由は、 を に格納することはTできず、IEnumerable<T>読み取ることしかできないからです。を期待していて、IEnumerable<Animal>が与えられているIEnumerable<MaineCoonCat>場合、 を読むことを期待するたびにAnimalのインスタンスを読み取ります。MainCoonCatこれは から継承するAnimalため、それを置き換えることができます。のこの機能は共分散IEnumerable<T>と呼ばれます。

ただし、このような動作には制限があります。これは、インターフェースを格納場所のタイプ (変数、パラメーターなど) として使用することと、それを制約として使用することには違いがあるという事実に起因します。Null 非許容値の型ごとに、実際にはランタイム内に 2 つの関連する型があります。そのうちの 1 つは実数値型で、継承の概念はありません (ただし、インターフェイスを実装できます)。もう 1 つは、から派生するヒープ オブジェクト型ですValueType(これは から派生しますObject)。ほとんどの .net 言語は、前者の型を後者に暗黙的に変換し、コードが後者を前者に明示的に変換できるようにします。インターフェイス型の格納場所は、ヒープ オブジェクトへの参照のみを保持できます。これは、インターフェイスを実装する構造体がそのインターフェイス タイプに変換可能です。これは、構造のインスタンスがそのインターフェイス タイプのインスタンスであることを意味しません。共分散は、たとえば an によって返されるすべてのオブジェクトが、変換なしIEnumerable<DerivedType>で のインスタンスとして直接使用される可能性があるという前提で機能します。このような直接置換可能性は、継承されたクラス型、およびクラス型によって実装されるインターフェイスで機能します。構造体型によって実装されたインターフェイス、または構造体を持たないジェネリックでは機能しません。BaseType class制約。ジェネリック クラス型パラメーターにクラス制約を追加すると、その型パラメーターが共分散に参加できるようになりますが、ジェネリック型パラメーターとして構造体を使用できなくなる場合があります。インターフェースが構造体によって実装されることを期待する特別な理由がない限り (たとえばIComparable<T>、多くの場合、インターフェースが構造体によって実装される可能性は低いため、class制約は無害になります)。

于 2012-10-01T16:12:04.553 に答える
2

これTは、インターフェイスIA自体ではないためです。それの一つの実装です。

を実装する別のクラスがあるとしますIA

Public Class B
  Implements IA
  Public Property B_A As String Implements IA.A
  Public Property OtherProperty as Object
End Class

Generic Class次に、次のような新しいインスタンスを作成します。

Dim genericObject as new GenericClass(Of B, A)

したがって、この場合、Tnow はBであり、AにキャストすることはできませんB

この場合、代わりに、あなたの疑問の部分を置き換えます。私にとって意味のあるコードです:

Dim foo4 As IA = New T()

コメントによる編集

をインスタンス化できるようにするには、型定義で制約Tを宣言する必要があります。Newしたがって、ジェネリック クラス宣言は次のようになります。

Public Class GenericClass(Of T As {New, IA}, T2 As A)
于 2012-10-01T15:47:42.063 に答える