JGTM'2008 [MVP]

Thinking in WPF...
随笔 - 36, 评论 - 453, 引用 - 16

导航

标签

每月存档

最新留言

广告

 

周末熬夜终于搞定的AOP尝鲜系列文章第三篇一出,就收到了很多朋友的反馈和邮件。首先感谢大家的关注!也衷心谢谢给我指出文章错误、文字疏忽的朋友们!

有一位细心朋友今早给我发来邮件,“批评”我又在简单问题上面犯了糊涂,他所指的是文章中出现的这个语句:

Console.WriteLine("Add: " + Thread.CurrentContext);

其中Thread.CurrentContext属性将返回当前线程所处的执行环境,类型是System.Runtime.Remoting.Contexts名称空间中的Context。一个字串常量怎么可以和一个对象直接相加呢!肯定是我忘了写ToString()了吧?他对此的评语也很有意思,“老兄以为在写JScript呐!”……嘿嘿!一针见血啊!

我回复他,感谢他的热心和仔细(再次:),顺便问了一句:我文中的代码你动手编译过吗?因为我清楚的记得像这样的代码我已经不是写一次两次了——偶的实践经验告诉我:这个语句是可以在Visual C# .NET中编译并正确运行的!不仅如此,我还经常写这样的语句:

string tempFilename = null;
tempFilename += Environment.TickCount + ".tmp"; // 啊?string += int?

或者:

string guidKey = "{" + Guid.NewGuid() + "}"; // 奋特!

再或者:

string logLine = "Log: " + DateTime.Now; // 咣当……

……就像读者所说:这是C#还是JScript啊!?实际上,我也没有在C#语言规范中找到能解释这个现象的理论依据(如果你知道的话希望能告诉我:)。所以我只能说这是Visual C# .NET编译器的一种编译器优化手段造成的side effect(将静态字串相加转化为String.Concat()调用)——不过事实证明,这种写法的效率比起String.Format()还要高(虽然没有人家灵活),甚至有时候比每一个用ToString()还要快!原因是什么?也很容易分析出来,留给聪明的你做个练习吧(可以把你的想法用反馈告诉我)!:)

最后还是按照惯例,做个练习——想想下面这个表达式中对quiz求值将是什么结果?

string quiz = null;
quiz += 1 + 2 + "3" + 4 + 5;

P.S: USE THIS TRICK AT YOUR OWN RISK! AND IT IS NOT RECOMMENDED AT ALL (THOUGH IT'S OFTEN USEFUL AND HANDY DURING DEBUGGING.)

打印 | 张贴于 2004-04-05 21:31:00 | Tag:.NET Stuffs

留言反馈

#re: .NET Trick: Is it C# or JScript?! 编辑
C#缺少像VB那样的专门的字符串连接运算符(&),所以才会造成这个奇象。在VB中
1 & 2 & "3" & 4 & 5
不会造成任何理解困难,结果就是“12345”

另外我想+如果是从左到右计算的话,那
1 + 2 + "3" + 4 + 5
结果应当是"3345"

只有VB这种垃圾语言才会有运算符,C#并不鼓励用+来操作字符串,String.Format才是王道,对于复杂的字符串生成,则有StringBuilder伺候。+生成大量临时字符串,效率很成问题
2005-12-07 23:59:00 | [匿名:Atry]
#re: .NET Trick: Is it C# or JScript?! 编辑
所有的对象都继承了一个ToString()方法,而且这个方法通常会自行调用。:)
2005-01-03 15:55:00 | [匿名:Stela]
#re: .NET Trick: Is it C# or JScript?! 编辑
同意marshine的说法。

string str = 3 + "3" + 4 + 5;

String.Concat( Object, Object );
String.Concat(params[] string strs)
关键是你想调用哪个重载方法,当然是尽量调用不会执行box的、性能高的。
2004-11-07 08:57:00 | [匿名:hsb0307]
#回复: .NET Trick: Is it C# or JScript?! 编辑
正如coollzh所说,string+int其实是发生了boxing。在C#里,string为引用对象,int为值对象。这两种对象在C#里称为封箱,其实类似类型转换。

不过对于一般的object类型,如果要作为某种具体的类型,例如string,int。最好还是用tostring()或Convert.to...()操作来完成。这样似乎显得更严谨。
2004-07-08 09:14:00 | [匿名:wayfarer]
#回复: .NET Trick: Is it C# or JScript?! 编辑
string + int 是没有问题的,很早以前蔡学庸就写过文章,这个时候,int类型会自动box的,并调用ToString()方法
2004-04-26 22:19:00 | [匿名:coollzh]
#回复: .NET Trick: Is it C# or JScript?! 编辑
原理应该是kaneboy所说的方式,说比直接使用.ToString()快不敢苟同,如果加的都是string,将会调用String.Concat(params[] string strs),所以除非是混合使用非String对象和String对象,否则没有快的理由,即便是使用Object,也很难感觉到快(差别太小了)。呵呵,是不是有点太抠门了。
.Net本质论好像说过这个问题。
2004-04-26 17:12:00 | [匿名:marshine]
#回复: .NET Trick: Is it C# or JScript?! 编辑
Console.WriteLine(123 + "4");

