オブジェクト (C# プログラミング ガイド)
更新 : 2007 年 11 月
クラスまたは構造体の定義は、型が実行できる操作を指定する設計図のようなものです。オブジェクトとは、基本的に、設計図に基づいて割り当ておよび構成されたメモリ ブロックです。プログラムでは、同じクラスの多数のオブジェクトを作成できます。オブジェクトはインスタンスとも呼ばれ、名前付き変数か、配列またはコレクションに格納できます。クライアント コードは、これらの変数を使用してメソッドを呼び出し、オブジェクトのパブリック プロパティにアクセスするコードです。C# などのオブジェクト指向言語の場合、一般的なプログラムは、動的に対話する複数のオブジェクトで構成されます。
メモ : |
---|
静的な型の動作は、ここでの説明とは異なります。詳細については、「静的クラスと静的クラス メンバ (C# プログラミング ガイド)」を参照してください。 |
構造体のインスタンスとクラスのインスタンス
クラスは参照型であるため、クラス オブジェクトの変数は、マネージ ヒープ上のオブジェクトのアドレスへの参照を保持します。同じ型の 2 番目のオブジェクトが最初のオブジェクトに割り当てられる場合は、両方の変数がそのアドレスのオブジェクトを参照します。この点については、後で詳しく説明します。
クラスのインスタンスは、new 演算子を使用して作成されます。次の例では、Person が型であり、person1 と person 2 がその型のインスタンス (つまりオブジェクト) です。
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public Person(string name, int age)
{
Name = name;
Age = age;
}
//Other properties, methods, events...
}
class Program
{
static void Main()
{
Person person1 = new Person("Leopold", 6);
Console.WriteLine("person1 Name = {0} Age = {1}", person1.Name, person1.Age);
// Declare a new person, assign person1 to it.
Person person2 = person1;
//Change the name of person2, and person1 also changes.
person2.Name = "Molly";
person2.Age = 16;
Console.WriteLine("person2 Name = {0} Age = {1}", person2.Name, person2.Age);
Console.WriteLine("person1 Name = {0} Age = {1}", person2.Name, person2.Age);
// Keep the console open in debug mode.
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}
/*
Output:
person1 Name = Leopold Age = 6
person2 Name = Molly Age = 16
person1 Name = Molly Age = 16
*/
構造体は値型であるため、構造体オブジェクトの変数は、オブジェクト全体のコピーを保持します。次の例に示すように、構造体のインスタンスも new 演算子を使用して作成できますが、これは必須ではありません。
public struct Person
{
public string Name;
public int Age;
public Person(string name, int age)
{
Name = name;
Age = age;
}
}
public class Application
{
static void Main()
{
// Create a struct instance and initialize by using "new".
// Memory is allocated on thread stack.
Person p1 = new Person("Alex", 9);
Console.WriteLine("p1 Name = {0} Age = {1}", p1.Name, p1.Age);
// Create a new struct object. Note that a struct can be initialized
// without using "new".
Person p2 = p1;
// Assign values to p2 members.
p2.Name = "Spencer";
p2.Age = 7;
Console.WriteLine("p2 Name = {0} Age = {1}", p2.Name, p2.Age);
// p1 values remain unchanged because p2 is a copy.
Console.WriteLine("p1 Name = {0} Age = {1}", p1.Name, p1.Age);
// Keep the console open in debug mode.
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}
/*
Output:
p1 Name = Alex Age = 9
p2 Name = Spencer Age = 7
p1 Name = Alex Age = 9
*/
p1 と p2 のメモリは、スレッド スタックに割り当てられています。メモリは、それが宣言されている型やメソッドと共に再利用されます。これは、構造体が代入時にコピーされる 1 つの理由でもあります。これとは対照的に、クラスのインスタンスに割り当てられるメモリは、オブジェクトへのすべての参照がスコープ外に出ると、共通言語ランタイムによって自動的にクリア (ガベージ コレクト) されます。C++ で行うようにクラス オブジェクトを確定的に破棄することはできません。.NET Framework のガベージ コレクションの詳細については、「ガベージ コレクション」を参照してください。
メモ : |
---|
マネージ ヒープ上のメモリの割り当てと解放は、共通言語ランタイムで高度に最適化されます。ほとんどの場合、ヒープへのクラス インスタンスの割り当てとスタックへの構造体のインスタンスの割り当ての間で、パフォーマンスに対する影響が大きく変わることはありません。 |
オブジェクト ID と値の等価性
2 つのオブジェクトの等価性を比較するときは、2 つの変数がメモリ内の同じオブジェクトを表すかどうか、または 1 つ以上のオブジェクトのフィールドの値が等しいかどうかのどちらを特定する必要があるのかを最初に区別する必要があります。値を比較する場合は、オブジェクトが値型 (構造体) と参照型 (クラス、デリゲート、配列) のどちらのインスタンスであるかを考慮してください。
2 つのクラスのインスタンスがメモリ内の同じ場所を参照する (つまり、ID が同じである) かどうかを確認するには、静的メソッド Equals を使用します (System.Object は、ユーザー定義の構造体とクラスを含む、すべての値型および参照型の暗黙の基本クラスです)。
2 つの構造体のインスタンスのインスタンス フィールドの値が同じかどうかを確認するには、ValueType.Equals メソッドを使用します。すべての構造体は暗黙に System.ValueType を継承するため、次の例に示すように、オブジェクトで直接メソッドを呼び出します。
Person p1 = new Person("Wallace", 75);
Person p2;
p2.Name = "Wallace";
p2.Age = 75;
if (p2.Equals(p1))
Console.WriteLine("p2 and p1 have the same values.");
// Output: p2 and p1 have the same values.
Equals の System.ValueType 実装では、任意の構造体にどのようなフィールドが含まれているかを判断する必要があるため、リフレクションが使用されます。独自の構造体を作成する場合は、Equals メソッドをオーバーライドして、効率的に等価性を判断する型固有のアルゴリズムを実装してください。
関連項目
詳細情報