什么时候使用 Duck Typing?
When to use Duck Typing?
问题
我现在已经阅读了很多关于 Duck Typing 的内容,我似乎理解了这个概念。
我不明白的是,在什么情况下放弃强类型化编程的好处而转向 Duck Typing 的好处实际上是有意义的。 在什么情况下会使用 Duck Typing 而不是接口和继承?
我的意思是,如果您无论如何都需要确保传递给方法的对象实现某些方法,为什么我不应该简单地定义一个接口?
澄清一下,我知道 Duck Typing 的工作原理。我想知道什么时候真正有意义使用它。
澄清:
在什么情况下你会使用
public bool MyMethod(dynamic obj)
而不是
public bool MyMethod(ISomeInterface obj)
//or
public bool MyMethod(SomeBaseClass obj)
C# 具有强类型是有原因的。除非您有充分的理由(例如需要 COM 互操作)使用 dynamic
类型,否则您应该像避免瘟疫一样避免使用它,否则您将面临将编译时问题转化为运行时问题的风险。 dynamic
功能强大,但容易被滥用。仔细考虑一下您是否真的 需要 动态类型 - 如果您认为需要,那么您很可能一开始就错误地解决了问题,并且需要重构您的代码。
具体回答您的问题 - 一个潜在的用例是,如果您正在编写序列化代码并需要接受反序列化的对象,例如来自 Web API 请求的反序列化 JSON 结构。这些方法需要处理给定的任何类型,在这种情况下使用 dynamic
比替代方法(即大量反射)更好。
我能想到的另一个例子是与特定于动态语言运行时的语言(例如 JavaScript、IronPython、IronRuby 等)的互操作性,并且需要编写一个方法来接受来自此类的类型语言。
来自Beginning Visual C# 2012 Programming:
For most C# code that you write, avoid the dynamic
keyword. However, if a situation arises where you need to use it, use it and love it - and spare a thought for those poor programmers of the past who didn't have this powerful tool at their disposal.
Duck-typing 在 C# 中被大量使用,大多数时候你只是没有意识到它。编译器在幕后大量使用它,用于 foreach
语句、Linq、await
和集合初始值设定项。 question 详细说明了这一点。
另一种使用鸭子类型的方法是使用 dynamic
关键字。让我们成为法郎,你应该尽可能避免它。但是与动态languages/contexts互操作非常有用。例如,假设您正在调用一个 Web 服务,该服务使用定义不明确的 json 进行应答(因此您无法轻松地将其反序列化为已知的 class)。使用 json.Net 将其解析为 JObject
并将 JObject
用作 dynamic
.
可能会容易得多
dynamic myParsedJson = JObject.Parse(json);
string theStringImLookingFor = myParsedJson.foo.bar.blah.nicestring;
另一个用例是 ASP.net MVC 视图模型。拥有动态视图模型可能非常强大。 Orchard CMS 大量使用了它,虽然一开始有点难以理解它,但它允许非常强大的用例。
COM 互操作也浮现在脑海中。
鸭子打字:
Please you do this rather than asking who you are.
示例:
Here coding should be simply define and execution. Example, here are
the things that I want the following object do something.
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());
This is the result after excuting test.
So, the above objects will do things that we requesting to do only.
Additional, I have added the question to ask them answer who they,
too. Here is the code in 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();
}
问题
我现在已经阅读了很多关于 Duck Typing 的内容,我似乎理解了这个概念。
我不明白的是,在什么情况下放弃强类型化编程的好处而转向 Duck Typing 的好处实际上是有意义的。 在什么情况下会使用 Duck Typing 而不是接口和继承?
我的意思是,如果您无论如何都需要确保传递给方法的对象实现某些方法,为什么我不应该简单地定义一个接口?
澄清一下,我知道 Duck Typing 的工作原理。我想知道什么时候真正有意义使用它。
澄清:
在什么情况下你会使用
public bool MyMethod(dynamic obj)
而不是
public bool MyMethod(ISomeInterface obj)
//or
public bool MyMethod(SomeBaseClass obj)
C# 具有强类型是有原因的。除非您有充分的理由(例如需要 COM 互操作)使用 dynamic
类型,否则您应该像避免瘟疫一样避免使用它,否则您将面临将编译时问题转化为运行时问题的风险。 dynamic
功能强大,但容易被滥用。仔细考虑一下您是否真的 需要 动态类型 - 如果您认为需要,那么您很可能一开始就错误地解决了问题,并且需要重构您的代码。
具体回答您的问题 - 一个潜在的用例是,如果您正在编写序列化代码并需要接受反序列化的对象,例如来自 Web API 请求的反序列化 JSON 结构。这些方法需要处理给定的任何类型,在这种情况下使用 dynamic
比替代方法(即大量反射)更好。
我能想到的另一个例子是与特定于动态语言运行时的语言(例如 JavaScript、IronPython、IronRuby 等)的互操作性,并且需要编写一个方法来接受来自此类的类型语言。
来自Beginning Visual C# 2012 Programming:
For most C# code that you write, avoid the
dynamic
keyword. However, if a situation arises where you need to use it, use it and love it - and spare a thought for those poor programmers of the past who didn't have this powerful tool at their disposal.
Duck-typing 在 C# 中被大量使用,大多数时候你只是没有意识到它。编译器在幕后大量使用它,用于 foreach
语句、Linq、await
和集合初始值设定项。 question 详细说明了这一点。
另一种使用鸭子类型的方法是使用 dynamic
关键字。让我们成为法郎,你应该尽可能避免它。但是与动态languages/contexts互操作非常有用。例如,假设您正在调用一个 Web 服务,该服务使用定义不明确的 json 进行应答(因此您无法轻松地将其反序列化为已知的 class)。使用 json.Net 将其解析为 JObject
并将 JObject
用作 dynamic
.
dynamic myParsedJson = JObject.Parse(json);
string theStringImLookingFor = myParsedJson.foo.bar.blah.nicestring;
另一个用例是 ASP.net MVC 视图模型。拥有动态视图模型可能非常强大。 Orchard CMS 大量使用了它,虽然一开始有点难以理解它,但它允许非常强大的用例。
COM 互操作也浮现在脑海中。
鸭子打字:
Please you do this rather than asking who you are.
示例:
Here coding should be simply define and execution. Example, here are the things that I want the following object do something.
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());
This is the result after excuting test.
So, the above objects will do things that we requesting to do only. Additional, I have added the question to ask them answer who they, too. Here is the code in 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();
}