C# - 参照タイプ別の参照タイプ
-
11-10-2019 - |
質問
注:これは、リストとArrayListの両方に適用されます
次の簡単なコードを見てください。
class Creature
{
public string Name;
}
class Game
{
// This is a reference type
public Creature CurrentCreature;
}
class Program
{
static void Main(string[] args)
{
// First, we'll create 2 objects and let the
// reference type "CurrentCreature" points to one of them
Creature dragon = new Creature();
dragon.Name = "Dragon";
Creature Unicorn = new Creature();
dragon.Name = "Unicorn";
Game game = new Game();
game.CurrentCreature = dragon;
// Now we'll create a list which will contain
// the reference type "CurrentCreature"
List<Creature> list = new List<Creature>();
list.Add(game.CurrentCreature);
foreach (Creature c in list)
{
Console.WriteLine(c.Name); // Output is "Dragon"
}
// Now, we'll let "CurrentCreature" point to a different object
game.CurrentCreature = unicorn;
// The reference in the list still pointing to the original object!!!
foreach (Creature c in list)
{
Console.WriteLine(c.Name); // Output is "Dragon"!!!
}
Console.ReadLine();
}
}
リストがアイテムを追加する方法を確認しましたが、新しいオブジェクトのインスタンス化はありません。これはlist.addメソッドです(リフレクターツールを使用)
public void Add(T item)
{
if (this._size == this._items.Length)
{
this.EnsureCapacity(this._size + 1);
}
this._items[this._size++] = item; // No instantiation
this._version++;
}
それで、なぜこれが起こるのですか?リストの要素は、「currentCreature」によって指摘されたオブジェクトへの参照である必要がありますか、それともそうではありませんか?リストを削除すると、次のコードに似ていませんか?:
class A
{
public B X;
}
class B
{
public string Name;
}
....
A a = new A();
B b1 = new B(); b1.Name = "b1";
B b2 = new B(); b2.Name = "b2";
a.X = b1;
Console.WriteLine(a.X.Name); // output: b1
b1 = b2;
Console.WriteLine(a.X.Name); // output: b1
解決
あなたがするとき
game.CurrentCreature = unicorn;
Game.CurrentCreatureのポインターをUnicornオブジェクトに上書きします。配列には、ドラゴンオブジェクトへのポインターがまだあります。変更するべきではありません。これがポインターの仕組みです。
編集:
ポインターで何が起こるかについての少しの説明:
最初に2つのオブジェクトを作成しました
Creature dragon = new Creature();
dragon.Name = "Dragon";
Creature Unicorn = new Creature();
dragon.Name = "Unicorn";
これにより、ドラゴンはドラゴンオブジェクトへのポインターを持ち、ユニコーンにはユニコーンオブジェクトへのポインターがあります。
次に、Game.CurrentCreatureのポインターをDragonのポインターに設定します。
game.CurrentCreature = dragon;
次に、現在のクリーチャーであるドラゴンへのポインターをリストに追加します
List<Creature> list = new List<Creature>();
list.Add(game.CurrentCreature);
次に、game.currentcreature(ドラゴン)のポインターをユニコーンオブジェクトへのポインターに置き換えます。
game.CurrentCreature = unicorn;
これは、ドラゴンオブジェクトに保持されているポインターに決して影響しません。
乾杯、
他のヒント
参照タイプは変更だけではありません。
ゲームではなく、リストにクリーチャーを追加しています。次に、ゲームの参照を変更してAnoTerクリーチャーを使用します。しかし、リストで参照されているクリーチャーは同じままであるため、同じ結果が再び出力されます。
参照 オブジェクトではなく、リストにコピーされます。後 list.Add(myobject);
2つの参照(同じオブジェクトを参照しています)を取得します。Myobjectとリストにあるもの。