Adding an item to IEnumerable

I had a list <> of my objects, but now I need to change it to IEnumerable <>. So, I have this:

public IEnumerable<TransactionSplitLine> TransactionSplitLines { get; set; } 

However, I can no longer do:

 reply.TransactionSplitLines.Add(new TransactionSplitLine {Amount = "100", Category = "Test", SubCategory = "Test More", CategoryId=int.Parse(c)}); 

How do I add items now?

+6
c # ienumerable
source share
8 answers

You can do something like the following using Concat:

 reply.TransactionSplitLines = reply.TransactionSplitLines.Concat(new []{new TransactionSplitLine { Amount = "100", Category = "Test", SubCategory = "Test More", CategoryId = int.Parse(c)}}); 

This creates a new IEnumerable . It’s hard to say which is the best solution in your case, since information about your use case is not enough.

EDIT: Note that List<T> implements IEnumerable<T> . Therefore, if you need to pass IEnumerable<T> as a parameter, for example, you can also pass List<T> , perhaps by explicitly specifying AsEnumerable() in your list. Therefore, perhaps you can stick to the list instead of IEnumerable.

+19
source share

Short answer: You cannot add elements to IEnumerable<T>

A bit longer explanation:

IEnumerable is an interface that is extremely concerned about the ability to list / repeat a set of elements. This is the sole purpose of IEnumerable . It abstracts any idea of ​​how to store or retrieve enumerated elements (this can be a character string, a list of elements, a stream of bytes or a series of calculation results), so if you have an interface that is IEnumerable , you cannot add elements to it, you can iterate over only the elements it provides.

However, the correct way to add elements to IEnumerable is to return a new IEnumerable with new elements added to the contents of the original.

Also with Linq libraries, you have an extension method that allows you to use your IEnumerable in a List via IEnumerable.ToList() , and you can add items to the list. This may not be the right way.

With the Linq libraries in your namespace, you can do the following:

 using System; using System.Collections.Generic; using System.Linq; namespace EnumTester { class Program { static void Main(string[] args) { IEnumerable<string> enum = GetObjectEnumerable(); IEnumerable<string> concatenated = enum.Concat(new List<string> { "concatenated" }); List<string> stringList = concatenated.ToList(); } } } 
+9
source share

You cannot add elements to IEnumerable<T> since this interface does not have an Add method.
if TransactionSplitLines always returns an instance of List<TransactionSplitLine> , you can change its type to IList<TransactionSplitLine> .
If you cannot change the type of TransactionSplitLines , and you can guarantee that it always returns a IList<TransactionSplitLines> , you can use it as in

 ((IList<TransactionSplitLine>)reply.TransactionSplitLines).Add(new TransactionSplitLine {Amount = "100", Category = "Test", SubCategory = "Test More", CategoryId=int.Parse(c)}); 
+5
source share

IEnumerable<T> does not have an Add(T) method. Depending on your real type, you can do this as follows:

 var item = new TransactionSplitLine {Amount = "100", Category = "Test", SubCategory = "Test More", CategoryId=int.Parse(c)}; ((IList)reply.TransactionSplitLines).Add(item); 

If the collection you are using implements IList .

Remember that you want to use most of the basic interfaces / classes when passing objects. Therefore, if you need to use methods from IList , I suggest you use this instead of IEnumerable .

I suggest you make the following changes:

 public IList<TransactionSplitLine> TransactionSplitLines { get; set; } 
+3
source share

It depends on the value and purpose of your TransactionSplitLines property.

If you want to allow editing (adding / removing) from outside your class, just make your property less general than IEnumerable<T> , for example:

 public IList<TransactionSplitLine> TransactionSplitLines { get; set; } 

or better:

 public ICollection<TransactionSplitLine> TransactionSplitLines { get; set; } 

Instead, if you just need to edit the collection internally (I mean in the scope of the class), why don't you do something like this:

 private List<TransactionSplitLine> transactionSplitLines; public IEnumerable<TransactionSplitLine> TransactionSplitLines { get { return transactionSplitLines; } } 

so you can use the TransactionSplitLines field to modify the collection internally.

+2
source share

I would create this extension method that does all this lazily:

 public static IEnumerable<T> Append<T>(this IEnumerable<T> source, params T[] items) { return source.Concat(items); } 

So in your case:

 var item = new TransactionSplitLine { Amount = "100", Category = "Test", SubCategory = "Test More", CategoryId = int.Parse(c) }; reply.TransactionSplitLines.Append(item); 

Similarly, you can have Prepend :

 public static IEnumerable<T> Prepend<T>(this IEnumerable<T> source, params T[] items) { return items.Concat(source); } 
+2
source share

You can use the Concat method to concatenate two such sets:

 reply.TransactionSplitlines = reply.TransactionSplitlines.Concat(/* another enumerable */); 

You will need to write an AsEnumerable extension method that will take obj and do something like yield return obj; . You can avoid writing an extension method and simply pass new [] with the object in it to the Concat method, but if your interface is based on IEnumerable , you probably need the AsEnumerable method in some other cases too.

This is if you really need to be IEnumerable . However, I would advise you to consider switching to IList<T> or some other interface that supports add . If you need to implement some interface with the IEnumerable<> property, you can have IList<> as an internal field for this property and change it separately - the probability that you are working with a specific object here, and not with the interface. If you are working with an interface and should still use add , IEnumerable<> is just a poor type choice for this interface.

0
source share

IEnumerable is an immutable collection, which means you cannot add or remove an element. The extension method creates a new instance (explained, for example, here: What is the best way to add one element to IEnumerable <T>? ) Rather, by creating an extension method, you can add it to the list first, as shown below: for example, in my case, user roles are defined as IEnumerable (in the user model class). So, to add value to this role. I originally defined a list:

 List<Role> rols=new List<Role>(); 

Inside the loop, a value is added for this list, for example:

 foreach(int i=0;i<chkRoles.count;i++) { Role r=new Role(); r.RoleId="2"; r.RoleName="Admin"; rols.add(r); } 

and then specify this value in IEnumerable ist:

 user.Roles=rols.AsEnumerable(); 
0
source share

All Articles