2016-01-22 75 views
5

示例代码是这样的:当我们访问C#中字符串的'Length'属性时会发生什么?

string hi = "HelloWorld"; 
int length = hi.Length; 
Console.WriteLine(length); 
Console.WriteLine(length); 
... 

string hi = "HelloWorld"; 
int length = hi.Length; 
Console.WriteLine(hi.Length); 
Console.WriteLine(hi.Length); 
... 

如果字符串的长度财产将被访问超过一次,是第一个代码段比第二个好?为什么?

当我们访问 hi.Length的方式字符串的长度,CLR将数字符的数目并返回,或只返回一个10起因长度属性已被分配一个值在当时的10个已初始化或其他?

在Java中如何?

+1

[.NET String.Length属性返回什么?替代中性长度或完整的字符长度](http://stackoverflow.com/questions/5656472/what-does-the-net-string-length-property-return-surrogate-neutral-length-or-co) – Michael

+1

@VMA - 不,海报问是否调用'hi.length'的开销值得存储值以供重用 –

+0

您是否要学习编写10万亿不同代码片段的“最佳”方法,然后盲目地坚持使用尽管他们可以做些什么来提高可读性?优化的第一条规则是:不。写*简单*,*清除*,可理解的代码,同时设置性能*目标*。然后衡量你的表现并评估你是否达到了目标。如果您还没有,请确定*性能问题在哪里,然后将精力集中在那里。微优化房地产访问是非常值得怀疑的。 –

回答

4

你的问题是关于在.NET中发生的真正低级别的事情。执行JIT和优化代码时会发生什么情况可能与您期望的不同。

然而,一种方式来回答你的问题是所产生的IL看:

string hi = "HelloWorld"; 
int length = hi.Length; 
Console.WriteLine(length); 
Console.WriteLine(length); 

编译成

ldstr  "HelloWorld" 
callvirt System.String.get_Length 
dup   
call  System.Console.WriteLine 
call  System.Console.WriteLine 

string hi = "HelloWorld"; 
Console.WriteLine(hi.Length); 
Console.WriteLine(hi.Length); 

(在那里我有因为它没有被使用,删除了作业到length)编译为

ldstr  "HelloWorld" 
dup   
callvirt System.String.get_Length 
call  System.Console.WriteLine 
callvirt System.String.get_Length 
call  System.Console.WriteLine 

第一版本似乎比第二要稍微更有效,因为仅存在一个呼叫到System.String.get_Length两者使用一个额外的堆栈单元(dup)。然而,JIT'er可以设想内联这个调用,然后使用间接从内存位置读取值,然后几乎没有任何区别。

请注意,.NET字符串类型存储字符串对象中字符串的长度,因此不需要对字符串中的字符进行计数。字符串创建时的长度是已知的。

11

Length是一个数组的属性(字符串是内部字符数组),这意味着它始终在内存中可用(数组总是固定长度,因此Length属性不会更改)。在这两种情况下,您应该始终使用hi.Length而不是声明另一个变量。现在你只需要在内存中保存两次(一次在堆栈上为int,一次在堆上为属性)。

编辑:正如以下评论所指出的,此方法已针对ICollection进行了优化,以便使用属性而不是迭代。 如果您要使用linq方法 .Count(),这将导致您的程序遍历整个数组来计算元素。

0

根据MSDNString.Length是一个属性,它会给你当前String对象中的字符数。

在你的情况下,第二个选项是比较好的;因为它可以避免额外的int variable。并且String.Length也不会创建任何实例或额外的内存空间,它将返回字符串的堆中分配的内存空间。

相关问题