关于using及foreach的一点看法,及其他- 老赵点滴- 追求编程之美- 博客园
2010-07-02 12:00 by Jeffrey Zhao, 1596 visits, , ,

,其中的观点很多我看得不太懂,某些看懂的地方(如)感觉又不太对。不过firelong还有一些观点我是明白的,便是对于增加using和foreach这样的语言特性表示不满,觉得这是让语言变得臃肿,像foreach这样的设计模式,应该有类库提供。那么我们现在就来讨论一下这方面的问题吧。

首先是using关键字,using关键字的作用是对IDisposable资源作管理,保证不会发生泄漏等问题。例如:

using (var stream = new FileStream("", FileMode.Create))
{
    // do something
}

那么,它又是怎么做的呢?其实效果是这样的:

var stream = new FileStream("", FileMode.Create);
try
{
    // do something
}
finally
{
    if (stream != null)
    {
        stream.Dispose();
    }
}

看代码不说话。我想了解一下,您是喜欢直接写第二段代码,还是写using代码呢?

foreach关键字是配合IEnumerable作遍历时使用的,比如这样的代码:

foreach (var i in source)
{
    Console.WriteLine(i);
}

其实等价于:

using (var etor = source.GetEnumerator())
{
    while (etor.MoveNext())
    {
        Console.WriteLine(etor.Current);
    }
}

咦,看上去并不复杂啊,只是多了一级缩进而已。不过您注意到没有,这里居然用到了“臃肿”的using关键字,所以说,这里的代码理应是这样写的:

var etor = source.GetEnumerator();
try
{
    while (etor.MoveNext())
    {
        Console.WriteLine(etor.Current);
    }
}
finally
{
    if (etor != null)
    {
        etor.Dispose();
    }
}

看代码不说话。我想了解一下,您是喜欢直接写第二段代码,还是写foreach代码呢?如果有两层foreach嵌套呢?

firelong同学在文章中提到,用语言支持模式是一个设计上的错误,模式应该通过框架或类库来支持。这点我保留看法,因为在我看来,模式一定程度上是为了弥补语言特性不足而设计的。因此,面向对象语言有面向对象语言的模式(如xx的GoF23),函数式编程也有函数式编程的模式(例如monad应该可以算吧)。在C#,Python,Ruby里很少谈工厂方法模式,为什么?因为它们可以将函数作为方法的参数进行传递,不需要创建一个抽象类以及多个实现。同样的,策略模式等等也是一样。因此,如果一个语言特性简化模式的使用,且这个模式非常常用,如using和foreach,那么这个语言特性很有价值。

firelong同学在文章中回复到:“如果使用这种思路,那么Visitor模式,Adaptor模式等等难道也要加进来吗”,我觉得不能这样考虑问题,这有点类似“”里的“滑坡谬误”,比如这种说法:

动物实验有损对生命的尊重。如果不尊重生命,即可能越来越容忍诸如战争及xx等等暴力行为。那么,社会将很快就会沦为战场,人人都会时刻担忧自己的生命。这将是文明的末日。为了防止出现这种可怕结果,应当立即宣布动物实验为非法。

类比一下:

添加支持模式的语法有损语言的紧凑性。如果不考虑紧凑性,即可能越来越容忍诸如支持Visitor模式等等愚蠢行为。那么,语言很快就会沦为垃圾场,人人都会时刻担忧自己的代码。这将是程序的末日。为了防止出现这种可怕后果,应该立即废除对模式的语法支持。

其实每一个语法增加都是要权衡利弊的,例如using和foreach的确会大大简化开发,于是我很欢迎这个语法功能,而且如Iterator模式的确是非常常用的。这点看一下您代码中有多少foreach便知道了——当然,有了LINQ之后,foreach用的很少,但是我很担心firelong同学是否会支持LINQ所基于的多种语法特性。还有一方面,便是能否在语法上支持Visitor等模式,我没有想明白该怎么设计这个语法。我同样想不明白的是,firelong同学说的,用框架类库来支持模式,就拿foreach和using来说,该怎么做才能像现在这样优雅呢?

其实foreach等功能都是现代语言的“标配”,Python,Ruby连Java都有支持Iterator的语法(如Python等还有如yield等Iterator生成器),而且在Java 7里,也已经加入像C#里using这样的功能,所以其实我不是很理解firelong所说的:用框架类库支持模式才是“正途”。我希望firelong同学能够补充更多理由。

