Comment vérifier par programme si un type est une structure ou une classe?
Utilisation Type.IsValueType
:
Obtient une valeur indiquant si le Type est un type de valeur.
Utilisez-le soit comme ceci:
typeof(Foo).IsValueType
ou au moment de l'exécution comme ceci:
fooInstance.GetType().IsValueType
Inversement, il y a aussi un Type.IsClass
propriété (qui aurait dû être appelée IsReferenceType
à mon avis mais peu importe) qui peut ou non être plus appropriée pour vos utilisations en fonction de ce que vous testez.
Le code semble toujours mieux lire sans négations booléennes, alors utilisez ce qui aide à la lisibilité de votre code.
Comme Stefan le souligne ci-dessous, afin d'identifier correctement les structures , vous devez faire attention à éviter les faux positifs quand il s'agit de enums
. Un enum
étant un type de valeur, la propriété IsValueType
renverra true
pour enums
ainsi que structs
.
Donc, si vous recherchez vraiment structs
et pas seulement les types de valeur en général, vous devrez le faire:
Type fooType = fooInstance.GetType();
Boolean isStruct = fooType.IsValueType && !fooType.IsEnum;
Type type = typeof(Foo);
bool isStruct = type.IsValueType && !type.IsPrimitive;
bool isClass = type.IsClass;
Ce pourrait être encore: un type primitif ou une interface.
Edit: Il y a beaucoup de discussions sur la définition d'une structure. Une structure et un type de valeur sont en fait les mêmes, donc IsValueType
est la bonne réponse. Je devais généralement savoir si un type est un structure définie par l'utilisateur, cela signifie un type qui est implémenté en utilisant le mot clé struct
et non un type primitif. Je garde donc ma réponse pour tous ceux qui ont le même problème que moi.
Edit 2 : Selon la référence C # , les énumérations ne sont pas des structures, tandis que tout autre type de valeur l'est. Par conséquent, la bonne réponse pour déterminer si un type est une structure est:
bool isStruct = type.IsValueType && !type.IsEnum;
À mon humble avis, la définition d'une structure est plus confuse que logique. En fait, je doute que cette définition soit pertinente dans la pratique.
Méthode d'extension. Il retourne true
pour tout ce qui est défini comme struct
dans mon code mais pas pour des choses comme int
qui, bien qu'elles soient techniquement des structures, ne sont pas pour moi.
J'avais besoin de savoir quand un type peut avoir des champs ou des propriétés enfants mais était défini comme struct
et non comme class
. Parce que lorsque vous modifiez un struct
, il modifie simplement une copie, puis vous devez redéfinir l'original sur la copie modifiée pour que les modifications soient "collées".
public static bool IsStruct(this Type source)
{
return source.IsValueType && !source.IsPrimitive && !source.IsEnum;
}
Essayez ce qui suit
bool IsStruct(Type t) {
return t.IsValueType;
}
Pour chaque type de valeur, il existe un type de classe généré automatiquement qui dérive de System.ValueType
, qui dérive à son tour de System.Object
. Notez que les types de valeurs eux-mêmes ne dérivent de rien, mais sont implicitement convertible à ce type de classe et les instances de ce type de classe peuvent être explicitement converties en type de valeur.
Considérer:
public static int GetSomething <T> (T énumérateur) où T: IEnumerator <int> { T enumerator2 = énumérateur; enumerator.MoveNext (); enumerator2.MoveNext (); return enumerator2.Current; }
Appeler cette routine sur une variable de type List<int>.Enumerator
donnera un comportement très différent de l'appeler sur une variable de type IEnumerator<int>
qui se trouve avoir une instance de List<int>.Enumerator
stocké en son sein. Même si une variable de type List<int>.Enumerator
est un type de valeur, une instance de List<int>.Enumerator
stocké dans une variable de type IEnumerator<int>
se comportera comme un type de classe.