6

.NETは、参照によって値が等しい文字列を作成するのに邪魔にならないようです。

LINQPadでは、インターン文字列定数をバイパスすることを期待して、次のことを試しました。

var s1 = new string("".ToCharArray());
var s2 = new string("".ToCharArray());

object.ReferenceEquals(s1, s2).Dump();

しかし、それはを返しますtrue。ただし、他のオブジェクトstringと確実に区別できるものを作成したいと思います。string

(ユースケースは、オプションのパラメーターに使用する番兵値を作成することです。WebFormsをラップしています。Page.Validate()呼び出し元がオプションの検証グループ引数を指定したかどうかに応じて、適切なオーバーロードを選択したいと思います。発信者がその引数を省略したかどうか、または私のデフォルト値と等しい値を渡したかどうかを検出します。明らかに、この特定のユースケースにアプローチする他のあまり難解な方法はありませんが、この質問の目的はより学術的です。)、

4

4 に答える 4

6

.NETは、参照によって値が等しい文字列を作成するのに邪魔にならないようです。

実際、ここで説明しているような動作を示す文字列の特殊なケースは2つだけです。

  1. コード内の文字列リテラルはインターンされているため、2つの場所に同じリテラルがあると、同じオブジェクトへの参照になります。
  2. の文字列は特に奇妙なケースです。私が知る限り、.NETプログラムのすべての空の文字列は実際には同じオブジェクトです(つまり、「すべての空の文字列」は単一の文字列を構成します)。これは、.NETで私が知っている唯一のケースであり、new(クラスで)キーワードを使用しても、新しいオブジェクトが割り当てられない可能性があります。

あなたの質問から、あなたが最初のケースについてすでに知っていたという印象を受けます。2番目のケースは、あなたが偶然見つけたケースです。他の人が指摘しているように、先に進んで空でない文字列を使用すると、参照ではない文字列を作成するのが非常に簡単であることがわかります。これは、プログラム内の他の文字列と同じです。

public static string Sentinel = new string(new char[] { 'x' });

少し編集はさておき、私は実際にはこれをそれほど気にしません(文書化されている限り)。しかし、CLRの人々(?)が、アレイに対しても同じことを行わずに、この最適化を実装したことは、私を少し苛立たせます。つまり、彼らは先に進んで、すべてnew T[0]が同じオブジェクトを参照するようにしたのではないかと私には思えます。または、文字列に対してもそれを行わないでください。

于 2012-12-12T03:43:07.453 に答える
3

文字列がReferenceEqualの場合、それらは同じオブジェクトです。を呼び出すとnew string(new char[0])、string.Emptyと等しい参照である新しいオブジェクトは取得されません。それは不可能でしょう。むしろ、作成済みのstring.Emptyインスタンスへの新しい参照を取得します。これは、文字列コンストラクターの特殊なケースのコードの結果です。

これを試して:

var s1 = new string(new char { 'A', 'b' });
var s2 = new string(new char { 'A', 'b' });

object.ReferenceEquals(s1, s2).Dump();

また、文字列定数がインターンされていることに注意して"Ab"ください。コード内のリテラルのすべてのインスタンスは、すべて同じ文字列オブジェクトを参照しているため、互いに等しく参照されます。定数畳み込みも適用されるため、定数式"A" + "b"も。に等しい参照になり"Ab"ます。

したがって、センチメンタル値は、個人的に作成されたゼロ以外の長さの文字列にすることができます。

于 2012-12-12T03:21:20.647 に答える
1

印刷できない文字を文字列に入れることができます...0/nul文字ですら。しかし実際にはnull、番兵の値に使用し、他の場所のコードがnullではなく空の文字列を使用していることを確認しようとします。

于 2012-12-12T03:29:04.950 に答える
0

So I want to be able to detect whether the caller omitted that argument, or whether he passed a value that happens to be equal to my default value.

I've never done this before, but my thoughts would be to make a Nullable class... but instead of Nullable it would be Parameter and would keep track on whether or not it has been assigned anything (including null).

于 2012-12-12T03:10:43.007 に答える