【问题标题】:Why is RuntimeBinderException thrown when generic parameter is private?为什么泛型参数为私有时会引发 RuntimeBinderException?
【发布时间】:2017-06-20 03:29:57
【问题描述】:

当使用Foo<Bar> 形式的动态参数调用方法时,如果Bar 是私有的,则会抛出RuntimeBinderException。为什么? (请参阅下面Test1Run 方法中的评论。)

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 { }
    }
}

要查看为什么这是不合理/不一致的,请注意下面的Test2,不使用泛型,并且在动态参数为私有时成功。

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 { }
    }
}

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

【问题讨论】:

    标签: c# generics dynamic


    【解决方案1】:

    您提到的两个示例并非真正不一致(合理是另一回事):在每种情况下,运行时绑定程序都会在遇到class A 时尝试将T 设置为等于object。对于第一个示例,List&lt;A&gt; 类型的列表不能转换为List&lt;object&gt;,因此会引发异常。然而,在第二种情况下,将 A 类型的对象转换为 object 可以正常工作,并且不会引发异常。

    DoSomething的定义改为

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

    因为List&lt;A&gt; 类型的项目可以转换为IReadOnlyList&lt;object&gt; 类型。

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

    我自己遇到了这个问题的不同变体:所讨论的类型是内部的,而不是私有的,所以如果它位于定义该类的项目中,相同的确切代码运行良好,但不是在它所在的位置在不同的项目中。

    【讨论】:

    • @Little Endian 哦,谢谢 - 你的问题让我意识到自己的问题的解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-30
    • 1970-01-01
    • 1970-01-01
    • 2010-11-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多