至于yield和事件的设计,我将会在上讨论,因为这不是三句两句话能写清楚地内容。

好吧,我要说一些其他内容了,因为光说这些内容显得不够地道,而在一篇技术文章{zh1}谈谈,可能大家更容易容忍一些。

我实在不是很清楚,为什么firelong同学要针对我做反面例子,这次我在回复“Iterator实在太常见了,而且yield的帮助无穷大”,又被说成是“拿着一个new feature 抚摸来,抚摸去的新cool程序员”。以前的文章说的更难听,都说我败坏社区风气,骗取眼球,他见不得.NET社区这样沉沦下去,决定写博呐喊。没错,我是喜欢语言,但是您如果仔细看我的文章,就会发现我讨论的究竟是什么。我讨论的东西不是简单的语法功能,而是编程理念。我比较C#和Java,也是提到编程理念。我不断强调,我不会xx最普通的语法特性,而是考虑到引入语法以后,是否对编程思路有重要改进。我也不光在乎C#语法,我接触很多语言,要说我“拿个新Feature抚摸来抚摸去”,您看到我在反复强调C# 4.0的新特性吗?

firelong同学很注重性能,于是不知怎么就说我不重视性能了。事实上,性能相关的东西我写过很多,例如《》系列,《》系列,《》系列,《》系列,还有“”文章(如《》等等),累计几十篇。我不是不重视性能,相反我觉得我都在把性能相关的各个方面已经谈遍了。谈了很多,事实上我还一直在考虑该从哪个角度入手继续讨论,只是没有好的题材而已。而且,我强调的最多的还是基础,我不断强调算法和数据结构,还有一些如操作系统等基础课程,这从《》里便可以得知。在谈每一块时我都希望尽可能客观、正确、完整。这方面我谈的比任何人少过吗?当然,我的确没有天天强调性能,我觉得没有必要,可能这也和我没有在这方面性能问题上栽过跟头的缘故。

所以,我想对firelong同学说:您为什么总是说我重视语法,即便是我在您文章后面的评论中强调某个语言特性的作用,那不也是在您“讨论语法”的环境中进行的吗?您不喜欢被人扣屎盆子,己所不欲勿施于人,我也不想被扣——更何况,似乎我没有扣您什么东西吧。

