CategoryGenerics

HashSet

Hashset<T> is unordered collection. Because HashSet<T> does not contain keys and is unordered,  collection has to be enumerated to find element. HashSet is used because it is very fast collection and because HashSet guarantees uniqueness of elements.

Declaration

HashSet<T> can can contain reference or value types. We declare it by typing HashSet followed by<> (angle brackets) and inside <> should be our type and after that should be variable name:

Initialization

As HashSet<T>  is an reference type so we initialize it by assigning HashSet variable to HashSet instance. HashSet type should be specified while instantiating HashSet<T>.

Populating a HashSet <T>

Using collection initialzier

Using Add method

Add method returns bool value so Add method can also be used to detect if value already exists inside HashSet.

No exception will be thrown if string Zadar exist and Tokyo string will be added to the collection. Also note that if you try to add string LONDON (with uppercase letters) that value will be added so make sure that you check yourself for uppercase scenario or use StringComparer like this:

Remove an element from the HashSet<T> using Remove method

How to use HashSet<T>

Iterate through HashSet<T>

We can iterate an HashSet<T> using for and foraech statements. Using these loops elements will not be poped from the HashSet.

foreach (var cityName in cityNames)

{

     Console.WriteLine(cityName);

 }

for (int i = 0; i < cityNames.Count; i++)

{

    var city = cityNames.ElementAt(i);

    Console.WriteLine(city);

}

Number of elements inside of a HashSet<T>

int setCount = cityNames.Count;

 

Queue

Queue<T> is similar to Stack<T>. Difference is that Queue <T> is based on FIFO principle. First in first out. Meaning  element will be added to first location in the collection and when we try to remove element from the collection first element will be removed.

Declaration

Queue<T> can can contain reference or value types. We declare a Queue<T> by typing Queue followed by<> (angle brackets) and inside <> should be our type and after that should be variable name:

 

Initialization

As Queue<T>  is an reference type so we initialize it by assigning Queue variable to Queue instance. Queue<T> type should be specified while instantiating Queue<T>.

Populating a Queue<T> with values using Enqueue method

Queue<T> is populated by using Enqueue method.

Remove an element from the Queue <T>

Dequeue element

By using Dequeue method we can remove first element of the Queue<T> and get that value.

By using Dequeue method value will be removed from the Queue<T> and Count property will be decremented by 1.

Clear Queue <T>

By using Clear method all Queue<T> elements will be removed from the Queue<T>.

How to use Queue <T>

Peek first value

By using Peek method we can inspect first value with no fear of dequeuing it from the Queue.

Iterate through Queue<T>

We can iterate an Queue<T> using for and foraech statements. Using these loops elements will not be dequeued from the Queue<T>.

 

 

Number of elements inside of a Queue<T>

 

 

Stack

Stack<T> is a strongly typed collection of values, where elements can be added or removed at the top of the stack. Stack<T> is based on LIFO principle, meaning elements can be only added to the top and only top element can be removed. Stack<T>  is an reference type. System.Collections.Generic class methods that we can use with Stack<T>.

Declaration

Stack<T> can contain reference or value types. We declare a Stack<T> by typing Stack followed by<> (angle brackets) and inside <> should be our type and after that should be variable name:

Initialization

As Stack<T>  is an reference type so we initialize it by assigning Stack variable to Stack<T> instance. Stack<T>  type should be specified while instantiating Stack<T>.

Populating a Stack<T> with values using Push method

Stack<T> is populated by using Push method:

Remove an element from the Stack<T>

Pop element

By using Pop method we can remove top element of the Stack<T> and get that value.

By using Pop method value will be removed from the Stack<T> and Count property will be decremented by 1.

Clear Stack

By using Clear method all Stack<T> elements will be removed from the stack.

How to use Stack<T>

Peek top value

By using Peek method we can inspect top value with no fear of popping it from the stack.

Iterate through Stack<T>

We can iterate an Stack<T> using for and foraech statements. Using these loops elements will not be popped from the Stack<T>.

Number of elements inside of a Stack<T>

Dictionary

Dictionary<TKey, TValue> is a collection of keys and values, where key value must be unique to Dictionary and value must not be null. Dictionary<TKey, TValue> is an reference type. System.Collections.Generic class methods that we can use with Dictionary<TKey, TValue>.

Declaration

Dictionary<TKey, TValue> can can contain reference or value types. We declare a Dictionary<TKey, TValue>  by typing Dictionary followed by<> (angle brackets) and inside <> first type should be our key type and second should be type of our value desired type of our Dictionary and after that should be variable name:

Initialization

As Dictionary< TKey, TValue > is an reference type so we initialize it by assigning Dictionary variable to Dictionary instance. Types of key and value should be specified while instantiating Dictionary.

Populating a Dictionary<TKey,TValue>

