23

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.

Rohit Vipin Mathews
  • 11,629
  • 15
  • 57
  • 112
Sudha
  • 2,078
  • 6
  • 28
  • 53
  • 1
    You have tried `Concat`? How? You could wrap your single page in a collection, e.g. `new[]{singlePage}`. Then you can use that for `Enumerable.Concat`: `var pages = page.Concat(new[]{singlePage});` – Tim Schmelter Apr 02 '13 at 09:49

7 Answers7

8

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.

Mark Broadhurst
  • 2,675
  • 23
  • 45
8

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 });
        }
    }
}
Matthew Watson
  • 104,400
  • 10
  • 158
  • 276
6

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.

Steve
  • 6,334
  • 4
  • 39
  • 67
  • 2
    You would be better casting stringList2 to ICollection rather than a List as it will work for List as well as other objects which inherit from ICollection. If stringList is not an ICollection it will still fail and not add. – Mark Broadhurst Aug 27 '13 at 15:12
5

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

Fredrik Mörk
  • 155,851
  • 29
  • 291
  • 343
  • If you're going to use a more specific interface, I'd use the most high-level one you can get away with, which would be `ICollection`. – Anthony Apr 02 '13 at 15:18
1

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.

bash.d
  • 13,029
  • 3
  • 29
  • 42
1

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.

Ivaylo Slavov
  • 8,839
  • 12
  • 65
  • 108
1

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);
evgenyl
  • 7,837
  • 2
  • 27
  • 32