Possible Duplicate:
Collection<T> versus List<T> what should you use on your interfaces?
Consider this method—the returned variable myVar
is a List<T>
, but the return type of the method MyMethod()
is an IEnumerable<T>
:
public IEnumerable<T> MyMethod(string stuff)
{
var myVar = new List<T>();
//do stuff
return myVar;
}
Essentially, what I want to know is if returning myVar
as a different type is OK.
Specifically, with respect to my situation, the 'do stuff' goes through a DataRow
and assigns the items in that DataRow
to a list of objects. I also have similar situations with ICollection
and IList
return types in other places.
The reason I want to return either IEnumerable
or ICollection
is so that I'm not returning more than needed. But at the same time, this allows the caller to convert the returned value to a List
if it needs to do so.
However, it seems weird that my return statement is returning a List
, instead of what the method's return type is. Is this normal practice? Is there anything wrong with doing this?
Clarification (in response to the dupe comments):
Just to clarify, what I'm curious about is if it is okay that my return statement in the body is returning a List<T>
, but the method header has a return-type of IEnumerable
, or possibly ICollection
, Collection
, etc... Something different than than bodies return statement.
Not only there's nothing wrong with it, but it's actually good practice: expose only what is strictly necessary. That way, the caller can't rely on the fact that the method will return a List<T>
, so if for some reason you need to change the implementation to return something else, you won't break your contract. However the calling code might break if it (incorrectly) made assumptions about what the method actually returns.
The reason to return IEnumerable<T>
type is so that they caller cannot modify the list (without casting it back to a list). If you notice all(most?) the extension methods take an IEnumerable<T>
argument, so that you know that the extension method doesn't modify your list.
Secondly, List<T>
inherits from IEnumerable<T>
.
Edit:
As Thomas explained in a comment that the IEnumerable<T>
could be cast back to a List<T>
and modified by the caller. If your main goal is to make it Read-Only, you can return the list as myVar.AsReadOnly()
. But then the type is ReadOnlyCollection<T>
.
There is nothing wrong with it.
Actually returning concrete class is the only way to satisfy "returns interface" requirement.
There could be drawbacks if you let the knowledge of particular classes to sneak in to calling code (List<T> r = (List<T>)MyMethod("ff")
). But if you treat result as interface (as you supposed to) it is ok.
I think this isn't optimal, since it allows the caller to cast to List<T>
, which relies on an implementation detail. I'd add some kind of masking, such as Select(x=>x)
.
A dynamically typed caller might not even notice that you cast your list to IEnumerable<T>
. For him it's simply List<T>
.
Returning an internal permanent List<T>
as IEnumerable<T>
would be very wrong, since it allows the caller to mutate internal state of your class. But since you return a new instance of List<T>
on every call, that's not used anywhere else, this argument doesn't apply in your example.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With