web-dev-qa-db-fra.com

renvoyer un IEnumerable générique <T>

Je m'amuse avec les génériques et IEnumerable abit, mais je suis un peu coincé. Voici ce que j'essaie de faire:

de plus, je veux pouvoir renvoyer n'importe quel type de collection, de tout type de données . Je souhaite donc que cette méthode puisse renvoyer un List<string>, ainsi qu'un Stack<int>, ainsi qu'un List<double>... etc. 

 public IEnumerable<T> returnSomething() 
    {
        Stack<int> stackOfInts = new Stack<int>();
        List<string> listOfStrings = new List<string>();
        return stackOfInts;
    }

c'est ce que j'ai essayé jusqu'à présent. cela ne fonctionne cependant pas, je reçois cette erreur:

Cannot implicitly convert type 'System.Collections.Generic.Stack<int>' to 'System.Collections.Generic.IEnumerable<T>'. An explicit conversion exists (are you missing a cast?)

cependant, si je remplace le IEnumerable<T> dans la signature de méthode par IEnumerable<int>, je peux renvoyer n'importe quelle collection de type int. Cela signifie cependant que je ne peux plus retourner la ListOfStrings maintenant.

apprécierait des suggestions ou des idées :)

21
Thousand

Vous devez ajouter un paramètre de type generic à votre méthode:

public IEnumerable<T> ReturnSomething<T>() 
{
    Stack<T> stackOfT = new Stack<T>();
    return stackOfT;
}

Le paramètre type apparaît après le nom de la méthode, mais avant les paramètres. Il est également possible d'avoir une méthode avec plus d'un paramètre de type.

Lorsque vous appelez la méthode, vous pouvez spécifier le type:

IEnumerable<int> myInts = ReturnSomething<int>();
29
Mark Byers

L'astuce consiste à déclarer <T> à droite, si vous définissez un <T> générique, vous devez vous y tenir dans vos méthodes, donc si vous avez IEnumerable<T>, puis ailleurs dans votre méthode, vous devez utiliser <T> et non <int> ou tout autre type. . 

Ce n'est que plus tard que vous utilisez utilisez votre type générique vous substituez un <T> générique à un type réel.

Voir un échantillon

class Foo<T>
{
    public IEnumerable<T> GetList()
    {
        return new List<T>();
    }

    public IEnumerable<T> GetStack()
    {
        return new Stack<T>();
    }
}

class Program
{
    static void Main(string[] args)
    {
        Foo<int> foo = new Foo<int>();
        IEnumerable<int> list = foo.GetList();
        IEnumerable<int> stack = foo.GetStack();

        Foo<string> foo1 = new Foo<string>();
        IEnumerable<string> list1 = foo1.GetList();
        IEnumerable<string> stack1 = foo1.GetStack();
    }
}
11
oleksii
public IEnumerable<T> returnSomething() 
{
    Stack<int> stackOfInts = new Stack<int>();
    return (IEnumerable<T>) stackOfInts;
}
3
burning_LEGION

Le paramètre type doit être spécifié par l'appelant quelque part.

Soit lors de l'instanciation d'une classe générique:

public class MyClass<T>
{
    public IEnumerable<T> returnSomething()
    {
        Stack<T> stackOfTs = new Stack<T>();
        List<T> listOfTs = new List<T>();
        return stackOfTs;
    }
}

var v = new MyClass<int>();
foreach(var item in v.returnSomething())
{
}

Ou lorsque vous appelez une méthode générique d'une classe non générique:

public class MyClass
{
    public IEnumerable<T> returnSomething<T>()
    {
        Stack<T> stackOfTs = new Stack<T>();
        List<T> listOfTs = new List<T>();
        return stackOfTs;
    } 
}


var v = new MyClass();
foreach(var item in v.returnSomething<int>())
{
}
2
Joe

Oui, vous pouvez renvoyer n'importe quel type si vous changez IEnumerable<T> to IEnumerable<dynamic>

comme ça:

public IEnumerable<dynamic> returnSomething() 
{
.....
0
HatSoft