在特殊情况下解决泛型和非泛型IList扩展方法之间的模糊调用

时间:2016-01-21 09:45:42

标签: c# generics extension-methods

我有一个名为RemoveWhere的扩展功能。它只接受谓词并从列表中删除满足条件的项。为清楚起见,我删除了实现。

public static IList<object> RemoveWhere(this IList list, Func<object, bool> predicate, int offset = 0)
{
    ...
}

public static IList<T> RemoveWhere<T>(this IList<T> list, Func<T, bool> predicate, int offset = 0)
{
    ...
}

我也需要此方法用于通用IList<T>和非通用IList,因为我们有几种情况只有非通用接口可用。

但是,当我有一个特定的List<T>实例时,我得到一个模糊的调用编译时错误,因为它实现了通用和非通用接口。

如果不重命名其中一种方法,我怎么解决呢?

更新

我正在寻找适用于可能实现两种接口的所有集合的通用解决方案。我目前使用Visual Studio 2013并以.NET 4为目标。

更新2

事实证明,只有当我不在谓词中直接引用T的任何成员时,才会出现模糊的呼叫问题。这里的例子。

class Person {}
class SpecialPerson : Person {}

var list = new List<Person>();
// this resolves to the generic version
list.RemoveWhere(e => e.Name.Contains("Peter");
// this gives ambiguous call compiler error
list.RemoveWhere(e => e is SpecialPerson);

3 个答案:

答案 0 :(得分:2)

如果已经测试了这段代码,它会为不同的类型调用正确的扩展名:

class Program
{
    static void Main(string[] args)
    {
        var genericList = new List<String>() {"a", "b"};
        var listImplementation = new MyList();

        var resultGeneric = genericList.RemoveWhere(x => x.Contains("s"));
        var resultImplemented = listImplementation.RemoveWhere(x => x.Equals(1));
    }
}

class MyList : IList
{
   ...
}

public static class JTest
{
    public static IList RemoveWhere(this IList list, Func<object, bool> predicate, int offset = 0)
    {
        return list;
    }

    public static IList<T> RemoveWhere<T>(this IList<T> list, Func<T, bool> predicate, int offset = 0)
    {
        return list;
    }
}

答案 1 :(得分:1)

你可以引入第三个重载(!)来调用正确的重载,如:

public static IList<T> RemoveWhere<T>(this List<T> list, Func<T, bool> predicate, int offset = 0)
{
  return ((IList<T>)list).RemoveWhere(prdeicate, offset);
}

答案 2 :(得分:0)

对于这种特殊情况,当我没有引用谓词中T的任何成员时,我最终将通用参数添加到调用中,帮助编译器。

class Person {}
class SpecialPerson : Person {}

var list = new List<Person>();
// this resolves to the generic version
list.RemoveWhere(e => e.Name.Contains("Peter");
// this gives ambiguous call compiler error
list.RemoveWhere(e => e is SpecialPerson);
// if I help the compiler it resolves correctly
list.RemoveWhere<Person>(e => e is SpecialPerson);