Je veux faire quelque chose comme ça:
myYear = record.GetValueOrNull<int?>("myYear"),
Notez le type nullable comme paramètre générique.
Puisque la GetValueOrNull
fonction pouvait retourner null, ma première tentative était la suivante:
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 maintenant est:
Le type 'int?' doit être un type de référence pour pouvoir l'utiliser comme paramètre 'T' dans le type ou la méthode générique
Droite! Nullable<int>
est un struct
! J'ai donc essayé de changer la contrainte de classe en struct
contrainte (et comme effet secondaire, je ne peux plus retourner null
):
public static T GetValueOrNull<T>(this DbDataRecord reader, string columnName)
where T : struct
Maintenant l'affectation:
myYear = record.GetValueOrNull<int?>("myYear");
Donne l'erreur suivante:
Le type 'int?' doit être un type de valeur non nullable afin de l'utiliser comme paramètre 'T' dans le type ou la méthode générique
Est-il possible de spécifier un type nullable comme paramètre générique?
IDataRecord
deDbDataRecord
..Réponses:
Modifiez le type de retour sur Nullable et appelez la méthode avec le paramètre non nullable
la source
Utilisez-le simplement comme ceci:
la source
GetValueOrDefault
pour préciser qu'il revientdefault(T)
plutôt quenull
. Alternativement, vous pouvez lui faire lever une exception s'ilT
n'est pas annulable.Faites simplement deux choses avec votre code d'origine - supprimez la
where
contrainte et changez la dernièrereturn
dereturn null
enreturn default(T)
. De cette façon, vous pouvez retourner le type que vous souhaitez.Soit dit en passant, vous pouvez éviter l'utilisation de
is
en remplaçant votreif
relevé parif (columnValue != DBNull.Value)
.la source
return default
suffit (vous n'avez pas besoin de(T)
, le compilateur le déduira du type de retour de signature).Avertissement: Cette réponse fonctionne, mais est destinée à des fins éducatives uniquement. :) La solution de James Jones est probablement la meilleure ici et certainement celle avec laquelle j'irais.
Le
dynamic
mot - clé de C # 4.0 rend cela encore plus facile, mais moins sûr:Maintenant, vous n'avez pas besoin de l'indication de type explicite sur le RHS:
En fait, vous n'en avez même pas besoin du tout!
value
sera désormais un int, une chaîne ou tout autre type renvoyé par la base de données.Le seul problème est que cela ne vous empêche pas d'utiliser des types non nullables sur le LHS, auquel cas vous obtiendrez une exception d'exécution plutôt méchante comme:
Comme avec tout code qui utilise
dynamic
: caveat coder.la source
Je devais juste faire quelque chose d'incroyable similaire à cela. Mon code:
la source
Je pense que vous voulez gérer les types de référence et les types de struct. Je l'utilise pour convertir des chaînes d'élément XML en un type plus typé. Vous pouvez supprimer le nullAlternative avec réflexion. Le formatprovider doit gérer la culture dépendante "." ou «,» séparateur en par exemple décimales ou en pouces et doubles. Cela peut fonctionner:
Vous pouvez l'utiliser comme ceci:
la source
Cela peut être un fil mort, mais j'ai tendance à utiliser ce qui suit:
la source
Je viens de rencontrer le même problème moi-même.
... = reader["myYear"] as int?;
fonctionne et est propre.Il fonctionne avec tout type sans problème. Si le résultat est DBNull, il renvoie null lorsque la conversion échoue.
la source
int v=reader["myYear"]??-1;
ou une autre valeur par défaut au lieu de-1
. Cependant, cela pourrait soulever des problèmes si la valeur estDBNull
...Je sais que c'est vieux, mais voici une autre solution:
Maintenant, vous ne vous souciez plus de la
T
valeur ou du type de référence. Seulement si la fonction retourne true, vous avez une valeur raisonnable dans la base de données. Usage:Cette approche est très similaire à
int.TryParse("123", out MyInt);
la source
Plusieurs contraintes génériques ne peuvent pas être combinées de manière OU (moins restrictive), mais uniquement de façon ET (plus restrictive). Cela signifie qu'une méthode ne peut pas gérer les deux scénarios. Les contraintes génériques ne peuvent pas non plus être utilisées pour créer une signature unique pour la méthode, vous devez donc utiliser 2 noms de méthode distincts.
Cependant, vous pouvez utiliser les contraintes génériques pour vous assurer que les méthodes sont utilisées correctement.
Dans mon cas, je voulais spécifiquement que null soit renvoyé, et jamais la valeur par défaut des types de valeurs possibles. GetValueOrDefault = mauvais. GetValueOrNull = bon.
J'ai utilisé les mots "Null" et "Nullable" pour faire la distinction entre les types de référence et les types de valeur. Et voici un exemple de quelques méthodes d'extension que j'ai écrites et qui complimentent la méthode FirstOrDefault dans la classe System.Linq.Enumerable.
la source
La manière la plus courte:
revenir
0
pourint
, etnull
pourint?
la source