Since many years, we use generic collections most of the time. Sometimes we really do need a collection of anything (well, usually only a few different things but with no common base class). For such circumstances we can use either IList or the generic IList<object> as type for method arguments and properties.
Is there any reason to prefer one over the other? Performance characteristics?
Personally, I'm leaning towards IList<object>, as I think this makes it more clear that we really do accept "anything". When a parameter is typed as IList we cannot immediately tell if this method do accept anything, or if the lack of generics is due to history or sloppy coding.
There's a good reason: LINQ and its extension methods. These aren't implemented for pre-generics era types. You will need to call Cast<T> on the IList to take advantage of LINQ!
Other point is that, since newest .NET versions support covariance and contravariance and most of generic interfaces support one or the other (f.e. IEnumerable<out T>, T is covariant), you can easily downcast or upcast interfaces' generic parameters from and to object or a less-unspecific type.
Conclusion: why generics should be prefered?
Generic types have better performance because they avoid a lot of casts.
Newer APIs rely on generic collections and interfaces.
There're a lot of reasons to think that mixing objects of different types in the same list could be dangerous and a bad coding/design decision. And for the few cases where you'll store any kind of object, having LINQ and many other newer APIs and features as your friend is a powerful reason to don't reinvent wheels and save a lot of time!
Related
I was wondering, why on some occasions i see a class representing some type's collection.
For example:
In Microsoft XNA Framework: TextureCollection, TouchCollection, etc.
Also other classes in the .NET framework itself, ending with Collection.
Why is it designed this way? what are the benefits for doing it this way and not as a generic type collection, like was introduced in C# 2.0 ?
Thanks
The examples you gave are good ones. TextureCollection is sealed and has no public constructor, only an internal one. TouchCollection implements IList<TouchLocation>, similar to the way List<T> implements IList<T>. Generics at work here btw, the upvoted answer isn't correct.
TextureCollection is intentionally crippled, it makes sure that you can never create an instance of it. Only secret knowledge about textures can fill this collection, a List<> wouldn't suffice since it cannot be initialized with that secret knowledge that makes the indexer work. Nor does the class need to be generic, it only knows about Texture class instances.
The TouchCollection is similarly specialized. The Add() method throws a NotSupportedException. This cannot be done with a regular List<> class, its Add() method isn't virtual so cannot be overridden to throw the exception.
This is not unusual.
In the .NET framework itself, many type-safe collections predate 2.0 Generics, and are kept for compatibility.
For several XAML-related contexts, there's either no syntax to specify a generic class, or the syntax is cumbersome. Therefore, when List<T> wiould be used, there's a specific TList written for each need.
It allows you to define your own semantics on the collection (you may not want to have an Add or AddRange method etc...).
Additionally, readability is increased by not having your code littered with List<Touch> and List<Texture> everywhere.
There is also quite a lot of .NET 1.0/1.1 code that still needs to work, so the older collections that predate generics still need to exist.
It's not that easy to use generic classes in XAML for example.
Following on from Oded's answer, your own class type allows for much easier change down the track when you decide you want a stack / queue etc instead of that List. There can be lots of reasons for this, including performance, memory use etc.
In fact, it's usually a good idea to hide that type of implementation detail - users of your class just want to know that it stores Textures, not how.
What are the differences of the C# and Java implementations of the generic List class?
Well, in Java List<T> is an interface, to start with :)
The most important difference between the two is the difference between C# and Java generics to start with: in Java generics basically perform compile-time checks and include some metadata in generic fields etc - but the actual object doesn't know its generic type at execution time. You can't ask a List<?> what that ? is, in other words. Any references to a generic type parameter in the implementation act as Object, basically - so a ArayList<String> is really backed by an Object[]. In C# all the information is available at execution time too - so a List<string> is backed by a string[].
Similarly C# generics allow value type type arguments, so you can have a List<int> in C# but not in Java.
There are further differences in terms of variance etc - but this is moving a long way from List<T>.
In terms of just ArrayList<T> (Java) and List<T> (.NET), a couple of differences:
Java lists override equals/hashCode, whereas they don't in .NET
ArrayList<T> grows by multiplying the current capacity by 3/2; .NET's List<T> doubles the current capacity instead
Of course there are other differences in terms of the APIs exposed - if you could give more information about the kind of difference you're interested in, we could help more.
Are you asking for differences in their API or their underlying implementation? I believe Java generics are implemented completely via the compiler -- the JVM has no notion of generics. For C#, generics are a built-in concept of the .Net runtime. Wikipedia seems to have a good comparison of the two: http://en.wikipedia.org/wiki/Comparison_of_C_Sharp_and_Java#Generics
I need simple example to use ISerializable,IEnumerable,IList with Generics efficiently.
Also wish to know what are all the other Interfaces we can use along with Generics.
Update :
The task i need to perform is using these interfaces
I have to serialize the custom Types
Collect them in Generic object
Iterate them to find the match
This question is very broad.
Note that the interfaces you've listed are not all about the same thing.
ISerializable is not generic, and deals with serialization of objects to streams or similar.
IEnumerable is about being able to enumerating over a collection or something that produces a stream of elements.
IList is an interface that is typically implemented by such a collection.
It would help us helping you if you could narrow down your question somewhat. As your question stands now, it's more like "I need to know everything there is to know about cars".
As for "all other interfaces that can be used with generics", have you looked at the MSDN Documentation for the .NET framework classes?
I have a feeling that this question is a homework question...but I'll bite with a little information.
Generics != Interfaces. Basically you can use any interface that you want with Generics, it is one of the more powerful parts of generics, by using interfaces that you create, you can then define generic methods that process multiple concrete implementations by limiting the generic type to objects that implement a specific interface.
I'm implementing an AVL binary tree data structure in C# .NET 2.0 (possibly moving to 3.5). I've got it to the point where it is passing my initial unit tests without needing to implement any framework level interfaces.
But now, just looking through the FCL I see a whole bunch of interfaces, both non-generic and generic that I could implement to ensure my class plays nicely with language features and other data structures.
At the moment the only obvious choice (to me at least) is one of the Enumeration style interfaces to allow a caller to use the tree in a foreach loop and possibly with Linq later on. But which one (or more)?
Here are the interfaces I'm considering at present:
IEnumerable and IEnumerable<T>
IEnumerator and IEnumerator<T>
IComparable and IComparable<T>
IComparer and IComparer<T>
ICollection and ICollection<T>
IEquatable and IEquatable<T>
IEqualityComparer and IEqualityComparer<T>
ICloneable
IConvertible
Are there any published guidelines, either online or in book form, that provide recommendations regarding which framework interfaces to implement and when?
Obviously for some interfaces, if you don't want to provide that functionality, just don't implement the entire interface. But it appears there are certain conventions in the FCL classes (such as Collection classes) that perhaps we should also follow when building custom data structures.
Ideally the recommendations would provide guidance on such questions as when to use IComparer or IEqualityComparer, IEnumerable or IEnumerator? Or, if you implement a generic interface, should you also implement the non-geneic interface? etc..
Alternatively, if you have guidance to offer based on your own experiences, that would be equally useful.
You should be aware that some of those interfaces inherit from each other (ICollection<T> and IEnumberable<T>) and the generic versions of interfaces generally require the implententation their non-generic versions. IEnumerator and IEnumerable are connected (an IEnumerable traditionally creates an IEnumerator to do the enumeration)
Implementing IComparable<T> is on a collection is fraught with danger (are you comparing the members in the collection?), and IComparer<T> is a helper interface for sorting methods.
ICloneable is a bit outdated - but it's meant to enable creating a deep copy (which, again, is fraught with danger for a collection.
I'd take issue with your
Obviously for some interfaces, if you don't want to provide that functionality, just don't implement them.
If you implement an interface, you should implement all the members of it. (see Liskov Substitution Principle)
Implementing IConvertible for a collection also seems strange - you might perfer to implement ISerializable.
The MSDN Documentation for the interfaces is a bit terse, but you can always google them to see how they work.
The definite guide is Framework Design Guidelines.
It gives Do, Do Not and consider recommendations. A lot of it is also available in MSDN.
I don't think you'll find a one-size-fits-all answer to this, as the implementation of these interfaces depends on how you expect your class to be used.
All these interfaces are provided to allow use of a class from within the existing BCL or the language itself. So, as you say, IEnumerable allows use of the class in a foreach loop.
Implementing each of these depends on the way that your library might be used. For instance, ICloneable is directly appropriate to users of remoting and sometimes users of ORMs. If your class makes sense in that environment then you'll help your users by implementing it.
Put another way: who's going to use your class? What BCL framework methods would you expect them to use?
(Also, many of the generic interfaces themselves implement non-generic versions, e.g. IEnumerable implements IEnumerable, and IEnumerator implements IEnumerator.)
You just implement the ones that you want your class to have, i.e.
If you want to be able to enumerate items, then implement IEnumerable and IEnumerable<T> instead of inventing your own methods.
If you want to be able to deep-copy a tree, then implement ICloneable instead of inventing your own method.
If you want to be able to compare trees for value equality, then implement all the equality interfaces.
And so on. Other points:
Some interfaces should be implemented in a specific manner so as to avoid "surprising" behaviour in code that calls them. The equality interfaces in particular must be 100% consistent with each other and the System.Object virtual equality methods.
When there is a generic and non-generic version of the same interface, it is always useful to implement both.
Following the suggestions of FxCop and my personal inclination I've been encouraging the team I'm coaching to use ReadOnlyCollections as much possible. If only so that recipients of the lists can't modify their content. In their theory this is bread & butter. The problem is that the List<> interface is much richer exposing all sorts of useful methods. Why did they make that choice?
Do you just give up and return writable collections? Do you return readonly collections and then wrap them in the writable variety? Ahhhhh.
Update:
Thanks I'm familiar with the Framework Design Guideline and thats why the team is using FxCop to enforce it. However this team is living with VS 2005 (I know, I know) and so telling them that LINQ/Extension methods would solve their problems just makes them sad.
They've learned that List.FindAll() and .FindFirst() provide greater clarity than writing a foreach loop. Now I'm pushing them to use ReadOnlyCollections they lose that clarity.
Maybe there is a deeper design problem that I'm not spotting.
-- Sorry the original post should have mentioned the VS2005 restriction. I've lived with for so long that I just don't notice.
Section 8.3.2 of the .NET Framework Design Guidelines Second Edition:
DO use ReadOnlyCollection<T>, a subclass of ReadOnlyCollection<T>, or in rare cases IEnumerable<T> for properties or return values representing read-only collections.
We go with ReadOnlyCollections to express our intent of the collection returned.
The List<T> methods you speak of were added in .NET 2.0 for convenience. In C# 3.0 / .NET 3.5, you can get all those methods back on ReadOnlyCollection<T> (or any IEnumerable<T>) using extension methods (and use LINQ operators as well), so I don't think there's any motivation for adding them natively to other types. The fact that they exist at all on List is just a historical note due to the presence of extension methods being available now but weren't in 2.0.
First off, ReadOnlyCollection<T> does implement IEnumerable<T> and IList<T>. With all of the extension methods in .NET 3.5 and LINQ, you have access to nearly all of the functionality from the original List<T> class in terms of querying, which is all you should do with a ReadOnlyCollection<T> anyways.
That being said, your initial question leads me to make some suggestions...
Returning List<T> is bad design, so it shouldn't be a point of comparison. List<T> should be used for implementation, but for the interface, IList<T> should be returned. The Framework Design Guidelines specifically state:
"DO NOT use ArrayList or List<T> in public APIs." (Page 251)
If you take that into consideration, there is absolutely no disadvantage to ReadOnlyCollection<T> when compared to List<T>. Both of these classes implement IEnumerable<T> and IList<T>, which are the interfaces that should be returned anyways.
I don't have any insight as to why they weren't originally added. But now that we have LINQ I certainly see no reason to add them in future versions of the language. The methods you mentioned can easily be written in a LINQ query today. These days I just use the LINQ queries for pretty much everything. I actually more often get annoyed with List<T> having those methods because it conflicts with extension methods I write against IEnumerable<T>.
I think Jeff's answer kinda contains the answer you need; instead of ReadOnlyCollection<T>, return a subclass of it... one that you implement yourself to include the methods that you'd like to use without upgrading to VS2008/LINQ.