4

想知道为什么这不起作用。洞察力赞赏。

    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)' 的最佳重载方法匹配有一些无效参数

如果我不使用通用列表,这个 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)

4

5 回答 5

2

input应该是一个List<int>

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

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

于 2012-11-13T21:22:01.007 回答
2

也是另一种解决方案

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();
}
于 2012-11-13T21:28:38.903 回答
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)将没有意义。

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

于 2012-11-13T21:24:33.140 回答
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) 的方法。

于 2012-11-13T21:22:11.337 回答
0

编译器不能保证任何 <T> ——任何 <T>、 DateTime 、 object 等等—— 都可以转换为 int。这就是为什么你得到你的第一个错误。

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

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

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

于 2012-11-13T21:30:05.773 回答