web-dev-qa-db-fra.com

Réflexion C #: Comment obtenir le type d'un <int> Nullable?

Ce que je veux faire est quelque chose comme ceci:

switch( myObject.GetType().GetProperty( "id") )
{
    case ??: 
        // when Nullable<Int32>, do this
    case ??:
        // when string, do this
    case ??:
        // when Nullable<bool>, do this

Quel chemin sous object.GetType () aurait le nom de chaîne du type de données que je pourrais comparer en utilisant une instruction case? J'ai besoin de connaître le type pour pouvoir utiliser l'un des nombreux Convert.ToInt32 (chaîne) qui définissent la valeur de myObject à l'aide de Reflection.

24
Zachary Scott

Mise à jour: il semble que C # 7 supporte l'activation de Types comme le demandait cette question. C'est un peu différent, alors faites attention à la syntaxe des mines terrestres.

Vous n'avez pas besoin d'un nom de chaîne pour le comparer:

if (myObject.GetType().GetProperty("id").PropertyType == typeof(Nullable<Int32>))
    // when Nullable<Int32>, do this
else if (myObject.GetType().GetProperty("id").PropertyType == typeof(string))
    // when string, do this
else if (myObject.GetType().GetProperty("id").PropertyType == typeof(Nullable<bool>))
    // when Nullable<bool>, do this
10
M.Babcock

J'utilise le type de code suivant pour vérifier si le type est nullable et pour obtenir le type actuel:

if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
{
    return Nullable.GetUnderlyingType(type);
}

Si le type est par exemple Nullable, ce code retourne la partie int (type sous-jacent). Si vous avez juste besoin de convertir un objet en un type spécifique, vous pouvez utiliser System.Convert.ChangeType method.

54
Toni Parviainen

La question est très déroutante. Est-ce que "myObject" est un objet qui pourrait être un int nullable? Ou bien la propriété "id" est-elle éventuellement de type nullable int?

Si le premier cas, votre question ne peut pas être répondue car elle présuppose un mensonge. Il n'y a pas une telle chose comme un int nullable en boîte. Je remarque que toutes les réponses qui proposent if (myobject.GetType() == typeof(int?)) sont donc incorrectes; la condition ne sera jamais vraie.

Lorsque vous convertissez un int nullable en objet, il devient soit une référence null (si l'entier nullable n'a pas de valeur), soit un int encadré. Il n'y a aucun moyen de déterminer si un objet contient un int nullable car un objet never contient un int nullable.

Dans ce dernier cas, comparez le type de propriétéà typeof(int?). Vous ne pouvez pas utiliser un commutateur; seules les constantes peuvent être utilisées pour les cas de commutation et les types ne sont pas des constantes.

Cela dit, c'est une mauvaise odeur de code. Pourquoi utilisez-vous la réflexion en premier lieu?

17
Eric Lippert

Dans .net, les instances de types de valeur ne sont que des ensembles de bits, sans information de type associée. Cependant, pour chaque type de valeur autre que Nullable<T>, le système génère également un type de classe correspondant dérivé de System.ValueType. Une conversion d'élargissement existe du type valeur au type classe générée automatiquement, et une conversion restrictive du type classe généré automatiquement au type valeur. Dans le cas de Nullable<T>, il n'y a pas de type de classe généré automatiquement avec les conversions vers/depuis le type de valeur; Des conversions d'élargissement existent dans les deux sens entre Nullable<T> et le type de classe associé à T.

Autant que je sache, ce comportement étrange a été mis en œuvre pour permettre des comparaisons entre null et un Nullable<T> vide afin de renvoyer la valeur true.

2
supercat

Comme @Cody Grey l’a dit, les déclarations seraient probablement le meilleur moyen

var t = myObject.GetType();

if (t == typeof(Nullable<int>))
{ }
else if (t == typeof(string))
{}
else if (t==typeof(Nullable<bool>))
{}
0
heads5150