我完全理解.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之前参考?
答案 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)
字符串是不可变的,因此对字符串的所有修改操作总是导致新字符串的创建(和垃圾收集)。在这种情况下使用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);
}
}
}