为啥“as”运算符在 C# 中不使用隐式转换运算符?
Posted
技术标签:
【中文标题】为啥“as”运算符在 C# 中不使用隐式转换运算符?【英文标题】:Why does the "as" operator not use an implicit conversion operator in C#?为什么“as”运算符在 C# 中不使用隐式转换运算符? 【发布时间】:2016-06-01 04:30:53 【问题描述】:我已经在 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
吗?有没有类似非静态转换运算符的东西?
附:我实际上对编译时行为和运行时行为之间的差异最感兴趣,所以我有一个后续问题:Why are implicit type conversion operators not dynamically usable at runtime in C#?
【问题讨论】:
顺便说一句,我以前从未听说过as
运算符被称为“软演员”。
@JonSkeet 真的让我吃惊,也许不是官方术语,但我肯定见过很多次。
搜索“软演员”和 C# 得到 636 个结果,在我看来,这是一个 小 数字。我以后肯定会避免使用它——它肯定不是 C#规范术语的一部分。
@JonSkeet 是否有类似简洁(但更正确)的等效术语?
@MDeSchaepmeester:但在这种情况下,您只是在团队中加强了对非标准术语的使用。如果您使用标准术语,我怀疑他们会也理解您 - 但在外部讨论事物时,你们中的任何人都不必改变您的谈话方式。
【参考方案1】:
as
关键字不考虑用户定义的运算符。您需要改用强制转换运算符。相关article from Eric Lippert
在您的情况下,显式和隐式运算符都无法帮助您,因为您尝试从object
转换为string
而不是从MyType
转换为string
。要使用户定义的转换运算符起作用,请将实例的时间类型编译为 MyType
类型而不是 object
。因为不存在从object
到string
而是从MyType
到string
的转换。
【讨论】:
我相信使用dynamic
会使演员表工作。 (不过必须检查一下。)不过,这对 as
没有帮助。
换句话说,只有当参数实际上是 string
的实例时,演员才会起作用?
没错。添加了支持文章。【参考方案2】:
想象一下,必须调用隐式转换运算符。在这种情况下,任何调用
var castObj = rawObj as SomeType;
将需要 .NET 运行时使用反射来确定“rawObj”对象是否具有转换运算符。显然,这将比仅仅检查对象是 SomeType 类型还是它的子类型更昂贵。拥有一个快速且可预测的运算符比一个更通用但速度慢得多的运算符更好。
【讨论】:
【参考方案3】:C# 语言规范在 as
的文档中明确提到了这一点:
请注意,某些转化(例如用户定义的转化)不是 可以使用 as 运算符,而是应该使用 转换表达式。
所以你必须投射它。
【讨论】:
【参考方案4】:为什么软转换不使用隐式转换器?
嗯,基本上就是这样指定语言的。来自 C# 5 规范第 7.10.11 节:
如果 E 的编译时类型不是动态的,则操作 E as T 产生的结果与
E is T ? (T)(E) : (T)null
除了 E 只计算一次。
[...]
请注意,某些转换(例如用户定义的转换)不能使用 as 运算符进行,而应使用强制转换表达式来执行。
【讨论】:
这很清楚,但是您知道任何解决方法吗?如果我真的想要一个行为几乎完全像字符串(或 int 或其他任何东西)的类型怎么办? @MDeSchaepmeester:说实话,我会放弃这个目标。当试图让一种类型看起来像另一种一样透明时,总是会出现问题。我会回溯并查看其他设计。 很公平,但如果不是因为这一限制,一切都会顺利进行。无论如何,谢谢,如果您不知道解决方法,那么我敢肯定没有其他人会这样做:)以上是关于为啥“as”运算符在 C# 中不使用隐式转换运算符?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 Linq Cast<> 助手不能与隐式转换运算符一起使用?
为啥Java在使用“加号”运算符时会执行从双精度到整数的隐式类型转换? [复制]