web-dev-qa-db-fra.com

Comment puis-je retourner NULL à partir d'une méthode générique en C #?

J'ai une méthode générique avec ce code (factice) (oui, je sais que IList a des prédicats, mais mon code n'utilise pas IList, mais une autre collection, de toute façon, cela n'a aucune pertinence pour la question ...)

static T FindThing<T>(IList collection, int id) where T : IThing, new()
{
    foreach T thing in collecion
    {
        if (thing.Id == id)
            return thing;
    }
    return null;  // ERROR: Cannot convert null to type parameter 'T' because it could be a value type. Consider using 'default(T)' instead.
}

Cela me donne une erreur de construction 

"Impossible de convertir null en paramètre de type 'T', car il pourrait s'agir d'un type de valeur . Pensez à utiliser 'default (T)' à la place."

Puis-je éviter cette erreur?

481
edosoft

Deux options:

  • Retourne default(T), ce qui signifie que vous retournerez null si T est un type de référence (ou un type de valeur nullable), 0 pour int, '\0' pour char, etc. ( Tableau des valeurs par défaut (Référence C #) )
  • Restreindre T comme type de référence avec la contrainte where T : class puis renvoyer null comme d'habitude
844
Jon Skeet
return default(T);
74
Ricardo Villamil

Vous pouvez simplement ajuster vos contraintes:

where T : class

Puis retourner null est autorisé.

27
TheSoftwareJedi

Ajoutez la contrainte de classe en tant que première contrainte à votre type générique.

static T FindThing<T>(IList collection, int id) where T : class, IThing, new()
10
Min
  1. Si vous avez un objet alors besoin de dactylographier 

    return (T)(object)(employee);
    
  2. si vous devez retourner null. 

    return default(T);
    
6
user725388

Votre autre option serait d’ajouter ceci à la fin de votre déclaration:

    where T : class
    where T: IList

De cette façon, cela vous permettra de renvoyer null.

5
BFree

Voici les deux options que vous pouvez utiliser

return default(T);

ou

where T : class, IThing
 return null;
4
Jaydeep Shil

solution de TheSoftwareJedi fonctionne,

vous pouvez aussi l’archiver avec deux types de valeur et nullable:

static T? FindThing<T>(IList collection, int id) where T : struct, IThing
{
    foreach T thing in collecion
    {
        if (thing.Id == id)
            return thing;
    }
    return null;
}
2
devi

Prenez la recommandation de l'erreur ... et l'utilisateur default(T) ou new T.

Vous devrez ajouter une comparaison dans votre code pour vous assurer que la correspondance est valide si vous suivez cette voie.

Sinon, considérez potentiellement un paramètre de sortie pour "correspondance trouvée".

1
Mitchel Sellers

Voici un exemple de travail pour les valeurs de retour Nullable Enum:

public static TEnum? ParseOptional<TEnum>(this string value) where TEnum : struct
{
    return value == null ? (TEnum?)null : (TEnum) Enum.Parse(typeof(TEnum), value);
}
1
Luke

Une autre alternative aux 2 réponses présentées ci-dessus. Si vous modifiez votre type de retour en object, vous pouvez retourner null tout en générant le retour non nul.

static object FindThing<T>(IList collection, int id)
{
    foreach T thing in collecion
    {
        if (thing.Id == id)
            return (T) thing;
    }
    return null;  // allowed now
}
0
Jeson Martajaya