这是动态的错误吗? [英] Is this a bug in dynamic?

查看:95
本文介绍了这是动态的错误吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在泛型类上使用 dynamic 实现动态调度时,并且泛型类型参数是另一个类的私有内部类,运行时绑定程序将引发异常。 p>

例如:

 使用系统; 

公共抽象类Dispatcher< T> {
public T Call(object foo){return CallDispatch((dynamic)foo); }

受保护的抽象T CallDispatch(int foo);
受保护的抽象T CallDispatch(string foo);
}

公共类程序{
public static void Main(){
TypeFinder d = new TypeFinder();

Console.WriteLine(d.Call(0));
Console.WriteLine(d.Call()));
}

私有类TypeFinder:Dispatcher< CallType> {
受保护的覆盖CallType CallDispatch(int foo){
return CallType.Int;
}

受保护的覆盖CallType CallDispatch(string foo){
return CallType.String;
}
}

私有枚举CallType {Int,String}
}

在这里,将与消息一起引发 RuntimeBinderException


'Dispatcher.CallDispatch(int)'由于其保护级别而无法访问


原因在于类型参数 T 是私有的 CallType ,其中 Dispatcher< T> 无法访问。因此, CallDispatch 必须不可访问-但这不是,因为它可以作为 T 访问。



这是动态的错误,还是不应该支持?

解决方案

这是一个错误。如果您可以(并且可以)静态进行呼叫,则应该可以动态进行呼叫。



具体来说,以下代码有效:

 使用系统; 

公共抽象类Dispatcher< T> {
public T Call(object foo)
{
return CallDispatch((((object)(dynamic)foo).ToString());
}

受保护的抽象T CallDispatch(int foo);
受保护的抽象T CallDispatch(string foo);
}

公共类程序{
public static void Main(){
TypeFinder d = new TypeFinder();

Console.WriteLine(d.Call(0));
Console.WriteLine(d.Call()));
}

私有类TypeFinder:Dispatcher< CallType> {
受保护的覆盖CallType CallDispatch(int foo){
return CallType.Int;
}

受保护的覆盖CallType CallDispatch(string foo){
return CallType.String;
}
}

私有枚举CallType {Int,String}
}

请注意,我已经使用 ToString()来知道静态类型,C#编译器和CLR允许此上下文访问私有类型 CallType ,因此DLR也应允许。


When implementing dynamic dispatch using dynamic on a generic class, and the generic type parameter is a private inner class on another class, the runtime binder throws an exception.

For example:

using System;

public abstract class Dispatcher<T> {
    public T Call(object foo) { return CallDispatch((dynamic)foo); }

    protected abstract T CallDispatch(int foo);
    protected abstract T CallDispatch(string foo);
}

public class Program {
    public static void Main() {
        TypeFinder d = new TypeFinder();

        Console.WriteLine(d.Call(0));
        Console.WriteLine(d.Call(""));
    }

    private class TypeFinder : Dispatcher<CallType> {
        protected override CallType CallDispatch(int foo) {
            return CallType.Int;
        }

        protected override CallType CallDispatch(string foo) {
            return CallType.String;
        }
    }

    private enum CallType { Int, String }
}

Here, a RuntimeBinderException will be thrown with the message

'Dispatcher.CallDispatch(int)' is inaccessible due to its protection level

The reason for the inaccessibility is that the type parameter T is the private CallType which Dispatcher<T> cannot access. Therefore, CallDispatch must be inaccessible - but it isn't, because it's accessible as T.

Is this a bug with dynamic, or is this not supposed to be supported?

解决方案

It's a bug. If you can make the call statically (and you can), you should be able to make it dynamically.

Specifically, the following code works:

using System;

public abstract class Dispatcher<T> {
    public T Call(object foo)
    {
        return CallDispatch(((object)(dynamic)foo).ToString());
    }

    protected abstract T CallDispatch(int foo);
    protected abstract T CallDispatch(string foo);
}

public class Program {
    public static void Main() {
        TypeFinder d = new TypeFinder();

        Console.WriteLine(d.Call(0));
        Console.WriteLine(d.Call(""));
    }

    private class TypeFinder : Dispatcher<CallType> {
        protected override CallType CallDispatch(int foo) {
            return CallType.Int;
        }

        protected override CallType CallDispatch(string foo) {
            return CallType.String;
        }
    }

    private enum CallType { Int, String }
}

Note that I've used ToString() to make the static type known, the C# compiler and CLR allow this context to access the private type CallType, so the DLR should allow it as well.

这篇关于这是动态的错误吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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