Hello World
Spiga

拯救C# 2.0,但是我们真做的到吗?

2009-06-27 18:55 by 老赵, 25266 visits

似乎还有不少项目在用C# 2.0(本文最后我们来做一个调查),但是C# 2.0的生产力实在不如C# 3.0——如果您不信,那么一会儿就会意识到这一点。有朋友认为语言能力不重要,有了好用的框架/类库也可以有很高的生产力。所以这篇文章,我们就设法使用“类库”来弥补C# 2.0的缺陷。

但是,我们真做的到吗?

C# 2.0之殇

C# 2.0较C# 1.0来说是一个突破,其中引入了泛型,以及匿名方法等新特性。如果前者还可以说是平台的增强,而语言只是个“辅助”的话,而后者则百分之一百是编译器的魔法了。别小看这个特性,它为C# 3.0的高生产力踏出了坚实的一步——不过还是差了很多。例如,我们有一个要求:“把一个字符串数组中的元素转化为整数,再将其中的偶数放入一个List<int>容器中”。如果是C# 3.0,这是再简单不过的功能:

string[] strArray = { "1", "2", "3", "4" };
var even = strArray.Select(s => Int32.Parse(s)).Where(i => i % 2 == 0).ToList();

那么对于C# 2.0(当然对于C# 1.0也一样),代码又该怎么写呢?

List<int> even = new List<int>();
foreach (string s in strArray)
{
    int i = Int32.Parse(s);
    if (i % 2 == 0)
    {
        even.Add(i);
    }
}

有人说函数式编程有什么用,C# 3.0就是个很好的证明。C# 3.0中引入了Lambda表达式,增强了在语言中构造匿名方法的能力——这是一个语言中函数式编程特性的必备条件。C# 3.0的实现与C# 2.0相比,可读性高,可以直接看出转化、过滤,以及构造容器的过程和标准。由于语言能力的增强,程序的表现能力得到了很大的提高,在很多时候,我们可以省去将一些代码提取为独立方法的必要。当然,即使您将其提取为额外的方法,C# 3.0也可以让您写出更少的代码。

如果您觉得以上代码的差距还不是过于明显的话——那么以下功能呢?

int[] intArray = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

// 所有偶数的平均数
var evenAverage = intArray.Where(i => i % 2 == 0).Average();

// 都是偶数?
var allEven = intArray.All(i => i % 2 == 0);

// 包含偶数?
var containsEven = intArray.Any(i => i % 2 == 0);

// 第4到第8个数
var fourthToEighth = intArray.Skip(3).Take(5);

如果您使用C# 2.0来写,您会怎么做?

拯救C# 2.0

C# 3.0通过引入了函数式编程特性大幅增强了语言的生产力。如果说C# 2.0和Java还没有太大差距的话,那么C# 3.0已经将Java甩开地太远太远。不过真要说起来,在Java中并非不可以加入函数式编程的理念。只不过,如果没有足够的语言特性进行支持(如快速构造匿名函数、闭包、一定程度的类型推演等等),函数式编程对于某些语言来说几乎只能成为“理念”。不过现在,我们暂且先放下对“函数式编程”相关内容的探索,设法拯救C# 2.0所缺失的生产力吧。

C# 3.0中可以使用Lambda表达式构造一个匿名函数,这个能力其实在C# 2.0中也有。我们姑且认为这点不是造成差距的主要原因,那么有一点是C# 2.0绝对无法实现的,那就是“扩展方法”。C# 3.0中的扩展方法,可以“零耦合”地为一个,甚至一系列类型添加“实例方法”。当然,这也是编译器的功能,实际上我们只是定义了一些静态方法而已。这一点在C# 2.0中还是可以做到的:

public class Enumerable
{
    public static IEnumerable<T> Where<T>(Func<T, bool> predicate, IEnumerable<T> source)
    {
        foreach (T item in source)
        {
            if (predicate(item))
            {
                yield return item;
            }
        }
    }

    public static IEnumerable<TResult> Select<T, TResult>(Func<T, TResult> selector, IEnumerable<T> source)
    {
        foreach (T item in source)
        {
            yield return selector(item);
        }
    }

    public static List<T> ToList<T>(IEnumerable<T> source)
    {
        List<T> list = new List<T>();
        foreach (T item in source)
        {
            list.Add(item);
        }

        return list;
    }
}

于是现在,我们便可以换种写法来实现相同的功能了:

string[] strArray = { "1", "2", "3", "4" };

List<int> even = 
    Enumerable.ToList(
        Enumerable.Where(
            delegate(int i) { return i % 2 == 0; },
            Enumerable.Select(
                delegate(string s) { return Int32.Parse(s); },
                strArray)));

即使您可以接受delegate关键字构造匿名函数的能力,但是上面的做法还是有个天生的缺陷:逻辑与表现的次序想反。我们想表现的逻辑顺序为:转化(Select)、过滤(Where)、及容器构造(ToList),C# 3.0所表现出的顺序和它相同,而C# 2.0的顺序则相反。由于语言能力的缺失,这个差距无法弥补。很多时候,语言的一些“小功能”并不能说是可有可无的特性,它很可能直接决定了是否可以用某种语言来构造Internal DSL或进行BDD。例如,由于F#的灵活语法,FsTest使得开发人员可以写出"foobar" |> should contains "foo"这样的语句来避免机械的Assert语法。同样,老赵也曾经使用actor <= msg这样的逻辑来替代actor.Post(msg)的显式调用方式

封装逻辑

既然没有“扩展方法”,我们要避免静态方法的调用形式,那么就只能在一个类中定义逻辑了。这点并不困难,毕竟在API的设计发展至今,已经进入了关注Fluent Interface的阶段,这方面已经积累了大量的实践。于是我们构造一个Enumerable<T>类,封装IEnumerable<T>对象,以此作为扩展的入口:

public class Enumerable<T>
{
    private IEnumerable<T> m_source;

    public Enumerable(IEnumerable<T> source)
    {
        if (source == null) throw new ArgumentNullException("source");
        this.m_source = source;
    }

    ...
}

并以此定义所需的Select和Where方法:

public Enumerable<T> Where(Func<T, bool> predicate)
{
    if (predicate == null) throw new ArgumentNullException("predicate");
    return new Enumerable<T>(Where(this.m_source, predicate));
}

private static IEnumerable<T> Where(IEnumerable<T> source, Func<T, bool> predicate)
{
    foreach (T item in source)
    {
        if (predicate(item))
        {
            yield return item;
        }
    }
}

public Enumerable<TResult> Select<TResult>(Func<T, TResult> selector)
{
    if (selector == null) throw new ArgumentNullException("selector");
    return new Enumerable<TResult>(Select(this.m_source, selector));
}

private static IEnumerable<TResult> Select<TResult>(IEnumerable<T> source, Func<T, TResult> selector)
{
    foreach (T item in source)
    {
        yield return selector(item);
    }
}

这些扩展都是些高阶函数,也都有延迟效果,相信很容易理解,在此就不多作解释了。在这里我们直接观察其使用方式:

List<int> even = new Enumerable<string>(strArray)
    .Select(delegate(string s) { return Int32.Parse(s); })
    .Where(delegate(int i) { return i % 2 == 0; })
    .ToList();

不知道您对此有何感觉?

老赵对此并不满意,尤其是和C# 3.0相较之下。我们虽然定义了Enumerable封装类,并提供了Select和Where等逻辑,但是由于匿名函数的构造还是较为丑陋。使用delegate构造匿名函数还是引起了不少噪音

  • 与JavaScript的function关键字,和VB.NET的Function关键字一样,C# 2.0在构造匿名函数时无法省确delegate关键字。
  • 与C# 3.0中的Lambda表达式相比,使用delegate匿名函数缺少了必要的类型推演。
  • 使用delegate构造匿名函数时必须提供完整的方法体,也就是只能提供“语句”,而不能仅为一个“表达式”,因此return和最后的分号无法省确。

