C# 如何使此代码更具性能

C# 如何使此代码更具性能,c#,C#,我有以下代码: static void Main(string[] args) { int[] array = FillArray(); //Imagine FillArray() Fills the array with numbers from 0 to 100 string numbers = ""; for(int i = 0;i<array.Count();i++) { numbers += i.ToString(); }

我有以下代码:

static void Main(string[] args)
{
    int[] array = FillArray(); //Imagine FillArray() Fills the array with numbers from 0 to 100
    string numbers = "";
    for(int i = 0;i<array.Count();i++)
    {
        numbers += i.ToString();
    }

}
static void Main(字符串[]args)
{
int[]array=FillArray();//想象FillArray()用0到100的数字填充数组
字符串编号=”;

对于(int i=0;i,如果要多次连接字符串,请使用StringBuilder。 也可以使用array.Length

static void Main(string[] args)
{
    int[] array = FillArray(); //Imagine FillArray() Fills the array with numbers from 0 to 100
    var sb = new StringBuilder();
    var len = array.Length;
    for(int i = 0; i < len; i++)
    {
        sb.Append(i.ToString());
    }    
    var numbers = sb.ToString();        
}
static void Main(字符串[]args)
{
int[]array=FillArray();//想象FillArray()用0到100的数字填充数组
var sb=新的StringBuilder();
var len=array.Length;
对于(int i=0;i
如果要多次连接字符串,请使用StringBuilder。 也可以使用array.Length

static void Main(string[] args)
{
    int[] array = FillArray(); //Imagine FillArray() Fills the array with numbers from 0 to 100
    var sb = new StringBuilder();
    var len = array.Length;
    for(int i = 0; i < len; i++)
    {
        sb.Append(i.ToString());
    }    
    var numbers = sb.ToString();        
}
static void Main(字符串[]args)
{
int[]array=FillArray();//想象FillArray()用0到100的数字填充数组
var sb=新的StringBuilder();
var len=array.Length;
对于(int i=0;i
有多种不同的方法可以获得更好的性能。在我的测试中,StringBuilder可能有一点优势(多次运行的时间是可变的,数字非常接近,超过10次迭代,StringBuilder始终是最快的,其他两个一直在交换速度更快的方法)

static void-original(int[]数组)
{            
字符串编号=”;
对于(int i=0;in.ToString()).ToArray();
var s=string.Join(“,strings);
}
静态void Alternate2(int[]数组)
{
Concat(数组);
}
静态无效时间(字符串名称、操作、int[]数组)
{
秒表秒表=Stopwatch.StartNew();
行动(阵列);
秒表;
Console.WriteLine(“{0}-{1}”,名称,stopwatch.elapsedmillesons);
}
静态void Main(字符串[]参数)
{
var数组=可枚举的.Range(0,100000).ToArray();
对于(int i=0;i<10;i++)
{
时间(“原始”、原始、数组);
时间(“改进”,改进,阵列);
时间(“交替”,交替,数组);
时间(“Alternate2”,Alternate2,数组);
}
}

有多种不同的方法可以获得更好的性能。在我的测试中,StringBuilder可能有一点优势(多次运行的时间是可变的,数字非常接近,超过10次迭代,StringBuilder总是最快的,其他两个一直在交换速度更快的方法)

static void-original(int[]数组)
{            
字符串编号=”;
对于(int i=0;in.ToString()).ToArray();
var s=string.Join(“,strings);
}
静态void Alternate2(int[]数组)
{
Concat(数组);
}
静态无效时间(字符串名称、操作、int[]数组)
{
秒表秒表=Stopwatch.StartNew();
行动(阵列);
秒表;
Console.WriteLine(“{0}-{1}”,名称,stopwatch.elapsedmillesons);
}
静态void Main(字符串[]参数)
{
var数组=可枚举的.Range(0,100000).ToArray();
对于(int i=0;i<10;i++)
{
时间(“原始”、原始、数组);
时间(“改进”,改进,阵列);
时间(“交替”,交替,数组);
时间(“Alternate2”,Alternate2,数组);
}
}

试试专门为此设计的
string.Concat

static void Main(string[] args) {
  string numbers = string.Concat(FillArray());
  ...
}

请尝试专门为此设计的
string.Concat

static void Main(string[] args) {
  string numbers = string.Concat(FillArray());
  ...
}

要想变得非常快,你需要去掉(几乎)所有的分配。大多数人都不知道
i.ToString()
分配了一个新的字符串实例,这个实例在被附加到
StringBuilder
实例后就不再需要了

您的初始版本没有在每个
i.ToString()中包含“temp”字符串
这会导致字符串逐渐变大,因此每次分配新的稍大的字符串时都会变慢。这不是少数字符串的问题,但如果以这种方式处理数千或数百万个字符串,则此方法似乎永远不会终止

一个更好的方法是使用
StringBuilder
,它基本上是一个可变字符串,可以扩展其现有缓冲区。这允许在不创建新临时字符串的情况下高效追加字符串,因为字符串实例是不可变的。现在,您已经相当不错了,您可以通过分配足够大的字符数组来做得更好对于所有期望的整数。那么您不必
i.ToString()
而是
i.tocharray()
进入最终的字符缓冲区。这比
StringBuilder
方法快了一倍多

ArrayToStringSteakOverCooked        0.39s 0.40s 0.43s
ArrayToStringKeithNicolasAlternate2 0.43s 0.44s 0.46s
ArrayToStringAlois                  0.17s 0.16s 0.16s
上述数字是通过此代码实现的

int[] Integers = Enumerable.Range(-5, 5 * 1000 * 1000).ToArray();

void ArrayToStringAlois()
{
    char[] buffer = new char[Integers.Length * 11]; // an integer can have 10 digits plus sign = 11 digits. This buffer is big enough for all possible numbers
    int startIdx = 0;
    for (int i = 0; i < Integers.Length; i++)
    {
        startIdx += ToCharArray(Integers[i], buffer, startIdx);
    }

    string lret = new string(buffer, 0, startIdx);

    GC.KeepAlive(lret);
}

public static int ToCharArray(int value, char[] buffer, int bufferIndex)
{
    if (value == 0)
    {
        buffer[bufferIndex] = '0';
        return 1;
    }
    int len = 1;
    int upperBound = 0;
    if (value < 0)
    {
        buffer[bufferIndex] = '-';
        len = 2;
        upperBound = 1;
    }
    value = Math.Abs(value);

    for (int rem = value / 10; rem > 0; rem /= 10)
    {
        len++;
    }

    for (int i = len - 1; i >= upperBound; i--)
    {
        buffer[bufferIndex + i] = (char)('0' + (value % 10));
        value /= 10;
    }
    return len;
}

void ArrayToStringSteakOverCooked()
{
    var numbers = new StringBuilder();
    var length = Integers.Length;
    for (int i = 0; i < length; i++)
    {
        numbers.Append(i.ToString());
    }

    var lret = numbers.ToString();
    GC.KeepAlive(lret);
}

void ArrayToStringKeithNicolasAlternate2()
{
    var lret = string.Concat(Integers);
    GC.KeepAlive(lret);
}
int[]Integers=Enumerable