IEnumerable & Good Practices (& WCF) - c#

Is it a good practice to use IEnumerable application-wide whenever you don't need to actually add or remove things but only enumerate them?
Side question: Did you ever have any problems returning IEnumerable<T> from a WCF service? Can that cause problems to client applications? After all, I think that will be serialized to an array.

I tend to only return IEnumerable<T> when I want to hint to the caller that the implementation may use lazy evaluation. Otherwise, I'd usually return IList<T> or ICollection<T>, and implement as a ReadOnlyCollection<T> if the result should be readonly.
Lazy evaluation can be an important consideration: if your implementation can throw an exception, this won't be thrown until the caller starts enumerating the result. By returning IList<T> or ICollection<T>, you're guaranteeing that any exception will be thrown at the point the method is called.
In the case of a WCF method, returning IEnumerable<T> from a method that uses lazy evaluation means any exception might not be thrown until your response is being serialized - giving you less opportunity to handle it server-side.

I don't have any Good Practices sources, but i often tend to rely on List for my collections and it implements IEnumerable but i do pass it around as a List and not a IEnumerable, if i need it to be read only i rather pass a ReadOnlyCollection..

I don't like to return or accept IList<T> or List<T> because they implies the ability to modify a collection.
So prefer to return T[] as fixed-sized collection. Also array can be easily mapped to any other framework, platform, etc.
And prefer to accept IEnumerable<T> to emphasize that a method will enumerate that collection.

Related

IEnumerable to IReadOnlyCollection

I have IEnumerable<Object> and need to pass to a method as a parameter but this method takes IReadOnlyCollection<Object>
Is it possible to convert IEnumerable<Object> to IReadOnlyCollection<Object> ?
One way would be to construct a list, and call AsReadOnly() on it:
IReadOnlyCollection<Object> rdOnly = orig.ToList().AsReadOnly();
This produces ReadOnlyCollection<object>, which implements IReadOnlyCollection<Object>.
Note: Since List<T> implements IReadOnlyCollection<T> as well, the call to AsReadOnly() is optional. Although it is possible to call your method with the result of ToList(), I prefer using AsReadOnly(), so that the readers of my code would see that the method that I am calling has no intention to modify my list. Of course they could find out the same thing by looking at the signature of the method that I am calling, but it is nice to be explicit about it.
Since the other answers seem to steer in the direction of wrapping the collections in a truly read-only type, let me add this.
I have rarely, if ever, seen a situation where the caller is so scared that an IEnumerable<T>-taking method might maliciously try to cast that IEnumerable<T> back to a List or other mutable type, and start mutating it. Cue organ music and evil laughter!
No. If the code you are working with is even remotely reasonable, then if it asks for a type that only has read functionality (IEnumerable<T>, IReadOnlyCollection<T>...), it will only read.
Use ToList() and be done with it.
As a side note, if you are creating the method in question, it is generally best to ask for no more than an IEnumerable<T>, indicating that you "just want a bunch of items to read". Whether or not you need its Count or need to enumerate it multiple times is an implementation detail, and is certainly prone to change. If you need multiple enumeration, simply do this:
items = items as IReadOnlyCollection<T> ?? items.ToList(); // Avoid multiple enumeration
This keeps the responsibility where it belongs (as locally as possible) and the method signature clean.
When returning a bunch of items, on the other hand, I prefer to return an IReadOnlyCollection<T>. Why? The goal is to give the caller something that fulfills reasonsable expectations - no more, no less. Those expectations are usually that the collection is materialized and that the Count is known - precisely what IReadOnlyCollection<T> provides (and a simple IEnumerable<T> does not). By being no more specific than this, our contract matches expectations, and the method is still free to change the underlying collection. (In contrast, if a method returns a List<T>, it makes me wonder what context there is that I should want to index into the list and mutate it... and the answer is usually "none".)
As an alternative to dasblinkenlight's answer, to prevent the caller casting to List<T>, instead of doing orig.ToList().AsReadOnly(), the following might be better:
ReadOnlyCollection<object> rdOnly = Array.AsReadOnly(orig.ToArray());
It's the same number of method calls, but one takes the other as a parameter instead of being called on the return value.

Is the lost of efficiency worth returning IEnumerable instead of List?

