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

本文关键字:有效 方法 类型 对象 是否 检查 | 更新日期: 2023-09-27 17:52:34

警告:这段代码烂透了,请看安东尼的评论

哪个更快?

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> s,它是不正确的(并且不可修复)。在这里,不必担心装箱问题,因为我们已经被装箱了。

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

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

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

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

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

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

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

这可以通过创建一个实现IValue的结构体来演示: <>之前接口IValue {int值{get;设置;}};struct ValueStruct: IValue{Public int value {get;设置;}};}之前

用泛型测试例程和代码包装它:

<>之前Test(T it) where T:IValue{T duplicate = it;它。Value += 1;复制。值+= 10;Console.WriteLine (it.value.ToString ());}静态void测试(){ValueStruct v1 = new ValueStruct();v1。值= 9;IValue v2 = v1;Test (v1);Test (v1);Test (v1);Test (v1);Test (v2);Test (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

这使用了反射,但以一种清晰的方式代替了装箱和拆箱。