web-dev-qa-db-fra.com

Comment vérifier par programme si un type est une structure ou une classe?

Comment vérifier par programme si un type est une structure ou une classe?

44
Jader Dias

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;
74
Andrew Hare
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.

28
Stefan Steinegger

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;
}
5
toddmo

Essayez ce qui suit

bool IsStruct(Type t) {
  return t.IsValueType;
}
1
JaredPar

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.

0
supercat