How to check programmatically if a type is a struct or a class?
Solution 1
Use Type.IsValueType
:
Gets a value indicating whether the Type is a value type.
Use it either like this:
typeof(Foo).IsValueType
or at execution time like this:
fooInstance.GetType().IsValueType
Conversely there is also a Type.IsClass
property (which should have been called IsReferenceType
in my opinion but no matter) which may or may not be more appropriate for your uses based on what you are testing for.
Code always seems to read better without boolean negations, so use whichever helps the readability of your code.
As Stefan points out below, in order to properly identify structs you must be careful to avoid false positives when it comes to enums
. An enum
is a value type so the IsValueType
property will return true
for enums
as well as structs
.
So if you truly are looking for structs
and not just value types in general you will need to do this:
Type fooType = fooInstance.GetType();
Boolean isStruct = fooType.IsValueType && !fooType.IsEnum;
Solution 2
Type type = typeof(Foo);
bool isStruct = type.IsValueType && !type.IsPrimitive;
bool isClass = type.IsClass;
It could still be: a primitive type or an interface.
Edit: There is a lot of discussion about the definition of a struct. A struct and a value type are actually the same, so IsValueType
is the correct answer. I usually had to know whether a type is a user defined struct, this means a type which is implemented using the keyword struct
and not a primitive type. So I keep my answer for everyone who has the same problem then me.
Edit 2: According to the C# Reference, enums are not structs, while any other value type is. Therefore, the correct answer how to determine if a type is a struct is:
bool isStruct = type.IsValueType && !type.IsEnum;
IMHO, the definition of a struct is more confusing then logical. I actually doubt that this definition is of any relevance in praxis.
Solution 3
Extension method. It returns true
for anything defined as a struct
in my code but not for things like int
which although they are technically structs are not for my purposes.
I needed to know when a type may have child fields or properties but was defined as a struct
and not a class
. Because when you alter a struct
it just alters a copy, and then you have to set the original back to the altered copy to make the changes "stick".
public static bool IsStruct(this Type source)
{
return source.IsValueType && !source.IsPrimitive && !source.IsEnum;
}
Solution 4
I think it would be something like this:
Is it a structure
public bool IsStructure(Type LocalType)
{
bool result = false;
if (LocalType.IsValueType)
{
//Is Value Type
if (!LocalType.IsPrimitive)
{
/* Is not primitive. Remember that primitives are:
Boolean, Byte, SByte, Int16, UInt16, Int32, UInt32,
Int64, UInt64, IntPtr, UIntPtr, Char, Double, Single.
This way, could still be Decimal, Date or Enum. */
if (!LocalType == typeof(decimal))
{
//Is not Decimal
if (!LocalType == typeof(DateTime))
{
//Is not Date
if (!LocalType.IsEnum)
{
//Is not Enum. Consequently it is a structure.
result = true;
}
}
}
}
}
return result;
}
Is it a Class
public bool IsClass(Type LocalType)
{
bool result = false;
if (LocalType.IsClass)
{
//Is Class or Delegate
if (LocalType.GetType != typeof(Delegate))
result = true;
}
return result;
}
Solution 5
Try the following
bool IsStruct(Type t) {
return t.IsValueType;
}
Comments
-
Jader Dias almost 2 years
How to check programmatically if a type is a struct or a class?
-
Stefan Steinegger over 14 yearsA primitive type is also a value type.
-
Andrew Hare over 14 years@Stephan - It is true that all C# primitives happen to be value types but that does not mean that all value types are therefore C# primitives.
System.Guid
andSystem.DateTime
are both value types but are not language primitives. -
Stefan Steinegger over 14 years@Andrew: yes, Guid and DateTime are structs. See my answer.
-
Andrew Hare over 14 years@Stephan - You lost me. Are you saying that there is a difference between structs and value types?
-
Andrew Hare over 14 yearsStructs are simply one way that C# allows you to create value types in the resulting IL, enums are another way.
-
Stefan Steinegger over 14 years@Andrew: Structs are one kind of value types. Primitive types are another. So structs are value type, but value types not structs. (A bird is an animal, an animal is not a bird)
-
Andrew Hare over 14 years@Stephan - So would you consider
System.Int32
a value type, a struct, or a primitive? -
Stefan Steinegger over 14 years@Andrew: int is a primitive type, which is a special case of a value type.
-
Andrew Hare over 14 yearsTo expand my point, the term "primitive" is special and really only is reserve for certain types that have overridden the
IsPrimitiveImpl
method fromSystem.Type
. There is nothing stopping Microsoft from implementing a new primitive that happens to be a reference type. There is nothing about a primitive that necessitates that it must also be a value type. -
Andrew Hare over 14 yearsThe fact that all primitive types in mscorlib happen to be value types is either a design decision or a coincidence. Since the
IsPrimitiveImpl
method is defined inSystem.Type
it can freely be implemented by a reference type as well. Only if this method were implemented onSystem.ValueType
would you be able to say that all primitive types must be value types. The fact that all primitive types that are currently defined are value types is simply a coincidence. -
Andrew Hare over 14 yearsThe primitive type thing has been discussed to death in the comments of my answer :) You don't have to worry about an interface because and interface type instance will return
false
for bothIsClass
andIsValueType
. Also any type that implements the interface will return its true type regardless of what the reference to the type is typed as an interface or not. -
LukeH over 14 years@Stefan: Are you saying that primitive types are precluded from being structs? If so, you're incorrect. For example, section 11 of the C# spec says "the simple types provided by C#, such as
int
,double
, andbool
, are in fact allstruct
types". -
Stefan Steinegger over 14 years@Luke: Yes, this is indeed the definition of primitive types. I always had to know if a type is a user defined struct, excluding primitive types, which is normally simply referenced to as "struct". But you are right, strictly speaking primitive types are also structs.
-
Stefan Steinegger over 14 years@Andrew: I see, primitive types are actually defined as special case of structs, so I'm wrong. I added a note to my answer. I apologize for the troubles.
-
Andrew Hare over 14 years@Stephan - No trouble at all! A lively debate is good for everyone :)
-
Stefan Steinegger over 14 yearsFunny enough, in the C# reference here msdn.microsoft.com/en-us/library/s1ax56ch.aspx an enum is actually not defined as a struct. Quote: "The value types consist of two main categories: structs, enumerations". While "numeric types" are defined as structs. Doesn't sound logical.
-
Andrew Hare over 14 yearsCorrect, enums and structs are the two value types that C# supports. A helpful way to remember this is that a struct is a kind of value type, not the other way around.
-
Stefan Steinegger over 14 yearsSo the correct answer to the question here should be:
type.IsValueType && !type.IsEnum
-
Andrew Hare over 14 years@Stefan - Excellent point! The OP does ask specifically about structs, not value types - I will edit my answer.
-
supercat about 12 yearsCalling
GetType()
on a storage location will not reliably report whether the location holds a value type or a reference to a class-type instance. A boxed value type is actually a class-type object with the same fields and methods as its value-type namesake. If one has a field of typeIEnumerable<int>
which holds an instance of the structList<int>.Enumerator
, callingGetType().IsValueType
on that field will return true, even though the object referred to by the field will behave like a class-type instance (under the covers it will actually be one). -
gap over 11 yearsSee answer from @Stefan:
type.IsValueType && !type.IsEnum
-
nawfal about 11 yearsHow is this answering the question?
-
Allen Clark Copeland Jr over 8 yearsI might add, within the metadata, the Primitive concept is special because the actual metadata defining the use of those primitive types, in every way, and their interpretation is special. Primitive types aren't outlined in metadata as
System.Int32
, orSystem.Double
, but rather a special native type with unique bytes that specifyInt32
(ELEMENT_TYPE_I4
or0x08
) andDouble
(ELEMENT_TYPE_R8
or0x0D
.) I only know because I've had to write a metadata parser. -
Nick Sotiros about 6 yearsI need to serialize some data and this method does not work as it thinks a float is a struct. I need to recursively serialize structs down to their primitives but some structs can have other structs as fields.
-
thepirat000 about 6 years
type.IsValueType && !type.IsPrimitive
will not determine if the struct is a user-defined struct created using the keywordstruct
. It will return false positives for example fordecimal
,int?
, or any enum. -
Stefan Steinegger about 6 years@thepirat000: Yes. There is no concept of "user-defined struct" in C#. Decimals and nullables are structs like any other. Of course you can exclude them explicitly, if it makes sense. There is a related (but different!) question with a better answer here: stackoverflow.com/questions/863881/…
-
Panu Oksala almost 4 yearsDecimal is valuetype and not primitive (and not enum).
-
Peter Csala almost 4 yearsPlease provide some explanation.