我想那就是因为他封装成“大众型”的库,很多操作都非常仔细的处理,但我们很多时候根本不用考虑那么多。
因为这种“浪费的”操作使得他运行慢一点。当然,即时编译执行方式应该才是主要的因素。但这种执行上的浪费也是让人不爽的。就像美国人都觉得UNICODE编码不爽,因为他们仅需要ASCII码就够了,而UNICODE却无缘无故让他们的文档增加了一倍的空间!
参见一个操作,
Code
bool bOk = false;
bool.TryParse("true",out bOk);
调用TryParse试图翻译true
Code
1public static bool TryParse (string value, out bool result)
2{
3 result = false;
4 if (value != null)
5 {
6 if ("True".Equals(value, StringComparison.OrdinalIgnoreCase))
7 {
8 result = true;
9 return true;
10 }
11 if ("False".Equals(value, StringComparison.OrdinalIgnoreCase))
12 {
13 result = false;
14 return true;
15 }
16 if (bool.m_trimmableChars == null)
17 {
18 char[] destinationArray = new char[string.WhitespaceChars.Length + 1];
19 Array.Copy(string.WhitespaceChars, destinationArray, string.WhitespaceChars.Length);
20 destinationArray[destinationArray.Length - 1] = '\0';
21 bool.m_trimmableChars = destinationArray;
22 }
23 value = value.Trim(bool.m_trimmableChars);
24 if ("True".Equals(value, StringComparison.OrdinalIgnoreCase))
25 {
26 result = true;
27 return true;
28 }
29 if ("False".Equals(value, StringComparison.OrdinalIgnoreCase))
30 {
31 result = false;
32 return true;
33 }
34 }
35 return false;
36}
37
38
39
上面的代码来自System.Boolean类。前面的忽略字符大小写的比较是必须的,而后面的空白字符感觉就有些多余了。
因为这些函数都是内部使用,自己写的代码基本不会多写空白字符的,比如不会故意写成"trUe "这种,而很多人还很喜欢每个字符串后面来个Trim()感觉是自己代码很安全,而他不知道这些代码99%的情况都不会有实际效用但反而增加执行时间……
就相当于一个火车站要过10个门才能到站台上车,在保证所有人只能从一个入口进入的前提下仅需要在那个唯一入口检票即可。不用每过一个门就要检一次!
为了更高效率,可以不做Trim操作,"True","False"之外的" True "之类的就报异常,在发布之前就如果有异常就可以即时改正。真正必须的Trim只要在对外接口处(比如用户界面)上来一下就OK了。
或许还有人觉得一个Trim不会消耗多少吧?
不多说,看代码,System.String.Trim函数
Code
1public string Trim (params char[] trimChars)
2{
3 if ((trimChars == null) || (trimChars.Length == 0))
4 {
5 trimChars = string.WhitespaceChars;
6 }
7 return TrimHelper(trimChars, 2);
8}
9
10
11
在return时调用 System.String.TrimHelper函数
TrimHelper
1private string TrimHelper (char[] trimChars, int trimType)
2{
3 int num1 = Length - 1;
4 int startIndex = 0;
5 if (trimType != 1)
6 {
7 for (startIndex = 0;startIndex < Length; startIndex++)
8 {
9 int num3 = 0;
10 char chr1 = this[startIndex];
11 num3 = 0;
12 while (num3 < trimChars.Length)
13 {
14 if (trimChars[num3] == chr1)
15 {
16 break;
17 }
18 num3++;
19 }
20 if (num3 == trimChars.Length)
21 {
22 break;
23 }
24 }
25 }
26 if (trimType != 0)
27 {
28 for (num1 = Length - 1;num1 >= startIndex; num1--)
29 {
30 int num4 = 0;
31 char chr2 = this[num1];
32 num4 = 0;
33 while (num4 < trimChars.Length)
34 {
35 if (trimChars[num4] == chr2)
36 {
37 break;
38 }
39 num4++;
40 }
41 if (num4 == trimChars.Length)
42 {
43 break;
44 }
45 }
46 }
47 int length = (num1 - startIndex) + 1;
48 if (length == Length)
49 {
50 return this;
51 }
52 if (length == 0)
53 {
54 return string.Empty;
55 }
56 return InternalSubString(startIndex, length, false);
57}
在最后return时调用System.String.
InternalSubString
InternalSubString
1/**//*注意,这是unsafe的哦!呵呵,看见char*估计就会感觉很恐怖吧?原来你做的每一个字符串操作都可能跑到这里来的哦
2O(∩_∩)O哈哈~
3*/
4private unsafe string InternalSubString (int startIndex, int length, bool fAlwaysCopy)
5{
6 if (((startIndex == 0) && (length == Length)) && !fAlwaysCopy)
7 {
8 return this;
9 }
10 string text1 = string.FastAllocateString(length);
11 fixed (char* dmem = &text1.m_firstChar)
12 {
13 fixed (char* pinned2 = &m_firstChar)
14 {
15 string.wstrcpy(*dmem, * pinned2 + startIndex, length);
16 }
17 }
18 return text1;
19}
20
21
在这个函数中会调用string.FastAllocateString
string.FastAllocateString
1/**//*然后就看不到代码了,看来就是inline函数吧,
2之所以叫FastAllocate估计就是这么写的
3inline strAllocate(int len)
4{
5 if(xxx)
6 {……}
7 m_buf = new char[len];
8}
9*/
10[MethodImpl(MethodImplOptions.InternalCall)]
11private static string FastAllocateString (int length);
12
结束语
看见上面这么多函数调用,以后是不是也会对效率有些感觉了呢?其实在对效率要求不高时这个是不用考虑的。
或许是我现在一直在写C++程序的缘故吧,对效率看得很重。加之最近一个项目服务端要用C#写,要维护上千个客户端。很多时候需要同时对多个客户端进行通信和大数据量处理同时接收并处理(70kb 每帧* 2 帧 * 并行客户端数目 / 秒)数据。
哎,不知道那些家伙怎么想的,非要我用C#写服务端,而客户端是之前我用C++写的。O(∩_∩)O~ 奇怪吧?