【问题标题】:When to use Duck Typing?何时使用 Duck Typing?
【发布时间】:2015-08-17 14:26:54
【问题描述】:

问题

我现在已经阅读了很多关于 Duck Typing 的内容,并且我似乎理解了这个概念。

我不明白的是,在什么情况下,放弃强类型化编程的好处而改用 Duck Typing 的好处才有意义。 在什么情况下会使用 Duck Typing 而不是接口和继承?

我的意思是,如果您无论如何都需要确保传递给方法的对象实现某些方法,我为什么不应该简单地定义一个接口?

为了清楚起见,我知道 Duck Typing 的工作原理。我想知道什么时候使用它才真正有意义。

澄清:

你会在什么情况下使用

public bool MyMethod(dynamic obj)

而不是

public bool MyMethod(ISomeInterface obj)
//or
public bool MyMethod(SomeBaseClass obj)

【问题讨论】:

  • 考虑到在所有 .NET 中只有四五个鸭子类型(foreachawait、LINQ、集合初始化器),而且它们都是在编译器端实现的,我没有理解你的问题。
  • haacked.com/archive/2007/08/19/… - 这里有一个标题为“当你可能使用 Duck Typing 时非常有用的用例”的部分
  • 如果您不想在地狱中燃烧,请不要使用dynamic。这是我自己的意见。而在我编写的 150 万个 os 源代码中,dynamic 的使用次数有 2-3 次。
  • 如果你认为你需要它,你就不需要它。如果您毫无疑问地知道自己确实需要它,那么您可能仍然不需要它,只是没有正确应用继承原则。
  • 避免,避免,避免!但是...我写了很多使用这个概念的 DynamORM,从那次经验来看,我必须说这几乎是一件坏事。使用前请思考 10 次。当您制作一些后端并且不知道最终开发人员向您抛出什么问题时,动态很酷,例如您必须处理的 COM 或通用结构/类。

标签: c# duck-typing


【解决方案1】:

C# 具有强类型是有原因的。除非您有正当的理由(例如需要 COM 互操作)来使用 dynamic 类型,否则您可能应该像避免瘟疫一样避免使用它,否则您将面临将编译时问题变成运行时问题的风险。 dynamic 功能强大,但容易被滥用。仔细考虑您是否真的需要动态类型 - 如果您认为有,那么您可能一开始就错误地处理了问题,并且需要重构您的代码。

专门回答您的问题 - 一个潜在的用例是,如果您正在编写序列化代码并需要接受反序列化的对象,例如来自 Web API 请求的反序列化 JSON 结构。此类方法需要处理给定给它们的任何类型,在这种情况下,使用 dynamic 比其他方法更好(即一卡车的反射)。

我能想到的另一个例子是与专门针对动态语言运行时的语言(例如 JavaScript、IronPython、IronRuby 等)的互操作性,并且需要编写一个接受来自这些语言的类型的方法。

来自Beginning Visual C# 2012 Programming

对于您编写的大多数 C# 代码,请避免使用 dynamic 关键字。但是,如果出现您需要使用它的情况,请使用它并爱上它 - 并为过去没有这个强大工具的可怜程序员留个心眼。

【讨论】:

  • 如果它走路像鸭子,叫起来像鸭子,那么它可能就是我。
【解决方案2】:

Duck-typing 在 C# 中被大量使用,您只是大部分时间都没有意识到它。编译器在后台大量使用它,用于foreach 语句、Linq、await 和集合初始值设定项。这个question 很详细。

使用鸭子类型的另一种方法是使用 dynamic 关键字。让我们成为法郎,你应该尽可能避免它。但是与动态语言/上下文互操作非常有用。例如,假设您正在调用一个 Web 服务,该服务以定义不明确的 json 进行响应(因此您不能轻松地将其反序列化为已知类)。使用json.Net 将其解析为JObject 并将JObject 用作dynamic 可能会容易得多。

dynamic myParsedJson = JObject.Parse(json);
string theStringImLookingFor = myParsedJson.foo.bar.blah.nicestring;

另一个用例是在 ASP.net MVC Viewmodels 中。拥有动态视图模型可能非常强大。 Orchard CMS 大量使用它,尽管一开始有点难以理解它,但它提供了非常强大的用例。

COM 互操作也浮现在脑海中。

【讨论】:

    【解决方案3】:

    鸭子打字:

    请你这样做,而不是问你是谁。

    示例:

    这里的编码应该是简单的定义和执行。例子,这里是 我想让下面的对象做一些事情。

        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());
    

    这是执行测试后的结果。

    所以,上面的对象只会做我们要求做的事情。 另外,我添加了一个问题,要求他们回答他们是谁, 也。这是 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();
    }
    

    【讨论】:

    • 分享这个概念。它指出了一个有趣的用例。
    猜你喜欢
    • 2014-11-29
    • 1970-01-01
    • 2019-09-18
    • 1970-01-01
    • 2016-10-29
    • 1970-01-01
    • 2016-05-06
    • 1970-01-01
    • 2011-03-23
    相关资源
    最近更新 更多