What's the Difference Between Ienumerable and Array, Ilist and List

What's the difference between IEnumerable and Array, IList and List?

IEnumerable provides only minimal "iterable" functionality. You can traverse the sequence, but that's about it.

This has disadvantages; for example, it is very inefficient to count elements using IEnumerable, or to get the nth element.

But it has advantages too; for example, an IEnumerable could be an endless sequence, like the sequence of primes.

Array is a fixed-size collection with random access (i.e. you can index into it).

List is a variable-size collection (i.e. you can add and remove elements) with random access.

IList is an interface which abstracts list functionality (count, add, remove, indexer access) away from the various concrete classes such as List, BindingList, ObservableCollection, etc.

Comparison between List, IList, and IEnumerable


  • IEnumerable<T> is the base interface that the following extend or implement. It doesn't allow for direct access and is readonly. So use this only if you intend to iterate over the collection.

  • ICollection<T> extendsIEnumerable<T> but in addition allows for adding, removing, testing whether an element is present in the collection and getting the total number of elements. It doesn't allow for directly accessing an element by index. That would be an O(n) operation as you need to start iterating over it until you find the corresponding element.

  • IList<T> extends ICollection<T> (and thus it inherits all its properties) but in addition allows for directly accessing elements by index. It's an O(1) operation.

  • List<T> is just a concrete implementation of the IList<T> interface.

In your code you should always expose the type that's highest in the object hierarchy that will correspond to the needs of the callers. So for example if the callers are only going to enumerate over the dataset, use IEnumerable<T>. If they need to have direct access to elements by index expose an IList<T>.

List<T> should only be used internally by your code but usually not present in the signature of the methods you are exposing. This gives you more flexibility as you could easily swap the concrete implementation without breaking the contract.

C# IEnumerable and IList difference

IList inherits from IEnumerable so they are essentially the same just IList has extra functionality.

It depends on what you are doing with that data once its created as to whether you should use an IEnumerable or IList.

IEnumerable is good if you only want to iterate over the collections content as its readonly.

IList allows adding and removing of content (so does ICollection) and allows direct access to elements with an index

What's the difference between List string and IEnumerable String ?

A List<string> is a concrete implementation of IEnumerable<string>. The difference is that IEnumerable<string> is merely a sequence of string but a List<string> is indexable by an int index, can be added to and removed from and have items inserted at a particular index.

Basically, the interface IEnumerable<string> lets you stream the string in the sequence but List<string> lets you do this as well as modify and access the items in the lists in specific ways. An IEnumerable<string> is general sequence of string that can be iterated but doesn't allow random access. A List<string> is a specific random-access variable-size collection.

What is the difference between returning IList vs List, or IEnumerable vs List Class . I want to know which is better to return

There is no such a type that is always better to return. It's a decision you should make based on your design/performance/etc goals.

IEnumerable<T> is nice to use when you want to represent sequence of items, that you can iterate over, but you don't want to allow modifications(Add, Delete etc).

IList<T> gives you everything you could get using IEnumerable<T>, plus operations that give you more control over a collection: Add, Delete, Count, Index access etc.

List<T> is a concrete implementation of IList<T>. I would say that almost always it's better to expose IList<T> interface from your methods rather that List<T> implementation. And it's not just about lists - it's a basic design principle to prefer interfaces over concrete implementations.

Ok, now about non-generic versions IEnumerable, IList, List:
They actually came from very early versions of .NET framework, and life is much better using generic equivalents.

