【问题标题】:passing in nullable Expression<Func<T, TResult>>? as method parameter?传入可为空的 Expression<Func<T, TResult>>?作为方法参数?
【发布时间】:2014-04-07 22:11:07
【问题描述】:

所以我有一个方法

public IPagedList<MyObject> GetAll<T>(Expression<Func<MyObject, T>>? orderBy, 
    int pageNumber = 1, int pageSize = 10)
{
    return dataContext.MyObjects
      .OrderBy(orderBy.HasValue ? orderBy.Value : <WHAT GOES HERE?>)
      .ToPagedList<MyObject>(pageNumber, pageSize);
}

我的目标是让orderBy 参数可选,如果orderBynull,则默认顺序为属性MyObject.Id

我尝试过.OrderBy(orderBy.Hasvalue ? orderBy.Value : x =&gt; x.Id),但收到此错误:

Type of conditional expression cannot be determined because there is no implicit conversion between 'System.Func&lt;MyObject, T&gt;' and 'lambda expression'

我做错了什么?

谢谢!

【问题讨论】:

  • 这个编译是否带有问号? Expression&lt;Func&lt;MyObject, T&gt;&gt;?
  • Expression&lt;&gt; 是一个引用类型。不能做成Nullable&lt;&gt;Nullable&lt;&gt;只适用于值类型。
  • @KirkWoll 我知道,这就是我要问的原因。它应该在转换之前给出那个错误
  • 啊!我知道我哪里出错了

标签: c# lambda expression


【解决方案1】:

您的代码存在一些问题

  • Expression&lt;TDelegate&gt; 是一个类,所以它已经可以为空了;你可以简单地测试一下orderBy == nullNullable&lt;T&gt; 有一个通用约束 T 必须是 struct,所以 Expression&lt;Func&lt;MyObject, T&gt;&gt;? 不会编译。
  • 接下来你会遇到问题,因为T 类型没有绑定在方法内部,但x.Id 是。换句话说,您将无法创建使用条件运算符在 Expression&lt;Func&lt;MyObject, T&gt;&gt;Expression&lt;Func&lt;MyObject, int&gt;&gt; 的值之间进行选择(假设 Idint),同时仍然保持类型信息传递给OrderBy 方法。

解决方案是按照以下思路使用一些东西:

public IPagedList<MyObject> GetAll<T>(Expression<Func<MyObject, T>> orderBy, 
    int pageNumber = 1, int pageSize = 10)
{
    IQueryable<MyObject> objects = dataContext.MyObjects;
    objects = (orderBy != null) ? objects.OrderBy(orderBy) 
                                : objects.OrderBy(x => x.Id);
    return objects.ToPagedList<MyObject>(pageNumber, pageSize);
}

条件运算符在此代码中起作用,因为无论您传递给OrderBy 什么,返回类型都是相同的IQueryable&lt;MyObject&gt;

还请注意,您不能简单地为orderBy 传递一个空值,因为无法推断T。你必须这样称呼它:

var results = MyClass.GetAll<int>(null);

最终,您最好创建两个重载,一个接受 orderBy 表达式,另一个不接受。

【讨论】:

  • 或者您也可以将表达式参数设为可选:GetAll&lt;T&gt;(Expression&lt;Func&lt;MyObject, T&gt;&gt;? orderBy = null
  • @Selman22 我认为您的意思是从您的评论中删除 ?。即使int(或您传递的任何类型参数)没有以任何方式使用,您仍然必须将其称为MyClass.GetAll&lt;int&gt;()。我仍然建议您可以在没有orderBy 且没有类型参数的情况下调用一个重载。
猜你喜欢
  • 2011-07-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-12
相关资源
最近更新 更多