на мусор также.

преждение: этот вопрос немного еретический ... религиозные программисты всегда придерживаются хороших практик, пожалуйста, не читайте их. :)

Кто-нибудь знает, почему использованиеTypedReference так обескуражен (неявно, из-за отсутствия документации)?

Я нашел отличное применение для этого, например, при передаче общих параметров через функции, которые не должны быть общими (при использованииobject может быть избыточным или медленным, если вам нужен тип значения), когда вам нужен непрозрачный указатель или когда вам нужно быстро получить доступ к элементу массива, чьи спецификации вы найдете во время выполнения (используяArray.InternalGetReference). Поскольку CLR даже не допускает неправильное использование этого типа, почему это не рекомендуется? Это не кажется небезопасным или что-то ...

Другое использование, которое я нашел дляTypedReference:

«Специализированные» дженерики в C # (это безопасно для типов):

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); }
}

Написание кода, который работает с общими указателями (этоочень небезопасно при неправильном использовании, но быстро и безопасно при правильном использовании):

//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 
    {
        TypedReference
            elem1 = __makeref(ArrayOfTwoElements<T>.Value[0] ),
            elem2 = __makeref(ArrayOfTwoElements<T>.Value[1] );
        unsafe
        { return (uint)((byte*)*(IntPtr*)(&elem2) - (byte*)*(IntPtr*)(&elem1)); }
    }
}

Написание метода, который передает параметр «состояние», который хочет избежать бокса:

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*/ }
}

Так почему же такое использование "не рекомендуется" (из-за отсутствия документации)? Какие-то конкретные соображения безопасности? Это кажется совершенно безопасным и проверяемым, если оно не смешано с указателями (которые в любом случае не являются безопасными или проверяемыми) ...

Обновить:

Пример кода, чтобы показать, что, действительно,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 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
    }
}

(Редактировать: я редактировал бенчмарк выше, так как в последней версии поста использовалась отладочная версия кода [я забыл изменить ее на выпуск], и не оказывал давления на GC. Эта версия немного более реалистична, и в моей системе это более чем в три раза быстрее сTypedReference в среднем.)

Ответы на вопрос(3)

Ваш ответ на вопрос