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()からの期待される出力は、リスト{2、3}です。ただし、コンパイラはinput.Contains(b)、に次の2つのエラーを報告します。

  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がそれらのタイプの1つである場合、ステートメント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、オブジェクトなど)がintにキャスト可能であることを保証できません。そのため、最初のエラーが発生します。

状況によっては、関数のシグニチャでオブジェクトの種類を指定できる場合があります。

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

intは構造体であるため、これはあなたのケースでは機能しません。あなたは他の多くの方法でそれを扱うことができます(与えられた他の答えはいくつかの素晴らしい方法を概説しています)が、あなたは何らかの方法であなたの現在の戦略を調整しなければなりません。

于 2012-11-13T21:30:05.773 に答える