LINQ查询中的List <t> .Contains(T)错误</t>

时间:2012-11-13 21:18:12

标签: c# linq generics

想知道为什么这不起作用。洞察力很高兴。

    static void Main(string[] args)
    {
        List<int> foo = new List<int> { 1, 2, 3 };
        var myResult = MyTest<int>(foo);
    }

    private static List<int> MyTest<T>(List<T> input)
    {
        List<int> bar = new List<int> { 2, 3, 4 };
        return bar.Where(b => input.Contains(b)).ToList();
    }

MyTest()的预期输出是List {2,3}。但是,编译器会在input.Contains(b)上报告两个错误,如下所示:

  1. 参数1:无法从'int'转换为'T'

  2. 'System.Collections.Generic.List.Contains(T)'的最佳重载方法匹配有一些无效的参数

  3. 如果我不使用通用列表,这个Where()子句可以正常工作。

    这是我现实世界问题的简化,所以请不要陷入“为什么要写这个?”问题在于错误及其发生的原因。

    修订(希望)清晰度:

    namespace SandBox
    {
    
    class Foo
    {
        public int FooInt { get; set; }
        public string FooString { get; set; }
    }
    
    class Program
    {
        private static List<Foo> fooList = new List<Foo> {
                new Foo() {FooInt = 1, FooString = "A"},
                new Foo() {FooInt = 2, FooString = "B"},
                new Foo() {FooInt = 3, FooString = "C"}
        };
    
        static void Main(string[] args)
        {
            List<int> myIntList = new List<int> { 1, 2 };
            var myFirstResult = GetFoos<int>(myIntList);
    
            List<string> myStringList = new List<string> { "A", "B" };
            var mySecondResult = GetFoos<string>(myStringList);
        }
    
        /// <summary>
        /// Return a list of Foo objects that match the input parameter list
        /// </summary>
        private static List<Foo> GetFoos<T>(List<T> input)
        {
            //***
            // Imagine lots of code here that I don't want to duplicate in 
            // an overload of GetFoos()
            //***
    
            if (input is List<int>)
            {
                //Use this statement if a list of integer values was passed in
                return fooList.Where(f => input.Contains(f.FooInt));
            }
            else if (input is List<string>)
            {
                //Use this statement if a list of string values was passed in
                return fooList.Where(f => input.Contains(f.FooString));
            }
            else
                return null;
        }
    }
    }
    

    input.Contains(f.Property)报告了相同的编译器错误。

5 个答案:

答案 0 :(得分:2)

input应为List<int>

然后,每当你调用该函数时,如果T不是int,你就会知道它总会返回一个空列表。

T不是int时,该函数没有多大意义。

答案 1 :(得分:1)

单独看看这个功能。

private static List<int> MyTest<T>(List<T> input)
{
    List<int> bar = new List<int> { 2, 3, 4 };
    return bar.Where(b => input.Contains(b)).ToList();
}

如果T是对象...或者字符串怎么办?没有什么可以阻止T成为那些类型。如果T是这些类型中的一种,则语句input.Contains(b)将没有意义。

编译器抱怨,因为你允许使用方法体中的语句没有意义的类型。

答案 2 :(得分:1)

另一个解决方案

static void MainT(string[] args)
{
    List<int> foo = new List<int> { 1, 2, 3 };
    var myResult = MyTest<int>(foo);
}

private static List<int> MyTest<T>(List<T> input) where T : IEquatable<int>
{
    List<int> bar = new List<int> { 2, 3, 4 };
    return bar.Where(b => input.Any(i => i.Equals(b))).ToList();
}

答案 3 :(得分:0)

试试这个:

static void Main(string[] args)
{
    List<int> foo = new List<int> { 1, 2, 3 };
    var myResult = MyTest<int>(foo);
}

private static List<int> MyTest<T>(List<T> input)
{
    List<int> bar = new List<int> { 2, 3, 4 };
    return bar.Where(b => input.OfType<int>().Contains(b)).ToList();
}

问题在于编译器不知道T是什么类型。因为T可以是任何你不能调用期望int(input.Contains)。

的方法

答案 4 :(得分:0)

编译器不能保证任何&lt; T&gt; - 任何&lt; T&gt; ,DateTime,对象,等等 - 都可以转换为int。这就是你收到第一个错误的原因。

在某些情况下,您可以在函数的签名中指定一种对象:

 private static List<int> MyTest<T>(List<T> input)  where T : someObject

这对你的情况不起作用,因为int是一个结构。您可以通过许多其他方式使用它(其他答案给出了一些很好的方法),但您必须以某种方式调整当前的策略。