C# 为什么林克会出演<&燃气轮机;辅助对象不使用隐式强制转换操作符?

C# 为什么林克会出演<&燃气轮机;辅助对象不使用隐式强制转换操作符?,c#,linq,casting,implicit-conversion,coercion,C#,Linq,Casting,Implicit Conversion,Coercion,请通读到最后,然后再决定投票是否为副本 我有一个将隐式强制转换运算符实现为另一个类型的类型: class A { private B b; public static implicit operator B(A a) { return a.b; } } class B { } 现在,隐式和显式铸造工作刚刚好: B b = a; B b2 = (B)a; …那么为什么林克的.Cast没有呢 A[] aa = new A[]{...}; var bb = aa.Cast<B

请通读到最后,然后再决定投票是否为副本

我有一个将
隐式强制转换
运算符实现为另一个类型的类型:

class A
{
    private B b;
    public static implicit operator B(A a) { return a.b; }
}
class B
{
}
现在,隐式和显式铸造工作刚刚好:

B b = a;
B b2 = (B)a;
…那么为什么林克的
.Cast
没有呢

A[] aa = new A[]{...};
var bb = aa.Cast<B>();  //throws InvalidCastException
那么,为什么我的显式cast有效,而
.cast
中的cast无效呢

编译器是否增加了我的显式强制转换

附:我看到了,但我不认为它的答案能真正解释发生了什么

那为什么我的表演者工作,而里面的演员不工作呢

显式cast在编译时知道源类型和目标类型。编译器可以发现显式转换,并发出代码来调用它

泛型类型的情况并非如此。请注意,这并不是特定于
Cast
或LINQ的—如果您尝试一种简单的
Convert
方法,您会看到同样的情况:

public static TTarget Convert<TSource, TTarget>(TSource value)
{
    return (TTarget) value;
}
publicstaticttarget转换(TSource值)
{
返回(TTarget)值;
}

这将不会调用任何用户定义的转换,甚至不会调用(比如)从
int
long
的转换。它将只执行引用转换和装箱/拆箱转换。这只是泛型工作原理的一部分。

简单的回答是:
Cast
方法不支持自定义转换运算符

在第一个示例中:

B b = a;
B b2 = (B)a;
在静态分析期间,编译器可以看到这个
B(A)
操作符;编译器将其解释为对自定义运算符方法的静态调用。在第二个例子中:

foreach (object obj in source) 
    yield return (T)obj; 
不了解操作员的信息;这是通过
unbox.any
实现的(如果
T
是ref类型,则与
castclass
相同)

还有第三个选项:如果您通过
动态
,运行时实现将尝试模拟编译器规则,因此这将发现运算符。。。但不是作为C#to IL编译步骤的一部分:

dynamic b = a; // note that `dynamic` here is *almost* the same as `object`
B b2 = b;
Enumerable.Cast
是一种.Net framework方法,其行为在所有调用它的.Net语言中都是有意义的

另见Ander Hejlsberg关于的答复


编译器是否增加了我的显式强制转换

您所谓的“隐式强制转换运算符”实际上是一个“”。这是一个常见的错误


C#允许您使用强制转换语法指定转换。发生这种情况时,您使用的是不同的实例(转换),而不是更改对同一实例的引用(转换)。

那么是否应该始终定义显式运算符来补充隐式运算符?隐式运算符不“隐式”包含显式转换有什么原因吗?有什么方法可以让它工作吗?它在某些情况下非常有用-例如在使用Oracles时,愚蠢的类型甚至没有实现
IConvertible
。@DanielHilgarth:我想,最接近的方法是使用
动态
。@WillVousden:隐式运算符可以显式调用。向上面的示例代码中添加显式运算符不会改变观察到的行为。@WillVousden:这与转换是显式的还是隐式的无关-这只是因为您的转换是用户定义的转换。即使“它的答案不能真正解释发生了什么”,你也不应该问重复的问题;)@蒂姆,除了问一个更好的问题,你会建议我如何改进一个主题的答案(我不知道答案)吗?@TimSchmelter,如果这个问题得到了更好的答案,也许另一个问题应该作为一个重复来解决?我不知道正确的处理方法是什么。我经常看到问题在答案比提议的副本更好的地方被关闭。@蒂姆显然对元的共识是合并问题:-我已经标记了这个问题,让我们看看会发生什么:)你是对的。我尝试了这个,它抛出:
bb=(B)(object)a
我想这是因为我在静态上下文中隐藏了
一个
的真实类型…@CristiDiaconescu-yes;通过
对象
,它变成了一个简单的
castclass
,并且
castclass
不支持自定义运算符。顺便说一句。我想在上一个例子中,你的意思是
b2=(B)B
dynamic b = a; // note that `dynamic` here is *almost* the same as `object`
B b2 = b;