C# 言語のゲッターとセッターの概念を理解するのに苦労しています。Objective-C のような言語では、それらはシステムの不可欠な部分のように見えますが、C# ではそうではありません (私が知る限り)。私はすでに本や記事を読んでいるので、私の質問は、C# のゲッターとセッターを理解している人に、完全な初心者に概念を教える場合、どの例を個人的に使用しますか (これには数行のコードが含まれます)可能な限り)?
12 に答える
セッターとゲッターが何であるかを説明するのに少しのコードが役立つと思います。
public class Foo
{
private string bar;
public string GetBar()
{
return bar;
}
public void SetBar(string value)
{
bar = value;
}
}
この例では、barと呼ばれるクラスのプライベートメンバーがあります。GetBarメソッドとSetBarメソッドは、名前が正確に実行されます。一方はバーメンバーを取得し、もう一方はその値を設定します。
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では、プロパティのgetまたはset部分を省略できます。
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の値を読み取ることができます。
私の説明は次のとおりです。(それほど短くはないですが、とてもシンプルです。)
変数を持つクラスを想像してください。
class Something
{
int weight;
// and other methods, of course, not shown here
}
さて、このクラスには小さな問題がありweight
ます。weight
公開することはできますが、そうすると、誰もがいつでも を変更できるようになります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; }
基本的に、ゲッターとセッターはカプセル化を支援する手段にすぎません。クラスを作成すると、いくつかのクラス変数があり、それらを他のクラスに公開して、保存したデータの一部を垣間見ることができるようにすることができます。最初は変数を public にするだけでも問題ないように思えるかもしれませんが、長い目で見れば、他のクラスに自分のクラスのメンバー変数を直接操作させてしまったことを後悔することになるでしょう。セッターを介して強制的に実行する場合は、ロジックを追加して、奇妙な値が発生しないようにすることができます。また、このクラスを既に操作しているものに影響を与えることなく、将来いつでもそのロジックを変更できます。
すなわち
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 Simple
{
public int Propery { get; set; }
}
私が理解している限り、ゲッターとセッターはカプセル化を改善するためのものです。C# では複雑なことは何もありません。
オブジェクトのプロパティを次のように定義します。
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#のゲッターとセッターはコードを単純化するものです。
private string name = "spots";
public string Name
{
get { return name; }
set { name = value; }
}
そしてそれを呼び出します(nameプロパティを持つperson 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の両方を含める必要がないということです。プロパティを変更したくない場合は、setを含めないでください。
内部的には、ゲッターとセッターは単なるメソッドです。C# がコンパイルされると、次のようなゲッターとセッターのメソッドが生成されます。
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.
}
これは、getter と setter を持つオブジェクト「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;
}
}