警告:这个问题有点异端...宗教程序员始终恪守良好实践,请不要阅读它。:)
有谁知道为什么不鼓励使用TypedReference(隐式地,由于缺乏文档)?
我发现它有很好的用途,例如,当通过不应该是泛型的函数传递泛型参数时(object如果需要使用值类型,则使用over可能会导致过时或缓慢),需要不透明指针时;或者用于何时需要快速访问数组元素的信息,您可以在运行时找到其规格(使用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)); }
    }
}
编写一个传递“ 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 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上,平均速度要快三倍以上。)
int-> DockStyle)。这个盒子是真实的,并且慢了将近十倍。
                
TypedReference: 203 ticks,boxing/unboxing: 31 ticks。不管我尝试什么(包括执行计时的不同方法),装箱/拆箱在我的系统上仍然更快。