ゲッターとセッターの概念を理解するのに苦労していますC#言語で。 Objective-Cのような言語では、それらはシステムの不可欠な部分のように見えますが、C#ではそれほどではありません(私が知る限り)。私はすでに本や記事を読んだことがあるので、私の質問は、C#でゲッターとセッターを理解している人にとって、完全な初心者に概念を教える場合に個人的にどのような例を使用するかです(これには可能な限り数行のコード)?
少しのコードは、セッターとゲッターが何であるかを説明するのに役立つと思います:
public class Foo
{
private string bar;
public string GetBar()
{
return bar;
}
public void SetBar(string value)
{
bar = value;
}
}
この例では、barと呼ばれるクラスのプライベートメンバーがあります。 GetBarメソッドとSetBarメソッドは、指定されたとおりの処理を行います。1つはバーメンバーを取得し、もう1つはその値を設定します。
C#1.1 +にはプロパティがあります。基本的な機能も同じです:
public class Foo
{
private string bar;
public string Bar
{
get { return bar; }
set { bar = value; }
}
}
プライベートメンバーバーは、クラス外からはアクセスできません。ただし、パブリックの「Bar」には2つのアクセサがあります。上記の例のように「getBar()」がプライベートメンバーを返すgetと、前述のSetBar(string value)メソッドに対応するset例。
C#3.0以降では、コンパイラはそのようなプロパティがプライベートメンバーをソースとして持つ必要がない点まで最適化されました。コンパイラは、そのタイプのプライベートメンバを自動的に生成し、プロパティのソースとして使用します。
public class Foo
{
public string Bar { get; set; }
}
コードが示すのは、コンパイラーによって生成されたプライベートメンバーを持つ自動プロパティです。プライベートメンバーは表示されませんが、表示されます。これにより、主にアクセス制御に関する他の問題もいくつか発生しました。 C#1.1および2.0では、プロパティの取得または設定部分を省略できます。
public class Foo
{
private string bar;
public string Bar
{
get{ return bar; }
}
}
他のオブジェクトがFooクラスの "Bar"プロパティと対話する方法を制限する機会を与えます。 C#3.0以降から-自動プロパティを使用することを選択した場合、プロパティへのアクセスを次のように指定する必要があります。
public class Foo
{
public string Bar { get; private set; }
}
つまり、クラス自体のみがBarに値を設定できますが、Barの値は誰でも読み取ることができます。
C#では、 プロパティ はゲッターとセッターを表します。
以下に例を示します。
public class PropertyExample
{
private int myIntField = 0;
public int MyInt
{
// This is your getter.
// it uses the accessibility of the property (public)
get
{
return myIntField;
}
// this is your setter
// Note: you can specify different accessibility
// for your getter and setter.
protected set
{
// You can put logic into your getters and setters
// since they actually map to functions behind the scenes
DoSomeValidation(value)
{
// The input of the setter is always called "value"
// and is of the same type as your property definition
myIntField = value;
}
}
}
}
このプロパティにはフィールドと同じようにアクセスします。例えば:
PropertyExample example = new PropertyExample();
example.MyInt = 4; // sets myIntField to 4
Console.WriteLine( example.MyInt ); // prints 4
その他の注意事項:
ほとんどの言語はこの方法で行いますが、C#でも実行できます。
public void setRAM(int RAM)
{
this.RAM = RAM;
}
public int getRAM()
{
return this.RAM;
}
しかし、C#はこれに対してよりエレガントなソリューションも提供します。
public class Computer
{
int ram;
public int RAM
{
get
{
return ram;
}
set
{
ram = value; // value is a reserved Word and it is a variable that holds the input that is given to ram ( like in the example below )
}
}
}
後でアクセスします。
Computer comp = new Computer();
comp.RAM = 1024;
int var = comp.RAM;
C#の新しいバージョンの場合はさらに優れています。
public class Computer
{
public int RAM { get; set; }
}
以降 :
Computer comp = new Computer();
comp.RAM = 1024;
int var = comp.RAM;
私の説明は次のようになります。 (それほど短くはありませんが、非常に簡単です。)
変数を持つクラスを想像してください:
_class Something
{
int weight;
// and other methods, of course, not shown here
}
_
さて、このクラスには小さな問題があります:weight
を見ることができません。 weight
をパブリックにすることもできますが、everyoneはいつでもweight
を変更できます(これはおそらく望んでいないことです)。そのため、次の機能を実行できます。
_class Something
{
int weight;
public int GetWeight() { return weight; }
// and other methods
}
_
これはすでに優れていますが、今では普通の_something.Weight
_の代わりにsomething.GetWeight()
を入力する必要がありますが、これは見苦しいです。
プロパティを使用しても同じことができますが、コードはクリーンなままです。
_class Something
{
public int weight { get; private set; }
// and other methods
}
int w = something.weight // works!
something.weight = x; // doesn't even compile
_
素晴らしいので、プロパティを使用すると、変数アクセスをより細かく制御できます。
もう1つの問題:わかりました。外側のコードでweight
を設定できるようにしたいのですが、その値を制御し、100未満の重みを許可しないようにします。さらに、他の内部変数がありますdensity
はweight
に依存するため、density
が変更されたらすぐにweight
を再計算する必要があります。
これは従来、次の方法で実現されています。
_class Something
{
int weight;
public int SetWeight(int w)
{
if (w < 100)
throw new ArgumentException("weight too small");
weight = w;
RecalculateDensity();
}
// and other methods
}
something.SetWeight(anotherSomething.GetWeight() + 1);
_
しかし、繰り返しますが、重みの設定は複雑な操作であることをクライアントに公開したくありません。意味的には、新しい重みを割り当てることです。したがって、セッターを使用したコードは同じように見えますが、より優れています。
_class Something
{
private int _w;
public int Weight
{
get { return _w; }
set
{
if (value < 100)
throw new ArgumentException("weight too small");
_w = value;
RecalculateDensity();
}
}
// and other methods
}
something.Weight = otherSomething.Weight + 1; // much cleaner, right?
_
ですから、疑いもなく、プロパティは「単なる」構文上の砂糖です。しかし、それはクライアントのコードをより良くします。興味深いことに、プロパティのようなものの必要性は非常に頻繁に発生します。他の言語でGetXXX()やSetXXX()などの関数を見つける頻度を確認できます。
C#では、ほとんどの面倒な作業を行うプロパティが導入されています...
すなわち
public string Name { get; set; }
書き込みへのC#ショートカットです...
private string _name;
public string getName { return _name; }
public void setName(string value) { _name = value; }
基本的に、ゲッターとセッターはカプセル化を支援する手段にすぎません。クラスを作成するとき、おそらく他のクラスに公開して、保存するデータの一部を垣間見ることができるようにするいくつかのクラス変数があります。最初に変数を公開するだけでも受け入れられるように思えるかもしれませんが、長い目で見れば、他のクラスにクラスメンバー変数を直接操作させることを後悔するでしょう。セッターを介してそれらを強制する場合、奇妙な値が発生しないようにロジックを追加できます。また、このクラスを既に操作していることに影響を与えることなく、いつでもそのロジックを変更できます。
すなわち
private string _name;
public string getName { return _name; }
public void setName(string value)
{
//Don't want things setting my Name to null
if (value == null)
{
throw new InvalidInputException();
}
_name = value;
}
実際の使用例でのゲッターセッターの一般的な使用方法は次のとおりです。
public class OrderItem
{
public int Id {get;set;}
public int quantity {get;set;}
public int Price {get;set;}
public int TotalAmount {get {return this.quantity *this.Price;}set;}
}
簡単な例
public class Simple
{
public int Propery { get; set; }
}
私が理解している限り、ゲッターとセッターはカプセル化を改善することです。 C#でそれらについて複雑なことは何もありません。
次のようにonオブジェクトのプロパティを定義します。
int m_colorValue = 0;
public int Color
{
set { m_colorValue = value; }
get { return m_colorValue; }
}
これが最も簡単な使用法です。基本的に内部変数を設定するか、その値を取得します。次のようなプロパティを使用します。
someObject.Color = 222; // sets a color 222
int color = someObject.Color // gets the color of the object
最終的には、次のようにセッターまたはゲッターの値を処理することができます。
public int Color
{
set { m_colorValue = value + 5; }
get { return m_colorValue - 30; }
}
setまたはgetをスキップすると、プロパティは読み取り専用または書き込み専用になります。それは私がものを理解する方法です。
これは、可能な限り最小限のコードを使用したC#のget/setです。 C#3.0+の自動実装プロパティ を取得します。
public class Contact
{
public string Name { get; set; }
}
これは、ゲッターとセッターを持つオブジェクト「Article」の基本的な例です。
public class Article
{
public String title;
public String link;
public String description;
public string getTitle()
{
return title;
}
public void setTitle(string value)
{
title = value;
}
public string getLink()
{
return link;
}
public void setLink(string value)
{
link = value;
}
public string getDescription()
{
return description;
}
public void setDescription(string value)
{
description = value;
}
}
内部的には、ゲッターとセッターは単なるメソッドです。 C#がコンパイルされると、次のようなgetterおよびsetterのメソッドが生成されます。
public int get_MyProperty() { ... }
public void set_MyProperty(int value) { ... }
C#では、簡単な構文を使用してこれらのメソッドを宣言できます。以下の行は、アプリケーションをビルドするときに上記のメソッドにコンパイルされます。
public int MyProperty { get; set; }
または
private int myProperty;
public int MyProperty
{
get { return myProperty; }
set { myProperty = value; } // value is an implicit parameter containing the value being assigned to the property.
}
C#のゲッターとセッターは、コードを単純化するものです。
private string name = "spots";
public string Name
{
get { return name; }
set { name = value; }
}
そしてそれを呼び出します(名前プロパティを持つ人物objがあると仮定します):
Console.WriteLine(Person.Name); //prints "spots"
Person.Name = "stops";
Console.Writeline(Person.Name); //prints "stops"
これにより、コードが簡素化されます。 Javaでは、プロパティのGet()とSet()の2つのメソッドが必要になる場合がありますが、C#ではすべて1つの場所で行われます。クラスの開始:
public string foobar {get; set;}
これにより、foobarプロパティのゲッターとセッターが作成されます。それを呼び出すことは、前に示したのと同じ方法です。注意すべき点は、getとsetの両方を含める必要がないことです。プロパティを変更したくない場合は、セットを含めないでください!