Neden kamera arkası eden typedreference? O'ın bu kadar hızlı ve güvenli... neredeyse sihirli!
Uyarı: Bu soru biraz sapkın... dini programcılar her zaman iyi uygulamalar, lütfen uyan okumuyorsun. :)
Herkes TypedReference kullanılması önerilmez (örtülü olarak, belgelerin eksikliği) neden biliyor mu?
Buldum harika kullanır, gibi zaman geçirmeden genel parametreleri ile fonksiyonları olmamalı genel (kullanırken object
olabilir overkill veya yavaş, eğer ihtiyacınız olan bir değer türü), için ihtiyacın varken opak işaretleyici, ya da ne zaman ihtiyacınız erişim bir elemanın bir dizi hızlı olan özellikleri bulmak için, çalışma zamanında (kullanarak Array.InternalGetReference
). CLR bile bu tür yanlış kullanım izin vermez bu yana, neden önerilmez? Ya da güvenli olmayan bir şey var gibi görünüyor
DiÄŸer TypedReference
buldum kullanır:
"(Tip-güvenli) jenerik C#:. uzmanlaşmış
static void foo<T>(ref T value)
{
//This is the ONLY way to treat value as int, without boxing/unboxing objects
if (value is int)
{ __refvalue(__makeref(value), int) = 1; }
else { value = default(T); }
}
Yazı genel işaretçiler ile çalışan (bu . kod ^em>çokgüvensiz, ama hızlı ve güvenli eğer doğru kullanılırsa) yanlış:
//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);
}
Bir yazıyöntemsürüm bazen yararlı olabilir sizeof
talimat:
static class ArrayOfTwoElements<T> { static readonly Value = new T[2]; }
static uint SizeOf<T>()
{
unsafe
{
TypedReference
elem1 = __makeref(ArrayOfTwoElements<T>.Value[0] ),
elem2 = __makeref(ArrayOfTwoElements<T>.Value[1] );
unsafe
{ return (uint)((byte*)*(IntPtr*)(&elem2) - (byte*)*(IntPtr*)(&elem1)); }
}
}
Yazı geçer bir yöntem bir "devlet bu boks önlemek istiyor" parametre:
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 types
try
{
action(0, state);
}
finally { /*Do any cleanup needed*/ }
}
Neden kullanır bu gibi "" (eksik evrak)? cesareti yani Herhangi bir özel güvenlik sebep? Tamamen güvenli ve eğer işaretçiler güvenli ve doğrulanabilir değil) ile karışık değilse... doğrulanabilir görünüyor
Güncelleme:
Örnek kod, gerçekten de, TypedReference
iki kat daha hızlı olabileceğini göstermek (veya daha fazla):
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 GC
var 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
}
}
(Edit: ben düzenlenmiş kriter yukarıda, son sürüm sonrası kullanılan bir hata ayıklama sürümü kodu [unuttum onu değiştirmek için serbest] ve hiçbir baskı GC. Bu sürüm biraz daha gerçekçi ve benim sistem ortalama TypedReference
ile üç kat daha hızlı.)
CEVAP
Kısa cevap:taşınabilirlik.
__arglist
, __makeref
__refvalue
ikendil uzantılarıve belgelenmemiş C# Dili özelliklerini, yapıları kullanılan uygular başlık altında (vararg
çağırma, TypedReference
yazın, arglist
, refanytype
, mkanyref
, ve refanyval
talimatları) mükemmel belgelenen CLI Specification (ECMA-335)Sırasında kütüphane.
Sırasında kütüphanede tanımlanan öncelikle değişken uzunlukta argüman listeleri başka da bir şey yok destek amaçlı olduğunu açıkça göstermektedir. Değişken bağımsız değişken listesi dış C kodu ile arayüz gerek yok bu platformlarda küçük yaramaz varargs kullanır. Bu nedenle, Varargs kütüphane herhangi CLİ profilinin bir parçası değildir. Meşru uygulamaları CLİ CLİ Çekirdek profil dahil değil gibi Varargs kütüphane destek vermemeyi tercih edebilir:
4.1.6 Sırasında
sırasında ayarlama özelliğideğişken uzunlukta argüman listeleri destekler ve çalışma yazılan işaretçiler.
Ä°hmal: eÄŸer
vararg
çağırma yöntemi başvurmak için herhangi bir girişim veya imza kodlamalar sırasında yöntemleri ile ilgili (Bakınız Bölüm II)System.NotImplementedException
istisna olacaktır. Yöntemleri CIL talimatlarıarglist
,refanytype
,mkrefany
,refanyval
System.NotImplementedException
istisna olacaktır. Özel hassas zamanlama belirtilmedi. 32* *türü tanımlanmış olması gerekmez.
Güncelleme (GetValueDirect
yorum cevap):
FieldInfo.GetValueDirect
FieldInfo.SetValueDirect
değilTemel Sınıf Kütüphanesi bir parçası. Arasında bir fark olduğunu unutmayın .NET Çerçeve Sınıf Kütüphanesi ve Temel Sınıf Kütüphanesi. BCI tek şey CLİ en uygun uygulama için gerekli C/ * ve ECMA TR/84 belgelenmiştir. (Aslında, FieldInfo
Yansıma kütüphanenin bir parçası kendisi ve Çekirdek profil ya CLİ) dahil değil.
BCI dışında bir yöntem kullanmaya başladığınızda, biraz taşınabilirlik (ve bu Silverlight gibi non-.NET CLİ uygulamaları gelişiyle giderek daha önemli hale geliyor ve MonoTouch) verirsiniz. Eğer bir uygulama ile Microsoft compatiblility artırmak istese bile .NET Çerçeve Sınıf Kütüphanesi, sadece sağlamak GetValueDirect
SetValueDirect
alarak TypedReference
yapmadan TypedReference
Özel İdare tarafından çalışma zamanı (temel olarak, yapım onları eşdeğer kendi object
meslektaşları kalmaksızın yarar).
C belgelenmiş oldu onlar# en azından birkaç etkileri olurdu:
- Herhangi bir özelliği, gibiolabilirözellikle bu gerçekten C tasarımında uymuyor bu yana yeni özellikler için bir barikat haline,# ve çalışma zamanı tarafından bir tür garip sözdizimi uzantıları ve özel teslim gerektirir.
- Tüm uygulamaları C# için bir şekilde uygulamak bu özelliği şey demiyorum önemsiz/Olası için C# uygulamaları bu yok kaçak üst bir CLİ hiç veya çalışma üstünde bir CLİ olmadan Varargs.
Neden `1000000000000000 aralığı(100000...
Neden tanıtan bir işe yaramaz MOV tali...
Neden bu kadar hızlı C, ve neden değil...
Neden MATLAB matris çarpımı kadar hızl...
Neden bu kadar inanılmaz derecede hızl...