SORU
21 Ocak 2011, Cuma


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
23 Ocak 2011, Pazar


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ğervararg ç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.SetValueDirectdeğ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:

  1. 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.
  2. 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.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • DJAndrewRyan

    DJAndrewRyan

    22 Ocak 2007
  • Kyler Briskey

    Kyler Briske

    20 ŞUBAT 2011
  • Tina Chen

    Tina Chen

    26 Mayıs 2012