![](/img/trans.png)
[英]C# Custom generic struct with same compiler behavior as 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.