Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Delegation in C#

16 views
Skip to first unread message

Yasushi Shinjo

unread,
May 2, 2003, 3:44:05 PM5/2/03
to
新城@筑波大学情報です。こんにちは。

C# に、delegation という考え方があるみたいですが、これはどう
いう意味で使っているのでしょうか。

今までの私の理解では、delegation というのは、継承と対抗する
考え方で、「継承は使わない代りにプロトタイプ・オブジェクトに
メッセージを転送してコードの共有を行う仕組み」です。でも、C#
で出てくるのは、なんか違うみたい。

うちの若いものが、プロトタイプは知らなくて、C# から入ったら
しくて、話が通じなくて困っています。自信たっぷりに「
delegation は、関数へのポインタだ」と説明してはくれるのです
けど。で、内部の動きを追求しても、私の納得いく説明はしてくれ
ないんです。

オブジェクト指向に closure は要らないというと、まあそんな気
はするんだけど、あってもいいような気もするし。

\\ 新城 靖 (しんじょう やすし) \\
\\ 筑波大学 電子・情報       \\

Shinji KONO

unread,
May 2, 2003, 10:56:55 PM5/2/03
to
河野真治 @ 琉球大学情報工学です。

In article <YAS.03Ma...@kirk.is.tsukuba.ac.jp>, y...@is.tsukuba.ac.jp (Yasushi Shinjo) writes


> C# に、delegation という考え方があるみたいですが、これはどう
> いう意味で使っているのでしょうか。

http://www.csharphelp.com/archives/archive259.html

とかかなぁ。
外部イベントに対応するハンドラを登録しておいて、
イベントがくると、ハンドラ(複数)を呼び出す
ってわけなので、普通の言葉だったらcall backっていう
と思う。(勝手な名前つけるのもいいけどさ...)

> オブジェクト指向に closure は要らないというと、まあそんな気
> はするんだけど、あってもいいような気もするし。

call back はclosureにせざるをえないと思いますけど。単なる
データ構造だっていう人はいるかも知れない。Java の無名クラス
みたいなのも便利ですけどね。どうも C# では「がんがんクラス
を作る」っていう方針みたいですね。

---
Shinji KONO @ Information Engineering, University of the Ryukyus,
PRESTO, Japan Science and Technology Corporation
河野真治 @ 琉球大学工学部情報工学科,
科学技術振興事業団さきがけ研究21(機能と構成)

Yasushi Shinjo

unread,
May 3, 2003, 4:04:10 AM5/3/03
to
新城@筑波大学情報です。こんにちは。

In article <3988294...@insigna.ie.u-ryukyu.ac.jp>
ko...@ie.u-ryukyu.ac.jp (Shinji KONO) writes:
> 河野真治 @ 琉球大学情報工学です。


> > C# に、delegation という考え方があるみたいですが、これはどう
> > いう意味で使っているのでしょうか。
> http://www.csharphelp.com/archives/archive259.html
> とかかなぁ。
> 外部イベントに対応するハンドラを登録しておいて、
> イベントがくると、ハンドラ(複数)を呼び出す
> ってわけなので、普通の言葉だったらcall backっていう
> と思う。(勝手な名前つけるのもいいけどさ...)

固有名詞と言えば、そうなんだろうけれど。

「A が B に C を delegate する」とした時に、A, B, C に何が入
るのかが、今一つ納得いかないものがあります。

http://www.csharphelp.com/archives/archive259.html
------------------------------------------------------------
Delegation-Event model : This concept of Delegation-Event
model is very simple wherein a source generates an event and
sends it to all the registered listeners.
------------------------------------------------------------
「A source が listeners に an event を delegates する」とし
ても、a source がもともと自分では何もしないのに他の人に
delegates していいのかという所が引っ掛かるわけです。

Java の Listener は、別に普通だと思うんだけれど。

呼び出される複数のハンドラの順番は、決まっているんでしょうね。
順番で挙動が変るプログラムを書いてはいけないんでしょうね。

> > オブジェクト指向に closure は要らないというと、まあそんな気
> > はするんだけど、あってもいいような気もするし。
> call back はclosureにせざるをえないと思いますけど。

あ、そういえば、C言語の昔の関数のポインタの callback しか食
わないようなライブラリに対して、C言語で closure を使って、
mediator (proxy, wrapper, interposition agent, ...) を作ると
いう話がありました[1]。

> 単なる
> データ構造だっていう人はいるかも知れない。Java の無名クラス
> みたいなのも便利ですけどね。どうも C# では「がんがんクラス
> を作る」っていう方針みたいですね。

