检查对象是否为值类型的最有效方法
本文关键字:有效 方法 类型 对象 是否 检查 | 更新日期: 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。
用泛型测试例程和代码包装它:
<>之前Test注意,在每种情况下,对传递给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
这使用了反射,但以一种清晰的方式代替了装箱和拆箱。