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:
the compiler can see this
B(A a)operator during static analysis; the compiler interprets this as a staticcallto your custom operator method. In the second example:that has no knowledge of the operator; this is implemented via
unbox.any(which is the same ascastclassifTis 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: