示例代码如下:
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);
...
如果多次访问字符串的Length属性,第一个片段代码是否优于第二个?为什么呢?
当我们以 hi.Length 的方式访问字符串的长度时,CLR将计算 hi 中的字符数并返回它或只返回10因为在 hi 初始化或其他什么时,长度属性被赋值为10?
在Java中怎么样?
答案 0 :(得分:11)
Length
是数组的属性(字符串是内部的字符数组),这意味着它在内存中始终可用(数组总是固定长度,因此Length
属性不会更改)。在这两种情况下,您应该始终只使用hi.Length
而不是声明另一个变量。现在你只需要在内存中保存两次长度(一次在堆栈上为int
,一次在堆上为属性)。
编辑:正如下面的评论者指出的那样,此方法针对ICollection
进行了优化,以使用该属性而不是迭代。
如果您要使用linq方法 .Count()
,这将导致您的程序遍历整个数组以计算元素。
答案 1 :(得分:4)
您的问题是关于在非常低级别的.NET中发生的事情。当JIT' ed和优化代码执行时真正发生的事情可能与您期望的不同。
但是,回答问题的方法是查看生成的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可以设想内联这个调用,然后使用间接从内存位置读取值,然后几乎没有任何区别。
请注意,.NET字符串类型在字符串对象中存储字符串的长度,因此无需计算字符串中的字符数。创建字符串时,长度是已知的。
答案 2 :(得分:0)
根据MSDN String.Length
是一个属性,它将为您提供当前String对象中的字符数。
在你的情况下,第二种选择是相对最好的;因为它可以避免额外的int variable
。并且String.Length
也不会创建任何实例或额外的内存空间,它将在堆中为字符串返回已分配的内存空间。