- PR -

特集「私がJavaからC#に乗り換えた10の理由」について

投稿者投稿内容
英-Ran
ベテラン
会議室デビュー日: 2002/06/12
投稿数: 55
投稿日時: 2003-07-16 21:11
引用:

一郎さんの書き込み (2003-07-16 10:44) より:
コード:

c1.SampleEvent1 += new SampleEvent1Handler(m.listenClass2SampleEvent2);
c2.SampleEvent2 += new SampleEvent2Handler(m.listenClass1SampleEvent1);


はできますよね。



ご明察。C#のドキュメントにはきちんと書いてありますが、delegateで定義したオブジェクトは単なる「メソッド参照のラッパーオブジェクト」で、実体は「target.handler」の方です。型が付いているように見えるのはみかけだけです。

引用:
そう考えていくと、メソッドに明確な型を持たせるというのも面白いかもしれませんね。



そろそろ、Javaの無名InnerClassの設計がいかによく考えられたものであるかということに気付きませんか?

引用:

>英-Ranさん
私は、基本的にはyaさんと同じ意見ですが、お二人が全く異なる事を言っている訳では無いと私は思います。
「delegate」を型の視点で整理してみると良いと思います。
メソッドは、型付けしないと、殆ど有効には利用出来ないと私は思います。



objectさんは、無名InnerClassだけでなく、C#のdelegateもきちんと理解できていないと思われますので、そのような発言は慎んだほうがよろしいかと思います。

[ メッセージ編集済み 編集者: 英-Ran 編集日時 2003-07-16 21:12 ]
object
ぬし
会議室デビュー日: 2002/03/20
投稿数: 338
お住まい・勤務地: 香川県高松市
投稿日時: 2003-07-16 21:34
引用:

英-Ranさんの書き込み (2003-07-16 21:11) より:
objectさんは、無名InnerClassだけでなく、C#のdelegateもきちんと理解できていないと思われますので、そのような発言は慎んだほうがよろしいかと思います。

英-Ranさん、それでは、私も今後の為に、「delegate」をきちんと理解したいと思いますので、分かり易くご教授をお願いします。
楽しみにしております。
お犬様
ベテラン
会議室デビュー日: 2003/01/26
投稿数: 67
投稿日時: 2003-07-16 22:38
引用:
ほむらさんの書き込み (2003-07-16 12:39) より:

そして、この関数のポインタ的要素がバグの発生源であり保守性の低下につながることとしてJavaには採用されていないのだと思います。

これは違うかもしれません。使用用途が違いますが Java にもリフレクションのために使用する java.lang.reflect.Method がありますし、これをオブジェクトへの参照と組み合わせて使えば機能的には delegate と似たような事をする事も可能です。(コンパイル時の型検査が甘くなるか、コンパイル時の型検査をするために結構な量のコードを追加するかしないといけないので普通はしませんが)

引用:
Kuolemaさんの書き込み (2003-07-16 15:02) より:

