Whats is the difference between:
List<MyType> myList;
and
myList : List<MyType>
Its obvious that the first one is list and second one is a class. But my question is what's the advantage of second over first one.
Whats is the difference between:
List<MyType> myList;
and
myList : List<MyType>
Its obvious that the first one is list and second one is a class. But my question is what's the advantage of second over first one.
The latter is a new class that inherits from the base, but is distinct. The most obvious distinction is that it doesn't have the same constructors, but you'll also run into problems streaming it.
Those are the disadvantages. The advantage is that you could add some of your own methods. Even then, I'd consider using containment, with has-a relationship instead of is-a.
The latter gives you the ability to have a function which takes a myList, instead of just a List. This also means that if the type of myList changes (perhaps to a sorted list) you don't have to change your code anywhere. So instead of declaring List<myType>
everwhere, and then having to change them, if you had MyList
objects everywhere, you're golden.
Its also a syntactic difference. Does myList have a list, or is it a list?
I would lean towards having a MyList : List<MyType>
if it is used commonly throughout your program.
List<MyType> myList is an instance of the generic type List that can contain items that are of MyType (or of any types derived from MyType)
var myTypeInstance = new MyType();
var myList = new List<MyType>;
myList.Add(myTypeInstance);
myList : List<MyType> is a new type that inherits from List from which you can then make multiple instances:
var myTypeInstance = new MyType();
var myCollectionVariable = new myList();
myCollectionVariable.Add(myTypeInstance);
The main advantage of the latter over the former is if you wanted to have some methods that act on a List you can put them on your class, rather than storing them in a "helper" or "utility" library, for example:
class myList : List<MyType>
{
public void DoSomethingToAllMyTypesInList()
{
...
...
}
}
Some people find benefits in abstracting data structures away from their application logic. If you decide that generic list is no longer the best data structure to represent MyList you can change your MyList implementation, and as long as your interface is the same, you don't have to update any other code.
This is over kill in many situations however.
There are also semantic benefits to working with an abstracted data type rather than the original, though the list type blurs the line. It is more obvious when working with a dictionary data structure. If you wrap the dictionary in a custom collection type, and expose keys and values as properties. you can write code that reads more like the business logic you are implementing.
I would prefer not to inherit implementation where possible. It has its uses, but if it's not entirely necessary, then it's not worth it.
The major answer to your question is that by inheriting List<T>
, you make all its methods public by default. Usually when writing a new class, you want encapsulation. You don't want to let the internals leak out. For example, suppose you wanted to make a thread-safe container. If you inherit from a thread-ignorant container, your clients will be able to use the public interface of the base class to bypass any locking you try to put in.
Another popular mistake comes when you find yourself using a particular container type a lot, it's tempting to try and use inheritance to make a short name for it:
class ShortName : Dictionary<string, List<string>> { };
But that's not what you've done - you've created a completely new type. This means that if you have some other library that can produce the right data structure, it won't be directly usable by your code; you'll have to copy it into a ShortName
first. An example is Linq, which can easily build a Dictionary<string, List<string>>
from a very readable, functional expression, ending with ToDictionary
.
So instead, do this:
using ShortName = Dictionary<string, List<string>>;
Now you have a short snappy alias for the unweildy typename, but you're actually still using the same type.
The Microsoft design guidelines (FxCop and VS Code Analysis) don't recommend inheriting publicly-visible classes from List<T>. Instead you can inherit from Collection<T> as described in this blog post.
These guidelines aren't necessarily relevant for private assemblies or internal classes though.
A couple of reasons why you might want to inherit from Collection<T> or List<T> are:
So you can add custom application-specific members to your collection class.
So you can create a ComVisible collection class (you can't expose a generic List directly to COM, but you can expose a derived class).
By the way the naming guidelines would also recommend you name your derived class with the "Collection" suffix, i.e.
MyTypeCollection : List<MyType> // or : Collection<MyType>, IList<MyType>
rather than
MyList : List<MyType> // or : Collection<MyType>, IList<MyType>