2012-01-12 4 views
2

私は会社で働いていて、ここでは比較的新しいですが、何か非常に奇妙なものがあります。 C#でもっと知っている人は、「物事を特別なやり方でやる」よりも。だから私は、私が説明しようとしていることをする理由を考えて、疑念の恩恵を与えようとしているが、私は何も考え出すことができない。C#ダウンキャスティングIListの "特別な戦術"リスト

上記ラインが問題の核心である

IList<Facility> Facilities = new List<Facility>();

...すべてのコードを通して他の奇妙はいくつかのインターフェイスを使用することができないことから来るため、データは、に戻ってコピーしなければなりませんリストを使用する前に(例えば、webservice経由でのエクスポートはインターフェイスを使用できません。IListの実装である必要があります)

ここでは、インターフェイスが素晴らしいと思っています。あなたのメソッドに渡されているインプリメンテーションに存在するインタフェースですが、...

誰かが私をここで助けてもらえますか?だれでも、アプリケーションのデータレイヤーのインターフェイスにリストを即座にダウンキャストしようと思っている人はいますか?

これらのリストは、互換性のあるデータ型にも使用されていません。これは、Listが定義されて格納されている場所に格納され、格納されているデータ型ごとにIListが存在します。

ありがとうございます!

答えて

6

階層内の可能な限り高いクラスで作業することをお勧めします。だから、あなただけが唯一のIEnumerable<T>を公開する必要がある値をループする必要がある場合:

IEnumerable<Facility> Facilities = new List<Facility>(); 
// now you can foreach over the facilities or chain with LINQ 

あなたはインデクサアクセスが必要な場合はあなたが可能な限り最高のクラス/インタフェースを暴露後ろIList<Facility>

IList<Facility> Facilities = new List<Facility>(); 
// in addition to looping now you can access facilities by index 
// and you can also add and remove facilities 

アイデアを使用することができますいくつかのAPIを設計する際の階層は、List<T>を使用している実装の詳細を隠す方法です。明日、APIのコンシューマーと契約した契約を実装するHyperSpecialListWhichIsVeryFast<T>を発明した場合、このコンシューマーはコード内で何も変更する必要はありません。彼は気にしない。彼はIEnumerable<T>で作業します。なぜなら、彼が必要とするのは、たとえばループするだけだからです。あなたの新しいリストのおかげで、彼のコードは何も変更する必要なく速く実行されます。

しかし、今歴史の本にあるラ.NET 1.0緩やかに型付けされたコレクションà非ジェネリックを使用すると、ブードゥー教の魔法のようなものです:

IList Facilities = new List<Facility>(); 

が、これは有用であろう、なぜ何らかの理由を考えることはできません。非ジェネリック版にダウンキャストすると、基になるタイプTにアクセスするためにクライアントが強制的にキャストされます。このようにして、彼はジェネリックが提供するコンパイル時の安全性をすべて失っています。

+0

奇妙なことに、彼らはIListにダウンキャストされ、IListではなく、()です。 – ivowiblo

+0

が合意しました!私はテンプレート版を使用していますが、一般版は使用しません! –

+0

@ivowiblo、はい、それは変です。人がこれをやる理由がないとは思いません。 –

1

あなたがFacilities変数をどのように消費するかについては、すべてです。 IList(そのインタフェースで定義されているメソッドだけを呼び出すつもりである)としてオペレーティングする場合は、そのメソッドを呼び出すことを試みないようにその変数を宣言するのが妥当ですではなく、そのインターフェイスで定義されているです。このようにして、使用するデータ構造をIListの別の実装に簡単に置き換えることができます。

私自身は、特に必要がない限り、非ジェネリック版の使用を避けます。 (つまり、IListの代わりにIList<Facility>を使用します)非ジェネリックバージョン(コード内の他の場所)を使用する可能性のあるシナリオは、明らかに他のコードがFacilityについて何も知らないことを要求しないということです。オブジェクトの一般的なリストとして一覧表示します。

+0

IMHO、IList は非ジェネリックな '' IList'を継承しません。非汎用バージョンが読み取り専用の実装であれば、安全に行うことができます。そうすることで、 'IEnumerable 'を受け入れるコードが、渡された' IList 'の' Count'プロパティにアクセスできるようになります。 – supercat

+0

これは問題です...すべてがIList として保存されていますが、Webサービスでエクスポートするために使用されるコード内の他の場所では、データはIList からリストにコピーされます –

0

必要なクラスのすべてのメンバーを含むインターフェースを持っている場合は、コンストラクター呼び出しと静的メソッドを除いて、クラスを使用するすべての場所でインターフェースを使用することにはあまり問題はありませんクラス(*)を使用する必要があります)。クラスの代わりにインターフェイスを使用することに伴う最大の問題は、それを行う最大の理由です。インターフェイスを指定するコードは、クラスを使用するコードで面倒なインターフェイスになることがよくあります。将来的にインタフェースを使用する必要がある可能性がある場合は、get-goからそうすることで、あとで潜在的に厄介なリファクタリング・ジョブを避けることができます。

(*)私はdruthersを持っていた場合、インターフェイスは宣言インターフェイスIFooは、それがfooで「提携」でした指定された場合、IFoo.Bar()Foo.Bar()と同等になるよう、コンストラクタや静的メソッドで使用するクラスを指定することができますnew IFoo(3)new Foo(3) 'に相当します。残念ながら、そのような機能は存在しません。もしそうなら、私はインターフェイスがずっと一貫して使われるだろうと思っています。

関連する問題