[C#] IEnumerable <T> 컬렉션에 항목을 추가하려면 어떻게해야합니까?

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

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 (!string.IsNullOrEmpty(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에없는 것이 너무 나쁩니다.


답변

.net Core Enumerable.Append에는 정확히 그렇게 하는 방법 이 있습니다.

메소드의 소스 코드는 GitHub에서 사용할 수 있습니다. …. 구현 (다른 답변의 제안보다 더 정교함)은 가치가 있습니다 :).


답변

IEnumerable은 항목 추가를 지원하지 않습니다.

‘대체’는 다음과 같습니다.

var List = new List(items);
List.Add(otherItem);


답변

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

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