Двойная отправка в C # 4.0 - динамическое ключевое слово? - PullRequest
3 голосов
/ 22 марта 2012

Я понимаю, что об этом уже спрашивали, но я не нашел четкого соглашения о лучшем решении.

Является ли использование динамического (как показано ниже) лучшим способом сделать это? Я полагаю, что лучше всего избегать динамических изменений, когда это возможно, чтобы помочь выявить проблемы во время компиляции.

(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 ]

3 голосов
/ 22 марта 2012

Является ли использование динамического (как показано ниже) лучшим способом сделать это?

Что ж, это способ сделать это - до тех пор, пока типы времени выполнения всегда будут иметь то, что удовлетворит разрешение перегрузки.

Возможно, вы захотите поставить метод обратного останова

static void Foo(object x, object y)

в случае, если ни один из методов не применим (например, a является реализацией не ClassA1 / ClassA2). Это не поможет вам, если оба значения равны нулю, учтите ...

Обычно я пытаюсь изменить дизайн так, чтобы это не требовалось, но трудно найти лучшее решение без дополнительного контекста.

0 голосов
/ 22 марта 2012

Вы могли бы сделать что-то ужасное с отражением - но я уверен, что это не лучше, чем делать динамические:

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();
    }
}
0 голосов
/ 22 марта 2012

C # традиционно был типизированным языком.Ключевое слово dynamic добавляет динамическую типизацию к языку .Обычный совет - использовать «динамический» экономно .Здесь может быть случай, когда вам это нужно.

Обобщения не будут вырезать его, поскольку это не скомпилируется:

    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 { }
0 голосов
/ 22 марта 2012

Являются ли 'classA1' и т. Д. Реализациями InterfaceA?Если так, то почему бы просто не объявить функции Foo как принимающие InterfaceA и InterfaceB и привести их к конкретной реализации, ожидаемой функцией?Например,

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

Динамический не предназначен для использования таким образом.

...