More on implicit conversion operators and interfaces in C# (again)

后端 未结 4 808
你的背包
你的背包 2020-12-09 16:02

Okay. I\'ve read this post, and I\'m confused on how it applies to my example (below).

class Foo
{
    public static implicit operator Foo(IFooCompatible fo         


        
4条回答
  •  情书的邮戳
    2020-12-09 16:43

    The context of your example, it won't work again because the implicit operator has been placed against an interface... I'm not sure how you think your sample is different to the one you linked other than you try to get one concrete type across to another via an interface.

    There is a discussion on the topic here on connect:

    http://connect.microsoft.com/VisualStudio/feedback/details/318122/allow-user-defined-implicit-type-conversion-to-interface-in-c

    And Eric Lippert might have explained the reason when he said in your linked question:

    A cast on an interface value is always treated as a type test because it is almost always possible that the object really is of that type and really does implement that interface. We don't want to deny you the possibility of doing a cheap representation-preserving conversion.

    It seems to be to do with type identity. Concrete types relate to each other via their hierarchy so type identity can be enforced across it. With interfaces (and other blocked things such as dynamic and object) type identity becomes moot because anyone/everyone can be housed under such types.

    Why this is important, I have no idea.

    I prefer explicit code that shows me I am trying to get a Foo from another that is IFooCompatible, so a conversion routine that takes a T where T : IFooCompatible returning Foo.

    For your question I understand the point of discussion, however my facetious response is if I see code like Foo f = new Bar() in the wild I would very likely refactor it.


    An alternative solution:

    Don't over egg the pudding here:

    Foo f = new Bar().ToFoo();
    

    You have already exposed the idea that Foo compatible types implement an interface to achieve compatibility, use this in your code.


    Casting versus converting:

    It is also easy to get wires crossed about casting versus converting. Casting implies that type information is integral between the types you are casting around, hence casting doesn't work in this situation:

    interface IFoo {}
    class Foo : IFoo {}
    class Bar : IFoo {}
    
    Foo f = new Foo();
    IFoo fInt = f;
    Bar b = (Bar)fInt; // Fails.
    

    Casting understands the type hierarchy and the reference of fInt cannot be cast to Bar as it is really Foo. You could provide a user-defined operator to possibly provide this:

    public static implicit operator Foo(Bar b) { };
    

    And doing this in your sample code works, but this starts to get silly.

    Converting, on the other hand, is completely independent of the type hierarchy. Its behaviour is entirely arbitrary - you code what you want. This is the case you are actually in, converting a Bar to a Foo, you just happen to flag convertible items with IFooCompatible. That interface doesn't make casting legal across disparate implementing classes.


    As for why interfaces are not allowed in user-defined conversion operators:

    Why can't I use interface with explicit operator?

    The short version is that it's disallowed so that the user can be certain that conversions between reference types and interfaces succeed if and only if the reference type actually implements that interface, and that when that conversion takes place that the same object is actually being referenced.

提交回复
热议问题