我们设法拯救C# 2.0,但是我们真的做到了吗?

框架/类库真能弥补语言的生产力吗?

再谈Java语言

老赵对与Java语言印象非常差,至今没有任何改变——不知这次还会有多少人使用“Java平台”进行反驳。

博客园中的一位高人也曾经在文章末尾提问“您是否特别讨论某种语言,请您仔细思考一下,这个结论站的住脚吗?”——虽然是“疑问句”,但是人人都听的出其中的意思嘛!在国内经常听到一些说法,说比较语言,谈论语言是没有价值的。那么讨论哪些东西有价值呢?编程能力(这个的确很重要),解决方案(例如XX编程三百问)……哦,还有“业务”(技术无用论?)。总之,讨论语言,评价语言在国内社区显得很“浮躁”,没有层次。其实对语言的讨论在行业内是非常重要的一个方面,许多国内“精英”无比崇拜外国技术人员们对这些话题的争论才叫一个热烈。老赵搞不懂的是,为什么这些精英一边看轻国内技术人员,一边崇拜老外,一边却看轻老外也喜欢讨论的内容呢?

“月亮总是外国的圆”,这句话说得真tmd有道理呀。

我们要反对的不应该是“讨论语言”,而是应该反对讨论语言的不良目的。例如有人讨论语言的目的是为了“彰显品质”,是为了嘲笑他人,是为了找出哪种语言“更有前途”,这些才应该是我们需要强烈抵制的。一个类比就是:搓麻将没有错,错的是用麻将来赌博。“做什么”和“怎么做”,两者是有很多区别的。

C# 3.0中对于集合的操作方式的确好用。Java社区也构造一个项目lambdaj,希望可以缓解一下这方面操作的不便。这个项目很有趣,对于编写Fluent Interface是一个不错的参考。

当然,如果真要老赵选择,我会使用Scala,它真比Java好多了。

总结

本文谈论了C# 2.0在集合操作方面与C# 3.0的差距。老赵提出了一种解决方法,但是自认为效果不甚理想。不过聊胜于无,如果可以把C# 3.0这方面的功能移植过来,也算是略有功德的事情——但是最好还是尽快升级到C# 3.0吧。C# 4.0?这的确是个好东西,不过光从语言层面上讲,其中的新特性(如dynamic和协变逆变)对我没有太大的吸引力。不过.NET 4.0对于框架类库的增强的确非常引人注目,如果可以的话,我也希望可以尽快使用.NET 4.0进行开发。

最后我们来做一个简单的调查:http://www.micropoll.com/akira/mpview/617003-179427

Creative Commons License

本文基于署名 2.5 中国大陆许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名赵劼(包含链接),具体操作方式可参考此处。如您有任何疑问或者授权方面的协商,请给我留言

Add your comment

