问题描述
我终于了解了的用法TypedReference.MakeTypedReference
方法,但是为什么参数如此有限?与MakeTypedReference
相比,底层的私有InternalMakeTypedReference(void* result, object target, IntPtr[] flds, RuntimeType lastFieldType)
可以做更多的事情,MakeTypedReference
限制了字段数组包含元素并且字段类型是非基本的.
I've finally understood the usage of the TypedReference.MakeTypedReference
method, but why are the arguments so limited? The underlying private InternalMakeTypedReference(void* result, object target, IntPtr[] flds, RuntimeType lastFieldType)
can do a lot more things than the MakeTypedReference
that limits the field array to have elements and the field types to be non-primitive.
我制作了一个示例用法代码,显示了它的全部可能性:
I've made a sample usage code that shows the full possibility of it:
private static readonly MethodInfo InternalMakeTypedReferenceMethod = typeof(TypedReference).GetMethod("InternalMakeTypedReference", flags);
private static readonly Type InternalMakeTypedReferenceDelegateType = ReflectionTools.NewCustomDelegateType(InternalMakeTypedReferenceMethod.ReturnType, InternalMakeTypedReferenceMethod.GetParameters().Select(p => p.ParameterType).ToArray());
private static readonly Delegate InternalMakeTypedReference = Delegate.CreateDelegate(InternalMakeTypedReferenceDelegateType, InternalMakeTypedReferenceMethod);
public static void MakeTypedReference([Out]TypedReference* result, object target, params FieldInfo[] fields)
{
IntPtr ptr = (IntPtr)result;
IntPtr[] flds = new IntPtr[fields.Length];
Type lastType = target.GetType();
for(int i = 0; i < fields.Length; i++)
{
var field = fields[i];
if(field.IsStatic)
{
throw new ArgumentException("Field cannot be static.", "fields");
}
flds[i] = field.FieldHandle.Value;
lastType = field.FieldType;
}
InternalMakeTypedReference.DynamicInvoke(ptr, target, flds, lastType);
}
不幸的是,实际上调用它需要更多的技巧,因为不能从MethodInfo
调用它,并且一个参数是RuntimeType
,因此委托类型必须动态生成(也可以使用DynamicMethod
).
Unfortunately, actually calling it needs more hacks, as it can't be invoked from MethodInfo
and one parameter is RuntimeType
, so the delegate type has to be generated dynamically (DynamicMethod
can be also used).
现在这能做什么?它可以不受限制地访问任何对象的任何值的任何字段(类或结构类型,甚至是基本类型).而且,它可以创建对装箱值类型的引用.
Now what can this do? It can access any field (class or struct type, even primitive) of any value of any object without limitations. Moreover, it can create a reference to a boxed value type.
object a = 98;
TypedReference tr;
InteropTools.MakeTypedReference(&tr, a);
Console.WriteLine(__refvalue(tr, int)); //98
__refvalue(tr, int) = 1;
Console.WriteLine(a); //1
那么为什么开发人员似乎无意识地决定禁止这种用法,而这显然是有用的?
So why have the developers seemingly senselessly decided to disallow this kind of usage, while this is obviously useful?
推荐答案
责备柏拉图和他那令人毛骨悚然的类型理论" ...
Blame Plato and his darn "theory of types"...
这是任何ref
(托管指针)引用的本质所固有的-包括新的C#7 ref local 和 ref return 功能-以及如您所见, TypedReference ,您可以将其用于读取和写入到目标.因为这不是重点吗?
It is the inherent in the nature of any ref
(managed pointer) reference--including the new C# 7 ref local and ref return features--and as you observe, TypedReference, that you can use such for both reading and writing to the target. Because isn't that the whole point?
现在,因为 CTS 不能排除这两种可能性中的任何一种,强类型化要求每个ref
的Type
均受类型中上和下的限制层次结构.
Now because the CTS can't rule-out either of those possibilities, strong-typing requires that the Type
of every ref
be constrained from both above and below in the type hierarchy.
更正式地说,Type
被限制为多态协方差和自变量,否则将可以使用.显然,此交集的结果会折叠成单个Type
,此后此值不变.
More formally, the Type
is constrained to be the intersection of the polymorphic covariance and contravariance for which it would otherwise be eligible. Obviously, the result of this intersection collapses to a single Type
, itself, which is henceforth invariant.
这篇关于为什么TypedReference.MakeTypedReference如此受限制?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!