2013-06-10 16 views
6

私は最近実装したカスタムユーザーコントロールにインターフェイスを追加しました。インターフェイスはかなり基本的です。ジェネリック、インターフェイス、キャストに関する問題

Public Interface IMyInterface(Of T As WebControl) 
    Function DoSomething() As T 
End Interface 

実装はまた、かなり基本的なもの:

Public Class MyCustomControl 
    Inherits CompositeControl 
    Implements IMyInterface(Of MyCustomControl) 

Public Function DoSomething() As MyCustomControl _ 
    Implements IMyInterface(Of MyCustomControl).DoSomething 
    ' do stuff 

    Return Me 
End Class 

すべてが、この時点までに正常に動作しますこれは、チェーン化をサポートしてい一つの方法を持っています。

Dim myList = New List(Of IMyInterface(Of WebControl)) 

myList.Add(someCustomControl) 

myList.ForEach(Sub(i) i.DoSomething()) 

someCustomControlIMyInterface(Of MyCustomControl)代わりのIMyInterface(Of WebControl)実装MyCustomControlです:私はすべてのようにのように、IMyInterfaceインタフェースを実装するコントロールのコレクションをループしようとすると問題が生じます。

私は(私はsomeCustomControlを追加しよう)二行目に、このエラーを取得しています:

オプション厳密には、「(WebBrowserコントロールの)IMyInterfaceという」から「MyCustomControl」からの暗黙的な変換を禁止します。

このエラーを回避する手段はありますか?私はそれが働くことに近いですが、私はこの点を超えてジェネリックについて十分に知りません。

+0

あなたは 'Dim myList =新しいリスト(Of WebControl)'のようにmyListを宣言しようとしますが、 'Dim myList =新しいリスト(Of Object)'などを試してみてください。 – Vishal

+0

@Vishal 'IMyInterface'型を持たずに、' ForEach'ループ内のオブジェクトに対して 'DoSomething()'を呼び出すことができないと思います。 – jbabey

+0

申し訳ありませんが、私はそれを知りませんでした。 – Vishal

答えて

4

共分散は、VS 2010で導入された言語機能であり、問​​題を解決します。

 
Public Interface IMyInterface(Of Out T As WebControl) 
    Function DoSomething() As T 
End Interface 

あなたがOutキーワードを使用する場合、あなたは共分散を使用している:あなたはタイプTは、その前にOutキーワードを持っていることを、あなたの一般的なように定義する必要があります。これにより、ベースタイプのジェネリックの代わりに、より派生したタイプのジェネリックを使用することができます。したがって、あなたのケースでは、コード(通常、あなたのforループなど)が予想される場所でIMyInterface(Of MyCustomControl))オブジェクトが許可されます。

共分散には制限があります。共変タイプTは、関数の戻り値としてのみ使用でき、関数(またはサブ)へのパラメータとしては使用できません。例えばIMyInterfaceDoSomething署名はこのように見えた場合、コンパイラは文句を言うでしょう:

は、あなたの連鎖シナリオを考えると
' Here the type T is used as an input param - compiler error 
Sub DoSomething(ByVal sampleArg As T) 

、私は上記の制限が問題ではないと思います。MSDNで

詳細:

+0

これはまさに私が探していたものです。ありがとうございました。 – jbabey

0

あなたはそれを追加する前にオブジェクトをキャストする必要があります。

myList.Add(CType(someCustomControl, IMyInterface(Of WebControl))) 

あなたはまた、インタフェース自体として汎用的で、あなたの「DoWork」メソッドの戻り値の型ではないインターフェースを作るconciderすることもできます。

Public Interface IMyInterface 
    Function DoSomething() As IMyInterface 
End Interface 

あなたはそれが一種の(実装について知る必要がない)インターフェースの電源から奪うインタフェース定義でタイプを指定する必要があります。

+0

連鎖機能を壊さずに動作させたい場合 – jbabey

+0

それ自身を返すインターフェイスがチェーン機能を満たさない場合は、インターフェイスを再設計するか、インターフェイスを使用しないでください。あるいは、同じことをする 'WebControl'の基本クラスを書くこともできます。 – Jay

1

私はあなたの関数DoSomethingが何をするかわからないが、私は、テスト目的のためにそこにあるインスタンスののCssClassを割り当ててみてください。

次のようにインターフェースを宣言します。

Public Interface IMyInterface(Of Out T As WebControl) 
    Function DoSomething() As T 
End Interface 

お知らせOut Tパラメータを。

インタフェースを実装する2つのコントロールを作成します。テストページのPageLoadイベントで

Public Class MyCustomControl1 
    Inherits CompositeControl 
    Implements IMyInterface(Of MyCustomControl1) 

    Public Function DoSomething() As MyCustomControl1 Implements IMyInterface(Of MyCustomControl1).DoSomething 
     ' do stuff 
     Me.CssClass = "XXX" 
     Return Me 
    End Function 

End Class 

Public Class MyCustomControl2 
    Inherits CompositeControl 
    Implements IMyInterface(Of MyCustomControl2) 

    Public Function DoSomething() As MyCustomControl2 Implements IMyInterface(Of MyCustomControl2).DoSomething 
     ' do stuff 
     Me.CssClass = "YYY" 
     Return Me 
    End Function 

End Class 

を:

Dim someCustomControl As New MyCustomControl1 
Dim someCustomControl2 As New MyCustomControl2 

Dim myList = New List(Of IMyInterface(Of WebControl)) 

myList.Add(someCustomControl) 
myList.Add(someCustomControl2) 

myList.ForEach(Sub(i) Literal1.Text &= i.DoSomething.CssClass & "<br />") 

結果は、両方のsomeCustomControl & someCustomControl2のCssClassプロパティがそれぞれに設定されています値。

これは、インターフェイス関数DoSomethingが正常に呼び出され、インスタンスが変更されたことを示しています。

+0

「Out」は私が行方不明だったものです。ありがとうございました。 – jbabey

関連する問題