プロパティとメソッドの選択
一般に、メソッドはアクションを表し、プロパティはデータを表します。プロパティはフィールドのように使用されます。つまり、プロパティは計算上複雑であったり、副作用が発生したりしないようにする必要があります。次のガイドラインに違反しない場合は、メソッドではなくプロパティの使用を検討してください。経験の浅い開発者は、プロパティの方が使いやすいと考えるからです。
プロパティを使用するケース
- 型が論理属性(bool)を表す場合は、プロパティの使用を検討してください。
- プロパティの値がプロセスメモリに格納され、プロパティが値へのアクセスのみを提供する場合は、メソッドではなくプロパティを使用してください。
次のサンプルはメソッドですが、プロパティにすべきです。
ケース1
private int hp;
private int mp;
public int GetHp()
{
return hp;
}
public void SetHp(int value)
{
hp = value;
}
public int GetMp()
{
return mp;
}
public void SetMp(int value)
{
mp = value;
}
ケース2
private int hp;
private int mp;
public void SetHp(int hp)
{
this.hp = hp;
}
public void SetMp(int mp)
{
this.mp = mp;
}
プロパティに変更
展開したコード
class Player
{
private int hp;
private int mp;
public int Hp
{
get
{
return hp;
}
set
{
hp = value;
}
}
public int Mp
{
get
{
return mp;
}
set
{
mp = value;
}
}
}
短縮したコード
class Player
{
private int hp;
private int mp;
public int Hp { get => hp; set => hp = value; }
public int Mp { get => mp; set => mp = value; }
}
自動プロパティ(C#6からこのように省略可能)
class Player
{
public int Hp { get; set; }
public int Mp { get; set; }
}
自動プロパティ(コンパイラ内部での処理)
自動プロパティは、プログラマにはシンプルに扱えて便利ですね
ただ、内部での処理は次のようになっていて、人の代わりにメンバーを追加しています
なお、この補完されたメンバー(<Hp>__BackingFieldなど)は、人が参照することはできません
internal class Player
{
// [コンパイラが作成]
private int <Hp>k__BackingField;
// [コンパイラが作成]
private int <Mp>k__BackingField;
public int Hp
{
// [コンパイラが作成]
get
{
return <Hp>k__BackingField;
}
// [コンパイラが作成]
set
{
<Hp>k__BackingField = value;
}
}
public int Mp
{
// [コンパイラが作成]
get
{
return <Mp>k__BackingField;
}
// [コンパイラが作成]
set
{
<Mp>k__BackingField = value;
}
}
}
メソッドを使用するケース
プロパティはフィールドよりも桁違いに低速です。スレッドのブロックを回避するために非同期バージョンの操作を提供することを検討している場合でも、プロパティとは遅すぎる可能性があります。特に、ネットワークやファイルシステムにアクセスする操作(初期化のために1回以外)は、プロパティではなくメソッドにすべきです。
引数から計算して結果を返す場合
キロメートルをメートルに変換するサンプルなど
public int KiloMeterToMeter(int meter)
{
return meter * 1000;
}
呼び出されるたびに値が変わる
呼び出されるたびに異なる結果を返す場合は、メソッドの方がいいです
int hpCount;
public int Count()
{
return hpCount++;
}
型が配列型
参照型の場合、読み込み専用にしていても、値を変更できてしまいます
そのような場合、次のようにメソッドで読み出すようにします
int[] hpCount = new int[] { 1, 2, 3, 4, 5 };
public int[] Count()
{
return hpCount;
}
ちなみにプロパティの場合、次のようになります
int[] hpCount = new int[] { 1, 2, 3, 4, 5 };
public int[] Count
{
get
{
return hpCount;
}
}
読み出すサンプルは次のようになります
ここで着目してもらいたいのが、読み取りオンリーを期待したのに、書き換えができてしまうところです
myClass.Count[3] = 3;がエラーになりません
なので、このような場合、思わぬ挙動になりますので、メソッドで実装する方がいいです
using System;
namespace Property_Array
{
class Program
{
static void Main(string[] args)
{
MyClass myClass = new();
myClass.Count[3] = 3;
foreach (var item in myClass.Count)
{
Console.WriteLine(item);
}
}
}
class MyClass
{
int[] hpCount = new int[] { 1, 2, 3, 4, 5 };
public int[] Count
{
get
{
return hpCount;
}
}
}
}
実行結果
1
2
3
3
5
Press any key to continue...
ディスカッション
コメント一覧
まだ、コメントがありません