Reputation: 6868
I have a class library which contains a method returning List to the clients (mvc,console app etc...).
Now while I was reading Guidelines for Collections, I came to know about below point:
X DO NOT use ArrayList or
List<T>
in public APIs.
Currently the client which is consuming my class library api is MVC which just loops on it and perform some string.format on some properties from List<Statistics>
but do not change anything on original list.
I have thought of considering IEnumerable<Statistics>
but then client can also cast it to List and then manipulate it and same goes with IReadOnlyList also.
MSDN design guidelines does not state that if not ArrayList
or List<T>
then what should be the appropriate COLLECTION for return List of something for public API?
This is my base class which is exposed to client :
public abstract class BaseManager
{
//Other shared code
public abstract List<Statistics> GetStatistics();
}
public class Manager1 : BaseManager
{
public override List<Statistics> GetStatistics()
{
var stats = new List<Statistics>();
stats.Add(new Statistics { .... });
stats.Add(new Statistics { .... });
stats.Add(new Statistics { .... });
stats.Add(new Statistics { .... });
return stats;
}
}
Upvotes: 0
Views: 1750
Reputation: 82514
As a rule of thumb, you want to expose to your clients as little as possible.
You also don't want to tie them to a specific implementation if you have an interface that guarantees the contract you allow them.
So, in this spirit -
If you want your client to only be able to read the data returned using a foreach
loop, then return an IEnumerable<T>
.
If you want your clients to have access to the count
property, return an IReadOnlyCollection<T>
.
If you want your client to be able to access a specific part of the data based on it's index, than return an IReadOnlyList<T>
.
Please note that IReadOnlyList<T>
inherits the IReadOnlyCollection<T>
and this interface inherits the IEnumerable<T>
- so all of these options will allow the usage of foreach
, the last two will allow the usage of count
(as a property), and the last one will allow the usage of an indexer.
Also, please note that your underlying type can still be a List
as it implements the IReadOnlyList<T>
and therefor all other interfaces I've mentioned.
Another thing to keep in mind is that the ReadOnly
in this case does not mean that all the members held by the collection are immutable - you can still change the properties of them (assuming they are mutable types) - but the collection itself being immutable - you can't add or remove items to / from it.
Update
Following your comment:
If the IEnumerable<T>
is a list you can down-cast it:
IEnumerable<int> myIEnum = new List<int>();
var myList = (List<int>)myIEnum;
But the ToList()
extension method only creates a list that is a copy of the original IEnumerable<T>
.
If your base class would be:
public abstract class BaseManager
{
//Other shared code
public abstract IEnumerable<Statistics> GetStatistics();
}
The derived classes can still use a list inside the method, but will return it as an IEnumerable<Statistics>
:
public class Manager1 : BaseManager
{
public override IEnumerable<Statistics> GetStatistics()
{
var stats = new List<Statistics>();
stats.Add(new Statistics { .... });
stats.Add(new Statistics { .... });
stats.Add(new Statistics { .... });
stats.Add(new Statistics { .... });
return stats;
}
}
If you want to actually create an IEnumerable
that can't be down-cast to a list you can always do this:
public override IEnumerable<Statistics> GetStatistics()
{
var stats = new List<Statistics>();
stats.Add(new Statistics { .... });
stats.Add(new Statistics { .... });
stats.Add(new Statistics { .... });
stats.Add(new Statistics { .... });
foreach(var stat in stats)
{
yield return stat;
}
}
Upvotes: 2
Reputation: 27254
If you are familiar with .Net, you may notice there are a lot class with the name of _______Collection
. They match the conditions in the article, so I think they are what the guideline recommends.
Such as:
So what they suggest are
StatisticsCollection
ICollection<Statistics>
Upvotes: 0