[英]Is it possible to cheat C# compiler to box Nullable<T> struct ant not its value?
Well, the question may seem odd. 嗯,问题可能看起来很奇怪。 And it really is.
它确实是。
Yet I strongly believe that such hacks help in understanding the language and .net platform. 然而,我坚信这些黑客有助于理解语言和.net平台。
It is how C# compiler treats nullable types implies this question. C#编译器如何处理可空类型意味着这个问题。
Nullable<T>
is a struct. Nullable<T>
是一个结构。 But compiler boxes not this struct but the value it holds or just null reference. 但编译器框不是这个结构,而是它保存的值或只是空引用。
It is also intersting how unboxing will work in the case of the boxed Nullable. 在盒装Nullable的情况下,拆箱将如何工作也很有用。
Nullable<int> myInt = boxedStruct as Nullable<int>;
here I meen that boxedStruct
is not a boxed int but the whole struct. 在这里我认为
boxedStruct
不是一个盒装的int而是整个结构。
Well, may be Nullables are treated differently at CLR level because I cannot understand the ouptut of the program below. 好吧,可能是在CLR级别对Nullables的处理方式不同,因为我无法理解下面程序的ouptut。
class Program
{
public static bool? Property { get; set; }
static void Main(string[] args)
{
Property = true;
var valueType = typeof (Program).GetProperty("Property").GetValue(null).GetType();
var propType = typeof (Program).GetProperty("Property").PropertyType;
Console.WriteLine("Value's type '{0}' is the same as type of the property '{1}' - '{2}'", valueType, propType, valueType == propType);
Console.ReadKey();
}
}
The output: 输出:
Value's type 'System.Boolean' is the same as type of the property 'System.Nullable`1[System.Boolean]' - 'False'
值的类型'System.Boolean'与属性'System.Nullable`1 [System.Boolean]'的类型相同 - ''False'
Update: 更新:
Here what specification (ECMA 335) says: 这里的规范(ECMA 335)说:
I.8.2.4 Boxing and unboxing of values
I.8.2.4值的装箱和拆箱
......
If the value type is a nullable type—defined as an instantiation of the value type System.Nullable—the result is a null reference or bitwise copy of its Value property of type T, depending on its HasValue property (false and true, respectively).如果值类型是可空类型 - 定义为值类型System.Nullable的实例化 - 结果是其类型为T的Value属性的空引用或按位副本,具体取决于其HasValue属性(分别为false和true) 。
So if I understand this correctly. 所以如果我理解正确的话。
Nullable<T>
strcut cannot be boxed in .Net Framework and it's not just impossible with C# compiler but with CLR as well. Nulllable
Nullable<T>
strcut不能装入.Net Framework中,它不仅不可能用C#编译器,而且用CLR也是如此。
I am conjecturing that the question you are trying to ask is: 我猜想你要问的问题是:
Can you box a
Nullable<int>
value without producing a null reference or a boxed int value, but instead an actually boxedNullable<int>
?你可以
Nullable<int>
值而不产生空引用或盒装int值,而是实际装箱的Nullable<int>
吗?
No. 没有。
Is it possible to cheat C# compiler to box
Nullable<T>
?有可能欺骗C#编译器来装箱
Nullable<T>
吗?
No, as it is not the compiler who does the boxing, it is the CLR. 不,因为不是编辑谁做拳击,它是CLR。 Yes, the boxing of nullable types is specifically handled in the CLR itself.
是的,可空类型的装箱是在CLR本身中专门处理的。
So is there a way to box a nullable struct without this special handling? 那么有没有办法在没有这种特殊处理的情况下装入可以为空的结构? Also no.
也没有。
But it is possible to box another structure that looks like Nullable<T>
(ensuring it has the appropriate layout) and with the help of undocumented keywords and memory hacking trick the CLR into thinking the boxed object is actually of Nullable<T>
. 但是可以打包另一个看起来像
Nullable<T>
(确保它具有适当的布局),并且在未记录的关键字和内存黑客的帮助下,让CLR认为盒装对象实际上是Nullable<T>
。
Beware! 谨防! This code should be used only for educational purposes.
此代码仅用于教育目的。 I can't guarantee it will work on other platforms or work at all in different conditions, because it relies on the underlying layout of managed objects.
我不能保证它可以在其他平台上工作或在不同条件下工作,因为它依赖于托管对象的底层布局。
public static unsafe object BoxNullable<T>(T? nullable) where T : struct
{
object scam = new NullableFake<T>(nullable);
TypedReference tr = __makeref(scam);
IntPtr typehandle = typeof(Nullable<T>).TypeHandle.Value;
IntPtr* trstruct = (IntPtr*)&tr;
**((IntPtr**)trstruct[0]) = typehandle;
return scam;
}
struct NullableFake<T> where T : struct
{
public readonly T? Value;
public NullableContainer(T? nullable)
{
Value = nullable;
}
}
The NullableFake<T>
structure has the same layout as Nullable<T>
, so it is safe to use it for boxing. 所述
NullableFake<T>
结构具有的布局相同Nullable<T>
所以它是安全的使用它的拳击。 TypedReference
is used for obtaining a pointer to the variable (that contains a pointer to the object), exposing the object itself. TypedReference
用于获取指向变量的指针(包含指向对象的指针),从而暴露对象本身。 The first value in the object's memory layout is a pointer to the object's type. 对象内存布局中的第一个值是指向对象类型的指针。 Overwriting it results in the CLR thinking the type is different.
覆盖它会导致CLR认为类型不同。
I don't know any safer way to do it. 我不知道有任何更安全的方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.