[解決済み] なぜIListやListを使うのか?
質問
この件に関して多くの投稿があることは知っていますが、なぜIListのようなインターフェースを渡して、具象リストではなくIListのようなインターフェースを返さなければならないのか、まだ混乱しています。
私は、これが後で実装を変更することを容易にするという多くの投稿を読みましたが、私はそれがどのように機能するのか完全に理解していません。
もし私がこのメソッドを持っているとします。
public class SomeClass
{
public bool IsChecked { get; set; }
}
public void LogAllChecked(IList<SomeClass> someClasses)
{
foreach (var s in someClasses)
{
if (s.IsChecked)
{
// log
}
}
}
IListを使うことで、今後どのように役に立つのかがよくわかりません。
すでにメソッドの中にいる場合はどうでしょうか?やはりIListを使うべきでしょうか?
public void LogAllChecked(IList<SomeClass> someClasses)
{
//why not List<string> myStrings = new List<string>()
IList<string> myStrings = new List<string>();
foreach (var s in someClasses)
{
if (s.IsChecked)
{
myStrings.Add(s.IsChecked.ToString());
}
}
}
IListを使うことで何が得られるのでしょうか?
public IList<int> onlySomeInts(IList<int> myInts)
{
IList<int> store = new List<int>();
foreach (var i in myInts)
{
if (i % 2 == 0)
{
store.Add(i);
}
}
return store;
}
今はどうでしょうか?intのリストについて、何か新しい実装があり、それを変更する必要があるのでしょうか?
基本的に、私は IList を使用することで、単に List をすべてに取り込むよりも何らかの問題を解決できたという、いくつかの実際のコード例を見てみる必要があります。
私の読みでは、私はちょうどものを通してループしているので、私はIListの代わりにIEnumberableを使用することができたと思う。
編集 私はこれを行う方法について、いくつかの私のメソッドで遊んでいました。私はまだ戻り値の型(私がそれをより具体的またはインターフェイスに作るべきかどうか)について確信が持てません。
public class CardFrmVm
{
public IList<TravelFeaturesVm> TravelFeaturesVm { get; set; }
public IList<WarrantyFeaturesVm> WarrantyFeaturesVm { get; set; }
public CardFrmVm()
{
WarrantyFeaturesVm = new List<WarrantyFeaturesVm>();
TravelFeaturesVm = new List<TravelFeaturesVm>();
}
}
public class WarrantyFeaturesVm : AvailableFeatureVm
{
}
public class TravelFeaturesVm : AvailableFeatureVm
{
}
public class AvailableFeatureVm
{
public Guid FeatureId { get; set; }
public bool HasFeature { get; set; }
public string Name { get; set; }
}
private IList<AvailableFeature> FillAvailableFeatures(IEnumerable<AvailableFeatureVm> avaliableFeaturesVm)
{
List<AvailableFeature> availableFeatures = new List<AvailableFeature>();
foreach (var f in avaliableFeaturesVm)
{
if (f.HasFeature)
{
// nhibernate call to Load<>()
AvailableFeature availableFeature = featureService.LoadAvaliableFeatureById(f.FeatureId);
availableFeatures.Add(availableFeature);
}
}
return availableFeatures;
}
今、私はIListを返しています。これは、このようなプロパティを持っている私のドメインモデルにこれを追加するという単純な事実のためです。
public virtual IList<AvailableFeature> AvailableFeatures { get; set; }
上記は、nhibernateで使うのが標準のようなので、IListそのものを使用しています。そうでなければ、IEnumberableを返したかもしれませんが、よくわかりません。それでも、ユーザーが100%必要とするものは何なのかがわからない(そこがconcreteを返すことの優位性)。
編集 2
また、メソッド内で参照渡しを行いたい場合はどうなるのでしょうか?
private void FillAvailableFeatures(IEnumerable<AvailableFeatureVm> avaliableFeaturesVm, IList<AvailableFeature> toFill)
{
foreach (var f in avaliableFeaturesVm)
{
if (f.HasFeature)
{
// nhibernate call to Load<>()
AvailableFeature availableFeature = featureService.LoadAvaliableFeatureById(f.FeatureId);
toFill.Add(availableFeature);
}
}
}
は、これで問題が発生するでしょうか?配列(固定サイズ)を渡すことはできないのでしょうか?それは多分具体的なリストのために良いですか?
どのように解決するのですか?
ここでは3つの疑問があります。正式なパラメータにはどのような型を使うべきでしょうか?ローカル変数には何を使うべきか? そして戻り値の型には何を使うべきか?
フォーマルパラメータです。
ここでの原則は
必要以上のものを要求しない
.
IEnumerable<T>
は "このシーケンスの要素を最初から最後まで取得する必要がある" を伝える。
IList<T>
は "このシーケンスの要素を任意の順序で取得・設定したい" を伝えます。
List<T>
は "私は任意の順序でこのシーケンスの要素を取得および設定する必要があり、私はリストのみを受け付けます; 私は配列を受け付けません。
必要以上のものを要求することで、(1)あなたの不必要な要求を満たすために呼び出し側に不必要な作業をさせる、(2)読み手に虚偽を伝えることになります。 自分が使う分だけを要求しましょう。そうすれば、呼び出し側がシーケンスを持っている場合、あなたの要求を満たすためにその上でToListを呼び出す必要はありません。
ローカル変数。
好きなものを使ってください。それはあなたのメソッドです。メソッドの内部実装の詳細を見ることができるのはあなただけです。
戻り値の型です。
前と同じ原理で、逆になっています。
呼び出し元が必要とする最低限のものを提供する。
呼び出し元がシーケンスを列挙する機能だけを要求している場合、彼らにだけ
IEnumerable<T>
.
関連
-
[解決済み] メンバー '<メンバー名>' にインスタンス参照でアクセスできない
-
[解決済み】「...は'型'であり、与えられたコンテキストでは有効ではありません」を解決するにはどうすればよいですか?(C#)
-
[解決済み】Moqを使用してメソッド呼び出しを検証する
-
[解決済み】WSACancelBlockingCallの例外について
-
[解決済み] IDisposable インターフェースの正しい使用法
-
[解決済み] なぜList<T>を継承しないのですか?
-
[解決済み] EqualsメソッドがオーバーライドされたときにGetHashCodeをオーバーライドすることが重要な理由は何ですか?
-
[解決済み] C#でHashtableよりDictionaryが好まれる理由とは?
-
[解決済み] IList<string> または IEnumerable<string> からカンマ区切りリストを作成する。
-
[解決済み】なぜFunc<T>ではなくExpression<Func<T>を使うのですか?
最新
-
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 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】エラー。「戻り値を変更できません」 C#
-
[解決済み] エンティティタイプ ApplicationUser は、現在のコンテキストのモデルの一部ではありません。
-
解決済み] Critical error detected c0000374 - C++ dll returns pointer off allocated memory to C# [解決済み] Critical error detected c0000374 - C++ dll returns pointer off allocated memory to C#.
-
[解決済み】Unity3DでOnTriggerEnterが動作しない件
-
[解決済み】クロススレッド操作が有効でない。作成されたスレッド以外のスレッドからアクセスされたコントロール
-
[解決済み] [Solved] アセンブリ System.Web.Extensions dll はどこにありますか?
-
[解決済み】ファイルへの読み書きの際に共有違反のIOExceptionが発生する C#
-
[解決済み] 2つのリストを結合する
-
[解決済み】エラー「必要なフォーマルパラメータに対応する引数が与えられていない」を解決する?
-
[解決済み】別のスレッドがこのオブジェクトを所有しているため、呼び出し側のスレッドはこのオブジェクトにアクセスできない