为什么TypedReference.MakeTypedReference如此受限制? [英] Why is TypedReference.MakeTypedReference so constrained?

查看:139
本文介绍了为什么TypedReference.MakeTypedReference如此受限制?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我终于了解了的用法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 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 不能排除这两种可能性中的任何一种,强类型化要求每个refType均受类型中的限制层次结构.

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被限制为多态

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如此受限制?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