Book Image

.NET 4.0 Generics Beginner's Guide

By : Sudipta Mukherjee
Book Image

.NET 4.0 Generics Beginner's Guide

By: Sudipta Mukherjee

Overview of this book

Generics were added as part of .NET Framework 2.0 in November 2005. Although similar to generics in Java, .NET generics do not apply type erasure but every object has unique representation at run-time. There is no performance hit from runtime casts and boxing conversions, which are normally expensive..NET offers type-safe versions of every classical data structure and some hybrid ones. This book will show you everything you need to start writing type-safe applications using generic data structures available in Generics API. You will also see how you can use several collections for each task you perform. This book is full of practical examples, interesting applications, and comparisons between Generics and more traditional approaches. Finally, each container is bench marked on the basis of performance for a given task, so you know which one to use and when. This book first covers the fundamental concepts such as type safety, Generic Methods, and Generic Containers. As the book progresses, you will learn how to join several generic containers to achieve your goals and query them efficiently using Linq. There are short exercises in every chapter to boost your knowledge. The book also teaches you some best practices, and several patterns that are commonly available in generic code. Some important generic algorithm definitions are present in Power Collection (an API created by Wintellect Inc.) that are missing from .NET framework. This book shows you how to use such algorithms seamlessly with other generic containers. The book also discusses C5 collections. Java Programmers will find themselves at home with this API. This is the closest to JCF. Some very interesting problems are solved using generic containers from .NET framework, C5, and PowerCollection Algorithms ñ a clone of Google Set and Gender Genie for example! The author has also created a website (http://www.consulttoday.com/genguide) for the book where you can find many useful tools, code snippets, and, applications, which are not the part of code-download section
Table of Contents (20 chapters)
.NET 4.0 Generics
Credits
Foreword
About the Author
Acknowledgement
About the Reviewers
www.PacktPub.com
Preface
2
Lists
4
LINQ to Objects
Migration Cheat Sheet

Appendix A. Performance Cheat Sheet

List<T>

Methods

Complexity (for n elements and count m)

Add

O(1)

AddRange

O(n + m)

AsReadOnly

O(1)

BinarySearch

O(log n)

Clear

O(n)

Contains

O(n)

ConvertAll

O(n)

CopyTo

O(n)

Exists

O(n)

Find

O(n)

FindAll

O(n)

FindIndex

O(n)

ForEach

O(n)

GetRange

O(n)

IndexOf

O(n)

Insert

O(n)

InsertRange

O(n + m)

LastIndexOf

O(n)

RemoveAll

O(n)

RemoveAt

O(n)

RemoveRange

O(n)

Reverse

O(n)

Sort

O(n log n)

ToArray

O(n)

TrimExcess

O(n)

TrueForAll

O(n)

Stack<T>

Methods

Complexity (for n elements)

Clear

O(n)

Contains

O(n)

CopyTo

O(n)

Peek

O(1)

Pop

O(1)

Push

O(1)

CopyTo

O(n)

ToArray

O(n)

TrimExcess

O(n)

Queue<T>

Methods

Complexity (for n elements)

Clear

O(n)

Contains

O(n)

CopyTo

O(n)

Dequeue

O(1)

Enqueue

O(1)

Peek

O(1)

ToArray

O(n)

HashSet<T>

Methods

Complexity (n and m are number of elements)

Add

O(1)

Clear

O(n)

Contains

O(1)

CopyTo

O(n)

ExceptWith

O(n)

IntersectWith

O(n + m)

IsProperSubsetOf

O(n)

IsProperSupersetOf

O(n)

IsSubsetOf

O(n + m)

IsSupersetOf

O(n + m)

Overlaps

O(n)

Remove

O(1)

RemoveWhere

O(n)

SetEquals

O(n)

SymmetricExceptWith

O(n + m)

TrimExcess

O(n)

UnionWith

O(n)

SortedSet<T>

Methods

Complexity (for n elements and count m. l is lower bound and u is upper bound of the view)

Add

O(log n)

Clear

O(n)

Contains

O(log n)

CopyTo

O(n)

ExceptWith

O(n)

GetViewBetween

O(u l)

IntersectWith

O(n)

IsProperSubsetOf

O(n)

IsProperSupersetOf

O(n + m)

IsSubsetOf

O(n + m)

IsSupersetOf

O(n + m)

Overlaps

O(n)

Remove

O(n)

RemoveWhere

O(n)

Reverse

O(1)

SetEquals

O(n + m)

SymmetricExceptWith

O(n + m)

UnionWith

O(n)

Dictionary<TKey,TValue>

Methods

Complexity (for n elements)

Add

O(1)

Clear

O(n)

ContainsKey

O(1)

ContainsValue

O(n)

Remove

O(1)

TryGetValue

O(1)

SortedDictionary<TKey,TValue>

Methods

Complexity (for n elements)

Add

O(log n)

Clear

O(1)

ContainsKey

O(log n)

ContainsValue

O(n)

Remove

O(log n)

TryGetValue

O(log n)

Parameters to consider

The following are the top 20 parameters to consider when selecting a generic collection:

  1. 1. Simple or associative

  2. 2. Random access capability

  3. 3. Lookup speed

  4. 4. Random insertion speed

  5. 5. Edge insertion speed

  6. 6. Random deletion speed

  7. 7. Edge deletion speed

  8. 8. Speed to empty

  9. 9. Time to count

  10. 10. Zero-based indexing

  11. 11. Native sorting capability

  12. 12. Thread safety

  13. 13. Interoperability

  14. 14. Platform portability

  15. 15. Memory requirement

  16. 16. Construction versatility

  17. 17. Native bsearch support

  18. 18. Speed of set operations

  19. 19. Code readability

  20. 20. Least effort to migrate

None of these facilities come in a single collection. So you need to deal with calculated tread-off and strike a balance between computational cost and optimum performance.

The parameters are explained as follows:

  1. 1. Simple or associative:

    If you want to store a few elements in a random order then you don’t need an associative collection. Simple lists are IList<T> based where as associative collections are IDictionary<TKey,TValue> based.

  2. 2. Random access capability:

    If you regularly need to access elements, you would need a collection that supports this functionality to boost performance. Mostly, random access capability is offered by zero-based indexing. Containers that implement IList offer this functionality.

  3. 3. Lookup speed:

    Lookup speed can be crucial in the selection of associative containers. More the speed, the better. Normally, hash-based implementations outperform tree-based or list-based implementations. Thus, accessing an element in SortedDictionary<TKey,TValue> is faster than SortedList<TKey,TValue>.

  4. 4. Random insertion speed:

    If there are a lot of insertions at random locations in the collection, then you should consider how fast you can insert a few elements at arbitrary locations inside the collection. LinkedList<T> offers faster random insertion than List<T>.

  5. 5. Edge insertion speed:

    If you know that there will be many insertions at the edges (start or end) of the collection, choose one that is programmed to offer a faster speed. For example, Stack<T>, Queue<T>, or LinkedList<T>. Inserting in an array-based container, such as List<T>, offers the worst performance as all the elements beyond the point of insertion have to be shifted.

  6. 6. Random deletion speed:

    If there are a lot of deletions at random locations in the collection, then you should consider how fast you can delete a few elements at arbitrary locations inside the collection. LinkedList<T> offers faster random deletion than List<T>.

  7. 7. Edge deletion speed:

    If deletions occur only at the extreme ends of the collection, then you should consider collections optimized for that, such as Stack<T>, Queue<T>, or LinkedList<T> over List<T>.

  8. 8. Speed to empty:

    In many situations, you need to clear all the elements of the collection, perhaps inside a loop. In such situations, you should consider collections that take minimum time to clear all the elements.

  9. 9. Time to count:

    It is crucial to count how many elements there are in the collection. If it takes O(n) that’s not good. In such situations, resort to collections that offer constant timecount operations. Luckily most of them do.

  10. 10. Zero-based indexing:

    Zero-based indexing has become the habit of programmers of our time, thanks to C arrays and C++ vectors. If you need random access on a simple sequential collection, resort to the one that offers this, such as List<T>, rather than using the ElementAt() method.

  11. 11. Native sorting capability:

    If you need to sort the collection every now and then, you can consider those that offer native sorting capabilities such as List<T> or resort to a sorted collection such as SortedSet<T>. It is better than using OrderBy() because a Lambda expression evaluation is generally slower.

  12. 12. Thread safety:

    If your collection will be used in a multi-threaded environment, it is better to use new concurrent collections than a primitive locking mechanism.

  13. 13. Interoperability:

    IUse collections that are more flexible, or in other words, that implement more interfaces. For example, if you need associative storage, then you can use SortedList<TKey,TValue>. However, SortedDictionary<TKey,TValue> is also good because it supports serialization. So, in future, it would be easy to serialize.

  14. 14. Platform portability:

    If you are programming for a platform limited by memory, then some part of the framework will be absent. Be sure to check for the availability of the collection in the framework targeted to the hardware you are using.

  15. 15. Memory requirement:

    If you are in a memory-crunched system, you should also check the storage requirement of the collection. If it takes up too much memory, you might have to resort to something else. For example, if all you need is to add elements at the end and process them from the front, a Queue<T> would do just fine and you don’t need a List<T> which is more heavyweight.

  16. 16. Construction versatility:

    The easier it is to create the generic container, the better. It’s better if a collection offers more variations in constructor, because you always remain prepared for unprecedented situations. You would never know how much information you would need to create a collection.

  17. 17. Native bsearch support:

    Binary search is crucial to finding an item in a long list. You can always use the BinarySearch() method of an Array class; however, if native support is available, that’s better. You would save a couple of boxing and unboxing calls.

  18. 18. Speed of set operations:

    Although you can perform all set operations via LINQ, resort to one proper set implementation if you need a set.

  19. 19. Code readability:

    Make sure to choose a collection that signals your intent more obviously than others, resulting in more readable code.

  20. 20. Least effort to migrate:

    Remember that the element of least surprise always works. Select collections that are available conceptually in several other languages.