with values

Add element to end of a Dictionary

Using collection initializer

Remove an element from the Dictionary<TKey,TValue> by key value

How to use generic Dictionary<TKey,TValue>

Retrieve value by index

We retrieve an element from Dictionary<TKey,TValue> by specifying value of that key. If for example we wanted to retrieve element with key value 1 from our previous Dictionary we can access that value like this:

Of course if we have Dictionary of objects we can specify value of an element and select property to display.

We can check if value exist with ContainsKey method.

We can check if key exist with ContainsValue method.

We can also check if key exists and if the key exists retrieve it’s value in one run using TryGetValue method. Note that if key does not exist exception will not be thrown.

Iterate through Dictionary<TKey,TValue>

We can iterate an Dictionary using for and foraech statements

Number of elements inside of a Dictionary<TKey,TValue>

Generic List

List<T> is an zero based, expandable size collection of elements, meaning first index of a List<T> is 0, once we initialize a List<R> we can change it’s length add or remove elements. List<T> is an reference type. System.Collections.Generic.List class holds methods that we can use with List<T>. Note that Generic List is similar to an Array.

Declaration

List<T> can can contain reference or value types. We declare a List<T>  by typing List followed by<> (angle brackets) and inside <> should be desired type of our List<T> and after that should be variable name:

 

Initialization

As List<T> is an reference type so we initialize it by assigning List variable to List<T> instance. Type of List should be specified while instantiating List<T>.

Populating a List<T> with values

Add element to end of a List

 

Using collection initializer

 

Add element to specific index in a List<T>

This action will insert element on index value 1.

Remove an element from the List<T>

Remove element by value

This action will remove first occurrence of “Tokyo” string inside of a List.

Remove element by index value

This action will remove element at index value 3.

How to use generic List<T>

Retrieve value by index

We retrieve an element from List<T> by specifying index of that value. If for example we wanted to retrieve first element from our previous List we can access that value like this:

Of course if we have List of objects we can specify index of an element and select property to display

Iterate through List<T>

We can iterate an List<T> using for and foraech statements

 

 

Find value at specified index

 

Number of elements inside of a List<T>

Capacity of a list

Note that Capacity property value can be different than that of Count property. Count property value tells us how many elements are inside of an List, but Capacity value tells us how many elements List<T> can hold before it expands. Default List<T> capacity is 4, and every time we add more elements than List<T> can hold capacity value doubles.

Good practices for using List<T>:

Use plural variable name. Variable name cityNames is better naming convention than cityName.

Use List<T> if you do not know List size during design time because List<T>size can be changed during runtime.

 

Generics

Generics introduce to the .NET Framework the concept of type parameters, which make it possible to design classes and methods that defer the specification of one or more types until the class or method is declared and instantiated by client code.

In essence Generics are way of writing code that is:

  • Without specific type
  • Type-safe
  • Reusable

Lets say for example that we want to display integer value and a message in our Console application. We can write standard Program class that uses DisplayIntValue class.

In future we receive request that our application must display also an double value and integer. What would be our options? We could create a new class  DisplayDoubleValue that would be the same as DisplayIntValue but with a few tweaks, but that breaks DRY principle. This would be a good candidate to implement Generics.

We should make a copy of DisplayIntValue class and rename it to DisplayGenericValue. Then we change type of InputValue property and input parameter type intValue to T variable. T stands for generic type. Note that we get error: The type or namespace name ‘T’ could not be found (are you missing a using directive or an assembly reference?). You get this error because T variable is not defined in class signature. So next step will be to add <T> in your class signature. Your class signature should look like this now: public class DisplayGenericValue<T>. Lets try out our new code by displaying string or double value.

Note that you had to specify type while creating instance of DisplayGenericValue class. By doing so, our generics class knew of what type or T variable will be.

FAQ

Q:  Can i use multiple generic types?

A: Yes you can, but remember to add them first to class signature. Also, for readability sake naming convention for generic types goes like this: capital T followed by description. For example TMessage.

Q: Can i create an generic method?

A: Of course you can. Make sure that return type of method is an generic variable and that your method signature contains generic variable.

Note that if you define variable in class signature you do not have to specify type in Method signature.

Q: I want to set limit types that can consume my generics class or method. How can i make it happen?

A: In your class/method signature you can add combination of following lines:

  • where T: struct   – limits types to reference types.
  • where T : class    – limits types to reference types.
  • where T : new()   – limits types to classes that have public parameterless constructor.
  • where T : <base class name>   – limits types to specified class or class that derives from that class.
  • where T : <interface name>     – limits types to specified  interface or interface that inherits that interface.
  • where T : U                                         – the type argument supplied for T must be or derive from the argument supplied for U.

 

 

 

© 2019 LearnC#WithDarko

Theme by Anders NorenUp ↑