Everytime I've had to return a collection, I've returned a List. I've just read that I should return IEnumerable or similar interface (IQueryable for instance).
The problem I see is that often I want to work with a List. To do that, I'd have to do a .ToList() on the returned result.
Example
//...
List<Guid> listOfGuids = MyMethod().ToList();
//...
public IEnumerable<Guid> MyMethod()
{
using (var context = AccesDataRépart.GetNewContextRépart())
{
return context.MyTable.ToList();
}
}
Is executing a .ToList() twice the right practice.
If the caller actually needs a list, return a list (if that's what you have). Returning an IEnumerable when you already have a list, and when you know the caller is going to need a list, is just being wasteful, and for no real benefit.
If you feel that there is a chance that you'll be changing the underlying type of the object you are returning in future versions of the method it can, potentially, make it a bit easier on the library implementer to return an interface instead, but it's easier on the caller of the method when a more derived type is returned (they have the ability to do more with it than if they are just given an interface).
It is the reverse with input parameters. When passing parameters in the more derived the type the more "power" the library implementer has to work with the type, especially in future revisions, but using a much less restrictive type makes life easier on the caller of your library, as they don't need to convert what they have to what your method accepts.
This makes these decisions something to think about a fair bit when writing a libraries public API. You need to consider how much "power" you need right now, as well as how much you think you might need in the future. Once you know how restrictive/general the types need to be for you to do your job, you can then work to make your methods more convenient to use for callers. There is no one answers that will apply in every case. Saying that you should always return IEnumerable instead of List isn't proper, just the same as saying that you should always return List is also improper. You need to make a judgement call based on the specific situation you are in.
I would recommend just returning a List<T>, or perhaps an IList<T>. The reason that someone might recommend against returning List, is that it locks you in to that implementation. Depending on the usage of the API, that might not be a concern.
My general rule of thumb is to be more permissive in what you accept and more specific in what you return. So, IEnumerable<T> for method parameters, and IList<T>, List<T> or possibly even T[] for method return values.
You don't have to call ToList on the returned value, It is already a List. The reason you can't return IEnumerable is that you have using statement around your DataContext it will be disposed. So modify your method return type as List<T> and then don't call ToList on the returned value.
//...
List<Guid> listOfGuids = MyMethod(); //No ToList here
//...
public List<Guid> MyMethod()
{
using (var context = AccesDataRépart.GetNewContextRépart())
{
return context.MyTable.ToList();
}
}
I've just read that I should return IEnumerable or similar interface
(IQueryable for instance).
Don't worry about that - return IList<> or List<> if you actually need a list object at the point the collection is consumed. The problem with returning IEnumerable can be that no-one knows what the cost of enumerating it is going to be - which is a down-side to the whole Linq concept that doesn't always get fair mention from the people who are encouraging everyone to return IEnumerable everywhere.
It really depends. Do you want to enumerate the collection before or after returning it?
Enumerate before: Every time you call ToList, ToArray, etc. you are enumerating the IEnumerable. If you are doing this many times after it is returned, this can be redundant and wasteful. Either returning it in an already enumerated form (e.g., IList, Array) or enumerating it once after returned and using that for the future processing probably be more preferable.
Enumerate after: Returning an IEnumerable allows you to defer the enumeration of the collection until later (e.g., save processing up front). If it turns out that you never end up enumerating the collection, or you only enumerate a subset of it, then the IEnumerable approach can be very advantageous.

Why is IList not deferred execution?

As I understand it IEnumerable and IQueryable are deferred execution. Why wouldn't it be of benefit for IList to also support deferred execution?
The longer I think about it, the more I question whether the whole idea of "deferred execution" is actually of pedagogic value at all.
I'll answer your question by denying it. IEnumerable<T>, IQueryable<T> and IList<T> do not in any way represent "deferred" or "eager" calculations.
Rather, interfaces represent an ability to provide a service. IEnumerable<T> represents the service "I can provide a sequence, possibly infinite, of items of type T, one at a time". IQueryable<T> represents the service "I can represent a query against a data source, and provide the results of that query on demand". IList<T> represents the service "I can provide random access to a possibly mutable, finite-sized list of items of type T".
None of those services say anything about the implementation details of the service providers. The provider of an IList<T> service could be entirely lazy; the provider of an IQueryable<T> service could be entirely eager. If you want to make a deferred-execution IList<T>, you go right ahead. No one is stopping you!
IList<T> supports random access via the indexer - as well as the Count property. Both of these go against the spirit of deferred execution with streaming data, unless you're suggesting that you really just want something which loads the entire list as soon as you access anything. If that's what you're after, Lazy<T> might be the ticket...
As #Joe pointed out, IList<T> abstracts a noun. IEnumerable<T> and IQueryable<T> are abstractions of verbs.
IList<T> is an abstraction of a collection that can be treated as a list. IEnumerable<T> and 'IQueryable abstract actions: the enumeration over, or querying of the items contained in the underlying collection.
Think through the consequences of what you're saying.
What would be deferred, and until when?
In the case of IEnumerable and IQueryable what's deferred is the enumeration. And the interfaces don't expose anything else that depends on the enumeration having been done.
There are a multitude of reasons, just some:
an IList should be independent from the underlying data source that
was used to create the IList
accessing an IList member by index is expected to be O(1) - with deferred execution this cannot be guaranteed - access might be very slow, at least the first time.
accessing an IList member should not produce an exception because of how the IList being constructed when you access (there are all sorts of problems that can arise with deferred execution, think i.e. not being able to access the original data source) - this is going back to the first point.

Is it bad practice to use generics as return values from functions?

Somebody told me this but i have not seen this anywhere and i have used it all over, i don't see why would it be bad practice.
Example of what i mean is having functions such as:
public List<SomeCustomeType> GetListOfStuff()
{
}
or
public void DoSomeStuff(List<SomeCustomeType> param)
{
}
can anyone tell me why would this be bad practice or should not be used?
thanks!
Closed and Open generic types can be and are used in the framework and should be used. If you are using an incorrect type or exposing functionality you don't need, then it might be bad practice - for example, it is better to return IList<T> then List<T> as then you are not tied to the implementation and can use any type that implements IList<T>.
In a similar vein, you should only use types that expose the minumun required - better to return IEnumerable<T> than IList<T> if you only ever need to enumerate over the returned list.
In the era of LINQ and its associated extension methods, it's considered best practice to return IEnumerable<T>, even if the underlying collection implements IList<T>. The LINQ extension methods Count() and ElementAt() both have optimizations when the underlying collection is an IList<T>, so the performance impact is generally negligible.
This practice insulates the client code from the details of how you're managing the collection (maybe you'll want to use a different type of collection in the future?) The main thing to consider when following this pattern is to clearly document if you're doing some form of stateful lazy evaluation that may warrant the client caching the result on their own (using ToArray(), for instance.)
No, it's not bad. It might be better to use the generic interface IList<T> than the generic class List<T>, though.
the first is better by far. it is clear that the method creates new list and return it,
it is unclear who is responsible to create the second version list and what will happen if it is not empty...