And few words about performance:
IEnumerable<T>(with IEnumerator<T>) is actually an iterator which allows you to defer some computations until later. It means that there is no need to allocate memory right away for storing amounts of data(of course, it's not the case when you have, say, array behind iterator). You can compute data gradually as needed. But it means that these computations might be performed over and over again(say, with every foreach loop). On the other hand, with List you have fixed data in memory, with cheap Index and Count operations. As you see, it's all about compromise.

Why is an IEnumerable(or IList) implemented using arrays instead of Linked Lists?


I was under the impression that an IENumerable is essentially very
similar to a linked list.

I'm not really sure where you got that impression. An object implementing IEnumerable or IEnumerable<T> means "this object exposes an enumerator, which makes it iteratable", it has nothing to do directly to an implementation of a linked list, or an array. They do both share the common feature of being iteratable. It is a binding contract to the caller.

So then why is one (a linked list) being implemented using the other
(an array) when we actually argue that they are quite different?

A linked list can have an array as it's storage as an implementation detail, though that would definitely be a poor design choice.

You may note that List<T> also uses an array as it's internal storage, which it re-sizes once it hits the maximum size of the internal array.

Practical difference between List and IEnumerable

One important difference between IEnumerable and List (besides one being an interface and the other being a concrete class) is that IEnumerable is read-only and List is not.

So if you need the ability to make permanent changes of any kind to your collection (add & remove), you'll need List. If you just need to read, sort and/or filter your collection, IEnumerable is sufficient for that purpose.

So in your practical example, if you wanted to add the four strings one at a time, you'd need List. But if you were instantiating your collection all at once, you could use IEnumerable.

IEnumerable firstFourLettersOfAlphabet = new[]{"a","b","c","d"};

You could then use LINQ to filter or sort the list however you wanted.

IEnumerable vs List - What to Use? How do they work?

IEnumerable describes behavior, while List is an implementation of that behavior. When you use IEnumerable, you give the compiler a chance to defer work until later, possibly optimizing along the way. If you use ToList() you force the compiler to reify the results right away.

Whenever I'm "stacking" LINQ expressions, I use IEnumerable, because by only specifying the behavior I give LINQ a chance to defer evaluation and possibly optimize the program. Remember how LINQ doesn't generate the SQL to query the database until you enumerate it? Consider this:

public IEnumerable<Animals> AllSpotted()
{
return from a in Zoo.Animals
where a.coat.HasSpots == true
select a;
}

public IEnumerable<Animals> Feline(IEnumerable<Animals> sample)
{
return from a in sample
where a.race.Family == "Felidae"
select a;
}

public IEnumerable<Animals> Canine(IEnumerable<Animals> sample)
{
return from a in sample
where a.race.Family == "Canidae"
select a;
}

Now you have a method that selects an initial sample ("AllSpotted"), plus some filters. So now you can do this:

var Leopards = Feline(AllSpotted());
var Hyenas = Canine(AllSpotted());

So is it faster to use List over IEnumerable? Only if you want to prevent a query from being executed more than once. But is it better overall? Well in the above, Leopards and Hyenas get converted into single SQL queries each, and the database only returns the rows that are relevant. But if we had returned a List from AllSpotted(), then it may run slower because the database could return far more data than is actually needed, and we waste cycles doing the filtering in the client.

In a program, it may be better to defer converting your query to a list until the very end, so if I'm going to enumerate through Leopards and Hyenas more than once, I'd do this:

List<Animals> Leopards = Feline(AllSpotted()).ToList();
List<Animals> Hyenas = Canine(AllSpotted()).ToList();

IEnumerable T vs. Array

Usually - and since a while - this solved using immutable collections.

Your public properties should be, for example, of type IImmutableList<T>, IImmutableHashSet<T> and so on.

Any IEnumerable<T> can be converted to an immutable collection:

  • someEnumerable.ToImmutableList();
  • someEnumerable.ToImmutableHashSet();
  • ... and so on.

This way you can work with private properties using mutable collections and provide a public surface of immutable collections only.

For example:

public class A
{
private List<string> StringListInternal { get; set; } = new List<string>();
public IImmutableList<string> StringList => StringListInternal.ToImmutableList();
}

There's also an alternate approach using interfaces:

public interface IReadOnlyA
{
IImmutableList<string> StringList { get; }
}

public class A : IReadOnlyA
{
public List<string> StringList { get; set; } = new List<string>();
IImmutableList<string> IReadOnlyA.StringList => StringList.ToImmutableList();
}

Check that IReadOnlyA has been explicitly-implemented, thus both mutable and immutable StringList properties can co-exist as part of the same class.

When you want to expose an immutable A, then you return your A objects upcasted to IReadOnlyA and upper layers won't be able to mutate the whole StringList in the sample above:

public IReadOnlyA DoStuff()
{
return new A();
}

IReadOnlyA a = DoStuff();

// OK! IReadOnly.StringList is IImmutableList<string>
IImmutableList<string> stringList = a.StringList;

Avoiding converting the mutable list to immutable list every time

It should be a possible solution to avoid converting the source list into immutable list each time immutable one is accessed.

Equatable members

If type of items overrides Object.Equals and GetHashCode, and optionally implements IEquatable<T>, then both public immutable list property access may look as follows:

public class A : IReadOnlyA
{
private IImmutableList<string> _immutableStringList;

public List<string> StringList { get; set; } = new List<string>();

IImmutableList<string> IReadOnlyA.StringList
{
get
{
// An intersection will verify that the entire immutable list
// contains the exact same elements and count of mutable list
if(_immutableStringList.Intersect(StringList).Count == StringList.Count)
return _immutableStringList;
else
{
// the intersection demonstrated that mutable and
// immutable list have different counts, thus, a new
// immutable list must be created again
_immutableStringList = StringList.ToImmutableList();

return _immutableStringList;
}
}
}
}


Related Topics



Leave a reply



Submit