のAddRange()
方法はありませんIList<T>
。
アイテムをIList<T>
繰り返し処理したり、Add()
メソッドを使用したりせずに、アイテムのリストをに追加するにはどうすればよいですか?
のAddRange()
方法はありませんIList<T>
。
アイテムをIList<T>
繰り返し処理したり、Add()
メソッドを使用したりせずに、アイテムのリストをに追加するにはどうすればよいですか?
回答:
AddRange
List<T>
インターフェイスではなく、で定義されます。
にアクセスするために、変数をのList<T>
代わりに宣言するか、変数をIList<T>
キャストList<T>
することができますAddRange
。
((List<myType>)myIList).AddRange(anotherList);
はそうではないIList<T>
かもしれないので、これは良い習慣ではありません(以下のコメントを参照)List<T>
が、インターフェースを実装し、AddRange
メソッドを持たない可能性がある他のタイプ-そのような場合、コードがスローするときだけわかります実行時の例外。
したがって、タイプが実際にaであることが確実にわかっている場合を除いて、List<T>
を使用しようとしないでくださいAddRange
。
これを行う1つの方法は、isまたはas演算子を使用して型をテストすることです(C#7以降)。
if(myIList is List<T>)
{
// can cast and AddRange
}
else
{
// iterate with Add
}
List<T>
(または、これが適切でない場合AddRange
は、ローカライズされた状態に保つ必要がある場所でキャストを行います-これは非常に低コストの操作です)。
InvalidCastException
、List<T>
(たとえば、配列)以外で使用された場合のようなものを明らかにスローするからです。
Listのc#ソースコードを見ると、List.AddRange()には、単純なループでは対処できない最適化があると思います。したがって、拡張メソッドは、IListがリストであるかどうかを確認するだけでよく、リストである場合は、ネイティブのAddRange()を使用する必要があります。
ソースコードをざっと見てみると、.NETの人々は.ToList()などの独自のLinq拡張機能で同様のことを行っています(リストの場合はキャストします...それ以外の場合は作成します)。
public static class IListExtension
{
public static void AddRange<T>(this IList<T> list, IEnumerable<T> items)
{
if (list == null) throw new ArgumentNullException(nameof(list));
if (items == null) throw new ArgumentNullException(nameof(items));
if (list is List<T> asList)
{
asList.AddRange(items);
}
else
{
foreach (var item in items)
{
list.Add(item);
}
}
}
}
list
にList<T>
2回キャストしています。そのうちの1つは、as
キーワードを使用して最適化できます。
if (list is List<T> castedList) { castedList.AddRange(items); }
あなたはこのようなことをすることができます:
IList<string> oIList1 = new List<string>{"1","2","3"};
IList<string> oIList2 = new List<string>{"4","5","6"};
IList<string> oIList3 = oIList1.Concat(oIList2).ToList();
したがって、基本的にはConcat()
拡張機能を使用ToList()
して、と同様の機能を取得しAddRange()
ます。
Enumerable.Concat
によって実装されSystem.Linq.Enumerable
、そのメソッドの戻り値がIEnumerable<TSource>
であるため、キャストバックすべきではないとIList<TSource>
思います-ソースコードをチェックせずに実装の詳細がわからないため、何か他のものを返す可能性があります-ただし、変更されないという保証はありません。したがって、複数の.NETバージョンをサポートする場合は、特別な注意を払う必要があります。
次のような拡張メソッドを作成することもできます。
internal static class EnumerableHelpers
{
public static void AddRange<T>(this IList<T> collection, IEnumerable<T> items)
{
foreach (var item in items)
{
collection.Add(item);
}
}
}
使用法:
IList<int> collection = new int[10]; //Or any other IList
var items = new[] {1, 4, 5, 6, 7};
collection.AddRange(items);
これはまだアイテムを反復処理していますが、呼び出すたびに反復を記述したりキャストしたりする必要はありません。
Concat
@Self_Taught_Programmerが回答したように、キャストするかLINQを使用します。