I see this a lot in tutorials, with navigation properties as ICollection<T>
.
Is this a mandatory requirement for Entity Framework? Can I use IEnumerable
?
What's the main purpose of using ICollection
instead of IEnumerable
or even List<T>
?
I see this a lot in tutorials, with navigation properties as ICollection<T>
.
Is this a mandatory requirement for Entity Framework? Can I use IEnumerable
?
What's the main purpose of using ICollection
instead of IEnumerable
or even List<T>
?
Usually what you choose will depend on which methods you need access to. In general - IEnumerable<>
(MSDN: http://msdn.microsoft.com/en-us/library/system.collections.ienumerable.aspx) for a list of objects that only needs to be iterated through, ICollection<>
(MSDN: http://msdn.microsoft.com/en-us/library/92t2ye13.aspx) for a list of objects that needs to be iterated through and modified, List<>
for a list of objects that needs to be iterated through, modified, sorted, etc (See here for a full list: http://msdn.microsoft.com/en-us/library/6sh2ey19.aspx).
From a more specific standpoint, lazy loading comes in to play with choosing the type. By default, navigation properties in Entity Framework come with change tracking and are proxies. In order for the dynamic proxy to be created as a navigation property, the virtual type must implement ICollection
.
A navigation property that represents the "many" end of a relationship must return a type that implements ICollection, where T is the type of the object at the other end of the relationship. -Requirements for Creating POCO ProxiesMSDN
List
should be a lot better, yeah? –
Obligate List
a lot. Although it has the most overhead it provides the most functionality. –
Stunk ListName[i]
which can be very handy. The sort is built in. –
Stunk List<T>
type, true, but that's more of an "extra". For example, the IList<T>
interface doesn't have a Sort()
method. –
Uttasta private IEnumerable<int> _integers = new List<int> { 1, 2, 3 };
uses the same memory as private List<int> _integers = new List<int> { 1, 2, 3 };
–
Uttasta List
with an IEnumberable
which is rather pointless. Just leave it as a List, you already took the hit! The point I was making of a small footprint in memory is that most IEnumberable
implement a deferred execution (your example just explicitly makes that execution to be at the time of definition). –
Stunk IEnumerable<T>
in my example with ICollection<T>
(which means we're no longer confused by the possibility of using linq queries). How does that use any less memory than List<T>
? –
Uttasta List<T>
has a GetEnumerator()
method, separate from its implementation of IEnumerable<T>
, which returns a mutable structure type List<T>.Enumerator
. In most contexts, that type will yield slightly better performance than would a standalone heap object. Compilers which duck-type enumerators (as both C# and vb.net do) can take advantage of this when generating foreach
code. If the List<T>
is cast to IEnumrable<T>
before the foreach
, the IEnumerable<T>.GetEnumerator()
method will return a heap-allocated object, rendering the optimization impossible. –
Supertonic IEnumarable
is not thread safe either so by using it next to async methods is somekind of violation on it its own. The problem is that every thread that iterates on IEnumarable executes the backing query and if the context is closed on the main thread, and already enumerated object in another thread, fails to enumerate in this thread. ICollection holds your nongeneric data enumerated, so after Linq-to-SQL has executed there is no point in passing IEnumarble up the Layers any more. IMHO –
Situla ICollection<T>
is used because the IEnumerable<T>
interface provides no way of adding items, removing items, or otherwise modifying the collection.
List<T>
implements ICollection<T>
. –
Huzzah ICollection
doesn't allow any way to add items, but it's still a useful adjunct to IEnumerable<T>
because it provides a Count
member which is typically much faster than enumerating everything. Note that if an IList<Cat>
or ICollection<Cat>
is passed to code expecting an IEnumerable<Animal>
, the Count()
extension method will be fast if it implements the non-generic ICollection
, but not if it only implements the generic interfaces since a typical ICollection<Cat>
will not implement ICollection<Animal>
. –
Supertonic Responding to your question about List<T>
:
List<T>
is a class; specifying an interface allows more flexibility of implementation. A better question is "why not IList<T>
?"
To answer that question, consider what IList<T>
adds to ICollection<T>
: integer indexing, which means the items have some arbitrary order, and can be retrieved by reference to that order. This is probably not meaningful in most cases, since items probably need to be ordered differently in different contexts.
There are some basics difference between ICollection and IEnumerable
Simple Program:
using System;
using System.Collections;
using System.Collections.Generic;
namespace StackDemo
{
class Program
{
static void Main(string[] args)
{
List<Person> persons = new List<Person>();
persons.Add(new Person("John",30));
persons.Add(new Person("Jack", 27));
ICollection<Person> personCollection = persons;
IEnumerable<Person> personEnumeration = persons;
// IEnumeration
// IEnumration Contains only GetEnumerator method to get Enumerator and make a looping
foreach (Person p in personEnumeration)
{
Console.WriteLine("Name:{0}, Age:{1}", p.Name, p.Age);
}
// ICollection
// ICollection Add/Remove/Contains/Count/CopyTo
// ICollection is inherited from IEnumerable
personCollection.Add(new Person("Tim", 10));
foreach (Person p in personCollection)
{
Console.WriteLine("Name:{0}, Age:{1}", p.Name, p.Age);
}
Console.ReadLine();
}
}
class Person
{
public string Name { get; set; }
public int Age { get; set; }
public Person(string name, int age)
{
this.Name = name;
this.Age = age;
}
}
}
I remember it this way:
IEnumerable has one method GetEnumerator() which allows one to read through the values in a collection but not write to it. Most of the complexity of using the enumerator is taken care of for us by the for each statement in C#. IEnumerable has one property: Current, which returns the current element.
ICollection implements IEnumerable and adds few additional properties the most use of which is Count. The generic version of ICollection implements the Add() and Remove() methods.
IList implements both IEnumerable and ICollection, and add the integer indexing access to items (which is not usually required, as ordering is done in database).
The basic idea of using ICollection
is a provide an interface to readonly-access to some finite amount of data. In fact you have a ICollection.Count property. IEnumerable
is more suitable for some chain of the data where you read till some logical point, some condition esplicitly specified by consumer or till the end of the enumeration.
ICollection
is read-only while ICollection<T>
is not. –
Buyse What I have done in the past is declare my inner class collections using IList<Class>
, ICollection<Class>
or IEnumerable<Class>
(if static list) depending on whether or not I will have to do any number of the following in a method in my repository: enumerate, sort/order or modify. When I just need to enumerate (and maybe sort) over objects then I create a temp List<Class>
to work with the collection within an IEnumerable method. I think this practice would only be effective if the collection is relatively small, but it may be good practice in general, idk. Please correct me if there is evidence as to why this would not good practice.
Navigation properties are typically defined as virtual so that they can take advantage of certain Entity Framework functionality such as lazy loading.
If a navigation property can hold multiple entities (as in many-to-many or one-to-many relationships), its type must be a list in which entries can be added, deleted, and updated, such as ICollection.
Lets try thinking outside of the box with/by logic and understand clearly these three interfaces in your question:
When the class of some instance implements the System.Collection.IEnumerable interface then, in simple words, we can say that this instance is both enumerable and iterable, which means that this instance allows somehow in a single loop to go/get/pass/traverse/iterate over/through all the items and elements that this instance contains.
This means that this is also possible to enumerate all the items and elements that this instance contains.
Every class that implements the System.Collection.IEnumerable interface also implements the GetEnumerator method that takes no arguments and returns an System.Collections.IEnumerator instance.
Instances of System.Collections.IEnumerator interface behaves very similar to C++ iterators.
When the class of some instance implements the System.Collection.ICollection interface then, in simple words, we can say that this instance is some collection of things.
The generic version of this interface, i.e. System.Collection.Generic.ICollection, is more informative because this generic interface explicitly states what is the type of the things in the collection.
This is all reasonable, rational, logical and makes sense that System.Collections.ICollection interface inherits from System.Collections.IEnumerable interface, because theoretically every collection is also both enumerable and iterable and this is theoretically possible to go over all the items and elements in every collection.
System.Collections.ICollection interface represents a finite dynamic collection that are changeable, which means that exist items can be removed from the collection and new items can be added to the same collection.
This explains why System.Collections.ICollection interface has the "Add" and "Remove" methods.
Because that instances of System.Collections.ICollection interface are finite collections then the word "finite" implies that every collection of this interface always has a finite number of items and elements in it.
The property Count of System.Collections.ICollection interface supposes to return this number.
System.Collections.IEnumerable interface does not have these methods and properties that System.Collections.ICollection interface has, because it does not make any sense that System.Collections.IEnumerable will have these methods and properties that System.Collections.ICollection interface has.
The logic also says that every instance that is both enumerable and iterable is not necessarily a collection and not necessarily changeable.
When I say changeable, I mean that don't immediately think that you can add or remove something from something that is both enumerable and iterable.
If I just created some finite sequence of prime numbers, for example, this finite sequence of prime numbers is indeed an instance of System.Collections.IEnumerable interface, because now I can go over all the prime numbers in this finite sequence in a single loop and do whatever I want to do with each of them, like printing each of them to the console window or screen, but this finite sequence of prime numbers is not an instance of System.Collections.ICollection interface, because this is not making sense to add composite numbers to this finite sequence of prime numbers.
Also you want in the next iteration to get the next closest larger prime number to the current prime number in the current iteration, if so you also don't want to remove exist prime numbers from this finite sequence of prime numbers.
Also you probably want to use, code and write "yield return" in the GetEnumerator method of the System.Collections.IEnumerable interface to produce the prime numbers and not allocating anything on the memory heap and then task the Garbage Collector (GC) to both deallocate and free this memory from the heap, because this is obviously both waste of operating system memory and decreases performance.
Dynamic memory allocation and deallocation on the heap should be done when invoking the methods and properties of System.Collections.ICollection interface, but not when invoking the methods and properties of System.Collections.IEnumerable interface (although System.Collections.IEnumerable interface has only 1 method and 0 properties).
According to what others said in this Stack Overflow webpage, System.Collections.IList interface simply represents an orderable collection and this explains why the methods of System.Collections.IList interface work with indexes in contrast to these of System.Collections.ICollection interface.
In short System.Collections.ICollection interface does not imply that an instance of it is orderable, but System.Collections.IList interface does imply that.
Theoretically ordered set is special case of unordered set.
This also makes sense and explains why System.Collections.IList interface inherits System.Collections.ICollection interface.
Googling brought me here, and I haven't seen anyone mention this yet. I just got bamboozled by an API that looks similar to the following:
void Load(object key)
void Load(IEnumerable keys)
Passing in a string selects the IEnumerable
overload, which is not what I (nor the API authors) intended. If the IEnumerable
would have been an ICollection
instead, then the object
overload would have been selected for strings, which is the intention.
Just something to think about when trying to express intent in APIs. I'd guess it's more common than not for people to use IEnumerable
even when their intent is to treat the type as a collection and NOT include other types of enumerables (like string
).
© 2022 - 2024 — McMap. All rights reserved.