检查对象是否为值类型的最有效方法

时间:2011-04-21 19:11:35

标签: c# .net performance value-type

警告:此代码告知,请参阅安东尼的评论

哪个更快?

1

  public bool IsValueType<T>(T obj){
       return obj is ValueType;
  }

2

  public bool IsValueType<T>(T obj){
       return obj == null ? false : obj.GetType().IsValueType;
  } 

3

  public bool IsValueType<T>(T obj){
       return default(T) != null;
  }

4.其他

6 个答案:

答案 0 :(得分:88)

您并未真正测试对象 - 您想测试类型。要调用它们,调用者必须知道类型,但是...... meh。鉴于签名<T>(T obj),唯一合理的答案是:

public bool IsValueType<T>() {
    return typeof(T).IsValueType;
}

或者如果我们想使用示例对象进行类型推断:

public bool IsValueType<T>(T obj) {
    return typeof(T).IsValueType;
}

这不需要拳击(GetType()是拳击),并且Nullable<T>没有问题。一个更有趣的案例是你通过object ...

 public bool IsValueType(object obj);

在这里,我们已经遇到null的大量问题,因为那可能是一个空的Nullable<T>(一个结构)或一个类。但合理的尝试将是:

public bool IsValueType(object obj) {
    return obj != null && obj.GetType().IsValueType;
}

但请注意,对于空Nullable<T> s它是不正确的(并且不可修复)。在这里担心拳击变得毫无意义,因为我们已经装箱了。

答案 1 :(得分:7)

我的第一个答案是编写一个简单的测试并自行查找。

我的第二个答案(当然没有任何测试)将是选项1 。这是最简单的检查。第二种方法涉及两个单独的检查,而第三种方法涉及创建类型的默认实例。

您还应该考虑可读性。该框架已经使您能够在代码中包含以下内容:

if(someObj is ValueType)
{
    // Do some work
}

为什么甚至打扰创建一个简单地将上述语句转换为的方法(假设您使方法成为静态并允许编译器推断泛型类型):

if(IsValueType(someObj))
{
    // Do some work
}

答案 2 :(得分:3)

定义结构实际上定义了两种类型:值类型和从System.ValueType派生的类类型。如果请求创建从System.ValueType派生的类型的变量,参数,字段或数组(统称为&#39;存储位置&#39;),系统将创建一个存储位置,该存储位置将存储对象的字段,而不是存储对这些字段出现的对象的引用。另一方面,如果请求创建从System.ValueType派生的类型的实例,则系统将创建从System.ValueType派生的类的对象实例。

这可以通过创建实现IValue的结构来证明:

interface IValue {int value {get; set;}};
struct ValueStruct : IValue
{
  public int value {get; set;}};
}

使用通用测试例程和代码来包装它:

static void Test<T>(T it) where T:IValue
{
  T duplicate = it;
  it.value += 1;
  duplicate.value += 10;
  Console.WriteLine(it.value.ToString());
}
static void Test()
{
  ValueStruct v1 = new ValueStruct();
  v1.value = 9;
  IValue v2 = v1;
  Test<ValueStruct>(v1); 
  Test<ValueStruct>(v1); 
  Test<IValue>(v1); 
  Test<IValue>(v1); 
  Test<IValue>(v2);
  Test<IValue>(v2);
}

请注意,在每种情况下,在传递给Test的参数上调用GetType都会产生ValueStruct,它会将自身报告为值类型。尽管如此,传入的项目只是一个真实的&#34;前两个调用的值类型。在第三次和第四次调用时,它实际上是一个类类型,事实证明对duplicate的更改会影响it。在第五次和第六次通话时,更改将传播回v2,因此第二次通话将&#34;见&#34;它

答案 3 :(得分:2)

static class Metadata<T>
{
    static public readonly Type Type = typeof(T);
    static public readonly bool IsValueType = Metadata<T>.Type.IsValueType;
}

//fast test if T is ValueType
if(Metadata<T>.IsValueType) //only read static readonly field!
{
    //...
}

答案 4 :(得分:0)

有两条规则:

1-All Classes是引用类型,例如Object和String,因此.NET Framework 支持它。

2 - 所有结构都是类型,例如bool和char,即使它包含引用成员,因此它受.NET Framework 结构支持。

只需右键单击任何类型和转到定义如果它是一个类,那么这意味着它是一个引用类型,如果它是一个Struct,那么这意味着它是一个值类型:)

答案 5 :(得分:-1)

你可以使用

obj.GetType().IsValueType

这使用反射但清晰的方式而不是装箱拆箱。