14

如果我尝试这个,它将起作用:

var query = myContextObject.Users.Where(u=>u.Name == "John");
query.ToList();

我可以打电话ToList和很多其他的扩展方法。

但如果我试试这个:

public List ConvertQueryToList(IQueryable query)
{
    return query.ToList();
}

ToList将无法访问,我猜这是因为ToList它是一种扩展方法,但是ToList在第一个示例中是如何附加的?ToList在第二种情况下可以访问吗?

4

4 回答 4

20

你需要把它写成:

public List<T> ConvertQueryToList<T>(IQueryable<T> query)
{
    return query.ToList();
}

这将导致IQueryable<T>返回适当的List<T>,因为该Enumerable.ToList()方法需要一个IEnumerable<T>as 输入(它也适用于IQueryable<T>, as IQueryable<T>inheritsIEnumerable<T>)。

话虽如此,确实没有理由以这种方式使用它。ToList()如果您需要在第二层内部创建一个抽象,您总是可以直接调用List<T>,这只会进一步混淆 API。

如果您尝试转换非通用IQueryable接口,则需要执行以下操作:

public List<T> ConvertQueryToList<T>(IQueryable query)
{
    return query.Cast<T>.ToList();
}

这将需要像这样调用:

var results = ConvertQueryToList<SomeType>(queryable);

或者,如果您想保留这个非泛型(我不推荐),那么您可以使用:

public ArrayList ConvertQueryToList(IQueryable query)
{
    ArrayList results = new ArrayList();
    results.AddRange(query.Cast<object>().ToList());
    return results;
}
于 2012-09-03T22:58:42.633 回答
10

您的第一个示例返回一个IQueryable<T>,而在​​第二个示例中您正在使用IQueryable(没有通用类型参数)。

您可以在此处此处查看两个完全不同的界面。

于 2012-09-03T22:57:45.600 回答
5

这是一个扩展方法:

public static class ListHelper
{
    public static IList ToList(this IQueryable query)
    {
        var genericToList = typeof(Enumerable).GetMethod("ToList")
            .MakeGenericMethod(new Type[] { query.ElementType });
        return (IList)genericToList.Invoke(null, new[] { query });
    }
}
于 2016-06-16T07:50:53.843 回答
-1

这是您使用 IQueryable<> 的情况的通用扩展方法。当然,这不是绝对安全的,因为类型可能是错误的,并且转换可能会失败。因此,如果您使用该方法,请小心。

using System.Collections.Generic;
  
namespace System.Linq
{
    public static class Extensions
    {
        public static List<T> ToList<T>(this IQueryable queriable)
        {
            return ((IQueryable<T>)queriable).ToList();
        }
    }
}
于 2020-07-14T19:29:20.967 回答