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
Get Last 10 Lines of Very Large Text File > 10Gb
If Statements Matching Multiple Values
How to Check the Number of Bytes Consumed by a Structure
Searching for a Specific Jtoken by Name in a Jobject Hierarchy
ASP.NET Calling Webmethod with Jquery Ajax "401 (Unauthorized)"
Check for Column Name in a SQLdatareader Object
Generating Permutations of a Set (Most Efficiently)
How to Calculate Float Type Precision and Does It Make Sense
C# Deserializing a Struct After Receiving It Through Tcp
What Static Analysis Tools Are Available for C#
Dynamically Add C# Properties at Runtime
.Net Out of Memory Exception - Used 1.3Gb But Have 16Gb Installed
In C#, How to Check If a Tcp Port Is Available
What Exactly Are Unmanaged Resources
What Is Cool About Generics, Why Use Them
How to "Steal" an Event Handler from One Control and Give It to Another