【问题标题】:How to check programmatically if a type is a struct or a class?如何以编程方式检查类型是结构还是类?
【发布时间】:2010-12-22 02:17:55
【问题描述】:

如何以编程方式检查类型是结构还是类?

【问题讨论】:

标签: c# .net class struct types


【解决方案1】:

使用Type.IsValueType:

获取一个值,指示Type是否为值类型。

像这样使用它:

typeof(Foo).IsValueType

或在执行时像这样:

fooInstance.GetType().IsValueType

相反,还有一个Type.IsClass 属性(在我看来应该称为IsReferenceType,但不管怎样),根据您的测试内容,它可能更适合您的用途,也可能不适合。

如果没有布尔否定,代码似乎总能更好地阅读,因此请使用有助于代码可读性的任何一种。


正如 Stefan 在下面指出的那样,为了正确识别 structs,当涉及到 enums 时,您必须小心避免误报。 enum 是一种值类型,因此 IsValueType 属性将为 enumsstructs 返回 true

因此,如果您真的在寻找 structs 而不仅仅是一般的值类型,您将需要这样做:

Type fooType = fooInstance.GetType();
Boolean isStruct = fooType.IsValueType && !fooType.IsEnum;

【讨论】:

  • 原始类型也是值类型。
  • @Stephan - 确实所有 C# 原语都是值类型,但这并不意味着所有值类型都是 C# 原语。 System.GuidSystem.DateTime 都是值类型,但不是语言原语。
  • 为了扩展我的观点,术语“原始”是特殊的,实际上只保留用于覆盖System.Type 中的IsPrimitiveImpl 方法的某些类型。没有什么能阻止 Microsoft 实现一个恰好是引用类型的新原语。原语并没有要求它也必须是值类型。
  • @Andrew:我明白了,原始类型实际上被定义为结构的特殊情况,所以我错了。我在答案中添加了注释。对于给您带来的麻烦,我深表歉意。
  • 正确,枚举和结构是 C# 支持的两种值类型。记住这一点的一个有用方法是结构是一种值类型,而不是相反。
【解决方案2】:
Type type = typeof(Foo);

bool isStruct = type.IsValueType && !type.IsPrimitive;
bool isClass = type.IsClass;

它仍然可以是:原始类型或接口。


编辑:关于结构的定义有很多讨论。结构体和值类型实际上是相同的,所以IsValueType 是正确答案。我通常必须知道一个类型是否是用户定义的结构,这意味着使用关键字struct 实现的类型而不是原始类型。所以我为所有和我有同样问题的人保留我的答案。


编辑 2:根据C# Reference,枚举不是结构,而任何其他值类型都是。因此,如何判断一个类型是否为结构体的正确答案是:

bool isStruct = type.IsValueType && !type.IsEnum;

恕我直言,结构的定义比逻辑更混乱。我实际上怀疑这个定义在实践中是否具有任何相关性。

【讨论】:

  • 原始类型的事情已经在我的回答的 cmets 中被讨论死了 :) 你不必担心接口,因为接口类型实例将为 IsClass 返回 falseIsValueType。此外,任何实现该接口的类型都将返回其真实类型,而不管对该类型的引用是否被键入为接口。
  • @Stefan:你是说原始类型被排除在结构之外吗?如果是这样,那你就错了。例如,C# 规范第 11 节说“C# 提供的简单类型,例如 intdoublebool,实际上都是 struct 类型”。
  • @Luke:是的,这确实是原始类型的定义。我总是必须知道一个类型是否是用户定义的结构,不包括原始类型,通常简单地称为“结构”。但你是对的,严格来说原始类型也是结构体。
  • type.IsValueType && !type.IsPrimitive 不会确定该结构是否是使用关键字 struct 创建的用户定义结构。它将返回误报,例如 decimalint? 或任何枚举。
  • @thepirat000:是的。 C# 中没有“用户定义的结构”的概念。小数和可空值是和其他结构一样的结构。当然,如果有意义的话,您可以明确排除它们。这里有一个相关的(但不同的!)问题有更好的答案:stackoverflow.com/questions/863881/…
【解决方案3】:

扩展方法。对于在我的代码中定义为struct 的任何内容,它都会返回true,但不会为int 这样的东西返回,尽管它们在技术上是不符合我的目的的结构。

我需要知道一个类型何时可能有子字段或属性,但被定义为struct 而不是class。因为当您更改 struct 时,它只会更改副本,然后您必须将原件设置回更改后的副本以使更改“生效”。

public static bool IsStruct(this Type source) 
{
  return source.IsValueType && !source.IsPrimitive && !source.IsEnum;
}

【讨论】:

  • 十进制是值类型而不是原始类型(也不是枚举)。
【解决方案4】:

我想应该是这样的:

是结构吗

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

【讨论】:

  • 请提供一些解释。
【解决方案5】:

试试下面的

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

【讨论】:

  • 查看@Stefan 的回答:type.IsValueType && !type.IsEnum
【解决方案6】:

对于每个值类型,都有一个对应的自动生成的类类型,它派生自 System.ValueType,而后者又派生自 System.Object。请注意,值类型本身不派生自任何东西,但可以隐式转换到该类类型,并且该类类型的实例可以显式转换为值类型。

考虑:

public static int GetSomething(T enumerator) where T : IEnumerator { T enumerator2 = 枚举器; 枚举器.MoveNext(); enumerator2.MoveNext(); 返回 enumerator2.Current; }

List<int>.Enumerator 类型的变量上调用此例程将产生与在IEnumerator<int> 类型的变量上调用它非常不同的行为,IEnumerator<int> 恰好存储了List<int>.Enumerator 的实例。尽管List<int>.Enumerator 类型的变量是值类型,但存储在IEnumerator<int> 类型变量中的List<int>.Enumerator 实例将表现为类类型。

【讨论】:

  • 这是如何回答问题的?
【解决方案7】:

结构:

// 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;

【讨论】:

    【解决方案8】:
        //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;
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-02-14
      • 2014-07-09
      • 1970-01-01
      • 1970-01-01
      • 2012-03-17
      • 1970-01-01
      相关资源
      最近更新 更多