373 votes

Type Nullable en tant que paramètre générique possible?

Je veux faire quelque chose comme ceci :

myYear = record.GetValueOrNull<int?>("myYear"),

Notez le type nullable que le paramètre générique.

Depuis le GetValueOrNull fonction peut retourner null ma première tentative a été ceci :

public static T GetValueOrNull<T>(this DbDataRecord reader, string columnName)
  where T : class
{
    object columnValue = reader[columnName];

    if (!(columnValue is DBNull))
    {
        return (T)columnValue;
    }
    return null;
}

Mais l'erreur que je reçois aujourd'hui est

Le type 'int?' doit être un type de référence afin de l'utiliser comme paramètre " T " dans le générique du type ou de la méthode

La droite! Nullable est une structure! J'ai donc essayé de changer la classe de contrainte sur une struct contrainte (et comme un effet secondaire peut pas retourner la valeur null ou plus):

public static T GetValueOrNull<T>(this DbDataRecord reader, string columnName)
  where T : struct

Maintenant la cession

myYear = record.GetValueOrNull<int?>("myYear");

Donne l'erreur suivante

Le type 'int?' doit être un non nullable type de valeur afin de l'utiliser comme paramètre " T " dans le générique du type ou de la méthode

Est la spécification d'un type nullable comme un paramètre générique à tous les possibles?

311voto

Greg Dean Points 12048

Changer le type de retour de Nullable et appelez la méthode avec le paramètre non nullable

127voto

James Jones Points 3291

Quelques années tard pour cela un mais je pense que c’est la meilleure solution :

Simplement l’utiliser comme ceci :

70voto

Robert C. Barth Points 9788

Juste faire deux choses pour votre code d’origine. Supprimer l’où les contrainte et le changement de la dernière déclaration de retourner une valeur null pour retourner des default (t). De cette façon vous pouvez retourner n’importe quel type que vous voulez.

Par ailleurs, vous pouvez éviter l’usage de « est » en changeant votre si déclaration if (columnValue ! = DBNull.Value).

7voto

Ian Kemp Points 6408

Avertissement: Cette réponse œuvres, mais il est conçu pour des buts éducatifs seulement. :) James Jones solution est probablement le meilleur ici et certainement celui que j'irais avec.

C# 4.0 dynamic mot-clé cela rend encore plus facile, si on l'est moins sûr:

public static dynamic GetNullableValue(this IDataRecord record, string columnName)
{
  var val = reader[columnName];

  return (val == DBNull.Value ? null : val);
}

Maintenant, vous n'avez pas besoin du type explicite allusion sur les RHS:

int? value = myDataReader.GetNullableValue("MyColumnName");

En fait, vous n'avez même pas besoin du tout!

var value = myDataReader.GetNullableValue("MyColumnName");

value va maintenant être un entier ou une chaîne de caractères, ou quel que soit le type renvoyé à partir de la DB.

Le seul problème est que cela ne vous empêche pas d'utiliser la non-types nullables LHS, dans ce cas, vous aurez un assez méchant runtime exception comme:

Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: Cannot convert null to 'int' because it is a non-nullable value type

Comme avec tous les code qui utilise dynamic: mise en garde codeur.

4voto

Toby Points 1340

Je devais juste faire quelque chose d’incroyable semblable à celui-ci. Mon code :

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