IEnumerable<T> vs T[]

I just realize that maybe I was mistaken all the time in exposing T[] to my views, instead of IEnumerable<T>.
Usually, for this kind of code:
foreach (var item in items) {}
item should be T[] or IEnumerable<T>?
Than, if I need to get the count of the items, would the Array.Count be faster over the IEnumerable<T>.Count()?
IEnumerable<T> is generally a better choice here, for the reasons listed elsewhere. However, I want to bring up one point about Count(). Quintin is incorrect when he says that the type itself implements Count(). It's actually implemented in Enumerable.Count() as an extension method, which means other types don't get to override it to provide more efficient implementations.
By default, Count() has to iterate over the whole sequence to count the items. However, it does know about ICollection<T> and ICollection, and is optimised for those cases. (In .NET 3.5 IIRC it's only optimised for ICollection<T>.) Now the array does implement that, so Enumerable.Count() defers to ICollection<T>.Count and avoids iterating over the whole sequence. It's still going to be slightly slower than calling Length directly, because Count() has to discover that it implements ICollection<T> to start with - but at least it's still O(1).
The same kind of thing is true for performance in general: the JITted code may well be somewhat tighter when iterating over an array rather than a general sequence. You'd basically be giving the JIT more information to play with, and even the C# compiler itself treats arrays differently for iteration (using the indexer directly).
However, these performance differences are going to be inconsequential for most applications - I'd definitely go with the more general interface until I had good reason not to.
It's partially inconsequential, but standard theory would dictate "Program against an interface, not an implementation". With the interface model you can change the actual datatype being passed without effecting the caller as long as it conforms to the same interface.
The contrast to that is that you might have a reason for exposing an array specifically and in which case would want to express that.
For your example I think IEnumerable<T> would be desirable. It's also worthy to note that for testing purposes using an interface could reduce the amount of headache you would incur if you had particular classes you would have to re-create all the time, collections aren't as bad generally, but having an interface contract you can mock easily is very nice.
Added for edit:
This is more inconsequential because the underlying datatype is what will implement the Count() method, for an array it should access the known length, I would not worry about any perceived overhead of the method.
See Jon Skeet's answer for an explanation of the Count() implementation.
T[] (one sized, zero based) also implements ICollection<T> and IList<T> with IEnumerable<T>.
Therefore if you want lesser coupling in your application IEnumerable<T> is preferable. Unless you want indexed access inside foreach.
Since Array class implements the System.Collections.Generic.IList<T>, System.Collections.Generic.ICollection<T>, and System.Collections.Generic.IEnumerable<T> generic interfaces, I would use IEnumerable, unless you need to use these interfaces.
http://msdn.microsoft.com/en-us/library/system.array.aspx
Your gut feeling is correct, if all the view cares about, or should care about, is having an enumerable, that's all it should demand in its interfaces.
What is it logically (conceptually) from the outside?
If it's an array, then return the array. If the only point is to enumerate, then return IEnumerable. Otherwise IList or ICollection may be the way to go.
If you want to offer lots of functionality but not allow it to be modified, then perhaps use a List internally and return the ReadonlyList returned from it's .AsReadOnly() method.
Given that changing the code from an array to IEnumerable at a later date is easy, but changing it the other way is not, I would go with a IEnumerable until you know you need the small spead benfit of return an array.

Categories