C# 在特殊情况下解决泛型和非泛型IList扩展方法之间的不明确调用

C# 在特殊情况下解决泛型和非泛型IList扩展方法之间的不明确调用,c#,generics,extension-methods,C#,Generics,Extension Methods,我有一个名为removehere的扩展函数。它只接受一个谓词并从满足条件的列表中删除项。为了清晰起见,我删除了实现 public static IList<object> RemoveWhere(this IList list, Func<object, bool> predicate, int offset = 0) { ... } public static IList<T> RemoveWhere<T>(this IList<

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

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)
{
    ...
}

您可以引入第三个重载(!),称之为正确的重载,如中所示:

public static IList<T> RemoveWhere<T>(this List<T> list, Func<T, bool> predicate, int offset = 0)
{
  return ((IList<T>)list).RemoveWhere(prdeicate, offset);
}
公共静态IList RemoveWhere(此列表,Func谓词,int offset=0)
{
return((IList)list).RemoveWhere(prdeicate,offset);
}

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

public static IList<T> RemoveWhere<T>(this List<T> list, Func<T, bool> predicate, int offset = 0)
{
  return ((IList<T>)list).RemoveWhere(prdeicate, offset);
}
公共静态IList RemoveWhere(此列表,Func谓词,int offset=0)
{
return((IList)list).RemoveWhere(prdeicate,offset);
}

如果您已经测试了此代码,并且它为不同类型调用了正确的扩展名:

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;
    }
}
类程序
{
静态void Main(字符串[]参数)
{
var genericList=新列表(){“a”,“b”};
var listImplementation=new MyList();
var resultGeneric=genericList.RemoveWhere(x=>x.Contains(“s”);
var resultImplemented=listImplementation.RemoveWhere(x=>x.Equals(1));
}
}
类MyList:IList
{
...
}
公共静态类JTest
{
公共静态IList RemoveWhere(此IList列表,Func谓词,int offset=0)
{
退货清单;
}
公共静态IList RemoveWhere(此IList列表,Func谓词,int offset=0)
{
退货清单;
}
}

如果您已经测试了此代码,并且它为不同类型调用了正确的扩展名:

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;
    }
}
类程序
{
静态void Main(字符串[]参数)
{
var genericList=新列表(){“a”,“b”};
var listImplementation=new MyList();
var resultGeneric=genericList.RemoveWhere(x=>x.Contains(“s”);
var resultImplemented=listImplementation.RemoveWhere(x=>x.Equals(1));
}
}
类MyList:IList
{
...
}
公共静态类JTest
{
公共静态IList RemoveWhere(此IList列表,Func谓词,int offset=0)
{
退货清单;
}
公共静态IList RemoveWhere(此IList列表,Func谓词,int offset=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);
class-Person{}
类特殊人物:人物{}
var list=新列表();
//这将解析为通用版本
list.removehere(e=>e.Name.Contains(“Peter”);
//这将导致不明确的调用编译器错误
list.remove其中(e=>e是SpecialPerson);
//如果我帮助编译器,它将正确解析
list.remove其中(e=>e是SpecialPerson);

对于这种特殊情况,当我没有在谓词中引用
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);
class-Person{}
类特殊人物:人物{}
var list=新列表();
//这将解析为通用版本
list.removehere(e=>e.Name.Contains(“Peter”);
//这将导致不明确的调用编译器错误
list.remove其中(e=>e是SpecialPerson);
//如果我帮助编译器,它将正确解析
list.remove其中(e=>e是SpecialPerson);


尝试像这样声明第一个:…RemoveWhere(this System.Collections.IList list,…查看此声明是否能解决问题:`}公共静态T RemoveWhere(this T list,Func predicate,int offset=0)其中T:IList{}`@jvanrhyn是的,这就解决了它,但是现在在
列表上调用它将选择这个不太具体的版本,没有强类型谓词,等等。我可能最终会将这些版本放在单独的名称空间中。不,不是。实际上
IList
并没有实现
IList
,这很有趣。但这不是与此无关。感谢大家的评论,我想我将把它们放在单独的名称空间中,如
Utils.CollectionExtensions
Utils.CollectionExtensions.NonGeneric
,或者反之亦然。试着像这样声明第一个:…removehere(this System.Collections.IList list,…查看此声明是否能解决以下问题:`}public static T removehere(此T list,Func谓词,int offset=0)其中T:IList{}`@jvanrhyn是的,这就解决了它,但是现在在
列表上调用它将选择这个不太具体的版本,没有强类型谓词,等等。我可能最终会将这些版本放在单独的名称空间中。不,不是。实际上
IList
并没有实现
IList
,这很有趣。但这不是谢谢大家的评论,我想我会把它们放在不同的名称空间中,比如
Utils.CollectionExtensions
Utils.CollectionExtensions.NonGeneric
,或者反之亦然。谢谢大家,是的,这肯定是一个选项,但我正在寻找一个通用的解决方案,它可以覆盖ccollection实现两个接口。但是我不清楚这一点,所以我会投票支持你,因为这当然是一个有效的答案。谢谢你,是的,这肯定是一个选项,但我正在寻找一个通用的解决方案,它将涵盖集合实现两个接口的所有场景。但是我不清楚这一点,所以我会我投票支持你,因为这当然是一个有效的答案。很有趣。我不知道为什么它对我不起作用。我使用的是Visual Studio 2013,目标是.NEt 4。你使用哪个编译器版本?@ZoltánTamási jvanrhyn是对的。问题中的复制示例似乎没有重现你的问题。等等!替换为
var resultGeneric=genericList.RemoveWhere(x=>true);
问题又被重现了!有点奇怪。@JeppeStigNielsen明白了,我尝试在谓词中使用
T
的一个成员,编译器发现我需要泛型版本。在我的