How to Add an Item to a Ienumerable<T> Collection

How can I add an item to a IEnumerable T collection?

You cannot, because IEnumerable<T> does not necessarily represent a collection to which items can be added. In fact, it does not necessarily represent a collection at all! For example:

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??

What you can do, however, is create a new IEnumerable object (of unspecified type), which, when enumerated, will provide all items of the old one, plus some of your own. You use Enumerable.Concat for that:

 items = items.Concat(new[] { "foo" });

This will not change the array object (you cannot insert items into to arrays, anyway). But it will create a new object that will list all items in the array, and then "Foo". Furthermore, that new object will keep track of changes in the array (i.e. whenever you enumerate it, you'll see the current values of items).

How to add an item to an IEnumerable

IEnumerable is an interface. You can't use Add() on an IEnumerable because they're not required to implement an Add() method. See the IEnumerable documentation on MSDN.

Instead, create a generic list which inherits from the interface IList. Types that use the IList interface must implement Add().

List<MyBlahType> test = _blah.tolist();
test.Add(new MyBlahType());

If you still want to use an interface to avoid a concrete type, then use IList directly.

IList<MyBlahType> test= _blah.tolist();
test.Add(new MyBlahType());

By the way, it's usually considered poor styling to start variable/type names with underscores and to not use proper capitalization. The preferred style in C# is to use PascalCase or camelCase for capitalization.

What's the Best Way to Add One Item to an IEnumerable T ?

Nope, that's about as concise as you'll get using built-in language/framework features.

You could always create an extension method if you prefer:

arr = arr.Append("JKL");
// or
arr = arr.Append("123", "456");
// or
arr = arr.Append("MNO", "PQR", "STU", "VWY", "etc", "...");

// ...

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

Adding an item to IEnumerable

You could 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)}});

That basically creates a new IEnumerable. It's hard to say what's the best solution in your case, since there are not enough information about your use case.

EDIT:
Please note that List<T> implements IEnumerable<T>. So if you need to pass an IEnumerable<T> as a parameter for example, you can also pass a List<T> instead, maybe calling explicitly AsEnumerable() on your list first. So maybe you could stick with a List instead of an IEnumerable.

How can I add an item to a IEnumerable (T item, int? number) ?

The point of the interface is that you don't need to know anything about the source of the list, only that you can enumerate it. It could be that the method returns a list, computes the elements on the fly or reads them from the internet one at a time.

To add a value, you'll need to make sure that you work with a List<T>:

var enumResult = new List<(T item, int? number)>();
enumResult.Add(...);

Note that a List is also an IEnumerable so you can still use enumResult wherever the IEnumerable is expected.

How can I add an IEnumerable T to an existing ICollection T

Just use Enumerable.Concat:

IEnumerable<YourType> result = dest.Concat(items);

If you want a List<T> as result use ToList:

List<YourType> result = dest.Concat(items).ToList();
// perhaps:
dest = result;

If dest is actually already a list and you want to modify it use AddRange:

dest.AddRange(items);

Update:

if you have to add items to a ICollection<T> method argument you could use this extension:

public static void AddRange<T>(this ICollection<T> collection, IEnumerable<T> seq)
{
List<T> list = collection as List<T>;
if (list != null)
list.AddRange(seq);
else
{
foreach (T item in seq)
collection.Add(item);
}
}

// ...

public static void Foo<T>(ICollection<T> dest)
{
IEnumerable<T> items = ...
dest.AddRange(items);
}

Adding IEnumerable T items to IEnumerable T

Well, I think there is some confusion here,

var result = selected.SelectMany(item => 
_repo.GetAllDCategories(item).Select(cat =>
new
{
Label = cat.Name,
Value = cat.Id
});

seems to me what you want.

You can use SelectMany to "squash" or "flatten" an IEnumerable<IEnumerable<T>> into an IEnumerable<T>.

Its similar to having a function like this

IEnumerable<KeyValuePair<string, int>> GetSelectedCategories(
IEnumerable<string> selected)
{
foreach (var item in selected)
{
foreach (var category in _repo.GetAllDCategories(item))
{
yield return new KeyValuePair<string, int>(
category.Name,
category.Id);
}
}
}

Adding objects to IEnumerable

There is the IEnumerable.Append. This is great if you want to tack on one additional item to a large list without making a full copy, but it is not appropriate to use when adding many items.

I would probably suggest using an iterator block

public IEnumerable<Person> GetData(){
...
var lines = file.Skip(1);
foreach(var line in lines){
var cells = line.Split(';');
var person = new Person(...);
yield return person;
}
}

This is a easy and compact way to write a lazy reader that processes data as it is needed. But be aware that this parsing will be done each time the IEnumerable is iterated over. So in many cases the first thing you do is convert it to a list anyway.

I would be careful about claims about memory management. If you are processing huge files, some kind of streaming solution like this can indeed be critical, but you need to be really careful so that you never need to keep all of the file in memory. However, when processing small files it might very well be more efficient to do all the processing in one go. Or do something in between, like processing chunks of data. It really depends on what your use case is and what the memory and performance requirements are.

How to add item to class list of objects populated in an IEnumerable

Unless you really need a property to be publically (i.e. from the outside of your class) settable, don't make it public. An IEnumerable<T> is a read-only type, you cannot add elements to it. However, you can add elements to a List<T>.

Convert your auto-property to a property with a backing field and then access the field inside your class, but use the property for public reading of the players:

public class Team
{
private readonly List<Player> players;

public string Name { get; }
public IEnumerable<Player> Players => this.players;
// older versions of C#: Players { get { return this.players; } }

public Team(string name, List<Player> players)
{
this.Name = name;
this.players = players;
}

public void addPlayer(Player pl) {
this.players.Add(pl);
}
}


Related Topics



Leave a reply



Submit