Spiga

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

2009-06-27 18:55 by Jeffrey Zhao, 24525 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

标签: C# 2.0, FP, Lambda
Add your comment

134 条回复

    评论共2页: 上一页 1 2 
  1. #35楼 地狱门神      2009-06-27 23:48
    不过4.0的beta好像不能用这种方法。
     回复 引用 查看   
  2. #36楼 xiaotie      2009-06-27 23:48
    @Jeffrey Zhao
    我的数据库都不复杂,ActiveRecord模式够用了。要关注,下一步也是关注OODBMS,进一步提高生产力。
     回复 引用 查看   
  3. #37楼[楼主] Jeffrey Zhao      2009-06-27 23:50
    @xiaotie
    OODBMS还远着吧,尤其是RDMBS已经实现的可靠性,性能等之间的平衡。
    当然,还是要看什么项目。
     回复 引用 查看   
  4. #38楼 xiaotie      2009-06-27 23:51
    @地狱门神
    实在搞不懂微软为啥把扩展方法搞成C# 3.0的语法糖而不是VS2008的语法糖。那样不引入System.Core就可以用扩展方法了。
     回复 引用 查看   
  5. #39楼[楼主] Jeffrey Zhao      2009-06-27 23:51
    @地狱门神
    因为.NET 3.5和2.0的CLR是一样的,.NET 4.0连CLR都变了。
     回复 引用 查看   
  6. #40楼[楼主] Jeffrey Zhao      2009-06-27 23:53
    @xiaotie
    这些肯定和VS 2008无关,这是C# 2.0编译器的问题。
    不过,我也不知道更新C# 2.0编译器是否会遇到什么问题。技术角度肯定是没有问题的。
     回复 引用 查看   
  7. #41楼 xiaotie      2009-06-27 23:54
    @Jeffrey Zhao

    OODBMS在性能上貌似没啥问题,可靠性上我心中还没谱。不过注意备份问题也不大,OODBMS备份简单。但好处实在太大了。规模上,我的数据量OODBMS都满足。目前最大的郁闷是db4o是gpl的,我考虑采用Event机制或插件机制来摆脱直接引用db4o。
     回复 引用 查看   
  8. #42楼 xiaotie      2009-06-27 23:56
    @Jeffrey Zhao
    引入System.Core.dll了,所有3.0的特性都能用,包括lambda,linq,扩展方法,即使是 2.0 的项目。而linq依赖 System.Core.dll可以理解,但扩展方法实在没理由依赖 System.Core.dll,它完全就是一个编译器的语法糖嘛。
     回复 引用 查看   
  9. #43楼 地狱门神      2009-06-27 23:56
    在.Net内部增加Attribute是因为互操作性的原因。
    你在C#里定义一个扩展方法,需要在VB中也能用。
     回复 引用 查看   
  10. #44楼 Cat Chen      2009-06-28 00:01
    在用惯了JavaScript之后,我变得非常鄙视不支持lambda的语言。虽然JavaScript那个要写function的匿名函数也非常不方便,但总好过没有。
     回复 引用 查看   
  11. #45楼[楼主] Jeffrey Zhao      2009-06-28 00:03
    @地狱门神
    你是指什么?我没有听懂。
     回复 引用 查看   
  12. #46楼[楼主] Jeffrey Zhao      2009-06-28 00:05
    @xiaotie
    是的,我的意思是,微软不升级C# 2.0的编译器,是不是有什么限制。例如Licence上的,例如标准提交上的……当然往坏里想,微软的目的也可能是希望用户快快升级。
     回复 引用 查看   
  13. #47楼[楼主] Jeffrey Zhao      2009-06-28 00:06
    @Cat Chen
    所以说,函数式编程可以使用的抽象粒度更小一些,很容易影响API的设计。
     回复 引用 查看   
  14. #48楼 Cat Chen      2009-06-28 00:10
    下面两者有什么区别吗?
    * 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分别是上下文中的什么类型吗?看到你头晕你也不知道。类型推断不是给你在一眼看得出是什么类型的场合省事用的,而是用于那些无需关注类型(即泛型)的场合的。
     回复 引用 查看   
  15. #49楼 xiaotie      2009-06-28 00:16
    @Jeffrey Zhao
    这个应该没关系吧。我感觉无非是为了推广3.0,System.Core中定义了一堆扩展方法。而这功能应该像{get;set;}语法糖那样,用上2008了,就可以用了。
     回复 引用 查看   
  16. #50楼 勇赴2009-06-28 00:17
    微软出3.0不就是为淘汰2.0吗?
     回复 引用   
  17. #51楼[楼主] Jeffrey Zhao      2009-06-28 00:48
    @xiaotie
    不过微软的确也是要付出成本的,因为VS 2008不负责编译啊,它负责调用csc.exe编译,微软如果要做到你说的这点,需要修改C# 2的csc.exe了,呵呵。
     回复 引用 查看   
  18. #52楼 WizardWu      2009-06-28 01:38
    若先不论 C# 的版本,
    .NET 2.0, 3.0, 3.5 都是同一版的 CLR,
    .NET 4.0 才是全新的 CLR,但可选择要用先前的 CLR 2.0 来 Compile

    台湾一堆金融机构,还在用 .NET 1.1 不愿更新。
    主管怕死或怕麻烦,连 C# 2.0, DataSource 控件都没得用。
     回复 引用 查看   
  19. #53楼 GWPBrian      2009-06-28 09:05
    向老赵学习
     回复 引用 查看   
  20. #54楼 炭炭      2009-06-28 09:32
    编程无非就是搭积木,语言再好也是小积木块,你自己肯定要构建自己大的积木块才可以。为什么讨论语言优劣没意义,就是这个道理。好用无非是进行了再封装,你自己不会封吗?不论什么平台都能搭出漂亮的框架来,这才是一个架构是应该考虑的吧。跟着一好的架构师工作,程序员是分不出什么2.0,3.0的。
     回复 引用 查看   
  21. #55楼 yeml[未注册用户]2009-06-28 10:21
    老赵还是多发点深入学习的文章吧, 不要发这些比较了

    而且2。0都够用了,3.0还是3.5那个framework太鸟大了,对于我这种做共享软件的人来说,简直没办法接受
    难不成用户要为了安装我10M的程序,得去下个200M的framewrok?!
     回复 引用   
  22. #56楼 飞林沙      2009-06-28 10:55
    我们原公司打着3.5的牌子,但是在用着1.1的特性.......
     回复 引用 查看   
  23. #57楼 非空      2009-06-28 11:15
    我现在要遍历3层才能找到控件 很痛苦,代码写起来那是懒婆娘的裹脚布--又臭又长
     回复 引用 查看   
  24. #58楼 非空      2009-06-28 11:52
    还有那个N大的安装包,给人发过去一看 100个人有一百个说:
    “( ⊙o⊙ )哇 这么大”
     回复 引用 查看   
  25. #59楼 s1ihome      2009-06-28 12:05
    进步太大了,我没觉得可读性比2.0更高反而觉得更加晦涩难懂了。
     回复 引用 查看   
  26. #60楼 asheng      2009-06-28 12:55
    是 C#好,java也不是不好
    只是各有优缺点吧
    还是别一棍子打死的好
     回复 引用 查看   
  27. #61楼 装配脑袋      2009-06-28 13:33
    于此没有诚意的拯救相比,是不是我的VBF更值得一看呢^_^
    特别是在2005年的上下文之中
     回复 引用 查看   
  28. #62楼 装配脑袋      2009-06-28 13:45
    C# 3.0之新特性,C#2不能拥有,本身就是这个语言设计的悲哀。为何不能让开发者自己补充语法呢?本质就是“补充语法”这件事情没有很好地抽象出来,没有这方面设计的模型。

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

    至于这方面的尝试,尽请期待……
     回复 引用 查看   
  29. #63楼 testtest[未注册用户]2009-06-28 13:53
    借个地方说话,最近看Webcast老赵的MVC讲座,总感觉声音小小的,老赵同志下次录讲座时能不能大声点啊,听得很费劲啊,拜托。
     回复 引用   
  30. #64楼[楼主] Jeffrey Zhao      2009-06-28 14:34
    @炭炭
    这个积木是什么做的,这个是改变不了的。这就是我说的,类库框架弥补不了语言缺陷。
    而且,积木的材料也会影响搭建方式,语言是会影响大量涉及的。
    最近在看mina的源代码,对于Java缺少语言特性而造成的大量Future类,我觉得真是冗余啊。

    还有说到架构师,如果你不了解不同语言,你很难做出好的架构决定。
    例如,为什么Twitter实用Rails做前端,后端用Scala做消息传递平台,而不是Java?
    为什么用Twitter用了大量的Actor机制,配合mina进行使用?
    此外,架构师还需要决定一个技术选择后所带来的生产力,如你的项目是否需要强类型检查?duck typing使用到什么程度?
    你现在看轻的,觉得“理所当然”而不去思考的东西,到最后很容易成为你的瓶颈。
     回复 引用 查看   
  31. #65楼[楼主] Jeffrey Zhao      2009-06-28 14:36
    @yeml
    这个东西是基础,涉及到思维方式,一味追求“深入”我不觉得有什么效果。
    就好比我自己的感受,如果不了这些,是很难突破一些东西的。
    如果你觉得这些比较没有意义的话,以后很多东西你也理解不了啊,因为思维是连续的。
    例如,我接下来会在C#里的Actor模型提供一个Dispatcher,为了弥补缺少模式匹配的遗憾。
    但是,这个就是要了解“语言”,了解为什么需要模式匹配,它的含义和作用是什么才能想到的补充方式。
    否则你就算知道了现在的做法,遇到其它问题还是没法自己想办法出来。
    我认为思维方式才是有价值的,但是好像大家都喜欢看一个结论,有时候让我无可奈何。

    // 当然,客户端程序有其特殊考虑,这个没有办法,不过我就讨论语言特性。
     回复 引用 查看   
  32. #66楼[楼主] Jeffrey Zhao      2009-06-28 14:37
    @asheng
    又是套话,你说一个Java语言的“优势”出来呢?
    我对Java的了解不比C#少。
    // 是Java语言,不是Java平台。
     回复 引用 查看   
  33. #67楼[楼主] Jeffrey Zhao      2009-06-28 14:41
    @装配脑袋
    我这个拯救很有诚意啊,是可以直接用在生产环境下的。现在我写C# 2.0就会用到这个方式。
     回复 引用 查看   
  34. #68楼[楼主] Jeffrey Zhao      2009-06-28 14:47
    @testtest
    这个应该是MSDN WebCast录音的问题,可以去向MSDN WebCast那里提一下意见,如果我声音再想,就变大吼大叫了,呵呵。
     回复 引用 查看   
  35. #69楼[楼主] Jeffrey Zhao      2009-06-28 14:52
    @s1ihome
    因为你没有去了解C# 3.0的写法,所以会觉得晦涩难懂,等你了解之后就好了。
    所以我建议你使用C# 3.0一个月,然后再来谈谈感受,呵呵。
     回复 引用 查看   
  36. #70楼 装配脑袋      2009-06-28 14:57
    你想啊,VB2005都没有匿名方法或任何替代品,我都能用现有语法强行模拟Lambda出来。还特别查了编译器代码来寻找可以利用的奇技淫巧,这才叫有诚意啊 :D

    PS. 若想用C#3开发.NET 2程序并且想使用匿名方法的话,无需System.Core,只需自己定义ExtensionAttribute,放在正确的命名空间下即可。使用Lambda更是没有限制。没人知道你是用哪个版本的C#编译的,哪怕是Mono的呢。所以放心用新版编译器吧。。
     回复 引用 查看   
  37. #71楼[楼主] Jeffrey Zhao      2009-06-28 15:05
    @装配脑袋
    脑袋最厉害了,哈哈。
    匿名方法本来就是……理论上CLR 1上的特性啊,当然可以使用了。
    其实如果可以使用C# 3.0的编译器的话,我倒情愿装上.NET 3.5了。
    总之,我现在遇到2.0的项目,都强推3.5的,哈哈。
     回复 引用 查看   
  38. #72楼 装配脑袋      2009-06-28 15:33
    扩展方法啦……口误
     回复 引用 查看   
  39. #73楼 代码乱了      2009-06-28 15:34
    只要稍加调整,可以让.net2.0 同样支持扩展方法,这个我已经试验过了。
     回复 引用 查看   
  40. #74楼[楼主] Jeffrey Zhao      2009-06-28 15:37
    @代码乱了
    扩展方法本来就是语法糖啊,对于CLR 2.0层面上的东西都是可以的。
    包括如果你用到的类库是.NET 2.0就有的,用C# 3.0编译器得到的结果也一样可以运行的。
     回复 引用 查看   
  41. #75楼 代码乱了      2009-06-28 15:40
    @Jeffrey Zhao
    嗯,扩展方法实际上是编译器上面做的文章,只是在3.0后把他发挥到极致
     回复 引用 查看   
  42. #76楼 代码乱了      2009-06-28 15:46
    现在用.net 3.5做项目遇到的最不爽的问题就是,部署,如果客户机器没有装.net framework 3.5,那个部署真叫一个烦啊,不知道精简下来的情况如何了。所以有时候想想.net 2.0还是有点好处的
     回复 引用 查看   
  43. #77楼[楼主] Jeffrey Zhao      2009-06-28 15:49
    @代码乱了
    还好我从来没有做过客户端项目……
     回复 引用 查看   
  44. #78楼 Haozes      2009-06-28 16:09
    老赵,用了你的这个博皮,置顶文章文章不能置顶了哦,你自个试先
     回复 引用 查看   
  45. #79楼[楼主] Jeffrey Zhao      2009-06-28 16:10
    @Haozes
    是的,所以自己Hack吧,呵呵。
    这个问题只有dudu可以解决啊。
     回复 引用 查看   
  46. #80楼 xiaotie      2009-06-28 16:11
    我的大部分是客户端项目,我恨3.5!
     回复 引用 查看   
  47. #81楼 装配脑袋      2009-06-28 16:36
    @xiaotie
    Windows 7来拯救你了。。不过.NET 4.0又来了……
     回复 引用 查看   
  48. #82楼[楼主] Jeffrey Zhao      2009-06-28 16:39
    @装配脑袋
    所以还是做服务器比较好……客户端的话……做开发工具也不错……
     回复 引用 查看   
  49. #83楼 xiaotie      2009-06-28 16:42
    @装配脑袋
    大部分人还在用xp啊,咋办呢
     回复 引用 查看   
  50. #84楼 xiaotie      2009-06-28 16:42
    @Jeffrey Zhao
    程序员没有花钱买开发工具的习惯
     回复 引用 查看   
  51. #85楼[楼主] Jeffrey Zhao      2009-06-28 16:43
    @xiaotie
    嗯嗯,有道理……我从没考虑过卖软件的,所以没有想到……
     回复 引用 查看   
  52. #86楼 WizardWu      2009-06-28 17:28
    等两年后 Windows 7 普及 (内附 .NET 3.x),
    就有希望 C# 3 普及,
    否则客户和老板最大。
     回复 引用 查看   
  53. #87楼[楼主] Jeffrey Zhao      2009-06-28 17:30
    @WizardWu
    还好我只做服务器端产品。
     回复 引用 查看   
  54. #88楼 lhking      2009-06-28 19:33
    只能跟着公司的路线走,新技术确实不错。

    老赵,你的照片挺年轻的
     回复 引用 查看   
  55. #89楼 地狱门神      2009-06-28 20:14
    @Jeffrey Zhao
    我说的是扩展方法,是由C#或者VB编译器在那个扩展方法上附加了
    System.Runtime.CompilerServices.ExtensionAttribute
    这个标记来表示的。
    C#里面增加了定义扩展方法的语法,VB里面没有增加语法。
    不管如何,有这么一个标记,才能使得跨程序集的程序也能使用扩展方法。
    而这个标记是System.Core.dll里新增的。
    不过编译器只要发现现在的程序引用的程序集中在那个命名空间中有那个标记,就能够使用扩展方法。所以做一个dll,只含有那个标记,引用那个dll就能开启扩展方法的功能。
     回复 引用 查看   
  56. #90楼 everthink[未注册用户]2009-06-28 21:17
    没有主持或者参与过较大复杂度的软件项目,就不会明白软件开发的核心问题域。其实语言层面给项目带来的所谓生产力实际上是非常微不足道的。真正能带来生产力提升的是良好的架构。给一个设计非常差或者根本就没有设计的系统扩充功能或改变功能时,又或者去维护一个原来开发者已经早已没了踪影的系统时,你对此就有直观的体会了。
    当然,可能有人说,大不了推翻重做,重新开发个比原来更能满足用户需求的。却不曾想过,推翻重做的成本却又有几何?
     回复 引用   
  57. #91楼[楼主] Jeffrey Zhao      2009-06-28 21:43
    @everthink
    我写这篇文章是说语言重要,又没有说架构不重要,架构自然是重要的。
    不过,语言是会影响系统的设计和架构方式的。
    这里引入一篇文章,里面谈论了Functional Programming对程序的影响:http://lorgonblog.spaces.live.com/Blog/cns!701679AD17B6D310!511.entry
    如果语言差别不大,为什么要有混合编程?为什么系统中不同组件要用不同语言来实现?
     回复 引用 查看   
  58. #92楼 代码乱了      2009-06-28 21:50
    @地狱门神
    这也是我之前的回复要表达的
     回复 引用 查看   
  59. #93楼 DiggingDeeply      2009-06-28 22:14
    C#到底能进化成什么样子呢?我也是从2.0之后有些看不明白了。
    说一点,本人特别不喜欢var这个关键字,确实省力了,但是代码的易读性也没了。
     回复 引用 查看   
  60. #94楼[楼主] Jeffrey Zhao      2009-06-28 22:17
    @DiggingDeeply
    var其实也只是少打一些字,个人认为它是C# 3.0中作用最少的功能之一了。
    当然,它也是为了配合匿名类型这样的新特性出现的。
     回复 引用 查看   
  61. #95楼 DiggingDeeply      2009-06-28 22:24
    @Jeffrey Zhao
    你在啊?
    匿名类型和JSON蛮像;Lambda最初我是在python里看到的,到C#里就看着变扭了,和C、C++家族语言越来越不像了。
     回复 引用 查看   
  62. #96楼 xiaotie      2009-06-28 22:27
    @地狱门神
     回复 引用 查看   
  63. #97楼[楼主] Jeffrey Zhao      2009-06-28 22:32
    @DiggingDeeply
    我觉得C#里的Lambda很漂亮,为什么要和C、C++相像呢?
     回复 引用 查看   
  64. #98楼 DiggingDeeply      2009-06-28 22:43
    @Jeffrey Zhao
    C#既然叫CSharp,还是想继承C系列语言的传统了,本人一家之言。
    我觉得C#在设计上融合了好多语言的特点,这样做不知道是不是为了吸引更多的开发人员更容易上手C#,拉拢开发人员。
    Lambda节省了代码,也同时表明了调用的逻辑,是比较优雅的方式。
     回复 引用 查看   
  65. #99楼 看不惯[未注册用户]2009-06-28 22:55
    1、老赵是个牛人,小弟心仪已久。。。
    2、老赵很虚幻,让小弟景仰之。。。
    3、老赵很无聊,名词太多吓唬人,小弟沉思之。。。
    4、老赵和楼上的丫们,喜欢做MPV不?偶看老赵貌似一个MVPer。。。
     回复 引用   
  66. #100楼 看不惯[未注册用户]2009-06-28 22:56
    WK,独独疯掉了,居然有两个99楼。。。
     回复 引用   
  67. #101楼[楼主] Jeffrey Zhao      2009-06-28 22:59
    @看不惯
    这些名词不是吓唬人来的,如果这也叫多也叫吓唬人的话,随便找一本书来绝对可以让你晕过去了,呵呵。
     回复 引用 查看   
  68. #102楼 Leon Weng      2009-06-29 08:12
    --引用--------------------------------------------------
    看不惯: WK,独独疯掉了,居然有两个99楼。。。
    --------------------------------------------------------

    是何原因?
     回复 引用 查看   
  69. #103楼 装配脑袋      2009-06-29 08:43
    @地狱门神
    你只需自己定义 System.Runtime.CompilerServices.ExtensionAttribute
    类型即可,无需引用System.Core.dll

    另外,自己定义还可以将它放开为定义在属性上(原本仅仅能定义在方法上)。这样在VB里,属性也可以扩展的哦(C#仍然是不行滴)。
     回复 引用 查看   
  70. #104楼[楼主] Jeffrey Zhao      2009-06-29 09:12
    @Leon Weng
    有一定几率发生,一般总是同步上的问题。
     回复 引用 查看   
  71. #105楼 麒麟.NET      2009-06-29 10:51
    跟领导提过很多次将项目升级到3.0,但是得到的回复是:只要现有技术能满足业务需求即可,产品的稳定才是最重要的,我们只需要最稳定的技术,不需要最先进的技术。

    其实,我很无语……
     回复 引用 查看   
  72. #106楼[楼主] Jeffrey Zhao      2009-06-29 10:52
    @麒麟.NET
    很多时候只是个借口,例如为啥说.NET 3.5不稳定,估计领导也说不出理由来。
     回复 引用 查看   
  73. #107楼 麒麟.NET      2009-06-29 11:15
    其实所谓的稳定与否是指开发人员对技术的熟练程度……,领导怕开发人员对技术不熟导致效率和稳定性降低……

    哎,啥也不说了,继续无语……
     回复 引用 查看   
  74. #108楼 妖居      2009-06-29 11:55
    记得以前 装配脑袋 曾经用2.0下的VB做了一个类似3.0功能的类库,让2.0的VB可以支持函数式编程和LINQ之类的东西。好像实现方法和老赵的差不多。
     回复 引用 查看   
  75. #109楼 伟zzz[未注册用户]2009-06-29 13:22
    同意四楼的,
    #4楼 没办法啊。 [未注册用户]
    2009-06-27 22:14
    2.0的包在没装。net的机子上引用打包才十来M
    但是3.5的就到了100多M了,这个选择很无奈啊

    B/S结构的还好,如果遇上C/S结构的,如果3.0以上的框架那个东东部署起来就麻烦了,安装包大,安装起来也慢,2.0的框架大小与安装速度都还凑合,啥时候3.0或以上的框架如果能弄个精简版的打包程序,俺就第一时间换
     回复 引用   
  76. #110楼 罗里罗嗦夫斯基      2009-06-29 13:41
    文中提及的语法可以看一下,至于标题的拯救2.0就没有必要了,3.0版本升级而已。难道4.0出来了后,还要拯救3.0了吗?

    建议把标题改为<C#3.0新增语法之一>
     回复 引用 查看   
  77. #111楼 韦恩卑鄙      2009-06-30 22:23
    vb的 linq to xml 生产力还真是高到不行 c#死活不支持
    我恨阿
     回复 引用 查看   
  78. #112楼 RednaxelaFX      2009-07-02 04:36
    @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语言的话,语法结构完全可以在运行时由程序员来指定,那么想封装什么结构都很容易,要写起库来也就会更灵活(写库的同时也就是在创作一个小型语言)。
     回复 引用 查看   
  79. #113楼 吴碧宇      2009-07-02 14:35
    一直希望使用Lambda 表达式但一直没有得到Lambda 表达式的一个较详的性能上的分析,固迟迟敢下手。
    希望老赵能否对Lambda 表达式的 效率做一个详细的分细。
     回复 引用 查看   
  80. #114楼[楼主] Jeffrey Zhao      2009-07-02 14:36
    @吴碧宇
    放心用吧,没有问题。
    Lambda Expression构建的委托和普通委托,编译后一模一样。
     回复 引用 查看   
  81. #115楼 葛云飞      2009-07-02 16:00
    lamda表达和Linq to SQL
    确实是很强的东西
    分部方法也是一样
    原来不以为然,但是在开发中发现真是好用。

    我觉得C#正在向一种非常唯美的方向的发展
     回复 引用 查看   
  82. #116楼 RednaxelaFX      2009-07-02 23:29
    说起来,C# 3.0的lambda在Mono.Options库里也得到了有趣的应用,看例子:http://tirania.org/blog/archive/2008/Oct-14.html
    这个库是用来解析命令行参数的
     回复 引用 查看   
  83. #117楼 吕不为[未注册用户]2009-08-02 21:01
    呵呵,讨论的不错。我发一个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年前就支持这种东西。
     回复 引用   
  84. #118楼[楼主] Jeffrey Zhao      2009-08-02 21:46
    @吕不为
    早在2、30年前搞函数式编程的时候这些就可以有了,如今在F#里也是支持的,但是Java/C++至今没有。
    这东西也是个语言设计者的选择问题,Java太弱,F#太强太复杂,C#是我感觉平衡的相当好的。
     回复 引用 查看   
  85. #119楼 镜涛      2009-08-03 20:41
    呵呵,看了老赵的文章总会有些顿悟的东西,给自己带来很大帮助。不知老赵的msn是??有些问题请教下!
     回复 引用 查看   
  86. #120楼[楼主] Jeffrey Zhao      2009-08-03 21:27
    @镜涛
    右下角的Web Messenger吧。
     回复 引用 查看   
  87. #121楼 菜鸟毛      2009-08-14 11:08
    发表一点愚见,那些where,select等方法,只有在集合的时候才能发挥作用吧.平常时候好像没有什么作用啊.让您见笑.
     回复 引用 查看   
  88. #122楼[楼主] Jeffrey Zhao      2009-08-14 11:12
    @菜鸟毛
    这个自然,哪有什么可以操作任何东西的,不过集合操作太常见了。
     回复 引用 查看   
  89. #123楼 peipei[未注册用户]2009-08-15 13:06
    夜郎自大
     回复 引用   
  90. #124楼 邀月      2009-09-08 22:55
    老实说, 我不想介入什么语言之争,因为我任何一门都没能熟练掌握,更谈不上深入研究了。仅就楼主的一句话发表个人看法:
    “那么C# 3.0已经将Java甩开地太远太远。”这话有点不能服众。语言是一种工具,高效的生产力是它的最基本特性。c# 3.0真的那么优秀,为什么那些中高端用户会视而不见?它自身有一些无法克服的弱项。而恰恰对手java又具备了这些。语言优劣恐怕是本世纪最无厘头的话题之一了吧。
     回复 引用 查看   
  91. #125楼[楼主] Jeffrey Zhao      2009-09-08 23:04
    @邀月
    您既然没有熟练掌握任何一门语言,又何谈说语言优劣是最无厘头的话题呢?
    您难道认为,那么多研究语言,发明语言的科学家们都是吃干饭的吗?
    您能否可以解释一下,为什么新语言还是层出不穷呢?
    轻视语言是国内计算机教育的弊病,当然,国内轻视的东西实在太多了,所以普遍水平上不去。
    可以这么说,轻视是因为眼界狭隘,眼界狭隘又反过来导致轻视各种东西。

    谁说中高端用户对C# 3.0视而不见?Java领域许多大牛都赞同C#现在比Java优秀很多。
    用Java多,是因为其他人想要用Java平台,而当时Java平台只有Java语言一个选择而已。
    但是,现在Java平台上有Scala,Groovy,Clojure多种选择,Java语言就靠边站吧。
    时间会证明一切的,看近几个月来Scala的蓬勃发展,社区对Project Coin怨声载道,还不能说明问题吗?
     回复 引用 查看   
  92. #126楼 邀月      2009-09-09 10:20
    引用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真的很优秀!那就证明给大家看吧!但短期内应该不会是一枝独秀!
     回复 引用 查看   
  93. #127楼[楼主] Jeffrey Zhao      2009-09-09 10:24
    @邀月
    我只是说Java语言不行,我有要求别人不使用Java平台吗?我四处推荐大家使用Java平台+Scala语言,被你直接忽略了?
    我总是希望在讨论时逻辑可以清晰一点,知道我在讨论什么,讨论语言时就讨论语言,又把平台扯进来做什么。
    我也从没有说过C#是一枝独秀,不知道你是怎么理解的。我平时除了用C#,也用Scala,F#,JavaScript,也很喜欢Haskell。
    C#别说短期,永远不可能一枝独秀,因为C#肯定不适合所有情况,我也从来不希望C#一枝独秀。

    我的观点只有一个:C# 3.0远超Java语言,用Java语言限制API设计,Java语言浪费代码,编程费时费力。C# 3.0相对要优秀许许多多。
     回复 引用 查看   
  94. #128楼[楼主] Jeffrey Zhao      2009-09-09 10:26
    @邀月
    国内的一大教育方面就是“语言不是关键的”,导致好像要表示自己“客观”,就不能说任何一门语言的坏话,否则就是“档次低”。
    你的质疑其实我也听过无数遍,还有例如就是“我虽然不很了解Java和C#,但是我的心态绝对好”。
    我比较奇怪,既然不很了解,为什么不去了解了再来说话。一直抱有封闭的,认为自己了解的肯定是对的这种心态,如何成长。
     回复 引用 查看   
  95. #129楼[楼主] Jeffrey Zhao      2009-09-09 10:28
    当然,要放弃以前的形成的关键是很痛苦的,我也改变过几次。
    例如,学校一直教育我说语言如何如何,我现在改了。
    例如,学校一直教育我说,开发没前途,要做项目经理,现在我改了。

    根据事实说话,不要凭感觉,找依据,用事实作为靠山,你将立于不败之地。
    “感觉”这种东西,是相当不靠谱的
     回复 引用 查看   
  96. #130楼 邀月      2009-09-09 10:40
    引用Jeffrey Zhao:
    @邀月
    国内的一大教育方面就是“语言不是关键的”,导致好像要表示自己“客观”,就不能说任何一门语言的坏话,否则就是“档次低”。
    你的质疑其实我也听过无数遍,还有例如就是“我虽然不很了解Java和C#,但是我的心态绝对好”。
    我比较奇怪,既然不很了解,为什么不去了解了再来说话。一直抱有封闭的,认为自己了解的肯定是对的这种心态,如何成长。

    楼主:我在学校学的是数学教育。开发是后来兴趣和机遇使然。自己仅有的一点技能是自己摸索的或在一些论坛或网站像code Projects,msdn.com,souurceforge.net,ibm developworks等了解的。也没有参加什么北大青鸟之类的。所以谈不上什么随众吆喝。如果有这种印象,那说明我认识世界的方法观有问题,我自我检讨!
    引用Jeffrey Zhao:
    当然,要放弃以前的形成的关键是很痛苦的,我也改变过几次。
    例如,学校一直教育我说语言如何如何,我现在改了。
    例如,学校一直教育我说,开发没前途,要做项目经理,现在我改了。

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

    我虚心接受老赵的观点,学习中了解,事实中成长。
     回复 引用 查看   
  97. #131楼[楼主] Jeffrey Zhao      2009-09-09 10:41
    @邀月
    别介意,后面几句牢骚不是对你说的,赫赫。:)
     回复 引用 查看   
  98. #132楼 邀月      2009-09-09 10:47
    引用Jeffrey Zhao:
    @邀月
    别介意,后面几句牢骚不是对你说的,赫赫。:)

    在项目中经历无数次的观点碰撞了!该学习的学习,该接受的接受,实在不能接受的,那就剖析它,把它的优秀成分吸收起来。
    感谢老赵的回复。我的观点是:学无止境,学以致用。
     回复 引用 查看   
  99. #133楼 上山打老虎      2009-09-18 10:47
    引用Jeffrey Zhao:@chegan<br/>嗯嗯,只可惜不少时候,这样的人会被认为是高手,不断地影响后人。<br/>所以,我现在很看不惯这样的情况。


    这个很重要啊,新手都是向老手学习的。
     回复 引用 查看   
  100. #134楼[楼主] Jeffrey Zhao      2009-09-18 10:54
    @上山打老虎
    可惜现在看来,社区需要的是“和谐”。我对某高手提出质疑时,被无数人指责人品不好,呵呵。
     回复 引用 查看   
  101. 评论共2页: 上一页 1 2 
发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 1512390 ymWOU5E0eAE=