2009-07-20 4 views
0

私はこれを持っている:私はCountから何かを得ることができますか?

private IEnumerable _myList; 

は、私は、そのオブジェクトのオフカウントを取得する必要があります。以前は_myListを配列に入力して長さを取得していましたが、今は同じ種類のコードを別の種類のオブジェクトで使用しています。それはコレクション型(厳密に型付けされたSubsonic Collectionオブジェクトです)ですが、オブジェクト内のアイテムの総数を取得するために必要なビットを除いて、すべてがうまく機能します。

私はCollectionBaseなど多くの他の型を入力しようとしましたが、.Countや.Lengthなどのものは何も得られません。

誰でも正しい方向に向けることができますか?

編集:私は3.5を使用していません.2を使用しています。したがって、Linqを扱うものは動作しません。これを前に投稿してくれないのは残念です。

答えて

11

これは実際にIEnumerable代わりのIEnumerable<T>ですか?もしそうなら、LINQは直接あなたを助けません。 (他の場所で示唆したようにあなたはCast<T>()を使用することができますが、それは比較的遅くなります - 特に、それはIList/IList<T>実装用に最適化されることはありません。)

を、私はあなたが書い勧め:タイプ

public static int Count(this IEnumerable sequence) 
{ 
    if (sequence == null) 
    { 
     throw new ArgumentNullException("sequence"); 
    } 

    // Optimisation: won't optimise for collections which 
    // implement ICollection<T> but not ICollection, admittedly. 
    ICollection collection = sequence as ICollection; 
    if (collection != null) 
    { 
     return collection.Count; 
    } 

    IEnumerator iterator = sequence.GetEnumerator(); 
    try 
    { 
     int count = 0; 
     while (iterator.MoveNext()) 
     { 
      // Don't bother accessing Current - that might box 
      // a value, and we don't need it anyway 
      count++; 
     } 
     return count; 
    } 
    finally 
    { 
     IDisposable disposable = iterator as IDisposable; 
     if (disposable != null) 
     { 
      disposable.Dispose(); 
     } 
    } 
} 
+0

"using"ステートメントではなくtry/finallyブロックの理由は何ですか? –

+4

すべてのIEnumeratorがIDisposablesであるわけではないので、私は賭けたいと思う。 – Rytmis

+0

@Rytmisはまさに正しいです。 IEnumerator はIDisposableを継承しますが、IEnumeratorは使用しません。したがって、usingステートメントでは使用できません。 Fun fact:foreachはC#1.2でイテレータを処分し始めました。 C#1.0ではそれはしませんでした。 .NET 1.1があるにもかかわらず、私はC#1.1仕様を知らない。 –

0

.ToList()についてはどうなりますか?

+0

は(長いシーケンスのために、これはそれまでの結果-たびにコピーし、いくつかのますます大きなメモリブロックを割り当てます)元のリストのコピーを作成します。 –

+0

カウントを取得するためだけにリストに変換する必要はありません.Enumerable.Count()も同様に機能するはずです。 –

10

IEnumerable<T>の場合は、System.Linq.Enumerable.Count拡張メソッドがこれを行います。 型なしIEnumerableために独自の拡張機能を作ってみてください。

public static int Count(this IEnumerable source) 
    { 
     if (source == null) 
     { 
      throw new ArgumentNullException("source"); 
     } 

     ICollection collectionSource = source as ICollection; 
     if (collectionSource != null) 
     { 
      return collectionSource.Count; 
     } 

     int num = 0; 
     IEnumerator enumerator = source.GetEnumerator(); 
     //try-finally block to ensure Enumerator gets disposed if disposable 
     try 
     { 
      while (enumerator.MoveNext()) 
      { 
       num++; 
      } 
     } 
     finally 
     { 
      // check for disposal 
      IDisposable disposableEnumerator = enumerator as IDisposable; 
      if(disposableEnumerator != null) 
      { 
       disposableEnumerator.Dispose(); 
      } 
     } 
     return num; 
    } 
+1

Intellisenseで使用できるようにするには、usingステートメントにSystem.Linqを含めるようにしてください。 – LBushkin

+0

また、IEnumerableの代わりにIEnumerable に再定義する必要があります。 –

+1

Count()は、IEnumerableではなく、IEnumerable でのみ使用できます。 –

1

LINQはCount()拡張メソッドを提供します。

using System.Linq; 

...

var count = _myList.Count(); 
4

は、.NET 3.5を使用している場合は、任意のIEnumerable<T>からカウントを取得するためにEnumerable.Count()を使用することができます。

IEnumerableでは非対応ではありませんが、IEnumerable<T>が必要です。

しかし、Subsonicのコレクションクラスは適切なインターフェイスを実装しているので、これはうまくいくはずです。定義をIEnumerableからIEnumerable<MyClass>に変更する必要があります。

+0

はい、なぜIEnumerable の代わりに 'IEnumerable'と宣言されていますか? –

1

System.Linq名前空間を含める場合、IEnumerable<T>にはCount() extension methodがあります。あなた自身の拡張メソッドを書くことで非ジェネリック版にすることができます。 このメソッドはボックスの値の型になりますので、パフォーマンス上の懸念を引き起こす可能性がある場合はJon Skeet's solutionとしてください。これは単なる単純です。

public static int Count(this IEnumerable enumerable) 
{ 
    int count = 0; 
    foreach(object item in enumerable) 
    { 
     count++; 
    } 
    return count; 
} 
+0

それはint []のようなものなら、シーケンス内のすべてを囲みます。必要はありません。私の答えは、やや面倒ですが、潜在的により効率的な解決策を見てください。 –

+0

@ジョン良い点、ありがとう。 –

1

Countプロパティを持たないIEnumerableを使用します。しかし、一般的な同等のIEnumerable(T)にはCountプロパティがあります。

明白な解決策は、IEnumerableを(T)を使用することですが、あなたは、あなたがこのような何かを行うことができないことができる場合:

_myList.Cast<MyListItemType>().Count() 

キャストがIEnumerableをへてIEnumerableを変換する簡単な方法は、(ありますSomeType)でも、カウントをパフォーマンスに合わせるには最良の方法ではないことは明らかです。

パフォーマンスが重要な場合は、基になるコレクションにCountプロパティがあることが分かっている場合を除き、値をループするだけです(Jon Skeetの回答を参照)。

0

基本オブジェクトがICollectionを実装する場合は、.Count()プロパティを使用できます。

0

同じものが必要でしたし、IEnumerableListを作成しました。その理由は、Count()という拡張メソッドのように、列挙可能なオブジェクト全体でカウントが必要になるたびに評価したくないからです。

それについての詳細ここに:http://fknet.wordpress.com/2010/08/11/string-formatwith-extension/

関連する問題