C# 表达式树lambda不能包含null传播运算符
问题:行C# 表达式树lambda不能包含null传播运算符,c#,linq,null-coalescing-operator,C#,Linq,Null Coalescing Operator,问题:行price=co?.price??0,在下面的代码中给出了上述错误。但是如果我从公司?中删除?,效果会很好。我试图跟踪他们在行上使用?的位置,选择新的{person.FirstName,PetName=subpet?.Name??String.Empty}所以,我似乎需要了解何时将?与?一起使用,何时不使用 错误: 表达式树lambda不能包含null传播运算符 公共类CustomerOrdersModelView { 公共字符串CustomerID{get;set;} 公共整数FY{g
price=co?.price??0,
在下面的代码中给出了上述错误。但是如果我从公司?
中删除?
,效果会很好。我试图跟踪他们在行上使用?
的位置,选择新的{person.FirstName,PetName=subpet?.Name??String.Empty}
所以,我似乎需要了解何时将?
与?
一起使用,何时不使用
错误:
表达式树lambda不能包含null传播运算符
公共类CustomerOrdersModelView
{
公共字符串CustomerID{get;set;}
公共整数FY{get;set;}
公开浮动?价格{get;set;}
....
....
}
公共异步任务ProductAnnualReport(字符串rpt)
{
var qry=来自c in_context.Customers
在上下文中加入ord
c.CustomerID等于ord.CustomerID到co
来自m in co.DefaultIfEmpty()
选择新CustomerOrdersModelView
{
CustomerID=c.CustomerID,
FY=c.FY,
价格=co?,价格=0,
....
....
};
....
....
}
您引用的示例使用LINQ to对象,其中查询中的隐式lambda表达式转换为委托。。。而您使用的是EF或类似工具,以及IQueryable
queryies,其中lambda表达式被转换为表达式树。表达式树不支持空条件运算符(或元组)
就按老办法做吧:
price = co == null ? 0 : (co.price ?? 0)
(我相信空合并运算符在表达式树中是可以使用的。)您链接到的代码使用列表<代码>列表
实现IEnumerable
但不实现IQueryable
。在这种情况下,投影在内存中执行,?。
工作
您使用的是一些IQueryable
,其工作原理非常不同。对于IQueryable
,将创建投影的表示,并且您的LINQ提供程序将决定在运行时如何处理它。出于向后兼容的原因,?。
不能在此处使用
根据LINQ提供者的不同,您可能能够使用普通的
,但仍然无法获得任何NullReferenceException
Jon Skeet的答案是正确的,在我的例子中,我对实体类使用了DateTime
。
当我尝试使用like时
(a.DateProperty == null ? default : a.DateProperty.Date)
我犯了错误
Property 'System.DateTime Date' is not defined for type 'System.Nullable`1[System.DateTime]' (Parameter 'property')
所以我需要为我的实体类和
(a.DateProperty == null ? default : a.DateProperty.Value.Date)
虽然表达式树不支持C#6.0空传播,但我们可以创建一个访问者来修改表达式树以实现安全的空传播,就像操作符所做的那样
公共类NullPropagationVisitor:ExpressionVisitor
{
私有只读布尔递归;
公共NullPropagationVisitor(布尔递归)
{
_递归=递归;
}
受保护的重写表达式访问权限(UnaryExpression propertyAccess)
{
if(propertyAccess.Operator为MemberExpression mem)
回访成员(mem);
if(propertyAccess.Operator为MethodCallExpression满足)
回访方法调用(met);
if(propertyAccess.Operator为ConditionalPression cond)
返回表达式.条件(
测试:条件测试,
Ifrue:MakeNullable(访问(cond.Ifrue)),
ifFalse:MakeNullable(访问(cond.ifFalse));
返回base.visitonary(propertyAccess);
}
受保护的重写表达式VisitMember(MemberExpression propertyAccess)
{
返回Common(propertyAccess.Expression,propertyAccess);
}
受保护的重写表达式VisitMethodCall(MethodCallExpression propertyAccess)
{
if(propertyAccess.Object==null)
返回base.VisitMethodCall(propertyAccess);
返回公共(propertyAccess.Object,propertyAccess);
}
专用块表达式公用(表达式实例、表达式属性访问)
{
var safe=_recursive?base.Visit(实例):实例;
var caller=Expression.Variable(safe.Type,“caller”);
var assign=Expression.assign(调用者,安全);
var acess=MakeNullable(新表达式替换程序(实例,
IsNullableStruct(实例)?调用者:Removenulable(调用者)).Visit(propertyAccess));
var=表达式.条件(
测试:Expression.Equal(调用者,Expression.Constant(null)),
ifTrue:Expression.Constant(null,acess.Type),
如果是:访问);
返回表达式.Block(
类型:acess.type,
变量:新[]
{
呼叫者
},
表达式:新表达式[]
{
分配
三元,
});
}
私有静态表达式MakeNullable(表达式ex)
{
if(IsNullable(ex))
退换货;
返回表达式.Convert(ex,typeof(null).MakeGenericType(ex.Type));
}
私有静态bool可为空(表达式ex)
{
return!ex.Type.IsValueType | |(Nullable.GetUnderlyingType(ex.Type)!=null);
}
私有静态bool IsNullableStruct(表达式ex)
{
返回ex.Type.IsValueType&(null.getUnderlineType(ex.Type)!=null);
}
私有静态表达式可移除(表达式ex)
{
if(IsNullableStruct(ex))
返回表达式.Convert(ex,ex.Type.GenericTypeArguments[0]);
退换货;
}
私有类ExpressionReplacer:ExpressionVisitor
{
私有只读表达式_oldEx;
私有只读表达式_newEx;
内部表达式替换程序(表达式oldEx、表达式newEx)
{
_oldEx=oldEx;
(a.DateProperty == null ? default : a.DateProperty.Value.Date)