Multiple Generics ambiguity

后端 未结 2 1706
名媛妹妹
名媛妹妹 2021-01-06 06:33

The codes below are exactly the same, except that one is C# and the other one is VB.Net. C# compiles just fine, but VB.Net throws the warning:

Interfa

相关标签:
2条回答
  • 2021-01-06 07:18

    It's bad design to implement both. Have two different child objects which you subscribe to the two observers. I recommend having two child objects, with each implementing one of the interfaces.

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

    When is contra-variance ambiguous?

    Still I don't see an immediate problem here, so the VB.net warning looks indeed strange to me.

    IObserver<in T> is contra-variant. So to cause an ambiguity you'd need to find a T such both IObserver<Foo> and IObserver<Bar> are IObserver<T>.

    If both Foo and Bar are independent classes, no such T exists, since it's need to derive from both of them, which the .net type system doesn't allow.

    If either of them were an interface, there would be an ambiguity: Just create a class that derives from Foo and implements IBar.

    If one derived from the other, it'd be ambiguous too: if Foo derived from Bar, then IObserver<Bar> is also IObserver<Foo>.

    When is co-variance ambiguous?

    And finally with co-variant interfaces, such as IEnumerable<T> it's enough to have a common base class to which both are reference convertible. And Object fulfills this for any two classes(but not value types).

    But IEnumerable<T> would break even without covariance, since you need a consistent implementation of the non generic IEnumerable, and that's not possible for two independent classes.

    0 讨论(0)
  • Summing up:

    • VB appears to be giving the warning unnecessarily here. I'll mention it to the VB testers when they're back from Christmas vacation.
    • This is a suspicious programming practice regardless of whether it is safe or not; it's a bit strange to implement two versions of the same interface.
    • If instead you chose a covariant interface like IEnumerable<T> then the warning would be justified. If you have an object that is both a sequence of Turtles and a sequence of Giraffes, then what happens when you implicitly convert it to sequence of Animal? Do you get Turtles or Giraffes? The runtime just picks one, which is not necessarily the behaviour you want.

    For some interesting discussion of the last point see the comments to my 2007 article on the subject:

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

    0 讨论(0)
提交回复
热议问题