Ale*_*ese 28 c# pattern-matching c#-7.0 visual-studio-2017
我已将项目升级到目标C#7,并使用Visual Studio 2017 RC在我的解决方案中实现模式匹配.在执行此操作之后,引入了与通用参数的模式匹配相关的一些错误.
请考虑以下代码:
public class Packet
{
}
public class KeepalivePacket : Packet
{
}
public void Send<T>(T packet)
where T : Packet
{
if (packet is KeepalivePacket keepalive)
{
// Do stuff with keepalive
}
switch (packet)
{
case KeepalivePacket keepalivePacket:
// Do stuff with keepalivePacket
break;
}
}
Run Code Online (Sandbox Code Playgroud)
无论是if语句和case声明产生一个编译错误.
类型为T的表达式不能由KeepalivePacket类型的模式处理
如果我首先转换参数以键入object模式匹配按预期工作.罗斯林然后将演员标记object为多余.
if ((object)packet is KeepalivePacket keepalive)
{
// This works
}
Run Code Online (Sandbox Code Playgroud)
此错误仅适用于通用参数和变量.Roslyn似乎不知道这个问题,因为它建议更改代码以通过分析器使用模式匹配,并允许我应用"代码修复"导致代码损坏.
Ale*_*ese 20
正如微软的Neal Gafter解释的那样:
它不起作用的原因是没有从T到KeepalivePacket定义的转换(显式或隐式).模式匹配需要存在这样的转换,因为它是根据需要转换的转换运算符来定义的.语言规范和编译器同意不存在转换.对我来说似乎很奇怪,语言规范的定义使得这里不存在(显式)转换.我们将看看我们能做些什么.
我们不会在C#7中对此做任何事情.您必须在代码中添加一个强制转换来解决它.一旦我们有递归模式,这可能更难以解决.而且,这个问题背后的尴尬语言规则(即没有从T转换为KeepalivePacket)并没有多大意义.
更新
现在正在使用C#7.1
C#7.0 的答案是
if ((Packet)packet is KeepalivePacket keepalive)
{
// Do stuff with keepalive
}
switch ((Packet)packet)
{
case KeepalivePacket keepalivePacket:
// Do stuff with keepalivePacket
break;
}
Run Code Online (Sandbox Code Playgroud)