Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/meteor/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 关于使用推广方法的实践是否发生了变化,或者是否有两种学派?_C#_Extension Methods - Fatal编程技术网

C# 关于使用推广方法的实践是否发生了变化,或者是否有两种学派?

C# 关于使用推广方法的实践是否发生了变化,或者是否有两种学派?,c#,extension-methods,C#,Extension Methods,当我第一次了解扩展方法时,我读到: 通常,我们建议您实现扩展方法 只有在你必须的时候,才有节制地。只要可能,客户端代码 必须扩展现有类型的应通过创建新类型来实现 从现有类型派生 然而,我多次看到在各种生产代码库中非常自由地使用扩展方法 诚然,我的经验并不能代表大多数人,但我想知道指导方针是否发生了变化,是否有另一种设计理念,或者我是否碰巧看到足够多的代码忽略了指导方针,让我这么想 注意:我并不是想引发一场辩论(这将立即导致问题的结束)-我真的对此感到疑惑了一段时间,我觉得我得到答案的最佳机会就在

当我第一次了解扩展方法时,我读到:

通常,我们建议您实现扩展方法 只有在你必须的时候,才有节制地。只要可能,客户端代码 必须扩展现有类型的应通过创建新类型来实现 从现有类型派生

然而,我多次看到在各种生产代码库中非常自由地使用扩展方法

诚然,我的经验并不能代表大多数人,但我想知道指导方针是否发生了变化,是否有另一种设计理念,或者我是否碰巧看到足够多的代码忽略了指导方针,让我这么想


注意:我并不是想引发一场辩论(这将立即导致问题的结束)-我真的对此感到疑惑了一段时间,我觉得我得到答案的最佳机会就在这里。我认为所有这些突出之处都是理论和实践之间的通常区别。理论上我们应该少用它们,但实际上我们不这样做。从理论上讲,我们应该做很多我们在实践中没有做的事情,在生活中,通常不仅仅是编程。

扩展类是一个好方法,但它通常不适用于使用第三方库的代码(这是生产代码的常见情况,与教育/示例代码不同)。所以,如果有意义的话,可以派生新类,但当扩展方法使代码更具可读性时,可以随意使用它们

有很多扩展方法的原因有很多:

  • 通常,您无法扩展类来添加方法,从而使产品代码更具可读性。例如,值类型(如字符串)或层次结构(如流)中的某些基类
  • 扩展方法是在不污染接口的情况下向接口添加方法的有价值的方法。LINQ是一个很好的例子,它如何产生更可读的代码
  • 一些框架建议在特定情况下使用扩展方法。也就是说,对于MVC,建议向HtmlHelper添加扩展

我认为使用扩展方法有利弊

优点:可将扩展方法视为访客模式(GoF)。因此,它利用了模式,也就是说,在不修改代码的情况下,我们可以扩展一些特性

缺点:尽管有优势,但MSDN之所以谨慎使用扩展方法,是因为,依我看,扩展方法在某个时候会导致问题。首先,如果扩展方法的对象具有与扩展不同的名称空间,我们应该知道它在哪里。这导致有时我们无法使用扩展中的一些重要特性。此外,我还看到了很多滥用扩展的代码。由于扩展是基于类型的,所以这种类型的对象有时确实不需要扩展,但是在编码时,我们应该看到很多扩展方法


[更新]

国际海事组织,关于扩展方法的滥用

  • 对扩展方法使用如此通用的类型,比如object:如果有很多对象类型的扩展方法,而扩展只关注少数类型,这会让我们恼火,因为每个对象都与这些方法链接
  • 与点运算符的链接中断或误解:让我举个例子。代码如下,我们应该依次调用Read和Write方法。但是,我们可以按相反的顺序调用这些方法

    public static string Read(this string message)
    {
        //do something
        return message;
    }
    
    public static string Write(this string message)
    {
        //do something
        return message;
    }
    
    public static void Method()
    {
        "message".Read().Write();
        "message".Write().Read(); // this is problem!
    }
    

  • 多态性不适用于扩展方法,因为它们是在编译时绑定的

    ParentClass parentClass = new ParentClass();
    ParentClass derivedClass = new DerivedClass();
    
    如果这两个类都有一个名为ExtensionMethod()的扩展方法(我确实看到过扩展方法试图模仿虚拟/重写方法),那么这两个调用都将调用父类的扩展方法:

     parentClass.ExtensionMethod();
     derivedClass.ExtensionMethod();
    
    为了实际使用派生扩展方法,您必须调用:

     ((DerivedClass)derivedClass).ExtensionMethod();
    

    “在理论上,理论和实践没有区别。在实践中有区别。”作为一个设计/最佳实践问题,这可能有一个更好的地方。我曾多次看到在生产代码中非常自由地使用任何可怕的代码实践。abuse@AaronAnodide我更新了我的答案,但请记住这是IMO。我将查看其他人的答案以归档解决方案。