You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何表达式树允许类型匹配`is`表达式却禁止空值匹配?

问题:表达式树中为何类型匹配is允许,空值匹配is null却报错?

先看第一段可正常运行的代码:

internal static class Program
{
    private static void Main()
    {
        object value = "Hello";
        Console.WriteLine(value.Test(o => o is string));
    }

    private static bool Test<T>(this T value, Expression<Func<T, bool>> test) => 
        test.Compile().Invoke(value);
}

运行结果:

True

再对比这段触发编译错误的代码:

internal static class Program
{
    private static void Main()
    {
        string? value = "Hello";
        Console.WriteLine(value.Test(o => o is null)); // 编译错误
    }

    private static bool Test<T>(this T value, Expression<Func<T, bool>> test) =>
        test.Compile().Invoke(value);
}

编译错误提示:

An expression tree cannot contain pattern-matching 'is' expression

为何后者触发上述编译错误,而前者同样使用is表达式却能正常运行?即为何类型匹配被允许,空值匹配却不行?

注:已知可以用Func<T, bool>替代Expression<Func<T, bool>>,但本次讨论不涉及该方案。


解答

核心原因在于C#对表达式树支持的语法存在版本差异和规则区分:

  • o is string被编译器当作传统类型检查,而非模式匹配
    在C# 7.0引入模式匹配语法之前,is就已经用于类型检查,表达式树对这种场景的支持是原生的——编译器会将o is string直接转换为Expression.TypeIs节点,这是表达式树很早就支持的基础节点类型,因此可以正常编译。

  • o is null属于C# 7.0+引入的常量模式匹配,表达式树对其支持未覆盖
    is null是模式匹配中的常量模式,而表达式树对模式匹配的支持是逐步扩展的。早期版本的表达式树解析器无法处理这种模式匹配语法,编译器无法将其转换为对应的表达式树节点,因此抛出编译错误。

  • 两者的编译器处理逻辑完全不同
    编译器对o is string的处理逻辑是类型检查,属于表达式树的原生支持范畴;而对o is null会识别为模式匹配表达式,由于表达式树未实现该模式的解析逻辑,导致报错。

简单总结:is string是表达式树原生支持的类型检查操作,而is null是后来引入的模式匹配语法,不在表达式树早期支持的范围内,因此出现编译差异。


内容的提问来源于stack exchange,提问作者Matthew Layton

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 23:51:09