在 C# 中精确复制字符串的时间和最佳方法
When and best way to make exact copies of strings in C#
假设我有一个字符串数组来自于执行这个 Split 方法
string[] parsed = message.Split(' ');
然后我想将这个数组的某个值存储在一个新的字符串中
string name = parsed[3];
现在我使用扩展方法从数组中删除这个字符串,此方法删除指定索引处的值并将所有内容移回以填补空白
parsed = parsed.RemoveAt(3);
我知道因为字符串在 C# 中是引用类型,所以我的 name 变量现在为 null,经过一些搜索后我被告知在 C# 中精确复制字符串是没有用的。将 name 变量设置为新实例以使其在 .RemoveAt() 调用后不会被删除的最佳和正确方法是什么?
编辑:
这是目前为止我找到的最好的方法
string name = new string(parsed[3].ToCharArray());
提出的另一种方式
parsed = parsed.Where((source, index) => index != 3).ToArray();
编辑 2:
请忽略这个问题并阅读已批准的答案,我误解了引用类型的工作原理。
您确定您的字符串中有 RemoveAt 吗?集合上有 RemoveAt,但字符串或字符串数组本身没有。
您可以这样做:
List<string> lstParse = new List<string>();
foreach (var i in parsed)
{
lstParse.Add(i);
}
string name = parsed[3];
lstParse.RemoveAt(3);
再次加入列表并将其转换为字符串:
string strResult = string.Join(" ", lstParse.ToArray());
如果您真的想在没有新对象列表的情况下删除索引,请忽略上面的代码,您可以改为执行以下一行:
parsed = parsed.Where((source, index) => index != 3).ToArray();
为什么您认为 name
变量应该为空?从数组中删除后它将保持不变。你的原始代码足以完成你想要的。
您误解了引用类型的工作原理。从数组中删除对象不会以任何方式修改该对象 - 它只是意味着该数组不再包含对该对象的 引用。
你可以自己测试一下。 运行 您包含在调试器(或控制台应用程序)中的代码,然后在最后查看(或打印出)name
的值。
当有两个变量(或数组或其他)持有对同一对象的引用时,可以 用引用类型欺骗你。在这种情况下,通过一个变量对对象所做的更改将在通过另一个变量访问对象时反映出来——它是同一个对象,但是有两个不同的变量引用它。如果您希望两个变量都引用它们自己的 "copy" 对象,则必须自己创建一个副本并将其分配给其中一个变量。
但是,在 C# 中,string
类型是 immutable,这意味着一旦创建了 string
对象,就无法更改该对象.所以从来没有理由创建一个字符串的副本。如果有一个引用特定字符串的变量,您可以确定没有其他引用可以从您下面更改它。
假设我有一个字符串数组来自于执行这个 Split 方法
string[] parsed = message.Split(' ');
然后我想将这个数组的某个值存储在一个新的字符串中
string name = parsed[3];
现在我使用扩展方法从数组中删除这个字符串,此方法删除指定索引处的值并将所有内容移回以填补空白
parsed = parsed.RemoveAt(3);
我知道因为字符串在 C# 中是引用类型,所以我的 name 变量现在为 null,经过一些搜索后我被告知在 C# 中精确复制字符串是没有用的。将 name 变量设置为新实例以使其在 .RemoveAt() 调用后不会被删除的最佳和正确方法是什么?
编辑:
这是目前为止我找到的最好的方法
string name = new string(parsed[3].ToCharArray());
提出的另一种方式
parsed = parsed.Where((source, index) => index != 3).ToArray();
编辑 2:
请忽略这个问题并阅读已批准的答案,我误解了引用类型的工作原理。
您确定您的字符串中有 RemoveAt 吗?集合上有 RemoveAt,但字符串或字符串数组本身没有。
您可以这样做:
List<string> lstParse = new List<string>();
foreach (var i in parsed)
{
lstParse.Add(i);
}
string name = parsed[3];
lstParse.RemoveAt(3);
再次加入列表并将其转换为字符串:
string strResult = string.Join(" ", lstParse.ToArray());
如果您真的想在没有新对象列表的情况下删除索引,请忽略上面的代码,您可以改为执行以下一行:
parsed = parsed.Where((source, index) => index != 3).ToArray();
为什么您认为 name
变量应该为空?从数组中删除后它将保持不变。你的原始代码足以完成你想要的。
您误解了引用类型的工作原理。从数组中删除对象不会以任何方式修改该对象 - 它只是意味着该数组不再包含对该对象的 引用。
你可以自己测试一下。 运行 您包含在调试器(或控制台应用程序)中的代码,然后在最后查看(或打印出)name
的值。
当有两个变量(或数组或其他)持有对同一对象的引用时,可以 用引用类型欺骗你。在这种情况下,通过一个变量对对象所做的更改将在通过另一个变量访问对象时反映出来——它是同一个对象,但是有两个不同的变量引用它。如果您希望两个变量都引用它们自己的 "copy" 对象,则必须自己创建一个副本并将其分配给其中一个变量。
但是,在 C# 中,string
类型是 immutable,这意味着一旦创建了 string
对象,就无法更改该对象.所以从来没有理由创建一个字符串的副本。如果有一个引用特定字符串的变量,您可以确定没有其他引用可以从您下面更改它。