繁体   English   中英

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

[英]Most efficient way to check if an object is a 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.别的

您并不是真的在测试对象 - 您想要测试类型 要调用这些,调用者必须知道类型,但是……嗯。 给定签名<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>是不正确的(并且无法修复)。 在这里担心拳击变得毫无意义,因为我们已经被拳击了。

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

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

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

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

为什么还要创建一个方法来简单地将上述语句转换为(假设您将方法设为静态并允许编译器推断泛型类型):

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

定义结构实际上定义了两种类型:值类型和派生自System.ValueType的类类型。 如果请求创建派生自 System.ValueType 的类型的变量、参数、字段或数组(统称为“存储位置”),系统将改为创建一个存储位置,用于存储对象的字段而不是存储对出现这些字段的对象的引用。 另一方面,如果请求创建派生自 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,它将自身报告为值类型。 尽管如此,传入的项目在前两次调用中只会是“真实”值类型。 在第三次和第四次调用中,它确实是一个类类型,正如对duplicate的更改会影响it的事实所证明的那样。 在第五次和第六次调用中,更改将传播回 v2,因此第二次调用将“看到”它。

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!
{
    //...
}

有两个规则:

1-所有类都是Object和String等引用类型,所以.NET Framework类都支持。

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

只需右键单击任何类型并转到定义,如果它是类,则意味着它是引用类型,否则,如果它是结构,则意味着它是值类型:)

您可以使用

obj.GetType().IsValueType

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM