参照型
コンストラクターは、型のインスタンスを良好な状態に初期化するための特別なメソッドです。参照型のインスタンスを作成するとき、まずインスタンスのデータ フィールドにメモリが割り当てられ、次にインスタンスの追加フィールドにメモリが割り当てられます。オブジェクト (型オブジェクト ポインターと同期ブロック インデックス) が初期化され、最後に型のインスタンス コンストラクターを呼び出してオブジェクトの初期化状態を設定します。
参照型オブジェクトを構築するとき、オブジェクトに割り当てられたメモリは、電気泳動型のインスタンス コンストラクターの前に常に 0 にリセットされます。コンストラクターによって明示的にオーバーライドされないすべてのフィールドは、0 または null 値を取得することが保証されます。
他のメソッドとは異なり、Strength コンストラクターは決して継承できません。つまり、クラスには、クラス自体によって定義された Smooth コンストラクターのみがあります。インスタンス コンストラクターは継承できないため、Virtual、new、override、sealed、abstract の修飾子はインスタンス コンストラクターで使用できません。クラスがコンストラクターを明示的に定義していない場合、C# コンパイラーはデフォルトでデフォルトのパラメーターなしのコンストラクターを使用し、単に基本クラスのパラメーターなしのコンストラクターを呼び出します。
クラスの修飾子がabstractの場合、コンパイラによって生成されるデフォルトのコンストラクタのアクセシビリティはproductです。それ以外の場合、コンストラクタにはpublic accessible属性が割り当てられます。基本クラスがパラメーターなしのコンストラクターを提供しない場合、派生クラスは基本クラスのコンストラクターを明示的に呼び出す必要があります。そうしないと、コンパイラーによってエラーが報告されます。クラス修飾子が静的 (シールおよび抽象) の場合、コンパイラーはクラス定義にデフォルトのコンストラクターをまったく生成しません。
1 つの型で複数のインスタンス コンストラクターを定義できます。各コンストラクターは異なるシグネチャを持つ必要があり、それぞれが異なるアクセス可能なプロパティを持つことができます。コードを「検証可能」にするには、クラスの初期化子は、基本クラスから継承されたフィールドにアクセスする前に、基本クラスのコンストラクターを呼び出す必要があります。派生クラス コンストラクターが基本クラス コンストラクターを明示的に呼び出さない場合、C# コンパイラーはデフォルトの基本クラス コンストラクターへの呼び出しを自動的に生成します。最終的に、System.Object の引数なしの public コンストラクターが呼び出されます。コンストラクターは何もせず、直接戻ります。System.Object にはインスタンス データ フィールドがないため、コンストラクターは何も行いません。
まれに、インスタンス コンストラクターを呼び出さずに型インスタンスを作成できる場合があります。代表的な例は、Object の MemberwiseClone メソッドです。このメソッドは、メモリを割り当て、オブジェクトの追加フィールドを初期化し、ソース オブジェクト自体のデータを新しいオブジェクトにコピーします。さらに、ランタイム シリアライザー (ランタイム シリアライザー) を使用してオブジェクトを逆シリアル化する場合、同じプロセスでコンストラクターを呼び出す必要はありません。逆シリアル化では、System.Runtime.Serialization.FormatterServices 型の GetUnnitalizedObject メソッドまたは GetSafeUninitailizedObject メソッドを使用してオブジェクトにメモリを割り当てます。プロセス中にコンストラクターは呼び出されません。
ヒント:
コンストラクターで仮想メソッドを呼び出さないでください。その理由は、インスタンス化された型が仮想メソッドをオーバーライドすると、派生型の仮想メソッドの実装が実行されますが、この時点では、継承階層内のすべてのフィールドの初期化が完了していないためです (インスタンス化された型のコンストラクター)まだ実行されていません)。したがって、仮想メソッドを呼び出すと、予期しない動作が発生する可能性があります。結局のところ、これは、仮想メソッドが呼び出されたときに、そのメソッドが実行される実際の型が実行時まで選択されないためです。
値型 (構造体) コンストラクター
値型 (構造体) コンストラクターは、参照型 (クラス) のコンストラクターとはまったく異なる動作をします。 CLR では常に値型のインスタンスの作成が許可されており、値型のインスタンス化を防ぐ方法はありません。したがって、値型では実際にコンストラクターを定義する必要はなく、C# コンパイラーは値型の既定の引数なしのコンストラクターをまったくインライン化しません。次のコードを見てください:
internal struct Point {
public int m_x, m_y;
}
internal sealed class Reactangel
{
public Point m_TopLeft;m_bottomRight;
}
長方形を作成するの場合は、new 演算子を使用し、コンストラクターを指定する必要があります。この例では、C# コンパイラーによって自動的に生成されたデフォルトのコンストラクターが呼び出されます。 Point 値型の 2 つのインスタンスを含む Reatangle にメモリを割り当てます。パフォーマンスを考慮して、CLR は参照型に含まれる各値型フィールドのコンストラクターを積極的に呼び出しません。ただし、前述したように、値型フィールドは 0 または null に初期化されます。
CLR では、値型に対してコンストラクターを定義できますが、実行するにはコンストラクターを明示的に呼び出す必要があります。
内部構造体 Point {
public int m_x, m_y;
public Point(int x, int y)
{
m_x = x;
m_y = y;
}
}
内部シールクラス Reactangel
{
public Point m_TopLeft, m_bottomRight;
public Reactangel()
{
this.m_TopLeft = new Point(1,2);
this.m_bottomRight = new Point(100) 、200 );
}
}
値型のインスタンス コンストラクターは、明示的に呼び出された場合にのみ実行されます。したがって、Rectangle のコンストラクターが new 演算子を使用して Point のコンストラクターを呼び出して Reatangle の m_TopLeft フィールドと m_bottomRight フィールドを初期化しない場合、2 つのポイント フィールドの m_x フィールドと m_y フィールドは両方とも 0 になります。
上記を書き換えますコード:
内部構造体 Point {
public int m_x, m_y;
public Point()
{
m_x = 5;
m_y = 6;
}
}
内部sealed class Reactangel
{
public Point m_TopLeft, m_bottomRight;
public Reactangel()
{
}
}
さて、新しい Rectangle クラスを構築するとき、2 つの Point フィールドの m_x フィールドと m_y フィールドwill どれくらい初期化されるのですか、0ですか、5ですか?
おそらく、C# コンパイラーは Reactangel のコンストラクターでコードを生成し、Reactangel の 2 つのフィールドに対して Point のデフォルトの引数なしのコンストラクターを自動的に呼び出すと考えているかもしれません。ただし、アプリケーションの実行時のパフォーマンスを向上させるために、C# コンパイラーはそのようなコードを自動的に生成しません。実際、値型がパラメーターなしのコンストラクターを提供する場合でも、多くのコンパイラはそれを呼び出すコードを生成しません。値型のパラメーターなしコンストラクターを実装するには、開発者は値型コンストラクターを明示的に呼び出すコードを追加する必要があります。しかし、この理由で Point' の 2 つのフィールドは 0 に初期化されるのでしょうか?結果は次のようになります:
C# コンパイラでは、開発者がそのようなコンストラクターが呼び出されるタイミングについて混乱するのを防ぐために、値型でパラメーターなしのコンストラクターを定義することを意図的に許可していません。パラメーターなしのコンストラクターは定義できないため、パラメーターなしのコンストラクターがないと、値型のフィールドは常に 0 または null に初期化されます。
型コンストラクター:
静的コンストラクター、クラス コンストラクター、または型初期化子とも呼ばれます。型コンストラクターは、参照型および値型とともに使用できます。インスタンス コンストラクターの目的は、型のインスタンスの初期状態を設定することです。同様に、型コンストラクターの役割は、型の初期状態を設定することです。デフォルトでは、型は型コンストラクターを定義しません。定義されている場合、存在できるのは 1 つだけです。さらに、型コンストラクターにはパラメーターがありません。
内部シールクラス SomeRefType {
static SomeRefType()
{
//初回アクセス時はここのコードを実行
}
}
内部構造体 SomeValType
{
静的SomeValType ()
{
//初めてアクセスするときは、ここでコードを実行してください
}
}
型コンストラクターの定義は、パラメーターなしのインスタンス コンストラクターの定義に似ていることがわかりますが、違いは次のとおりです。静的としてマークする必要があるということです。さらに、型コンストラクターは常にプライベートです。これが非公開である理由は、開発者がそれを呼び出すコードを作成できないようにするためであり、CLR は常にその呼び出しに対して責任を負います。
ヒント:
値型で型コンストラクターを定義できますが、CLR が値型の静的コンストラクターを呼び出さない場合があるため、実際には定義しないでください。たとえば、
internal struct SomeValType
{
static SomeValType()
{
Console.WriteLine("この文は表示されません");
}
public int m_x;
}
class Program
{
static void Main(string [ ] args)
{
SomeValType[] a = new SomeValType[10];
a[0].m_x = 123;
Console.WriteLine(a[0].m_x);
Console.ReadKey ( );
}
}
型コンストラクターのコードは、その型の静的フィールドにのみアクセスでき、その型破りな使用法は、これらのフィールドを初期化することです。
以上がコンストラクターとは何ですか?参照型とは何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。