29 条回复

  1.  2010-07-02 12:13
    难得做老赵的沙发。
    我也喜欢c#中的快捷开发
  2.  2010-07-02 12:13
    沙发,追求性能是对的,但这般固执就太过了。
  3.  2010-07-02 12:15
    顶,喜欢这样的氛围。
  4. 2010-07-02 12:18
    我以为是try/final。
    还是支持老赵。
  5. 2010-07-02 12:18
    好像不能用google登录了.
  6.  2010-07-02 12:18
    快捷开发是双刃剑
    如果不明白后面的机理的话,遇到某些情况的时候,哭都来不及。
    比如,Using在异常处理的时候,可能会覆盖先前的Exception信息
    当然存在的就是合理的,只要知道原理,使用Using还是可以的
  7. 2010-07-02 12:20
    顶4楼,我记得看过几本书讲using都是等同于try/final的
  8.  2010-07-02 12:24
    不喜欢楼主的文章.
  9.  2010-07-02 12:25
  10. [楼主]  2010-07-02 12:26
    qmigh:顶4楼,我记得看过几本书讲using都是等同于try/final的

    我确认了一下,是我错了,多谢指出,呵呵。
  11. [楼主]  2010-07-02 12:28
    Duron800:
    我以为是try/final。
    还是支持老赵。

    你没错,是我错了,我改好了,呵呵。
  12. 2010-07-02 12:30
    儿子不懂事,表见怪。
  13.  2010-07-02 12:36
    “在C#,Python,Ruby里很少谈工厂方法模式,为什么?因为它们可以将函数作为方法的参数进行传递,不需要创建一个抽象类以及多个实现。”
    我对这个比较感兴趣,怎么实现的?
  14.  2010-07-02 13:15
    非常喜欢,yield、foreach、using
  15.  2010-07-02 13:15
    挑个刺
    "所以,我相对firelong同学说:"
  16.  2010-07-02 13:22
    喜欢这种讨论气氛,无论谁对谁错,对大家都是一种进步

    同时恭喜老赵又获MVP,呵呵
  17.  2010-07-02 13:22
    有个老赵的出面,可以让更少的新人误解C#。避免了别人只看到了firelong的说法而对C#充满误解。
  18.  2010-07-02 13:26
    richardzeng:
    “在C#,Python,Ruby里很少谈工厂方法模式,为什么?因为它们可以将函数作为方法的参数进行传递,不需要创建一个抽象类以及多个实现。”
    我对这个比较感兴趣,怎么实现的?

    因为工厂方法封装了变化,但是你用函数(他本身就是变化的部分。
    public void FactoryAction(Action<T> action)
    {
        //不变的部分
        action(T)//原工厂封装的变化部分如Switch的那部分,或if else。
        //不变的部分
    }
    
  19.  2010-07-02 13:33
    在看文章的时候突然想到一个问题:是不是因为语言越来越复杂,所以出现了越来越复杂的设计模式?将来会不会是一个恶性循环:语言越来越强大,特性越来越多,设计模式也越来越复杂?
  20.  2010-07-02 13:42
    其实都是语法糖,又不影响性能,何来“臃肿”之说呢。。。不想用大可不用,跳出来毫无根据地说设计有问题,实在是让人无语。
  21.  2010-07-02 13:45
    up
  22.  2010-07-02 13:48
    如果为IEnumerable实现一个ForEach扩展方法,不就不需要foreach关键字了吗?
    我也不大喜欢把语言和类库混合在一起设计的做法.
    using关键字和foreach不一样,这个关键字不牵扯到类库.
  23.  2010-07-02 13:48
    foreach用起来简单,但是遍历过程中集合无法更改,因此应用的场景会受到一点限制。我觉得这种语法上的问题,不是太大的问题。我觉得在.Net3.5(没用过4.0)中集成上WF/WPF之类的东西没多大必要。
  24.  2010-07-02 13:52
    顶一老赵,辛苦的了。分享东西也要时间。
  25. [楼主]  2010-07-02 13:52
    Birdshover
    遍历集合过程中不能修改和foreach无关,就算不用foreach,而是直接使用IEnumerator,MoveNext之类的,不能修改的集合还是不能修改的。
  26. [楼主]  2010-07-02 13:55
    013231:
    如果为IEnumerable实现一个ForEach扩展方法,不就不需要foreach关键字了吗?
    我也不大喜欢把语言和类库混合在一起设计的做法.
    using关键字和foreach不一样,这个关键字不牵扯到类库.

    如果有扩展方法和Lambda表达式,以及闭包等特性,的确可以不用foreach。不过从理论上说,这个做法会有性能损失(主要是闭包造成的),因为我不知道性能至上和语言简单主义者能否接受这样的语言特性,呵呵。

    至于using,和foreach也是一回事情,你也可以写这样的代码:

    new FileStream(...).Using(stream =>
    {
        ...
    });
    
  27.  2010-07-02 13:57
    针对这个话题而不是老赵的帖子说几句

    喜欢C#就喜欢呗,不喜欢就不喜欢呗,那是个人的事,没必要说服别人。那些被说服的,或者两边倒的,说明还没搞清楚自己喜不喜欢,让他们自己慢慢搞好了。

    软件开发需要经验,而经验都是从错误和失败中得来的,不是从别人的帖子里得来的。

    三天两头讨论这样的话题,cnblogs的价值,唉……不说了
  28.  2010-07-02 13:58
    老赵你还是歇歇吧,借陈志武教授的话就是:“哪有科学家写书驳斥跳大神儿的!”
  29.  2010-07-02 14:26
    支持老赵,看了老赵很多文章,感觉他很重视性能的
  30.  2010-07-02 14:39
    老赵啊
    您这是对牛弹琴
    有些人脑子里是没有逻辑的
    特别是那些“firelong们”

    王半仙:老赵你还是歇歇吧,借陈志武教授的话就是:“哪有科学家写书驳斥跳大神儿的!”


    这句话太对了。
郑重声明:资讯 【关于using及foreach的一点看法,及其他- 老赵点滴- 追求编程之美- 博客园】由 发布,版权归原作者及其所在单位,其原创性以及文中陈述文字和内容未经(企业库qiyeku.com)证实,请读者仅作参考,并请自行核实相关内容。若本文有侵犯到您的版权, 请你提供相关证明及申请并与我们联系(qiyeku # qq.com)或【在线投诉】,我们审核后将会尽快处理。
—— 相关资讯 ——