Is returning IList worse than returning T[] or List?
Is returning IList worse than returning T[] or List?
The answers to questions like this: List
public static IList ExposeArrayIList() { return new[] { 1, 2, 3 }; } public static IList ExposeListIList() { return new List { 1, 2, 3 }; }
And use them in my test program:
static void Main(string[] args) { IList arrayIList = ExposeArrayIList(); IList listIList = ExposeListIList(); //Will give a runtime error arrayIList.Add(10); //Runs perfectly listIList.Add(10); }
In both cases when I try to add a new value, my compiler gives me no errors, but obviously the method which exposes my array as an IList
gives a runtime error when I try to add something to it. So people who don't know what's happening in my method, and have to add values to it, are forced to first copy my IList
to a List
to be able to add values without risking errors. Of course they can do a typecheck to see if they're dealing with a List
or an Array
, but if they don't do that, and they want to add items to the collection they have no other choice to copy the IList
to a List
, even if it already is a List
. Should an array never be exposed as IList
?
Another concern of mine is based upon the accepted answer of the linked question (emphasis mine):
If you are exposing your class through a library that others will use, you generally want to expose it via interfaces rather than concrete implementations. This will help if you decide to change the implementation of your class later to use a different concrete class. In that case the users of your library won't need to update their code since the interface doesn't change.
If you are just using it internally, you may not care so much, and using List may be ok.
Imagine someone actually used my IList
they got from my ExposeListIlist()
method just like that to add/remove values. Everything works fine. But now like the answer suggests, because returning an interface is more flexible I return an array instead of a List (no problem on my side!), then they're in for a treat...
TLDR:
1) Exposing an interface causes unnecessary casts? Does that not matter?
2) Sometimes if users of the library don't use a cast, their code can break when you change your method, even though the method remains perfectly fine.
I am probably overthinking this, but I don't get the general consensus that returning an interface is to be preferred over returning an implementation.
Answer by dotctor for Is returning IList worse than returning T[] or List?
No, because the consumer should know what exactly IList is:
IList is a descendant of the ICollection interface and is the base interface of all non-generic lists. IList implementations fall into three categories: read-only, fixed-size, and variable-size. A read-only IList cannot be modified. A fixed-size IList does not allow the addition or removal of elements, but it allows the modification of existing elements. A variable-size IList allows the addition, removal, and modification of elements.
You can check for IList.IsFixedSize
and IList.IsReadOnly
and do what you want with it.
I think IList
is an example of a fat interface and it should have been split into multiple smaller interfaces and it also violates Liskov substitution principle when you return an array as an IList
.
Read more if you want to make decision about returning interface
UPDATE
Digging more and I found that IList
does not implement IList
and IsReadOnly
is accessible through base interface ICollection
but there is no IsFixedSize
for IList
. Read more about why generic IList<> does not inherit non-generic IList?
Answer by Dennis for Is returning IList worse than returning T[] or List?
Maybe this is not directly answering your question, but in .NET 4.5+, I prefer to follow these rules when designing public or protected APIs:
- do return
IEnumerable
, if only enumeration is available; - do return
IReadOnlyCollection
if both enumeration and items count are available; - do return
IReadOnlyList
, if enumeration, items count and indexed access are available; - do return
ICollection
if enumeration, items count and modification are available; - do return
IList
, if enumeration, items count, indexed access and modification are available.
Last two options assume, that method must not return array as IList
implementation.
Answer by CodeCaster for Is returning IList worse than returning T[] or List?
As with all "interface versus implementation" question, you'll have to realise what exposing a public member means: it defines the public API of this class.
If you expose a List
as a member (field, property, method, ...), you tell the consumer of that member: the type obtained by accessing this method is a List
, or something derived of that.
Now if you expose an interface, you hide the "implementation detail" of your class using a concrete type. Of course you can't instantiate IList
, but you can use an Collection
, List
, derivations thereof or your own type implementing IList
.
The actual question is "Why does Array
implement IList
", or "Why has the IList
interface so many members".
It also depends on what you want the consumers of that member to do. If you actually return an internal member through your Expose...
member, you'll want to return a new List
anyway, as otherwise the consumer can try and cast them to IList
and modify your internal member through that.
If you just expect consumers to iterate the results, expose IEnumerable
or IReadOnlyCollection
instead.
Answer by Martin Maat for Is returning IList worse than returning T[] or List?
Returning an interface is not necessarily better than returning a concrete implementation of a collection. You should always have a good reason to use an interface instead of a concrete type. In your example it seems pointless to do so.
Valid reasons to use an interface could be:
You do not know what the implementation of the methods returning the interface will look like and there may be many, developed over time. It may be other people writing them, from other companies. So you just want to agree on the bare necessities and leave it up to them how to implement the functionality.
You want to expose some common functionality independent from your class hierarchy in a type-safe way. Objects of different base types that should offer the same methods would implement your interface.
One could argue that 1 and 2 are basically the same reason. They are two different scenarios that ultimately lead to the same need.
"It's a contract". If the contract is with yourself and your application is closed in both functionality and time, there is often no point in using an interface.
Answer by craftworkgames for Is returning IList worse than returning T[] or List?
Be careful with blanket quotes that are taken out of context.
Returning an interface is better than returning a concrete implementation
This quote only makes sense if it's used in the context of the SOLID principles. There are 5 principles but for the purposes of this discussion we'll just talk about the last 3.
Dependency inversion principle
one should ?Depend upon Abstractions. Do not depend upon concretions.?
In my opinion, this principle is the most difficult to understand. But if you look at the quote carefully it looks a lot like your original quote.
Depend on interfaces (abstractions). Do no depend on concrete implementations (concretions).
This is still a little confusing but if we start applying the other principles together it starts to make a lot more sense.
Liskov substitution principle
?objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program.?
As you pointed out, returning an Array
is clearly different behavior to returning a List
even though they both implement IList
. This is most certainly a violation of LSP.
The important thing to realize is that interfaces are about the consumer. If you're returning an interface, you've created a contract that any methods or properties on that interface can be used without changing the behavior of the program.
Interface segregation principle
?many client-specific interfaces are better than one general-purpose interface.?
If you're returning an interface, you should return the most client specific interface your implementation supports. In other words, if you're not expecting the client to call the Add
method you shouldn't return an interface with an Add
method on it.
Unfortunately, the interfaces in the .NET framework (particularly the early versions) are not always ideal client specific interfaces. Although as @Dennis pointed out in his answer, there are a lot more choices in .NET 4.5+.
Fatal error: Call to a member function getElementsByTagName() on a non-object in D:\XAMPP INSTALLASTION\xampp\htdocs\endunpratama9i\www-stackoverflow-info-proses.php on line 72
0 comments:
Post a Comment