这个语句最后会导致这样的一个调用:

static String String.Concat( Object, Object );

就是说:IL代码会先将值类型123进行装箱操作,装箱成一个Object,然后调用Concat(Object, Object),将每个Object参数的String形式连接起来,并返回最终的String,然后调用:

Console.WriteLine( String )

来完成操作。
2004-04-08 09:35:00 | [匿名:kaneboy]
#回复: .NET Trick: Is it C# or JScript?! 编辑
回去我又复习了一下,原来lovecreatesbeauty所言就是在C#语言规范的7.7.4节(Addition operator)——之前一直没有看到可能是因为这一节前面一直在讲数值相加的规则(而且7.7节又是Arithmetic operators),我就忽视了最后面提到的enumeration和string相加的规则。

不过偶学知识大多也正是如此先有实践再求理论的说,嘿嘿……

谢谢各位的反馈。
2004-04-07 20:46:00 | [匿名:JGTM'2004 [MVP]]
#回复: .NET Trick: Is it C# or JScript?! 编辑
我记得在csdn的java区看到过一个问题,怎么讲一个int转为它的string表示。有人回答的就是
string s = "" + i;
2004-04-07 09:11:00 | [匿名:Meyer]
#回复: .NET Trick: Is it C# or JScript?! 编辑
It's nothing speical, Java is like this always. :)

C# learned it.
2004-04-07 03:04:00 | [匿名:blahblah]
#回复: .NET Trick: Is it C# or JScript?! 编辑
@lovecreatesbeauty:

谢谢你的信息!看来我读的还是不够仔细——现在也没有找到这段话在C# Language Specification中的出处。能否告诉我这是在规范的哪一章节?

@all:

还是那句话,在容易引起歧义的情况中不建议使用这种写法。不过既然规范里面明确提到了这种表达式的正确性,那么我想合理的使用也算不得错——只要代码可读性好,同时不影响执行性能就是了。所以所有批判1+2+"3"+4+5的朋友们都是有责任心的good programmers(当然我自己也绝对不会写这样的东西出来,呵呵,写出来只是为了加深对此问题的印象——也许有一天碰到与之相关的bug时这就是一条线索呢)。
2004-04-06 21:23:00 | [匿名:JGTM'2004 [MVP]]
#回复: .NET Trick: Is it C# or JScript?! 编辑
C# 语言规范

当一个或两个操作数为 string 类型时,二元 + 运算符执行字符串串联。在字符串串联运算中,如果它的一个操作数为 null,则用空字符串来替换此操作数。否则,任何非字符串参数都通过调用从 object 类型继承的虚 ToString 方法,转换为它的字符串表示形式。如果 ToString 返回 null,则替换成空字符串。

-------
不是说得很明白吗?
2004-04-06 15:54:00 | [匿名:lovecreatesbeauty]
#回复: .NET Trick: Is it C# or JScript?! 编辑
This is not a good habit.
2004-04-06 12:30:00 | [匿名:maomao]
#回复: .NET Trick: Is it C# or JScript?! 编辑
这是强类型转换
也是java 1.5 版本中特别强调的亮点
没想到C#已经实现了
2004-04-06 10:40:00 | [匿名:Transbuerg]
#回复: .NET Trick: Is it C# or JScript?! 编辑
我觉得还是写严谨一点好,毕竟代码是给人读的,像quiz += 1 + 2 + "3" + 4 + 5;这样很容易引起误解,不知道原作者的意图到底是"12345"还是"3345"呢。
2004-04-06 10:38:00 | [匿名:sam1111]
#回复: .NET Trick: Is it C# or JScript?! 编辑
有危险
2004-04-06 01:10:00 | [匿名:lonelystranger]
#回复: .NET Trick: Is it C# or JScript?! 编辑
这几个例子不算什么,强类型的framework我觉得就是能够处理这种问题的。而且这也比较符合oo的思想。
当然,严谨是最好的。
2004-04-05 23:10:00 | [匿名:virushuo]
#回复: .NET Trick: Is it C# or JScript?! 编辑
C#缺少像VB那样的专门的字符串连接运算符(&),所以才会造成这个奇象。在VB中
1 & 2 & "3" & 4 & 5
不会造成任何理解困难,结果就是“12345”

另外我想+如果是从左到右计算的话,那
1 + 2 + "3" + 4 + 5
结果应当是"3345"
2004-04-05 22:33:00 | [匿名:Ninputer]
对不起,目前本随笔不允许发表新评论.

Powered by: Joycode.MVC引擎 0.5.2.0