Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 结合使用隐式转换运算符和开关_C# - Fatal编程技术网

C# 结合使用隐式转换运算符和开关

C# 结合使用隐式转换运算符和开关,c#,C#,不清楚行为,如果我声明类型: struct Token { public static implicit operator int(Token x) { return 0; } public static implicit operator string(Token x) { return ""; } } 我们有两个隐式转换。 工作文件,如果我使用 var t = new Token(); if (t == "

不清楚行为,如果我声明类型:

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

    public static implicit operator string(Token x)
    {
        return "";
    }
}
我们有两个隐式转换。 工作文件,如果我使用

var t = new Token();

if (t == "123")
{

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

如果我使用:

switch (t)
{
    case "123" :
    {
        break;
    }
}
但若我删除int隐式转换,那个么错误就会消失

struct Token
{
    public static implicit operator string(Token x)
    {
        return "";
    }
}

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

编译器的困惑似乎是可以理解的。
switch
语句可以在
int
string
上运行。您向它传递一个
令牌
,该令牌包含对两者的隐式转换。编译器应该选择哪一个?它无法知道哪个是首选。隐式构造函数没有优先级


if
的情况下,很明显您是在比较字符串,因此使用了转换。但这种转变是不明确的。错误并不完全清楚,但我假设,在不知道要选择哪种转换时,它会尝试将
令牌
实例本身放入交换机中,从而显示此错误。

这是正确的行为,因为
开关
语句不知道要将
t
转换为什么类型:

switch (t)
{
    case "123" :
        break;
    case 0:
        break;
}
这应该很清楚,因为
t
不能转换为
int
string
,但以下操作有效:

switch ((string)t)
{
    case "123" :
        break;
}

现在,您可以清楚地定义要切换字符串…

这是正确的行为。根据规范:

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


我们还可以在上看到实现规范的(下一版本)编译器源代码。
请注意,我已经删除了一些代码和注释,这只是为了获得总体思路:

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);
基本上,代码迭代隐式转换,并将找到的第一个转换保持为可以出现在
开关中的类型。如果它找到另一个类型,则返回。如果只找到一种类型,则返回该类型。

同样,这是代码的一个简短版本,完整的代码处理更多的案例和barkwards兼容性。

我添加了Roslyn的相关代码。这不是强制性的,因为规范是国王,但我想看看我是否能找到它。天真地,我期望在某个地方有
Types.Count==1
<代码>:P