atwiki-logo
  • 新規作成
    • 新規ページ作成
    • 新規ページ作成(その他)
      • このページをコピーして新規ページ作成
      • このウィキ内の別ページをコピーして新規ページ作成
      • このページの子ページを作成
    • 新規ウィキ作成
  • 編集
    • ページ編集
    • ページ編集(簡易版)
    • ページ名変更
    • メニュー非表示でページ編集
    • ページの閲覧/編集権限変更
    • ページの編集モード変更
    • このページにファイルをアップロード
    • メニューを編集
    • 右メニューを編集
  • バージョン管理
    • 最新版変更点(差分)
    • 編集履歴(バックアップ)
    • アップロードファイル履歴
    • ページ操作履歴
  • ページ一覧
    • ページ一覧
    • このウィキのタグ一覧
    • このウィキのタグ(更新順)
    • このページの全コメント一覧
    • このウィキの全コメント一覧
    • おまかせページ移動
  • RSS
    • このウィキの更新情報RSS
    • このウィキ新着ページRSS
  • ヘルプ
    • ご利用ガイド
    • Wiki初心者向けガイド(基本操作)
    • このウィキの管理者に連絡
    • 運営会社に連絡(不具合、障害など)
ページ検索 メニュー
プログラミング図書館・本館
  • ウィキ募集バナー
  • 目安箱バナー
  • 操作ガイド
  • 新規作成
  • 編集する
  • 全ページ一覧
  • 登録/ログイン
ページ一覧
プログラミング図書館・本館
  • ウィキ募集バナー
  • 目安箱バナー
  • 操作ガイド
  • 新規作成
  • 編集する
  • 全ページ一覧
  • 登録/ログイン
ページ一覧
プログラミング図書館・本館
ページ検索 メニュー
  • 新規作成
  • 編集する
  • 登録/ログイン
  • 管理メニュー
管理メニュー
  • 新規作成
    • 新規ページ作成
    • 新規ページ作成(その他)
      • このページをコピーして新規ページ作成
      • このウィキ内の別ページをコピーして新規ページ作成
      • このページの子ページを作成
    • 新規ウィキ作成
  • 編集
    • ページ編集
    • ページ編集(簡易版)
    • ページ名変更
    • メニュー非表示でページ編集
    • ページの閲覧/編集権限変更
    • ページの編集モード変更
    • このページにファイルをアップロード
    • メニューを編集
    • 右メニューを編集
  • バージョン管理
    • 最新版変更点(差分)
    • 編集履歴(バックアップ)
    • アップロードファイル履歴
    • ページ操作履歴
  • ページ一覧
    • このウィキの全ページ一覧
    • このウィキのタグ一覧
    • このウィキのタグ一覧(更新順)
    • このページの全コメント一覧
    • このウィキの全コメント一覧
    • おまかせページ移動
  • RSS
    • このwikiの更新情報RSS
    • このwikiの新着ページRSS
  • ヘルプ
    • ご利用ガイド
    • Wiki初心者向けガイド(基本操作)
    • このウィキの管理者に連絡
    • 運営会社に連絡する(不具合、障害など)
  • atwiki
  • プログラミング図書館・本館
  • .NET
  • コレクション

コレクション

最終更新:2011年09月04日 18:53

atachi

- view
管理者のみ編集可

コレクションの種類

ObservableCollection

  • WPFでの使用が可能
  • データバインディング対応

LinkedList

  • 双方向リスト
  • 途中に要素を追加したり、削除するなら通常のListより効率がよい。

Queue

  • 先入れ先出し(FIFO)リスト

Stack

  • 後入れ先出し(LIFO)リスト

IEnumerator<T>

コレクションの運用方法

クラスがpublicとして外部にコレクションを公開するフィールドやプロパティにはICollection / ICollection<T>を使います。

Listなどのコレクションの実態を返してしまうと、クラスが別の実体のコレクションを実装する場合に公開しているプロパティの型と参照している参照先をすべて変更しなければならなくなります。

線形リスト

List<T> 非推奨。複雑であり、拡張しずらい
Collection<T> 推奨。シンプル。
ObservableCollection<T> カスタムコントロールの設計でコレクションのプロパティを公開する場合に使用する

Collection<T>型 を使うことが推奨されます。
その理由にはCollectionは拡張性を考慮した設計を行っていることと、コレクションとして最低限必要なインターフェースだけを実装している点です。また、Collection<T>→List<T>への変換は簡単に行えます。

