属性
プロパティは、物事の状態を表します。プロパティのアクセス方法は、読み取り(読み取り)または書き込み(ストア)できます。読み取りプロパティと書き込みプロパティはget
、それぞれとで表されますset
。
修饰符 类型名 属性名{
get{
// 读
}
set{
// 写
}
}
属性とフィールドの比較:
- 属性は読み取り専用または書き込み専用にすることができますが、フィールドはできません。
- 属性のsetメソッドは、ユーザーが指定した値の有効性をチェックして、正しい状態のみを設定できることを確認できますが、フィールドは設定できません。
- 属性のgetメソッドは、フィールド変数の値を返すだけでなく、計算または処理されたデータを返すこともできます。
- プロパティは実際には実装時のメソッドであるため、抽象プロパティを定義する機能など、メソッドのいくつかの利点があります。
C#では、属性が状態の設定と取得をより適切に表現していることがわかります。したがって、C#では、次の原則が一般的に採用されています。
- 物事の状態情報がクラス内に記録されている場合、フィールド変数が使用されます。
- フィールド変数は通常、外部での使用を防ぐためにプライベートで変更されます。
- 物事のステータス情報を公開するには、属性を使用します。
- 属性は通常、1つまたは複数のフィールド変数と対応する関係があります。
属性の省略形:
C#3.0以降、単純なケースでは、属性を省略できます。{ set; get; }
実装本体を記述せずに、書き込むだけで、コンパイラはそれを実装するためのフィールドを自動的に生成します。例えば:
class Person
{
public string Name {
set; get; }
public string Age {
set; get; }
}
コンパイラは、次のようなコードを自動的に生成します。
class Person
{
private string name;
private int age;
public string Name {
get => name; set => name = value; }
public int Age {
get => age; set => age = value; }
}
この省略形は、プログラムの記述を大幅に簡素化し、一種のコンパイラー「シンタックスシュガー」です。(本当に甘い)
オブジェクトが初期化されるときに、属性に直接値を割り当てます
C#でオブジェクト(新規)を作成する場合、属性に値を直接割り当てることができます:
Person p = new Person {
Name = "Joe", Age = 19
};
これも一種のシンタックスシュガーであり、コンパイラーは1つのnew
ステートメントと複数の属性割り当てステートメントを生成します。
匿名型
次のようにクラスを事前に定義する代わりに、作成されたオブジェクトエンティティとその属性を直接定義できます。
new {
Title = "C#", Author = "Tang", Price = 1.5 }
匿名型オブジェクトは、次のobject
ように使用できます。
static void Main (string[] args) {
object[] books = {
new {
Title = "C#", Author = "Tang", Price = 1.5 },
new {
Title = "Java", Author = "Zhang", Price = 2.1 }
};
Console.WriteLine (books.Length);
}
インデクサー
インデクサー(インデクサー)は、オブジェクトが添え字を付けることによって値を取得できるようにする機能メンバーでもあります。「インデクサー」を定義すると、クラスの「仮想配列」が作成され、このクラスのインスタンスには[](配列アクセス演算子)を使用してアクセスできます。ある意味で、属性はフィールドへのアクセスであり、インデクサーは配列(または要素のセット)へのアクセスです。
インデクサーの定義と使用
配列のような関数またはコレクションのような関数をカプセル化するクラスの場合、インデクサーを使用すると、このクラスのユーザーは配列構文を使用してクラスにアクセスできます。
修饰符 类型名 this [参数列表]{
set{
}
get{
}
}
その中には、属性の定義に似たsetメソッドとgetメソッドがあります。setメソッドでは、特別な変数を使用しvalue
て、ユーザーが指定した値を表すこともできます。getメソッドは、return
返されたインデクサー値を使用します。
ただし、属性の定義とは異なり、ここには属性名はありませんが、とthis
を使用した[]
インデクサーがあります。
インデクサーを使用する方法は次のとおりです。
对象名[参数]
インデクサーは、読み取りと書き込みの両方に使用できます。システムは、対応するgetメソッドとsetメソッドを自動的に呼び出します。実際、コンパイラーは、タイプがTでパラメーターリストがPであるインデクサーに対して、次の2つのメソッドを自動的に生成します。
T get_Item(p);
void set_Item(P, T value);
インデクサの過負荷
同じクラスの複数のインデクサーは、異なるパラメーターリスト(署名)を必要とします。つまり、パラメーターの数が異なるか、パラメータータイプが異なるか、パラメータータイプの順序が異なります。
例:IndexerRecord.csは、インデクサーを使用して本のレコードを表します。この例では、2つのインデクサーが提供されています。1つはパラメーターとして整数を使用し、もう1つはパラメーターとしてキーワードを使用します。プログラムは、1つのインデクサーで別のインデクサーも呼び出します。
class IndexerRecord
{
private string[] data = new string[6];
private string[] keys = {
"Author", "Publisher", "Title",
"Subject", "ISBN", "Comments"
};
public string this[int idx] {
set {
if (idx >= 0 && idx < data.Length)
data[idx] = value;
}
get {
if (idx >= 0 && idx < data.Length)
return data[idx];
return null;
}
}
public string this[string key] {
set {
int idx = FindKey (key);
this[idx] = value;
}
get {
return this[FindKey (key)];
}
}
private int FindKey (string key) {
for (int i = 0; i < keys.Length; i++)
if (keys[i] == key) return i;
return -1;
}
static void Main (string[] args) {
Console.WriteLine ("Hello World!");
IndexerRecord record = new IndexerRecord ();
record[0] = "马克-吐温";
record[1] = "Crox出版公式";
record[2] = "汤姆-索亚历险记";
Console.WriteLine (record["Title"]);
Console.WriteLine (record["Author"]);
Console.WriteLine (record["Publisher"]);
}
}
属性とインデクサーの比較
属性とインデクサーの両方が物事の状態を表すことができます。それらの比較は次のとおりです。