[英]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.