object[] objs = new object[]{"one","two","three"};
文字列オブジェクトへの参照として配列に格納されている文字列
[@] - one
[@] - two
[@] - three
または、文字列オブジェクトが配列要素に格納されていますか?
[one][two][three]
ありがとう。
編集:申し訳ありませんが、私の派手な図は惨めに失敗しました。
文字列オブジェクトは、配列に直接格納したり、他の変数として格納したりすることはできません。次のような単純なケースであっても、常に参照です。
string x = "foo";
ここで、 の値x
は参照であり、オブジェクトではありません。式の値がオブジェクトになることはありません。常に、参照、値型の値、またはポインターのいずれかです。
Jon Skeet は実際の実装について非常によく説明していますが、CLR が文字列を配列に直接格納することが無意味である理由を考えてみましょう。
最初の理由は、文字列を配列に直接格納するとパフォーマンスが低下するためです。文字列が配列に直接格納されている場合、配列の要素 1000 に到達するために、CLR は要素 1000 に到達するまで配列内のすべての文字列のバイトを調べ、その間ずっと文字列の境界をチェックする必要があります。文字列やその他の参照型は参照として配列に格納されるため、配列の正しい要素を見つけるには、1 回の乗算、1 回の加算、および 1 つのポインターの追跡が必要です (ここでのポインターの概念は実装レベルであり、プログラマーから見えるものではありません)。レベル)。これにより、パフォーマンスが大幅に向上します。
文字列を配列に直接格納できない 2 つ目の理由は、参照型の C# 配列が共変であることです。で生成された配列に文字列が直接格納されたとしましょう
string[] strings = new string[] {"one", "two", "three"};
次に、これをオブジェクト配列にキャストします。これは合法です
object[] objs = (object[])strings;
コンパイラは、この可能性を考慮したコードをどのように生成することになっていますか? オブジェクト配列をパラメーターとして受け取るメソッドには、文字列配列を渡すことができるため、CLR は、オブジェクト配列、文字列配列、またはその他の種類の配列として配列にインデックスを付けるかどうかを知る必要があります。どういうわけか、実行時にすべての配列を配列の型宣言でマークする必要があり、すべての配列アクセスは型宣言をチェックしてから、配列の型に応じて異なる方法で配列をトラバースする必要があります。配列アクセスの単一の実装を許可し、起動時のパフォーマンスを向上させる参照を使用する方がはるかに簡単です。
それらは参照として内部的に保存されます。文字列のコピーが保存され、その文字列が使用されている場所には、保存されている同じ文字列への参照があります。(これは、文字列が不変である多くの理由の 1 つです。そうしないと、文字列の 1 つのインスタンスを変更すると、それが現れたすべての場所が変更されます)
すべてのプリミティブ型は配列に直接格納されますが、他のすべてのオブジェクトまたは参照型はメモリ参照として格納されます。これは、文字列に限定されないすべてのオブジェクトに当てはまります。