Hello World
Spiga

谈谈年度最佳代码“不管你们信不信,反正我信了”

2011-08-05 23:15 by 老赵, 20332 visits

最近有段十分流行的代码,是从江湖传闻“身怀八蛋”的铁道部发言人王勇平同志的一句名言:“不管你们信不信,反正我信了……这是生命的奇迹……它就是发生了”所引申出来的。这段代码虽然只是在调侃,但是围绕这段代码也产生了一些讨论(如代码风格,编程规范等等),在此顺手记录一下,就当无聊罢。

这段代码是这样的:

try
{
    if (you.believe(it) == true || you.believe(it) == false)
    {
        I.believe(it);
    }
}
catch (Exception ex)
{
    throw new Exception("It's a miracle!");
}
finally
{
    it.justHappened();
}

代码与原文的对应关系不言自明,从命名风格上看,我们默认其为Java代码。话题主要是围绕在if条件的写法上。

书写风格

先来看看它的书写风格问题。我说这段代码不是老鸟写的,因为老鸟不会把一个布尔表达式跟true和false直接判断,而会写成:

if (you.believe(it) || !you.believe(it))

于是有朋友提出,把布尔表达式跟true或false相比较来的更清晰一些,我表示这话并没有什么道理,因为这种读代码的方式是把视角停留在“数据”层面上:一个布尔表达式返回了布尔型的“数据”,于是把它和另外一个“数据”进行比较。如今的编程都在不断强调“语义”,“语义”的清晰才是真的清晰。我说Java是一门糟糕的语言,主要原因就是指它的表达能力太差,导致写出来的代码体现不出问题的解决方式,让人们把目光都集中在具体每条语句上了,所谓“见木不见林”。C#等现代语言都在强调“做什么”而不是“怎么做”,语义上就有很大提高了。

回到目前这个具体问题上,if里面的语义是“you.believe(it)”的返回结果,而不是它的值与另外一个布尔常量的比较结果。其实这个观点我从初中搞信息学竞赛时就被老师不断强调,今天我同样咨询了同事,他也赞同我的观点。如果您还继续坚持这种写法不太清晰的话,我只能说“这只是不适应而已,要让自己适应这类写法”,很多人还觉得LINQ不清晰呢,小学生还觉得高中数学的解法不清晰呢。

还有朋友认为,作为编码规范,应该要求这么写,例如:

if (10 == i)

就是说,把常量写在比较操作的左边,并认为“这样更有普遍意义”。其实这也没有必要,这个习惯是从C语言时代遗传下来的“陋习”。在C语言里,如果把常量写在比较右侧,并且一不小心把“比较”操作符(两个等号)写成“赋值”操作符(一个等号),也可以编译通过,但是结果却大不相同,这给错误排查也会带来许多麻烦。但是,在如今的语言里已经比C语言做的安全多了,所以没必要制定这种规范。把一种语言的标准带入另一种语言不叫做“有普遍意义”,只是多余。

代码含义

然后要谈的便是代码与那句话的“映射”关系了,再来仔细读一下这个if子句:

if (you.believe(it) || !you.believe(it))
{
    I.believe(it);
}

从“需求”上来理解,我认为代码应该保证if内部的代码一定会执行。那么现在这个需求肯定会满足吗?不一定,因为you.believe方法可能是有副作用的:如果它第一次调用返回false,而第二次调用时返回true,则if内部的代码就会整段略过,这显然不是铁道部王发言人的意图。因此,有同学提议代码应该是这样的:

if (true || you.believe(it))

这么做的确可以忽略you.believe(it)的结果,因为它已经被短路了根本不会执行。可能它也能满足需求,但我想更合理的做法可能应该是:

if (you.believe(it) || true)

这段代码与之前的区别就在于you.believe(it)一定会被调用一次,但是无所谓其结果是如何,这充分符合天朝某些部门喜欢装摸作样“咨询民意”的状况。

扩展思考

最后再来一道扩展思考题吧:有人把“你爱,或者不爱我,爱就在那里,不增不减”写成了一段C#代码:

if (you.Love(me) || !you.Love(me))
{
    love++;
    love--;
}

有人说,这段代码的if条件本身应该被编译器优化掉,因此会直接执行if内部的代码。还有人说,if内部的代码也会被编译器优化掉。您怎么看,为什么呢?

