2014年11月12日

C#でn日後を返す関数を返す関数を定義する

   このエントリーをはてなブックマークに追加 Clip to Evernote
どう書く?orgに感謝を込めて」シリーズ その48

■問題 (出題者: にしお さん)
整数nを渡すと「日時のデータを受け取って、n日後の日時を返す関数」を返す関数を作ってください。 関数を返す関数が作れない場合は、関数の代わりになるようなオブジェクトでも構いません。
出題の意図としては「関数を返す関数」と「日時の差分の扱い方」を、それぞれ単体だと簡単すぎるので合わせ技にしてみた、というところです。

「n日後を返す関数」ではなくて、「n日後を返す関数」を返す関数 を定義せよ、という問題です。

C#では、デリゲートを返すメソッドを定義すれば良いということですね。
GetFuncNDaysLater というメソッドを定義し、その戻り値を Func<DateTime, DateTime> デリゲートとしました。
ラムダ式便利ですね。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Doukaku.Org {
    class Program {
        static void Main(string[] args) {
            var FiveDaysLater = GetFuncNDaysLater(5);
            Console.WriteLine("{0:d}", FiveDaysLater(DateTime.Today));
            Console.WriteLine("{0:d}", FiveDaysLater(new DateTime(2014, 12, 27)));
            Console.WriteLine("{0:d}", FiveDaysLater(new DateTime(2038, 1, 30)));
            Console.ReadLine();

        }

        // 「日付を受け取り日付を返す関数」が戻り値なので、
        // 戻り値は、Func<DateTime, DateTime> ですね。
        // ラムダ式は、デリゲートに変換できるので、ラムダ式を返せばよい。
        static Func<DateTime, DateTime> GetFuncNDaysLater(int n) {
            return (DateTime dt) => { return dt.AddDays(n); };
        }

    }
}

  

Posted by gushwell at 23:00Comments(0)TrackBack(0)

2007年08月17日

C#3.0:ラムダ式

   このエントリーをはてなブックマークに追加 Clip to Evernote
ラムダ式

delegate int MyFunction(int i);

static int Triple(int n) {
return n * 3;
}

static void Test() {
// C#1.1
MyFunction f = new MyFunction(Triple);
int n = f(11);
Console.WriteLine(n);
}

このコードは、delegateの動きを説明した C#1.1のコード。

これが、C#2.0になると、こんな書き方になる。

delegate int MyFunction(int i);

static void Test() {
// C#2.0 匿名メソッド
MyFunction f3 = delegate(int x) { return x * 3; };
n = f3(20);
Console.WriteLine(n);
}

わざわざ Tripleというメソッドを定義する必要がなくなったわけだ。

そして、C#3.0では、

delegate int MyFunction(int i);

static void Ramda() {
// C#3.0 ラムダ式
MyFunction f4 = (int x) => { return x * 3; }; // (*)
n = f4(30);
Console.WriteLine(n);
}

ここまでは、C#2.0 と C#3.0 では、記述方法が変化しただけと見ることもできる。
さらに、

    MyFunction f4 = (int x) => return x * 3;    // (*)

と書ける。さらに、この(*)の記述が、

    MyFunction f4 = (int x) => x * 3;

    MyFunction f4 = (x) => x * 3;

    MyFunction f4 = x => x * 3;

と短くすることができる。

いきなり、最後の文を見せられたときは、いきなり出てきた xって何だ?
と面食らったけど、順番に見ていけば、それほど難しくはない。
でも、慣れるのが大変そう。
  
Posted by gushwell at 20:54Comments(0)TrackBack(2)

2007年08月13日

Control.Invokeの書き方

   このエントリーをはてなブックマークに追加 Clip to Evernote
Control.Invokeの書き方について、ちょっと考察。

private delegate void MyDelegate();

private void MyDisplay() {
label1.Text = "ほにゃらら";
}

private void Foo(...) {
this.Invoke(new MyDelegate(MyDisplay));
}

これが、C#1.1の頃の書き方。

これが C#2.0になると、

private delegate void MyDelegate();

private void Foo(...) {
this.Invoke(new MyDelegate(delegate {
label1.Text = "ほにゃらら";
}));
}

と書ける。さらに、 MethodInvoker という delegateが定義済みなので、

private void Foo(...)  {
this.Invoke(new MethodInvoker(delegate {
label1.Text = "ほにゃらら";
}));
}

とさらに簡単になる。
しかし、次の書き方がどうしてOKなのかが、はっきりとは分からない。

private void Foo(...)  {
this.Invoke((MethodInvoker)delegate {
label1.Text = "ほにゃらら";
});
}

たぶん、

button1.Click += new EventHandler(button1_Click);

が、
button1.Click += button1_Click;

って書けるのと関係しているんだと思うけど...
誰か教えてくれないかな。

...
そんなことより、

private void Foo(...)  {
this.Invoke(delegate {
label1.Text = "ほにゃらら";
});
}

で良いと思うんだけど。これだとエラーになってしまう。
  
Posted by gushwell at 21:17Comments(0)TrackBack(1)