以下各项的目的、结果和/或性能(在所有类型中(是否有任何差异:
Marshal.SizeOf(typeof(T))
和
Marshal.SizeOf(default(T))
?
第一种方法采用类型,第二种方法采用实例。它们都返回关联结构的大小。
后一种方法调用前一种方法。这由 coreclr 中的源代码备份:
public static int SizeOf(Object structure)
{
if (structure == null)
throw new ArgumentNullException(nameof(structure));
// we never had a check for generics here
Contract.EndContractBlock();
return SizeOfHelper(structure.GetType(), true);
}
public static int SizeOf(Type t)
{
if (t == null)
throw new ArgumentNullException(nameof(t));
if (!(t is RuntimeType))
throw new ArgumentException(SR.Argument_MustBeRuntimeType, nameof(t));
if (t.IsGenericType)
throw new ArgumentException(SR.Argument_NeedNonGenericType, nameof(t));
Contract.EndContractBlock();
return SizeOfHelper(t, true);
}
一个重要的区别是,当使用引用类型时,其中一个调用将引发另一个调用不会的异常:
这将成功:
Marshal.SizeOf(typeof(AReferenceType))
这将错误(null 传递给方法(
Marshal.SizeOf(default(AReferenceType))
注意引用类型:Marshal.SizeOf
ArgumentNullException 结构参数为空。
对于引用类型,default(T)
将是null
,所以这不是一个好主意。
在第一次调用中,传递类型为 Type 的实例,该实例是引用类型。 其大小将始终与所有引用类型的大小相同。
但是,在第二次调用中,传递一个值,该值可以是: 1. 引用类型,大小与第一次调用中的大小相同。 2.值类型,现在这可能会有所不同。 例如。大小(默认值(字节(( 将返回 1, .SizeOf(default(int(( 将返回 4, .SizeOf(default(long(( 将返回 8。
区别与Marshal.SizeOf(typeof(int))
、Marshal.SizeOf<int>()
和Marshal.SizeOf(0)
之间的区别相同。
在内部,它们都做同样的事情:
Marshal.SizeOf(object structure)
在运行时获取对象的类型:Marshal.SizeOfHelper(structure.GetType(), true)
Marshal.SizeOf(Type t)
只是调用具有已知类型的相同方法:Marshal.SizeOfHelper(t, true)
Marshal.SizeOf<T>()
调用上一个重载:Marshal.SizeOfHelper(typeof(T))
至于我,只要在编译时知道类型或泛型,我更喜欢通用版本;Type
运行时已知类型时重载;并且object
当您有一个对象而不是一个类型时,重载。看起来这就是每种方法的设计目的。
此外,Marshal.SizeOf(default(T((' 使其目的不太清晰和可读。