Cri*_*scu 15 c# linq casting coercion implicit-conversion
请在决定投票前重复阅读...
我有一个类型,实现了implicit cast另一种类型的运算符:
class A
{
private B b;
public static implicit operator B(A a) { return a.b; }
}
class B
{
}
Run Code Online (Sandbox Code Playgroud)
现在,隐式和显式转换工作正常:
B b = a;
B b2 = (B)a;
Run Code Online (Sandbox Code Playgroud)
......那么Linq怎么.Cast<>没有?
A[] aa = new A[]{...};
var bb = aa.Cast<B>(); //throws InvalidCastException
Run Code Online (Sandbox Code Playgroud)
看一下源代码.Cast<>,没有太大的魔力:如果参数真的是一个特殊情况IEnumerable<B>,那么:
foreach (object obj in source)
yield return (T)obj;
// ^^ this looks quite similar to the above B b2 = (B)a;
Run Code Online (Sandbox Code Playgroud)
那么为什么我的显式演员会工作,而不是里面的演员.Cast<>?
编译器是否加重了我的显式演员?
PS.我看到了这个问题,但我认为它的答案并没有真正解释发生了什么.
Jon*_*eet 13
那么为什么我的显式演员工作,以及里面的那个.Cast <>不行?
您的显式转换在编译时知道源和目标类型是什么.编译器可以发现显式转换,并发出代码来调用它.
这是不是与泛型类型的情况.请注意,这不是特定于CastLINQ或一般的LINQ - 如果您尝试了一个简单的Convert方法,您会看到同样的事情:
public static TTarget Convert<TSource, TTarget>(TSource value)
{
return (TTarget) value;
}
Run Code Online (Sandbox Code Playgroud)
这不会调用任何用户定义的转换 - 甚至是(比如说)int转换long.它只会执行参考转换和装箱/拆箱转换.这只是仿制药工作方式的一部分.
简短的回答很简单:该Cast<T>方法不支持自定义转换运算符.
在第一个例子中:
B b = a;
B b2 = (B)a;
Run Code Online (Sandbox Code Playgroud)
编译器可以B(A a)在静态分析期间看到此运算符; 编译器将此解释为call自定义运算符方法的静态.在第二个例子中:
foreach (object obj in source)
yield return (T)obj;
Run Code Online (Sandbox Code Playgroud)
有没有知识的操作人员; 这是通过实现unbox.any(这是相同的castclass,如果T是一个REF-类型).
还有第三种选择:如果你经过dynamic,运行时实现试图模仿编译器规则,所以这将找到运算符......但不是作为C#-to-IL编译步骤的一部分:
dynamic b = a; // note that `dynamic` here is *almost* the same as `object`
B b2 = b;
Run Code Online (Sandbox Code Playgroud)