.NET での System.String.Copy の用途は何ですか?
-
21-08-2019 - |
質問
非常にばかげた質問で申し訳ありませんが、何かが欠けているはずです。
なぜ使用したいのか 文字列.コピー(文字列)?
ドキュメントにはメソッドが記載されています
指定された文字列と同じ値を持つ文字列の新しいインスタンスを作成します。
.NET では文字列は不変であるため、このメソッドを使用する利点はわかりません。
string copy = String.Copy(otherString);
すべての実用的な目的では、次と同じ結果が得られるように見えます
string copy = otherString;
つまり、内部で行われている帳簿管理と、コピーがコピーされないという事実を除いては、 ReferenceEquals
otherString に対して、目に見える違いはありません。String は不変クラスであり、その等価性は同一性ではなく値に基づいています。(私の元の表現が、両者の間に違いがあることに気づくほど正確ではなかったと指摘してくれた @Andrew Hare に感謝します。 Copy
しているかどうかはわかりませんが、不足していると認識されることを懸念していました。 役に立つ 違い。)
もちろん合格したときは、 null
引数の場合、コピーは ArgumentNullException
, そして、「新しいインスタンス」はより多くのメモリを消費する可能性があります。後者はほとんど利点とは思えませんし、null チェックが 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の質問に答えなかったことにかなり怒っている人がたくさんいます。質問自体の誤った前提を修正して、質問に回答したと思います。私の要点をうまく説明できる類似の(単純化しすぎではないにしても)質問と回答を次に示します。
質問:
私の車には、車の両側に 1 つずつ、計 2 つのドアがあることに気付きました。どのドアを使っても最終的には運転席に座ることになるのは事実だと思います。もう一方の扉の目的は何でしょうか?
答え:
実際には、どちらのドアを使っても運転席に着くというのは真実ではありません。運転席側ドアを使用すると運転席、助手席側ドアを使用すると助手席になります。
この例では、質問が「助手席側ドアの目的は何ですか?」であるため、実際には答えではないと主張することもできます。しかし、その質問はドアがどのように機能するかについての完全な誤解に基づいていたため、前提の反駁は演繹によってもう一方のドアの目的に新たな光を当てるということにはなりませんか?
ここではパズルの一片です。あなたがそれをしたいと思う理由は説明していないが、それは機能的な違いを説明するのに役立つん。
あなたは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
メソッドは約 6 か所で呼び出されます。使用法は、大まかに次のカテゴリに分類されます。
渡された文字列を損傷する可能性のあるネイティブ関数との相互運用用。P/Invoke 宣言に影響を与えることができず、呼び出される関数を修正できない場合は、
string.Copy
が最良の選択です。パフォーマンス上の理由から文字列がその場で変更される場合。潜在的に長い文字列の中で数文字だけを小文字に変換する必要がある場合、文字列を 2 回コピーして追加のゴミを作成せずに変換する唯一の方法は、文字列を変更することです。
必要がないと思われる場所でも。一部のプログラマは 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
がb
が作成したサイズ100のバッファにa
ポイントとして、その後、StringBuilder
より多くのRAMを取るだろうと思います。 (StringBuilder.ToString()
法の内側を見てください)
私はStringBuilder
がString.Copy()
を使用すると思うし、.NETフレームワークStringBuilder
doesの一部である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
}
}
}
私は2つの例示的な方法は、並列に実行された場合、それらは同じオブジェクトをロックするので、一方が他方をそのロック・ブロック内にあるながら実行することができなくなると考えています。
しかし、あなたがこのように変更した場合...
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では、新しいString(文字列)も何をString.copy(STR)を行います。 、同じ値を持つ新しい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オブジェクトを強制することができ、それは隠されたメモリリーク/浪費を防止するために、[]自身のシャア割り当てます。