C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[8]: IListとList


(過去ログ 44 を表示中)

[トピック内 12 記事 (1 - 12 表示)]  << 0 >>

■23453 / inTopicNo.1)  IListとList
  
□投稿者/ メタボmen (1回)-(2008/08/15(Fri) 12:51:19)

分類:[雑談] 

以下のC#2.0のソースコードで、前者がコンパイルできて後者がコンパイルできないことに納得がいきません。

IList<int> list = new List<int>();
IList<IList<int>> matrix = new List<List<int>>();

わめいても仕方ないんですが...
ここでわめかせてください。 ヽ(`Д´)ノ
引用返信 編集キー/
■23454 / inTopicNo.2)  Re[1]: IListとList
□投稿者/ επιστημη (1244回)-(2008/08/15(Fri) 13:04:40)
επιστημη さんの Web サイト
> IList<IList<int>> matrix = new List<List<int>>();
> わめいても仕方ないんですが...
> ここでわめかせてください。 ヽ(`Д´)ノ

ほげ<X> と ほげ<Y> は XとYがどんなに近親関係にあろうが
(X,Yが同一でないかぎり)"まったく別物"扱いですからねー。
引用返信 編集キー/
■23456 / inTopicNo.3)  Re[1]: IListとList
□投稿者/ NyaRuRu (52回)-(2008/08/15(Fri) 13:28:35)
2008/08/15(Fri) 13:31:11 編集(投稿者)

