Является ли хорошей практикой приводить объекты к динамическим, чтобы вызывался правильный перегруженный метод? - PullRequest
20 голосов
/ 25 ноября 2011

Мой вопрос о том, является ли нижеследующее подходящим использованием ключевого слова dynamic в C # 4.

У меня есть несколько вспомогательных методов, которые обеспечивают более полезное представление различных объектов, чем их стандартные ToString методы, которые я использую для модульного тестирования. Вот упрощенный пример:

public static string PrettyPrint<T>(IEnumerable<T> list)
{
    return string.Join(", ", list);
}

// Needed because string is IEnumerable<char>, to prevent
// "Hello" -> "H, e, l, l, o"
public static string PrettyPrint(string s)
{
    return s;
}

public static string PrettyPrint(object o)
{
    return o.ToString();
}

Я использую их примерно так:

public static void PrettyPrinting()
{
    object[] things = { 1, "Hello", new int[] {1, 2, 3} };

    foreach (dynamic item in things)
    {
        Console.WriteLine(PrettyPrint(item));
    }
}

Это дает следующий вывод:

1
Hello
1, 2, 3

Обратите внимание, что если я заменю ключевое слово dynamic на object, я получу следующее (все вызовы маршрутизируются через PrettyPrint(object)), чего я стараюсь избегать:

1
Hello
System.Int32[]

Таким образом, мой вопрос по сути это кодовый запах или это законно бросить object в dynamic таким образом?

Ответы [ 3 ]

6 голосов
/ 25 ноября 2011

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

3 голосов
/ 25 ноября 2011

Что касается вашего вопроса, я не уверен на 100%, так как не знаю стиль кодирования вашей команды. (Я тоже вижу небольшие комментарии;))

DuckTyping имеет свое применение - однако разработчик должен знать, что он делает, прежде чем его использовать. Иначе это похоже на бег с ножницами; ею можно злоупотреблять, как и другими ключевыми словами в системе C #.

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

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

3 голосов
/ 25 ноября 2011

Не ответ на точный вопрос, но я бы сказал, что ваш код не очень хороший, что является еще одним запахом.

В идеале вы хотите вызвать item.PrettyPrint(), и каждый элемент должен вернуть свое представление и переопределить PrettyPrint.

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

Если вы все еще хотите иметь логику для отображения каждого типа в одном классе, я бы комбинировал методы расширения с шаблоном посетителя .

Тем не менее, у меня нет среды C #, поэтому я не могу проверить, что я предлагаю. Дайте мне знать, если вы попробуете это, и если это работает.

...