Why does the Linq Cast<> helper not work with the implicit cast operator?

前端 未结 3 1804
隐瞒了意图╮
隐瞒了意图╮ 2020-12-01 14:12

Please read to the end before deciding of voting as duplicate...

I have a type that implements an implicit cast operator to another type:

相关标签:
3条回答
  • 2020-12-01 15:02

    Enumerable.Cast<T> is a .Net framework method and has a behavior that makes sense in all of the .Net languages that call it.

    See also, Ander Hejlsberg's reply on this discussion.


    Does the compiler sugar-up my explicit cast ?

    What you call an "implicit cast operator" is actually an "implicit conversion operator". It's a common mistake.

    C# allows you to specify conversions using the casting syntax. When this happens, you are using a different instance (converting), not changing the reference to the same instance (casting).

    0 讨论(0)
  • 2020-12-01 15:06

    The short answer would be simply: the Cast<T> method doesn't support custom conversion operators.

    In the first example:

    B b = a;
    B b2 = (B)a;
    

    the compiler can see this B(A a) operator during static analysis; the compiler interprets this as a static call to your custom operator method. In the second example:

    foreach (object obj in source) 
        yield return (T)obj; 
    

    that has no knowledge of the operator; this is implemented via unbox.any (which is the same as castclass if T is a ref-type).

    There is also a third option: if you went via dynamic, the runtime implementation tries to mimic compiler rules, so this will find the operator ... but not as part of the C#-to-IL compile step:

    dynamic b = a; // note that `dynamic` here is *almost* the same as `object`
    B b2 = b;
    
    0 讨论(0)
  • 2020-12-01 15:10

    So why my explicit cast work, and the one inside .Cast<> doesn't?

    Your explicit cast knows at compile time what the source and destination types are. The compiler can spot the explicit conversion, and emit code to invoke it.

    That isn't the case with generic types. Note that this isn't specific to Cast or LINQ in general - you'd see the same thing if you tried a simple Convert method:

    public static TTarget Convert<TSource, TTarget>(TSource value)
    {
        return (TTarget) value;
    }
    

    That will not invoke any user-defined conversions - or even conversions from (say) int to long. It will only perform reference conversions and boxing/unboxing conversions. It's just part of how generics work.

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