当我们在C#中访问字符串的'Length'属性时会发生什么?

时间:2016-01-22 09:27:17

标签: c# string

示例代码如下:

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中怎么样?

3 个答案:

答案 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也不会创建任何实例或额外的内存空间,它将在堆中为字符串返回已分配的内存空间。