0

我完全理解 .NET 中的 ref 词

由于使用相同的变量,会提高使用 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;
}

在legalchars之前更好地参考?

4

4 回答 4

9

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

于 2011-03-01T20:27:43.040 回答
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 。

于 2011-03-01T20:29:18.687 回答
0

关于传递字符串 ByReference ("ref") 而不是 ByValue 的一般性能增益的一句话:

有性能提升,但非常小!

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

按值:249 毫秒

按参考: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);
        }

    }
}
于 2012-03-20T16:29:19.850 回答
0

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

于 2011-03-01T20:31:42.043 回答