Length这个属性,肯定是内部加缓存的,不会每次都查长度,你的方法应该没问题class String
{
   int _length = -1;
   public int Length 
   {
    get {
          if (_length == -1)
          {
              //运行一次求长度的函数
          }
          return _length;
        }
   }
}

解决方案 »

  1.   

    你师兄说得没错,你做的只是很小的一个模块,如果是用在系统的底层,很多的其他模块都来调用的话,会造成性能影响的,在可能的情况下,应尽可能的使效率高些。
    B.J.在设计C++时,标榜的就是效率,和C的效率相差,可以控制在5%以内
      

  2.   

    你师兄的说法反而不如你的效率高,我看过一些.net资料,上面讲的,我没有具体核实过,仅供参考
    好像,net里对这种情况进行了优化
    如果你的循环里的遇到对字符串s的操作,程序内部还要检查i是否符合<s.length,而你的就不需要了,
      

  3.   

    就算是加缓存,也会每次都作判断_length==-1,仍然不如把求长度放到循环外面效率高。
    当然现在的pc性能已经很好,不必太苛求效率
      

  4.   

    我上面的编码只是个示范,字符串的长度完全可能是在字符串初始化或被赋值时就算好了的, 记住String是immutableclass String
    {
       int _length = -1;
       public int Length 
       {
        get {
                return _length;
            }
       }   //初始化或被赋值时, 运行一次求长度的函数
    }
      

  5.   

    思归 说得对
    对于一般的字符常量及字符数组等的长度都是先存好的 如果另外计算反而会增加内存(虽然很小) 
    但另如 ArrayList.Count 之类的长度就不同了
      

  6.   

    i<s.Length()属于for-condition的,每次都求值你师兄说的对,不管Length属性是缓存还是没有缓存,s.Length总是一个对象.属性的调用,
    如果循环次数很多的话,应该比直接调用一个 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在循环开始之前只求值一次
      

  7.   

    我觉得你的师兄的思路还是对的,但是他忘记考虑的一件事情就是在.Net,编译器是会进行优化的。
    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中,这个长度是和字符串一起存放的,所以求长度不会耗费很多的计算。
      

  8.   

    补充一下,string的长度可能是确定的,应为在.net 中string长度赋值后是不能更改的
      

  9.   

    最好的方法莫过于让事实说话。using System;
    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
    所以,我的方法是最好的选择。
      

  10.   

    下面所有的测试都不是在IDE中进行的,是使用了编译好的文件。
    这是在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方法,指令都完全一样,不过次序有点不一样。
      

  11.   

    看的今天的这个帖子,让我想到了以前看到的一篇文章,<<远去的代码>>...
      

  12.   

    我也测试了 whxbb(whxbb)的代码 结果基本和TheAres(班门斧)的一样
    不过我也试了 string[] 和ArrayList 结果完全不同
    Arraylist 的效率和string 一样
    在 string[]中 三种方式 基本相同 但第一种捎快一点 
      

  13.   

    编译器肯定会对这种情况进行优化,两种效率一样的
    如果C#的compiler连这都做不到,我们都不要用了:)
      

  14.   

    在以前的C、C++语言中,在外面的效率高些,C#中就一样了。(记得哪本书中有过)
    效率一样,你的可读性好一些。
      

  15.   

    你师兄的出发点是好的,在学习C++的时候我也和老师讨论过,他也建议一般情况下用你师兄那种。虽然你的可读性好:)不过看了几位高手的解释让我受益匪浅:)看来我还需要好好看看Jeffery Ritcher的那本书:)
      

  16.   

    Test1:43462496
    Test2:23734128
    Test3:25036000
      

  17.   

    刚刚看了MONO的源码,思归的猜想是正确的:
    private int length;
    .............
    public int Length {
    get {
    return length;
    }
    }
      

  18.   

    如果三种方式的性能都一样的话,你用 Test1没问题, 但是在你不知道性能怎样,又没时间去测试比较分析甚至是看他们的源代码话,你应该用 Test3。