.NET中的System.String.Copy有什么用?
恐怕这是一个非常愚蠢的问题,但我一定会错过一些东西。
为什么要用String.Copy(string) ?
文档说明了这个方法
使用与指定的String相同的值创buildString的新实例。
由于string在.NET中是不可变的,所以我不确定使用这种方法有什么好处,就像我想的那样
string copy = String.Copy(otherString);
对于所有的实际目的,似乎都会产生同样的结果
string copy = otherString;
也就是说,除了正在进行的内部簿记之外,以及事实上副本不是ReferenceEquals
到otherString,没有可观察到的差异 – string是一个不可变的类,其相等性基于值而不是标识。 (感谢@Andrew Hare指出,我原来的措辞不够精确,不足以表明我意识到Copy
和非Copy
之间存在差异,但担心感觉缺乏有用的差异。)
当然,当传递一个null
参数时,Copy抛出一个ArgumentNullException
,并且“新实例”可能消耗更多的内存。 后者似乎不是一个好处,我不确定这个空检查是一个足够大的奖金,以保证整个Copy方法。
谢谢。
有了String.Copy
你实际上正在分配新的内存并将字符从一个string复制到另一个string。 你会得到一个全新的实例,而不是使两个variables都是同一个实例。 这可能会影响,如果你使用非托pipe代码的string直接处理内存位置,可以改变string。
String.Copy
返回一个新的String
,并不会产生相同的结果
String copy = otherString;
尝试这个:
using System; class Program { static void Main() { String test = "test"; String test2 = test; String test3 = String.Copy(test); Console.WriteLine(Object.ReferenceEquals(test, test2)); Console.WriteLine(Object.ReferenceEquals(test, test3)); Console.ReadLine(); } }
当你设置test2 = test
这些引用指向相同的String
。 Copy
函数返回一个新的String
引用,它具有相同的内容,但在堆上是不同的对象。
编辑:有很多人都很沮丧,我没有回答OP的问题。 我相信我是通过纠正问题本身的错误前提来回答这个问题的。 这是一个类似的(如果不是过于简单的)问题和答案,希望能够说明我的观点:
题:
我观察到,我的车有两个车门,一个在车的两边。 我相信,无论我使用哪扇门,我最终都会坐在驾驶座上。 另一扇门的目的是什么?
回答:
事实上,如果你使用任何一个门,你最终还是会坐在驾驶座上。 如果使用驾驶员的侧门,则最终进入驾驶座,如果使用乘客的侧门,则最终会进入乘客座位。
现在在这个例子中,你可能会认为答案不是真正的答案,因为问题是“乘客侧门的目的是什么?”。 但是,既然这个问题完全是基于对门的工作方式的错误认识,那么否定这个前提的驳斥将会通过推论来揭示另一个门的目的?
这是一个难题。 这并不能解释你为什么要这样做,但它确实有助于解释function差异。
如果使用fixed
关键字fixed
string,则内容将是可变的。 在我头顶,我想不出你想要这样做的情况,但是这是可能的。
string original = "Hello World"; string refCopy = original; string deepCopy = String.Copy(original); fixed(char* pStr = original) { *pStr = 'J'; } Console.WriteLine(original); Console.WriteLine(refCopy); Console.WriteLine(deepCopy);
输出:
Jello World Jello World Hello World
string a = "abc"; string b = String.Copy(a); Monitor.Enter(a); // not the same as Monitor.Enter(b);
然而
string c = "123"; string d = c; Monitor.Enter(c); // the same as Monitor.Enter(d);
至于任何人都会关心的方式,我认为这是完整的。
也
StringBuilder sb = new StringBuilder(100); sb.Append("abc"); string a = sb.ToString(); string b = String.Copy(a);
我认为a
会占用更多的RAM,然后b
,指向StringBuilder
创build的大小为100的缓冲区。 (看看StringBuilder.ToString()
方法的内部)
我认为StringBuilder
使用String.Copy()
并作为.NET框架的一部分, StringBuilder
确实改变了string
的内容。 所以一个string
并不总是不变的。
通过.NET 4.0的BCL快速search显示,在大约六个地方调用string.Copy
方法。 用法大致分为以下几类:
-
与本地函数互操作,可能会损坏传递给它们的string。 如果您不能影响P / Invoke声明并且无法修复正在调用的函数,
string.Copy
是最好的select。 -
出于性能原因,对string进行就地修改的情况。 如果您需要在可能的长string中只将几个字符转换为小写字符,唯一的方法是在不复制string两次的情况下创build额外的垃圾信息就是改变它。
-
在似乎没有必要的地方。 一些程序员很可能更习惯于Java或C ++string,并没有意识到在C#中复制string很less有用。
除了什么tvanfosson说(我不认为你可以从非托pipe代码访问托pipestring使用的缓冲区…我知道这将是困难的,至less),我相信,如果string是可能有所不同用作对multithreadingfunction进行locking的对象。
例如…
using System; public class Class1 { string example1 = "example"; string example2 = example1; public void ExampleMethod1() { lock (example1) { Console.WriteLine("Locked example 1"); //do stuff... } } public void ExampleMethod2() { lock (example2) { Console.WriteLine("Locked example 2"); //do stuff } } }
我相信如果这两个示例方法并行运行,它们将locking相同的对象,因此一个将不能执行,而另一个在其locking块内。
但是,如果您将其更改为此…
using System; public class Class1 { string example1 = "example"; string example2 = string.Copy(example1); public void ExampleMethod1() { lock (example1) { Console.WriteLine("Locked example 1"); //do stuff... } } public void ExampleMethod2() { lock (example2) { Console.WriteLine("Locked example 2"); //do stuff } } }
然后我相信他们只会阻止执行其他线程执行相同的方法(即执行ExampleMethod1的任何线程将被locking,直到每个完成,但他们不会干扰运行ExampleMethod2的线程)。
不知道这是一个有用的区别,因为有更好的同步机制(我不认为lockingstring是一个非常好的主意)。
string a = "test"; string b = a; //Object.ReferenceEquals(a,b) is true a += "more"; //Object.ReferenceEquals(a,b) is now false !
自动更改检测?
我不知道如何在.NET中实现string,但我认为Java是一个很好的参考。
在Java中,新的String(str)也会做什么String.copy(str); 做,分配一个新的string具有相同的值。
这似乎没用,但在内存优化中非常有用。
String在实现中包含一个char [],偏移量和长度。 如果你做了一个子string,它不会做一个内存拷贝,但返回一个新的string实例共享相同的字符[]。 在很多情况下,这种模式会节省大量的内存拷贝和分配。 但是,如果你在一个很长的大string中对一小段子进行子串处理。 它仍然会引用大字符[],即使原来的大string也可以是GC。
String longString = // read 1MB text from a text file String memoryLeak = largeString.substring(100,102); largeString=null; // memoryLeak will be sized 1MB in the memory String smaller = new String(largeString.substring(100,102)); // smaller will be only few bytes in the memory
它可以强制新的String对象分配它自己的char []来防止隐藏的内存泄漏/浪费。