web-dev-qa-db-fra.com

Comment initialiser le type de paramètre générique T?

Question simple:
Si vous avez un string x, pour l’initialiser, procédez de l’une des manières suivantes: 

string x = String.Empty;  

ou 

string x = null;

Qu'en est-il du paramètre générique T? 

J'ai essayé de faire: 

void someMethod<T>(T y)
{
    T x = new T();  
    ...
}

Générer une erreur:
Impossible de créer une instance du type de variable 'T' car elle n'a pas la contrainte new ()

19
JavaSa

Vous avez deux options:

Vous pouvez contraindre T: vous faites cela en ajoutant: where T : new() à votre méthode. Maintenant, vous pouvez uniquement utiliser la variable someMethod avec un type doté d'un constructeur par défaut sans paramètre (voir Contraintes sur les paramètres de type ).

Ou vous utilisez default(T). Pour un type de référence, cela donnera null. Mais par exemple, pour une valeur entière, ceci donnera 0 (voir Mot-clé default dans Code générique ).

Voici une application console de base qui montre la différence:

using System;

namespace Stackoverflow
{
    class Program
    {
        public static T SomeNewMethod<T>()
            where T : new()
        {
            return new T();
        }

        public static T SomeDefaultMethod<T>()
            where T : new()
        {
            return default(T);
        }

        struct MyStruct { }

        class MyClass { }

        static void Main(string[] args)
        {
            RunWithNew();
            RunWithDefault();
        }

        private static void RunWithDefault()
        {
            MyStruct s = SomeDefaultMethod<MyStruct>();
            MyClass c = SomeDefaultMethod<MyClass>();
            int i = SomeDefaultMethod<int>();
            bool b = SomeDefaultMethod<bool>();

            Console.WriteLine("Default");
            Output(s, c, i, b);
        }

        private static void RunWithNew()
        {
            MyStruct s = SomeNewMethod<MyStruct>();
            MyClass c = SomeNewMethod<MyClass>();
            int i = SomeNewMethod<int>();
            bool b = SomeNewMethod<bool>();

            Console.WriteLine("New");
            Output(s, c, i, b);
        }

        private static void Output(MyStruct s, MyClass c, int i, bool b)
        {
            Console.WriteLine("s: " + s);
            Console.WriteLine("c: " + c);
            Console.WriteLine("i: " + i);
            Console.WriteLine("b: " + b);
        }

    }
}

Il produit la sortie suivante:

New
s: Stackoverflow.Program+MyStruct
c: Stackoverflow.Program+MyClass
i: 0
b: False
Default
s: Stackoverflow.Program+MyStruct
c:
i: 0
b: False
30
Wouter de Kort

utilisez le mot clé default

T x = default(T);

Voir: Mot clé par défaut dans le code générique (Guide de programmation C #)

Étant donné une variable t d'un type paramétré T, l'instruction t = null n'est valide que si T est un type de référence et que t = 0 ne fonctionnera que pour types de valeur numérique mais pas pour les structures. La solution consiste à utiliser le mot-clé par défaut, qui renvoie null pour les types de référence et zéro pour les types de valeur numérique. Pour les structures, il retournera chaque membre de la structure initialisée à zéro ou à zéro selon qu'il s'agisse de types de valeur ou de référence.

9
Habib

Vous devez ajouter une contrainte new pour le paramètre de type T.

void someMethod<T>(T y) where T : new()
{
    T x = new T();  
    ...
}

Cela ne sera cependant valable que pour les types avec un constructeur par défaut.

La clause where pour T est une contrainte de type generic . Dans ce cas, tout type T auquel cette méthode est appliquée doit avoir un constructeur public sans paramètre.

7
Lee

Si vous avez vraiment besoin d'une instance de T et non d'une valeur null par défaut pour les types de référence, utilisez:

Activator.CreateInstance()
4
Oscar

Vous pouvez utiliser la construction default pour la définir sur le type par défaut de Type.

Le mot-clé default vous permet d'indiquer au compilateur qu'au moment de la compilation, la valeur par défaut de cette variable doit être utilisée. Si l'argument de type fourni est une valeur numérique (par exemple, int, long, decimal), la valeur par défaut est zéro. Si l'argument de type fourni est un type de référence, la valeur par défaut est null. Si l'argument de type fourni est une structure, la valeur par défaut de la structure est déterminée en initialisant chaque zone de membre de la structure sur zéro pour les types numériques ou sur null pour les types de référence.

Utilisez quelque chose comme:

T data = default(T);

Pour plus de détails, lisez: Initialisation des variables génériques à leurs valeurs par défaut

0
Amar