警告:此代码告知,请参阅安东尼的评论
哪个更快?
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.其他
答案 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
这使用反射但清晰的方式而不是装箱拆箱。