ToList()-- does it create a new list? - c#

Let's say I have a class
public class MyObject
{
public int SimpleInt{get;set;}
}
And I have a List<MyObject>, and I ToList() it and then change one of the SimpleInt, will my change be propagated back to the original list. In other words, what would be the output of the following method?
public void RunChangeList()
{
var objs = new List<MyObject>(){new MyObject(){SimpleInt=0}};
var whatInt = ChangeToList(objs );
}
public int ChangeToList(List<MyObject> objects)
{
var objectList = objects.ToList();
objectList[0].SimpleInt=5;
return objects[0].SimpleInt;
}
Why?
P/S: I'm sorry if it seems obvious to find out. But I don't have compiler with me now...

Yes, ToList will create a new list, but because in this case MyObject is a reference type then the new list will contain references to the same objects as the original list.
Updating the SimpleInt property of an object referenced in the new list will also affect the equivalent object in the original list.
(If MyObject was declared as a struct rather than a class then the new list would contain copies of the elements in the original list, and updating a property of an element in the new list would not affect the equivalent element in the original list.)

From the Reflector'd source:
public static List<TSource> ToList<TSource>(this IEnumerable<TSource> source)
{
if (source == null)
{
throw Error.ArgumentNull("source");
}
return new List<TSource>(source);
}
So yes, your original list won't be updated (i.e. additions or removals) however the referenced objects will.

ToList will always create a new list, which will not reflect any subsequent changes to the collection.
However, it will reflect changes to the objects themselves (Unless they're mutable structs).
In other words, if you replace an object in the original list with a different object, the ToList will still contain the first object.
However, if you modify one of the objects in the original list, the ToList will still contain the same (modified) object.

Yes, it creates a new list. This is by design.
The list will contain the same results as the original enumerable sequence, but materialized into a persistent (in-memory) collection. This allows you to consume the results multiple times without incurring the cost of recomputing the sequence.
The beauty of LINQ sequences is that they are composable. Often, the IEnumerable<T> you get is the result of combining multiple filtering, ordering, and/or projection operations. Extension methods like ToList() and ToArray() allow you to convert the computed sequence into a standard collection.

The accepted answer correctly addresses the OP's question based on his example. However, it only applies when ToList is applied to a concrete collection; it does not hold when the elements of the source sequence have yet to be instantiated (due to deferred execution). In case of the latter, you might get a new set of items each time you call ToList (or enumerate the sequence).
Here is an adaptation of the OP's code to demonstrate this behaviour:
public static void RunChangeList()
{
var objs = Enumerable.Range(0, 10).Select(_ => new MyObject() { SimpleInt = 0 });
var whatInt = ChangeToList(objs); // whatInt gets 0
}
public static int ChangeToList(IEnumerable<MyObject> objects)
{
var objectList = objects.ToList();
objectList.First().SimpleInt = 5;
return objects.First().SimpleInt;
}
Whilst the above code may appear contrived, this behaviour can appear as a subtle bug in other scenarios. See my other example for a situation where it causes tasks to get spawned repeatedly.

A new list is created but the items in it are references to the orginal items (just like in the original list). Changes to the list itself are independent, but to the items will find the change in both lists.

Just stumble upon this old post and thought of adding my two cents. Generally, if I am in doubt, I quickly use the GetHashCode() method on any object to check the identities. So for above -
public class MyObject
{
public int SimpleInt { get; set; }
}
class Program
{
public static void RunChangeList()
{
var objs = new List<MyObject>() { new MyObject() { SimpleInt = 0 } };
Console.WriteLine("objs: {0}", objs.GetHashCode());
Console.WriteLine("objs[0]: {0}", objs[0].GetHashCode());
var whatInt = ChangeToList(objs);
Console.WriteLine("whatInt: {0}", whatInt.GetHashCode());
}
public static int ChangeToList(List<MyObject> objects)
{
Console.WriteLine("objects: {0}", objects.GetHashCode());
Console.WriteLine("objects[0]: {0}", objects[0].GetHashCode());
var objectList = objects.ToList();
Console.WriteLine("objectList: {0}", objectList.GetHashCode());
Console.WriteLine("objectList[0]: {0}", objectList[0].GetHashCode());
objectList[0].SimpleInt = 5;
return objects[0].SimpleInt;
}
private static void Main(string[] args)
{
RunChangeList();
Console.ReadLine();
}
And answer on my machine -
objs: 45653674
objs[0]: 41149443
objects: 45653674
objects[0]: 41149443
objectList: 39785641
objectList[0]: 41149443
whatInt: 5
So essentially the object that list carries remain the same in above code. Hope the approach helps.

I think that this is equivalent to asking if ToList does a deep or shallow copy. As ToList has no way to clone MyObject, it must do a shallow copy, so the created list contains the same references as the original one, so the code returns 5.

ToList will create a brand new list.
If the items in the list are value types, they will be directly updated, if they are reference types, any changes will be reflected back in the referenced objects.

In the case where the source object is a true IEnumerable (i.e. not just a collection packaged an as enumerable), ToList() may NOT return the same object references as in the original IEnumerable. It will return a new List of objects, but those objects may not be the same or even Equal to the objects yielded by the IEnumerable when it is enumerated again

var objectList = objects.ToList();
objectList[0].SimpleInt=5;
This will update the original object as well. The new list will contain references to the objects contained within it, just like the original list. You can change the elements either and the update will be reflected in the other.
Now if you update a list (adding or deleting an item) that will not be reflected in the other list.

I don't see anywhere in the documentation that ToList() is always guaranteed to return a new list. If an IEnumerable is a List, it may be more efficient to check for this and simply return the same List.
The worry is that sometimes you may want to be absolutely sure that the returned List is != to the original List. Because Microsoft doesn't document that ToList will return a new List, we can't be sure (unless someone found that documentation). It could also change in the future, even if it works now.
new List(IEnumerable enumerablestuff) is guaranteed to return a new List. I would use this instead.

Related

Immutable list not adding data

I am using an ImmutableList as follows:
Referenced the package using Nuget and following is the usage code:
using System.Collections.Immutable;
private ImmutableList<Data> immutableList = ImmutableList.Create<Data>();
// Write Action
Action writeAction = (() =>
{
Data writeData = new Data();
// Fill Data type with valid values
immutableList.Add(writeData);
});
This code above is not adding any data to the Immutable list. It remains empty, I cannot figure out the reason when all the data is valid. Similar code is used to fill other data structures like ConcurrentQueue and ConcurrentBag and it works fine.
Am I missing something in the usage of the immutable list, does it requires correction?
Please note this is a multi-threaded operation, but that can't be an issue, since this data structure is thread safe.
As the name suggest list is immutable i.e. you cannot add the item to original list. Under remarks section of MSDN link:
When you add or remove items from an immutable list copy of the
original list is made with the items added or removed, and the
original list is unchanged.
Also from here, of Add method documentation:
It returns a new immutable list with the object added, or the current list if it
already contains the specified object.
Add will get you new list reference with item added in it (original list will remain unchanged):
immutableList = immutableList.Add(writeData);
Immutable list is a list that does not change. Here is a description from MSDN on what it means:
When you add or remove items from an immutable list copy of the original list is made with the items added or removed, and the original list is unchanged.
This means that every time you perform operation like Add, your original list is not changed, but the new list with added element is returned. This means that you would need to use a code like this to have the correct list:
immutableList = immutableList.Add(writeData);
This makes me think that you are using it for wrong scenario.
Create your normal list... Turn it into Array
Use that array to make immutable list... heres my snippet
var result = csvReader.GetRecords<Data>().ToArray();
return ImmutableList.Create<Data>(result);
ImmutableList immutableList = ImmutableList.Create<string>("data1", "data2");
This works perfectly for me.
The answers already states that the immutable list is really immutable, when you add items, you must designate the new immutable list from the add operation to the same variable for example.
A possibility for easier use is to wrap the immutable list with a functional container class like the following code, which can be pasted in Linqpad 5 (make sure you hit F4 to add Nuget reference to System.Collections.Immutable and pick the namespace from that assembly).
void Main()
{
var numbersInImmutableList = new ImmutableWrappedList<int>();
numbersInImmutableList.AddRange(new[] { 3, 1, 4, 1, 5, 9, 2 });
numbersInImmutableList.AddRange(new[]{ 2, 7, 1, 8, 2, 1, 8 });
numbersInImmutableList.RemoveAt(2);
numbersInImmutableList.Dump();
}
public class ImmutableWrappedList<T> {
public ImmutableList<T> _internalList {get; private set; }
public ImmutableWrappedList()
{
_internalList = ImmutableList.Create<T>();
}
public void Clear() => _internalList.Clear();
public void AddRange(IEnumerable<T> itemsToAdd) => _internalList = _internalList.AddRange(itemsToAdd);
public void Add(T itemToAdd) => _internalList = _internalList.Add(itemToAdd);
public void Remove(T itemToAdd) => _internalList = _internalList.Remove(itemToAdd);
public void RemoveAt(int index) => _internalList = _internalList.RemoveAt(index);
public void Insert(T itemToAdd, int position) => _internalList = _internalList.Insert(position, itemToAdd);
}

How do I change my new list without changing the original list?

I have a list that gets filled in with some data from an operation and I am storing it in the memory cache. Now I want another list which contains some sub data from the list based on some condition.
As can be seen in the below code I am doing some operation on the target list. The problem is that whatever changes I am doing to the target list is also being done to the mainList. I think its because of the reference is same or something.
All I need is that operation on the target list not affect data inside the main list.
List<Item> target = mainList;
SomeOperationFunction(target);
void List<Item> SomeOperationFunction(List<Item> target)
{
target.removeat(3);
return target;
}
You need to clone your list in your method, because List<T> is a class, so it's reference-type and is passed by reference.
For example:
List<Item> SomeOperationFunction(List<Item> target)
{
List<Item> tmp = target.ToList();
tmp.RemoveAt(3);
return tmp;
}
Or
List<Item> SomeOperationFunction(List<Item> target)
{
List<Item> tmp = new List<Item>(target);
tmp.RemoveAt(3);
return tmp;
}
or
List<Item> SomeOperationFunction(List<Item> target)
{
List<Item> tmp = new List<Item>();
tmp.AddRange(target);
tmp.RemoveAt(3);
return tmp;
}
You need to make a copy of the list so that changes to the copy won't affect the original. The easiest way to do that is to use the ToList extension method in System.Linq.
var newList = SomeOperationFunction(target.ToList());
Build a new list first and operate on that, because List is a reference type, i.e. when you pass it in a function, you do not just pass the value but the actual object itself.
If you just assign target to mainList, both variables point to the same object, so you need to create a new List:
List<Item> target = new List<Item>(mainList);
void List<Item> SomeOperationFunction() makes no sense, because either you return nothing (void) or you return a List<T>. So either remove the return statement from your method or return a new List<Item>. In the latter case, I would rewrite this as:
List<Item> target = SomeOperationFunction(mainList);
List<Item> SomeOperationFunction(List<Item> target)
{
var newList = new List<Item>(target);
newList.RemoveAt(3);
return newList;
}
I tried many of the answers above. On all the ones I tested, an update to the new list modifies the original. this is what works for me.
var newList = JsonConvert.DeserializeObject<List<object>>(JsonConvert.SerializeObject(originalList));
return newlist.RemoveAt(3);
Even if you create a new list, the references to the items in the new list will still point to the items in the old list, so I like to use this extension method if I need a new list with new references...
public static IEnumerable<T> Clone<T>(this IEnumerable<T> target) where T : ICloneable
{
If (target.IsNull())
throw new ArgumentException();
List<T> retVal = new List<T>();
foreach (T currentItem in target)
retVal.Add((T)(currentItem.Clone()));
return retVal.AsEnumerable();
}
Your target variable is a reference type. This means that anything you do to it will be reflected in the list you pass into it.
To not do that, you are going to need to create a new list in the method, copy target contents to it, and then perform the remove at operation on the new list.
About Reference and Value Types
Since a List is a reference type, what is passed to the function is a reference to the original list.
See this MSDN article for more information about how parameters are passed in C#.
In order to achieve what you want, you should create a copy of the list in SomeOperationFunction and return this instead. A simple example:
void List<Item> SomeOperationFunction(List<Item> target)
{
var newList = new List<Item>(target);
newList.RemoveAt(3);
return newList; // return copy of list
}
As pointed out by Olivier Jacot-Descombes in the comments to another answer, it is important to bear in mind that
[...] the list still holds references to the same items if
the items are of a reference type. So changes to the items themselves
will still affect the items in both lists.
Your are seeing the original list being modified because, by default, any non-primitive objects, are passed by reference (It is actually pass by value, the value being the reference, but that is a different matter).
What you need to do is clone the object. This question will help you with some code to clone a List in C#: How do I clone a generic list in C#?
Instead of assigning mainList to target, I would do: target.AddRange(mainList);
Then you will have a copy of the items instead of a reference to the list.
Just make sure that you initialize the new list with a list created by copying the elements of the source list.
List<Item> target = mainList; Should be List<item> target = new List<Item>(mainList);
You'll need to make a copy of the list since in your original code what you're doing is just passing around, as you correctly suspected, a reference (someone would call it a pointer).
You could either call the constructor on the new list, passing the original list as parameter:
List<Item> SomeOperationFunction(List<Item> target)
{
List<Item> result = new List<Item>(target);
result.removeat(3);
return result;
}
Or create a MemberWiseClone:
List<Item> SomeOperationFunction(List<Item> target)
{
List<Item> result = target.MemberWiseClone();
result.removeat(3);
return result;
}
Also, you are not storing the return of SomeOperationFunction anywhere, so you might want to revise that part as well (you declared the method as void, which should not return anything, but inside it you're returning an object).
You should call the method this way:
List<Item> target = SomeOperationFunction(mainList);
Note: the elements of the list will not be copied (only their reference is copied), so modifying the internal state of the elements will affect both lists.

Getting a ref/address from a list in C#

I am aware that C# does not deal with pointers but I wonder if I can get a ref to a list when I know its first element?
For example:
Let's say I have a list defined as
List<T> abc
If I have abc[0], can I get a reference of abc?
I am new to C#, I apologize if my question seems weird. In C/C++, I can get the address of an array abc by using &abc[0]. Does C# provide us with similar tool that help us refer back to the collection itself when we know one item in the collection?
Thanks,
This is now possible, starting with .NET 5.0, by using the System.Runtime.InteropServices.CollectionsMarshal.AsSpan method.
As indicated by the documentation, items should not be added to or removed from the list while using the span or item references taken from the span. Technically this should also be extended to say that the Capacity should not be changed nor should TrimExcess() be called. If these operations are used while actively using the span or its references, then the internal memory of the list may no longer be the same as the memory in the span.
// Create a simple list with three items.
var list = new List<int>();
list.Add(123);
list.Add(456);
list.Add(789);
// Print list to console.
Console.WriteLine("List items:");
foreach (var item in list)
Console.WriteLine(item);
Console.WriteLine();
// Get a reference to the second item in the list.
// WARNING: DO NOT ADD/REMOVE ITEMS FROM THE LIST WHILE USING THIS SPAN
// OR ANY REFERENCES DERIVED FROM THIS SPAN!
var listSpan = CollectionsMarshal.AsSpan(list);
ref var secondItem = ref listSpan[1];
Console.WriteLine($"Referenced value (original): {secondItem}");
// Change the referenced list item.
secondItem = 0;
Console.WriteLine($"Referenced value (modified): {secondItem}");
Console.WriteLine();
// Print the list to console.
Console.WriteLine("List items:");
foreach (var item in list)
Console.WriteLine(item);
Console.WriteLine();
You should get output like this:
List items:
123
456
789
Referenced value (original): 456
Referenced value (modified): 0
List items:
123
0
789
Collections don't work the same way in C# as they do in C++, for example you can add the same object to multiple different collections and so it doesn't really make sense to ask to get a reference to the list that an object is contained in, as it could be in many lists (or none, or even in the same list multiple times)
object myObject = new object();
List<object> list = new List<object>();
list.Add(myObject);
object[] someArray = new object[] { myObject };
Assert.AreEqual(list[0], someArray[0]);
If it helps you can think of lists in C# as being lists of pointers references to the objects being stored where the pointer itself is hidden from you, although understand that in reality the implementation may be more complicated (and is also irrelevant).
If there is a relationship between the objects in a list and the list contents of that list then its up to you to explicitly declare and keep track of what that realtionsip is, for example through a Parent property on the object in the list
List<T> myList = new List<T>();
// Whenever an item is added to myList set the Parent property
myList.Add(item);
item.Parent = myList;
This is what Windows Forms does in order to maintain the relationship between the controls in a container, and the container in which those controls are contained. Obviously you should decide what to do if someone tries to add the same object to multiple lists.
Not unless the type of abc[0] explicitly holds a reference to the list. In fact you cannot do that in C++ either without an explicit reference.
Think about it, in C++ if you can expect firstElemPtr == arrayPtr it is just because arrays store the elements that way and it only works for arrays; everything else is just by accident.
Now consider any list structure that allocates something else (maybe element count) before the pointer to the first element. Your assumption will not work anymore.
If you are designing the type of the items in the collection, then you can add a property to the item's type that "points" to the containing list; when you construct each item, pass in the containing list and save this in the property.
Something like this:
class ListItem
{
public List<ListItem> Parent { get; set; }
public ListItem(List<ListItem> parent)
{
Parent = parent;
}
}
ListItem listItem = new ListItem(abc);
abc.Add(listItem);
// Get collection from item.
List<T> def = listItem.Parent;
Consider:
unsafe static void Main() {
int[] arr = new int[100];
fixed(int* ptr = arr) {
// ptr is a pointer to the zeroth item in the array
}
}
However, unsafe code is not all that common in c# and should be limited to performance-critical regions (and even then used sparingly). In particular, note that we have "pinned" the array by doing this - and note that ptr is only reliable while it is pinned. Outside of the fixed block, GC is free to relocate the array, making ptr invalid.
Clarification: I don't suggest you should do this, but: such things are entirely possible.
List is defined somewhat like this:
public class List<T> : IList<T> blabla
{
private T [] data;
public T this[int index] {
get { return data[index]; }
set { data[index]=value; }
}
... blabla
}
YES, it is NOT linked list of any kind. So you must use it accordingly. Though since .NET value types are small and class types are all references, there usually no heavy array-copy operations as it is possible with C++ for example so such implementation of general-puprose collection is good enough (unless abused). Vector could be a better name from academic standpoint, but it's not.
You would not be able to get a reference to data array, as it's private variable. Nor you would have any need for this. If you need enumerator, use GetEnumerator explicitely or foreach for implicit use.

C#: Immutable view of a list's objects?

I have a list, and I want to provide read-only access to a collection containing its contents. How can I do this?
Something like:
public ICollection<Foo> ImmutableViewOfInventory() {
IList<Foo> inventory = new List<Foo>();
inventory.add(new Foo());
return inventory.ImmutableView();
}
Additionally, an immutable IEnumerable would also be fine.
UPDATE: I realize now that an immutable view of the list would actually be better. (Preserving list ordering semantics.)
This won't give me list behavior, right:
public ReadOnlyCollection<PickUp> InventoryItems()
{
return new ReadOnlyCollection<PickUp>(inventory);
}
I'm looking in the documentation but not immediately seeing ReadOnlyList<T>.
If you are wanting an immutable list of the items, you can return a ReadOnlyCollection by calling the AsReadOnly() method on your list:
public IList<Foo> ImmutableViewOfInventory()
{
List<Foo> inventory = new List<Foo>();
inventory.Add(new Foo());
return inventory.AsReadOnly();
}
This returns an implementation of IList that is both strongly-typed and not modifiable.
It does not however prevent changes to any of the items contained in the list (unless they are value types). To do that, each item must be cloned (deep-cloned if they themselves contain other objects) and added to a new read only list that is returned from your ImmutableViewOfInventory method. You will have to implement this yourself unfortunately.
Have you looked at ReadOnlyCollection<T>?
http://msdn.microsoft.com/en-us/library/ms132474.aspx
new ReadOnlyCollection(inventory);

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

My question as title above. For example
IEnumerable<T> items = new T[]{new T("msg")};
items.ToList().Add(new T("msg2"));
but after all it only has 1 item inside. Can we have a method like items.Add(item) like the List<T>?
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).
The type IEnumerable<T> does not support such operations. The purpose of the IEnumerable<T> interface is to allow a consumer to view the contents of a collection. Not to modify the values.
When you do operations like .ToList().Add() you are creating a new List<T> and adding a value to that list. It has no connection to the original list.
What you can do is use the Add extension method to create a new IEnumerable<T> with the added value.
items = items.Add("msg2");
Even in this case it won't modify the original IEnumerable<T> object. This can be verified by holding a reference to it. For example
var items = new string[]{"foo"};
var temp = items;
items = items.Add("bar");
After this set of operations the variable temp will still only reference an enumerable with a single element "foo" in the set of values while items will reference a different enumerable with values "foo" and "bar".
EDIT
I contstantly forget that Add is not a typical extension method on IEnumerable<T> because it's one of the first ones that I end up defining. Here it is
public static IEnumerable<T> Add<T>(this IEnumerable<T> e, T value) {
foreach ( var cur in e) {
yield return cur;
}
yield return value;
}
Have you considered using ICollection<T> or IList<T> interfaces instead, they exist for the very reason that you want to have an Add method on an IEnumerable<T>.
IEnumerable<T> is used to 'mark' a type as being...well, enumerable or just a sequence of items without necessarily making any guarantees of whether the real underlying object supports adding/removing of items. Also remember that these interfaces implement IEnumerable<T> so you get all the extensions methods that you get with IEnumerable<T> as well.
In .net Core, there is a method Enumerable.Append that does exactly that.
The source code of the method is available on GitHub..... The implementation (more sophisticated than the suggestions in other answers) is worth a look :).
A couple short, sweet extension methods on IEnumerable and IEnumerable<T> do it for me:
public static IEnumerable Append(this IEnumerable first, params object[] second)
{
return first.OfType<object>().Concat(second);
}
public static IEnumerable<T> Append<T>(this IEnumerable<T> first, params T[] second)
{
return first.Concat(second);
}
public static IEnumerable Prepend(this IEnumerable first, params object[] second)
{
return second.Concat(first.OfType<object>());
}
public static IEnumerable<T> Prepend<T>(this IEnumerable<T> first, params T[] second)
{
return second.Concat(first);
}
Elegant (well, except for the non-generic versions). Too bad these methods are not in the BCL.
No, the IEnumerable doesn't support adding items to it. The alternative solution is
var myList = new List(items);
myList.Add(otherItem);
To add second message you need to -
IEnumerable<T> items = new T[]{new T("msg")};
items = items.Concat(new[] {new T("msg2")})
I just come here to say that, aside from Enumerable.Concat extension method, there seems to be another method named Enumerable.Append in .NET Core 1.1.1. The latter allows you to concatenate a single item to an existing sequence. So Aamol's answer can also be written as
IEnumerable<T> items = new T[]{new T("msg")};
items = items.Append(new T("msg2"));
Still, please note that this function will not change the input sequence, it just return a wrapper that put the given sequence and the appended item together.
Not only can you not add items like you state, but if you add an item to a List<T> (or pretty much any other non-read only collection) that you have an existing enumerator for, the enumerator is invalidated (throws InvalidOperationException from then on).
If you are aggregating results from some type of data query, you can use the Concat extension method:
Edit: I originally used the Union extension in the example, which is not really correct. My application uses it extensively to make sure overlapping queries don't duplicate results.
IEnumerable<T> itemsA = ...;
IEnumerable<T> itemsB = ...;
IEnumerable<T> itemsC = ...;
return itemsA.Concat(itemsB).Concat(itemsC);
Others have already given great explanations regarding why you can not (and should not!) be able to add items to an IEnumerable. I will only add that if you are looking to continue coding to an interface that represents a collection and want an add method, you should code to ICollection or IList. As an added bonanza, these interfaces implement IEnumerable.
you can do this.
//Create IEnumerable
IEnumerable<T> items = new T[]{new T("msg")};
//Convert to list.
List<T> list = items.ToList();
//Add new item to list.
list.add(new T("msg2"));
//Cast list to IEnumerable
items = (IEnumerable<T>)items;
Easyest way to do that is simply
IEnumerable<T> items = new T[]{new T("msg")};
List<string> itemsList = new List<string>();
itemsList.AddRange(items.Select(y => y.ToString()));
itemsList.Add("msg2");
Then you can return list as IEnumerable also because it implements IEnumerable interface
Instances implementing IEnumerable and IEnumerator (returned from IEnumerable) don't have any APIs that allow altering collection, the interface give read-only APIs.
The 2 ways to actually alter the collection:
If the instance happens to be some collection with write API (e.g. List) you can try casting to this type:
IList<string> list = enumerableInstance as IList<string>;
Create a list from IEnumerable (e.g. via LINQ extension method toList():
var list = enumerableInstance.toList();
IEnumerable items = Enumerable.Empty(T);
List somevalues = new List();
items.ToList().Add(someValues);
items.ToList().AddRange(someValues);
Sorry for reviving really old question but as it is listed among first google search results I assume that some people keep landing here.
Among a lot of answers, some of them really valuable and well explained, I would like to add a different point of vue as, to me, the problem has not be well identified.
You are declaring a variable which stores data, you need it to be able to change by adding items to it ? So you shouldn't use declare it as IEnumerable.
As proposed by #NightOwl888
For this example, just declare IList instead of IEnumerable: IList items = new T[]{new T("msg")}; items.Add(new T("msg2"));
Trying to bypass the declared interface limitations only shows that you made the wrong choice.
Beyond this, all methods that are proposed to implement things that already exists in other implementations should be deconsidered.
Classes and interfaces that let you add items already exists. Why always recreate things that are already done elsewhere ?
This kind of consideration is a goal of abstracting variables capabilities within interfaces.
TL;DR : IMO these are cleanest ways to do what you need :
// 1st choice : Changing declaration
IList<T> variable = new T[] { };
variable.Add(new T());
// 2nd choice : Changing instantiation, letting the framework taking care of declaration
var variable = new List<T> { };
variable.Add(new T());
When you'll need to use variable as an IEnumerable, you'll be able to. When you'll need to use it as an array, you'll be able to call 'ToArray()', it really always should be that simple. No extension method needed, casts only when really needed, ability to use LinQ on your variable, etc ...
Stop doing weird and/or complex things because you only made a mistake when declaring/instantiating.
Maybe I'm too late but I hope it helps anyone in the future.
You can use the insert function to add an item at a specific index.
list.insert(0, item);
Sure, you can (I am leaving your T-business aside):
public IEnumerable<string> tryAdd(IEnumerable<string> items)
{
List<string> list = items.ToList();
string obj = "";
list.Add(obj);
return list.Select(i => i);
}

Categories