Creative Commons License

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

Add your comment

78 条回复

  1. SNAKE
    220.200.31.*
    链接

    SNAKE 2011-08-05 23:22:48

    最后一个问题我想我现在的回答是:写出代码,看其IL代码,再作结论.

  2. Dozer
    180.152.91.*
    链接

    Dozer 2011-08-05 23:24:47

    最后一个,就像前面说的,会有副作用,所以应该不会被编译器优化掉吧?

  3. 老赵
    admin
    链接

    老赵 2011-08-05 23:31:01

    @SNAKE

    想这么简单你就败了……

  4. 老赵
    admin
    链接

    老赵 2011-08-05 23:31:36

    @Dozer

    最后其实提出了两个问题,你都不说清楚是哪个。

  5. lijinfeng042
    222.65.175.*
    链接

    lijinfeng042 2011-08-05 23:34:29

    看问题的角度不同啊,果然是...差距啊 都是些很常见的东西,信手拈来就是不同了

  6. cui
    125.69.147.*
    链接

    cui 2011-08-05 23:35:38

    如果它第一次调用返回false,而第一次调用时返回true typo?

  7. 链接

    JeffWong 2011-08-05 23:43:16

    编译器的优化和设计一点不懂,但是我认为一个人写了一段代码,然后编译器将其优化掉,没有完全满足Coder的真实意图,这样的优化也是有严重副作用的。比如最后一段代码,我让“你爱,或者不爱我,爱就在那里,不增不减”执行一百万次,没有别的意图,就想看看服务器执行有多快,但是编译器优化掉完全无法得到真实的结果。所以我认为智能的编译器设计原则不能以牺牲代码的真实执行意图为代价。

  8. 老赵
    admin
    链接

    老赵 2011-08-05 23:49:04

    @JeffWong: 所以我认为智能的编译器设计原则不能以牺牲代码的真实执行意图为代价。

    这句话是没错,但是编译器只要保证的是代码的执行结果正确(这是真实意图)就行了,速度当然是越快越好,指令能少执行一些当然也是好事,所谓“没有别的意图,就想看看服务器执行有多快”就比较无厘头了。

  9. ericpoon
    183.5.22.*
    链接

    ericpoon 2011-08-05 23:54:40

    要看IL代码,但不晓得怎么知道是否被优化。

  10. 链接

    JeffWong 2011-08-05 23:57:26

    那我写个循环100万次,间接替代Thread.Sleep,这样可不可以呢?反正我的真实意图是看执行的时间开销,而优化的结果很可能是一点时间都不花嘛。当然这种想法确实是无厘头的。

  11. 链接

    小城故事 2011-08-05 23:57:30

    根据《.Net设计规范》,任何时候都不能抛出Exception异常,由于铁道部的异常非比寻常,所以一定要定义一新异常类型:MiracleException

  12. PinkLi
    114.249.136.*
    链接

    PinkLi 2011-08-06 00:01:47

    因为you.believe方法可能是有副作用的:如果它第一次调用返回false,而第一次调用时返回true,则if内部的代码就会整段略过

    这段里“而第一次调用时返回true”,应该是“第二次”,笔误吧

  13. PinkLi
    114.249.136.*
    链接

    PinkLi 2011-08-06 00:16:24

    "爱就在那里,不增不减"隐含的意义应该是指“我的爱不变”,

    love++;
    love--;
    

    要不要写成

    me.Love = SOME_CONSTANT_INITIAL_VALUE;
    

    哈哈

  14. 老赵
    admin
    链接

    老赵 2011-08-06 00:24:44

    @JeffWong

    所以你就不要搞这种无厘头的想法了,想点正经的……

  15. anonymous
    115.192.108.*
    链接

    anonymous 2011-08-06 00:37:11

    老赵最后给的扩展故意把上下文省略不说来抛出问题。编译器能做的优化极大程度依赖于上下文提供的信息。省略掉就意味着要分情况讨论。要讨论多深又是另外一回事。

    那么建立其中一种可能的上下文:

    1. you是局部变量,它指向的是一个Shitizen类型的对象实例。
    2. Shitizen类上有非虚成员方法bool Love(object o)
    3. bool Shitizen.Love(object o)的实现是return true;;关键在于无副作用。
    4. love是int类型的局部变量,前面已经有初始化。

    设定这样的上下文,放在CLR上跑,

    • 非虚的小方法可以内联,这样if (you.Love(me) || !you.Love(me))被内联为if (true || !true)
    • 常量折叠+常量条件折叠,条件化简为if (true),这样原本的分支判断就削除了(原本if语句构成的作用域仍然起作用,但这里正好没影响,因为原本没有在if里声明新的局部变量)
    • Int32是CLR直接支持的内建值类型,并且love是局部变量(意味着它的状态不会逃逸),自增与自减可以做安全的对消
    • 结果:原本例子里的代码完全削除掉。

    前面设定的条件随便改改就可以引出别的推导过程和结论。楼下的各种猿们继续

  16. Kevin Wei
    114.249.229.*
    链接

    Kevin Wei 2011-08-06 00:39:14

    不错,这都能研究出来个所以然,厉害!

  17. zjx
    204.152.218.*
    链接

    zjx 2011-08-06 00:46:22

    代码命名上有一些问题you.believe(it)和I.believe(it),这两个函数是不一样的,因为一个是是否相信,一个是相信了

    所以可以考虑

    you.believe+or_not(it) 和 I.believe(it,true)

  18. 老赵
    admin
    链接

    老赵 2011-08-06 00:53:31

    @anonymous

    你得到了它,要分情况讨论的。

  19. KingBright
    122.96.13.*
    链接

    KingBright 2011-08-06 01:35:39

    我也来说几句自己的见解,其实要语义的清晰,只要是面向对象的语言都能表达的比较好吧,就像上面那位 zjx 说的,把you.believe()写成you.believeOrNot()能使语义更清晰,而I.believe()可以永远返回true。反正一般我写代码只要返回boolean值,特别是方法是用于判断的,都会加上is等前缀,或者OrNOt等后缀,使方法作用一目了然。

    这样一讨论的话,就能引申出作者最后提出的问题了,关键的方法的实现没给出,所以,需要根据实际情况讨论,但是至少love++和love--是能抵消的吧。

    现在我看到有些同事写判断还是这样的:

    String s="abc";
    if("".equals(s)){
        ...
    }
    

    我表示压力很大,我觉得至少也要尽可能的把一些常量先定义一下,避免使用硬编码,既不利于理解,也不利于维护。而且我也更偏好于把比较对象也在方法外面,把常量值作为方法参数传进去。

    仅代表个人愚见。

  20. lixiong
    58.41.84.*
    链接

    lixiong 2011-08-06 01:48:50

    if (you.believe(it) || true)
    

    这个如果是C代码的话, 由于从右往左运算, .believe不会执行的. 当年刚刚转到C#的时候老写错. 至于最后的love, 至少被某关键字修饰的时候, 不会被优化掉. 这个love说不定是个全局变量, 很多thread在用呢.

  21. anonymous
    115.192.108.*
    链接

    anonymous 2011-08-06 01:56:17

    C才没规定从右向左运算呢。如果有的话请在C语言规范里找出相关规定。

  22. yixianggao
    222.131.43.*
    链接

    yixianggao 2011-08-06 02:00:01

    其实“不管你信不信,反正我信了”这句话根本不应该用if语句表达此语义,并且类设计也的有问题,而用try...final...表达更为准确:

    try {
        rearEndAccident.ConfirmBy(isBelieve, you);
    } 
    final {
        rearEndAccident.ConfirmBy(true, me);
    }
    

    老赵意下如何?

  23. kusk
    124.127.78.*
    链接

    kusk 2011-08-06 09:51:23

    @lixiong:

    C的&&、||是从左到右求值,带短路。所以才有类似 if (p != NULL && p->data) { ... } 这样的惯用写法。若是从右向左求值,p为空时先跑 p->data 会crash.

  24. zzfff
    123.249.127.*
    链接

    zzfff 2011-08-06 11:26:36

    • AndAlso

    (e1) && (e2) 等价于 ((e1) == false) ? false : (e1) & (e2)

    • OrElse

    (e1) || (e2) 等价于 ((e1) == true) ? true : (e1) | (e2)

    e1只会评估一次,e2不一定会评估

    每个称职的同学都该深入System.Linq.Expressions:)

  25. zzfff
    123.249.127.*
    链接

    zzfff 2011-08-06 12:01:41

    (上面的等价代码只说明程序的语义)

  26. zzfff
    123.249.127.*
    链接

    zzfff 2011-08-06 12:17:06

    抄点expr-tree-spec.pdf:

    There are some additional complexities with AndAlso/OrElse, in particular combining overloaded operators and nullables. Here is the comment from BinaryExpression.cs:

    // For a userdefined type T which has op_False defined and L, R are
    // nullable, (L AndAlso R) is computed as:
    //
    // L.HasValue
    //     ? T.op_False(L.GetValueOrDefault())
    //         ? L
    //         : R.HasValue 
    //             ? (T?)(T.op_BitwiseAnd(L.GetValueOrDefault(), R.GetValueOrDefault()))
    //             : null
    //     : null
    //
    // For a userdefined type T which has op_True defined and L, R are
    // nullable, (L OrElse R)  is computed as:
    //
    // L.HasValue
    //     ? T.op_True(L.GetValueOrDefault())
    //         ? L
    //         : R.HasValue 
    //             ? (T?)(T.op_BitwiseOr(L.GetValueOrDefault(), R.GetValueOrDefault()))
    //             : null
    //     : null
    //
    
  27. luotong
    123.9.195.*
    链接

    luotong 2011-08-06 12:58:18

    妙哉 妙哉...

  28. AnonymousRoot
    218.201.112.*
    链接

    AnonymousRoot 2011-08-06 17:04:11

    love++; love--; 不是不增不减额

  29. hamigua
    125.122.174.*
    链接

    hamigua 2011-08-06 21:06:31

    学习了!!收获很多啊。

  30. lixiong
    58.41.84.*
    链接

    lixiong 2011-08-06 21:46:13

    原来C的时候我就错了,C只是部分运算符是Right Operator associativity,具体的在这个表:

    http://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B#Operator_precedence

  31. 陈澄
    218.82.161.*
    链接

    陈澄 2011-08-06 21:59:34

    回答最后的扩展题:两者都不会被优化。(1)因为函数默认是有副作用的 (2)love的类型没确定呢

  32. 陈澄
    218.82.161.*
    链接

    陈澄 2011-08-06 22:01:27

    刚才第(2)点没说清楚,我的意思是++操作符也会是方法调用(有副作用),因此不会被优化。

  33. 链接

    lengleng3898 2011-08-07 19:51:38

    try
        if
            believe it || not
        then
            i believe it
     with
        | _ -> 
            raise (System.InvalidOperationException(
                    "It's a miracle!"))
     it just happened
    
  34. superbryant
    125.91.21.*
    链接

    superbryant 2011-08-08 11:26:43

    老赵,请教一个问题,一个合格的程序员需要具备哪些方面? 很喜欢你的签名"先做人,再做技术人员,最后做程序员。"

  35. fatbigbright
    60.29.117.*
    链接

    fatbigbright 2011-08-08 13:16:55

    我认为对于“不增不减”,可不可以把大括号中的代码写成//love++;及//love--;?

  36. 鹤冲天
    218.59.74.*
    链接

    鹤冲天 2011-08-08 16:04:18

    要表达语义,还得用扩展方法:

    IThing it = null;
    IPerson you = null;
    IPerson I = null;
    //...
    Predicate<IThing> youBelieve = you.Believe;
    try
    {
        if (youBelieve.OrNot(it))
        {
            I.Believe(it);
        }
    }
    catch (Exception ex)
    {
        throw new Exception("It's a miracle!");
    }
    finally
    {
        it.JustHappened();
    }
    

    扩展方法参考实现:

    public static class Extensions
    {
        public static bool OrNot<T>(this Predicate<T> func, T t)
        {
            return func(t) || !func(t);
        }
    }
    

    接口定义:

    public interface IThing
    {
        void JustHappened();
    }
    
    public interface IPerson
    {
        bool Believe(IThing thing);
    }
    
  37. 鹤冲天
    218.59.74.*
    链接

    鹤冲天 2011-08-08 16:24:47

    或者:

    object it = null;
    IPerson you = null;
    IPerson I = null;
    
    if (((WhatEver)you.Believe).OrNot(it))
    {
        I.Believe(it);
    }
    

    扩展方法、委托和接口:

    public delegate bool WhatEver(object obj);
    
    public static class Extensions
    {
        public static bool OrNot(this WhatEver func, object t)
        {
            return func(t) || !func(t);
        }
    }
    
    public interface IPerson
    {
        bool Believe(object thing);
    }
    
  38. 链接

    鹤冲天 2011-08-08 16:35:47

    没登录,不能修改评论,只好再发一个强类型版本的:

    IThing it = null;
    IPerson you = null;
    IPerson I = null;
    
    if (((WhatEver)you.Believe).OrNot(it))
    {
        I.Believe(it);
    }
    

    扩展方法、委托和接口:

    public delegate bool WhatEver(IThing obj);
    
    public static class Extensions
    {
        public static bool OrNot(this WhatEver func, IThing t)
        {
            return func(t) || !func(t);
        }
    }
    
    public interface IPerson
    {
        bool Believe(IThing thing);
    }
    
    public interface IThing
    {
    }
    
  39. zzfff
    61.184.206.*
    链接

    zzfff 2011-08-08 16:42:27

    看见楼上的发言,来点感想:)

    var x = new[] { 1, 2, 3 };
    var y = new List<string>();
    
    //方法一
    y.AddRange(x.Select(i =>
    {
        //...
        return i.ToString("X");
    }));
    
    //方法二
    foreach (var i in x)
    {
        //...
        y.Add(i.ToString("X"));
    }
    

    方法一和方法二谁能清楚的表达作者的意图?

  40. 老赵
    admin
    链接

    老赵 2011-08-08 17:09:53

    @鹤冲天

    哈哈,你还真是会滥用扩展方法啊……

  41. dreign
    222.44.51.*
    链接

    dreign 2011-08-08 17:15:29

    C#代码:

    class Program
    {
        static void Main(string[] args)
        {
            var me = true;
            TestLove(me);
        }
        private static void TestLove(bool me)
        {
            var love = 0;
            if (you.Love(me) || !you.Love(me))
            {
                love++;
                love--;
            }
            Console.WriteLine("in you heart,I am " + love.ToString());
            Console.ReadLine();
        }
    }
    class you
    {
        public static bool Love(bool me)
        {
            return me;
        }
    }
    

    下面是对应的IL代码,可以看到.net并不会优化掉++、--操作:

    http://images.cnblogs.com/cnblogs_com/dreign/59717/r_il.jpg

  42. 链接

    鹤冲天 2011-08-08 18:10:31

    @老赵

    呵呵呵呵,这是我唯一善长的。

  43. 老赵
    admin
    链接

    老赵 2011-08-08 23:56:43

    @dreign

    你确定你用了Release编译?你确定这两条IL指令在JIT之后还存在?

  44. anonymous
    115.193.163.*
    链接

    anonymous 2011-08-09 00:33:27

    @dreign

    你只演示了csc没优化++与--,真正的优化在CLR的JIT里。

    奇怪,这帖装配脑袋居然没来说几句

  45. thelONE
    118.34.242.*
    链接

    thelONE 2011-08-09 00:52:16

    if (you.Love(me) || !you.Love(me))
    {
        love++;
        love--;
    }
    

    这里的Love函数本身就有可能有副作用, love也有可能是重载了操作符的对象, 另外还有可能其他线程对这个变量进行访问. 总的来说这段代码提供的信息太有限了. 另外据我所知现在的编译器在这种操作的优化上是非常谨慎的, 编译器总是在假设最坏的情况, 不出错才是最重要的.

  46. 老赵
    admin
    链接

    老赵 2011-08-09 10:12:00

    @thelONE

    嘿嘿,其实我就是想得到你这样的答案。

    编译器的职责之一就是保证程序正确,所以肯定很谨慎的。当然反过来说,只要不出错,各种优化手段也可以很激进。

  47. 屋顶海洋
    58.32.228.*
    链接

    屋顶海洋 2011-08-10 11:54:50

    哈哈,这一段不错 if (you.believe(it) || true)

  48. kennylee
    113.65.137.*
    链接

    kennylee 2011-08-11 12:50:15

    其实if (true | you.believe(it)) 也许表达意思更加贴切

  49. 豆子
    163.125.82.*
    链接

    豆子 2011-08-12 09:12:19

    try {
        MOR.doRescue(workers,CRH);
    } catch (SomeOneStillAliveException e) {
        final Person morSpokesman = MOR.getSpokesman();
        final Person youOrMe = China.getSomeOneRandom();
        if(youOrMe.believe(CRH_REAR_END) || !youOrMe.believe(CRH_REAR_END)){
            morSpokesman.makeBelieveChoice(CRH_REAR_END);
            morSpokesman.say("这是个奇迹");
        }
    }
    
  50. 链接

    Leo 2011-08-17 17:01:07

    这个是不是可以诠释Jeffery zhao的 追求编程之美。哈哈

  51. barry
    60.63.80.*
    链接

    barry 2011-08-17 22:47:42

    受益匪浅。 编译器的优化都需要付出一定的代价,也许就会造成程序结果的出错。

  52. 老赵
    admin
    链接

    老赵 2011-08-18 16:17:09

    @barry

    优化的基本要求就是不出错,出错就是失败,不叫做“代价”,没有把失败叫做“代价”的。

  53. 宁波婚纱摄影
    220.189.18.*
    链接

    宁波婚纱摄影 2011-08-18 16:42:49

    支持一个 博主的文章很实在!!

  54. 浅陌
    124.201.10.*
    链接

    浅陌 2011-08-20 08:55:16

    这篇博文在欢乐之余也让我学习到了老赵是怎么分析一段代码的。

  55. 链接

    ilovehaley.kid 2011-09-02 15:04:29

    学习~学习~学习~

  56. 链接

    老菜 2011-09-15 21:09:46

    学习了。读这篇文章受益匪浅,更加感受到自己一无所知,要努力学习。

  57. 程序诗人
    222.65.163.*
    链接

    程序诗人 2011-09-15 23:00:44

    文章最后的代码,不是语言进行正确使用的初衷呀。 如果编译器能够做到智能判断就好了。

  58. 链接

    yzx21xz@163.com 2011-09-23 16:06:26

    基础非常薄弱说不出理论来,只是留个爪印告之一下我想把这篇留在自己博客园随笔中,以后参考

    不考虑其他情况,套用前面believe所讲的[代码含义]

    if (you.Love(me) || !you.Love(me)) { love++; love--; }

    首先if (you.Love(me) || !you.Love(me))不会被优化掉。

    但是会有副作用,如果第一次“你爱我”返回true,第二次返回false,括号内语句会被略过。 (在这里请问,第二次是指执行you.Love方法的第二次,还是对这条判断语句执行第二次,我猜测可能是前者,在一次判断条件里,一个方法执行两次,分别返回true 和 false,确实有点不合理,直接跳过?)

    至于 i++; i--; 会否被优化掉?为什么?

    不会被优化掉,参见(dreign 2011-08-08 09:15:29的回复),原来IL是做这个的,很有兴趣学一下。

  59. Sasoritattoo
    183.17.35.*
    链接

    Sasoritattoo 2011-09-26 21:42:50

    真是高手过招啊,感觉就像是每人拿着一根头发就分出了胜负。。。。 看的人却感觉异常的精彩!!!

  60. rq2
    114.80.140.*
    链接

    rq2 2011-09-30 11:04:26

    在娱乐的时候还想着严谨。所以程序员分木讷与不木讷两种(此分类不严谨)。做科学需要木讷。在香港娱乐圈就不需要这个。

  61. stackpop
    202.120.50.*
    链接

    stackpop 2011-10-10 22:27:34

    呵呵,老赵果然高手~

  62. 利丰
    113.83.131.*
    链接

    利丰 2011-11-11 17:36:43

    王勇平同志太悲剧了~~呵呵

  63. 鹏雕
    222.39.20.*
    链接

    鹏雕 2011-11-13 16:43:27

    很喜欢看你的博客,学习的榜样

  64. vikeyxp
    113.97.34.*
    链接

    vikeyxp 2011-11-15 17:11:49

    <?php
    
    if(it->be_people()&&it->learned){it->people=true;};
    
    if(it->be_technician()&&it->people){it->technician=true;};
    
    if(it->be_programer()&&it->technician){it->programer=true; };
    
    ?>
    

    ah ha , am i right?

  65. lurenjia
    176.34.2.*
    链接

    lurenjia 2011-12-25 00:59:53

    很是无聊的讨论,作者随意写之,众人随意附之,无错无对,只是浪费时间和资源而已。

  66. Red
    114.88.163.*
    链接

    Red 2012-01-07 19:31:11

    同意楼上.不过有时候无聊也能看出一个人的层次.

  67. ntyangxd
    221.133.237.*
    链接

    ntyangxd 2012-02-10 08:45:14

    其实这个函数 you.believe(it) 因为函数名相同,传入的参数相同,那么返回的结果也应该相同。所以上述的代码也没有什么问题!博主想得太多了。

  68. 二孬
    124.193.180.*
    链接

    二孬 2012-03-10 18:26:23

    我觉得应该这样写:

    var r = you.believe(it);
    if (r || !r) {
    
    }
    
  69. lockmyeye
    182.89.205.*
    链接

    lockmyeye 2012-03-25 15:06:58

    我对上述讨论表示无语。 感觉就老赵做了一个假设,大家就根据这个假设再整一系列的假设。 老赵的假设是一个没有明确前提的假设,不是让大家去证明的,反正答案多海去了,你们忙着猜去吧,老赵悠哉游哉去喝茶。

    最后,再对我自己表示无语,居然还参与进来了。

  70. Osiris
    202.222.33.*
    链接

    Osiris 2012-03-27 16:28:32

    把“||”改成“|”呢?“信“和“不信“都能执行一遍

  71. 木木勇
    183.0.18.*
    链接

    木木勇 2012-04-08 23:02:40

    java不好?java不好,C#还不是跟java类似?还不是跟着java的屁股跑? java不好?它开源,它跨平台,C#你能吗?

  72. 老赵
    admin
    链接

    老赵 2012-04-09 11:07:44

    @木木勇

    您又来说笑话了,你先了解下C#再说吧,别无知者无畏了。

  73. dsf
    113.111.107.*
    链接

    dsf 2012-04-11 12:22:45

    楼主在装,真无知!

  74. 恭喜
    116.3.14.*
    链接

    恭喜 2012-05-01 15:14:42

    好好学习!!差的太多了!

  75. 链接

    Metisria 2012-06-25 23:20:25

    在百度空间看一篇有关Matlab与C#的文章导航到这里。

    ...很多人还觉得LINQ不清晰呢,小学生还觉得高中数学的解法不清晰呢。

    对此很有同感!

    对于最后的提出的问题,我认为编译器不会做任何优化

    if(you.believe(it)||!you.believe(it))
    

    我认为编译器在代码分析阶段会生成如下类似代码:

    var $b1 = you.believe(it);
    var $b2 =! you.believe(it);
    if($b1 || !$b2)
    

    必须保证you.believe(it)被调用2次,因此不会做优化。

    但是我通常会这样写代码

    var result = you.believe(it);
    if(result||!result)
    

    如果照上述这样的方式写,我认为编译会进行优化if(true)

    对于{ love++;love--;},考虑到多线程的话,如果在执行love++后线程被立即挂起,CPU执行另一指令,那么love在其它方法应该会有影响,因此这个代码也不会被优化。

    时隔1年了,才看到文章,唉,信息落后啊。。。

  76. 老赵
    admin
    链接

    老赵 2012-06-26 09:42:06

    @Metisria

    第一个优化肯定不对的,因为||的右边可能会被短路,怎么可以提前计算呢?

  77. d_in_g
    58.53.148.*
    链接

    d_in_g 2013-05-05 14:28:51

    这个厉害啊,佩服得五体投地,编程N年了还没想过这种问题.

  78. ciznx
    174.139.28.*
    链接

    ciznx 2015-03-09 21:01:42

    也来聊聊最后两个小问题。

    1. 就像上面所说,两个 you.love(me) 肯定不会被缩略掉,因为调用可能被短路,也有可能会有负作用;
    2. 中间的 love++ 和 love-- 也不会被优化掉,因为没有保证整个调用是线程安全的,因此这些指令都是有其含义的。

发表回复

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

昵称:(必填)

邮箱:(必填,仅用于Gavatar

主页:(可选)

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

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

使用Live Messenger联系我