请在决定投票前重复阅读......
我有一个类型,它将implicit cast
运算符实现为另一种类型:
class A
{
private B b;
public static implicit operator B(A a) { return a.b; }
}
class B
{
}
现在,隐式和显式转换工作正常:
B b = a;
B b2 = (B)a;
......那么Linq的.Cast<>
怎么没有?
A[] aa = new A[]{...};
var bb = aa.Cast<B>(); //throws InvalidCastException
查看.Cast<>
的源代码,没有太大的魔力:如果参数确实是IEnumerable<B>
,则会出现一些特殊情况,然后:
foreach (object obj in source)
yield return (T)obj;
// ^^ this looks quite similar to the above B b2 = (B)a;
那么为什么我的显式投射工作,而不是.Cast<>
内部的工作?
编译器是否会对我的显式转换加油?
PS。我看到了this question,但我认为它的答案并没有真正解释发生了什么。
答案 0 :(得分:13)
那么为什么我的显式演员工作,以及里面的那个.Cast&lt;&gt;不?
您的显式转换在编译时知道 源和目标类型是什么。编译器可以发现显式转换,并发出代码来调用它。
不是泛型类型的情况。请注意,这并非特定于Cast
或LINQ - 如果您尝试使用简单的Convert
方法,则会看到相同的内容:
public static TTarget Convert<TSource, TTarget>(TSource value)
{
return (TTarget) value;
}
这将不调用任何用户定义的转化 - 甚至从({)int
转换为long
。它仅执行引用转换和装箱/拆箱转换。这只是仿制药工作方式的一部分。
答案 1 :(得分:8)
简短的回答很简单:Cast<T>
方法不支持自定义转化运算符。
在第一个例子中:
B b = a;
B b2 = (B)a;
编译器可以在静态分析期间看到此B(A a)
运算符;编译器将此解释为您的自定义运算符方法的静态call
。在第二个例子中:
foreach (object obj in source)
yield return (T)obj;
对操作员无知识;这是通过unbox.any
实现的(如果castclass
是ref-type,则与T
相同。)
还有第三种选择:如果你通过dynamic
,运行时实现会尝试模仿编译器规则,所以将找到运算符...但不是作为C#-to-IL编译步骤:
dynamic b = a; // note that `dynamic` here is *almost* the same as `object`
B b2 = b;
答案 2 :(得分:2)
Enumerable.Cast<T>
是一种.Net框架方法,其行为在调用它的所有.Net语言中都有意义。
另见Ander Hejlsberg对this discussion的回复。
编译器是否会对我的显式转换加油?
你称之为“隐式演员”的实际上是“implicit conversion operator”。这是一个常见的错误。
C#允许您使用强制语法指定转换。发生这种情况时,您正在使用不同的实例(转换),而不是更改对同一实例的引用(转换)。