Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 字符串。Concat无效代码?_C#_String_.net 4.0_Concatenation - Fatal编程技术网

C# 字符串。Concat无效代码?

C# 字符串。Concat无效代码?,c#,string,.net-4.0,concatenation,C#,String,.net 4.0,Concatenation,我在调查弦。康卡特:(反射器) 非常奇怪: 具有值数组 他们创建了一个新的数组,稍后将其发送到ConcatArray 问题: 为什么他们创建了一个新的阵列?他们从一开始就有值 编辑 代码: public static string Concat(params string[] values) { if (values == null) { throw new ArgumentNullException("values"); } int total

我在调查弦。康卡特:(反射器)

非常奇怪:

具有值数组

他们创建了一个新的数组,稍后将其发送到
ConcatArray

问题:

为什么他们创建了一个新的阵列?他们从一开始就有

编辑 代码:

public static string Concat(params string[] values)
{
    if (values == null)
    {
        throw new ArgumentNullException("values");
    }
    int totalLength = 0;
    string[] strArray = new string[values.Length];
    for (int i = 0; i < values.Length; i++)
    {
        string str = values[i];
        strArray[i] = (str == null) ? Empty : str;
        totalLength += strArray[i].Length;
        if (totalLength < 0)
        {
            throw new OutOfMemoryException();
        }
    }
    return ConcatArray(strArray, totalLength);
}
公共静态字符串Concat(参数字符串[]值)
{
如果(值==null)
{
抛出新的ArgumentNullException(“值”);
}
int-totalength=0;
string[]strArray=新字符串[values.Length];
for(int i=0;i
他们创建了一个新数组,将
null
条目标准化为
String.Empty
。无法在提供的
数组上执行此操作,因为这样他们将修改输入

首先,这意味着新数组的内容可以被信任为非空。。。。一成不变

如果没有复制,另一个线程可以在调用
ConcatArray
期间修改原始数组,这可能会引发异常,甚至触发安全错误。通过复制,可以随时更改输入数组-每个元素将被精确读取一次,因此不存在不一致性。(结果可能是新旧元素的混合,但最终不会导致内存损坏。)

假设信任
ConcatArray
对其传递的数组中的字符串进行大容量复制,而不检查缓冲区溢出。然后,如果您在正确的时间更改输入数组,那么最终可能会在分配的内存之外进行写入。不好。有了这个防御性副本,系统可以确保1总长度实际上就是总长度


除非反射用于更改字符串的内容。但是,如果没有相当高的权限,这是不可能做到的,而更改数组的内容是很容易的

低效

不,没关系。相对于串联,数组的创建和复制速度非常快,它只是复制引用


看起来他们这样做是为了将输入数组中的
null
字符串转换为
String.Empty
(他们不能对
值执行此操作,因为这将修改输入,而输入是no-no),并在实际执行串联之前检测可能溢出的浓缩(这就是
if(totalLength<0)的情况)
测试用于测试)。此外,他们还可以使用
totalLength
预先为连接的字符串分配内存,这样效率更高。

可能是为了确保它在方法的生命周期内不会改变。这将导致
totalLength
不再适合数组的内容


我怀疑
ConcatArray
使用了一些不安全的内存复制,并且没有再次检查字符串
Length
s。可以重写它以避免分配,但是一个额外的小的、短期的分配是相当便宜的。

据我所知,他们对此做了一些工作-我猜你不想改变原来的一个。。。记住,您当然希望Concat函数的字符串保持不变-如果未声明,请不要更改参数引用

他们为什么要创建一个新阵列

我可以证实乔恩的猜测;我面前有原始的源代码。这些注释表明复制的原因是因为一些愚蠢的人可能正在修改在另一个线程中传递的数组。那么会发生什么呢?长度的计算可以说结果中将有100字节的字符串数据,但在复制发生时,数组中可能有100万字节的字符串数据


那太糟糕了。通过制作副本可以很容易地避免此问题。

可能是因为它使ConcatArray更高效,而不必为null设置特殊情况。你知道它没有复制所有的字符串,对吗?它只是创建了一个对现有字符串的引用的新数组。我不确定我是否理解
totalLength
怎么可能小于零。我忽略了什么愚蠢的事情?@LarsTech当overflowexception发生时-int是负数…等等,你是如何检查Concat的?我一直在试图弄清楚如何查看内置方法中的代码,但我所发现的只是我需要使用cecil。@Walkereno:获取或查看程序集。另一个源是。另一个线程也可以在复制过程中修改原始文件。在我看来,这似乎不是正确的推理。(我没有投反对票,只是没有投反对票。)@Jason:不过这没关系——每个元素只读取一次(注意复制到
str
而不是重复访问)——所以要么在更改之前读取,要么在更改之后读取。(有些元素可以在更改之前读取,有些可以在更改之后读取,这很好。)
totalLength
肯定仍然适用于新数组,并且所有值仍然保证为非null。您的猜测是正确的;如果有人在另一个线程上修改数组,这是为了确保安全。@Jon Skeet:我明白了,但仍然存在一个无法避免的竞争条件。@Jason:你是对的;我应该指出,我所说的“安全”不是“线程安全”——不管是什么——而是内存安全。字符串代码在幕后使用不安全的代码填充新的缓冲区,我们必须不惜一切代价避免损坏内存。如果结果是无意义的,因为有人变异了在上使用的数组