82 votes

Vérification du paramètre de type d'une méthode générique en C#

Est-il possible de faire quelque chose comme ça en C# ?

public void DoSomething<T>(T t)  
{
    if (T is MyClass)
    {
        MyClass mc = (MyClass)t 
        ...
    }
    else if (T is List<MyClass>)
    {
        List<MyClass> lmc = (List<MyClass>)t
        ...
    }
}

128voto

Jon Skeet Points 692016

Oui :

if (typeof(T) == typeof(MyClass))
{
    MyClass mc = (MyClass)(object) t;
}
else if (typeof(T) == typeof(List<MyClass>))
{
    List<MyClass> lmc = (List<MyClass>)(object) t;
}

Il est un peu étrange que vous deviez passer par une conversion en objet, mais c'est ainsi que fonctionnent les génériques - il n'y a pas autant de conversions à partir d'un type générique qu'on pourrait le penser.

Bien entendu, une autre solution consiste à utiliser le contrôle normal du temps d'exécution :

MyClass mc = t as MyClass;
if (mc != null)
{
    // ...
}
else
{
    List<MyClass> lmc = t as List<MyClass>;
    if (lmc != null)
    {
        // ...
    }
}

Cela se comportera différemment du premier bloc de code si t est nul, bien sûr.

Je voudrais essayez d'éviter ce type de code dans la mesure du possible, cependant - cela peut être nécessaire parfois, mais l'idée des méthodes génériques est d'être en mesure d'écrire Générique qui fonctionne de la même manière pour tous les types.

13voto

mark.monteiro Points 1038

À partir de C# 7, vous pouvez le faire de manière concise avec la fonction is opérateur :

public void DoSomething<T>(T value)  
{
    if (value is MyClass mc)
    {
        ...
    }
    else if (value is List<MyClass> lmc)
    {
        ...
    }
}

Voir la documentation : https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/is#pattern-matching-with-is

10voto

Sousuke Points 878

Nous sommes en 2017 et nous avons maintenant C# 7 avec le pattern matching. Si votre type T hérite object vous pouvez coder comme ceci

void Main()
{
    DoSomething(new MyClass { a = 5 });
    DoSomething(new List<MyClass> { new MyClass { a = 5 }, new MyClass { a = 5 }});
}

public void DoSomething(object t)
{
    switch (t)
    {
        case MyClass c:
            Console.WriteLine($"class.a = {c.a}");
            break;
        case List<MyClass> l:
            Console.WriteLine($"list.count = {l.Count}");
            break;
    }
}

class MyClass
{
    public int a { get; set;}
}

3voto

this. __curious_geek Points 23728

Je crois qu'il y a un problème dans votre conception. Vous voulez comparer des types dans une méthode déjà générique. Les génériques sont destinés à gérer les situations de type-variable. Je recommande de le faire de cette façon

//Generic Overload 1
public void DoSomething<T>(T t)
    where T : MyClass
{
    ...
}

//Generic Overload 2
public void DoSomething<T>(T t)
    where T : List<MyClass>
{
    ...
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X