ジェネリックデリゲートってなに?
Actionただし、Action
delegate() { }を
() => { }で置き換えるように使う。
static void Main(string[] args) { // 3人をお供に加える。 Dog dog = new Dog(); Monkey monkey = new Monkey(); Kiji kiji = new Kiji(); // 攻撃の作戦をたてる Action[] attacks = new Action[4]; attacks[0] = dog.Attack; attacks[1] = monkey.Attack; //attacks[2] = delegate() // 匿名メソッドを attacks[2] = () => // ラムダ式で書き換え { //ここで関数を直に定義している。 Console.WriteLine("ここで一休み"); }; attacks[3] = kiji.Attack; // 攻撃する for (int i = 0; i < attacks.Length; i++ ) { attacks[i](); } Console.ReadLine(); }
() => {式} (変数) => {式} 変数 => {式} // ()を省略 変数 => 式 // {}を省略
static void Main(string[] args) { // 3人をお供に加える。 Dog dog = new Dog(); Monkey monkey = new Monkey(); Kiji kiji = new Kiji(); // 攻撃の作戦をたてる //Attack[] attacks = new Attack[3]; Action[] attacks = new Action[4]; attacks[0] = dog.Attack; attacks[1] = monkey.Attack; attacks[2] = delegate() //★匿名メソッド★ { //ここで関数を直に定義している。 Console.WriteLine("ここで一休み"); }; attacks[3] = kiji.Attack; // 攻撃する for (int i = 0; i < attacks.Length; i++ ) { attacks[i](); } Console.ReadLine(); }
delegate void Attack();という宣言が必要とのことだったけど、実は戻り値がvoidのようなデリゲートの関数は、.Net側で準備してあるのでわざわざ宣言しなくてもよいよというような機能。
namespace MomoTaro { class Program { static void Main(string[] args) { // 3人をお供に加える。 Dog dog = new Dog(); Monkey monkey = new Monkey(); Kiji kiji = new Kiji(); // 攻撃の作戦をたてる //Attack[] attacks = new Attack[3]; // 不要になった Action[] attacks = new Action[3]; attacks[0] = dog.Attack; attacks[1] = monkey.Attack; attacks[2] = kiji.Attack; // 攻撃する for (int i = 0; i < attacks.Length; i++ ) { attacks[i](); } Console.ReadLine(); } } // delegate void Attack(); // 不要 class Dog { public void Attack() { Console.WriteLine("BowWow"); } } class Monkey { public void Attack() { Console.WriteLine("ウキー"); } } class Kiji { public void Attack() { Console.WriteLine("ケーン"); } } }
public delegate void Action();と定義されていることがわかる。
delegate void Attack();そうすると、この例でいうとAttackを型として使える。 Attack型にはAttackと引数と戻り値が一致する関数がなんでも代入できる。この例でいうと引数が0で戻り値がvoidのものを代入できる。
class Program { static void Main(string[] args) { // 3人をお供に加える。 Dog dog = new Dog(); Monkey monkey = new Monkey(); Kiji kiji = new Kiji(); // 攻撃の作戦をたてる Attack[] attacks = new Attack[3]; attacks[0] = dog.Attack; attacks[1] = monkey.Attack; attacks[2] = kiji.Attack; // 攻撃する for (int i = 0; i < attacks.Length; i++ ) { attacks[i](); } Console.ReadLine(); } } delegate void Attack(); class Dog { public void Attack() { Console.WriteLine("BowWow"); } } class Monkey { public void Attack() { Console.WriteLine("ウキー"); } } class Kiji { public void Attack() { Console.WriteLine("ケーン"); } }
class Cat { public void Cry() { Console.WriteLine("にゃお~"); } } class CatKing : Cat { public void Cry() { Console.WriteLine("にゃお~猫王だぞ~"); } }そうすると警告はでるが、コンパイルは通る。警告はnewを使用してください。というような内容。
class Program { static void Main(string[] args) { Cat tama = new CatKing(); tama.Cry(); Console.ReadLine(); } } class CatKing : Cat { public new void Cry() { Console.WriteLine("にゃお~猫王だぞ~"); } } class Cat { public void Cry() { Console.WriteLine("にゃお~"); } }結果は「にやお~」になる。
class Program { static void Main(string[] args) { Cat tama = new CatKing(); tama.Cry(); Console.ReadLine(); } } class CatKing : Cat { public override void Cry() { Console.WriteLine("にゃお~猫王だぞ~"); } } class Cat { public virtual void Cry() { Console.WriteLine("にゃお~"); } }結果は「にゃお~猫王だぞ~」になる。
private string myName; public string MyName { get { return myName; } set { myName = value; } }を、こんな感じで省略できるようになったこと。
public string MyName { get; set; }C#コンパイラは、内部的には前者のようなコードを作ってるので、実装者からは見えないけど、プロパティに対応するフィールドが内部的には存在しているとのこと。
class Program { static void Main(string[] args) { cat tama = new cat("タマ"); tama.SayName(); Console.ReadKey(); } } class cat { //読み取り専用フィールド private readonly string name; public cat(string newName) { name = newName; } public void SayName() { //name = "にゃんこ"; // ここを有効にするとコンパイルエラーになる。 Console.WriteLine(name + "です。"); } }・クラスは値でなく参照型なので、代入しても実態は一つ。コピーされない。
cat tama = new cat("タマ"); tama.Age = 3; cat tama2 = tama; // コピーはされない。tama2もtamaも同一。 tama2.Age = 4;とすると、tamaもtama2も4歳になる。
struct position { public position(int x, int y, int z) { m_x = x; m_y = y; m_z = z; } public int m_x; public int m_y; public int m_z; }・なんだけどプロパティをもつ構造体の場合は、また制約があり、こういう風に書くとコンパイルエラーが発生する。デフォルトコンストラクタを呼ぶ前にメソッドを呼び出すとだめという制約がある。
struct position { public position(int x, int y, int z) { X = x; Y = y; Z = z; } public int X { get; set; } public int Y { get; set; } public int Z { get; set; } }で、これに対応する場合はこうすればい。
struct position { public position(int x, int y, int z) :this() // デフォルトコンストラクタを呼ぶ。 { X = x; Y = y; Z = z; } public int X { get; set; } public int Y { get; set; } public int Z { get; set; } }・C#4からは省略可能な引数というのがある。引数の数だけことなるようなオーバーロードをするときの代替として使える。型がちがうオーバーロードの代わりにはならないので、オーバーロードがいらなくなるわけではないと思う。 ・オブジェクト初期化子とは? newするときにプロパティを設定できる機能。コンストラクタとの使い分けが難しそう。。。