コードは以下のようになります:
namespace Test
{
public interface IMyClass
{
List<IMyClass> GetList();
}
public class MyClass : IMyClass
{
public List<IMyClass> GetList()
{
return new List<IMyClass>();
}
}
}
コード分析を実行すると、次の推奨事項が表示されます。
警告 3 CA1002: Microsoft.Design: 'IMyClass.GetList()' の 'List' を Collection、ReadOnlyCollection、または KeyedCollection を使用するように変更してください
これを修正するにはどうすればいいでしょうか、またここでの良い方法は何でしょうか?
ベストアンサー1
なぜそうしないのかという質問の「なぜ」の部分に答えるためにList<T>
その理由は、将来性があり、API がシンプルだからです。
将来を見据えた
List<T>
サブクラス化によって簡単に拡張できるようには設計されていません。内部実装が高速になるように設計されているのです。メソッドは仮想ではないためオーバーライドできず、フックも存在しません。Add
/Insert
/Remove
オペレーション。
つまり、将来コレクションの動作を変更する必要がある場合 (たとえば、ユーザーが追加しようとする null オブジェクトを拒否したり、これが発生したときにクラスの状態を更新するなどの追加作業を実行したりする場合)、返すコレクションのタイプをサブクラス化できるものに変更する必要があります。これは、インターフェイスの変更による互換性の喪失になります (もちろん、null を許可しないなどのセマンティクスの変更もインターフェイスの変更になる可能性がありますが、内部のクラス状態の更新などは変更にはなりません)。
したがって、簡単にサブクラス化できるクラスを返すことで、Collection<T>
または次のようなインターフェースIList<T>
、ICollection<T>
またはIEnumerable<T>
内部実装をニーズに合わせて別のコレクション型に変更できます。その場合、期待する型を返すことができるため、コンシューマーのコードが壊れることはありません。
APIのシンプルさ
List<T>
次のような便利な操作が多数含まれていますBinarySearch
、Sort
などなど。ただし、これが公開するコレクションである場合、リストのセマンティクスを制御するのはユーザーであり、コンシューマーではない可能性があります。したがって、クラスが内部的にこれらの操作を必要とする場合でも、クラスのコンシューマーがそれらを呼び出すことを望む (または呼び出す必要がある) 可能性は非常に低くなります。
したがって、よりシンプルなコレクション クラスまたはインターフェイスを提供することで、API のユーザーに表示されるメンバーの数が減り、ユーザーが使いやすくなります。