Programming

IEnumerable에 항목을 추가하는 방법

procodes 2020. 2. 26. 22:43
반응형

IEnumerable에 항목을 추가하는 방법 수집?


위의 제목으로 내 질문입니다. 예를 들어

IEnumerable<T> items = new T[]{new T("msg")};
items.ToList().Add(new T("msg2"));

그러나 결국에는 1 개의 항목 만 있습니다.

우리는 같은 방법을 가질 수 있습니까 items.Add(item)?

같은 List<T>


IEnumerable<T>항목을 추가 할 수있는 컬렉션을 반드시 나타내지는 않기 때문에 할 수 없습니다 . 사실, 반드시 컬렉션을 나타내는 것은 아닙니다! 예를 들면 다음과 같습니다.

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<T>이 이러한 작업을 지원하지 않습니다. IEnumerable<T>인터페이스 의 목적은 소비자가 컬렉션의 내용을 볼 수 있도록하는 것입니다. 값을 수정하지 마십시오.

.ToList (). Add ()와 같은 작업을 수행하면 새 List<T>목록을 만들고 해당 목록에 값을 추가합니다. 원래 목록에 연결되어 있지 않습니다.

할 수있는 작업은 확장 추가 방법을 사용하여 추가 IEnumerable<T>된 값으로 새로 작성하는 것 입니다.

items = items.Add("msg2");

이 경우에도 원본 IEnumerable<T>객체 는 수정되지 않습니다 . 참조를 보유하여 확인할 수 있습니다. 예를 들어

var items = new string[]{"foo"};
var temp = items;
items = items.Add("bar");

이 작업 집합 후에도 변수 temp는 값 집합에서 단일 요소 "foo"를 가진 열거 형 만 참조하지만 항목은 "foo"및 "bar"값을 가진 다른 열거 형을 참조합니다.

편집하다

나는 Add가 일반적인 확장 방법이 아니라는 것을 잊어 버렸 IEnumerable<T>습니다. 여기있어

public static IEnumerable<T> Add<T>(this IEnumerable<T> e, T value) {
  foreach ( var cur in e) {
    yield return cur;
  }
  yield return value;
}

ICollection<T>또는 IList<T>인터페이스를 대신 사용해 보셨습니까? 또는 Add메소드 를 사용하려는 이유가 있습니다 IEnumerable<T>.

IEnumerable<T>실제 기본 개체가 항목 추가 / 제거를 지원하는지 여부를 반드시 보장하지 않고 유형을 '잘 표시, 열거 가능 또는 일련의 항목으로'표시 '하는 데 사용됩니다. 또한 이러한 인터페이스는 구현 IEnumerable<T>되어 있으므로 모든 확장 방법을 사용할 수 IEnumerable<T>있습니다.


몇 가지 짧고 달콤한 확장 방법이 IEnumerable있고 IEnumerable<T>나를 위해합니다.

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에서 사용할 수 있습니다. .... 구현 (다른 답변의 제안보다 더 정교함)은 가치가 있습니다. :).


두 번째 메시지를 추가하려면-

IEnumerable<T> items = new T[]{new T("msg")};
items = items.Concat(new[] {new T("msg2")})

상태와 같은 항목을 추가 할 수있을뿐만 아니라 List<T>기존 열거자가 있는 항목 (또는 거의 다른 비 읽기 전용 컬렉션)에 항목을 추가 하면 열거자가 무효화됩니다 ( InvalidOperationException그때부터 던져 집니다).

일부 유형의 데이터 쿼리에서 결과를 집계하는 경우 Concat확장 방법을 사용할 수 있습니다 .

편집 : 원래 Union예제 에서 확장명을 사용했지만 실제로는 올바르지 않습니다. 내 응용 프로그램은 광범위하게 사용하여 겹치는 쿼리가 결과를 복제하지 않도록합니다.

IEnumerable<T> itemsA = ...;
IEnumerable<T> itemsB = ...;
IEnumerable<T> itemsC = ...;
return itemsA.Concat(itemsB).Concat(itemsC);

Enumerable.Concat확장 방법 외에도 Enumerable.Append.NET Core 1.1.1에 다른 방법이있는 것 같습니다 . 후자는 단일 항목을 기존 순서에 연결할 수 있습니다. 따라서 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-business를 제쳐두고 있습니다) :

public IEnumerable<string> tryAdd(IEnumerable<string> items)
{
    List<string> list = items.ToList();
    string obj = "";
    list.Add(obj);

    return list.Select(i => i);
}

참고 URL : https://stackoverflow.com/questions/1210295/how-can-i-add-an-item-to-a-ienumerablet-collection



반응형