c#ref for speed

时间:2011-03-01 20:24:55

标签: c# performance ref

我完全理解.NET中的引用词

由于使用相同的变量,会增加使用ref而不是复制的速度吗?

我发现密码一般存在瓶颈。

这是我的代码

protected internal string GetSecurePasswordString(string legalChars, int length)
{
    Random myRandom = new Random();
    string myString = "";
    for (int i = 0; i < length; i++)
    {
        int charPos = myRandom.Next(0, legalChars.Length - 1);
        myString = myString + legalChars[charPos].ToString();
    }
    return myString;
}

最好在lawchars之前参考?

4 个答案:

答案 0 :(得分:9)

按值传递字符串不会复制字符串。它只复制对字符串的引用。通过引用而不是按值传递字符串没有性能优势。

答案 1 :(得分:5)

不,您不应该通过引用传递字符串引用

但是, 无意义地创建了几个字符串。如果您正在创建长密码,那么这可能是它成为瓶颈的原因。这是一个更快的实现:

protected internal string GetSecurePasswordString(string legalChars, int length)
{
    Random myRandom = new Random();
    char[] chars = new char[length];
    for (int i = 0; i < length; i++)
    {
        int charPos = myRandom.Next(0, legalChars.Length - 1);
        chars[i] = legalChars[charPos];
    }
    return new string(chars);
}

然而,它仍有三大缺陷:

  • 每次都会创建Random的新实例。如果您快速连续两次调用此方法,您将获得两次相同的密码。不好的主意。
  • Random.Next()来电中指定的上限是独占的 - 因此您永远不会使用legalChars的最后一个字符。
  • 它使用System.Random,这并不意味着以任何方式加密安全。鉴于这是为了“安全密码”,您应该考虑使用System.Security.Cryptography.RandomNumberGenerator之类的东西。这样做的工作量更大,因为API更难,但你最终会得到一个更安全的系统(如果你做得恰到好处)。

如果您真的偏执,您可能还想考虑使用SecureString

答案 2 :(得分:0)

.Net中的

字符串是不可变的,因此对字符串的所有修改操作总是导致新字符串的创建(和垃圾收集)。在这种情况下使用ref不会获得性能提升。相反,请使用StringBuilder。

答案 3 :(得分:0)

关于传递字符串ByReference(“ref”)而不是ByValue的一般性能增益的说法:

有性能提升,但它非常小!

考虑下面的程序,其中函数被调用10.000.0000次,带有字符串参数的值和引用。测量的平均时间是

ByValue:249毫秒

ByReference:226毫秒

一般来说,“ref”要快一点,但通常不值得担心。

这是我的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;

namespace StringPerformanceTest
{
    class Program
    {
        static void Main(string[] args)
        {
            const int n = 10000000;
            int k;
            string time, s1;
            Stopwatch sw;

            // List for testing ("1", "2", "3" ...)
            List<string> list = new List<string>(n);
            for (int i = 0; i < n; i++)
                list.Add(i.ToString());

            // Test ByVal
            k = 0;
            sw = Stopwatch.StartNew();

            foreach (string s in list)
            {
                s1 = s;
                if (StringTestSubVal(s1)) k++;
            }

            time = GetElapsedString(sw);
            Console.WriteLine("ByVal: " + time);
            Console.WriteLine("123 found " + k + " times.");


            // Test ByRef
            k = 0;
            sw = Stopwatch.StartNew();

            foreach (string s in list)
            {
                s1 = s;
                if (StringTestSubRef(ref s1)) k++;
            }

            time = GetElapsedString(sw);
            Console.WriteLine("Time ByRef: " + time);
            Console.WriteLine("123 found " + k + " times.");
        }

        static bool StringTestSubVal(string s)
        {
            if (s == "123")
                return true;
            else
                return false;
        }

        static bool StringTestSubRef(ref string s)
        {
            if (s == "123")
                return true;
            else
                return false;
        }

        static string GetElapsedString(Stopwatch sw)
        {
            if (sw.IsRunning) sw.Stop();
            TimeSpan ts = sw.Elapsed;
            return String.Format("{0:00}:{1:00}:{2:00}.{3:000}", ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds);
        }

    }
}