Please read to the end before deciding of voting as duplicate...
I have a type that implements an implicit cast
operator to another type:
class A
{
private B b;
public static implicit operator B(A a) { return a.b; }
}
class B
{
}
Now, implicit and explicit casting work just fine:
B b = a;
B b2 = (B)a;
...so how come Linq's .Cast<>
doesn't?
A[] aa = new A[]{...};
var bb = aa.Cast<B>(); //throws InvalidCastException
Looking at the source code for .Cast<>
, there's not much magic going on: a few special cases if the parameter really is a IEnumerable<B>
, and then:
foreach (object obj in source)
yield return (T)obj;
// ^^ this looks quite similar to the above B b2 = (B)a;
So why does my explicit cast work, but not the one inside .Cast<>
?
Does the compiler sugar-up my explicit cast ?
PS. I saw this question but I don't think its answers really explain what's going on.
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;