I have the following which is an array
package.Resources
If I use
package.Resources.ToList().Add(resouce);
package.Resources doesn't actually contain the new item.
I have to use
var packageList = package.Resources.ToList();
packageList.Add(resource);
package.Resources = packageList.ToA开发者_JS百科rray();
Why is that?
ToList()
creates a completely new, different list based on the original array.
LINQ is read-only; Language INtegrated Query - it is only querying the data, not modifying it. All LINQ methods produce a projection - e.g., they project the original sequence into a new one, so you're always working against that.
When you call package.Resources.ToList().Add(resouce);
, it's functionally the same as doing this:
var resourcesAsList = new List<WhateverTypeResourcesContains>();
foreach(var item in package.Resources)
{
resourcesAsList.Add(item);
}
var resourcesAsList.Add(resouce);
What this means is that package.Resources
hasn't been modified, you've created a List<T>
that contains each item that package.Resources contained.
Exanding upon what Rex said, when you call .ToList()
on an array object, what you are saying is, "Make me a brand new List
object that's a distinct reference from the original array, but use the objects from my original array as the objects in my list."
Because arrays are fixed in size, there's really no way to Add()
an item to it without copying the existing array to a new array that has an increased capacity (even ReDim Preserve
in the VB world copies the array behind the scense).
Because of this, you should ask yourself why you are using an array if you don't know the total number of items in the array when you instantiate it. When you know the number of items or when you are instantiating the array from an existing List
or IEnumerable
, arrays can be a decent light-weight way of holding a collection of objects. However, when you don't know the capacity until runtime and the source is not an IEnumerable
, a List
might be a better option because it is built to grow in capacity as items are added.
I use the following collection types as properties in my classes:
IEnumerable
- I use
IEnumerable
when I'm going to be iterating over a collection that already exists and I won't be adding to it. For example, if I query a directory for its files and I want to have those files as a property in a class, I might usepublic IEnumerable<FileInfo> DirectoryFiles {get; set;}
. IEnumerable
allows me to query over an existing set of data, but I don't necessarily care what collection it is, as long as it implementsIEnumerable
.
- I use
List<T>
- I use a
List<T>
when I need a collection that could grow or shrink dynamically, i.e. the collection doesn't arealdy exist somewhere else and I may need to add or remove items from it. - A good example of this might be if you are allowing a user to add and remove items to a list box in the user interface of your application. Since the items in the list box might grow or shrink, a
List<T>
makes sense.
- I use a
ObservableCollection<T>
- I use this type of collection in the Silverlight/WPF world because it has built-in events for when the number of items in the collection changes. This is especially handy for data-binding scenarios when you want a UI element to automatically update when the list changes.
I almost never use Arrays explicitly unless I'm consuming an object that already has arrays. Granted, they're a nice lightweight way in which store a collection, but I can usually get by with the 3 types I listed above.
The property Resources
is returning an IEnumerable
. Enumerable.ToList()
builds a new list from this IEnumerable
. You are then adding an item to a new list, not the original collection that Resources
is accessing, hence your update is having no affect.
精彩评论