Collection<T>型 を使用する場合でも、「Collection<MyClass> arr = new Collection<MyClass>()」とするよりもMyClassクラスを要素に持つCollection<T>型を継承したクラスを作成すべき。(小さな手間以上の利点がある)

class MyClassCollection : Collection<MyClass> {
    // 利点として、SortやEmptyなどのメソッドを独自に実装できる
}

下記は、List<T>型 によるコレクション。

List<string> messages = new List<string>();
 
messages.Add("リストでは");
messages.Add("任意の場所に要素を追加できるよ");
List<string> messages = new List<string>();
 
messages.Add("リストでは");
messages.Add("任意の場所に要素を追加できるよ");
 
List<string> messages2 = new List<string>();
messages2.Add("末尾に付け足すこともできる");
 
messages.AddRange(messages2);

読み取り専用のコレクション

  • List<T>.AsReadOnly()
  • ReadOnlyCollection

foreachによるコレクションの操作

foreach内での要素追加・削除

foreach内ではコレクションへの要素の追加・削除はできません。
これらを行おうとすると、実行時に「コレクションが変更されました。列挙操作は実行されない可能性があります。」というエラーメッセージとともに例外が投げられます。

理由は説明するまでもなく、コレクションの走査中に内部に格納した要素の位置や順序が変わるということは正しい順序で走査できないためです。

解決策には、走査したいコレクションと同じ順番のコレクション(配列)を作成し、そのコレクションでforeachを実行する事になります。

// MyDataは何らかのクラス(参照クラスまたは値クラス)
 
ICollection<MyData> mydatas = new Collection<MyData>();
 
mydatas.Add(new MyData{name="test"}); 
... // 適当にmydatasコレクションへ要素を追加
 
// foreachのための配列を作成
MyData[] dmy = new MyData[mydatas.Count];
foreach(var obj in dmy){
	if(obj.name.StartWith("t")){
		mydatas.Remove(obj);
	}
}

foreachを直接mydatasコレクションを使うと上記のコードでは例外が発生する(*1)

CopyToメソッドは任意の配列に要素をコピー(シャローコピー)するメソッド。
これにより新たな配列が確保される。シャローコピーなので、要素のインスタンスは新しくヒープに作成されません。

ただし、調子によって次のようなコードでも...と思うと痛い目に遭う。

// foreachのためのコレクションを作成
ICollection<MyData> secondCollection = new Collection(mydatas);
foreach(var obj in secondCollection){
	if(obj.name.StartWith("t")){
		mydatas.Remove(obj);
	}
}

Collectionクラスのコンストラクタには別のコレクションを引数にする定義があります。
しかし、このコンストラクタは新たなコレクションを作り出す意味ではなく、引数のコレクションをラップするコレクションを作成するためのコンストラクタです。

要素を格納しているリストそのものは、mydatasとsecondCollectionは同じものを示しているため、foreach文が使うsecondCollectionのリストへの変更はそのままmydatasコレクションのリスト操作へ繋がるため、上記のコードではやはり例外が発生します。

foreach文での要素への値設定

foreach文の要素の走査でのループ決定のタイミングについてですが、 foreach文では最初の呼び出し時にコレクションのIEnumerable.GetEnumerator()が呼び出されイテレータが取得されます。
あとはイテレータのMoveNext()を呼び出し次の要素を取得していきます。最後はMoveNext()がnullを返したときにループを終了します。

foreachのループ順序はforeachが決めているのではなく、コレクションが定義したIEnumerableによって決定されます。

そのため、コレクションが持つIEnumerableの実装方法によってforeach内での要素への値設定は不正となる可能性が出てきます。

ICollection<MyData> items = new MyDataCollection(mydatas); // MyDataCollectionは独自に定義したコレクションクラス
 
int lastOrder = 0;
foreach(var item in items){
	lastOrder = item.Order;
	item.Order = items[MyDataCollection.Count];
}

潜在的にバグがあるであろうと誰でもわかるように上記のコードとしました。
このバグはコンパイラは報告してくれません(*2)

「誰でもわかる」というのは、MyData.OrderというプロパティがおそらくMyDataCollectionでの要素の位置を示しているであろうことを、開発者は直感で感じ取るからです。
foreach内で要素の順番に関わるプロパティの値を変更することは、プログラムが復帰不可能となるか無限ループに陥ります。

