将隐式转换运算符与switch结合使用

ant*_*ord 3 c#

不明确的行为,如果我声明类型:

struct Token
{
    public static implicit operator int(Token x)
    {
        return 0;
    }

    public static implicit operator string(Token x)
    {
        return "";
    }
}
Run Code Online (Sandbox Code Playgroud)

我们有两个隐式转换.如果我使用工作文件

var t = new Token();

if (t == "123")
{

}
Run Code Online (Sandbox Code Playgroud)

CS0151:开关表达式或大小写标签必须是bool,char,string,integral,enum或相应的可空类型

如果我使用:

switch (t)
{
    case "123" :
    {
        break;
    }
}
Run Code Online (Sandbox Code Playgroud)

但如果我删除int隐式转换,则错误消失.

struct Token
{
    public static implicit operator string(Token x)
    {
        return "";
    }
}
Run Code Online (Sandbox Code Playgroud)

它是编译器中的错误还是正确的行为?

Avn*_*tan 6

编译器的混乱似乎是可以理解的.该switch声明可以同时运行intstring.您传递的内容Token包含对两者的隐式转换.编译器应该选择哪一个?它无法知道哪个是首选.隐式构造函数没有优先级.

在这种if情况下,很明显你要比较一个字符串,以便使用转换.但是转换是模棱两可的.错误并不完全清楚,但我假设,不知道选择哪个转换,它不选择,尝试将Token实例本身放在交换机中,从而显示此错误.


Kob*_*obi 6

这是正确的行为.从规范,8.7.2开关语句:

从switch表达式的类型到以下可能的控制类型之一,必须存在一个用户定义的隐式转换(第6.4节):sbyte,byte,short,ushort,int,uint,long,ulong,char,string.如果不存在此类隐式转换,或者存在多个此类隐式转换,则会发生编译时错误.


我们还可以看到实现规范的(下一版本)编译器源代码Conversions.UserDefinedImplicitConversions.
请注意,我删除了一些代码和注释,这只是为了得到一般的想法:

UserDefinedConversionResult? exactConversionResult = null;

foreach (UserDefinedConversionAnalysis analysis in u)
{
    TypeSymbol tx = analysis.ToType;
    if (tx.IsValidSwitchGoverningType(isTargetTypeOfUserDefinedOp: true))
    {
        if (!exactConversionResult.HasValue)
        {
            exactConversionResult = UserDefinedConversionResult.Valid(u, best.Value);
            continue;
        }

        return UserDefinedConversionResult.Ambiguous(u);
    }
}

// If there exists such unique TX in suitableTypes, then that operator is the  
// resultant user defined conversion and TX is the resultant switch governing type.
// Otherwise we either have ambiguity or no applicable operators.
return exactConversionResult.HasValue ?
    exactConversionResult.Value :
    UserDefinedConversionResult.NoApplicableOperators(u);
Run Code Online (Sandbox Code Playgroud)

基本上,代码会迭代隐式转换,并将它找到的第一个转换保持为可以出现的类型switch.如果找到它返回的另一种类型Ambiguous.如果它只找到一种类型,则返回它.
同样,这是代码的简短版本,完整代码处理更多案例和树皮兼容性.