代码之家  ›  专栏  ›  技术社区  ›  John M Gant aman_novice

添加我认为应该在框架中的扩展方法:坏主意?

  •  2
  • John M Gant aman_novice  · 技术社区  · 15 年前

    我希望在.NET框架中有一个特定的功能,但不是。我希望有一个dbdatareader.getString(或getdatetime、getInt32等)重载接受字段名而不是索引。使用字段名可以简化IMO的维护,但getxxx方法只接受字段位置。

    我可以通过使用扩展方法将这些添加到我的项目中(至少在有限的容量中以满足我的即时需求),但有些地方感觉不对劲。除了我必须为每个新项目重复这个过程的明显问题之外,还有什么理由不做我想做的事情吗?

    例如,我是否正沿着一条下坡路,试图重写框架以适应我的突发奇想?我会让那个不得不修改我的代码(可能是我)的可怜的家伙抓耳挠腮想弄清楚到底发生了什么事吗?我是否违反了OOP的一些核心原则?

    只是寻求指导和观点。谢谢。

    5 回复  |  直到 14 年前
        1
  •  6
  •   Scott Dorman    15 年前

    这正是扩展方法能够解决的场景之一。您需要的功能在您无法控制的类型上尚不可用。

    至于在每个项目中复制代码,您需要做的是创建一个类库项目来存储这样的公共/共享代码,然后在每个解决方案中包含该项目并使用项目引用,或者编译项目,将生成的程序集放在共享位置并将其作为文件项目引用包含。

    请记住,扩展方法只有在“引入范围”时才可用。这意味着,如果您有一个扩展方法定义为:

    namespace CustomExtensions
    {
        public static class StringExtensions
        {
           public static string InvariantToString(this int value)
           {
              return value.ToString(System.Globalization.CultureInfo.InvariantCulture);
           }
        }
    }
    

    它在任何字符串值上都不可见,除非代码文件包含带有using指令的customxtensions命名空间。

    因此,建议您 将自己的扩展放在.NET框架定义的命名空间中,而不是使用自己的命名空间。这样做可以最大限度地减少混淆的可能性,因为除非将扩展显式地引入范围,否则扩展将不可用。

    另外,请记住,如果您提供的扩展方法 完全相同的签名 作为“内置”方法,扩展方法将 从未 可见或可调用-内置方法 总是 优先考虑。如果Microsoft决定将该功能包含在更高版本的框架中,并使用 完全相同的签名 您选择的扩展方法将不再被调用。

    定义扩展方法时,实际上并没有重新定义要扩展的基础类型,因此没有自己的“单独版本”。扩展方法提供的所有方法都是在静态类中调用静态方法的一种更方便、更自然的方法。实际上,使用上面的示例扩展方法,这些调用是等效的:

    int i = 42;
    Console.WriteLine(i.InvariantToString());
    Console.WriteLine(StringExtensions.InvariantToString(i));
    

    虽然微软确实对框架中应该包含或不包含什么进行了大量的思考,但是他们无法了解可能会驱动您对某些功能的特定需求的特定用例。是的,大多数时候他们都做得很好,并提供“开箱即用”的功能,但其他时候他们没有(一个很好的例子是缺少InvariantToString()方法)。

        2
  •  2
  •   Daren Thomas    15 年前

    实际上,我认为.NET做得相当好:要使扩展方法工作,必须使用在中定义的名称空间。Visual Studio将向您显示方法的来源等。

    无论如何,如果您找到了一个使您的代码更易于阅读/维护的抽象,那么就开始吧!

        3
  •  1
  •   John Fisher    15 年前

    考虑以下问题的答案,然后继续创建扩展方法。使您的工作更容易是扩展方法成为语言的一部分的原因。

    1. 您应该将扩展方法包装到一个特定于这些扩展的名称空间中,这样开发人员就可以随心所欲地包含或排除这些方法。
    2. 将这些扩展放到一个单独的dll中可以让您在不复制项目之间的文件或代码的情况下重用它们。
    3. 别忘了好好考虑一下设计。如果其他人会使用它,你要把它磨光一点,确保他们能快速、轻松地使用它。这也是一种可能导致性能问题的特性,因此设计它的方式允许您在不改变扩展方法使用的情况下进行性能调整。
        4
  •  1
  •   Ben Lesh    15 年前

    扩展是句法上的糖。基本上,你所做的就是创建一些静态方法,就像其他静态方法一样…除了一个例外,他们为您节省了更多的输入。

    也就是说,如果你( 你的团队 如果你有一个!)确定某些扩展方法可以保存( 你的团队 )时间和努力,然后添加它们!

    注意这个想法:

    • 确保将方法命名为不会与其他框架功能混淆的名称。(像stream-tostream(这个对象o)这样的扩展方法肯定会很烦人!)
    • 注意不要添加太多的内容,这样会使你的智能感知变得杂乱无章,从而减慢你的速度!如果情况如此,那么将它们作为静态方法保留就可以了。
    • 只有当你在你的环境中经常使用这种类型时才添加它们。例如,我为我们的环境提供了一个graphicsPath.serialize()扩展程序,因为我几乎总是要为我们正在处理的内容序列化我的graphicsPath,我经常这样做。否则,对序列化程序类的简单调用就足够了。
    • 别忘了,如果你有一个扩展方法用于你自己的内部类,并且有人在这个类上用相同的名称创建了一个方法,那么你的扩展就会被击败!
        5
  •  0
  •   Marcel Jackwerth    15 年前

    在Java中,选择下载和编译自己的JRE。或者通过继承扩展类。现在重新考虑一下,在你的情况下,扩展张力方法不是最好的方法吗?

    我还建议您创建自己的“MyNiftyLibrary”,将此代码存储到中。它是我存储所有“StringHelper”、“…Helper”代码的地方。把它当作你的个人.NET插件。