このサンプルのように、明らかに要素の順番に関わっているであろうことがわかる場合ならよいのですが、現実にはそうでない場合がほとんどです。

この問題を引き起こさないためには、開発時にプロジェクト全体で1つのシナリオを定義しておくべきです。
ただし、「foreach内で要素のプロパティ値を設定しない」だけでは不十分です。要素のメソッドの呼び出しも注意が必要です。
foreach内で呼び出した要素のメソッドがOrder値を変更するような実装をしていたら上記と同じことになります。

このようなバグを回避するには、foreachを使わない、もしくはOrderをreadonlyとして宣言しておくなどのプロジェクト全体でこの問題についてのシナリオを議論する必要があります。

要素への逐次処理

C#ではラムダ式が使えるので、配列やコレクション内の要素に対して値を取得したり設定する場合に次のような記述ができます。

int[] array = { 1, 2, 3 };
int sum = 0;
 
Array.ForEach<int>(array, (i) =>         // Array.ForEach<>
	{
		sum += i
	});

ただし、この書き方は推奨できません。
デバッグがしづらいです。そのままforeach文として記述できるので、foreach文で書くべきです。

System.Array

C#ではラムダ式が使えるので、System.Arrayが定義する配列に対する操作がかなり簡潔に書けるようになりました(ほとんど、ワンライナーで記述が可能)

string[] names = new[] { "北海道", "本州", "四国", "九州", "沖縄" };
 
// ■ Findメソッド
string name = Array.Find(list, s => s.Length == 3);
Console.WriteLine(name);
 
// ■ Exists
// 任意の条件に一致する要素がある場合true
bool b = Array.Exists(list, s => s.StartWith("四") );
Console.WriteLine(b);
 
// ■FindIndex
// 任意の要素の位置
int index = Array.FindIndex(list, s => s == "本州");
Console.WriteLine(index);
 
// ■ForEachメソッド
// foreach構文と同じ。
Array.ForEach(list, s => Console.WriteLine(s));
 
// ■Sortメソッド
Array.Sort(list, (x, y) => x.Length - y.Length);
Array.ForEach(list, s => Console.WriteLine(s));
 
// ■ConvertAll
string[] list2 = Array.ConvertAll(list, s => s.ToLower());
Array.ForEach(list2, s => Console.WriteLine(s));

文字列配列の文字列一致

文字列型の配列から、特定の文字と完全に一致する要素があるかを検証する処理は簡単にできます。

string[] PrefectureNames = new string[] {
	"北海道",
	"青森",
	"岩手",
	"宮城",
	"秋田"
};
 
if(PrefectureNames.Contains("岩手"))
	System.Console.WriteLine("「岩手」は配列に存在します");

IList.Containsメソッドを使うと、引数のオブジェクトと一致する要素がある場合にtrueを返します。

  • .NET Frameworks3.0以降で有効

タグ:

.NET
「コレクション」をウィキ内検索
LINE
シェア
Tweet

[Amazon商品]


プログラミング図書館・本館
記事メニュー

C#

  • 新機能
  • 言語文法
    • 型
    • 関数
    • クラス
    • 演算子
    • 構文
    • デリゲート
    • イベント
    • 例外処理
    • アトリビュート
    • 名前空間
    • ジェネリクス
  • リフレクション
  • LINQ

.NET Frameworks

  • 数値
  • 文字列
  • 日付時刻
  • オブジェクト
  • コレクション
  • ファイルシステム
  • スレッド
  • データテーブル
  • グラフィックス
  • デバッグ
    • ログ出力
    • ユニットテスト
  • ユーティリティ
  • ネットワーク
    • HTTP
  • デバイス
    • COMポート
  • EntityFrameworks
    • Code First Programming Model
  • デバイスドライバ
    • WinUSB

WPF

  • XAML
  • イベント
  • コマンド
  • スタイル
  • データバインディング
  • コンポーネント
  • グラフィックス
  • カスタムコンポーネント
    • 依存関係プロパティ

アプリケーション

  • 二重起動の防止
  • アンマネージドDLLの読み込み
  • 外部のアプリケーションを起動

VisualStudio

  • 拡張機能
  • カラー設定

ライブラリ

  • WPFToolkit
  • A Fast CSV Reader
  • AvalonDock

実装方法

  • ドラッグアンドドロップ
  • アプリケーション内のドラッグアンドドロップ
  • CSVからDataTable

minecraft

  • Bukkit
  • プラグイン
    • Permissions
    • SlowHealth
    • CookieMonster
    • iConomy
    • WorldGuard
    • Lockette
    • MyHome
    • BorderGuard

サイトについて

プロフィール/リンク/未分類

メモ/ゲーム/Stacks/Omoikane


更新履歴

取得中です。

ここを編集

記事メニュー2

読んでいる本


Effective C#

QLOOKアクセス解析

ここを編集

人気記事ランキング
  1. 構文
もっと見る
最近更新されたページ
  • 5033日前

    Bukkit
  • 5039日前

    トップページ
  • 5060日前

    メニュー
  • 5070日前

    WPF/グラフィックス
  • 5070日前

    .NET/グラフィックス
  • 5070日前

    .NET/グラフィックス/画像の書き込み
  • 5070日前

    .NET/グラフィックス/画像の読み込み
  • 5076日前

    .NET/コレクション
  • 5094日前

    .NET/WinUSB
  • 5129日前

    BorderGuardプラグイン
もっと見る
「.NET」関連ページ
  • .NET/オブジェクト
人気記事ランキング
  1. 構文
もっと見る
最近更新されたページ
  • 5033日前

    Bukkit
  • 5039日前

    トップページ
  • 5060日前

    メニュー
  • 5070日前

    WPF/グラフィックス
  • 5070日前

    .NET/グラフィックス
  • 5070日前

    .NET/グラフィックス/画像の書き込み
  • 5070日前

    .NET/グラフィックス/画像の読み込み
  • 5076日前

    .NET/コレクション
  • 5094日前

    .NET/WinUSB
  • 5129日前

    BorderGuardプラグイン
もっと見る
ウィキ募集バナー
新規Wikiランキング

最近作成されたWikiのアクセスランキングです。見るだけでなく加筆してみよう!

  1. 機動戦士ガンダム EXTREME VS.2 INFINITEBOOST wiki
  2. MadTown GTA (Beta) まとめウィキ
  3. R.E.P.O. 日本語解説Wiki
  4. シュガードール情報まとめウィキ
  5. ソードランページ @ 非公式wiki
  6. AviUtl2のWiki
  7. Dark War Survival攻略
  8. シミュグラ2Wiki(Simulation Of Grand2)GTARP
  9. 星飼いの詩@ ウィキ
  10. ヒカマーWiki
もっと見る
人気Wikiランキング

atwikiでよく見られているWikiのランキングです。新しい情報を発見してみよう!

  1. アニヲタWiki(仮)
  2. ストグラ まとめ @ウィキ
  3. 機動戦士ガンダム EXTREME VS.2 INFINITEBOOST wiki
  4. ゲームカタログ@Wiki ~名作からクソゲーまで~
  5. 初音ミク Wiki
  6. 発車メロディーwiki
  7. 検索してはいけない言葉 @ ウィキ
  8. Grand Theft Auto V(グランドセフトオート5)GTA5 & GTAオンライン 情報・攻略wiki
  9. 機動戦士ガンダム バトルオペレーション2攻略Wiki 3rd Season
  10. モンスター烈伝オレカバトル2@wiki
もっと見る
全体ページランキング

最近アクセスの多かったページランキングです。話題のページを見に行こう!

  1. 参加者一覧 - ストグラ まとめ @ウィキ
  2. 魔獣トゲイラ - バトルロイヤルR+α ファンフィクション(二次創作など)総合wiki
  3. 鬼レンチャン(レベル順) - 鬼レンチャンWiki
  4. 機体一覧 - 機動戦士ガンダム EXTREME VS.2 INFINITEBOOST wiki
  5. ドンキーコング バナンザ - アニヲタWiki(仮)
  6. チンポ画像収集場 - 検索してはいけない言葉 @ ウィキ
  7. 仕込みマシンガン/仕込み爆弾(遊戯王OCG) - アニヲタWiki(仮)
  8. ヤマダ電機の唄 - アニヲタWiki(仮)
  9. 危険度7 - 検索してはいけない言葉 @ ウィキ
  10. 千鳥の鬼レンチャン 挑戦者一覧 - 千鳥の鬼レンチャン サビだけカラオケデータベース
もっと見る
注釈

*1 正確には、「例外が発生する場合」がある。

*2 だからbugともいう

  • このWikiのTOPへ
  • 全ページ一覧
  • アットウィキTOP
  • 利用規約
  • プライバシーポリシー

2019 AtWiki, Inc.