Java の無名クラスは、スタック上の変数をアクセス出きるんでし
たっけ。手元のプログラム見ると、ローカル変数に final ついて
いるなあ。なんだ、この final は。動的にコード生成しているん
ですか。

\\ 新城 靖 (しんじょう やすし) \\
\\ 筑波大学 電子・情報       \\

参考文献

[1] Yasushi Shinjo, Toshiyuki Kubo, and Calton Pu:
"Efficient Mediators through Dynamic Code Generation: a
Method and an Experiment", The Eighteenth Annual ACM
Symposium on Applied Computing (SAC 2003), pp.1147-1154
(March 9, 2003).

MAEDA Atusi

unread,
May 4, 2003, 3:19:19 PM5/4/03
to
y...@is.tsukuba.ac.jp (Yasushi Shinjo) writes:

> > > C# に、delegation という考え方があるみたいですが、これはどう
> > > いう意味で使っているのでしょうか。
> > http://www.csharphelp.com/archives/archive259.html
> > とかかなぁ。

「関数へのポインタ」ということだったら,たぶんdelegationじゃなくて
delegateの事ではないでしょうか.
http://www.csharphelp.com/archives2/archive408.html

public delegate bool comparator(Object, Object);
public static Object[] sort(comparator comp, Object[] array) {
...if (comp(array[i], array[j])) ...
}
みたいな感じで使います.上でcomparatorの型はSystem.Delegateという特別
なクラスのサブクラスになります.

Delegateは,要するにJavaのjava.lang.reflect.Methodクラスのようなもので
すが,
method = MyClass.class.getMethod("compare", MyClass.class, MyClass.class);
boolean result = ((Boolean)method.invoke(obj, new Object[]{arg1, arg2})).booleanValue();
のかわりに
comp = new comparator(obj.compareTo);
bool result = comp(arg1, arg2);
とか,
comp = new comparator(MyClass.compare);
bool result = comp(arg1, arg2);
みたいに書けます.たぶん,素直に実装するとコードの効率も良いでしょう.
(wrapperクラスとの変換が不要・引数の数や型のチェックはコンパイル時にで
きる.)

# もちろん,ふつうにJavaでやるときはMethodオブジェクトなんか使わず,
# interface Comparable { boolean compareTo(Object arg); }
# とか
# interface Comparator { boolean compare(Object arg1, Object arg2); }
# やるわけで,Delegateと効率はほぼ同等になるわけですが…

なんでこれがdelegateと呼ばれるのかは私もよく分かりません.J++の頃から
あったMicrosoft式の呼び方です.Delegation Event Modelとは(関連はあるも
のの) いちおう別の概念です.MicrosoftはJavaにこの独自拡張を加え,(Win
APIを呼び出すにはC++式のメソッドへのポインタが便利だったから?)「この方
がJavaのevent処理よりもエレガントで効率が良いのだ」と主張していました.

C#ではイベントハンドラーとしてXxxListenerとかのインターフェースオブジェ
クトを渡すのではなくDelegateオブジェクトを渡す流儀になっているようです.
イベントのマルチキャストなんかは,Javaだと特に言語を拡張しなくてもでき
る(AWTEventMulticasterインターフェースとか)わけですが,C#では
public delegate MyDelegate ...;
delegate1 = new MyDelegate(method1) + new MyDelegate(method2);
delegate1 += new MyDelegate(method3);
などとやります.これはいちおう,
delegate1 = (MyDelegate)System.Delegate.Combine(new MyDelegate(method1), new MyDelegate(method2));
delegate1 = (MyDelegate)System.Delegate.Combine(delegate1, new MyDelegate(method3));
の構文糖ということになっていますが,型チェックをコンパイル時に済ますで
あろうことを考えると,言語自体の拡張と考えるべきでしょう.Combineの戻
り値の型はSystem.MulticastDelegateクラスのサブクラスだそうです.

記述次第で色んな機能が実現できるなるべくシンプルな言語を作っておくとい
うポリシーではなくて,プログラムを書くのに便利そうなら,どんどん言語を
拡張しようというポリシーの現れでしょうね.setterやgetterを自動的に定義
するpropertyという予約語も同じような発想です.

前田敦司

MAEDA Atusi

unread,
May 4, 2003, 3:39:55 PM5/4/03
to
y...@is.tsukuba.ac.jp (Yasushi Shinjo) writes:

> Java の無名クラスは、スタック上の変数をアクセス出きるんでし
> たっけ。手元のプログラム見ると、ローカル変数に final ついて
> いるなあ。なんだ、この final は。動的にコード生成しているん
> ですか。

