MochiuWiki : SUSE, EC, PCB
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
検索
個人用ツール
ログイン
Toggle dark mode
名前空間
ページ
議論
表示
閲覧
ソースを閲覧
履歴を表示
C Sharpの基礎 - プロパティのソースを表示
提供: MochiuWiki : SUSE, EC, PCB
←
C Sharpの基礎 - プロパティ
あなたには「このページの編集」を行う権限がありません。理由は以下の通りです:
この操作は、次のグループのいずれかに属する利用者のみが実行できます:
管理者
、new-group。
このページのソースの閲覧やコピーができます。
== 概要 == プロパティとは、 クラスの外部から見るとメンバ変数のように振る舞い、 クラス内部から見るとメソッドのように振舞うものである。<br> 実装の隠蔽(カプセル化)の原則を崩すことなく、 アクセサ関数の煩雑さを解消するためのものである。<br> <br><br> == アクセサ関数とは == アクセサ関数とは、以下の例のように、void Re(double x)やdouble Re()等のメンバ変数の値の取得・変更を行うためのメソッドのことである。<br> C++やJavaでは、アクセサ関数のメソッド名はvoid SetRe(double x)やdouble GetRe()というように、メンバ変数の数だけアクセサ関数が必要になってしまう。<br> <syntaxhighlight lang="c#"> using System; // 複素数クラス class Complex { // 実装は外部から隠蔽する private double re; // 実部を記憶しておく private double im; // 虚部を記憶しておく public double Re(){return this.re;} // 実部を取り出す public void Re(double x){this.re = x;} // 実部を書き換え public double Im(){return this.im;} // 虚部を取り出す public void Im(double y){this.im = y;} // 虚部を書き換え public double Abs(){return Math.Sqrt(re * re + im * im);} // 絶対値を取り出す } class Sample { static void Main() { // x = 5 + 1i Complex x = new Complex(); x.Re(5); // x.re = 5 x.Im(1); // x.im = 1 // y = -2 + 3i Complex y = new Complex(); y.Re(-2); // y.re = -2 y.Im( 3); // y.im = 3 Complex z = new Complex(); z.Re(x.Re() + y.Re()); // z.re = x.re + y.re z.Im(x.Im() + y.Im()); // z.im = x.im + y.im Console.Write("|{0} + {1}i| = {2}\n", z.Re(), z.Im(), z.Abs()); // |3 + 4i| = 5 と表示される } } </source> <br><br> == プロパティ == アクセサ関数の煩雑さを減らすために、クラス内部から見るとメソッドのように振る舞い、 クラス利用側から見るとメンバ変数のように振舞うプロパティ機能がある。<br> <br> プロパティの定義の仕方は以下のようなシンタックスになる。<br> set移行のブロックに値の変更用の処理を、get移行のに値の取得用の処理を記述する。<br> <syntaxhighlight lang="c#"> アクセスレベル 型名 プロパティ名 { set { // setアクセサ(setterとも言う) // ここに値の変更時の処理を記述する // valueという名前の変数に代入された値が格納される } get { // getアクセサ(getterとも言う) // ここに値の取得時の処理を記述する // メソッドの場合と同様に、値はreturnキーワードを用いて返す } } </source> <br> 例えば、上記の複素数クラスのアクセサをプロパティを使用して書き換えると以下のようになる。<br> <syntaxhighlight lang="c#"> using System; // 複素数クラス class Complex { // 実装は外部から隠蔽(privateにしておく) private double re; // 実部を記憶しておく private double im; // 虚部を記憶しておく // 実部の取得・変更用のプロパティ public double Re { set { this.re = value; } get { return this.re; } } // 虚部の取得・変更用のプロパティ public double Im { set { this.im = value; } get { return this.im; } } // 絶対値の取得用のプロパティ public double Abs { // 読み取り専用プロパティ。 // setブロックを書かない。 get { return Math.Sqrt(re * re + im * im); } } } class Sample { static void Main() { Complex c = new Complex(); c.Re = 4; // Reプロパティのsetアクセサが呼び出される c.Im = 3; // Imプロパティのsetアクセサが呼び出される Console.Write("|{0} + ", c.Re); // Reプロパティのgetアクセサが呼び出される Console.Write("{0}i| =", c.Im); // Imプロパティのgetアクセサが呼び出される Console.Write(" {0}\n", c.Abs); // Absプロパティのgetアクセサが呼び出される } } </source> <br><br> == set / getで異なるアクセスレベルを設定 == ===== set / getで異なるアクセスレベルを設定 ===== C# 2.0から、プロパティのset/getアクセサそれぞれ異なるアクセスレベルを設定できる。 <syntaxhighlight lang="c#"> class A { private int n; public int N { get{ return this.n; } protected set{ this.n = value; } } } </source> <br> ===== 自動プロパティ ===== C# 3.0から、プロパティのget/setの中身の省略ができる。この機能を自動プロパティと呼ぶ。<br> また、コンパイラによって生成されるフィールド(上記の例では、__name)をバックフィールドと呼ぶ。<br> <syntaxhighlight lang="c#"> public string Name { get; set; } </source> <br> 上記の自動プロパティは、コンパイラは下記のように解釈する。<br> <syntaxhighlight lang="c#"> private string __name; public string Name { get { return this.__name; } set { this.__name = value; } } </source> <br> 自動プロパティを使用した複素数の例を記述する。<br> <syntaxhighlight lang="c#"> using System; class Complex { public double Re { get; set; } public double Im { get; set; } public double Abs { get { return Math.Sqrt(Re * Re + Im * Im); } } } </source> <br> ===== get-onlyプロパティ ===== C# 6では、getアクセサだけのプロパティを定義できる。<br> この場合、コンストラクタ内のみ値を代入できる。(以降、書き換え不可になる)<br> <syntaxhighlight lang="c#"> using System; class Complex { public double Re { get; } public double Im { get; } public Complex(double re, double im) { // コンストラクタ内のみ代入可能 Re = re; Im = im; } } </source> <br> 上記のサンプルコードは、以下のような意味になる。(readonlyのバックフィールドが作成される)<br> <syntaxhighlight lang="c#"> using System; class Complex { private readonly double _re; private readonly double _im; public double Re { get { return _re; } } public double Im { get { return _im; } } public Complex(double re, double im) { // コンストラクタ内のみ代入可能 _re = re; _im = im; } } </source> <br> ===== プロパティ初期化子 ===== 同じくC# 6.0から、自動プロパティに対して初期化子を与えることができる。<br> これにより、コンストラクタに記述しなくとも、プロパティに初期値を与えることができる。<br> <syntaxhighlight lang="c#"> class Point { public int X { get; set; } = 10; public int Y { get; set; } = 20; } </source> <br> ===== expression-bodiedなプロパティ ===== get-onlyのプロパティに限られるが、他のいくつかのメンバ関数と同様に、expression-bodied(本体が式の)形式でプロパティを定義できる。<br> 上記の複素数クラスでは、Absプロパティの定義が簡潔に記述できる。<br> <syntaxhighlight lang="c#"> using static System.Math; class Complex { public double Re { get; set; } public double Im { get; set; } public double Abs => Sqrt(Re * Re + Im * Im); } </source> <br><br> == 注意点 == C#には、インデックス付きプロパティは存在しない。<br> C#では、コレクションクラスを返すプロパティが推奨される。<br> <br> また、配列やICollection型を返す場合は、IEnumerable型を返すべきである。<br> <syntaxhighlight lang="c#"> // 配列を返す場合 // コンパイル可能 int[] x; public int[] X { get => x; } // コンパイルエラー //int[] x; //public int X[int i] //{ // get => x[i]; // private set => x[i] = value; //} private List<int> listItems; // Itemsプロパティのフィールド [System.Runtime.CompilerServices.IndexerName("Items")] public int this[int index] // インデクサ { get => listItems[index]; set => listItems[index] = value; } // IEnumerableを返す場合 int[] x; public IEnumerable<int> X { get => { foreach (var item in x) { yield return item; } } } </syntaxhighlight> <br> また、.NET Frameworkは、インデックス付きプロパティを認めている。(VB.NETはインデックス付きプロパティが存在する)<br> C#から呼び出す場合は、get_***というような名前のメソッドを呼び出す。<br> 例えば、VB.NETにてint X[int i]と言う名前でインデックス付きプロパティを定義した場合、 C#からはget_X(0)というように呼び出す。<br> <br> 更に特殊な事情として、COMの場合のみ、X[0]というような呼び出し方法が認められる。<br> 詳しくは、COM相互運用時の特別処理を参照すること。<br> <br><br> __FORCETOC__ [[カテゴリ:C_Sharp]]
C Sharpの基礎 - プロパティ
に戻る。
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
Collapse