MonthAugust 2016

Using keyword

Before we continue to FileInfo and Streams we need to explain using keyword in details.

Using directive

Using directive shortens our syntax so that we do not always have to type entire namespace:

Using directive grants us access to static members having to qualify the access with the type name:

Using directive enables us to create alias directive.

Using statement

Using statement provides us with a easy to use syntax which in return guarantees us with that types that implement IDisposable interface will be disposed of when we finish with them. For now do not stress yourself with questions like why do I need to dispose of something and what use IDisposable interface is to me. Those questions will be covered in a future post.

Example of using statement

Usage of using statement is straight-forward.

First we type using keyword and open parentheses, and inside of those brackets we instantiate class that implements IDisposable interface.  After that we proceed to use class instance inside curly brackets.

Of-course  you can instantiate more than one class while using using directive, just remember to separate them with coma:

I hope you will find using keyword helpful. I certainly use it on a daily basis in both forms

File and FileInfo

While trying to copy, move, rename, create, open, delete and appending to files we use File and FileInfo classes. File and File info classes derive from System.IO namespace. File class provides us static methods to work with files and FileInfo provides us with instance methods. Generally, you will use File class when working with a file and perform one operation on it. Difference between File and FileInfo approaches is that FileInfo does security checking only once (while accessing files).  Because FileInfo is a instance method it does not tack changes to a file so you will have to take a lot of precautions while using that class. File class is on a disadvantage, because you always have to apply path to a file, meaning, it takes more parameters than FileInfo class. Try discovering yourself which approach is faster in your scenario. Also both classes help us while creating FileStream (to be explained in next post).

Common operations working with File class

 

Common operations working with FileInfo  class

 

I hope you had no problem with learning how to use File and FileInfo classes. If you found File and FileInfo classes interesting I recommend that you continue learning about Streams.

Delegates part 2 Multicast Delegate

A useful feature of delegates is that delegates can point to more than one method. A delegate that points to multiple methods is called Multicast Delegate. When invoking Multicast Delegate all methods that he points to are invoked.  We add methods to delegate by using + or += operator. Methods can be removed from delegate by using – or -= operators.

When delegate has return type void, all methods are executed. The same is with all other return types. Difference is that when return type is not void, we will receive only value of last method executed.

 

Examples of Multicast Delegate using void return type:

 

Add methods to delegate by using + operator

We will create console application that will print content of four methods by using delegates.

First we created our new delegate VoidDelegate that has return type void and takes no input parameters. Then, inside our Main method, we defined 5 VoidDelegates, and instantiate four of the them. After we are done with instantiating 4 delegates, we assign those 4 delegates using + operator to fifth delegate. Lastly, we invoke the delegate. Console output will show all 4 ShowMessage methods results.

Remove methods from delegate by using – operator

Let’s rework our previous code so we can see example of removing methods from a delegates by using – operator. Next example will show you only Main method, because no changes are needed to be maid for ShowMessage methods.

First part of a code is same as in previous example, but later on we just use – operator to unsubscribe voidDelegate1  delegate (that uses ShowMessageOne method) from voidDelegate5 delegate. Note that ShowMessageOne  message is not shown.

 

Add methods to delegate by using += operator

Seems that += operators shortened our code and made it a lot readable. This time we needed to declare only one delegate and add methods to him by only using += operators.

Remove methods from delegate by using -= operator

 

Example of Multicast Delegate using string return type

While running this app, try entering debug mode, you will see that all methods were hit but only ShowMessageFour message was sent. Remember that while consuming your delegates.

 

We will continue delegates discussion with Anonymous methods.

Delegates part 1

A delegate is a reference type, type-safe function(method) pointer. Delegates are used to invoke the method through the delegate instance. To invoke method,  delegates methods signature and return type must be same as that of a delegate.

You declare delegate similar to declaring the method:

How do we use delegates?

Lets create simple console application that will use method to display value:

This class does its intended yob nicely, but we can expand it by adding delegate. First we must declare delegate outside our class and instantiate our newly created delegate inside Main method then we can use our delegate to pass the value to our function.

Q: This look very complicated process just to invoke function. Why would i ever need to use delegates?

A: Yes it takes some extra work to create delegates but in next example you will see where delegates make much more sense.

Why do we use delegates?

Imagine that you need to create application for HR department and in that application you need to predict salary increase for employees that are employed full-time in that company. You would create application that behaves  like this:

Here we have Employee class that has necessary properties and  NextYearSalary method. NextYearSalary that takes List of Employees and checks each employee for his IsFullTime status, if that status is true then it multiplies employees years of service in company with 1% then multiplies it again with current salary. That way we get potential salary increase and print it to the console. We compile our program and ship it to all companies that use our application.

After some time we receive request from another company. Other company wants to see potential salary increase not for its full time employees but for those employees who have worked there for at least 3 years.

We could expand NextYearSllary method to accommodate that request or create another method only for that company, but these two approaches are not good solution for our problem because we always tend to have clean code and because second approach breaks DRY principle. Instead we will use delegates:

First wee took a look in NextYearSalary method. Inside our foreach loop we found if statement that needed to be changed. If statement is a boolean and checks Employee object so we created delegate that returns bool value and takes Employee object as a parameter. Now we needed to create method that matches that signature, so we created PotentialSalaryIncreaseForFullTimeEmployees method in our Main method. Next step was to expand signature of NextYearSalary method with SalaryIncreaseDelegate  delegate and replace condition of if statement with our delegates variable. Lastly, we call of NextYearSalary method in Main method with missing delegate variable.

Exercise 1:

Try to create method that:

  • can be used for SalaryIncreaseDelegate
  • can decide which Employees next years potential salaries will be displayed using NextYearSalary method for those employees that have worked in company at least 3 years.

Exercise 2:

Try to create delegate that will emulate NextYearSalary logic for expected salary:

Continue to Delegates part 2

Yield keyword

When you use the yield keyword in a statement, you indicate that the method, operator, or get accessor in which it appears is an iterator. Using yield to define an iterator removes the need for an explicit extra class (the class that holds the state for an enumeration, see IEnumerator<T> for an example) when you implement the IEnumerable and IEnumerator pattern for a custom collection type.

Yield keyword has two forms:

  • yield return <expression>; (expression is defined in return type)
  • yield break;                                  (yield break is used to end iteration)

 

Yield must be of return type IEnumerable, IEnumerable<T>, IEnumerator, or IEnumerator<T>.

 

Yield keyword is consumed by an iterator method by using a foreach statement or LINQ query.

 

Example:

 

Using IComparable interface

Class that implements IComparable interface comes with only one member, CompareTo method. CompareTo method compares the current instance with another object of the same type and returns an integer that indicates whether the current instance precedes, follows, or occurs in the same position in the sort order as the other object.

In short we can compare two elements of the same collection and as a result we get int value that tells us relative order of the objects being compared.

We can also compare two instances of the same class and result tells us weather results are the same, first value is greater or less than compared value.

Example using non-generic IComparable interface:

Example using generic IComparable interface:

Difference between these two approaches:

  1. Using non-generic interface IComparable requires of us to cast obj to desired type.
  2. Generic interface IComparable<T> is type safe.

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>

© 2019 LearnC#WithDarko

Theme by Anders NorenUp ↑