恐怕这是一个非常愚蠢的问题,但我一定错过了一些东西。

为什么人们想要使用 字符串.复制(字符串)?

文档说的是方法

创建一个与指定字符串相同值的字符串的新实例。

由于字符串在 .NET 中是不可变的,我不确定使用这种方法有什么好处,因为我认为

 string copy = String.Copy(otherString);

出于所有实际目的似乎会产生与以下相同的结果

 string copy = otherString;

也就是说,除了正在进行的任何内部簿记,以及副本不存在的事实 ReferenceEquals 与 otherString 相比,没有明显的差异 - String 是一个不可变的类,其相等性基于值,而不是身份。(感谢@Andrew Hare 指出我原来的措辞不够精确,不足以表明我意识到两者之间存在差异 Copy荷兰国际集团和不是,但担心人们认为缺乏 有用 不同之处。)

当然当通过了 null 参数, Copy 抛出一个 ArgumentNullException, ,并且“新实例”可能会消耗更多内存。后者看起来似乎没什么好处,而且我不确定空检查是否有足够大的好处来保证整个 Copy 方法。

谢谢。

有帮助吗?

解决方案

使用String.Copy你实际上分配新的内存和复制从一个串到另一个字符;你会得到一个完全新的实例,而不是有两个变量是相同的实例。如果使用与非托管代码串,其直接与存储器位置优惠和可能变异字符串这可能无所谓。

其他提示

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的提问人的。我相信,我没有在这个问题本身纠正不正确的前提回答这个问题。下面是一个类似的(如果不是简单化)的问题和答案,希望能说明我的观点:

<强>问题:

  

我观察到我的车有两个门,一个在车的每一侧上。我相信这是真实的,不管我用这门我最终会坐在驾驶员的座位上。什么是其他门的目的是什么?

<强>答案:

  

其实这是不正确的,如果您使用的门,你会在司机的座位告终。如果你使用驾驶员侧车门,你会在驾驶座结束了,如果你使用的乘客侧车门,你会在乘客的座位告终。

现在,在这个例子中,你可能会认为,答案是没有真正的问题是“什么是乘客侧车门的目的是什么?”的答案。但由于这个问题是完全基于的一个误解的大门是如何工作它不遵循的前提驳斥将扣除洒在对方大门的目的,新的光?

这里的问题的一部分。这并不能解释为什么你会想这样做,但它确实有助于解释功能上的差异。

如果您固定使用fixed关键字字符串,内容将是可变的。关闭我的头顶,我想不出在其中,你会想这样做的情况,但它是可能的。

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

快速搜索 .NET 4.0 的 BCL 显示 string.Copy 方法在大约六个地方被调用。用途大致分为以下几类:

  1. 用于与本机函数的互操作,可能会损坏传递给它们的字符串。如果您无法影响 P/Invoke 声明并且无法修复正在调用的函数, string.Copy 是最好的选择。

  2. 适用于出于性能原因而就地修改字符串的情况。如果您需要将可能很长的字符串中的几个字符转换为小写,那么在不复制字符串两次并创建额外垃圾的情况下执行此操作的唯一方法是对其进行变异。

  3. 在一些看起来没有必要的地方。很可能某些程序员更习惯 Java 或 C++ 字符串,并且没有意识到在 C# 中复制字符串很少有用。

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,如a指向所述StringBuilder创建的尺寸100的缓冲液中。 (看StringBuilder.ToString()方法的内部)


我认为StringBuilder利用String.Copy()的和.NET框架StringBuilderdoes改变string的内容的是一部分。因此,一个string并不总是不变的。

除了什么tvanfosson说(我不认为你可以访问由非托管代码托管字符串中使用的缓冲......我知道这将是困难的,至少),我认为有可能是,如果差异的字符串被用作对象做一个锁定上的多线程功能。

有关实例...

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
        }
    }
}

我相信,如果两个示例方法在并行运行,它们将被锁定相同的对象,因此一个将无法执行,而另一个是它的锁块内。

不过,如果你把它变成这样...

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将被锁定,直到每个完成的任何线程,但它们不会与线程中运行ExampleMethod2干扰)。

不知道这是一个的有用的区别,因为有同步更好的机制(我不认为锁定字符串是一个非常不错的主意)。

string a = "test";
string b = a;
//Object.ReferenceEquals(a,b) is true
a += "more";
//Object.ReferenceEquals(a,b) is now false !

自动变化检测?

我不知道串是如何在.NET中实现的,但我认为Java是一个很好的参考。

在Java中,新的字符串(STR)也做什么String.copy(STR);这样做,分配一个新的字符串相同的值。

这似乎无用的,但它是在内存优化是非常有用的。

的字符串包含一个char []与在实施偏移量和长度。 如果你做一个类似的子串,它不会做内存拷贝,但返回一个新的String实例共享相同的char []。在许多情况下,这种模式将节省大量的内存拷贝和分配。但是,如果串长的大字符串中的一小块。它仍然会引用到大的char []甚至原大字符串能够被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

它可以迫使新的字符串对象分配它自己的char []可以防止隐式存储器泄漏/浪费。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top