2013-03-01 6 views
9

私のプロジェクトではMyClassがあり、IMyClassを実装しています。私は他の項目のリストを変換することによってIMyClassのリストを返す必要があります。簡単にするために、別のアイテムをそのコンストラクタに渡すだけでを作成できるとします(new MyClass(item))。ラムダでキャストするか、IEnumerableをキャストする必要がありますか?

(私の知る限りでは)これは、同じ結果を生成、次の2行を考えてみましょう:オプション#1は、すべての項目をキャストするために、一度、二重の列挙を必要とする私には思える

var option1 = items.Select(item => new MyClass(item)).Cast<IMyClass>().ToList() 
var option2 = items.Select(item => new MyClass(item) as IMyClass).ToList() 

を私のインターフェースと一度リストを生成する。もし私が正しいなら、オプション2はよりスマートになります。しかし、は、オプション#2のようなコードを使用していませんでした。私は、C#コミュニティの残りの部分が賢明ではないと思うほどスマートではないと思います。

オプション2は審美的に嬉しいですが、それは私だけだと思います。

私の質問は:私の選択肢#2私はそれが良いと思うより良いアイデアですか?私が行方不明になっているか、オプション#1にこだわりたい理由があるのでしょうか?それとも、私が完全に欠けているよりスマートな第3のものがあるときにおそらく2つの愚かなアイデアを比較していますか?

+3

enumerablesが怠惰で構成可能であることを忘れないでください!オプション1は、それが2回列挙されることはありません... –

+0

'MyClass'が' IMyClass'を実装すると、なぜキャストする必要がありますか? –

+1

あなたは推論なしでいつもタイプを綴ることができますか? ToString(); 'IEnumerable 'を返します。 –

答えて

17
asを使用していない、

var option3 = items.Select<Foo, IMyClass>(item => new MyClass(item)) 
        .ToList() 

代わりにちょうど通常キャスト:

私はオプション3のために行くだろう

var option4 = items.Select(item => (IMyClass) new MyClass(item)) 
        .ToList() 

両方ともCastを使用するよりもきれいに見えます。

ああ、および(による共分散)は、.NET 4とC#4のように、あなたの代わりにToListコールに型引数を入れることができます:

var option5 = items.Select(item => new MyClass(item)) 
        .ToList<IMyClass>() 
+0

オプション3と4は私にとって美的にはそれをしませんでしたが、オプション5は間違いなく行います。選択のための満員! – ean5533

+0

オプション4は、var option4 = items.Select(item =>(** IMyClass **)new MyClass(item)) 'ではありませんか? – pescolino

+0

@pescolino:はい、確かに - 固定、ありがとう。 –

3

そのオプション#1は、これは真実ではありませんダブル列挙

を必要とする私には思えます。どちらの場合も、になると、itemsコレクションが列挙されます。

ラインは

var option1 = items.Select(item => new MyClass(item)).Cast<IMyClass>().ToList() 

両者の唯一の違いは、最初の2つの機能は、アイテムごとに呼び出す必要があることである

var option1 = items.Select(item => new MyClass(item)).Select(x => (IMyClass)x).ToList() 

に相当する(C#が、何とかラムダをインライン化しない限り、どのI信じてはいけない)、2番目のオプションは1つだけ必要です。

個人的には、私はスタイルの問題として2番目のものと一緒に行きます。

+0

+1。私の個人的な理由は2つです。私はそのような意味で「キャスト」が好きではありません。それは、コレクションに入れるアイテムを決めることができなかったことを示しています。多くの場合、 'List 'の特別なタイプが必要ない場合は、 'IEnumerable 'が必要な場所で 'IEnumerable 'を使うことができるので、実際にはキャストが必要な場合があります。 。 –

1

あなたが使用しているのはどちらかといえば、私たちが本当にあなたに答えられないものです。

あなたの直感が正しい場合、Castはループに2番目の反復レイヤを追加します。それは非常にマイナーだ、と私はそれがパフォーマンスの測定可能な差異が生成されます疑うが、Cast方法は、基本的にこれを行い、新たなIEnumerableオブジェクトを返します。

foreach (object obj in source) yield return (TResult)obj; 

効果は、主にコールスタック上の別のレベルです。 yieldを使用しているため、ほとんどの他の方法のようにオンデマンドでのみ反復処理します。IEnumerableしかし、イテレータ状態の代わりに2つのレベルのイテレータ状態を返さなければなりません。それがあなたにとって重要かどうかは、あなた自身のアプリケーションのために測定する必要があるものです。

は、(また、少なくともリファレンスソースによると、それはキャストが無効な場合例外をスローする可能性があり危険なキャストを、ない、ということに注意してください。それはあなたのオプション#2を好むもう一つの理由です。)

1

あなたは常にあなたの選択に明示的な型の引数を提供することができます

var option2 = items.Select<IItem,IMyClass>(item => new MyClass(item)).ToList(); 

ここで、IItemは、アイテムをキャストできる型またはインターフェイスです。

関連する問題