主にプログラミングに関して。Python, .NET Framework(C#), JavaScript, その他いくらか。
記事にあるサンプルやコードは要検証。使用に際しては責任を負いかねます

スポンサーサイト

                
tags:
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

C#: クロージャ

                
C#でクロージャを書いた覚えがなかった。書いたコードをのせておく。

デリゲートを学びつつ。
http://csharp.keicode.com/basic/delegates-multicast.php
http://csharp.keicode.com/basic/delegates-generic-delegates.php

匿名メソッドを学びつつ。
http://www.atmarkit.co.jp/fdotnet/csharp20/csharp20_05/csharp20_05_01.html
http://stackoverflow.com/questions/2226510/closures-in-c-sharp-event-handler-delegates

はじめてクロージャを知ったのはJavaScriptのオライリー本。そこでは以下に似た例が一つポツンと書かれていて、おもしろいでしょと書いてあるだけだった。Pythonでクロージャを調べてもよく似た例にぶち当たったため、クロージャの概念を勘違いしていた。ある関数の実行によって関数への参照を返されたとき、返された関数をクロージャと呼ぶと思っていた。
function outer(hoge1)
{
function inner(hoge2)
{
var str = hoge1 + hoge2;
return str;
}
return inner;
}


クロージャとは、関数オブジェクトの一種で、変数を自分の定義の外にあるスコープ内をも参照して解決するものだ。まず↑と同様のやり方でクロージャを定義するものを書いてみる。でも関数のなかに関数を入れて、実行によって中の関数への参照を返すって少しややこしい。このあとでは別のやり方をする。
using System;

namespace CsClosure
{
class Program
{
delegate void MyAction();

static MyAction CreateClosure(string message)
{
return () =>
{
Console.WriteLine(message);
};
}

static void ConsoleWriter(string message)
{
Console.WriteLine(message);
}

public static void Main(string[] args)
{
// TODO: Implement Functionality Here
string str = "I am lambda";

// メソッドをデリゲートにする
Action<string> MyDelegate1 = ConsoleWriter;
MyDelegate1("I am delegate");

// ラムダ式を使ったデリゲート
Action MyDelegate2 = () =>
{
Console.WriteLine("I am delegate");
Console.WriteLine(str);
};
MyDelegate2();

// クロージャ作成
MyAction Clsr1 = CreateClosure("I am closure");
Clsr1();

// ラムダ式でのクロージャ作成
Func<string, Action> D2 = (innerString) =>
{
return () =>
{
Console.WriteLine("I am closure");
Console.WriteLine(innerString);
};
};
Action Clsr2 = D2(str);
Clsr2();

Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);
}
}
}


ここでは匿名関数を使うことで、ちょっとシンプルにクロージャを作る。ループなど処理が進むことで値が変わる変数をクロージャ内で使いたければ、そのコピーを作っておく。
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;

namespace CsClosureWithWPF
{
public class MyWindow : Window
{

public MyWindow()
{
Width = 300;
Height = 300;

StackPanel stackPanel = new StackPanel();
Content = stackPanel;

for (var x=0; x<6; x++)
{
Button button = new Button();
button.Content = "button" + x.ToString();
button.Height = 23;

// Func<string, Action<object, RoutedEventArgs>> D = (innerString) =>
// {
// return (Object sender, RoutedEventArgs e) =>
// {
// Console.WriteLine(innerString);
// };
// };
// Action<object, RoutedEventArgs> Clsr = D(x.ToString());
// button.Click += new RoutedEventArgs(Clsr);

var xClone = x;
button.Click += delegate(Object sender, RoutedEventArgs e)
{
var innerString = xClone.ToString();
Console.WriteLine(innerString);
};

stackPanel.Children.Add(button);
}


}

void button1_Click(object sender, RoutedEventArgs e)
{

}

[STAThread]
public static void Main()
{
Application app = new Application();
app.Run(new MyWindow());
}
}
}

WPFの参考
http://www.tbiro.com/Hello-WPF-Without-XAML.htm
            

コメントの投稿

非公開コメント

プロフィール

hMatoba

Author:hMatoba
Github

最新記事
リンク
作ったものなど
月別アーカイブ
カテゴリ
タグリスト

検索フォーム
Amazon
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。