为什么“as”运算符不在C#中使用隐式转换运算符?

我在C#(虚拟代码)中定义了从/到某个类型的隐式字符串转换:

public class MyType { public string Value { get; set; } public static implicit operator MyType(string fromString) { return new MyType { Value = fromString }; } public static implicit operator string(MyType myType) { return myType.Value; } } 

在外部库代码的某处, MyType的实例作为object参数传递给方法。 该方法的一部分看起来像这样的东西:

 private void Foo(object value) { // ... code omitted var bar = value as string // note that value is an instance of MyType at runtime if(bar != null) // false, cast fails { // ... code omitted } } 

为什么演员不使用隐式转换器? 我认为这些的重点是使铸造和透明使用成为可能吗?

如果MyType有一个explicit转换器,这会有效吗? 如果是这样,(怎么样)我可以两者兼得?

顺便说一下,如果类型在编译时已知,则转换肯定有效。 这是因为运营商是static ? 有没有像非静态转换运算符?

PS我实际上对编译时行为和运行时行为之间的差异最感兴趣,所以我有一个后续问题: 为什么隐式类型转换运算符在C#中不能在运行时动态使用?

为什么软转换不使用隐式转换器?

嗯,基本上就是语言的指定方式。 从C#5规范部分7.10.11:

如果E的编译时类型不是动态的,则操作E作为T产生与之相同的结果

 E is T ? (T)(E) : (T)null 

除了E只评估一次。

[…]

请注意,使用as运算符无法进行某些转换(例如用户定义的转换),而应使用强制转换表达式执行转换。

C#语言规范在文档中明确提到了这一点:

请注意,使用as运算符无法进行某些转换(例如用户定义的转换),而应使用强制转换表达式执行转换。

所以你必须施展它。

as关键字不考虑用户定义的运算符。 您需要使用强制转换运算符。 来自eric lippert的相关文章

在您的情况下,显式和隐式运算符都无法帮助您,因为您尝试从objectstring而不是从MyTypestring 。 要使用户定义的转换运算符起作用,请将实例的时间类型编译为MyType类型而不是object 。 因为从objectstring不存在转换,但是从MyTypestring不存在转换。

想象一下,必须调用隐式转换运算符。 在这种情况下,任何电话

var castObj = rawObj as SomeType;

将要求.NET运行时使用reflection,以确定“rawObj”对象是否具有转换运算符。 显然,这将比检查对象是SomeType类型还是其子类型在计算上更昂贵。 拥有一个快速且可预测的操作员比一个更通用但速度更慢的操作员更好。