4

以下のコードは、1つがC#で、もう1つがVB.Netであることを除いて、まったく同じです。C#は問題なくコンパイルされますが、VB.Netは警告をスローします。

インターフェイス'System.IObserver(Of Foo)'は、'インターフェイスIObserver(Of In T)'の'In'および'Out'パラメータのため、別の実装されたインターフェイス'System.IObserver(Of Bar)'とあいまいです。

VB.NetがC#ではなく警告を表示するのはなぜですか?そして最も重要なのは、どうすればこの問題を解決できますか?

Obs:Visual Studio2010Ultimateで.NetFramework4を使用しています。

VB.Netコード:

Module Module1

    Sub Main()

    End Sub

    Public Class Foo
    End Class
    Public Class Bar
    End Class
    Public Class Beholder
        Implements IObserver(Of Foo)
        Implements IObserver(Of Bar)

#Region "Impl"
        Public Sub OnCompleted() Implements System.IObserver(Of Bar).OnCompleted

        End Sub

        Public Sub OnError([error] As System.Exception) Implements System.IObserver(Of Bar).OnError

        End Sub

        Public Sub OnNext(value As Bar) Implements System.IObserver(Of Bar).OnNext

        End Sub

        Public Sub OnCompleted1() Implements System.IObserver(Of Foo).OnCompleted

        End Sub

        Public Sub OnError1([error] As System.Exception) Implements System.IObserver(Of Foo).OnError

        End Sub

        Public Sub OnNext1(value As Foo) Implements System.IObserver(Of Foo).OnNext

        End Sub
#End Region

    End Class

End Module

C#コード:

 class Program {
        static void Main(string[] args) {
        }
    }

    public class Foo { }
    public class Bar { }
    public class Beholder : IObserver<Foo>, IObserver<Bar> {
        #region IObserver<Foo> Members

        public void OnCompleted() {
            throw new NotImplementedException();
        }

        public void OnError(Exception error) {
            throw new NotImplementedException();
        }

        public void OnNext(Foo value) {
            throw new NotImplementedException();
        }

        #endregion

        #region IObserver<Bar> Members


        public void OnNext(Bar value) {
            throw new NotImplementedException();
        }

        #endregion
    }
4

2 に答える 2

4

まとめ:

  • VBはここで不必要に警告を出しているようです。彼らがクリスマス休暇から戻ったとき、私はそれをVBテスターに​​話します。
  • これは、安全かどうかに関係なく、疑わしいプログラミング手法です。同じインターフェースの2つのバージョンを実装するのは少し奇妙です。
  • 代わりに、のような共変インターフェースを選択した場合IEnumerable<T>、警告は正当化されます。カメのシーケンスとキリンのシーケンスの両方であるオブジェクトがある場合、それを暗黙的に動物のシーケンスに変換するとどうなりますか?カメやキリンはいますか?ランタイムは1つを選択するだけですが、これは必ずしも必要な動作ではありません。

最後の点に関する興味深い議論については、このテーマに関する私の2007年の記事へのコメントを参照してください。

http://blogs.msdn.com/b/ericlippert/archive/2007/11/09/covariance-and-contravariance-in-c-part-ten-dealing-with-ambiguity.aspx

于 2011-12-27T18:22:45.397 に答える
3

両方を実装するのは悪い設計です。2人のオブザーバーにサブスクライブする2つの異なる子オブジェクトがあります。2つの子オブジェクトを用意し、それぞれに1つのインターフェイスを実装することをお勧めします。

class Beholder
{
  public IObserver<Foo> FooObserver{get;private set;}
  public IObserver<Bar> BarObserver{get;private set;}
}

逆分散があいまいなのはいつですか?

それでも、ここでは差し迫った問題は見られないので、VB.netの警告は私には確かに奇妙に見えます。

IObserver<in T>逆変です。Tしたがって、あいまいさを引き起こすには、そのような両方を見つける必要がIObserver<Foo>ありIObserver<Bar>ますIObserver<T>

Fooとが両方ともBar独立したクラスである場合T、それらの両方から派生する必要があるため、そのようなものは存在しません。これは、.net型システムでは許可されていません。

それらのいずれかがインターフェースである場合、あいまいさがあります。から派生しFooて実装するクラスを作成するだけIBarです。

一方が他方から派生している場合、それもあいまいになります。Fooから派生しているBar場合IObserver<Bar>は、もIObserver<Foo>です。

共分散があいまいなのはいつですか?

IEnumerable<T>そして最後に、両方が参照変換可能な共通の基本クラスを持つだけで十分であるなど、共変インターフェースを使用します。そしてObject、任意の2つのクラス(値型ではない)に対してこれを満たします。

ただしIEnumerable<T>、非ジェネリックの一貫した実装が必要であり、IEnumerable2つの独立したクラスでは不可能であるため、共分散がなくても損益分岐点になります。

于 2011-12-27T18:29:46.943 に答える