适用于IEnumerable <t>和IQueryable <t>?</t> </t>的扩展方法

时间:2011-10-10 13:16:23

标签: c# generics extension-methods

我想要一个适用于我的List和IQueryable的扩展方法。下面的扩展方法实现了这一点,但是如果我添加另一个相同的扩展方法,但是在一个不同的完全不相关的类型上我得到了模糊的调用 编译错误。这是为什么?编译器是否足够聪明,无法知道哪种扩展方法有效?我的意思是,这些调用中只有一个是有效的,为什么编译器无法告诉?非常感谢!

class ClassA
{
  public bool IsActive{ get; set;}
}

class ClassB
{
  public bool IsActive { get; set;}
}


// then here are my extensions

public static T IsActive<T>(this T enumerableOrQueryable, bool isActive)
  where T : IEnumerable<ClassA>
{
  return (T)enumerableOrQueryable.Where(x => x.IsActive == isActive);
}

public static T IsActive<T>(this T enumerableOrQueryable, bool isActive)
  where T : IEnumerable<ClassB>
{
  return (T)enumerableOrQueryable.Where(x => x.IsActive == isActive);
}

3 个答案:

答案 0 :(得分:8)

重载规则没有考虑它正在考虑的方法的约束 - 它确定哪个重载最好,然后验证约束匹配。

编译器完全遵循C#规范的规则。

相关博文:

编辑:请注意,使用“enumerableOrQueryable”总是将lambda表达式转换为委托,而不是表达式树。因此,如果您希望它以不同的方式为数据库执行逻辑,那么无论如何都需要进行更改。

编辑:您的想法无效,因为无论如何都不会得到相同的结果类型 - 如果您在Where上致电List<string>,则返回值不是 a List<string>

如果您可以引入由ClassA和ClassB实现的新接口, 可以做什么呢?

public static IQueryable<T> IsActive<T>(this IQueryable<T> source, bool isActive)
    where T : ICanBeActive
{
    // Lambda converted to an expression tree
    return source.Where(x => x.IsActive == isActive);
}

public static IEnumerable<T> IsActive<T>(this IEnumerable<T> source,
    bool isActive) where T : ICanBeActive
{
    // Lambda converted to a delegate
    return source.Where(x => x.IsActive == isActive);
}

答案 1 :(得分:1)

编译器无法解决通用约束中的歧义。对于你的情况,你不能只做这样的事情吗?

public static IEnumerable<ClassA> IsActive(this IEnumerable<ClassA> enumerableOrQueryable, bool isActive)
{
  return enumerableOrQueryable.Where(x => x.IsActive == isActive);
}

答案 2 :(得分:0)

您可以尝试这样的事情:

public interface IActivatable
{
    bool IsActive { get; set; }
}

public class ClassA : IActivatable
{
    public bool IsActive{ get; set;}
}

public class ClassB : IActivatable
{
    public bool IsActive { get; set;}
}

public static class Ext
{
    public static IEnumerable<T> IsActive<T>(this IEnumerable<T> collection, bool isActive) where T : IActivatable
    {
        return collection.Where(x => x.IsActive == isActive);
    }
}