警告:这个问题有点异端......宗教程序员总是遵守良好做法,请不要阅读.:)
有谁知道为什么不鼓励使用TypedReference(隐含地,缺乏文档)?
我已经找到了很好的用途,例如通过不应该是通用的函数传递泛型参数(当使用object可能是过度杀手或缓慢,如果你需要值类型时),当你需要一个不透明的指针时,或者当你需要快速访问数组元素时,你在运行时找到它的规范(使用Array.InternalGetReference).由于CLR甚至不允许错误使用此类型,为什么不鼓励?它似乎不安全或任何东西......
我找到的其他用途TypedReference:
C#中的"Specializing"泛型(这是类型安全的):
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); }
}
Run Code Online (Sandbox Code Playgroud)
编写适用于通用指针的代码(如果误用,这是非常不安全的,但如果使用正确则快速且安全):
//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, …Run Code Online (Sandbox Code Playgroud) 想象一下,我们有一个可变的struct(是的,不要开始):
public struct MutableStruct
{
public int Foo { get; set; }
public override string ToString()
{
return Foo.ToString();
}
}
Run Code Online (Sandbox Code Playgroud)
使用反射,我们可以获取一个盒装实例,struct并在框内变异:
// this is basically what we want to emulate
object obj = new MutableStruct { Foo = 123 };
obj.GetType().GetProperty("Foo").SetValue(obj, 456);
System.Console.WriteLine(obj); // "456"
Run Code Online (Sandbox Code Playgroud)
我会喜欢做的是写一些IL可以做同样的,因为这-但速度更快.我是一个元编程迷; p
拆箱 - 任何值并使用常规IL改变值是微不足道的 - 但是你不能只是在之后调用它,因为这将创建一个不同的框.我猜我们需要做的是将它复制到现有的盒子上.我已经调查了ldobj/ stobj,但那些似乎没有做到这一点(除非我遗漏了什么).
那么:是否存在这样做的机制?或者我必须限制自己反思以执行盒装structs 的就地更新?
换句话说:什么... evil goes here...?
var method = …Run Code Online (Sandbox Code Playgroud) 假设我有以下代码更新struct使用反射的字段.由于struct实例被复制到DynamicUpdate方法中,因此需要在传递之前将其装箱到对象.
struct Person
{
public int id;
}
class Test
{
static void Main()
{
object person = RuntimeHelpers.GetObjectValue(new Person());
DynamicUpdate(person);
Console.WriteLine(((Person)person).id); // print 10
}
private static void DynamicUpdate(object o)
{
FieldInfo field = typeof(Person).GetField("id");
field.SetValue(o, 10);
}
}
Run Code Online (Sandbox Code Playgroud)
代码工作正常.现在,假设我不想使用反射,因为它很慢.相反,我想生成一些CIL直接修改id字段并将该CIL转换为可重用的委托(例如,使用动态方法功能).特别是,我想用s/t替换上面的代码,如下所示:
static void Main()
{
var action = CreateSetIdDelegate(typeof(Person));
object person = RuntimeHelpers.GetObjectValue(new Person());
action(person, 10);
Console.WriteLine(((Person)person).id); // print 10
}
private static Action<object, object> CreateSetIdDelegate(Type t)
{
// build dynamic method …Run Code Online (Sandbox Code Playgroud)