Code for adding to IEnumerable

2019-01-25 02:52发布

问题:

I have an enumerator like this

IEnumerable<System.Windows.Documents.FixedPage> page;

How can I add a page (eg: D:\newfile.txt) to it? I have tried Add, Append, Concat etc But nothing worked for me.

回答1:

Yes, it is possible

It is possible to concatenate sequences (IEnumerables) together and assign the concatenated result to a new sequence. (You cannot change the original sequence.)

The built-in Enumerable.Concat() will only concatenate another sequence; however, it is easy to write an extension method that will let you concatenate a scalar to a sequence.

The following code demonstrates:

using System;
using System.Collections.Generic;
using System.Linq;

namespace Demo
{
    public class Program
    {
        [STAThread]
        private static void Main()
        {
            var stringList = new List<string> {"One", "Two", "Three"};

            IEnumerable<string> originalSequence = stringList;

            var newSequence = originalSequence.Concat("Four");

            foreach (var text in newSequence)
            {
                Console.WriteLine(text); // Prints "One" "Two" "Three" "Four".
            }
        }
    }

    public static class EnumerableExt
    {
        /// <summary>Concatenates a scalar to a sequence.</summary>
        /// <typeparam name="T">The type of elements in the sequence.</typeparam>
        /// <param name="sequence">a sequence.</param>
        /// <param name="item">The scalar item to concatenate to the sequence.</param>
        /// <returns>A sequence which has the specified item appended to it.</returns>
        /// <remarks>
        /// The standard .Net IEnumerable extensions includes a Concat() operator which concatenates a sequence to another sequence.
        /// However, it does not allow you to concat a scalar to a sequence. This operator provides that ability.
        /// </remarks>

        public static IEnumerable<T> Concat<T>(this IEnumerable<T> sequence, T item)
        {
            return sequence.Concat(new[] { item });
        }
    }
}


回答2:

IEnumerable<T> does not contain a way to modify the collection.

You will need to implement either ICollection<T> or IList<T> as these contain an Add and Remove functions.



回答3:

If you have an idea of what the original type of the IEnumerable is, you can modify it...

List<string> stringList = new List<string>();
stringList.Add("One");
stringList.Add("Two");
IEnumerable<string> stringEnumerable = stringList.AsEnumerable();
List<string> stringList2 = stringEnumerable as List<string>;

if (stringList2 != null)
    stringList2.Add("Three");

foreach (var s in stringList)
    Console.WriteLine(s);

This outputs:

One
Two
Three

Change the foreach statement to iterate over stringList2, or stringEnumerable, you'll get the same thing.

Reflection might be useful to determine the real type of the IEnumerable.

This probably isn't a good practice, though... Whatever gave you the IEnumerable is probably not expecting the collection to be modified that way.



回答4:

IEnumerable<T> is a readonly interface. You should use an IList<T> instead, which provides methods for adding and removing items.



回答5:

IEnumerable is immutable. You can't add items, you can't delete items.
The classes from System.Collections.Generic return this interface so you can iterate over the items contained in the collection.

From MSDN

Exposes the enumerator, which supports a simple iteration over a collection of a specified type.

See here for MSDN reference.



回答6:

Try

IEnumerable<System.Windows.Documents.FixedPage> page = new List<System.Windows.Documents.FixedPage>(your items list here)

or

IList<System.Windows.Documents.FixedPage> page = new List<System.Windows.Documents.FixedPage>(1);
page.Add(your item Here);


回答7:

You cannot add elements to IEnumerable<T>, since it does not support addition operations. You either have to use an implementation of ICollection<T>, or cast the IEnumerable<T> to ICollection<T> if possible.

IEnumerable<System.Windows.Documents.FixedPage> page;
....
ICollection<System.Windows.Documents.FixedPage> pageCollection 
    = (ICollection<System.Windows.Documents.FixedPage>) page

If the cast is impossible, use for instance

ICollection<System.Windows.Documents.FixedPage> pageCollection 
   = new List<System.Windows.Documents.FixedPage>(page);

You can do it like this:

ICollection<System.Windows.Documents.FixedPage> pageCollection
    = (page as ICollection<System.Windows.Documents.FixedPage>) ??
      new List<System.Windows.Documents.FixedPage>(page);

The latter will almost guarantee that you have a collection that is modifiable. It is possible, though, when using cast, to successfully get the collection, but all modification operations to throw NotSupportedException. This is so for read-only collections. In such cases the approach with the constructor is the only option.

The ICollection<T> interface implements IEnumerable<T>, so you can use pageCollection wherever you are currently using page.