[解決済み] IList<T>を返すのは、T[]やList<T>を返すのより悪いのか?
質問
このような質問に対する回答です。 List<T> またはIList<T> は、コレクションの具体的な実装を返すよりもインターフェイスを返す方が良いということに常に同意しているようです。しかし、私はこれに悩んでいます。インターフェイスのインスタンス化は不可能なので、メソッドがインターフェイスを返していても、実は具体的な実装を返していることになります。これについては、小さなメソッドを2つ書いてちょっと実験してました。
public static IList<int> ExposeArrayIList()
{
return new[] { 1, 2, 3 };
}
public static IList<int> ExposeListIList()
{
return new List<int> { 1, 2, 3 };
}
そして、それらを私のテストプログラムで使用します。
static void Main(string[] args)
{
IList<int> arrayIList = ExposeArrayIList();
IList<int> listIList = ExposeListIList();
//Will give a runtime error
arrayIList.Add(10);
//Runs perfectly
listIList.Add(10);
}
どちらの場合も、新しい値を追加しようとすると、コンパイラは何のエラーも出しませんが、明らかに配列を
IList<T>
として公開するメソッドでは、何かを追加しようとするとランタイムエラーが発生します。
つまり、私のメソッドで何が起こっているのか知らない人が、それに値を追加しなければならない場合、まず最初に私の
IList
を
List
に追加することで、エラーのリスクを負わずに値を追加することができます。もちろん、タイプチェックを行い、相手が
List
を扱っているのか、それとも
Array
を使うことができますが、もしそうせずに、コレクションにアイテムを追加したい場合は
をコピーする以外に方法がないのです。
IList
を
List
であったとしても
List
. 配列は決して
IList
?
私のもうひとつの懸念は、受け入れ可能な回答である リンクされた質問 (強調) に基づいています。
<ブロッククオート他の人が使うライブラリを通してクラスを公開する場合。 の場合、一般的には具象実装よりもインターフェースを通して公開したいものです。 これは、後でクラスの実装を変更して別の具象クラスを使用することにした場合に役立ちます。この場合、インターフェイスは変更されないので、ライブラリのユーザはコードを更新する必要がありません。
内部で使うだけであれば、それほど気にすることもなく、Listを使ってもいいかもしれません。
誰かが実際に私の
IList<T>
から取得した
ExposeListIlist()
メソッドから取得した値を、そのまま追加/削除しています。すべてうまくいきます。しかし、今、回答が示唆するように、インターフェースを返すことはより柔軟なので、私はリストの代わりに配列を返します(私の側では問題はありません!)、そして、彼らは治療のためにあります...。
TLDRです。
1) インターフェイスを公開すると不要なキャストが発生する?それは問題ないのでしょうか?
2) ライブラリのユーザがキャストを使用しない場合、メソッドを変更すると、メソッドは全く問題なく残っているにもかかわらず、彼らのコードが壊れることがあります。
考えすぎかもしれませんが、インターフェイスを返すことが実装を返すことより好ましいという一般的なコンセンサスは得られません。
どのように解決するのですか?
これはあなたの質問に直接答えるものではないかもしれませんが、.NET 4.5+では、公開または保護されたAPIを設計するときに、私はこれらのルールに従うことを好んでいます。
-
を返します。
IEnumerable<T>
もし、列挙しかできない場合は -
を返す
IReadOnlyCollection<T>
列挙と項目数の両方が利用可能である場合。 -
を返す
IReadOnlyList<T>
もし、列挙、アイテム数、インデックス付きアクセスが可能であれば。 -
を返す
ICollection<T>
enumeration、items count、modificationが利用可能な場合。 -
を返す
IList<T>
もし、列挙、アイテム数、インデックス付きアクセス、修正などが可能であれば。
最後の2つのオプションは、メソッドが配列を返してはならないことを前提としています。
IList<T>
の実装として配列を返してはいけないと仮定しています。
関連
-
[解決済み] エンティティタイプ <type> は、現在のコンテキストのモデルの一部ではありません。
-
[解決済み】Visual Studio: 操作を完了できませんでした。パラメータが正しくありません
-
[解決済み】OnCollisionEnter2Dが実行されない?
-
[解決済み] なぜList<T>を継承しないのですか?
-
[解決済み] \0-9]よりも効率が悪い
-
[解決済み] IList<string> または IEnumerable<string> からカンマ区切りリストを作成する。
-
[解決済み] Distinct() with lambda?
-
[解決済み] C#4 インターフェースで定義されたオプションパラメータは、なぜ実装クラスで強制されないのですか?
-
[解決済み] IListを使用する場合とListを使用する場合について
-
[解決済み] なぜIListやListを使うのか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】Ajax処理で「無効なJSONプリミティブ」と表示される件
-
[解決済み】「入力文字列が正しい形式ではありませんでした」エラーの解決方法は?[重複しています]。
-
[解決済み】「namespace x already contains a definition for x」エラーの修正方法は?VS2010にコンバートした後に発生しました。
-
[解決済み】WSACancelBlockingCallの例外について
-
[解決済み】2つ(またはそれ以上)のリストを1つに統合する(C# .NETで
-
[解決済み】2年前のMSDateを把握する【クローズド
-
[解決済み】「namespace」なのに「type」のように使われる。
-
[解決済み】Microsoft.Extensions.LoggingからILoggerを解決することができない
-
[解決済み] List<T> または IList<T> [終了しました]。
-
[解決済み] なぜ配列はIListを実装しているのか?