سؤال

سؤالي كما في العنوان أعلاه.على سبيل المثال ،

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" });

وهذا <م> لن يغير من وجوه مجموعة (لا يمكنك إدراج العناصر في صفائف، على أي حال). ولكن فإنه سيتم إنشاء الكائن الجديد الذي سيتم سرد كافة العناصر في المصفوفة، ثم "فو". وعلاوة على ذلك، هذا الكائن الجديد <م> تتبع التغييرات في مجموعة (أي كلما تعداد ذلك، سترى القيم الحالية للمادة).

نصائح أخرى

نوع IEnumerable<T> لا يدعم هذه العمليات.الغرض من IEnumerable<T> واجهة هو السماح المستهلك لعرض محتويات المجموعة.لا تعديل القيم.

عند القيام بعمليات مثل .ToList().إضافة() أنت خلق جديد List<T> وإضافة قيمة إلى تلك القائمة.فإنه لا يوجد لديه اتصال القائمة الأصلية.

ما يمكنك القيام به هو استخدام إضافة امتداد طريقة لخلق جديد IEnumerable<T> مع القيمة المضافة.

items = items.Add("msg2");

حتى في هذه الحالة فإنه لن تعديل الأصلي IEnumerable<T> الكائن.ويمكن التحقق من ذلك من خلال عقد إشارة إلى ذلك.على سبيل المثال

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

بعد هذه مجموعة من العمليات متغير temp سوف لا تزال المرجعية الوحيدة وهي enumerable مع عنصر واحد "فو" في مجموعة من القيم حين البنود المرجعية مختلفة enumerable مع القيم "فو" و "بار".

تحرير

أنا كونتستانتلي تنسى أن تضيف ليست نموذجية طريقة التمديد على 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> أو <وأ href = " http://msdn.microsoft.com/en-us/library/5y536ey6.aspx "يختلط =" نوفولو noreferrer "> واجهات IList<T> بدلا من ذلك، فإنها موجودة لسبب بسيط، أن كنت تريد أن يكون وسيلة Add على وIEnumerable<T>.

ويستخدم IEnumerable<T> إلى "علامة" نوع بأنها ... حسنا، enumerable أو مجرد سلسلة من البنود من دون أي ضمانات بالضرورة ما إذا كان الكائن الأساسي الحقيقي يدعم إضافة / إزالة العناصر. تذكر أيضا أن هذه الواجهات تنفيذ 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);

في صافي الأساسية، هناك Enumerable.Append الطريقة التي تفعل ذلك تماما.

وشفرة المصدر من الأسلوب هو <وأ href = "https://github.com/dotnet/corefx/blob/master/src/System.Linq/src/System/Linq/AppendPrepend.cs" يختلط = " noreferrer "> متوفرة على جيثب. .... تنفيذ (أكثر تطورا من الاقتراحات في إجابات أخرى) يستحق نظرة :).

لإضافة الرسالة الثانية تحتاج إلى -

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 الأساسية 1.1.1. هذا الأخير يسمح لك لسلسلة عنصر واحد في تسلسل القائمة. لذلك الجواب Aamol يمكن أيضا أن يكتب

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

ومع ذلك، يرجى ملاحظة أن هذه الوظيفة لن يغير من تسلسل المدخلات، انها مجرد إرجاع المجمع الذي وضع تسلسل معين، وهذا البند إلحاق معا.

و

وآخرون إعطاء تفسيرات بالفعل كبيرة فيما يتعلق لماذا لا يمكن (ويجب أن لا!) تكون قادرة على إضافة عناصر إلى IEnumerable. وأود أن أضيف فقط أنه إذا كنت تبحث لمواصلة الترميز إلى واجهة التي تمثل مجموعة وتريد وسيلة إضافية، يجب أن الرمز إلى <لأ href = "http://msdn.microsoft.com/en-us/library/ 92t2ye13.aspx "يختلط =" نوفولو noreferrer "> 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);
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top