为什么TypedReference在幕后
我發現的其他用途TypedReference:
C#中的“專門化”泛型(這是類型安全的):
static void foo<T>(ref T value) {//This is the ONLY way to treat value as int, without boxing/unboxing objectsif (value is int){ __refvalue(__makeref(value), int) = 1; }else { value = default(T); } }誤用時不安全,但正確使用時快速和安全:
//This bypasses the restriction that you can't have a pointer to T, //letting you write very high-performance generic code. //It's dangerous if you don't know what you're doing, but very worth if you do. static T Read<T>(IntPtr address) {var obj = default(T);var tr = __makeref(obj);//This is equivalent to shooting yourself in the foot//but it's the only high-perf solution in some cases//it sets the first field of the TypedReference (which is a pointer)//to the address you give it, then it dereferences the value.//Better be 10000% sure that your type T is unmanaged/blittable...unsafe { *(IntPtr*)(&tr) = address; }return __refvalue(tr, T); }寫一個方法的版本sizeof指令,有時會有用:
static class ArrayOfTwoElements<T> { static readonly Value = new T[2]; }static uint SizeOf<T>() {unsafe {TypedReferenceelem1 = __makeref(ArrayOfTwoElements<T>.Value[0] ),elem2 = __makeref(ArrayOfTwoElements<T>.Value[1] );unsafe{ return (uint)((byte*)*(IntPtr*)(&elem2) - (byte*)*(IntPtr*)(&elem1)); }} }編寫一個傳遞“state”參數的方法,以避免裝箱:
static void call(Action<int, TypedReference> action, TypedReference state) {//Note: I could've said "object" instead of "TypedReference",//but if I had, then the user would've had to box any value typestry{action(0, state);}finally { /*Do any cleanup needed*/ } }那么,為什么像這樣的使用“不鼓勵”(由于缺乏文檔)?有什么特別的安全原因嗎?如果它不與指針混合(無論如何都不是安全的或可驗證的),那么它似乎是完全安全和可驗證的。
最新情況:
示例代碼來證明,確實,TypedReference可以是兩倍的速度(或更多):
using System; using System.Collections.Generic; static class Program {static void Set1<T>(T[] a, int i, int v){ __refvalue(__makeref(a[i]), int) = v; }static void Set2<T>(T[] a, int i, int v){ a[i] = (T)(object)v; }static void Main(string[] args){var root = new List<object>();var rand = new Random();for (int i = 0; i < 1024; i++){ root.Add(new byte[rand.Next(1024 * 64)]); }//The above code is to put just a bit of pressure on the GCvar arr = new int[5];int start;const int COUNT = 40000000;start = Environment.TickCount;for (int i = 0; i < COUNT; i++){ Set1(arr, 0, i); }Console.WriteLine("Using TypedReference: {0} ticks",Environment.TickCount - start);start = Environment.TickCount;for (int i = 0; i < COUNT; i++){ Set2(arr, 0, i); }Console.WriteLine("Using boxing/unboxing: {0} ticks",Environment.TickCount - start);//Output Using TypedReference: 156 ticks//Output Using boxing/unboxing: 484 ticks} }?
用戶回答回答于?2018-03-28
當__arglist,__makeref,和__refvalue是語言擴展在C#語言規范中是沒有文檔的,這些構造用于在引擎蓋下實現它們(vararg電話會議,TypedReference類型,arglist,refanytype,mkanyref,和refanyva。
在VarargLibrary中定義它可以很清楚地表明,它們主要是為了支持可變長度的參數列表,而不是其他的。變量參數列表在不需要與使用varargs的外部C代碼接口的平臺上沒有什么用處。因此,Varargs庫不是任何CLI配置文件的一部分。合法的CLI實現可能選擇不支持Varargs庫,因為它不包含在CLI內核配置文件中:
4.1.6 Vararg 大vararg特征集支持可變長度的參數列表和運行時類型的指針。undefined如果省略:對象引用方法的任何嘗試。vararg調用約定或與vararg方法關聯的簽名編碼(請參閱PartitionII)將引發System.NotImplementedException例外。方法使用CIL指令。arglist,refanytype,mkrefany,和refanyval將拋出System.NotImplementedException例外。未指定異常的確切時間。類型System.TypedReference不需要定義。
最新情況(回復)GetValueDirect評論):
FieldInfo.GetValueDirect是FieldInfo.SetValueDirect是不基類庫的一部分。請注意,.NET Framework類庫與基類庫之間存在差異。BCL是CLI/C#的一致性實現所需的唯一條件。
一旦使用bcl之外的方法,就會放棄一些可移植性(隨著Silverlight和MonoTouch等非.NET CLI實現的出現,這一點變得越來越重要)。即使實現想要增強與Microsoft.NET框架類庫的兼容性,它也可以簡單地提供GetValueDirect和SetValueDirect帶著...TypedReference不做TypedReference由運行時特別處理(基本上,使它們與它們的object沒有性能效益的對應方)。
如果他們把它記錄在C#中,它至少會有幾個暗示:
?
用戶回答回答于?2018-03-28
實際上,諸如指針這樣的特性,stackalloc,并且在某些情況下存在某些優化的框架函數以提高性能。
我會說初等類型安全的好處,也提高性能類似于Typedeference通過避免拳擊和取消拳擊。
static void call(Action<int, TypedReference> action, TypedReference state){action(0, state); }對此:
static void call<T>(Action<int, T> action, T state){action(0, state); } 創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的为什么TypedReference在幕后的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 鹏华半导体芯片etf怎么买?一文弄懂
- 下一篇: 第九节:JWT简介和以JS+WebApi