代码之家  ›  专栏  ›  技术社区  ›  thatismatt

C#扩展方法-多远才算太远?

  •  15
  • thatismatt  · 技术社区  · 17 年前

    Rails为Ruby引入了一些核心扩展,如 3.days.from_now 它会回来,就像你预期的三天后的约会一样。使用C#中的扩展方法,我们现在可以做类似的事情:

    static class Extensions
    {
        public static TimeSpan Days(this int i)
        {
            return new TimeSpan(i, 0, 0, 0, 0);
        }
    
        public static DateTime FromNow(this TimeSpan ts)
        {
            return DateTime.Now.Add(ts);
        }
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(
                3.Days().FromNow()
            );
        }
    }
    

    或者:

    static class Extensions
    {
        public static IEnumerable<int> To(this int from, int to)
        {
            return Enumerable.Range(from, to - from + 1);
        }
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            foreach (var i in 10.To(20))
            {
                Console.WriteLine(i);
            }
        }
    }
    

    这从根本上来说是错误的,还是有时候这是一个好主意,比如在Rails这样的框架中?

    7 回复  |  直到 17 年前
        1
  •  8
  •   Andrew Hare    17 年前

    我非常喜欢扩展方法,但我确实觉得,当它们在LINQ之外使用时,它们会以牺牲可维护性为代价提高可读性。

    拿 3.Days().FromNow() 作为一个例子。这是非常有表现力的,任何人都可以阅读这段代码并告诉你它的确切功能。这真是一件美丽的事情。作为程序员,我们很乐意编写自我描述和富有表现力的代码,这样它几乎不需要注释,阅读起来很愉快。在这方面,这一准则至关重要。

    然而,作为程序员,我们也对后代负责,而那些在我们之后的人将花费大部分时间试图理解这段代码是如何工作的。我们必须小心,不要过于表达,以至于调试代码需要在无数扩展方法之间来回切换。

    扩展方法掩盖了“如何”来更好地表达“什么”。我想这使它们成为一把双刃剑,最好(像所有东西一样)适度使用。

        2
  •  6
  •   peterchen    17 年前

    首先,我的直觉: 3.Minutes.from_now 看起来很酷,但并没有说明为什么扩展方法是好的。这也反映了我的总体看法:很酷,但我从来没有真正错过过它们。


    问题:是 3.Minutes 时间跨度还是角度?

    通过using语句“通常”引用的命名空间只影响类型,现在它们突然决定了什么 3.会议纪要 意味着。

    所以最好的办法是“不要让他们逃跑”。
    一个可能被引用的命名空间中的所有公共扩展方法最终都是“某种全局的”——所有潜在的问题都与之相关。将它们保留在程序集内部,或将它们放入单独的命名空间中,该命名空间单独添加到每个文件中。

        3
  •  5
  •   mackenir    17 年前

    就我个人而言,我喜欢int.To,我对int.Days感到矛盾,我不喜欢TimeSpan。从现在开始。

    我不喜欢我所看到的“流畅”接口的流行,这种接口允许你编写伪英语代码,但通过实现具有孤立名称的方法来实现。

    例如,这对我来说读起来不太好:

    TimeSpan.FromSeconds(4).FromNow()
    

    显然,这是一件主观的事情。

        4
  •  1
  •   Cœur Gustavo Armenta    7 年前

    在这个问题上,我同意西施的观点,并倾向于保守派。Rails内置了这种东西,所以它从来没有那么令人困惑。当你编写“days”和“fromnow”方法时,并不能保证你的代码没有bug。此外,您正在向代码添加依赖项。如果将扩展方法放在自己的文件中,则每个项目都需要该文件。在项目中,您需要在需要时包含该项目。

    尽管如此,对于非常简单的扩展方法(比如Jeff对 "left" 或者这是att在其他框架/世界中使用days.fromnow的用法,我认为这没问题。任何熟悉日期的人都应该理解“3.days().fromnow()”的意思。

        5
  •  0
  •   Szymon Rozga    17 年前

    我站在保守的一边,至少目前是这样,我反对扩展方法。对我来说,语法糖并不那么重要。我认为对于初级开发人员来说,如果他们是C#新手,这也可能是一场噩梦。我宁愿将扩展封装在我自己的对象或静态方法中。

    如果你打算使用它们,请不要过度使用它们,以免给自己带来方便,但会惹恼任何接触你代码的人。 :-)

        6
  •  0
  •   Jon Smock    17 年前

    每种语言都有自己的 观点 关于语言应该是什么。Rails和Ruby的设计都有自己非常不同的观点。PHP和C(++/#)有明显不同的观点。..Visual Basic也是如此(尽管我们显然不喜欢他们的风格)。

    平衡在于拥有许多易于阅读的内置函数,而不是对一切的实质性控制。我不希望有太多的函数,以至于每次你想做任何事情时都必须去查找(而且臃肿的框架肯定会有性能开销),但我个人喜欢Rails,因为它为我节省了很多开发时间。

    我想我在这里要说的是,如果你正在设计一门语言,那么就要表明立场,从那里开始,构建你(或 你的目标开发人员最常使用 .

        7
  •  0
  •   Mitchell Gilman    17 年前

    我个人的偏好是现在谨慎使用它们,并等待微软和其他大型组织如何使用它们。如果我们开始看到很多代码,教程和书籍都会使用像3.Days()这样的代码。FromNow()经常使用它。如果只有少数人使用它,那么你就有可能让你的代码过于难以维护,因为没有足够的人熟悉扩展的工作原理。

    另外,我想知道普通for循环和foreach循环的性能如何比较?第二种方法似乎会给计算机带来很多额外的工作,但我对这个概念还不够熟悉,无法确定。