静态方法/调用者的类类型推断?

时间:2010-06-28 14:17:12

标签: c# generics type-inference

鉴于以下两个类:

public class ABC
{
    public void Accept(Ordering<User> xyz)
    {
        // Do stuff with xyz...
    }
}

public class Ordering<TEntity>
        where TEntity : class
{
    private readonly Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> Transform;

    private Ordering(Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> transform)
    {
        this.Transform = transform;
    }

    public static Ordering<TEntity> By<TKey>(Expression<Func<TEntity, TKey>> expression)
    {
        return new Ordering<TEntity>(query => query.OrderBy(expression));
    }

    public static Ordering<TEntity> ByDescending<TKey>(Expression<Func<TEntity, TKey>> expression)
    {
        return new Ordering<TEntity>(query => query.OrderByDescending(expression));
    }

    public Ordering<TEntity> ThenBy<TKey>(Expression<Func<TEntity, TKey>> expression)
    {
        return new Ordering<TEntity>(query => this.Transform(query).ThenBy(expression));
    }

    public Ordering<TEntity> ThenByDescending<TKey>(Expression<Func<TEntity, TKey>> expression)
    {
        return new Ordering<TEntity>(query => this.Transform(query).ThenByDescending(expression)); 
    }

    public IOrderedQueryable<TEntity> Apply(IQueryable<TEntity> query)
    {
        return Transform(query);
    }

}

以下列方式使用:

ABC abc = new ABC();
abc.Accept(Ordering<User>.By(u => u.Id));

有没有办法推断T的类型如此:

abc.Accept(Ordering.By(u => u.Id));

1 个答案:

答案 0 :(得分:4)

您可以这样做,但不能使用通用类型。像这样的泛型类型推断只发生在泛型方法中。使用通用方法声明单独的 - 泛型类型:

public class XYZ
{
    public static XYZ Action<T, TKey> (TKey key, T element)
    {
        return new XYZ<T>(element);
    }
}

编辑:回答问题编辑。

不,你做不到这样的事情:

abc.Accept(Ordering.By(u => u.Id));

问题在于内在表达:

Ordering.By(u => u.Id)

这里u的类型是什么?它可以是具有Id属性的任何类。请注意,在查看abc.Accept之前,C#编译器需要计算出该表达式的类型。即使只有abc.Accept 适用于Ordering<User>,也会失败。

这里有三个选项:

  • 在泛型类中使用静态方法,显式指定源类型参数,并推断键类型参数:

    Ordering<User>.By(u => u.Id)
    
  • 在非泛型类中使用泛型方法,明确指定两个类型参数:

    Ordering.By<User, string>(u => u.Id)
    
  • 在非泛型类中使用泛型方法,显式指定lambda参数的类型,并让编译器推断键类型参数:

    Ordering.By((User u) => u.Id)
    

显然,所有这些情况都要求您在某处明确指定类型。

如果您通常已经拥有User的实例(或至少是该类型的变量),则另一个选项是 little 位奇怪是相关的。您可以将其作为一种示例,将被忽略:

public static Ordering<T> By<T,TKey>(Expression<Func<T, TKey>> func, T example)
{
    return By<T, TKey>(func);
}
...

Ordering.By(u => u.Id, dummyUser);