C#4.0中的双重调度 - 动态关键字?

时间:2012-03-22 18:04:07

标签: c# dynamic overloading

我之前已经意识到这一点,但我没有找到关于最佳解决方案的明确协议。

使用动态(如下所示)最好的方法吗? 我认为最好尽可能避免动态,以帮助在编译时捕获问题。

(classA1和classA2实现接口A,同样适用于B)

 public static void Foo(InterfaceA a, InterfaceB b) 
 { 
    Foo((dynamic)a, (dynamic)b); 
 }

static void Foo(classA1 a, classB1 b) {  //some code }
static void Foo(classA2 a, classB2 b) {  //some code }
static void Foo(classA1 a, classB2 b) {  //some code }
static void Foo(classA2 a, classB1 b) {  //some code }

或类似地......

public static void Foo(InterfaceA a, InterfaceB b) 
 { 
    ((dynamic) a).Foo(b); 
 }

public classA1
{
     void Foo(classB1 b) {  //some code }
}
//repeated for other cases    

4 个答案:

答案 0 :(得分:3)

  

使用动态(如下所示)是最好的方法吗?

这是一种方式 - 只要执行时间类型总是以超载分辨率满意的东西结束。

你可能想要一个

的支持方法
static void Foo(object x, object y)

如果没有一种方法适用(例如a是非ClassA1 / ClassA2实现)。如果两个值都为空,它不会帮助你,请注意......

我通常尝试重新设计以便不需要这样做,但如果没有更多的背景知识,很难知道最佳解决方案。

答案 1 :(得分:0)

'classA1'等InterfaceA的实现?如果是,那么为什么不将Foo函数声明为接受InterfaceAInterfaceB并将它们转换为函数所期望的具体实现?如,

static void Foo(InterfaceA a, InterfaceB b) {
    classA1 c1 = a as classA1;
    classB1 b1 = b as classB1;
    // ... etc
}

Dynamic不打算以这种方式使用。

答案 2 :(得分:0)

传统上,C#是一种静态类型的语言。动态关键字adds dynamic typing to the language。通常的建议是使用“动态”sparingly。这可能是您需要它的情况。

Generics 不会剪切它,因为它不会编译:

    private void button1_Click(object sender, EventArgs e)
    {
        Foo(new classA1(), new classB2());
    }

    static void Foo<T, T1>(T a, T1 b) where T: InterfaceA
        where T1: InterfaceB
    {
        Foo2(a, b);
    }

    static void Foo2(classA1 a, classB1 b) { }
    static void Foo2(classA2 a, classB2 b) { }
    static void Foo2(classA1 a, classB2 b) { }
    static void Foo2(classA2 a, classB1 b) { }

    interface InterfaceA { }
    interface InterfaceB { }

    class classA1 : InterfaceA { }
    class classA2 : InterfaceA { }

    class classB1 : InterfaceB { }
    class classB2 : InterfaceB { }

答案 3 :(得分:0)

你可以用反射做一些AWFUL - 但我确信它并不比做动态更好:

void Main()
{
    var a = "hello";//5;
    var b = "hello"; 

    var type1 = a.GetType();
    var type2 = b.GetType();

    var t = typeof(FooClass);

    var methods = t.GetMethods();

    foreach(var method in methods)
    {
        var parameters = method.GetParameters();

        if(parameters.Length == 2)
        {
            if(parameters[0].ParameterType == type1 
               && parameters[1].ParameterType == type2)
            {
                method.Invoke(this, new object[]{ a, b });
            }
        }
    }
}

public static class FooClass
{
    public static void Foo(int i, string s)
    {
        "Foo1".Dump();
    }

    public static void Foo(string s, string s2)
    {
        "Foo2".Dump();
    }
}