No23453 (メタボmen さん) に返信
> わめいても仕方ないんですが...
> ここでわめかせてください。 ヽ(`Д´)ノ

C# 4.0 でできるようになるかもしれませんし,ならないかもしれません.
このあたりはずっと議論が続いています.

ちなみに,議論に参加するにあたってそれなりに前提知識が求められるので結構大変です.
まずは covariant/contravariant という用語の理解からですかね.

covariant/contravariant について知った上で,
-.NET Generics が covariant/contravariant をサポートしていること
-標準ライブラリ (BCL) の Generics Type で,covariant/contravariant が考慮されていないこと
-C# の Generics で covariant/contravariant が考慮されていないこと
-Java で wildcard を許したら非常に記法が複雑化してしまったこと
http://www.infoq.com/jp/news/2007/12/closures-preserving-feel-of-java
あたりを踏まえ,C# 4.0 でどうなるのがいいですかね,という議論に繋がるという感じでしょうか.
http://blogs.msdn.com/ericlippert/archive/2007/11/02/covariance-and-contravariance-in-c-part-nine-breaking-changes.aspx


引用返信 編集キー/
■23458 / inTopicNo.4)  Re[2]: IListとList
□投稿者/ 渋木宏明(ひどり) (850回)-(2008/08/15(Fri) 13:46:02)
渋木宏明(ひどり) さんの Web サイト
> C# 4.0 でできるようになるかもしれませんし,ならないかもしれません.

そのうち入りそうな気はするけど、結構先になるんじゃないかなー?
CLR 本体に手を入れるのと同時期とか。

引用返信 編集キー/
■23459 / inTopicNo.5)  Re[3]: IListとList
□投稿者/ NyaRuRu (53回)-(2008/08/15(Fri) 14:24:41)
ついでに,Java/.NET の配列に関する有名な問題も.
http://www29.atwiki.jp/tmiya/pages/48.html

もし IList<IList<int>> matrix = new List<List<int>>(); が許されたとします.
この場合,続いて
matrix.Add(new int[10]);
と書けて,これはコンパイルエラーにならないはずですが,実行時にエラーになります.
なぜなら matrix の実体は List<List<int>> であって,その要素に int[] は追加できないからです.
引用返信 編集キー/
■23460 / inTopicNo.6)  Re[3]: IListとList
□投稿者/ ネタ好き未記入 (22回)-(2008/08/15(Fri) 14:28:14)
仮に採用されるとなると、やはり言語仕様にはネストレベルが規定されるのでしょうか?
無いと無限ループに陥る可能性があると思います。
それに、インターフェイスは多重継承(もどき)をサポートしているから、多重継承は採用しないというC#のポリシーに反するかも。
引用返信 編集キー/
■23461 / inTopicNo.7)  Re[4]: IListとList
□投稿者/ NyaRuRu (54回)-(2008/08/15(Fri) 14:30:39)
2008/08/15(Fri) 14:31:02 編集(投稿者)
こちらは C# で実際にコンパイルが通るけど実行時エラーになる例.
コンパイル時の型検証でエラーを判定できないという意味では,あまりありがたい仕様ではありません.
ちなみに Java 由来です.

class Program
{
    static void Main()
    {
        object[] objs = new string[10];
        objs[0] = 1; // ここで実行時例外
    }
}

引用返信 編集キー/
■23463 / inTopicNo.8)  Re[5]: IListとList
□投稿者/ ネタ好き未記入 (24回)-(2008/08/15(Fri) 14:40:29)
NyaRuRu さんの例凄くわかりやすくていいですね。
GetはいいけどSetはだめというのがよくわかります。

 class Program
 {
    static void Main() {
        object[] objs = new string[10];
        objs[0] = 1.ToString(); // ここでプログラマが注意できるか
     }
 }

ですね。確かにサポートされても嬉しくないかも・・・

引用返信 編集キー/
■23464 / inTopicNo.9)  Re[4]: IListとList
□投稿者/ NyaRuRu (55回)-(2008/08/15(Fri) 14:42:49)
No23460 (ネタ好き未記入 さん) に返信
> 仮に採用されるとなると、やはり言語仕様にはネストレベルが規定されるのでしょうか?
> 無いと無限ループに陥る可能性があると思います。

以下のクラス定義は,C# / Common Type System (CTS) ともに許可されます.

class P<T> {}
class C<U,V> : P<D<V,U>> {}
class D<W,X> : P<C<W,X>> {}

この型定義には,ループ構造が存在しますが,エラーにはなりません.
循環する型定義が有用な場合があるので,単なるループだけではエラーにならないようになっています.
ISO/IEC 23271:2006(E) の §9.2 Generics and recursive inheritance graphs に,エラーとする場合の判定アルゴリズムが書かれています.
引用返信 編集キー/
■23466 / inTopicNo.10)  Re[6]: IListとList
□投稿者/ ネタ好き未記入 (26回)-(2008/08/15(Fri) 14:46:05)
2008/08/15(Fri) 16:38:11 編集(投稿者)

NyaRuRu さん教えて頂き有難うございます。
早速読みます。

何とか読みました。
デッドロックを検出するために使用する、直列可能判定グラフと似た検出法ですね。渋木宏明(ひどり) さんが言った意味が何となくわかりました。
これサポートするのが難しそうですね。
おまけにプログラマの負担も増える予感がしました。

引用返信 編集キー/
■23516 / inTopicNo.11)  Re[7]: IListとList
□投稿者/ 凪瀬 (74回)-(2008/08/18(Mon) 10:27:24)
凪瀬 さんの Web サイト
代入互換性から
IList<IList<int>> matrix = new List<List<int>>();
と出来ないのは、ここまでのスレッドの流れのとおりなのですが、ジェネリクスのこの周辺を分かりにくくしているのは、通常の変数の代入互換とルールが違うためではないかと考えています。

オブジェクト指向の考え方では子クラスは親クラスを代替え可能ですから
IList list = new List();
はキャスト演算子なしに代入可能とされます。
これは、変数型の宣言IListによって、事実上「IListを継承した何か」を代入可能なわけですが、
IList<IList<int>>
の場合、ジェネリクス型パラメータのIList<int>はIList<int>であって、「IList<int>を継承した何か」ではないんですよね。
List<IList<int>>は代入できるけど、IList<List<int>>は代入できない。

この似て非なる代入互換性がジェネリクスを分かりにくくしているように思えます。
引用返信 編集キー/
■23518 / inTopicNo.12)  Re[8]: IListとList
□投稿者/ ネタ好き未記入 (28回)-(2008/08/18(Mon) 10:58:59)
No23516 (凪瀬 さん) に返信
同感です。テンプレートは元々高級マクロなんで継承しないんですよね。
D言語ではテンプレートの継承を実装する作業中らしいので、もしかしたらD言語ならば可能になるのかも。
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -