東方算程譚

Oriental Code Talk ── επιστημηが与太をこく、弾幕とは無縁のシロモノ。

目次

Blog 利用状況

ニュース

著作とお薦めの品々は

著作とお薦めの品々は
東方熱帯林へ。

あわせて読みたい

わんくま

  1. 東京勉強会#2
    C++/CLI カクテル・レシピ
  2. 東京勉強会#3
    template vs. generics
  3. 大阪勉強会#6
    C++むかしばなし
  4. 東京勉強会#7
    C++むかしばなし
  5. 東京勉強会#8
    STL/CLRによるGeneric Programming
  6. TechEd 2007 @YOKOHAMA
    C++・C++/CLI・C# 適材適所
  7. 東京勉強会#14
    Making of BOF
  8. 東京勉強会#15
    状態遷移
  9. 名古屋勉強会#2
    WinUnit - お気楽お手軽UnitTest

CodeZine

  1. Cで実現する「ぷちオブジェクト指向」
  2. CUnitによるテスト駆動開発
  3. SQLiteで組み込みDB体験(2007年版)
  4. C++/CLIによるCライブラリの.NET化
  5. C# 1.1からC# 3.0まで~言語仕様の進化
  6. BoostでC++0xのライブラリ「TR1」を先取りしよう (1)
  7. BoostでC++0xのライブラリ「TR1」を先取りしよう (2)
  8. BoostでC++0xのライブラリ「TR1」を先取りしよう (3)
  9. BoostでC++0xのライブラリ「TR1」を先取りしよう (4)
  10. BoostでC++0xのライブラリ「TR1」を先取りしよう (5)
  11. C/C++に対応した、もうひとつのUnitTestFramework ─ WinUnit
  12. SQLiteで"おこづかいちょう"
  13. STL/CLRツアーガイド
  14. マージ・ソート : 巨大データのソート法
  15. ヒープソートのアルゴリズム
  16. C++0xの新機能「ラムダ式」を次期Visual Studioでいち早く試す
  17. .NETでマンデルブロ集合を描く
  18. .NETでマンデルブロ集合を描く(後日談)
  19. C++/CLI : とある文字列の相互変換(コンバージョン)
  20. インテルTBBによる選択ソートの高速化
  21. インテルTBB3.0 によるパイプライン処理
  22. Visual C++ 2010に追加されたSTLアルゴリズム
  23. Visual C++ 2010に追加されたSTLコンテナ「forward_list」
  24. shared_ptrによるObserverパターンの実装
  25. .NETでマンデルブロ集合を描く(番外編) ── OpenCLで超並列コンピューティング
  26. StateパターンでCSVを読む
  27. 状態遷移表からStateパターンを自動生成する
  28. 「ソートも、サーチも、あるんだよ」~標準C++ライブラリにみるアルゴリズムの面白さ
  29. インテルTBBの同期メカニズム
  30. なぜsetを使っちゃいけないの?
  31. WPFアプリケーションで腕試し ~C++でもWPFアプリを
  32. C++11 : スレッド・ライブラリひとめぐり
  33. Google製のC++ Unit Test Framework「Google Test」を使ってみる
  34. メールでデータベースを更新するココロミ
  35. Visitorパターンで遊んでみたよ
  36. Collection 2題:「WPFにバインドできる辞書」と「重複を許す検索set」
  37. Visual C++ 2012:stateless-lambdaとSQLiteのぷち拡張
  38. 「Visual C++ Compiler November 2012 CTP」で追加された6つの新機能

@IT

  1. Vista時代のVisual C++の流儀(前編)Vista到来。既存C/C++資産の.NET化を始めよう!
  2. Vista時代のVisual C++の流儀(中編)MFCから.NETへの実践的移行計画
  3. Vista時代のVisual C++の流儀(後編) STL/CLRによるDocument/Viewアーキテクチャ
  4. C++開発者のための単体テスト入門 第1回 C++開発者の皆さん。テスト、ちゃんとしていますか?
  5. C++開発者のための単体テスト入門 第2回 C++アプリケーションの効率的なテスト手法(CppUnit編)
  6. C++開発者のための単体テスト入門 第3回 C++アプリケーションの効率的なテスト手法(NUnit編)

AWARDS


Microsoft MVP
for Visual Developer - Visual C++


Wankuma MVP
for いぢわる C++


Nyantora MVP
for こくまろ中国茶

Xbox

Links

記事カテゴリ

書庫

日記カテゴリ

C# 3.0 Collection Initializers

ネタ元 → オブジェクトの初期化

C# 3.0 ではコレクションの初期化が簡単になりました。

// 3.0
List<int> c = new List<int>{ 1, 2, 3 };

// 現2.0だと
List<int> c = new List<int>(new int[] { 1, 2, 3 });

C# 3.0 のスペック曰く:
「The collection object to which a collection initializer is applied must be of a type that implements System.Collections.Generic.ICollection<T> for exactly one T.」
ネタ元のコメントで青柳さん解説するに:
「collection initializer は ICollection<T>.Add(T) を順番に呼び出すだけですね。なので、対象となる型は ICollection<T> を実装していないとダメですし...」

ホントかなー?
AddできるだけでいいんならICollection<T>を実装しろっ
てのはちとオオゲサやん…てんでお試し。
collection initializer が使えるminimum-codeを書いてみました:

// Visual Studio 2008 codename "Orcas" β1 で検証
using System;
using System.Collections;
using System.Collections.Generic;

class Fake<T> : IEnumerable {

  private T[] data;
  private int size;
  private int capacity;

  public Fake(int capac) {
    Console.WriteLine("Fake({0})", capacity = capac);
    data = new T[capacity];
  }

  public void Add(T item) {
    Console.WriteLine("Add({0})", item);
    if ( size < capacity ) data[size++] = item;
  }

  IEnumerator IEnumerable.GetEnumerator()
  { for ( int i = 0; i < size; ++i )
      yield return data[i]; }

}

class Program {
  public static void Main() {
    Fake<int> c = new Fake<int>(10){ 1, 2, 3};
    foreach ( int item in c ) {
      Console.Write("{0} ", item);
    }
  }
}

…えとね、System.Collections.IEnumerable を実装し、
Addメソッドさえあればいいみたいよ。

投稿日時 : 2007年6月30日 14:33

コメントを追加

# re: C# 3.0 Collection Initializers 2007/07/01 3:17 シャノン

リフレクションかー。気持ちわりー。

IEnumerable ってのもビミョー。
Add メソッドさえあればいいなら、IEnumerable 要らんやん。
にもかかわらず IEnumerable を要求するってことは、「IEnumerable を実装している=コレクション」と認識されている、ってことだと思う。
けど、IEnumerable ってのは「列挙可能なもの」であって「コレクション」とは限らないんじゃないのかな。たとえば、素数を延々列挙し続けるクラスとか、コレクションとは言い難いと思う。
それとも、Collections 名前空間にあるってことは、IEnumerable はコレクションに使うものと想定されているってことだろうか。
ともあれ、何で「IEnumerable=コレクション」なんだろう。

あー、そうか。IEnumerable は「コレクションの最低要件」なのか。
ICollection は Count プロパティを持ってる=さっきみたいな無限要素には実装できないし、IList はそれに加えてインデックスアクセスも要求している=順不同なものには実装できない。

うーん…なんつーかなー。このへん、インターフェイス設計がマズいんちゃうん? と思う。
COM だと、あるインターフェイスが他のインターフェイスを継承しているってケースはほとんど無いのよね。インターフェイスって直交的な性質を持つものだから。

ICollection と IList なんて、名前だけだとどう使い分けたらいいのか分かりにくいし、「リスト=インデックスアクセスが可能」ってのもどうかと思う。リストと言えばぱっと思いつくリンクリストなんて、インデックスアクセスするのは現実的じゃないものね。

もっとも、このあたりは .NET Fx の中でも最古の部分だろうから、今さらどうこうするわけにはいかないんだろうけどさ。

LINQ が返すのが IEnumerable ってのも気に入らなかったり。あれこそ ICollection なり IList なりでいいんじゃないの? と。
なんか、「コレクション系インターフェイスは設計ミスっちゃったから、IEnumerable 以外は無かったことにしてしまおう」みたいな思惑を感じてしまうのは考えすぎ?

# re: C# 3.0 Collection Initializers 2007/07/01 3:57 επιστημη

うんうんう。

> IEnumerable ってのもビミョー。
> Add メソッドさえあればいいなら、IEnumerable 要らんやん。

なのよねー。
interface I追加できる<T> { void Add(T item); }
を定義すんのが王道よねぇ。

ためしに : IEnumerable を取っ払うと:
error CS1922: Collection initializer requires its type 'Fake<int>' to implement System.Collections.IEnumerable.
なんて文句たれます。

{ 1, 2, 3 } を 型IEnumerable<int>なインスタンスとみなしてくれれば
new List<int>({ 1, 2, 3 });
って書くことでIEnumerable<T>を引数とするコンストラクタが動くんだからそっちの方がカコイクね? とか思うし。

.NET 1.x の頃からコレクション系のinterfaceには違和感がありました。
IListは可変長配列Listのために"後付け"でこしらえた感がありますです。
順次アクセス可って意味を持たすならISequenceだよなー、とか。

なんかこー、.NET 1.0 からのいろんな"しがらみ"が感じられます。

# re: C# 3.0 Collection Initializers 2007/07/01 4:08 シャノン

他人のことを言えた義理じゃないが、こんな時間にレスがあったことにびっくりww

> { 1, 2, 3 } を 型IEnumerable<int>なインスタンスとみなしてくれれば

それをやってくれると、

IEnumerable<int> e = { 1, 2, 3 };

とか

foreach( int i in { 1, 2, 3 } )

なんてゆー書き方ができてしまうのよね。
これ、今はできないよね。

…できたほうがいい?

# re: C# 3.0 Collection Initializers 2007/07/01 4:21 επιστημη

エレガントだと思うけどねぇ。

東京勉強会#8のあと、いろいろこさえた中にそんなのがあるです。

class Enums {
 public static IEnumerable<T> List<T>(params T[] items) {
  foreach ( T item in items ) {
   yield return item;
  }
 }
}

foreach ( int i in Enums.List<int>(1, 2, 3))
なんてな。

# re: C# 3.0 Collection Initializers 2007/07/01 4:28 シャノン

さらに突っ込んでみる。

{ 1, 2, 3 } なんて、要素数が3であることは明らかなのだし、この方法で無限要素を持つリストを書くことはできないのだから、ICollection でも問題ないと思う。
要素数が明らかということは、{ 1, 2, 3 }.Count なんてやったって仕方ないんだけれど、"123".Length なんてのは出来るものね。

出来ても出来なくてもいいのは置いとくとしても、LINQ の結果は IEnumerable<T> なのよね。ってことは、結果の要素数を知ることができないってこと。
それってちょっと不便じゃないの? と思う。
SQL の Count 関数みたいに、クエリの中に要素数を取得する記述をすればいいのかもしれないけどね。
逆を言えば、IEnumerator.MoveNext が呼ばれるまで、次の要素のフェッチを遅らせることができるというメリットはあるんだけど。

やっぱり「IEnumerable以外はなかったことにしよう」なのかな。

あ、違うか。LINQはソースがIEnumerableだから、結果もIEnumerable以上にはできないのか。

# re: C# 3.0 Collection Initializers 2007/07/01 4:41 シャノン

すげー無意味。

foreach( int i in new int[]{ 1, 2, 3 })

と、どれほど違うねん?
ま、こんなの

static void Hoge<T>( params T[] ts)
{
foreach (T t in Enums.List<T>( ts ))
{
Console.WriteLine(t);
}
}

を書くために、int をハードコーディングしないで T にできるのはメリットかもしれん。

けど、T[] は IEnumerable<T> を実装するので、

public static IEnumerable<T> List<T>(params T[] items)
{
return items;
}

でいいし、それ言っちゃったら、

static void Hoge<T>( params T[] ts)
{
foreach (T t in ts)
{
Console.WriteLine(t);
}
}

でいいんだもの。

# re: C# 3.0 Collection Initializers 2007/07/01 4:52 επιστημη

> return items;
ぁぅぁぅー そーいやそぉだ orz
ちょっと寝よ。

# re: C# 3.0 Collection Initializers 2007/07/01 13:09 渋木宏明(ひどり)

>やっぱり「IEnumerable以外はなかったことにしよう」なのかな。

あると思います。
「失敗」の理由は「かっこ悪い」以外にもあるし。

# re: C# 3.0 Collection Initializers 2008/05/28 15:01 シャノン

古いエントリだけど…
これ、Add を拡張メソッドで宣言してもダメ?

Dictionary って、
 Add( TKey, TValue )
しかなくて、
 Add( keyValuePair( TKey, TValue ) )
が無いので、この方式で初期化できないの。
じゃあってんで、
 Add< TKey, TValue >( this IDictionary< TKey, TValue > dict, KeyValuePair< TKey, TValue > item )
なんてのをこしらえてみたんだけど、認識してくんない。
ジェネリックだからダメなのかしら?

タイトル
名前
URL
コメント