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

时间:2016-02-19 14:48:24

标签: c# .net types casting type-conversion

我在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
    }
}

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

如果MyTypeexplicit转换器,这会有效吗?如果是这样,(怎么样)我可以同时拥有两个?

顺便说一下,如果类型在编译时已知,那么强制转换肯定有效。这是因为运营商是static吗?有没有类似非静态转换运算符的东西?

P.S。我实际上对编译时行为和运行时行为之间的差异最感兴趣,所以我有一个后续问题:Why are implicit type conversion operators not dynamically usable at runtime in C#?

4 个答案:

答案 0 :(得分:19)

  

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

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

  

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

相同的结果
E is T ? (T)(E) : (T)null
     

除了E仅评估一次。

     

[...]

     

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

答案 1 :(得分:9)

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

  

请注意,某些转化(例如用户定义的转化)不是   可以使用as运算符,而应该使用   演员表达。

所以你必须施展它。

答案 2 :(得分:7)

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

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

答案 3 :(得分:2)

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

  

var castObj = rawObj as SomeType;

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