如何以编程方式检查一个类型是结构体还是类?
获取一个值,该值指示类型是否为值类型。
可以像这样使用它:
typeof(Foo).IsValueType
或者在执行时像这样:
fooInstance.GetType().IsValueType
相反地,还有一个Type.IsClass
属性(在我看来应该称为IsReferenceType
,但无论如何),根据您要测试的内容,并不一定更合适。代码总是阅读起来没有布尔否定语句更好,所以使用任何一种可以提高代码可读性的方式。正如Stefan在下面指出的那样,为了正确地识别结构体,必须小心避免在处理枚举
时出现误报。枚举是值类型,因此对于枚举和结构体,IsValueType
属性将返回true
。
因此,如果您真的正在寻找structs
而不仅仅是通用的值类型,则需要这样做:
Type fooType = fooInstance.GetType();
Boolean isStruct = fooType.IsValueType && !fooType.IsEnum;
System.Type
中的 IsPrimitiveImpl
方法类型。没有任何阻止微软实现一个新的原始引用类型的事情。原始类型并不需要也是值类型。 - Andrew HareSystem.Int32
或者System.Double
,而是一个具有独特字节的特殊本地类型,用于指定Int32
(ELEMENT_TYPE_I4
或者0x08
)和Double
(ELEMENT_TYPE_R8
或者0x0D
)。我之所以知道这些,是因为我曾经写过一个元数据解析器。 - Allen Clark Copeland JrType type = typeof(Foo);
bool isStruct = type.IsValueType && !type.IsPrimitive;
bool isClass = type.IsClass;
它仍然可以是原始类型或接口。
编辑:有关结构体定义的讨论很多。实际上,结构体和值类型是一样的,因此IsValueType
是正确的答案。我通常需要知道一个类型是否为自定义结构,这意味着使用关键字struct
而不是原始类型来实现该类型。因此,我保留我的回答,供所有遇到同样问题的人参考。
编辑2:根据C#参考文档,枚举不是结构体,而任何其他值类型都是。因此,确定类型是否为结构体的正确答案是:
bool isStruct = type.IsValueType && !type.IsEnum;
依我之见,结构体的定义比较令人困惑而不是符合逻辑。实际上,我怀疑这种定义在实践中是否有任何相关性。
IsClass
和IsValueType
都返回false
。此外,任何实现该接口的类型都将返回其真实类型,无论该类型的引用是作为接口还是其他类型。 - Andrew Hareint
、double
和bool
,实际上都是struct
类型”。 - LukeHtype.IsValueType && !type.IsPrimitive
无法确定结构体是否是使用关键字 struct
创建的用户定义结构体。例如,它会对 decimal
、int?
或任何枚举返回错误的结果。 - thepirat000true
,但对于不属于我的用途的内容(如int
),尽管它们在技术上是结构体,但不会返回true
。struct
而不是class
。因为当您更改struct
时,它只更改了副本,然后您必须将原始内容设置回更改后的副本才能使更改“生效”。public static bool IsStruct(this Type source)
{
return source.IsValueType && !source.IsPrimitive && !source.IsEnum;
}
它是否是一种结构
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;
}
这是一个类吗?
public bool IsClass(Type LocalType)
{
bool result = false;
if (LocalType.IsClass)
{
//Is Class or Delegate
if (LocalType.GetType != typeof(Delegate))
result = true;
}
return result;
}
请尝试以下操作
bool IsStruct(Type t) {
return t.IsValueType;
}
type.IsValueType && !type.IsEnum
翻译:判断类型是否为值类型并且不是枚举类型。 - gap这个结构体:
// determine if the type is a struct..
var isStruct = type.IsValueType && !type.IsEnum &&
!type.IsEquivalentTo(typeof(decimal)) &&
!type.IsPrimitive;
这个类:
var isClass = type.IsClass;
var isClassOrStruct = isStruct | isClass;
//I think it would be something like this:
public sbyte IsStructure(Type LocalType)
{
sbyte 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;
}
System.ValueType
,而后者又派生自System.Object
。请注意,值类型本身不派生自任何东西,但可以隐式转换为该类类型,并且该类类型的实例可以显式转换为值类型。public static int GetSomething<T>(T enumerator) where T : IEnumerator<int> { T enumerator2 = enumerator; enumerator.MoveNext(); enumerator2.MoveNext(); return enumerator2.Current; }在类型为
List<int>.Enumerator
的变量上调用此例程将产生与在类型为IEnumerator<int>
的变量上调用它时非常不同的行为,后者恰好存储了List<int>.Enumerator
的实例。即使类型为List<int>.Enumerator
的变量是值类型,在类型为IEnumerator<int>
的变量中存储的List<int>.Enumerator
实例将表现为类类型。