|
|
連載:[完全版]究極のC#プログラミング
Chapter13 自動実装と自動定義
川俣 晶
2010/02/17 |
|
|
13.12 オブジェクト初期化子の使用例
最後に、さるプログラムのために書いたコードを、テーマに沿わない部分を大幅に削除、修正を行ったうえで、リスト13.26として紹介する。あまり良いプログラムだとは思っていないが、オブジェクト初期化子を使うということが何を意味するかが浮き彫りになっていると思うので、掲載することにした。
using System;
using System.Collections.Generic;
using System.Reflection;
// スキルのレベルを整数で保管するクラス
// (このクラスはデータ保存のためシリアライズされる)
public static class Flags
{
public static int スチル撮影;
public static int 動画編集;
}
// 1つの種類のスキルを扱うクラス
public class Skill
{
public readonly string Name;
public readonly string Description;
private readonly Func<int> getter;
private readonly Action<int> setter;
public static implicit operator Skill(SkillTemplate t)
{
return new Skill(t);
}
public Skill(SkillTemplate t)
{
Name = t.Name;
Description = t.Description;
getter = t.getter;
setter = t.setter;
}
}
// スキルを初期化するテンプレート
public class SkillTemplate
{
public string Name;
public string Description;
public Func<int> getter;
public Action<int> setter;
}
// スキルの一覧
public static class Skills
{
public static Skill スチル撮影 = new SkillTemplate()
{
Name = "スチル撮影",
Description = "静止画撮影を行うスキル",
getter = () => Flags.スチル撮影,
setter = (v) => { Flags.スチル撮影 = v; },
};
public static Skill 動画編集 = new SkillTemplate()
{
Name = "動画編集",
Description = "動画データの編集を行うスキル",
getter = () => Flags.動画編集,
setter = (v) => { Flags.動画編集 = v; },
};
public static Skill[] GetSkillList()
{
List<Skill> list = new List<Skill>();
foreach (FieldInfo info in typeof(Skills).GetFields(
BindingFlags.Public | BindingFlags.Static))
{
Skill item = (Skill)info.GetValue(null);
list.Add(item);
}
return list.ToArray();
}
}
|
|
リスト13.26 オブジェクト初期化子の使用例 |
このプログラムは「スチル撮影」といった個人の能力を「スキル」という形でモデル化してオブジェクトに格納している。スキルの具体的な内容はあらかじめ決まっていて不変なので、Skillオブジェクトはreadonlyのフィールドでのみ構成されている(変化するスキルの能力値は別のFlagsクラスに格納している)。
ここで問題になるのは、オブジェクト初期化子はreadonlyのフィールドを初期化できないことである。そこで、Skillクラスとは別に、同等の情報を自由に読み書きできるSkillTemplateクラスを用意し、これを初期化する。そして、SkillTemplateクラスからSkillクラスへの暗黙的な変換(implicit operator Skill)を用意し、
Skill スチル撮影 = new SkillTemplate() { …… };
|
|
という異なる型の代入を可能としている。これにより、SkillTemplateクラスを用意しなければならなかった点を除けば、わりとすっきりとソースコードをまとめることができた*9。
*9 しかし、このやり方に100%満足しているわけではない。もっと良いやり方はないんだろうか? |
【Exercise】練習問題
次のプログラムは、Targetを3回別個の値で初期化している。このプログラムはどのような文字列を出力するか? 正しいものを選べ。
using System;
class V
{
public V(string s)
{
Console.Write(s);
}
}
class A
{
public V Target = new V("グー");
public A()
{
Target = new V("チョキ");
}
}
class Program
{
static void Main(string[] args)
{
A a = new A() { Target = new V("パー") };
}
}
|
|
- グーチョキパー
- チョキグーパー
- チョキパーグー
- チョキパーパー
- グーパーパー
◎解答:「1」(この行をマウスで選択してください)
Insider.NET 記事ランキング
本日
月間