IQueryable<T> 的通用扩展方法

6

我已经在IQueryable上编写了一个扩展方法,它返回相同类型的IQueryable,只是进行了一些过滤。假设它是这样的:

public static IEnumerable<T> Foo<T>(this IEnumerable<T> source, int? howmany = null)
{
    if (howmany.HasValue)
        return source.Take(howmany.Value);
    return source;
}

调用上述方法就像这样简单:someLinqResult.Foo(2) 我需要另一个方法,它将返回其他基类不同于源T的其他泛型类的实例。
因此,这里是代码,假设该方法应该返回给定类型的列表(与IQueryable具有不同的输入类型!)但长度相同[实际问题是关于转换NHibernate查询结果,但这并不重要]:
public static List<TTarget> Bar<TTarget,TSource>(this IEnumerable<TSource> source)
{
    return new List<TTarget>(source.Count());
}

现在,考虑到strLinqResultIQueryable<string>,我需要调用它的strLinqResult.Bar<int,string>();

关键是我必须传递两种类型,即使第一种类型已经知道,因为我正在已定义的IQuerable上调用方法。

由于只需调用Foo(2)而不是Foo<string>(2),我认为编译器能够自动“传递/猜测”类型。

那么为什么我需要调用第二个方法Bar<int,string>();而不仅仅是Bar<int>()


实际代码:

    public static ListResponse<TResponse> 
        BuildListResponse<T,TResponse>(this IQueryable<T> iq, ListRequest request)
        where TResponse: new()
    {
        var result = iq.ApplyListRequestParams(request).ToList().ConvertAll(x => x.TranslateTo<TResponse>());
        var tcount = iq.Count();
        return new ListResponse<TResponse> {
                Items =  result,
                _TotalCount = tcount,
                _PageNumber = request._PageNumber ?? 1,
            };
    }
ApplyListRequestParams是示例代码中的一种Foo方法 - 它仅适用于ListRequest对象中可用的分页和排序参数。 ItemsListResponse<T>类中的一个public List<T> ItemsTranslateTo是ServiceStack中的一个方法。
上述方法在NHibernate返回的IQueryable<T> (T是域模型)上调用,它采用请求参数(排序、分页),应用它们,然后将结果列表从DomainModel转换为类型为TResponse的DTO对象。然后,该列表被包装在一个泛型响应类中(泛型,因此它可重复使用于多个DTO类型)。

@migajek:链接的答案建议在一个单独的泛型类上使用静态方法(而不是您正在使用的那个类)。或者,您可以使用中间类型安排使用扩展方法语法进行调用,但这将需要两个扩展方法调用。只使用一个调用的扩展方法语法需要编译器推断其中一个类型参数,但它没有这样做。 - Jon
@Jon编译器说我不能在泛型类上定义扩展方法。 - migajek
1
假设您添加了一个 Bar<TSource>(this IEnumerable<TSource> source)。如果编译器接受了您的速记方式,那么现在 strLinqResult.Bar<string>(); 是指 Bar<string> 还是 Bar<string, string> 就不再含糊不清了。我认为这就是 Johny Skovdal 在他的回答中所说的,但我想详细说明一下。 - Tim Goodman
Tim,谢谢。我是C#和泛型编程的新手,所以这对我来说不是很明显。 - migajek
不用谢。当然,我的评论应该说“现在会有歧义”,而不是“没有歧义”……但你懂我的意思。 :) - Tim Goodman
显示剩余6条评论
1个回答

3
如果我正确理解您的问题,您正在尝试尽可能少地输入参数。这是不可能的。只有全部或没有,它可以自己找出所有内容。
只指定一部分的问题在于,您将能够引入一个具有1个更少类型参数的类似方法,并且现在已经破坏了实现。
但是您能否分享您的原始问题?也许可以让编译器以其他方式解决它?

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接