当通用参数为私有参数时,为什么会引发RuntimeBinderException? [英] Why is RuntimeBinderException thrown when generic parameter is private?

查看:65
本文介绍了当通用参数为私有参数时,为什么会引发RuntimeBinderException?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以动态参数形式 Foo< Bar> 调用方法时,会抛出 RuntimeBinderException 如果 Bar 是私有的。为什么? (请参见下面的 Test1 运行方法中的注释。)

 公共类Test1 
{
public void Run()
{
dynamic publicList = ListProvider.GetPublic();
DoSomething(publicList);

动态privateList = ListProvider.GetPrivate();
DoSomething(privateList); // Microsoft.CSharp.RuntimeBinder.RuntimeBinderException
}

private void DoSomething< T>(List< T> list){}

静态私有类ListProvider
{
静态公共对象GetPrivate(){返回新List< A>(); }
静态公共对象GetPublic(){返回新List< B>(); }

私人课程A {}
公共课程B {}
}
}

要了解为什么这样做不合理/不一致,请注意下面的 Test2 ,它不使用泛型,并且在动态参数为

 公共类Test2 
{
public void Run()
{
dynamic publicItem = ItemProvider.GetPublic();
DoSomething(publicItem);

动态privateItem = ItemProvider.GetPrivate();
DoSomething(privateItem); //没有抛出异常
}

private void DoSomething< T>(T t){}

静态私有类ItemProvider
{
静态公共对象GetPrivate(){返回新的A(); }
静态公共对象GetPublic(){返回new B(); }

私人课程A {}
公共课程B {}
}
}

使用泛型为什么会/应该影响动态参数对访问修饰符的解析?

解决方案

您提到的两个示例并非完全矛盾(合理是另一回事):在每种情况下,运行时绑定程序都尝试将 T 设置为相等面对 A类对象。对于第一个示例,不能将类型为 List< A> 的列表强制转换为 List< object> ,因此引发异常。但是,在第二种情况下,将类型为 A 的对象强制转换为 object 可以正常工作,并且不会引发异常


通过将 DoSomething 的定义更改为


<$可以使第一个示例运行。 p $ p> private void DoSomething< T>(IReadOnlyList< T> list){}

因为可以将类型 List< A> 的项强制转换为类型 IReadOnlyList< object>


您对问题的最初陈述并不完全正确:问题不是所讨论的类型是否为私有,而是代码是否通过动态调用参数具有对该类型的访问权限。如果您将 Run 方法移动到 ItemProvider 类中(作为静态方法,还使 DoSomething 静态以允许 Run 访问),两个测试都可以正常工作。但是,移动 DoSomething 并不重要。


我自己遇到了这个问题的另一种变化:该类型是内部的,而不是私有的,因此如果位于定义该类的项目中,则使用相同的精确代码也可以,但是当位于其他项目中时,则不能运行相同的代码。


When a method is called with a dynamic parameter of the form Foo<Bar>, a RuntimeBinderException is thrown when Bar is private. Why? (See comment in Run method of Test1 below.)

public class Test1
{
    public void Run()
    {
        dynamic publicList = ListProvider.GetPublic();
        DoSomething(publicList);

        dynamic privateList = ListProvider.GetPrivate();
        DoSomething(privateList); // Microsoft.CSharp.RuntimeBinder.RuntimeBinderException
    }

    private void DoSomething<T>(List<T> list) { }

    static private class ListProvider
    {
        static public object GetPrivate() { return new List<A>(); }
        static public object GetPublic() { return new List<B>(); }

        private class A { }
        public class B { }
    }
}

To see why this is unreasonable/inconsistent, note that Test2 below, does not use generics, and succeeds when dynamic parameter is private.

public class Test2
{
    public void Run()
    {
        dynamic publicItem = ItemProvider.GetPublic();
        DoSomething(publicItem);

        dynamic privateItem = ItemProvider.GetPrivate();
        DoSomething(privateItem); // No exception thrown
    }

    private void DoSomething<T>(T t) { }

    static private class ItemProvider
    {
        static public object GetPrivate() { return new A(); }
        static public object GetPublic() { return new B(); }

        private class A { }
        public class B { }
    }
}

Why would/should the use of generics affect the resolution of a dynamic parameter with respect to access modifiers?

解决方案

The two examples you mention are not truly inconsistent (reasonable is a different matter): In each case, the runtime binder attempts to set T equal to object when it is faced with class A. For the first example, a list of type List<A> cannot be cast to a List<object>, so an exception is thrown. In the second case, however, casting an object of type A to an object works fine, and no exception is thrown.

The first example can be made to run by changing the definition of DoSomething to

 private void DoSomething<T>(IReadOnlyList<T> list) { }

since an item of type List<A> can be cast to type IReadOnlyList<object>.

Your initial statement of the issue is not completely correct, however: The issue is not whether the type in question is private or not, but whether the code making the call with the dynamic parameter has access rights to that type. If you move the Run method inside the ItemProvider class (as a static method, and also make DoSomething static to allow Run access), both tests will work fine. Moving DoSomething, however, will not matter.

I ran into a different variation of this problem myself: The type in question was internal, not private, so the same exact code ran fine if it was located in the project where that class was defined, but not when it was located in a different project.

这篇关于当通用参数为私有参数时,为什么会引发RuntimeBinderException?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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