Javaに無名クラスやインナークラスを入れた時には,VMの仕様を拡張せずに実
現できるようにしました.そのため,JavaのVMの仕様としては,グローバルな
クラス定義しかない時代と同じままです.スタック上の自由変数を参照したり
はできません.
class MyClass {
...
void method1(final int x) {
ActionListener a = new ActionListener() {
public void actionPerformed(ActionEvent e) {
... xへの参照 ...
};
...
}
}
というコードは,
class MyClass$1 implements ActionListener {
private int x_copy;
MyClass$1(int x) { x_copy = x }
public void actionPerformed(ActionEvent e) {
... x_copyへの参照 ...
}
}
class MyClass {
...
void method1(final int x) {
ActionListener a = new MyClass$1(x);
...
}
}
のように変換されます.aを作ってからxの値を書き換えてもx_copyには反映さ
れなくて困るので,xを書き換えられないように制限がついています.xが
finalでないとコンパイラがエラーを出します.(定数の値が分かっている時に
は,コンストラクタの引数を追加せずに,xへの参照を定数で置き換えてしま
うこともあります.)

前田敦司

MAEDA Atusi

unread,
May 4, 2003, 3:38:23 PM5/4/03
to
y...@is.tsukuba.ac.jp (Yasushi Shinjo) writes:

> > > C# に、delegation という考え方があるみたいですが、これはどう
> > > いう意味で使っているのでしょうか。
> > http://www.csharphelp.com/archives/archive259.html
> > とかかなぁ。

「関数へのポインタ」ということだったら,たぶんdelegationじゃなくて
delegateの事ではないでしょうか.
http://www.csharphelp.com/archives2/archive408.html

public delegate bool comparator(Object, Object);
public static Object[] sort(comparator comp, Object[] array) {
...if (comp(array[i], array[j])) ...
}
みたいな感じで使います.上でcomparatorの型はSystem.Delegateという特別
なクラスのサブクラスになります.

Delegateは,要するにJavaのjava.lang.reflect.Methodクラスのようなもので
すが,
method = MyClass.class.getMethod("compare", new Class[]{MyClass.class, MyClass.class});

Yasushi Shinjo

unread,
May 5, 2003, 6:20:11 AM5/5/03
to
新城@筑波大学情報です。こんにちは。

In article <m3issq3...@maedapc.cc.tsukuba.ac.jp>
MAEDA Atusi <ma...@cc.tsukuba.ac.jp> writes:
> 「関数へのポインタ」ということだったら,たぶんdelegationじゃなくて
> delegateの事ではないでしょうか.

なるほど。delegation (委譲)と delegate は違うわけね。
delegate (Microsoft用語)に、いい訳語はないんですか。

最近の学生さんは、delegation (委譲) を知らないみたいです。参
考資料としては、何がいいでしょうか。次の論文はちょっと古いか
も。今使える言語処理系があるといいのだけれど。

H.Lieberman: "Using Prototypical Objects to Implement Shared
Behavior in Object Oritented Systems", OOPSLA'86, pp.214-223
(1986).

> なんでこれがdelegateと呼ばれるのかは私もよく分かりません.J++の頃から
> あったMicrosoft式の呼び方です.Delegation Event Modelとは(関連はあるも
> のの) いちおう別の概念です.MicrosoftはJavaにこの独自拡張を加え,(Win
> APIを呼び出すにはC++式のメソッドへのポインタが便利だったから?)「この方
> がJavaのevent処理よりもエレガントで効率が良いのだ」と主張していました.

裁判で揉めていたのは、この辺りなんですかね。

> public delegate MyDelegate ...;
> delegate1 = new MyDelegate(method1) + new MyDelegate(method2);
> delegate1 += new MyDelegate(method3);
> などとやります.これはいちおう,
> delegate1 = (MyDelegate)System.Delegate.Combine(new MyDelegate(method1), new MyDelegate(method2));
> delegate1 = (MyDelegate)System.Delegate.Combine(delegate1, new MyDelegate(method3));
> の構文糖ということになっていますが,型チェックをコンパイル時に済ますで
> あろうことを考えると,言語自体の拡張と考えるべきでしょう.Combineの戻
> り値の型はSystem.MulticastDelegateクラスのサブクラスだそうです.

なるほど。よくわかりました。

Combine は、イベントのマルチキャストなんかより(それも含んで
いるかもしれないけれど)、Aspect Oriented な記述に適している
ような気がするのですが、それもできるんですか。

Emacs Lisp だと、add-hook みたいに使うわけです。

Yasushi Shinjo

unread,
May 5, 2003, 6:29:34 AM5/5/03
to
新城@筑波大学情報です。こんにちは。

In article <m3d6iy33...@maedapc.cc.tsukuba.ac.jp>


MAEDA Atusi <ma...@cc.tsukuba.ac.jp> writes:
> Javaに無名クラスやインナークラスを入れた時には,VMの仕様を拡張せずに実
> 現できるようにしました.そのため,JavaのVMの仕様としては,グローバルな
> クラス定義しかない時代と同じままです.スタック上の自由変数を参照したり
> はできません.

やはり、そうでしたか。動的なコード生成は、していないわけです
ね。gcc のネストした関数定義のようなことは。

いくら Java で GC を入れたといっても、スタックにも変数を保存
しているとなると、簡単には Lisp の closure みたいにはならな
いと。


> class MyClass {
> ...
> void method1(final int x) {
> ActionListener a = new ActionListener() {
> public void actionPerformed(ActionEvent e) {
> ... xへの参照 ...
> };
> ...
> }
> }

...
> xが
> finalでないとコンパイラがエラーを出します.

Java も、けっこう難しいですね。C は、C で難しい (char とか書
いても内部は整数とか)けれど、Java は Java で手ごわいです。な
ぜ final にしないといけないか、GC とかスタックとか VM とか分
からないと説明できないということだとすると。

スレッドが入った段階で、かなり難しくはなっているんだけれど。
(Pthread よりははるかにいいんだけれど、避けて通れないという
意味では難しい。Pthread は、避けようと思ったら避けられます。)

Shinji KONO

unread,
May 5, 2003, 9:08:43 AM5/5/03
to
河野真治 @ 琉球大学情報工学です。

In article <YAS.03Ma...@kirk.is.tsukuba.ac.jp>, y...@is.tsukuba.ac.jp (Yasushi Shinjo) writes

> H.Lieberman: "Using Prototypical Objects to Implement Shared
> Behavior in Object Oritented Systems", OOPSLA'86, pp.214-223
> (1986).

これねぇ.... なんか例題がたこなんで、いまいちぴんとこない感じ。
といっても良い論文を知っているわけでもないんですけど。むしろ、
デザイン・パターンの方がいいと思います。

委譲の良いところは継承と違って特別な言語サポートがいらないと
ころだと思います。共有したコードで、

データ構造が単一ならば継承を用い、
データ構造がコンテキスト依存なら委譲を用いる

って感じですかね。

> Emacs Lisp だと、add-hook みたいに使うわけです。

便利なんだけど、きちゃないし、遅いし... Cのプリプロセッサよ
りはましな気もするけど、だからといって、コンパイラに頼るとわ
けわかになるし...

Yasushi Shinjo

unread,
May 5, 2003, 11:12:37 AM5/5/03
to
新城@筑波大学情報です。こんにちは。

In article <3988305...@insigna.ie.u-ryukyu.ac.jp>


ko...@ie.u-ryukyu.ac.jp (Shinji KONO) writes:
> 河野真治 @ 琉球大学情報工学です。

> 委譲の良いところは継承と違って特別な言語サポートがいらないと
> ころだと思います。共有したコードで、

self のサポートがないと、辛い所はないですかね。つまり、最初
にメッセージを受け取ったオブジェクトにもう一度戻したい時に。
委譲でプログラムを書いた経験はそんなにない(意識的にはない)
ので、実際には self なしで平気かもしれないけれど。

> データ構造が単一ならば継承を用い、
> データ構造がコンテキスト依存なら委譲を用いる
> って感じですかね。

データ構造か。まあ、継承使うからには、内部のデータも見ていい
ということで、いいでしょうね。後者は、has-a。
has-a と委譲は、同じと言えば同じだけど、自動化されていれば
楽だから違うということなんですか。

> > Emacs Lisp だと、add-hook みたいに使うわけです。
> 便利なんだけど、きちゃないし、遅いし... Cのプリプロセッサよ
> りはましな気もするけど、だからといって、コンパイラに頼るとわ
> けわかになるし...

add-hook になると、setq と違って複数のフックがあちこちで書け
る(setq では 1 つしか書けないから、1 つの defun にまとめない
といけない)、というのが元の話でした。

C プリプロセッサで、## や /**/ でトークンをくっつけてなにか
やろうとすると、かなり辛くなります。動的リンカの pre-load は、
かなりいいけど、pre-load がたくさんあった時にはやはり訳が分
からない状態になったりするのでしょう。そんなに大量の
pre-load を見たことはないけれど。

0 new messages