(廃止しないで非常口を残すのがC#流?、廃止してしまうのがJava流?)

既存の文法を廃止してまで制限を強化する、という流儀は Java にも無いと思います。既存の文法で廃止されたのは(公式にはバグ扱いになってるらしい) private protected ぐらいでしょうか?
mei
大ベテラン
会議室デビュー日: 2003/04/08
投稿数: 114
投稿日時: 2003-07-16 23:45
inner class vs delegateな話がちょっと出ていますが、
J++の頃にも色々な議論があったので、参考になるのではないでしょうか?

http://java-house.jp/ml/archive/j-h-b/020252.html

delegate自体は、ラッパークラス作成マクロみたいなもので、
コンパイラがチェックしてくれる分、楽だという面と、
わざわざ言語の一部で取り込むようなものだろうか?という面がありますね。

C#は哲学で言うところのプラグマティズム(実用主義)って感じなのかな?
お犬様
ベテラン
会議室デビュー日: 2003/01/26
投稿数: 67
投稿日時: 2003-07-16 23:52
記事へのツッコミです。

- 理由06 - interface

個人的に尾島氏が挙げている例は間が抜けていると思われます。「嘆かわしい」というほどコンパイル時の型検査が必要なら
public class MyClass implements Comparable{
 // このメソッドは Comparable とは関係ない。
 public int compareToMyClass(MyClass myClass) { /* 比較するコードは省略 */ }
 public int compareTo(Object obj) {
  return compareToMyClass((MyClass)obj);
 }
}
とでもすれば良いと思うんですが。上記の例でも尾島氏の例でも Comparable や IComparable としてはコンパイル時の型検査ができていないという意味では同等ですし。


- 理由08 - #if

デバッグ用途限定という事であれば J2SE 1.4 から assert が使えるようになっていますね。

[ メッセージ編集済み 編集者: お犬様 編集日時 2003-07-17 00:59 ]
ya
大ベテラン
会議室デビュー日: 2002/05/03
投稿数: 212
投稿日時: 2003-07-17 00:00
ども、突っ込み感謝です。

引用:

「delegate」を型の視点で整理してみると良いと思います。




確かにそうですね。型を考えると説明しやすいかも。
つまり、delegateというのは以前に書いたとおりclassやstructと同等レベルの「型」という概念を持ち、型システムに組み込まれているものなんです。そしてシステム固定ではなく(つまりvoid Method()とかみたいな型があらかじめ決められてそれが固定的に割り当てられるのではなく)、自分で定義でき、拡張可能なんです(それもオブジェクト指向的に)。
そして、型システムに組み込まれることによって.NETにおける強力な型システムの機能を利用する事ができます。

コード:

namespace Samples1
{
//NameSpace付加
public delegate MyNameSpaceDelegate();

//Custom Attribute(delegateとは関係ないコード)
[AttributeUsage(AttributeTagets.Delegate, false)]
public class MyCustomAttribute : Attribute
{
private string creatorName;
public string CreatorName
{
get
{
return creatorName;
}
}
public MyCustomAttribute(string creatorName)
{
this.creatorName = creatorName;
}
}

public class Sample1
{
//型参照のアクセス権設定
protected delegate void MyProtectedDelegate();

//Attributeの付加
[MyCustom("ya")]
public delegate void MyAddAttributeDelegate();

//動的型判定
public void InvokeMyAddAttributeDelegate(Delegate d)
{
if(d is MyAddAttributeDelegate)
{
MyAddAttributeDelegate md = (MyAddAttributeDelegate)d;
md();//md.Invoke(new object[0]{});かも
}
else
{
throw new InvalidArgumentException();
}
}
}
}




上のコードは.NETの型システムの機能の一部です。他にも所属アセンブリの取得とか数え上げればきりがないので、その辺は省略させていただきますが。
では、delegateオブジェクトとは具体的になんなのか。大雑把に言ってdelegateオブジェクトというのは自分から型情報が参照できるメソッドを委譲するための新規オブジェクト、とでも言えばいいのかもしれません。委譲するために新規にそれを意味するオブジェクトを作ってそれを渡す(つまりイベント登録等)わけです。delegate型は内部状態に「どのメソッドを呼び出せばよいか」を持っていて通知によりそれを呼び出す(リダイレクトする)オブジェクトであってけっして「そのメソッドそのもの」ではないわけです。メソッドに関連付けられてはいますが、それぞれ独立です。
ただ、ここでもう一つの議論があるんです。つまり、「そのオブジェクトはクラスとして作ることはできないか」ということです。結論から言えば現在の.NETのclassでは普通の方法ではできません(と思います)。根拠の一つとしてアクセス権の問題を挙げたいと思います。
委譲を考えてみると、委譲する段階でアクセス権チェックが本来できればよい(つまり委譲するものがそのメソッドへの参照を許可されていれば委譲してよい)わけで呼び出されるときにアクセス権チェックなんて要らないわけです。クラスのメソッドは呼び出すときのアクセス権チェックなわけでメソッドでは実現できません。
これはまさしくdelegate型で、その例は私の前回のコードを参照してみてください。ちなみに「チェックがなくなる」なんていうと「カプセル化が壊れるんじゃ…」って思う人がいるかもしれませんが、逆です。publicにしなくてもよくなるので逆に強くカプセル化できます。


さて、色々と反論を。
>>一郎さん
型に拡張したことによって、例えばAttributeをつけることができます。これは重要な事でそれらをクラス作成者が宣言できるということが大きいのです(それはこのイベントを実装したものがこのdelegateのみを参照してこれによって縛られている事のみを考慮して作ればよいということです)。
ちなみにメソッドの型付けですが、「〜アセンブリの〜クラスに所属している〜メソッド」というように型(?)だけなら既にあります。メソッドを書いた時点でそれが定義ですし。で、問題はパラメータと戻り値が同じならば人間は共通点を見つけるわけで、これはオブジェクト指向的に言うと同じ型から派生したものだと考える事ができるわけですが、しかしC#にはそれはない(delegateとは別物)。これはそれが型の発散を招く(つまり望ましくない)からだと思うのですが。
ちなみに型としてくくらなくても(めんどくさいですが)ダイナミック型システムで解析して同じように扱う事は可能です(それで十分かなと)。

>>ほむらさん
関数ポインタとつかい方及び動作がそっくりなので関数ポインタと説明すると楽なんですが、根本的に(概念は)「違うもの」です。関数ポインタは関数への参照そのものですが、delegateは関数への通知(リダイレクト)を実現するオブジェクト指向に乗っ取った型を持った(定義できる)オブジェクトです。C++で実現するならclassを使い、関数ポインタはそのオブジェクトの中でのみ使用されるものとなります。


では、突っ込みよろしくお願いします。

[ メッセージ編集済み 編集者: ya 編集日時 2003-07-17 01:06 ]
英-Ran
ベテラン
会議室デビュー日: 2002/06/12
投稿数: 55
投稿日時: 2003-07-17 08:56
引用:

yaさんの書き込み (2003-07-17 00:00) より:
つまり、delegateというのは以前に書いたとおりclassやstructと同等レベルの「型」という概念を持ち、型システムに組み込まれているものなんです。そしてシステム固定ではなく(つまりvoid Method()とかみたいな型があらかじめ決められてそれが固定的に割り当てられるのではなく)、自分で定義でき、拡張可能なんです(それもオブジェクト指向的に)。



明確に違います。そう思っているのであれば、yaさんはdelegateをまったく理解できていないということです。

【参考】http://java-house.jp/ml/archive/j-h-b/019802.html#body
ぢゃん♪
大ベテラン
会議室デビュー日: 2003/06/12
投稿数: 208
お住まい・勤務地: 都内
投稿日時: 2003-07-17 09:10
ここの議論には一切関わるつもりはなかったのですが、1つだけ疑問があるので、今回だけ。

引用:

英-Ranさんの書き込み (2003-07-17 08:56) より:

【参考】http://java-house.jp/ml/archive/j-h-b/019802.html#body



とありますが、この記述は相当古いうえ、

>Visual J++ 6.0 を動かす環境がないので確認ができないのですが (どなたか
   ……
>されるのではないかと予想します。

と書かれていますけど、この内容は合っているのでしょうか?
また、現在のC#でも、そのまま当てはまっているのでしょうか?

スキルアップ/キャリアアップ(JOB@IT)