140 条回复

  1. .easycode[未注册用户]
    *.*.*.*
    链接

    .easycode[未注册用户] 2009-06-27 21:57:00

    顶一个先 在用Lambda表达式 非常不错

  2. jacky song
    *.*.*.*
    链接

    jacky song 2009-06-27 22:11:00

    一直在用2.0,3.0还未接触,但从老赵这篇文章,我只能看出3.0是比2.0简洁多了,提高开发效率是肯定的,不知道性能会不会有所降低,回头学了去测试一下

  3. 老赵
    admin
    链接

    老赵 2009-06-27 22:12:00

    @jacky song
    什么东西的性能?
    很多东西是语法糖,编译出来的东西是一样的。
    例如C# 3.0里用lambda表达式和2.0里用delegate,完全等价的。

  4. 没办法啊。[未注册用户]
    *.*.*.*
    链接

    没办法啊。[未注册用户] 2009-06-27 22:14:00

    2.0的包在没装。net的机子上引用打包才十来M
    但是3.5的就到了100多M了,这个选择很无奈啊

  5. 老赵
    admin
    链接

    老赵 2009-06-27 22:15:00

    @没办法啊。
    嗯,如果是做客户端程序的话,的确是个问题。

  6. xiaotie
    *.*.*.*
    链接

    xiaotie 2009-06-27 22:18:00

    >> 框架/类库真能弥补语言的生产力吗?

    看你做什么了,目前影响我的生产力的主要是类库(C#的类库太缺了。最近新做一个图像处理的小项目,幸亏在偶然情况下找到一个好用的类库,然后马上我把写的代码删的删变的变,换成对方的,原本预计6-10天完成的项目,3天都搞定了)。

    也曾经一段时间把System.Core掏出来放进项目,但对效率提高不明显。

  7. 22xx[未注册用户]
    *.*.*.*
    链接

    22xx[未注册用户] 2009-06-27 22:19:00

    对老赵反北大青鸟表示支持,现在的培训机构什么鸟玩意?骗钱不要误人子弟,以前我们公司经常有北大青鸟培训的人,过去一面试,什么也不是。

  8. 老赵
    admin
    链接

    老赵 2009-06-27 22:20:00

    @xiaotie
    因为没有配套语言特性的话,System.Core的功能要打折扣的。

  9. 菌哥
    *.*.*.*
    链接

    菌哥 2009-06-27 22:21:00

    虽然知道是语法糖,但还是强迫自己用3.0的特性来写代码,现在是能用则用,以达到熟练的目的

  10. xiaotie
    *.*.*.*
    链接

    xiaotie 2009-06-27 22:23:00

    @Jeffrey Zhao
    引进来了,配套的语言特性都有了。

  11. 老赵
    admin
    链接

    老赵 2009-06-27 22:24:00

    @菌哥
    语法糖,如果可以提高开发效率,自然应该用,呵呵。

  12. 老赵
    admin
    链接

    老赵 2009-06-27 22:25:00

    @xiaotie
    现在看来,如果需要操作集合,没有C# 3.0的特性,简直是一场灾难啊。

  13. peterzb
    *.*.*.*
    链接

    peterzb 2009-06-27 22:31:00

    还没有接触3.0, 只用到2.0, C#现在是越来越少机会使用了

  14. 老赵
    admin
    链接

    老赵 2009-06-27 22:34:00

    @peterzb
    现在在做什么啊?

  15. ss33[未注册用户]
    *.*.*.*
    链接

    ss33[未注册用户] 2009-06-27 22:36:00

    @Jeffrey Zhao
    问你一个东西呀,asp.net mvc发展前途怎么样呀,现在公司在用asp.net mvc的多吗,以后会不会有很多呢,大量使用asp.net mvc吗

  16. Anders Cui
    *.*.*.*
    链接

    Anders Cui 2009-06-27 22:39:00

    --引用--------------------------------------------------
    Jeffrey Zhao: 在国内经常听到一些说法,说比较语言,谈论语言是没有价值的。那么讨论哪些东西有价值呢?编程能力(这个的确很重要),解决方案(例如XX编程三百问)……哦,还有“业务”(技术无用论?)。
    --------------------------------------------------------
    技术无用论是常见的论调,持这样的观点会错过很多好用的东西

  17. 老赵
    admin
    链接

    老赵 2009-06-27 22:40:00

    @ss33
    不错啊,易于扩展的东西用的人总是不少的。
    asp.net mvc是新东西,但是它的模型是久经考验的。
    例如rails,asp.net mvc和它很像,估计asp.net mvc team参考了不少。

  18. 不死鸟之魂
    *.*.*.*
    链接

    不死鸟之魂 2009-06-27 22:40:00

    其实ROR最被人诟病的就是用lambda表达式写出来的代码对一些人来说不是很容易理解,因为实现同样的功能,不同人的写法不同,高手和低手相互无法看懂对方的代码。

    3.0学自ruby,也会面临这个问题。

  19. 老赵
    admin
    链接

    老赵 2009-06-27 22:44:00

    @不死鸟之魂
    谁说3.0是学自ruby的,lambda表达式又不是ruby提出的东西,呵呵。

  20. xiaotie
    *.*.*.*
    链接

    xiaotie 2009-06-27 22:47:00

    我是坚持类库论者。

    目前的感觉,最近开始做Asp.Net项目,这个我主动升到了3.5。主要考虑是为了linq2sql。以前用ActiveRecord,但看Castle社区死气沉沉的,心中没底,不敢用了。

    而在此之前的一些项目,C# 2.0 + 的语言特性对我的作用没多大,foreach 写习惯了也很快的,不缺那点时间,且一个项目写 foreach 的机会也并不多。而对这些项目作用最大的就是适当的引入第三方的类库。拿我的几种项目类型来说。

    图像处理,绝对的类库第一,写算法能写死人。我之前一直把眼睛盯着OpenCV的,但在.Net下不好用。

    网络程序开发,最后也找到一个好用的和Mina近似的库,省很多事情(用WCF也可以,但我感觉那玩意有点重量级,且时间来不及学习)。

    目前语音识别.Net还没有开源的库。Sweet Home 3D 这个Java程序还没有对应的.Net程序。

    对近200M数据的序列化和反序列化,保证速度和压缩率,这个最后采用的是ProtoBuf#,压缩成10几M,且反序列化速度极快。如果不是这两年google 开源 ProtoBuf 的话,我得自己设计二进制协议,不知得几天。采用ProtoBuf,连学习带实现,半天搞定。并且把之前影响性能的xml序列化和反序列化部分,去也改成ProtoBuf了,改的很顺利,标一下属性就行了。

    其它,还有客户端和服务器端通讯,设计二进制协议,很烦人。

    太多太多了 。。。

    引入 System.Core 之后,我用的最多的也不是linq,lambda表达式,用的最多的是扩展方法。

    这篇文章中列举的这些需求,在我的项目中出现的地方并不多。有它,也就节省几分钟,无它也行。没有实质性的意义。

  21. 温景良(Jason)
    *.*.*.*
    链接

    温景良(Jason) 2009-06-27 22:47:00

    3.0特性确实不错,让我耳目一新.谢谢老赵让我知道这之间的差别

  22. xiaotie
    *.*.*.*
    链接

    xiaotie 2009-06-27 22:48:00

    @Jeffrey Zhao
    唉,在2.0下,我集合操作用的也挺好的。可能我这一块的操作不复杂,而我的复杂的集合操作封装一次就永远用了。

  23. 老赵
    admin
    链接

    老赵 2009-06-27 22:50:00

    @xiaotie
    自然类库对于面向功能的项目来说,是非常重要的。语言是基础架构,我现在是根本离不开C# 3.0了,我操作集合的情况的确比较多,呵呵。
    PS 1:Castle社区不行,NHibernate社区还是很活跃的。
    PS 2:.net下和mina接近的库是什么啊?

  24. xiaotie
    *.*.*.*
    链接

    xiaotie 2009-06-27 23:03:00

    @Jeffrey Zhao

    NHibernate 太复杂,看着头疼。

    ALAZ.SystemEx, ALAZ.SystemEx.NetEx 这玩意。写Socket程序很方便。

  25. ztofemale
    *.*.*.*
    链接

    ztofemale 2009-06-27 23:11:00

    我关心的是性能,性能永远是软件成功的关键,Vista就是例子,Java手机开发就是例子..........
    如果一个语法糖能提高开发效率而忽视了程序的性能,我愿用更多一点的时间用C++或Delphi..等去作性能高的程序
    我想在性能考虑方面,微软会失败的....

  26. peterzb
    *.*.*.*
    链接

    peterzb 2009-06-27 23:19:00

    @Jeffrey Zhao
    呵呵, 现在主要做手机视频监控/安防监控方面, 主要使用C++/Java, 业务领域移动,邮政方面 C#就很少有机会用了 以前做电子政务系统的时候 C#/Asp.Net使用比较多

  27. zeus2
    *.*.*.*
    链接

    zeus2 2009-06-27 23:25:00

    NHibernate确实够复杂,其实这种ORM框架不如自己编一套.
    支持数据库支持mssqlserver+mysql+oracle就行了

  28. 老赵
    admin
    链接

    老赵 2009-06-27 23:27:00

    @zeus2
    一个ORM要花的精力太多,因为同样的model可能会会map成不同的数据库schema,这方面要求很高。
    如果遇到需要的map再去补充的话,在项目中基本上是不太可能。

  29. chegan
    *.*.*.*
    链接

    chegan 2009-06-27 23:29:00

    “其实对语言的讨论在行业内是非常重要的一个方面,许多国内“精英”无比崇拜外国技术人员们对这些话题的争论才叫一个热烈。老赵搞不懂的是,为什么这些精英一边看轻国内技术人员,一边崇拜老外,一边却看轻老外也喜欢讨论的内容呢?“

    之前曾写过国人的妄自菲薄与夜郎自大,我们确实有这些个不自信与自满阿

  30. 老赵
    admin
    链接

    老赵 2009-06-27 23:29:00

    @ztofemale
    性能的确要考虑,但是在这之前你要知道,性能是什么造成的。
    例如一个web应用程序,你追究语言平台的性能,基本上就是走错方向了。
    一个数据库查询优化,一个缓存,什么都回来了。
    所以rails会流行,要知道ruby的性能没有任何优势。
    补充一句:“性能永远是软件成功的关键”这句话我不同意。

  31. 老赵
    admin
    链接

    老赵 2009-06-27 23:30:00

    @xiaotie
    NHibernate的确复杂,可以关注一下Fluent NHibernate。

  32. 老赵
    admin
    链接

    老赵 2009-06-27 23:32:00

    @chegan
    嗯嗯,只可惜不少时候,这样的人会被认为是高手,不断地影响后人。
    所以,我现在很看不惯这样的情况。

  33. rainnoless
    *.*.*.*
    链接

    rainnoless 2009-06-27 23:34:00

    --引用--------------------------------------------------
    Jeffrey Zhao: @jacky song
    什么东西的性能?
    很多东西是语法糖,编译出来的东西是一样的。
    例如C# 3.0里用lambda表达式和2.0里用delegate,完全等价的。
    --------------------------------------------------------
    恩,“语法糖”这个词出现以来就很贴切,一切华丽的背后都被编译器给还原的体无完肤了,有时候纠结一个新特性那么些所谓的性能优劣实在很无谓,呵呵,一个普通的应用程序项目,不涉及到关乎民生大计,飞机大炮宇宙飞船的,呵呵。真没有必要为了追求到每一个环节的性能极致,而放弃一些新生事物的尝试和使用,用了新生事物也并非降低整个应用程序的“可靠性”,呵呵。
    似乎现在都有一种观念侵袭着社区大多数人的理念:每一次新特性的推向都是建立在损失性能为代价的基础上的。不知道大多数.net阵营的同志是不是这样想的?也不知道为什么会有这种想法出现。

  34. 地狱门神
    *.*.*.*
    链接

    地狱门神 2009-06-27 23:44:00

    不在意版权问题的话,直接在*proj文件里加入
    <Reference Include="System.Core">
    <Private>True</Private>
    </Reference>
    就可以在VS2008中开发可部署到2.0环境的项目。
    最后只会多这么个600多K的dll。
    3.5的功能都有。

  35. xiaotie
    *.*.*.*
    链接

    xiaotie 2009-06-27 23:48:00

    @Jeffrey Zhao
    我的数据库都不复杂,ActiveRecord模式够用了。要关注,下一步也是关注OODBMS,进一步提高生产力。

  36. 地狱门神
    *.*.*.*
    链接

    地狱门神 2009-06-27 23:48:00

    不过4.0的beta好像不能用这种方法。

  37. 老赵
    admin
    链接

    老赵 2009-06-27 23:50:00

    @xiaotie
    OODBMS还远着吧,尤其是RDMBS已经实现的可靠性,性能等之间的平衡。
    当然,还是要看什么项目。

  38. 老赵
    admin
    链接

    老赵 2009-06-27 23:51:00

    @地狱门神
    因为.NET 3.5和2.0的CLR是一样的,.NET 4.0连CLR都变了。

  39. xiaotie
    *.*.*.*
    链接

    xiaotie 2009-06-27 23:51:00

    @地狱门神
    实在搞不懂微软为啥把扩展方法搞成C# 3.0的语法糖而不是VS2008的语法糖。那样不引入System.Core就可以用扩展方法了。

  40. 老赵
    admin
    链接

    老赵 2009-06-27 23:53:00

    @xiaotie
    这些肯定和VS 2008无关,这是C# 2.0编译器的问题。
    不过,我也不知道更新C# 2.0编译器是否会遇到什么问题。技术角度肯定是没有问题的。

  41. xiaotie
    *.*.*.*
    链接

    xiaotie 2009-06-27 23:54:00

    @Jeffrey Zhao

    OODBMS在性能上貌似没啥问题,可靠性上我心中还没谱。不过注意备份问题也不大,OODBMS备份简单。但好处实在太大了。规模上,我的数据量OODBMS都满足。目前最大的郁闷是db4o是gpl的,我考虑采用Event机制或插件机制来摆脱直接引用db4o。

  42. 地狱门神
    *.*.*.*
    链接

    地狱门神 2009-06-27 23:56:00

    在.Net内部增加Attribute是因为互操作性的原因。
    你在C#里定义一个扩展方法,需要在VB中也能用。

  43. xiaotie
    *.*.*.*
    链接

    xiaotie 2009-06-27 23:56:00

    @Jeffrey Zhao
    引入System.Core.dll了,所有3.0的特性都能用,包括lambda,linq,扩展方法,即使是 2.0 的项目。而linq依赖 System.Core.dll可以理解,但扩展方法实在没理由依赖 System.Core.dll,它完全就是一个编译器的语法糖嘛。

  44. Cat Chen
    *.*.*.*
    链接

    Cat Chen 2009-06-28 00:01:00

    在用惯了JavaScript之后,我变得非常鄙视不支持lambda的语言。虽然JavaScript那个要写function的匿名函数也非常不方便,但总好过没有。

  45. 老赵
    admin
    链接

    老赵 2009-06-28 00:03:00

    @地狱门神
    你是指什么?我没有听懂。

  46. 老赵
    admin
    链接

    老赵 2009-06-28 00:05:00

    @xiaotie
    是的,我的意思是,微软不升级C# 2.0的编译器,是不是有什么限制。例如Licence上的,例如标准提交上的……当然往坏里想,微软的目的也可能是希望用户快快升级。

  47. 老赵
    admin
    链接

    老赵 2009-06-28 00:06:00

    @Cat Chen
    所以说,函数式编程可以使用的抽象粒度更小一些,很容易影响API的设计。

  48. Cat Chen
    *.*.*.*
    链接

    Cat Chen 2009-06-28 00:10:00

    下面两者有什么区别吗?
    * delegate(int i) { return i % 2 == 0; }
    * i => (i % 2 == 0)

    当然有!前者是强类型的,后者是类型推断的。如果没有上下文对delegate(int i)中的int定义,那我们只能认为这是泛型T,因此这两者才是等价的:
    * delegate(T i) { return i % 2 == 0; }
    * i => (i % 2 == 0)

    当你在代码里面疯狂嵌套lambda和使用generic(或ducking type)时,强类型写法就逼着你写这样的定义:
    * delegate (T1 i, T2 j, T3 k, T4 l) { /* todo */ }

    你知道T1, T2, T3, T4分别是上下文中的什么类型吗?看到你头晕你也不知道。类型推断不是给你在一眼看得出是什么类型的场合省事用的,而是用于那些无需关注类型(即泛型)的场合的。

  49. xiaotie
    *.*.*.*
    链接

    xiaotie 2009-06-28 00:16:00

    @Jeffrey Zhao
    这个应该没关系吧。我感觉无非是为了推广3.0,System.Core中定义了一堆扩展方法。而这功能应该像{get;set;}语法糖那样,用上2008了,就可以用了。

  50. 勇赴
    *.*.*.*
    链接

    勇赴 2009-06-28 00:17:00

    微软出3.0不就是为淘汰2.0吗?

  51. 老赵
    admin
    链接

    老赵 2009-06-28 00:48:00

    @xiaotie
    不过微软的确也是要付出成本的,因为VS 2008不负责编译啊,它负责调用csc.exe编译,微软如果要做到你说的这点,需要修改C# 2的csc.exe了,呵呵。

  52. WizardWu
    *.*.*.*
    链接

    WizardWu 2009-06-28 01:38:00

    若先不论 C# 的版本,
    .NET 2.0, 3.0, 3.5 都是同一版的 CLR,
    .NET 4.0 才是全新的 CLR,但可选择要用先前的 CLR 2.0 来 Compile

    台湾一堆金融机构,还在用 .NET 1.1 不愿更新。
    主管怕死或怕麻烦,连 C# 2.0, DataSource 控件都没得用。

  53. GWPBrian
    *.*.*.*
    链接

    GWPBrian 2009-06-28 09:05:00

    向老赵学习

  54. 炭炭
    *.*.*.*
    链接

    炭炭 2009-06-28 09:32:00

    编程无非就是搭积木,语言再好也是小积木块,你自己肯定要构建自己大的积木块才可以。为什么讨论语言优劣没意义,就是这个道理。好用无非是进行了再封装,你自己不会封吗?不论什么平台都能搭出漂亮的框架来,这才是一个架构是应该考虑的吧。跟着一好的架构师工作,程序员是分不出什么2.0,3.0的。

  55. yeml[未注册用户]
    *.*.*.*
    链接

    yeml[未注册用户] 2009-06-28 10:21:00

    老赵还是多发点深入学习的文章吧, 不要发这些比较了

    而且2。0都够用了,3.0还是3.5那个framework太鸟大了,对于我这种做共享软件的人来说,简直没办法接受
    难不成用户要为了安装我10M的程序,得去下个200M的framewrok?!

  56. 飞林沙
    *.*.*.*
    链接

    飞林沙 2009-06-28 10:55:00

    我们原公司打着3.5的牌子,但是在用着1.1的特性.......

  57. 非空
    *.*.*.*
    链接

    非空 2009-06-28 11:15:00

    我现在要遍历3层才能找到控件 很痛苦,代码写起来那是懒婆娘的裹脚布--又臭又长

  58. 非空
    *.*.*.*
    链接

    非空 2009-06-28 11:52:00

    还有那个N大的安装包,给人发过去一看 100个人有一百个说:
    “( ⊙o⊙ )哇 这么大”

  59. s1ihome
    *.*.*.*
    链接

    s1ihome 2009-06-28 12:05:00

    进步太大了,我没觉得可读性比2.0更高反而觉得更加晦涩难懂了。

  60. asheng
    *.*.*.*
    链接

    asheng 2009-06-28 12:55:00

    是 C#好,java也不是不好
    只是各有优缺点吧
    还是别一棍子打死的好

  61. 装配脑袋
    *.*.*.*
    链接

    装配脑袋 2009-06-28 13:33:00

    于此没有诚意的拯救相比,是不是我的VBF更值得一看呢^_^
    特别是在2005年的上下文之中

  62. 装配脑袋
    *.*.*.*
    链接

    装配脑袋 2009-06-28 13:45:00

    C# 3.0之新特性,C#2不能拥有,本身就是这个语言设计的悲哀。为何不能让开发者自己补充语法呢?本质就是“补充语法”这件事情没有很好地抽象出来,没有这方面设计的模型。

    元编程未来的发展,应该是这种有抽象意义的语法均可通过类库来补充。要进一步提升语言的可扩展性。

    至于这方面的尝试,尽请期待……

  63. testtest[未注册用户]
    *.*.*.*
    链接

    testtest[未注册用户] 2009-06-28 13:53:00

    借个地方说话,最近看Webcast老赵的MVC讲座,总感觉声音小小的,老赵同志下次录讲座时能不能大声点啊,听得很费劲啊,拜托。

  64. 老赵
    admin
    链接

    老赵 2009-06-28 14:34:00

    @炭炭
    这个积木是什么做的,这个是改变不了的。这就是我说的,类库框架弥补不了语言缺陷。
    而且,积木的材料也会影响搭建方式,语言是会影响大量涉及的。
    最近在看mina的源代码,对于Java缺少语言特性而造成的大量Future类,我觉得真是冗余啊。

    还有说到架构师,如果你不了解不同语言,你很难做出好的架构决定。
    例如,为什么Twitter实用Rails做前端,后端用Scala做消息传递平台,而不是Java?
    为什么用Twitter用了大量的Actor机制,配合mina进行使用?
    此外,架构师还需要决定一个技术选择后所带来的生产力,如你的项目是否需要强类型检查?duck typing使用到什么程度?
    你现在看轻的,觉得“理所当然”而不去思考的东西,到最后很容易成为你的瓶颈。

  65. 老赵
    admin
    链接

    老赵 2009-06-28 14:36:00

    @yeml
    这个东西是基础,涉及到思维方式,一味追求“深入”我不觉得有什么效果。
    就好比我自己的感受,如果不了这些,是很难突破一些东西的。
    如果你觉得这些比较没有意义的话,以后很多东西你也理解不了啊,因为思维是连续的。
    例如,我接下来会在C#里的Actor模型提供一个Dispatcher,为了弥补缺少模式匹配的遗憾。
    但是,这个就是要了解“语言”,了解为什么需要模式匹配,它的含义和作用是什么才能想到的补充方式。
    否则你就算知道了现在的做法,遇到其它问题还是没法自己想办法出来。
    我认为思维方式才是有价值的,但是好像大家都喜欢看一个结论,有时候让我无可奈何。

    // 当然,客户端程序有其特殊考虑,这个没有办法,不过我就讨论语言特性。

  66. 老赵
    admin
    链接

    老赵 2009-06-28 14:37:00

    @asheng
    又是套话,你说一个Java语言的“优势”出来呢?
    我对Java的了解不比C#少。
    // 是Java语言,不是Java平台。

  67. 老赵
    admin
    链接

    老赵 2009-06-28 14:41:00

    @装配脑袋
    我这个拯救很有诚意啊,是可以直接用在生产环境下的。现在我写C# 2.0就会用到这个方式。

  68. 老赵
    admin
    链接

    老赵 2009-06-28 14:47:00

    @testtest
    这个应该是MSDN WebCast录音的问题,可以去向MSDN WebCast那里提一下意见,如果我声音再想,就变大吼大叫了,呵呵。

  69. 老赵
    admin
    链接

    老赵 2009-06-28 14:52:00

    @s1ihome
    因为你没有去了解C# 3.0的写法,所以会觉得晦涩难懂,等你了解之后就好了。
    所以我建议你使用C# 3.0一个月,然后再来谈谈感受,呵呵。

  70. 装配脑袋
    *.*.*.*
    链接

    装配脑袋 2009-06-28 14:57:00

    你想啊,VB2005都没有匿名方法或任何替代品,我都能用现有语法强行模拟Lambda出来。还特别查了编译器代码来寻找可以利用的奇技淫巧,这才叫有诚意啊 :D

    PS. 若想用C#3开发.NET 2程序并且想使用匿名方法的话,无需System.Core,只需自己定义ExtensionAttribute,放在正确的命名空间下即可。使用Lambda更是没有限制。没人知道你是用哪个版本的C#编译的,哪怕是Mono的呢。所以放心用新版编译器吧。。

  71. 老赵
    admin
    链接

    老赵 2009-06-28 15:05:00

    @装配脑袋
    脑袋最厉害了,哈哈。
    匿名方法本来就是……理论上CLR 1上的特性啊,当然可以使用了。
    其实如果可以使用C# 3.0的编译器的话,我倒情愿装上.NET 3.5了。
    总之,我现在遇到2.0的项目,都强推3.5的,哈哈。

  72. 装配脑袋
    *.*.*.*
    链接

    装配脑袋 2009-06-28 15:33:00

    扩展方法啦……口误

  73. 代码乱了
    *.*.*.*
    链接

    代码乱了 2009-06-28 15:34:00

    只要稍加调整,可以让.net2.0 同样支持扩展方法,这个我已经试验过了。

  74. 老赵
    admin
    链接

    老赵 2009-06-28 15:37:00

    @代码乱了
    扩展方法本来就是语法糖啊,对于CLR 2.0层面上的东西都是可以的。
    包括如果你用到的类库是.NET 2.0就有的,用C# 3.0编译器得到的结果也一样可以运行的。

  75. 代码乱了
    *.*.*.*
    链接

    代码乱了 2009-06-28 15:40:00

    @Jeffrey Zhao
    嗯,扩展方法实际上是编译器上面做的文章,只是在3.0后把他发挥到极致

  76. 代码乱了
    *.*.*.*
    链接

    代码乱了 2009-06-28 15:46:00

    现在用.net 3.5做项目遇到的最不爽的问题就是,部署,如果客户机器没有装.net framework 3.5,那个部署真叫一个烦啊,不知道精简下来的情况如何了。所以有时候想想.net 2.0还是有点好处的

  77. 老赵
    admin
    链接

    老赵 2009-06-28 15:49:00

    @代码乱了
    还好我从来没有做过客户端项目……

  78. Haozes
    *.*.*.*
    链接

    Haozes 2009-06-28 16:09:00

    老赵,用了你的这个博皮,置顶文章文章不能置顶了哦,你自个试先

  79. 老赵
    admin
    链接

    老赵 2009-06-28 16:10:00

    @Haozes
    是的,所以自己Hack吧,呵呵。
    这个问题只有dudu可以解决啊。

  80. xiaotie
    *.*.*.*
    链接

    xiaotie 2009-06-28 16:11:00

    我的大部分是客户端项目,我恨3.5!

  81. 装配脑袋
    *.*.*.*
    链接

    装配脑袋 2009-06-28 16:36:00

    @xiaotie
    Windows 7来拯救你了。。不过.NET 4.0又来了……

  82. 老赵
    admin
    链接

    老赵 2009-06-28 16:39:00

    @装配脑袋
    所以还是做服务器比较好……客户端的话……做开发工具也不错……

  83. xiaotie
    *.*.*.*
    链接

    xiaotie 2009-06-28 16:42:00

    @装配脑袋
    大部分人还在用xp啊,咋办呢

  84. xiaotie
    *.*.*.*
    链接

    xiaotie 2009-06-28 16:42:00

    @Jeffrey Zhao
    程序员没有花钱买开发工具的习惯

  85. 老赵
    admin
    链接

    老赵 2009-06-28 16:43:00

    @xiaotie
    嗯嗯,有道理……我从没考虑过卖软件的,所以没有想到……

  86. WizardWu
    *.*.*.*
    链接

    WizardWu 2009-06-28 17:28:00

    等两年后 Windows 7 普及 (内附 .NET 3.x),
    就有希望 C# 3 普及,
    否则客户和老板最大。

  87. 老赵
    admin
    链接

    老赵 2009-06-28 17:30:00

    @WizardWu
    还好我只做服务器端产品。

  88. lhking
    *.*.*.*
    链接

    lhking 2009-06-28 19:33:00

    只能跟着公司的路线走,新技术确实不错。

    老赵,你的照片挺年轻的

  89. 地狱门神
    *.*.*.*
    链接

    地狱门神 2009-06-28 20:14:00

    @Jeffrey Zhao
    我说的是扩展方法,是由C#或者VB编译器在那个扩展方法上附加了
    System.Runtime.CompilerServices.ExtensionAttribute
    这个标记来表示的。
    C#里面增加了定义扩展方法的语法,VB里面没有增加语法。
    不管如何,有这么一个标记,才能使得跨程序集的程序也能使用扩展方法。
    而这个标记是System.Core.dll里新增的。
    不过编译器只要发现现在的程序引用的程序集中在那个命名空间中有那个标记,就能够使用扩展方法。所以做一个dll,只含有那个标记,引用那个dll就能开启扩展方法的功能。

  90. everthink[未注册用户]
    *.*.*.*
    链接

    everthink[未注册用户] 2009-06-28 21:17:00

    没有主持或者参与过较大复杂度的软件项目,就不会明白软件开发的核心问题域。其实语言层面给项目带来的所谓生产力实际上是非常微不足道的。真正能带来生产力提升的是良好的架构。给一个设计非常差或者根本就没有设计的系统扩充功能或改变功能时,又或者去维护一个原来开发者已经早已没了踪影的系统时,你对此就有直观的体会了。
    当然,可能有人说,大不了推翻重做,重新开发个比原来更能满足用户需求的。却不曾想过,推翻重做的成本却又有几何?

  91. 老赵
    admin
    链接

    老赵 2009-06-28 21:43:00

    @everthink
    我写这篇文章是说语言重要,又没有说架构不重要,架构自然是重要的。
    不过,语言是会影响系统的设计和架构方式的。
    这里引入一篇文章,里面谈论了Functional Programming对程序的影响:http://lorgonblog.spaces.live.com/Blog/cns!701679AD17B6D310!511.entry
    如果语言差别不大,为什么要有混合编程?为什么系统中不同组件要用不同语言来实现?

  92. 代码乱了
    *.*.*.*
    链接

    代码乱了 2009-06-28 21:50:00

    @地狱门神
    这也是我之前的回复要表达的

  93. DiggingDeeply
    *.*.*.*
    链接

    DiggingDeeply 2009-06-28 22:14:00

    C#到底能进化成什么样子呢?我也是从2.0之后有些看不明白了。
    说一点,本人特别不喜欢var这个关键字,确实省力了,但是代码的易读性也没了。

  94. 老赵
    admin
    链接

    老赵 2009-06-28 22:17:00

    @DiggingDeeply
    var其实也只是少打一些字,个人认为它是C# 3.0中作用最少的功能之一了。
    当然,它也是为了配合匿名类型这样的新特性出现的。

  95. DiggingDeeply
    *.*.*.*
    链接

    DiggingDeeply 2009-06-28 22:24:00

    @Jeffrey Zhao
    你在啊?
    匿名类型和JSON蛮像;Lambda最初我是在python里看到的,到C#里就看着变扭了,和C、C++家族语言越来越不像了。

  96. xiaotie
    *.*.*.*
    链接

    xiaotie 2009-06-28 22:27:00

    @地狱门神

  97. 老赵
    admin
    链接

    老赵 2009-06-28 22:32:00

    @DiggingDeeply
    我觉得C#里的Lambda很漂亮,为什么要和C、C++相像呢?

  98. DiggingDeeply
    *.*.*.*
    链接

    DiggingDeeply 2009-06-28 22:43:00

    @Jeffrey Zhao
    C#既然叫CSharp,还是想继承C系列语言的传统了,本人一家之言。
    我觉得C#在设计上融合了好多语言的特点,这样做不知道是不是为了吸引更多的开发人员更容易上手C#,拉拢开发人员。
    Lambda节省了代码,也同时表明了调用的逻辑,是比较优雅的方式。

  99. 看不惯[未注册用户]
    *.*.*.*
    链接

    看不惯[未注册用户] 2009-06-28 22:55:00

    1、老赵是个牛人,小弟心仪已久。。。
    2、老赵很虚幻,让小弟景仰之。。。
    3、老赵很无聊,名词太多吓唬人,小弟沉思之。。。
    4、老赵和楼上的丫们,喜欢做MPV不?偶看老赵貌似一个MVPer。。。

  100. 看不惯[未注册用户]
    *.*.*.*
    链接

    看不惯[未注册用户] 2009-06-28 22:56:00

    WK,独独疯掉了,居然有两个99楼。。。

  101. 老赵
    admin
    链接

    老赵 2009-06-28 22:59:00

    @看不惯
    这些名词不是吓唬人来的,如果这也叫多也叫吓唬人的话,随便找一本书来绝对可以让你晕过去了,呵呵。

  102. Leon Weng
    *.*.*.*
    链接

    Leon Weng 2009-06-29 08:12:00

    --引用--------------------------------------------------
    看不惯: WK,独独疯掉了,居然有两个99楼。。。
    --------------------------------------------------------

    是何原因?

  103. 装配脑袋
    *.*.*.*
    链接

    装配脑袋 2009-06-29 08:43:00

    @地狱门神
    你只需自己定义 System.Runtime.CompilerServices.ExtensionAttribute
    类型即可,无需引用System.Core.dll

    另外,自己定义还可以将它放开为定义在属性上(原本仅仅能定义在方法上)。这样在VB里,属性也可以扩展的哦(C#仍然是不行滴)。

  104. 老赵
    admin
    链接

    老赵 2009-06-29 09:12:00

    @Leon Weng
    有一定几率发生,一般总是同步上的问题。

  105. 麒麟.NET
    *.*.*.*
    链接

    麒麟.NET 2009-06-29 10:51:00

    跟领导提过很多次将项目升级到3.0,但是得到的回复是:只要现有技术能满足业务需求即可,产品的稳定才是最重要的,我们只需要最稳定的技术,不需要最先进的技术。

    其实,我很无语……

  106. 老赵
    admin
    链接

    老赵 2009-06-29 10:52:00

    @麒麟.NET
    很多时候只是个借口,例如为啥说.NET 3.5不稳定,估计领导也说不出理由来。

  107. 麒麟.NET
    *.*.*.*
    链接

    麒麟.NET 2009-06-29 11:15:00

    其实所谓的稳定与否是指开发人员对技术的熟练程度……,领导怕开发人员对技术不熟导致效率和稳定性降低……

    哎,啥也不说了,继续无语……

  108. 妖居
    *.*.*.*
    链接

    妖居 2009-06-29 11:55:00

    记得以前 装配脑袋 曾经用2.0下的VB做了一个类似3.0功能的类库,让2.0的VB可以支持函数式编程和LINQ之类的东西。好像实现方法和老赵的差不多。

  109. 伟zzz[未注册用户]
    *.*.*.*
    链接

    伟zzz[未注册用户] 2009-06-29 13:22:00

    同意四楼的,
    #4楼 没办法啊。 [未注册用户]
    2009-06-27 22:14
    2.0的包在没装。net的机子上引用打包才十来M
    但是3.5的就到了100多M了,这个选择很无奈啊

    B/S结构的还好,如果遇上C/S结构的,如果3.0以上的框架那个东东部署起来就麻烦了,安装包大,安装起来也慢,2.0的框架大小与安装速度都还凑合,啥时候3.0或以上的框架如果能弄个精简版的打包程序,俺就第一时间换

  110. 罗里罗嗦夫斯基
    *.*.*.*
    链接

    罗里罗嗦夫斯基 2009-06-29 13:41:00

    文中提及的语法可以看一下,至于标题的拯救2.0就没有必要了,3.0版本升级而已。难道4.0出来了后,还要拯救3.0了吗?

    建议把标题改为<C#3.0新增语法之一>

  111. 韦恩卑鄙
    *.*.*.*
    链接

    韦恩卑鄙 2009-06-30 22:23:00

    vb的 linq to xml 生产力还真是高到不行 c#死活不支持
    我恨阿

  112. RednaxelaFX
    *.*.*.*
    链接

    RednaxelaFX 2009-07-02 04:36:00

    @DiggingDeeply
    嗯,大家都是通过不同的路径学习到各种知识,所以看同一个东西的感觉会很不同。
    Python的lambda表达式语法是用lambda关键字为引导,用冒号为分隔,与Python的其它语法保持高度的一致性。在保持语言结构的外观的一致性方面,Python真的做得很不错。
    succ = lambda x: x + 1

    看看Standard ML的lambda语法:
    val succ = fn x => x + 1;
    与C# 3.0的相比,都是用肥箭头:
    Func<int, int> succ = x => x + 1;
    Scala也是用肥箭头的。

    同是ML系语言的F#的lambda表达式,反而没有C# 3.0的像SML:
    let succ = fun x -> x + 1;;
    Haskell也是用瘦箭头:
    succ = \x -> x + 1

    像Scheme的话lambda是个特殊型,
    (define succ (lambda (x) (+ x 1)))

    C++的lambda:
    auto succ = [](int x) { return x + 1; };

    看得多了之后觉得C# 3.0的lambda在众多可用ASCII编码的语言的表示法中算是很顺眼的了……虽说写语法分析器的时候这玩儿让人很头疼 T T
    SML、F#、Haskell、ECMAScript 3、Python、Ruby、C++等等,这些语言的lambda语法都是有特殊标记开始的(分别是fn、fun、\、function、lambda、->、[...]),对预测式语法分析器来说这是个好事。而C# 3.0与Scala的却就是靠中间的那个肥箭头来标记,解析起来很麻烦。
    啊,据说EcmaScript 5会加入lambda关键字,不过还没定论。扯远了 orz……

    只是想支持一下老赵的观点,语言的外表“看起来”的样子会影响到大家使用语言的方式的。写起来特别麻烦的结构用的人就不会多,或者用得会很不爽。在某个具体项目中,影响生产力的还是framework和library,但它们也是构筑在语言之上,受到语言的影响的。像是说如果用Katahdin语言的话,语法结构完全可以在运行时由程序员来指定,那么想封装什么结构都很容易,要写起库来也就会更灵活(写库的同时也就是在创作一个小型语言)。

  113. 吴碧宇
    *.*.*.*
    链接

    吴碧宇 2009-07-02 14:35:00

    一直希望使用Lambda 表达式但一直没有得到Lambda 表达式的一个较详的性能上的分析,固迟迟敢下手。
    希望老赵能否对Lambda 表达式的 效率做一个详细的分细。

  114. 老赵
    admin
    链接

    老赵 2009-07-02 14:36:00

    @吴碧宇
    放心用吧,没有问题。
    Lambda Expression构建的委托和普通委托,编译后一模一样。

  115. 葛云飞
    *.*.*.*
    链接

    葛云飞 2009-07-02 16:00:00

    lamda表达和Linq to SQL
    确实是很强的东西
    分部方法也是一样
    原来不以为然,但是在开发中发现真是好用。

    我觉得C#正在向一种非常唯美的方向的发展

  116. RednaxelaFX
    *.*.*.*
    链接

    RednaxelaFX 2009-07-02 23:29:00

    说起来,C# 3.0的lambda在Mono.Options库里也得到了有趣的应用,看例子:http://tirania.org/blog/archive/2008/Oct-14.html
    这个库是用来解析命令行参数的

  117. 吕不为[未注册用户]
    *.*.*.*
    链接

    吕不为[未注册用户] 2009-08-02 21:01:00

    呵呵,讨论的不错。我发一个Python版的吧解决例子吧。
    一个字符串数组中的元素转化为整数,再将其中的偶数放入一个List中。
    老赵的没有再转化回来。
    s=['1','3','6','9','7']
    k=[int(x) for x in s if (int(x) % 2)==0]
    或者,保持原来的类型
    k=[x for x in s if (int(x) % 2)==0]

    所有偶数的平均数
    a=[int(x) for x in s if (int(x) %2)==0]
    print sum(a)/len(a)

    都是偶数
    len([x for x in s if int(x) %2==0]==len(s)

    包含一个偶数
    len([x for x in p if int(x) %2==0])>0

    第4到第8个数
    s[3:8]
    python 10年前就支持这种东西。

  118. 老赵
    admin
    链接

    老赵 2009-08-02 21:46:00

    @吕不为
    早在2、30年前搞函数式编程的时候这些就可以有了,如今在F#里也是支持的,但是Java/C++至今没有。
    这东西也是个语言设计者的选择问题,Java太弱,F#太强太复杂,C#是我感觉平衡的相当好的。

  119. 镜涛
    *.*.*.*
    链接

    镜涛 2009-08-03 20:41:00

    呵呵,看了老赵的文章总会有些顿悟的东西,给自己带来很大帮助。不知老赵的msn是??有些问题请教下!

  120. 老赵
    admin
    链接

    老赵 2009-08-03 21:27:00

    @镜涛
    右下角的Web Messenger吧。

  121. 菜鸟毛
    *.*.*.*
    链接

    菜鸟毛 2009-08-14 11:08:00

    发表一点愚见,那些where,select等方法,只有在集合的时候才能发挥作用吧.平常时候好像没有什么作用啊.让您见笑.

  122. 老赵
    admin
    链接

    老赵 2009-08-14 11:12:00

    @菜鸟毛
    这个自然,哪有什么可以操作任何东西的,不过集合操作太常见了。

  123. peipei[未注册用户]
    *.*.*.*
    链接

    peipei[未注册用户] 2009-08-15 13:06:00

    夜郎自大

  124. 邀月
    *.*.*.*
    链接

    邀月 2009-09-08 22:55:00

    老实说, 我不想介入什么语言之争,因为我任何一门都没能熟练掌握,更谈不上深入研究了。仅就楼主的一句话发表个人看法:
    “那么C# 3.0已经将Java甩开地太远太远。”这话有点不能服众。语言是一种工具,高效的生产力是它的最基本特性。c# 3.0真的那么优秀,为什么那些中高端用户会视而不见?它自身有一些无法克服的弱项。而恰恰对手java又具备了这些。语言优劣恐怕是本世纪最无厘头的话题之一了吧。

  125. 老赵
    admin
    链接

    老赵 2009-09-08 23:04:00

    @邀月
    您既然没有熟练掌握任何一门语言,又何谈说语言优劣是最无厘头的话题呢?
    您难道认为,那么多研究语言,发明语言的科学家们都是吃干饭的吗?
    您能否可以解释一下,为什么新语言还是层出不穷呢?
    轻视语言是国内计算机教育的弊病,当然,国内轻视的东西实在太多了,所以普遍水平上不去。
    可以这么说,轻视是因为眼界狭隘,眼界狭隘又反过来导致轻视各种东西。

    谁说中高端用户对C# 3.0视而不见?Java领域许多大牛都赞同C#现在比Java优秀很多。
    用Java多,是因为其他人想要用Java平台,而当时Java平台只有Java语言一个选择而已。
    但是,现在Java平台上有Scala,Groovy,Clojure多种选择,Java语言就靠边站吧。
    时间会证明一切的,看近几个月来Scala的蓬勃发展,社区对Project Coin怨声载道,还不能说明问题吗?

  126. 邀月
    *.*.*.*
    链接

    邀月 2009-09-09 10:20:00

    Jeffrey Zhao:
    @邀月
    轻视语言是国内计算机教育的弊病,当然,国内轻视的东西实在太多了,所以普遍水平上不去。


    我绝没有轻视之意。相反,我对任何语言一视同仁。毕竟是工具,给我带来发很多方便,抑或给许多人带来了快乐!?

    Jeffrey Zhao:
    谁说中高端用户对C# 3.0视而不见?Java领域许多大牛都赞同C#现在比Java优秀很多。
    用Java多,是因为其他人想要用Java平台,而当时Java平台只有Java语言一个

    平台就是它的一大优势,整体的优势。只要看一下.net Framework X百M的尺寸,就知道,它功能肯定更强了,要不然做那么大干嘛,那应用为什么没有迅速普及呢,让客户为发运行一个Helloworld,装X百M的Framework?? C#2 20多M用户还是可以接受的。或许Win7/8已经集成了,那要多少时间呢?用户不是win怎么办?

    Jeffrey Zhao:
    时间会证明一切的,看近几个月来Scala的蓬勃发展,社区对Project Coin怨声载道,还不能说明问题吗?


    时间会证明一切!也许,C#3真的很优秀!那就证明给大家看吧!但短期内应该不会是一枝独秀!

  127. 老赵
    admin
    链接

    老赵 2009-09-09 10:24:00

    @邀月
    我只是说Java语言不行,我有要求别人不使用Java平台吗?我四处推荐大家使用Java平台+Scala语言,被你直接忽略了?
    我总是希望在讨论时逻辑可以清晰一点,知道我在讨论什么,讨论语言时就讨论语言,又把平台扯进来做什么。
    我也从没有说过C#是一枝独秀,不知道你是怎么理解的。我平时除了用C#,也用Scala,F#,JavaScript,也很喜欢Haskell。
    C#别说短期,永远不可能一枝独秀,因为C#肯定不适合所有情况,我也从来不希望C#一枝独秀。

    我的观点只有一个:C# 3.0远超Java语言,用Java语言限制API设计,Java语言浪费代码,编程费时费力。C# 3.0相对要优秀许许多多。

  128. 老赵
    admin
    链接

    老赵 2009-09-09 10:26:00

    @邀月
    国内的一大教育方面就是“语言不是关键的”,导致好像要表示自己“客观”,就不能说任何一门语言的坏话,否则就是“档次低”。
    你的质疑其实我也听过无数遍,还有例如就是“我虽然不很了解Java和C#,但是我的心态绝对好”。
    我比较奇怪,既然不很了解,为什么不去了解了再来说话。一直抱有封闭的,认为自己了解的肯定是对的这种心态,如何成长。

  129. 老赵
    admin
    链接

    老赵 2009-09-09 10:28:00

    当然,要放弃以前的形成的关键是很痛苦的,我也改变过几次。
    例如,学校一直教育我说语言如何如何,我现在改了。
    例如,学校一直教育我说,开发没前途,要做项目经理,现在我改了。

    根据事实说话,不要凭感觉,找依据,用事实作为靠山,你将立于不败之地。
    “感觉”这种东西,是相当不靠谱的

  130. 邀月
    *.*.*.*
    链接

    邀月 2009-09-09 10:40:00

    Jeffrey Zhao:
    @邀月
    国内的一大教育方面就是“语言不是关键的”,导致好像要表示自己“客观”,就不能说任何一门语言的坏话,否则就是“档次低”。
    你的质疑其实我也听过无数遍,还有例如就是“我虽然不很了解Java和C#,但是我的心态绝对好”。
    我比较奇怪,既然不很了解,为什么不去了解了再来说话。一直抱有封闭的,认为自己了解的肯定是对的这种心态,如何成长。


    楼主:我在学校学的是数学教育。开发是后来兴趣和机遇使然。自己仅有的一点技能是自己摸索的或在一些论坛或网站像code Projects,msdn.com,souurceforge.net,ibm developworks等了解的。也没有参加什么北大青鸟之类的。所以谈不上什么随众吆喝。如果有这种印象,那说明我认识世界的方法观有问题,我自我检讨!

    Jeffrey Zhao:
    当然,要放弃以前的形成的关键是很痛苦的,我也改变过几次。
    例如,学校一直教育我说语言如何如何,我现在改了。
    例如,学校一直教育我说,开发没前途,要做项目经理,现在我改了。

    根据事实说话,不要凭感觉,找依据,用事实作为靠山,你将立于不败之地。
    “感觉”这种东西,是相当不靠谱的


    我虚心接受老赵的观点,学习中了解,事实中成长。

  131. 老赵
    admin
    链接

    老赵 2009-09-09 10:41:00

    @邀月
    别介意,后面几句牢骚不是对你说的,赫赫。:)

  132. 邀月
    *.*.*.*
    链接

    邀月 2009-09-09 10:47:00

    Jeffrey Zhao:
    @邀月
    别介意,后面几句牢骚不是对你说的,赫赫。:)


    在项目中经历无数次的观点碰撞了!该学习的学习,该接受的接受,实在不能接受的,那就剖析它,把它的优秀成分吸收起来。
    感谢老赵的回复。我的观点是:学无止境,学以致用。

  133. 上山打老虎
    *.*.*.*
    链接

    上山打老虎 2009-09-18 10:47:00

    Jeffrey Zhao:@chegan<br/>嗯嗯,只可惜不少时候,这样的人会被认为是高手,不断地影响后人。<br/>所以,我现在很看不惯这样的情况。



    这个很重要啊,新手都是向老手学习的。

  134. 老赵
    admin
    链接

    老赵 2009-09-18 10:54:00

    @上山打老虎
    可惜现在看来,社区需要的是“和谐”。我对某高手提出质疑时,被无数人指责人品不好,呵呵。

  135. Tenny
    61.144.61.*
    链接

    Tenny 2010-08-18 14:12:10

    牛啊,可惜老研究这些有啥用呢?有什么应用价值呢?研究技术是要开辟新的理念,而不是像你这样去证实技术的优缺点,典型的专牛角尖型,白猫黑猫能实现需求的就是好猫,没必要老把时间花到这方面上去,不上不下的,即不能对.net framework的改进带来益处,也不能给开发过程中带来更高的效率.看下国外有谁会去搞这些没实用的东西.人家研究的是SOA和云计算,只有有一理念才能将一项技术给应用的更广泛,这才是技术之道.

  136. 老赵
    admin
    链接

    老赵 2010-08-18 15:35:05

    @Tenny

    不研究优缺点,怎么做到扬长避短呢?这些东西不能给开发过程中带来更高的效率吗?除了SOA(这也是多少年前的东西了啊)和云计算,国外就没有人搞其他了吗?你看到的不是国外搞的,而是从国内听到“国外在搞”的东西,换句话说,就是吵闹得比实际做得更凶的东西……

  137. Kouga
    118.112.242.*
    链接

    Kouga 2010-09-25 09:38:31

    www,其实咱现在在C++下面用LAMBDA毫无压力啊喵……匿名函数表达式什么滴C++封装的比.Net好很多……

    不过 Array.Skip().Get().Select().Where()真滴有必要这么用么喵?

  138. 老赵
    admin
    链接

    老赵 2010-09-25 17:21:29

    @Kouga

    “C++的匿名函数比C#封装的好很多”你是指什么呀?后面这种写法当然是十分需要的啊。

  139. 链接

    Cherry 2013-09-25 08:52:04

    c#新人来挖一句。。 所谓开发效率,我个人认为,程序的可读性是第一位的。 扩展方法的使用是为了增加可读性,将与某类紧密联系的操作变成和该类绑定在一起。是否将某个操作变成扩展方法,要看它和类结合的情况,语言是人用的,永远不要滥用。匿名方法也是这样,不过感觉该用匿名方法的情况很少。 至于第一个例子,我强烈认为下面的写法可读性更好……我认为lambda表达式和LINQ简直是破坏可读性的元凶,能不用尽量别用。自己把查询的逻辑实现出来,读起来是最清晰的,非要写一行乱七八糟的玩意鬼知道你在干啥?

  140. 老赵
    admin
    链接

    老赵 2013-09-28 11:28:05

    @Cheery

    小学生当然觉得高等数学可读性不好了,呵呵。

发表回复

登录 / 登录并记住我 ,登陆后便可删除或修改已发表的评论 (请注意保留评论内容)

昵称:(必填)

邮箱:(必填,仅用于Gavatar

主页:(可选)

评论内容(大于5个字符):

  1. Your Name yyyy-MM-dd HH:mm:ss

使用Live Messenger联系我