繁体   English   中英

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

[英]Is it possible to cheat C# compiler to box Nullable<T> struct ant not its value?

嗯,问题可能看起来很奇怪。 它确实是。
然而,我坚信这些黑客有助于理解语言和.net平台。

C#编译器如何处理可空类型意味着这个问题。

Nullable<T>是一个结构。 但编译器框不是这个结构,而是它保存的值或只是空引用。

在盒装Nullable的情况下,拆箱将如何工作也很有用。

Nullable<int> myInt = boxedStruct as Nullable<int>;

在这里我认为boxedStruct不是一个盒装的int而是整个结构。

好吧,可能是在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();
    }
}

输出:

值的类型'System.Boolean'与属性'System.Nullable`1 [System.Boolean]'的类型相同 - ''False'

更新:

这里的规范(ECMA 335)说:

I.8.2.4值的装箱和拆箱
...
如果值类型是可空类型 - 定义为值类型System.Nullable的实例化 - 结果是其类型为T的Value属性的空引用或按位副本,具体取决于其HasValue属性(分别为false和true) 。

所以如果我理解正确的话。 Nulllable Nullable<T> strcut不能装入.Net Framework中,它不仅不可能用C#编译器,而且用CLR也是如此。

我猜想你要问的问题是:

你可以Nullable<int>值而不产生空引用或盒装int值,而是实际装箱的Nullable<int>吗?

没有。

有可能欺骗C#编译器来装箱Nullable<T>吗?

不,因为不是编辑谁做拳击,它是CLR。 是的,可空类型的装箱是在CLR本身中专门处理的。

那么有没有办法在没有这种特殊处理的情况下装入可以为空的结构? 也没有。

但是可以打包另一个看起来像Nullable<T> (确保它具有适当的布局),并且在未记录的关键字和内存黑客的帮助下,让CLR认为盒装对象实际上是Nullable<T>
谨防! 此代码仅用于教育目的。 我不能保证它可以在其他平台上工作或在不同条件下工作,因为它依赖于托管对象的底层布局。

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;
    }
}

所述NullableFake<T>结构具有的布局相同Nullable<T>所以它是安全的使用它的拳击。 TypedReference用于获取指向变量的指针(包含指向对象的指针),从而暴露对象本身。 对象内存布局中的第一个值是指向对象类型的指针。 覆盖它会导致CLR认为类型不同。

我不知道有任何更安全的方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM