0

いくつかの背景情報;

  • LanguageResource は基本クラスです
  • LanguageTranslatorResource と LanguageEditorResource は LanguageResource から継承します
  • LanguageEditorResource は IsDirty プロパティを定義します
  • LanguageResourceCollection は LanguageResource のコレクションです
  • LanguageResourceCollection は内部的に LanguageResources を保持しますDictionary<string, LanguageResource> _dict
  • LanguageResourceCollection.GetEnumerator() が返す_dict.Values.GetEnumerator()

LanguageEditorResource オブジェクトのみを含む LanguageResourceCollection _resources があり、LINQ を使用してダーティなものを列挙したいので、次のことを試しました。私の具体的な質問は太字で示しています。

  1. _resources.Where(r => (r as LanguageEditorResource).IsDirty)

    どちらも Where not 他の LINQ メソッドは Intellisense によって表示されますが、とにかくコーディングすると、「LanguageResourceCollection には 'Where' の定義が含まれておらず、拡張メソッドもありません...」と言われます。

    LanguageResourceCollection が IEnumerable を実装する方法によって、LINQ のサポートが妨げられるのはなぜですか?

  2. クエリを

    (_resources as IEnumerable<LanguageEditorResource>).Where(r => r.IsDirty)

    Intellisense に変更すると、LINQ メソッドが表示され、ソリューションがコンパイルされます。しかし、実行時に ArgumentNullException 「値を null にすることはできません。パラメータ名: ソース」が発生します。

    これは私の LINQ コードの問題ですか?
    クラスの一般的な設計に問題がありますか?
    LINQ が生成するものを掘り下げて、問題の内容を確認するにはどうすればよいですか?

この質問に対する私の目的は、特定の問題の解決策を得ることではなく、他の (LINQ 以外の) 手段を使用して解決する必要があるためです。むしろ、LINQ の理解を深め、設計を改善する方法を学ぶことです。私のクラスの LINQ でより適切に動作します。

4

3 に答える 3

6

IEnumerableコレクションがではなくを実装しているように聞こえるIEnumerable<T>ため、次のものが必要です。

_resources.Cast<LanguageEditorResource>().Where(r => r.IsDirty)

はではなくEnumerable.Whereで定義されていることに注意してください。非ジェネリック型の場合は、(または) を使用して正しい型を取得する必要があります。違いは、 ではないものを見つけた場合に例外をスローするのに対し、 -as は .ではないものを単に無視することです。コレクションには のみが含まれていると述べたので、静かにデータを削除するのではなく、を使用してその仮定を確認するのが合理的です。IEnumerable<T>IEnumerableCast<T>OfType<T>Cast<T>TOfType<T>TLanguageEditorResourceCast<T>

Whereまた、拡張メソッドを取得するために、「System.Linq を使用している」こと (および System.Core (.NET 3.5; それ以外の場合は .NET 2.0 の LINQBridge) を参照していること) を確認してください。

実際には、コレクションを実装する価値があります。これは、メソッドまたはイテレータ ブロック ( )IEnumerable<LanguageResource>を使用して非常に簡単に行うことができます。Cast<T>yield return

[編集] Richard Poole のメモに基づいて構築するには、おそらく を使用して(および でそれを使用し、またはを実装して)、独自の汎用コンテナーをここに記述できます。ちょっとした考え。T : LanguageResourceTDictionary<string,T>IEnumerable<T>ICollection<T>

于 2008-11-06T08:40:46.457 に答える
1

LINQ が生成するものを掘り下げて、問題の内容を確認するにはどうすればよいですか?

Linq はここでは何も生成していません。デバッガーを使用してステップスルーできます。

LINQ の理解を深め、クラスの設計を改善して LINQ をより適切に操作する方法を学びます。

System.Linq.Enumerable メソッドは、IEnumerable< T > コントラクトに大きく依存しています。クラスがこのコントラクトをサポートするターゲットを生成する方法を理解する必要があります。T が表す型は重要です。

このメソッドを LanguageResourceCollection に追加できます。

public IEnumerable<T> ParticularResources<T>()
{
  return _dict.Values.OfType<T>();
}

そしてそれを次のように呼び出します:

_resources
  .ParticularResources<LanguageEditorResource>()
  .Where(r => r.IsDirty)

コレクション クラスが同じ _dict.Values に対して IEnumerable< T > を実装していない場合、この例はより理にかなっています。ポイントは、IEnumerable < T > とジェネリック型付けを理解することです。

于 2008-11-06T16:25:30.170 に答える
1

LanguageResourceCollectionMarc G の回答に加えて、それが可能な場合は、汎用クラスを優先してカスタム クラスを削除することを検討してくださいList<LanguageResource>。これにより、現在の問題が解決され、厄介な .NET 1.1 っぽいカスタム コレクションが取り除かれます。

于 2008-11-06T09:02:26.600 に答える