是否有可能欺骗C#编译器使其框为Nullable<;T>;struct ant不是它的值吗?

是否有可能欺骗C#编译器使其框为Nullable<;T>;struct ant不是它的值吗?,c#,nullable,C#,Nullable,嗯,这个问题可能看起来很奇怪。确实如此。 然而,我坚信这样的黑客行为有助于理解语言和.net平台 这就是C#编译器处理可空类型的方式暗示了这个问题。 Nullable是一个结构。但是编译器不会选择此结构,而是选择它所包含的值,或者只选择空引用。 在装箱可空的情况下,拆箱将如何工作也很有趣 Nullable<int> myInt = boxedStruct as Nullable<int>; 输出: 值的类型“System.Boolean”与属性的类型相同 'System

嗯,这个问题可能看起来很奇怪。确实如此。
然而,我坚信这样的黑客行为有助于理解语言和.net平台

这就是C#编译器处理可空类型的方式暗示了这个问题。

Nullable
是一个结构。但是编译器不会选择此结构,而是选择它所包含的值,或者只选择空引用。

在装箱可空的情况下,拆箱将如何工作也很有趣

Nullable<int> myInt = boxedStruct as Nullable<int>;
输出:

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

更新:

以下是规范(ECMA 335)所述内容:

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


如果我理解正确的话
Nullable
struct不能在.Net Framework中装箱,这不仅在C#编译器中是不可能的,而且在CLR中也是不可能的。

我猜想您想问的问题是:

您是否可以在不生成空引用或已装箱的int值的情况下装箱一个
Nullable
值,而是实际装箱的
Nullable

没有

有没有可能欺骗C#编译器将其设置为box
Nullable

不,因为装箱的不是编译器,而是CLR。是的,可空类型的装箱是在CLR本身中专门处理的

那么,有没有一种方法可以在没有这种特殊处理的情况下装箱一个可为null的结构?也没有

但是,可以装箱另一个看起来像
Nullable
(确保其具有适当的布局)的结构,并且借助未记录的关键字和内存黑客技巧,CLR会认为装箱的对象实际上是
Nullable

小心此代码应仅用于教育目的。我不能保证它能在其他平台上工作,或者在不同的条件下工作,因为它依赖于托管对象的底层布局

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;
    }
}
公共静态不安全对象BoxNullable(T?nullable),其中T:struct
{
对象诈骗=新的NullableFake(nullable);
类型引用tr=\u makeref(scam);
IntPtr typehandle=typeof(可为空).typehandle.Value;
IntPtr*trstruct=(IntPtr*)&tr;
**((IntPtr**)trstruct[0])=typehandle;
退货骗局;
}
结构NullableFake,其中T:struct
{
公共只读T值;
公共可空容器(T?可空)
{
值=可为空;
}
}
nullablefeake
结构与
Nullable
具有相同的布局,因此可以安全地将其用于装箱
TypedReference
用于获取指向变量(包含指向对象的指针)的指针,从而公开对象本身。对象内存布局中的第一个值是指向对象类型的指针。覆盖它会导致CLR认为类型不同


我不知道更安全的方法。

你能更具体一点吗?我真的不明白你在干什么。你应该在你的问题中举个例子让它更清楚。@X.L.Ant,是的,我更新了这个问题。通过C代码,我非常怀疑。最有可能的情况是直接编写IL代码。@EricLippert“你能在不转换成装箱的
null
值或装箱的
int
值的情况下,将
null
值装箱吗?”是的。嗯,我认为我应该更好地学习英语来表达不那么模糊的想法。我认为OP想要一个类型为
object{int?}
的实例。它似乎是从
int?
隐式转换为
int
的。因此需要作弊。
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;
    }
}