I installed FxCop and had it analyze my application. In several spots, it says:
"Do not expose List<T> in object models. Use Collection<T>,
ReadOnlyCollection<T> or KeyedCollection<K,V> instead.
List<T> is meant to be used from implementation, not
in object model API. List<T> is optimized for performance
at the cost of long term versioning. For example, if
you return List<T> to the client code, you will not
ever be able to receive notifications when client code
modifies the collection."
I'm a bit weak in my OO.. so I'm not sure what "expose" really means in this context. Is this saying to not use List<T> Why not

We're not supposed to use List<T> ? ( List )
SameerNSameer
mtronix
Note, though, if you hide members as you have done, instead of overriding virtual members, the behavior changes depending on the compile-time type. For example, if you do this:
It will call List<>.Add(), not ColumnList.Add(). You may say you'll never cast ColumnList as List< Column >, but a month or two down the road, you may have forgotten this bit, and do so because you came up with a situation where it's desirable to treat it as List<> seeing that List<> is a superclass.
Tim Dallmann
Hi,
I've implemented this thing in a treelist control I made recently.
If you expose List<T> in your class, the user of the class can directly Add or Remove items from it using collection methods. Now what if you want to do some other things before adding it to the collection. for that we need a collection class.
class ColumnList : List<Column>
{
// provide your own Add method
public new void Add(string columnname)
{
Column col = new Column(columnname);
col.Width = DEFAULT_WIDTH;
base.Add(col);
}
}
So, I'll expose ColumnList as a property in my class.
regards
Kevin Rodgers
A related, maybe more important, reason to use interface, rather than class, to expose features is that it faciliates looser coupling between your code and your users' code (or between different modules in your case).
Anyway, there are general OO rules, but no dogma. Each design decision has its own cost and benefit depending on the context, and you should use what you think is the best for the situation.
ernisj
Also, if I did want the ability to sort the list, then the Employees property would have to return type List<Employee>, right
Danny Thorpe MSFT
Well,
I don;t think anyone would ever do that. Suppose I am using a TreeList and I need to access a column in treelist, I do something like
treeList.ColumnList[index].Add(). If someone is explicitly taking a List<Column> var, he has other things in mind.
regards
Tryin2Bgood
public ICollection<Employee> Employees
{
get { return listOfEmployees; }
}
...would do the same thing and you wouldn't be exposing implementation details.
Also, it's generally a bad idea to return a mutable collection through the interface. This lets clients to your class modify internal data, unchecked. I'm surprised FxCop didn't want about that as well.
iliketoeaticecream
ColumnList columnList = treeList.ColumnList;
Column column = columnList[index];
column.Add();
bobslayer
public class Roster
{
private string name;
private List<Employee> listOfEmployees;
public string Name
{
get { return name; }
set { name = value; }
}
public List<Employee> EmployeeList
{
get { return listOfEmployees; }
}
}
...what's wrong with using List<T> this way
RossDempster
They're suggesting you use a more generic (not Generics) type. For example, a List is a specific type of collection. If there's a more generic type that a type implements, it's better to use that while still using the specialized type for the implementation.
For example, if you have a member of type List<T> in a class (say "Car") and you want to expose it (say in a property called "Tires"), you'd set the type of that property to the most generic interface/type that List<T> implements, like ICollection.
That way, you further abstract your implementation from your interface. If you return List<T> as the type, then you're tied to that implementation. If you return ICollection you can switch your implementation from List<T> to Stack<T> without changing your outward-facing interface.
begginer_gameprogrammer
Member hiding breaks polymorphism. If the class is a utility class or part of model module (as in MVC), the chance of misuse would be greater. But I agree it's less likely in your context (i.e., purpose-built GUI control).
This is why I wish C# makes members virtual by default - the benefit would outweigh the performance hit. Ok, I went too far off-topic.
Cheers.
HMCSharon
List<> exposes many more members (features) than ICollection<>, so unless those additional exposed members of List<> are actually necessary, it's safer to expose more restricted interface of ICollection<>. If later, you found that you need some features not provided by ICollection<>, you can expose/add them to the class by exposing more featureful interface (e.g., IList<>) or adding methods to the same effect. On the other hand, if you exposed List<>, but later found that List<> exposes some features that you actually don't want users to use, it's gets hairy to prevent their use since users may already be using those features. Basically, expose as little as necessary - exposing more later is always easier than trying to take back what has already been exposed.
Interfaces, like ICollection, IList, and so on, are in general designed for exposure - hence the name interface. ;-) So it'd be better to use them to expose members/features than implementation classes like List<>.
On the other hand, if you feel most/all List<> features are necessary features to be exposed, then exposing List<> would be expedient.
Boris Zakharin
public ICollection<Employee> Employees
{
get { return new List<Employee>(listOfEmployees); }
}
nec4b
FxCop messages (at least the majority) are based on proven techniques for writing code that is more robust, multithreading capable, reliable, easier to maintain, etc. Yes, you're a one-man-shop and you're the only guy looking at the code... I'm generally a one-man-shop, and take it from me, it's easier to fix an FxCop warning early in the life-cycle than it is to ignore it only to have to completely re-architect the program later because you went down a path that can't do that you want to do. Multithreading is a perfect example. You can have a lovely class with all sorts of goodies in it; but, if you're passing back a reference to a private variable you have no clean way of synchronizing that, each class that uses that return value ends up having to synchronize to some pseudo-global variable...
It's not so much an issue with larger shops where *much* time is spent on designing these interfaces. But, with smaller shops where the implementation tends to evolve greatly over time, it's easy to paint yourself into a corner.