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

如何从作为参数的Linq表达式获取值并避免空引用异常?

解决Linq Expression表达式链中空引用异常的问题

当你传递包含多级成员访问的Linq Expression到GetVal方法时,若链中某个对象为null,执行编译后的委托就会抛出NullReferenceException。以下两种方案可以解决这个问题:

方案一:调用时使用空传播操作符(?.)

直接在表达式中使用C#的空传播操作符,让表达式本身处理空值情况。修改调用代码即可:

private static void TestGetVal()
{
    MyEntity p = new MyEntity();
    // 使用?.自动处理MySubEntity为null的情况,此时返回null而非抛出异常
    var myvalue = GetVal(p, p => p.MySubEntity?.Description);
}

这种方式简单直接,不需要修改GetVal方法,由调用者明确控制空值处理逻辑。如果MySubEntity为null,表达式会返回null,不会触发异常。

方案二:在GetVal方法中自动修改表达式树添加空检测

如果你希望对所有传入的表达式自动处理空值,无需调用者手动添加?.,可以通过解析并修改表达式树,在每个成员访问节点前插入空值检查逻辑。

实现代码如下:

public static object GetVal<TModel, TResult>(TModel model, Expression<Func<TModel, TResult>> expression)
{
    // 修改表达式树,添加空值检测逻辑
    var safeExpression = AddNullChecks(expression.Body, expression.Parameters[0]);
    var safeLambda = Expression.Lambda<Func<TModel, TResult>>(safeExpression, expression.Parameters);
    
    Func<TModel, TResult> compiledDelegate = safeLambda.Compile();
    return compiledDelegate(model);
}

private static Expression AddNullChecks(Expression expression, ParameterExpression parameter)
{
    if (expression is MemberExpression memberExpr)
    {
        // 递归处理成员访问的源表达式
        var sourceWithNullCheck = AddNullChecks(memberExpr.Expression, parameter);
        
        // 创建空检查:如果源为null,返回默认值;否则访问成员
        var nullCheck = Expression.Condition(
            Expression.Equal(sourceWithNullCheck, Expression.Constant(null)),
            Expression.Default(memberExpr.Type),
            memberExpr
        );
        return nullCheck;
    }
    // 如果是参数表达式,直接返回
    else if (expression == parameter)
    {
        return expression;
    }
    // 其他类型表达式(如常量、方法调用等)直接返回
    else
    {
        return expression;
    }
}

这个方法会递归遍历表达式树中的所有成员访问节点,自动为每个成员访问添加空值判断:如果成员的源对象为null,则返回该成员类型的默认值(比如string类型返回null,值类型返回默认值如0),否则正常访问成员。

两种方案对比

  • 方案一:代码量少,灵活可控,适合需要针对特定表达式定制空值处理的场景。
  • 方案二:对调用者透明,统一处理所有表达式的空值情况,适合通用工具类场景,但表达式树解析逻辑相对复杂,需要考虑更多表达式类型的兼容(比如方法调用、索引器等)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 23:01:14