.NET 8中Marshal.SizeOf<T>泛型重载的行为不一致问题
Marshal.SizeOf泛型重载的行为不一致问题(基于.NET 8运行时)
我发现Marshal.SizeOf<T>方法的泛型重载存在行为不一致问题,以下仅讨论泛型重载场景:
问题1:Marshal.SizeOf<T>()支持范围过窄
考虑以下代码:
using System.Collections.Generic; using System.Runtime.InteropServices; // ... int size1a = Marshal.SizeOf<KeyValuePair<int, int>>(KeyValuePair.Create(123, 456)); // 正常,返回8 int size1b = Marshal.SizeOf<KeyValuePair<int, int>>(default); // 正常,返回8 int size2 = Marshal.SizeOf<KeyValuePair<int, int>>(); // 抛出异常?!
说明:KeyValuePair<TKey, TValue>是包含两个非静态字段(类型为TKey和TValue)的struct。当TKey和TValue均为无托管字段的int时,KeyValuePair<int, int>不含引用类型成员,属于“非托管类型”。
预期:size2应能像size1a和size1b一样计算出大小(值为8)
实际:抛出ArgumentException,提示“T不能是泛型类型”
疑问:为何接收参数的重载能正常计算大小,无参重载却无法做到?
注意:自C# 7.3起,封闭类型KeyValuePair<int, int>可满足where TSomething : unmanaged泛型约束,自然预期其大小可被计算。
问题2:Marshal.SizeOf<T>(T structure)支持范围过宽
在KeyValuePair<,>中使用托管类型:
using System.Collections.Generic; using System.Runtime.InteropServices; // ... int size3 = Marshal.SizeOf<KeyValuePair<string, string>>(KeyValuePair.Create("arbitrarily long text", "can go in here"));
预期:由于该类型/实例持有托管对象引用(此处为System.String类),调用应抛出异常
实际:调用成功,返回值取决于编译平台,例如x86平台返回8(==4+4),x64平台返回16(==8+8)等
疑问:为何返回值为运行时引用宽度的两倍?
此场景在.NET Framework 4.8中表现正常:尝试计算size3会抛出指定参数异常。因此问题2是.NET 8新增的异常行为。
请问我是否应将这些问题报告为.NET的bug,还是我忽略了某些细节?
内容的提问来源于stack exchange,提问作者Jeppe Stig Nielsen
相关产品推荐
相关产品推荐

