IEnumerable< T>にアイテムを追加するにはどうすればよいですか?コレクション?
-
06-07-2019 - |
質問
上記のタイトルとしての私の質問。たとえば、
IEnumerable<T> items = new T[]{new T("msg")};
items.ToList().Add(new T("msg2"));
ただし、内部には1つのアイテムしかありません。
items.Add(item)
のようなメソッドを使用できますか?
List&lt; T&gt;
のように
解決
できません。 IEnumerable&lt; T&gt;
は、アイテムを追加できるコレクションを必ずしも表すとは限らないためです。実際、必ずしもコレクションを表すとは限りません!例:
IEnumerable<string> ReadLines()
{
string s;
do
{
s = Console.ReadLine();
yield return s;
} while (s != "");
}
IEnumerable<string> lines = ReadLines();
lines.Add("foo") // so what is this supposed to do??
ただし、できることは、新しい IEnumerable
オブジェクト(指定されていないタイプ)を作成することです。これは、列挙されると、古いアイテムをすべて提供し、プラスあなた自身のいくつか。そのために Enumerable.Concat
を使用します:
items = items.Concat(new[] { "foo" });
この配列オブジェクトは変更されません(とにかくアイテムを配列に挿入することはできません)。ただし、配列内のすべての項目をリストする新しいオブジェクトを作成し、「Foo」を作成します。さらに、その新しいオブジェクトは、配列の変更を追跡します(つまり、列挙するたびに、アイテムの現在の値が表示されます)。
他のヒント
タイプ IEnumerable&lt; T&gt;
は、このような操作をサポートしていません。 IEnumerable&lt; T&gt;
インターフェースの目的は、消費者がコレクションのコンテンツを表示できるようにすることです。値を変更しないでください。
.ToList()。Add()などの操作を実行すると、新しい List&lt; T&gt;
を作成し、そのリストに値を追加します。元のリストへの接続はありません。
できることは、拡張機能の追加メソッドを使用して、値が追加された新しい IEnumerable&lt; T&gt;
を作成することです。
items = items.Add("msg2");
この場合でも、元の IEnumerable&lt; T&gt;
オブジェクトは変更されません。これは、参照を保持することで確認できます。例
var items = new string[]{"foo"};
var temp = items;
items = items.Add("bar");
この一連の操作の後、変数tempは、単一の要素&quot; foo&quot;を持つ列挙可能なもののみを参照します。アイテムは値&quot; foo&quot;を持つ異なる列挙型を参照しますが、および「バー」。
編集
Addは、 IEnumerable&lt; T&gt;
の典型的な拡張メソッドではないことを常に忘れてしまいます。これは、Addが最初に定義するものの1つだからです。ここにあります
public static IEnumerable<T> Add<T>(this IEnumerable<T> e, T value) {
foreach ( var cur in e) {
yield return cur;
}
yield return value;
}
ICollection&lt; T&gt;
の使用を検討しましたかまたは IList&lt; T&gt;
インターフェースではなく、 IEnumerable&lt; T&gt;
に Add
メソッドを持たせたいという理由で存在します。
IEnumerable&lt; T&gt;
は、実際の基本オブジェクトが追加/サポートをサポートするかどうかを必ずしも保証せずに、タイプを...まあ、列挙可能、または単なるアイテムのシーケンスとして「マーク」するために使用されますアイテムの削除。また、これらのインターフェイスは IEnumerable&lt; T&gt;
を実装しているため、 IEnumerable&lt; T&gt;
で取得するすべての拡張メソッドも取得することに注意してください。
IEnumerable
および IEnumerable&lt; T&gt;
のいくつかの短い、甘い拡張メソッドは私のためにそれを行います:
public static IEnumerable Append(this IEnumerable first, params object[] second)
{
return first.OfType<object>().Concat(second);
}
public static IEnumerable<T> Append<T>(this IEnumerable<T> first, params T[] second)
{
return first.Concat(second);
}
public static IEnumerable Prepend(this IEnumerable first, params object[] second)
{
return second.Concat(first.OfType<object>());
}
public static IEnumerable<T> Prepend<T>(this IEnumerable<T> first, params T[] second)
{
return second.Concat(first);
}
エレガント(非汎用バージョンを除く)。残念なことに、これらのメソッドはBCLに含まれていません。
いいえ、IEnumerableはアイテムの追加をサポートしていません。
「代替」とは:
var List = new List(items);
List.Add(otherItem);
.net Coreには、まさにそれを行う Enumerable.Append
というメソッドがあります。
メソッドのソースコードは GitHubで利用可能。 ....実装(他の回答の提案よりも洗練されている)は一見の価値があります:)。
必要な2番目のメッセージを追加するには-
IEnumerable<T> items = new T[]{new T("msg")};
items = items.Concat(new[] {new T("msg2")})
自分のようにアイテムを追加できるだけでなく、既存のアイテムがある List&lt; T&gt;
(または他のほとんどの非読み取り専用コレクション)にアイテムを追加した場合列挙子は無効になります(それ以降は InvalidOperationException
がスローされます)。
何らかのタイプのデータクエリの結果を集計する場合は、 Concat
拡張メソッドを使用できます:
編集:私はもともと、この例では Union
拡張機能を使用していましたが、実際には正しくありません。私のアプリケーションは、重複するクエリが結果を重複させないように、それを広範囲に使用しています。
IEnumerable<T> itemsA = ...;
IEnumerable<T> itemsB = ...;
IEnumerable<T> itemsC = ...;
return itemsA.Concat(itemsB).Concat(itemsC);
ちょうどここに来て、 Enumerable.Concat
拡張メソッドとは別に、.NET Core 1.1.1には Enumerable.Append
という名前の別のメソッドがあるようです。後者では、単一のアイテムを既存のシーケンスに連結できます。したがって、Aamolの答えは次のように書くこともできます
IEnumerable<T> items = new T[]{new T("msg")};
items = items.Append(new T("msg2"));
それでも、この関数は入力シーケンスを変更せず、指定されたシーケンスと追加されたアイテムをまとめるラッパーを返すだけであることに注意してください。
他の人は、 IEnumerable
にアイテムを追加できない(できない)理由について既に素晴らしい説明をしています。コレクションを表すインターフェイスへのコーディングを継続し、addメソッドが必要な場合にのみ、 ICollection
または IList
。追加の大当たりとして、これらのインターフェイスは IEnumerable
を実装します。
これを行うことができます。
//Create IEnumerable
IEnumerable<T> items = new T[]{new T("msg")};
//Convert to list.
List<T> list = items.ToList();
//Add new item to list.
list.add(new T("msg2"));
//Cast list to IEnumerable
items = (IEnumerable<T>)items;
それを行う最も簡単な方法は単純です
IEnumerable<T> items = new T[]{new T("msg")};
List<string> itemsList = new List<string>();
itemsList.AddRange(items.Select(y => y.ToString()));
itemsList.Add("msg2");
IEnumerableインターフェイスを実装しているため、IEnumerableとしてリストを返すことができます
もちろん、次のことができます(私はあなたのTビジネスを脇に置きます):
public IEnumerable<string> tryAdd(IEnumerable<string> items)
{
List<string> list = items.ToList();
string obj = "";
list.Add(obj);
return list.Select(i => i);
}