Когда использовать Duck Typing?
вопрос
теперь я много читал о печатании утки, и я, кажется, понимаю концепцию.
чего я не понял, так это того, в каком случае имеет смысл отказаться от преимуществ сильного типизированного программирования к преимуществам типизации утки. в каком случае вместо интерфейсов и наследования будет использоваться типирование утки?
Я имею в виду, если вам все равно нужно обеспечить, чтобы объект, переданный методу, реализовывал определенные методы, почему бы мне просто не определить интерфейс?
просто для ясности, я знаю, как работает Утиная печать. Я хочу знать, когда это действительно имеет смысл использовать его.
пояснение:
в этом случае вы бы использовали
public bool MyMethod(dynamic obj)
вместо
public bool MyMethod(ISomeInterface obj)
//or
public bool MyMethod(SomeBaseClass obj)
3 ответов
C# имеет сильную типизацию по какой-то причине. Если у вас нет веской причины (например, необходимости com-взаимодействия) использовать dynamic
type, вы, вероятно, должны избегать его, как чумы, или вы рискуете превратить проблемы времени компиляции в Проблемы времени выполнения. dynamic
является мощным, но легко злоупотреблять. Подумайте долго и упорно, если вы действительно нужно динамическая типизация - если вы думаете, что есть, есть шанс, что ты подходишь к проблеме не так, чтобы начать с, и нужно перестраивать код.
чтобы конкретно ответить на ваш вопрос-один из возможных вариантов использования был, если вы писали код сериализации и должны были принять десериализованный объект, например десериализованную структуру JSON из запроса веб-API. Такие методы должны были бы обрабатывать любой тип, заданный им, что является ситуацией, в которой использование dynamic
- Это лучше, чем альтернатива (т. е. грузовик-груз отражения).
другой пример, который я могу придумать, - это взаимодействие с языками конкретно на динамические язык (например. В JavaScript, Установить IronPython, IronRuby, ...), и нужно написать метод, принимающий типы из таких языков.
С Начало Программирования Visual C# 2012:
для большинства кода C#, который вы пишете, избегайте
dynamic
ключевое слово. Однако, если возникает ситуация, где вы нужно использовать его, использовать его и любить его - и подумал об этих бедных программистов прошлого, не было этого мощный инструмент в их распоряжении.
Duck-typing часто используется в C#, вы просто не знаете об этом большую часть времени. Компилятор использует его много под крышкой, для foreach
операторы, для Linq, для await
и инициализаторы коллекций. Это вопрос подробности это красиво.
другой способ для вас, чтобы использовать утку набрав с dynamic
ключевое слово. И давайте будем Франком, вы должны избегать этого как можно больше. Но очень полезно взаимодействовать с динамическими языками / контекстами. Например, предположим, вы вызываете веб-службу, которая отвечает с плохо определенным json (поэтому вы не можете десериализовать ее легко в известный класс). Это может быть намного проще для вас toparse это как JObject
используя json.Net, и использовать JObject
как dynamic
.
dynamic myParsedJson = JObject.Parse(json);
string theStringImLookingFor = myParsedJson.foo.bar.blah.nicestring;
другой вариант использования находится в ASP.net MVC Viewmodels. Наличие динамической viewmodel может быть очень мощным. The Orchard CMS сильно использует его, и даже thoug немного трудно обернуть голову вокруг это во-первых, это позволяет очень мощные случаи использования.
com interop приходит на ум, а также.
Утиной Типизацией:
пожалуйста, сделайте это, а не спрашивайте, кто вы.
пример:
здесь кодирование должно быть просто определено и выполнено. Пример, вот вещи, которые я хочу, чтобы следующий объект что-то делал.
Please("Walk", new Dog());
Please("Run", new Duck());
Please("Fly", new Cup());
Please("Fly", new Bird());
Please("Fly", new Man());
Please("Walk", new Man());
Please("Run", new Man());
это результат после excuting испытания.
Так, вышеперечисленные объекты будут делать то,что мы просим делать только. Кроме того, я добавил вопрос, чтобы спросить их, кто они, тоже. Вот код на C#.
private void Please(string Action, object Obj)
{
MethodInfo method = Obj.GetType().GetMethod(Action, Type.EmptyTypes, null);
if (method != null)
{
method.Invoke(Obj, new object[] { });
}
else
{
Console.WriteLine(string.Format("I can not {0} because {1}", Action, WhoAreYou(Obj)));
}
}
private string WhoAreYou(object unknown)
{
string question = "WhoAreYou";
MethodInfo whoAreYou = unknown.GetType().GetMethod(question, Type.EmptyTypes, null);
return whoAreYou.Invoke(unknown, new object[] { }).ToString();
}