2010-02-19 3 views
15

Pour un Type, il existe une propriété IsClass en C#, mais comment décider un Type est une structure?Comment décider qu'un Type est une structure personnalisée?

Bien que IsValueType soit une condition nécessaire, elle n'est évidemment pas suffisante. Pour un int est également un type de valeur.

Quelqu'un suggère le code suivant:

bool IsStruct = type.IsValueType && !type.IsEnum && !type.IsPrimitive; 

Mais je ne suis pas sûr que ce soit une méthode précise. La formule devrait indiquer la différence entre struct et d'autres types tels que DateTime, int et array s.

Comme certains amis ont souligné que, ici, je veux dire struct défini par l'utilisateur et non prédéfinis types, tels que DateTime.

+2

Je ne suis pas sûr de comprendre la question. Un DateTime ** est ** une structure. Pourquoi retourneriez-vous faux là-bas? –

+3

Actuellement, int est également un type struct. La spécification de langage stipule que "C# fournit un ensemble de types de structures prédéfinis appelés les types simples". –

+2

Il serait intéressant de savoir pourquoi vous vous en souciez. Qu'est-ce que tu fais? Il pourrait y avoir une meilleure façon de faire ce que vous voulez. –

Répondre

8

Techniquement, un int est aussi une structure. IsPrimitive vérifie simplement si le type est l'un des types primitifs que le CLR gère un peu différemment. Vous devriez être bien avec la suggestion IsValueType && !IsEnum && !IsPrimitive. Si vous ne voulez que des structures personnalisées (ie non fournies par la BCL), vous pouvez avoir de la chance en excluant les types avec un FullName qui commence par "System.", ou en incluant seulement ceux qui vous intéressent en filtrant par assembly ou espace de noms ou utilisez un attribut personnalisé.

+2

+1 Ou '' Microsoft. "' Ou '" FSharp. "' Ou. . . Je pense qu'il aura du mal à les éliminer tous. –

2

doit être au moins

bool isStruct = type.IsValueType && !type.IsEnum && 
       !type.IsPrimitive && type != typeof(decimal); 
0

Vous allez avoir un moment difficile avec cela. Le Framework de base ne sait pas quels sont tous les types prédéfinis dans d'autres parties du Framework. Il est déraisonnable de s'attendre à ce que le Core Framework connaisse par exemple System.Drawing.Point.

OregonGhost a probablement le meilleur answer: obtenir l'information de type et vérifier la propriété FullName pour voir si elle commence par "System.". Mais vous devrez également vérifier "Microsoft." et "FSharp", et peut-être d'autres. Cliquez simplement sur "Ajouter une référence" dans Visual Studio, et voyez quels noms apparaissent.

Et puis vous risquez de trop bloquer. Microsoft distribue certains assemblages via des packages NuGet, et les types de ces assemblys ont souvent des noms commençant par "System." ou "Microsoft." Considérez-vous ces types "intégrés" même s'ils ne sont pas distribués avec le Framework?

1

http://msdn.microsoft.com/en-us/library/bfft1t3c.aspx dit: IsValueType est vrai si le type est dans {bool, byte, char, décimal, double, ENUM, flotteur, int, long, sbyte, bref, struct, uint, ulong, ushort}.

http://msdn.microsoft.com/en-us/library/system.type.isprimitive%28v=vs.110%29.aspx dit: IsPrimitive est vrai si le type est dans {Boolean, Byte, SByte, Int16, UInt16, Int32, UInt32, Int64, UInt64, IntPtr, UIntPtr, Char, Double et simple}.

Que pour IsStruct vous pouvez utiliser la méthode comme ceci:

public static bool IsStruct(this Type type) 
{ 
    return type.IsValueType 
      && !type.IsPrimitive 
      && !type.IsEnum 
      && type != typeof(decimal); 
} 
0

Il a travaillé pour moi x.PropertyType.IsSecurityTransparent & & x!.PropertyType.IsClass

0

pas une solution parfaite, mais vous pouvez toujours limiter la recherche par types connus dans les assemblées que vous souhaitez chercher:

System.Reflection.Assembly.GetAssembly(tyepof(OneOfMyTypes)) 
    .GetExportedTypes() 
    .Where(t => t.IsValueType); 

L'aide à éliminer les faux positifs (? Plus sûr), mais il est moins portable.