类型 T 的表达式不能由类型 X 的模式处理 [英] Expression of type T cannot be handled by a pattern of type X

查看:29
本文介绍了类型 T 的表达式不能由类型 X 的模式处理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已将我的项目升级到面向 C# 7 并使用 Visual Studio 2017 RC 在我的解决方案中实现模式匹配.这样做之后,引入了一些与使用通用参数进行模式匹配相关的错误.

I have upgraded my project to target C# 7 and used Visual Studio 2017 RC to implement pattern matching across my solution. After doing this some errors were introduced relating to pattern matching with generic parameters.

考虑以下代码:

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;
    }
}

if 语句和 case 语句都会产生编译错误.

Both the if statement and the case statement produce a compilation error.

T 类型的表达式不能被 KeepalivePacket 类型的模式处理

An expression of type T cannot be handled by a pattern of type KeepalivePacket

如果我首先将参数转换为 object 类型,则模式匹配会按预期工作.Roslyn 然后将转换为 object 标记为多余.

If I first cast the parameter to type object the pattern matching works as expected. Roslyn then marks the cast to object as redundant.

if ((object)packet is KeepalivePacket keepalive)
{
    // This works
}

此错误似乎仅适用于通用参数和变量.Roslyn 似乎没有意识到这个问题,因为它建议更改代码以通过分析器使用模式匹配,并允许我应用导致代码损坏的代码修复".

This error only appears to apply to generic parameters and variables. Roslyn appears to not be aware of this issue as it recommends changing the code to use pattern matching via an analyzer and allows me to apply the "code fix" resulting in the broken code.

推荐答案

As 由 Neal Gafter 解释 来自微软:

它不起作用的原因是没有定义从 T 到 KeepalivePacket 的转换(显式或隐式).模式匹配需要存在这样的转换,因为它是根据强制转换运算符定义的,这需要存在转换.语言规范和编译器同意不存在转换.对我来说,语言规范的定义使得此处不存在(显式)转换,这对我来说似乎很奇怪.我们会看看我们能做些什么.

The reason it doesn’t work is that there is no conversion (explicit or implicit) defined from T to KeepalivePacket. Pattern matching requires such a conversion to exist, as it is defined in terms of the cast operator, which requires a conversion exist. The language specification and compiler agree that no conversion exists. It seems strange to me that the language specification is defined such that no (explicit) conversion exists here. We'll look at what we can do about that.

我们不会在 C# 7 中对此做任何事情.您必须向代码中添加强制转换才能解决它.一旦我们有了递归模式,这可能更难解决.此外,这个问题背后的尴尬语言规则(即没有从 T 到 KeepalivePacket 的转换)没有多大意义.

We're not going to do anything about this in C# 7. You'll have to add a cast to your code to work around it. Once we have recursive patterns, this may be more difficult to work around. Moreover, the awkward language rule that underlies this issue (i.e. that there is no conversion from T to KeepalivePacket) doesn't make a lot of sense.

更新

现在可以在 C# 7.1 中使用

This is now working in C# 7.1

这篇关于类型 T 的表达式不能由类型 X 的模式处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