简体   繁体   English

是否有可能欺骗C#编译器来封装Nullable <T> 结构蚂蚁不是它的价值?

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

相关问题 具有与Nullable相同的编译器行为的C#自定义通用结构<T> - C# Custom generic struct with same compiler behavior as Nullable<T> 在C#中为可为空的结构的成员分配值 - Assigning value to member of nullable struct in C# 如果结构不可为空,则在 C# 中检查结构是否为空 - Check for null for struct in C# if struct isn't nullable Nullable怎么样? <T> 与类似的自定义C#结构不同? - How is Nullable<T> different from a similar custom C# struct? 正确实施 IComparable<t> 在 C# 8 中的结构上,将 Nullable 设置为启用</t> - Properly implementing IComparable<T> on a Struct in C# 8 with Nullable set to enable Roslyn c# 编译器:非托管结构被检测为可为空,但我想知道这是否是一个悖论 - Roslyn c# compiler: unmanaged struct is detected as nullable, but I wonder if it's a paradox 是否可以在C#泛型方法中定义“not Nullable <T>”约束? - Is it possible to define a “not Nullable<T>” constraint in a C# generic method? C# 编译器抛出语言版本 (LangVersion) 引用错误“无效的‘可空’值:‘Enable’ for C# 7.3” - C# compiler throws Language Version (LangVersion) reference error "Invalid 'nullable' value: 'Enable' for C# 7.3" C#编译器是否优化了可空类型? - Is the C# compiler optimizing nullable types? 是否有可能通过c#中的值获取属性 - is it possible to get a property by its value in c#
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM