Length这个属性,肯定是内部加缓存的,不会每次都查长度,你的方法应该没问题class String
{
int _length = -1;
public int Length
{
get {
if (_length == -1)
{
//运行一次求长度的函数
}
return _length;
}
}
}
{
int _length = -1;
public int Length
{
get {
if (_length == -1)
{
//运行一次求长度的函数
}
return _length;
}
}
}
B.J.在设计C++时,标榜的就是效率,和C的效率相差,可以控制在5%以内
好像,net里对这种情况进行了优化
如果你的循环里的遇到对字符串s的操作,程序内部还要检查i是否符合<s.length,而你的就不需要了,
当然现在的pc性能已经很好,不必太苛求效率
{
int _length = -1;
public int Length
{
get {
return _length;
}
} //初始化或被赋值时, 运行一次求长度的函数
}
对于一般的字符常量及字符数组等的长度都是先存好的 如果另外计算反而会增加内存(虽然很小)
但另如 ArrayList.Count 之类的长度就不同了
如果循环次数很多的话,应该比直接调用一个 Int32耗时
或许你可以简写成
for (Int32 i=0,sLen=s.Length;i<sLen;i++)
{
Console.WriteLine(s[i]);
}不太清楚String内部使用的char数组还是什么?StringBuilder使用的是char数组
但c中的字符串要得到长度好像不像pascal一样直接,请大家补充:D有意思的是vb的for
for i=1 to col.countnext
col.count在循环开始之前只求值一次
string s = "abcdefg";
for(int i = 0; i < s.Length; i++)
{
//....
}
这个程序编译器优化以后就是你师兄的程序,编译器会给你取出来的所以你可以这么用。为了说明这个问题, 你可以编写一个很小的程序。
using System;namespace TheAres
{
class StrLen
{
public static void Main()
{
string s = "abcdefg";
for(int i = 0; i < s.Length; i++)
{
Console.Write(s[i]);
}
}
}
}
编译成一个1.exe文件,然后用你师兄的编译成2.exe文件。用VS.Net的ildasm.exe打开这两个文件中的Main函数,你就会看到,这里面有一个instance int32 [mscorlib]System.String::get_Length()就是求程度的函数,他都是执行一次的。
还有,关于去字符长度的问题,就想saucer(思归, MS .NET MVP)说的那样,系统会缓存这些的,并且据我看到的资料,.Net中求字符长度并不想c语言那样,遍历完了字符串才知道他的长度(主要要找\0),.Net中,这个长度是和字符串一起存放的,所以求长度不会耗费很多的计算。
class Class1
{
static void Main(string[] args)
{
int times = 5000;
string testString = "abcdefghigklmnuvwxyzabcdefghigklmnuvwxyzabcdefghigklmnuvwxyzabcdefghigklmnuvwxyzabcdefghigklmnuvwxyzabcdefghigklmnuvwxyz"; TestHandler test1 = new TestHandler(Test1);
TestHandler test2 = new TestHandler(Test2);
TestHandler test3 = new TestHandler(Test3); long t1 = RunTest(times, testString, test1);
long t2 = RunTest(times, testString, test2);
long t3 = RunTest(times, testString, test3);
Console.WriteLine("Test1:{0}", t1);
Console.WriteLine("Test2:{0}", t2);
Console.WriteLine("Test3:{0}", t3); Console.ReadLine();
}
public delegate void TestHandler(string testString); private static long RunTest(int times, string testString, TestHandler handler)
{
DateTime startAt = DateTime.Now;
for (int i = 0; i < times; i++)
{
for (int j = 0; j < 1000; j++)
{
handler(testString);
}
}
DateTime endAt = DateTime.Now;
return endAt.Ticks - startAt.Ticks;
} public static void Test1(string testString)
{
for(int i = 0; i < testString.Length; i++){};
}
public static void Test2(string testString)
{
int len = testString.Length;
for(int i = 0; i < len; i++){};
}
public static void Test3(string testString)
{
for(int i = 0, len = testString.Length; i < len; i++){};
}
}
你的方法耗时(Test1):95311890
而你师兄的方法则是(Test2):15937398
我的方法:15937398
所以,我的方法是最好的选择。
这是在debug模式下,代码优化没有打开的时候的结果
Test1:86406250
Test2:16562500
Test3:16718750
这是在release模式下,代码优化打开的时候的结果
Test1:15312500
Test2:12500000
Test3:12343750让代码空传是没有意义的,所以我在的代码的每一个循环中加入了。
char c = testString[i];
这是在debug模式下,代码优化没有打开的时候的结果
Test1:164375000
Test2:73281250
Test3:72812500
这是在release模式下,代码优化打开的时候的结果
Test1:22500000
Test2:28437500
Test3:28125000whxbb(whxbb)给了我们一个很好的例子,不过我认为这三个方法基本上是一样的。
在debug模式下,当代码优化被屏蔽以后(编译选项中缺省就是这样),我也是whxbb(whxbb)的结果。当用release模式下,这时候代码优化是打开的,得到的结果就基本一样了。当然,微小的差别还是用的。你可以再用ildasm.exe打开看看,特别是2,3方法,指令都完全一样,不过次序有点不一样。
不过我也试了 string[] 和ArrayList 结果完全不同
Arraylist 的效率和string 一样
在 string[]中 三种方式 基本相同 但第一种捎快一点
如果C#的compiler连这都做不到,我们都不要用了:)
效率一样,你的可读性好一些。
Test2:23734128
Test3:25036000
private int length;
.............
public int Length {
get {
return length;
}
}