Thursday, September 12, 2013

C# Tutorial Series III


Part 67 - Optional parameters in c#


Suggested Videos 
Part 64 - How and where are indexers used in .net
Part 65 - Indexers in c#
Part 66 - Overloading indexers



In this video, we will discuss the different ways that are available to make method parameters optional. This is a very common interview question.

There are 4 ways that can be used to make method parameters optional.
1. Use parameter arrays
2. Method overloading
3. Specify parameter defaults
4. Use OptionalAttribute that is present in System.Runtime.InteropServices namespace



Using parameter arrays, to make method parameters optional:
AddNumbers function, allows the user to add 2 or more numbers. firstNumber and secondNumber parameters are mandatory, where as restOfTheNumbers parameter is optional.
public static void AddNumbers(int firstNumber, int secondNumber,
   
params object[] restOfTheNumbers)
{
   
int result = firstNumber + secondNumber;
   
foreach (int i in restOfTheNumbers)
    {
        result += i;
    }

   
Console.WriteLine("Total = " + result.ToString());
}

Please note that, a parameter array must be the last parameter in a formal parameter list. The following function will not compile.
public static void AddNumbers(int firstNumber, params object[] restOfTheNumbers,
   
int secondNumber)
{
   
// Function implementation
}

If the user wants to add just 2 numbers, then he would invoke the method as shown below.
AddNumbers(10, 20);

On the other hand, if the user wants to add 5 numbers, then he would invoke the method as shown below.
AddNumbers(10, 20, 30, 40, 50);
or
AddNumbers(10, 20, new object[] { 30, 40, 50 });

In our next video, we will discuss method overloading, specifying parameter defaults & using OptionalAttribute.

Part 68 - Making method parameters optional using method overloading


Suggested Videos 
Part 65 - Indexers in c#
Part 66 - Overloading indexers
Part 67 - Optional parameters



In this video, we will discuss making method parameters optional using method overloading

This method allows us to add any number of integers
public static void AddNumbers(int firstNumber, int secondNumber,
    
int[] restOfNumbers)
{
    
int result = firstNumber + secondNumber;
   
if (restOfNumbers != null)
    {
       
foreach(int i in restOfNumbers)
        {
            result += i;
        }
    }

   
Console.WriteLine("Sum = " + result);
}



If we want to add 5 integers - 10, 20, 30, 40 and 50. We call the method as shown below.
AddNumbers(10, 20, new int[]{30, 40, 50});

At the moment all the 3 parameters are mandatory. If I want to add just 2 numbers, then I can invoke the method as shown below. Notice that, I am passing null as the argument for the 3rd parameter.
AddNumbers(10, 20, null);

We can make the 3rd parameter optional by overloading AddNumbers() function as shown below.
public static void AddNumbers(int firstNumber, int secondNumber)
{
    AddNumbers(firstNumber, secondNumber,
null);
}

Now, we have 2 overloaded versions of AddNumbers() function. If we want to add just 2 numbers, then I can use the overloaded version of AddNumbers() function, that takes 2 parameters as shown below.
AddNumbers(10, 20);

If I want to add 3 or more numbers, then I can use the overloaded version of AddNumbers() function, that takes 3 parameters as shown below.
AddNumbers(10, 20, new int[] { 30, 40 });

Part 69 - Making method parameters optional by specifying parameter defaults


Suggested Videos 
Part 66 - Overloading indexers
Part 67 - Optional parameters
Part 68 - Making method parameters optional using method overloading



In this video, we will discuss making method parameters optional by specifying parameter defaults.

This method allows us to add any number of integers 
public static void AddNumbers(int firstNumber, int secondNumber,
    
int[] restOfTheNumbers)
{
    
int result = firstNumber + secondNumber;
   
foreach (int i in restOfTheNumbers)
    {
        result += i;
    }

   
Console.WriteLine("Total = " + result.ToString());
}



If we want to add 5 integers - 10, 20, 30, 40 and 50. We call the method as shown below.
AddNumbers(10, 20, new int[]{30, 40, 50});

At the moment all the 3 parameters are mandatory. If I want to add just 2 numbers, then I can invoke the method as shown below. Notice that, I am passing an empty integer array as the argument for the 3rd parameter.
AddNumbers(10, 20, new int[]{});

We can make the 3rd parameter optional by specifying a default value of null for the 3rd parameter.
public static void AddNumbers(int firstNumber, int secondNumber,
    
int[] restOfTheNumbers = null)
{
    
int result = firstNumber + secondNumber;

    // loop thru restOfTheNumbers only if it is not null
    // otherwise you will get a null reference exception
   
if (restOfTheNumbers != null)
    {
       
foreach (int i in restOfTheNumbers)
        {
            result += i;
        }
    }
   
Console.WriteLine("Total = " + result.ToString());
}

Since we have specified a default value for the 3rd parameter, it is optional. So, if we want to add just 2 numbers, we can use the function as shown below.
AddNumbers(10, 20);

Optional parameters must appear after all required parameters
The following method will not comiple. This is because, we are making parameter "a" optional, but it appears before the required parameters "b" and "c".
public static void Test(int a = 10, int b, int c)
{
    // Do something
}

The following method will compile, as optional parameter "a" is specified after all the required parameters ("b" & "c").
public static void Test(int b, int c, int a = 10)
{
    // Do something
}

Named Parameters
In the following method, parameters "b" & "c" are optional.
public static void Test(int a, int b = 10, int c = 20)
{
   
Console.WriteLine("a = " + a);
    
Console.WriteLine("b = " + b);
    
Console.WriteLine("c = " + c);
}

When we invoke this method as shown below, "1" is paased as the argument for parameter "a" and "2" is passed as the argument for parameter "b" by default.
Test(1, 2);

My intention is to pass "2" as the argument for parameter "c". To achieve this we can make use of named parameters, as shown below. Notice that, I have specified the name of the parameter for which value "2" is being passed.
Test(1, c: 2);

Part 70 - Making method parameters optional by using OptionalAttribute


Suggested Videos 
Part 67 - Optional parameters
Part 68 - Making method parameters optional using method overloading
Part 69 - Making method parameters optional by specifying parameter defaults



In this video, we will discuss making method parameters optional by using OptionalAttribute that is present in System.Runtime.InteropServices namespace

This method allows us to add any number of integers. 
public static void AddNumbers(int firstNumber, int secondNumber,
    
int[] restOfTheNumbers)
{
    
int result = firstNumber + secondNumber;
   
foreach (int i in restOfTheNumbers)
    {
        result += i;
    }

   
Console.WriteLine("Total = " + result.ToString());
}



If we want to add 5 integers - 10, 20, 30, 40 and 50. We call the method as shown below.
AddNumbers(10, 20, new int[]{30, 40, 50});

At the moment all the 3 parameters are mandatory. If I want to add just 2 numbers, then I can invoke the method as shown below. Notice that, I am passing an empty integer array as the argument for the 3rd parameter.
AddNumbers(10, 20, new int[]{});

We can make the 3rd parameter optional by using OptionalAttribute that is present in System.Runtime.InteropServices namespace. Make sure you have "using" declaration for System.Runtime.InteropServices namespace.
public static void AddNumbers(int firstNumber, int secondNumber,
    [
Optionalint[] restOfTheNumbers)
{
    
int result = firstNumber + secondNumber;

    // loop thru restOfTheNumbers only if it is not null
    // otherwise you will get a null reference exception
   
if (restOfTheNumbers != null)
    {
       
foreach (int i in restOfTheNumbers)
        {
            result += i;
        }
    }

   
Console.WriteLine("Total = " + result.ToString());
}

So, if we want to add just 2 numbers, we can now use the function as shown below.
AddNumbers(10, 20);

Part 71 - Code snippets in visual studio


Suggested Videos 
Part 68 - Making method parameters optional using method overloading
Part 69 - Making method parameters optional by specifying parameter defaults
Part 70 - Making method parameters optional by using OptionalAttribute

In this video, we will discuss code snippets, that come with visual studio.



Code snippets are ready-made snippets of code you can quickly insert into your code. To insert code snippets there are several ways
1. Keyboard shortcut: CTRL K + X
2. Right click and select "Insert Snippet...", from the context menu
3. Click on Edit - Intellisense - Insert Snippet
4. Use code snippets short cut. For example to use "for loop" code snippet, type "for" and press TAB key twice



Once a code snippet is inserted, the editable fields are highlighted in yellow, and the first editable field is selected automatically. Upon changing the first editable field, press TAB to move to the next editable field. To come to the previous editable field use SHIFT + TAB. Press ENTER or ESC keys to cancel field editing and return the Code Editor to normal.

Code Snippet Types:
Expansion: These snippets allows the code snippet to be inserted at the cursor.
SurroundsWith: These snippets allows the code snippet to be placed around a selected piece of code.
Refactoring: These snippets are used during code refactoring.

Surround-with code snippets: These snippets surrounds the selected code, with the code snippets code.
1. Select the code to surround, and use keyboard shortcut CTRL K + S
2. Select the code to surround, right click and select "Surround with.." option from the context menu
3. Select the code to surround, then click on Edit menu, select "IntelliSense" and then select the "Surround With" command.

Code snippets can be used with any type of applications that you create with visual studio. For example, you can use them with
1. Console applications
2. ASP.NET web applications
3. ASP.NET MVC applications etc..

Code snippets are available for the following languages. 
1. C#
2. Visual Basic
3. XML
4. HTML
5. JScript
6. SQL

Code Snippet Manager can be used to Add or remove code snippets. You can also find the following information about a code snippet.
1. Description
2. Shortcut
3. Snippet Type
4. Author

To access code snippet manager, click on "Tools" and then select "Code Snippet Manager". Code snippets are xml files and have .snippet extension.

 


Part 72 - What is dictionary in c#


Suggested Videos 
Part 69 - Making method parameters optional by specifying parameter defaults
Part 70 - Making method parameters optional by using OptionalAttribute
Part 71 - Code snippets in visual studio



In thie video, we will discuss dictionary object in c#.
1. A dictionary is a collection of (key, value) pairs.
2. Dictionary class is present in System.Collections.Generic namespace.
3. When creating a dictionary, we need to specify the type for key and value.
4. Dictionary provides fast lookups for values using keys.
5. Keys in the dictionary must be unique.



Here is an example. The code is commented and is self-explanatory.
public class Program
{
   
public static void Main()
    {
       
// Create a Dictionary, CustomerID is the key. Type is int
        // Customer object is the value. Type is Customer
       
Dictionary<int, Customer> dictionaryCustomers = new Dictionary<intCustomer>();

        // Create Customer Objects
       
Customer customr1 = new Customer()
        {
            ID = 101,
            Name =
"Mark",
            Salary = 5000
        };

        
Customer customr2 = new Customer()
        {
            ID = 102,
            Name =
"Pam",
            Salary = 7000
        };

        
Customer customr3 = new Customer()
        {
            ID = 104,
            Name =
"Rob",
            Salary = 5500
        };

        // Add customer objects to the dictionary
        dictionaryCustomers.Add(customr1.ID, customr1);
        dictionaryCustomers.Add(customr2.ID, customr2);
        dictionaryCustomers.Add(customr3.ID, customr3);

        // Retrieve the value (Customer object) from the dictionary,
        // using key (customer ID). The fastest way to get a value
        // from the dictionary is by using its key

       
Console.WriteLine("Customer 101 in customer dictionary");
       
Customer customer101 = dictionaryCustomers[101];
        
Console WriteLine("ID = {0}, Name = {1}, Salary = {2}",
                            customer101.ID, customer101.Name, customer101.Salary);
       
Console.WriteLine("--------------------------------------------------");

        // It is also possible to loop thru each key/value pair in a dictionary
       
Console.WriteLine("All customer keys and values in customer dictionary");
       
foreach (KeyValuePair<int, Customer> customerKeyValuePair in dictionaryCustomers)
        {
           
Console.WriteLine("Key = " + customerKeyValuePair.Key);
           
Customer cust = customerKeyValuePair.Value;
            
Console.WriteLine("ID = {0}, Name = {1}, Salary = {2}", cust.ID, cust.Name, cust.Salary);
        }
       
Console.WriteLine("--------------------------------------------------");

       
// You can also use implicitly typed variable VAR to 
        // loop thru each key/value pair in a dictionary. But try
        // to avoid using var, as this makes your code less readable
       
Console.WriteLine("All customer keys and values in customer dictionary");
       
foreach (var customerKeyValuePair in dictionaryCustomers)
        {
           
Console.WriteLine("Key = " + customerKeyValuePair.Key);
           
Customer cust = customerKeyValuePair.Value;
            
Console.WriteLine("ID = {0}, Name = {1}, Salary = {2}", cust.ID, cust.Name, cust.Salary);
        }
       
Console.WriteLine("--------------------------------------------------");

       
// To get all the keys in the dictionary
       
Console.WriteLine("All Keys in Customer Dictionary");
       
foreach (int key in dictionaryCustomers.Keys)
        {
           
Console.WriteLine(key);
        }
       
Console.WriteLine("--------------------------------------------------");

        // To get all the values in the dictionary
       
Console.WriteLine("All Customer objects in Customer Dictionary");
       
foreach (Customer customer in dictionaryCustomers.Values)
        {
           
Console.WriteLine("ID = {0}, Name = {1}, Salary = {2}", customer.ID, customer.Name, customer.Salary);
        }

       
// If you try to add a key that already exists in the dictionary you 
        // will get an exception - An item with same key has already been 
        // added. So, check if the key already exists
       
if (!dictionaryCustomers.ContainsKey(101))
        {
            dictionaryCustomers.Add(101, customr1);
        }

       
// When accessing a dictionary value by key, make sure the dictionary 
        // contains the key, otherwise you will get KeyNotFound exception.
       
if (dictionaryCustomers.ContainsKey(110))
        {
           
Customer cus = dictionaryCustomers[110];
        }
       
else
        {
           
Console.WriteLine("Key does not exist in the dictionary");
        }
    }
}

public class Customer
{
   
public int ID { get; set; }
   
public string Name { get; set; }
   
public int Salary { get; set; }
}

Part 73 - What is dictionary in c# continued


Suggested Videos 
Part 70 - Making method parameters optional by using OptionalAttribute
Part 71 - Code snippets in visual studio
Part 72 - What is dictionary in c#



Please watch
Part 72 from the c# tutorial before proceeding with this video. This is a continuation to Part 72.

In this video, we will discuss the following methods of Dictionary class.
1. TryGetValue()
2. Count()
3. Remove()
4. Clear()
5. Using LINQ extension methods with Dictionary
6. Different ways to convert an array into a dictionary



Code used in the demo:
public class Program
{
   
public static void Main()
    {
        // Create Customer Objects
       
Customer customr1 = new Customer()
        {
            ID = 101,
            Name =
"Mark",
            Salary = 5000
        };

        
Customer customr2 = new Customer()
        {
            ID = 102,
            Name =
"Pam",
            Salary = 7000
        };

        
Customer customr3 = new Customer()
        {
            ID = 104,
            Name =
"Rob",
            Salary = 5500
        };

        // Create a Dictionary, CustomerID is the key. Type is int
        // Customer object is the value. Type is Customer
       
Dictionary<int, Customer> dictionaryCustomers = new Dictionary<int, Customer>();

        // Add customer objects to the dictionary
        dictionaryCustomers.Add(customr1.ID, customr1);
        dictionaryCustomers.Add(customr2.ID, customr2);
        dictionaryCustomers.Add(customr3.ID, customr3);

        // If you are not sure if a key is present or not, you can use 
        // TryGetValue() method to get the value from a dictionary.
       
Customer customer999;
       
if (dictionaryCustomers.TryGetValue(999, out customer999))
        {
           
Console.WriteLine("ID = {0}, Name = {1}, Salary = {2}", customer999.ID, customer999.Name, customer999.Salary);
        }
       
else
        {
            
Console.WriteLine("Customer with Key = 999 is not found in the dictionary");
            
Console.WriteLine("-------------------------------------------------------------------");
        }

        // To find the total number of items in a dictionary use Count() method
        Console.WriteLine(
"Total items in Dictionary = {0}", dictionaryCustomers.Count());
        Console.WriteLine(
"-------------------------------------------------------------------");

       
// LINQ extension methods can be used with Dictionary. For example, to find the 
        // total employees whose salary is greater than 5000.
        
Console.WriteLine("Items in dictionary where Salary is greater than 5000 = {0}",
            dictionaryCustomers.Count(x => x.Value.Salary > 5000));
        
Console.WriteLine("-------------------------------------------------------------------");

        // To remove an item from the dictionary, use Remove() method
        dictionaryCustomers.Remove(101);

        // To remove all items from the dictionary, use Clear() method
        dictionaryCustomers.Clear();

        // Create an array of customers
       
Customer[] arrayCustomers = new Customer[3];
        arrayCustomers[0] = customr1;
        arrayCustomers[1] = customr2;
        arrayCustomers[2] = customr3;

        // Convert customer array to a dictionary using ToDictionary() method.
        // In this example, key is Customer ID and value is the customer object
       
Dictionary<int, Customer> dict = arrayCustomers.ToDictionary(customer => customer.ID, customer => customer);
       
// OR        
        // Dictionary<int, Customr> dict = arrayCustomers.ToDictionary(customer => customer.ID);
        // OR use a foreach loop
        // Dictionary<int, Customer> dict = new Dictionary<int, Customer>();
        // foreach (Customer cust in arrayCustomers)
        // {
        //     dict.Add(cust.ID, cust);
        // }

       
// Loop thru the dictionary and print the key/value pairs
       
foreach (KeyValuePair<int, Customer> kvp in dict)
        {
           
Console.WriteLine("Key = {0}", kvp.Key);
           
Customer customr = kvp.Value;
            
Console WriteLine("ID = {0}, Name = {1}, Salary {2}", customr.ID, customr.Name, customr.Salary);
        }
       
Console.WriteLine("-------------------------------------------------------------------");
    }
}

public class Customer
{
   
public int ID { get; set; }
   
public string Name { get; set; }
    
public int Salary { get; set; }
}

Part 74 - List collection class in c#


Suggested Videos 
Part 71 - Code snippets in visual studio
Part 72 - What is dictionary in c#
Part 73 - What is dictionary in c# continued



List is one of the generic collection classes present in System.Collections.Generic namespcae. There are several generic collection classes in System.Collections.Generic namespace as listed below.
1. Dictionary - Discussed in
Parts 72 & 73
2. List
3. Stack
4. Queue etc



A List class can be used to create a collection of any type. For example, we can create a list of Integers, Strings and even complex types. The objects stored in the list can be accessed by index. Unlike arrays, lists can grow in size automatically. This class also provides methods to search, sort, and manipulate lists.

public class Program
{
   
public static void Main()
    {
       
// Create Customer Objects
       
Customer customer1 = new Customer()
        {
            ID = 101,
            Name =
"Mark",
            Salary = 5000
        };

        
Customer customer2 = new Customer()
        {
            ID = 102,
            Name =
"Pam",
            Salary = 7000
        };

        
Customer customer3 = new Customer()
        {
            ID = 104,
            Name =
"Rob",
            Salary = 5500
        };

       
Customer[] arrayCustomers = new Customer[2];
        arrayCustomers[0] = customer1;
        arrayCustomers[1] = customer2;
       
// The following line will throw an exception, Index was outside the bounds of the array. 
        // This is because, arrays does not grow in size automatically.
        // arrayCustomers[2] = customer3;
       
       
// Create a List of Customers. Here, we have set the size to 2. But when I add a third 
        // element the list size will automatically grow and we will not get an exception.
       
List<Customer> listCustomers = new List<Customer>(2);
       
// To add an element to the list, use Add() method.
        listCustomers.Add(customer1);
        listCustomers.Add(customer2);
       
// Adding an element beyond the initial capacity of the list will not throw an exception.
        listCustomers.Add(customer3);

       
// Items can be retrieved from the list by index. The following code will 
        // retrieve the first item from the list. List index is ZERO based.
       
Customer cust = listCustomers[0];
       
Console.WriteLine("ID = {0}, Name = {1}, Salary = {2}",
                 cust.ID, cust.Name, cust.Salary);
        
Console.WriteLine("------------------------------------------------");

        // foreach or for loop can be used to iterate thru all the items in the list
     
  // Using for loop
       
for (int i = 0; i < listCustomers.Count; i++)
        {
           
Customer customer = listCustomers[i];
           
Console.WriteLine("ID = {0}, Name = {1}, Salary = {2}",
                     customer.ID, customer.Name, customer.Salary);
        }
        
Console.WriteLine("------------------------------------------------");

       
// Using foreach loop
       
foreach (Customer c in listCustomers)
        {
           
Console.WriteLine("ID = {0}, Name = {1}, Salary = {2}", c.ID, c.Name, c.Salary);
        }
        
Console.WriteLine("------------------------------------------------");

        // All generic collection classes including List are strongly typed. This means 
        // if you have created a List of type Customer, only objects of type Customer 
        // can be added to the list. If you try to add an object of different type you would 
        // get a compiler error. The following line will raise a compiler error.
        // listCustomers.Add("This will not compile");

       
// If you want to insert an item at a specific index location of the list, use Insert() method. 
        // The following line will insert customer3 object at index location 1.
        listCustomers.Insert(1, customer3);
       
Console.WriteLine("ID = {0}, Name = {1}, Salary = {2}",
               listCustomers[1].ID, listCustomers[1].Name, listCustomers[1].Salary);
        
Console.WriteLine("------------------------------------------------");

       
// To get the index of specific item in the list use Indexof() method
       
Console.WriteLine("Index of Customer3 object in the List = " +    
                listCustomers.IndexOf(customer3));
        
Console.WriteLine("------------------------------------------------");
    }
}

public class Customer
{
   
public int ID { get; set; }
   
public string Name { get; set; }
    
public int Salary { get; set; }
}

Part 75 - List collection class in c# continued


Suggested Videos 
Part 72 - What is dictionary in c#
Part 73 - What is dictionary in c# continued
Part 74 - List collection class in c#



This is continuation to
Part 74. So, please watch Part 74, before proceeding. In this video, we will discuss
1. Contains() function - Use this function to check if an item exists in the list. This method returns true if the items exists, else false.

2. Exists() function - Use this function, to check if an item exists in the list based on a condition. This method returns true if the items exists, else false.

3. Find() function - This method searches for an element that matches the conditions defined by the specified lambda expression and returns the first matching item from the list.

4. FindLast() function - This method searches for an element that matches the conditions defined by the specified lambda expression and returns the Last matching item from the list.

5. FindAll() function - This method returns all the items from the list that match the conditions specified by the lambda expression.



6. FindIndex() function - This method returns the index of the first item, that matches the condition specified by the lambda expression. There are 2 other overloads of this method which allows us to specify the range of elements to search, with in the list.

7. FindLastIndex() function - This method returns the index of the last item, that matches the condition specified by the lambda expression. There are 2 other overloads of this method which allows us to specify the range of elements to search, with in the list.

8. Convert an array to a List - Use ToList() method

9. Convert a list to an array - Use ToArray() method

10. Convert a List to a Dictionary - Use ToDictionary() method

public class Program
{
   
public static void Main()
    {
        // Create Customer Objects
       
Customer customer1 = new Customer()
        {
            ID = 101,
            Name =
"Mark",
            Salary = 4000
        };

        
Customer customer2 = new Customer()
        {
            ID = 102,
            Name =
"Pam",
            Salary = 7000
        };

        
Customer customer3 = new Customer()
        {
            ID = 104,
            Name =
"Rob",
            Salary = 5500
        };

        
Customer[] arrayCustomers = new Customer[3];
        arrayCustomers[0] = customer1;
        arrayCustomers[1] = customer2;
        arrayCustomers[2] = customer3;

        // To convert an array to a List, use ToList() method
       
List<Customer> listCustomers = arrayCustomers.ToList();
       
foreach (Customer c in listCustomers)
        {
           
Console.WriteLine("ID = {0}, Name = {1}, Salary = {2}", c.ID, c.Name, c.Salary);
        }
        
Console.WriteLine("------------------------------------------------------");

        // To convert a List to an array, use ToLArray() method
        
Customer[] arrayAllCustomers = listCustomers.ToArray();
        foreach (
Customer c in arrayAllCustomers)
        {
            
Console.WriteLine("ID = {0}, Name = {1}, Salary = {2}", c.ID, c.Name, c.Salary);
        }
        
Console.WriteLine("------------------------------------------------------");

       
// To convert a List to a Dictionary use ToDictionary() method
       
Dictionary<intCustomer> dictionaryCustomers = listCustomers.ToDictionary(x => x.ID);
       
foreach (KeyValuePair<intCustomer> keyValuePairCustomers in dictionaryCustomers)
        {
            
Console.WriteLine("Key = {0}", keyValuePairCustomers.Key);
           
Customer c = keyValuePairCustomers.Value;
            
Console.WriteLine("ID = {0}, Name = {1}, Salary = {2}", c.ID, c.Name, c.Salary);
        }
        
Console.WriteLine("------------------------------------------------------");

       
// To check if an item exists in the list use Contains() function
        // This method returns true if the items exists, else false
       
if (listCustomers.Contains(customer2))
        {
            
Console.WriteLine("Customer2 object exists in the list");
        }
       
else
        {
            
Console.WriteLine("Customer2 object does not exist in the list");
        }
        
Console.WriteLine("------------------------------------------------------");

       
// To check if an item exists in the list based on a condition, then use Exists() function
        // This method returns true if the items exists, else false
       
if (listCustomers.Exists(x => x.Name.StartsWith("M")))
        {
            
Console.WriteLine("List contains customer whose name starts with M");
        }
       
else
        {
            
Console.WriteLine("List does not contain a customer whose name starts with M");
        }
        
Console.WriteLine("------------------------------------------------------");

        // Find() method searches for an element that matches the conditions defined by 
        // the specified lambda expression and returns the first matching item from the list
       
Customer cust = listCustomers.Find(customer => customer.Salary > 5000);
        
Console.WriteLine("ID = {0}, Name = {1}, Salary = {2}", cust.ID, cust.Name, cust.Salary);
        
Console.WriteLine("------------------------------------------------------");

       
// FindLast() method searches for an element that matches the conditions defined
        // by the specified lambda expression and returns the Last matching item from the list
       
Customer lastMatch = listCustomers.FindLast(customer => customer.Salary > 5000);
        
Console WriteLine("ID = {0}, Name = {1}, Salary = {2}", lastMatch.ID, lastMatch.Name, lastMatch.Salary);
        
Console.WriteLine("------------------------------------------------------");

       
// FindAll() method returns all the items from the list that
        // match the conditions specified by the lambda expression
       
List<Customer> filteredCustomers = listCustomers.FindAll(customer => customer.Salary > 5000);
        foreach (
Customer cstmr in filteredCustomers)
        {
            
Console.WriteLine("ID = {0}, Name = {1}, Salary = {2}", cstmr.ID, cstmr.Name, cstmr.Salary);
        }
        
Console.WriteLine("------------------------------------------------------");

       
// FindIndex() method returns the index of the first item, that matches the 
        // condition specified by the lambda expression. There are 2 other overloads
        // of this method which allows us to specify the range of elements to 

        // search, with in the list.
        
Console.WriteLine("Index of the first matching customer object whose salary is greater 5000 =" +
            listCustomers.FindIndex(customer => customer.Salary > 5000));
        
Console.WriteLine("------------------------------------------------------");

        // FindLastIndex() method returns the index of the last item, 
        // that matches the condition specified by the lambda expression. 
        // There are 2 other overloads of this method which allows us to specify 
        // the range of elements to search, with in the list.
        
Console.WriteLine("Index of the Last matching customer object whose salary is greater 5000 = " +
            listCustomers.FindLastIndex(customer => customer.Salary > 5000));
        
Console.WriteLine("------------------------------------------------------");
    }
}

public class Customer
{
   
public int ID { get; set; }
   
public string Name { get; set; }
   
public int Salary { get; set; }
}

Part 76 - Working with generic list class and ranges in c#


Suggested Videos 
Part 73 - What is dictionary in c# continued
Part 74 - List collection class in c#
Part 75 - List collection class in c# continued



Please watch
Part 74 & 75 before proceeding with this video. In thie video, we will discuss

1. AddRange() - Add() method allows you to add one item at a time to the end of the list, where as AddRange() allows you to add another list of items, to the end of the list.

2. GetRange() - Using an item index, we can retrieve only one item at a time from the list, if you want to get a list of items from the list, then use GetRange() function. This function expects 2 parameters, i.e the start index in the list and the number of elements to return.

3. InsertRange() - Insert() method allows you to insert a single item into the list at a specificed index, where as InsertRange() allows you, to insert another list of items to your list at the specified index.

4. RemoveRange() - Remove() function removes only the first matching item from the list. RemoveAt() function, removes the item at the specified index in the list. RemoveAll() function removes all the items that matches the specified condition. RemoveRange() method removes a range of elements from the list. This function expects 2 parameters, i.e the start index in the list and the number of elements to remove. If you want to remove all the elements from the list without specifying any condition, then use Clear() function.



public class Program
{
   
public static void Main()
    {
       
// Create Customer Objects
       
Customer customer1 = new Customer()
        {
            ID = 101,
            Name =
"Mark",
            Salary = 4000,
            Type =
"RetailCustomer"
        };

        
Customer customer2 = new Customer()
        {
            ID = 102,
            Name =
"Pam",
            Salary = 7000,
            Type = 
"RetailCustomer"
        };

        
Customer customer3 = new Customer()
        {
            ID = 103,
            Name =
"Rob",
            Salary = 5500,
            Type = 
"RetailCustomer"
        };

        
Customer customer4 = new Customer()
        {
            ID = 104,
            Name =
"John",
            Salary = 6500,
            Type =
"CorporateCustomer"
        };

        
Customer customer5 = new Customer()
        {
            ID = 105,
            Name =
"Sam",
            Salary = 3500,
            Type = 
"CorporateCustomer"
        };

       
       
List<Customer> listCustomers = new List<Customer>();
        // Add() method allows you to add one at a time to the end of the list
        listCustomers.Add(customer1);
        listCustomers.Add(customer2);
        listCustomers.Add(customer3);

       
List<Customer> listCorporateCustomers = new List<Customer>();
        listCorporateCustomers.Add(customer4);
        listCorporateCustomers.Add(customer5);

        // AddRange() allows you to add another list of items, to the end of the list
        listCustomers.AddRange(listCorporateCustomers);

       
foreach (Customer customer in listCustomers)
        {
           
Console.WriteLine("ID = {0}, Name = {1}, Salary = {2}, Type = {3}",
                customer.ID, customer.Name, customer.Salary, customer.Type);
        }
       
Console.WriteLine("------------------------------------------------------");

       
// GetRange() function returns a list of items from the list.
       
List<Customer> corporateCustomers = listCustomers.GetRange(3, 2);
       
foreach (Customer customer in corporateCustomers)
        {
           
Console.WriteLine("ID = {0}, Name = {1}, Salary = {2}, Type = {3}",
                customer.ID, customer.Name, customer.Salary, customer.Type);
        }
       
Console.WriteLine("------------------------------------------------------");

       
// Remove() function removes only the first matching item from the list.
        listCustomers.Remove(customer1);

       
// RemoveAt() function, removes the item at the specified index in the list.
        listCustomers.RemoveAt(0);

        // RemoveAll() function removes all the items that matches the specified condition.
        listCustomers.RemoveAll(x => x.Type ==
"RetailCustomer");

       
foreach (Customer customer in listCustomers)
        {
           
Console.WriteLine("ID = {0}, Name = {1}, Salary = {2}, Type = {3}",
                customer.ID, customer.Name, customer.Salary, customer.Type);
        }
       
Console.WriteLine("------------------------------------------------------");

       
// RemoveRange() method removes a range of elements from the list. 
        // This function expects 2 parameters, i.e the start index in the 
        // list and the number of elements to remove.
        listCustomers.RemoveRange(0, 2);

        // Insert() method allows you to insert a single item at a time into 
        // the list at a specificed index
        listCustomers.Insert(0, customer1);
        listCustomers.Insert(1, customer2);
        listCustomers.Insert(2, customer3);

        // InsertRange() allows you, to insert another list of items to your list at the specified index
        listCustomers.InsertRange(0, listCorporateCustomers);

       
foreach (Customer customer in listCustomers)
        {
           
Console.WriteLine("ID = {0}, Name = {1}, Salary = {2}, Type = {3}",
                customer.ID, customer.Name, customer.Salary, customer.Type);
        }
       
Console.WriteLine("------------------------------------------------------");

        // If you want to remove all the elements from the list without specifying 
        // any condition, then use Clear() function.
        listCustomers.Clear();

       
Console.WriteLine(" Total Items in the List = " + listCustomers.Count);
    }
}

public class Customer
{
   
public int ID { get; set; }
   
public string Name { get; set; }
   
public int Salary { get; set; }
    
public string Type { get; set; }
}

Part 77 - Sort a list of simple types in c#


Suggested Videos 
Part 74 - List collection class in c#
Part 75 - List collection class in c# continued
Part 76 - Working with generic list class and ranges in c#



Sorting a list of simple types like int, string, char etc, is straight forward. Just invoke Sort() method on the list instance and the data will be automatically sorted in ascending order.
List<int> numbers = new List<int> { 1, 8, 7, 5, 2, 3, 4, 9, 6 };
numbers.Sort();



If you want the data to be retrieved in descending order, use Reverse() method on the list instance.
numbers.Reverse();

However, when you do the same thing on a complex type like
Customer, we get a runtime invalid operation exception - Failed to compare 2 elements in the array. This because, .NET runtime does not know, how to sort complex types. We have to tell the way we want data to be sorted in the list by implementing IComparable interface. We will discuss this in a later video session.

So, the next obvious question - How is the sort functionality working for simple types like int, string, char etc?
That is because these types (int, string, decimal, char etc) have implemented IComparable interface already.

Here is the example code used in demo:
public class Program
{
   
public static void Main()
    {
       
List<int> numbers = new List<int> { 1, 8, 7, 5, 2, 3, 4, 9, 6 };

       
Console.WriteLine("Numbers before sorting");
       
foreach (int i in numbers)
        {
            
Console.WriteLine(i);
        }

       
// Sort() will sort data in ascending order 
        numbers.Sort();

        
Console.WriteLine("Numbers after sorting");
       
foreach (int i in numbers)
        {
            
Console.WriteLine(i);
        }

       
// Use Reverse() method to retrieve data in descending order
        numbers.Reverse();

        
Console.WriteLine("Numbers in descending order");
       
foreach (int i in numbers)
        {
            
Console.WriteLine(i);
        }

       
List<string> alphabets = new List<string>() { "B", "F", "D", "E", "A", "C" };

        
Console.WriteLine("Alphabets before sorting");
       
foreach (string alphabet in alphabets)
        {
            
Console.WriteLine(alphabet);
        }

        alphabets.Sort();

        
Console.WriteLine("Alphabets after sorting");
        foreach (
string alphabet in alphabets)
        {
            
Console.WriteLine(alphabet);
        }

        alphabets.Reverse();

        
Console.WriteLine("Alpabets in descending order");
       
foreach (string alphabet in alphabets)
        {
            
Console.WriteLine(alphabet);
        }

        
Customer customer1 = new Customer()
        {
            ID = 101,
            Name =
"Mark",
            Salary = 4000
        };

        
Customer customer2 = new Customer()
        {
            ID = 102,
            Name =
"Pam",
            Salary = 7000
        };

       
Customer customer3 = new Customer()
        {
            ID = 103,
            Name =
"Rob",
            Salary = 5500
        };

       
List<Customer> listCustomers = new List<Customer>();
        listCustomers.Add(customer1);
        listCustomers.Add(customer2);
        listCustomers.Add(customer3);

        
Console.WriteLine("Customers before sorting");
       
foreach (Customer customer in listCustomers)
        {
            
Console.WriteLine(customer.Name);
        }

       
// Invoking Sort() on list of complex types will 
        // throw invalid operation exception, unless 
        // IComparable interface is implemented
        listCustomers.Sort();
           
        
Console.WriteLine("Customers after sorting");
       
foreach (Customer customer in listCustomers)
        {
            
Console.WriteLine(customer.Name);
        }
    }
}

public class Customer 
{
   
public int ID { get; set; }
   
public string Name { get; set; }
    
public int Salary { get; set; }

}

Part 78 - Sort a list of complex types in c#


Suggested Videos 
Part 75 - List collection class in c# continued
Part 76 - Working with generic list class and ranges in c#
Part 77 - Sort a list of simple types in c#



This is continuation to
Part 77. Please watch Part 77, before proceeding.

To sort a list of complex types without using LINQ, the complex type has to implement IComparable interface and provide implementation for CompareTo() method. CompareTo() method returns an integer, and the meaning of the return value is shown below.
Return value greater than ZERO - The current instance is greater than the object being compared with.
Return value less than ZERO - The current instance is less than the object being compared with.
Return value is ZERO - The current instance is equal to the object being compared with.



Alternatively you can also invoke CompareTo() method. Salary property of the Customer object is int. CompareTo() method is already implemented on integer type, so we can invoke this method and return it's value as shown below.
return this.Salary.CompareTo(obj.Salary);

public class Customer : IComparable<Customer>
{
   
public int ID { get; set; }
   
public string Name { get; set; }
   
public int Salary { get; set; }

   
public int CompareTo(Customer obj)
    {
       
//if (this.Salary > obj.Salary)
        //    return 1;
        //else if (this.Salary < obj.Salary)
        //    return -1;
        //else
        //    return 0;

       
// OR, Alternatively you can also invoke CompareTo() method. 
       
return this.Salary.CompareTo(obj.Salary);
    }
}

If you prefer not to use the Sort functionality provided by the Customer class, then you can provide your own by implementing IComparer interface. For example, if I want the customers to sorted by name instead of salary.
Step 1: Implement IComparer interface
public class SortByName : IComparer<Customer>
{
   
public int Compare(Customer x, Customer y)
    {
       
return x.Name.CompareTo(y.Name);
    }
}

Step 2: Pass an instance of the class that implements IComparer interface, as an argument to the Sort() method.
SortByName sortByName = new SortByName();
listCutomers.Sort(sortByName);

Here is the Main() method code:
public class Program
{
   
public static void Main()
    {
       
Customer customer1 = new Customer()
        {
            ID = 101,
            Name =
"Mark",
            Salary = 4000
        };

        
Customer customer2 = new Customer()
        {
            ID = 102,
            Name =
"John",
            Salary = 7000
        };

        
Customer customer3 = new Customer()
        {
            ID = 103,
            Name =
"Ken",
            Salary = 5500
        };

       
List<Customer> listCutomers = new List<Customer>();
        listCutomers.Add(customer1);
        listCutomers.Add(customer2);
        listCutomers.Add(customer3);

       
Console.WriteLine("Customers before sorting");
       
foreach (Customer customer in listCutomers)
        {
            
Console.WriteLine(customer.Name + " - " + customer.Salary);
        }

        // Sort() method should sort customers by salary
        listCutomers.Sort();

        
Console.WriteLine("Customers after sorting");
       
foreach (Customer customer in listCutomers)
        {
            
Console.WriteLine(customer.Name + " - " + customer.Salary);
        }

       
// To sort customers by name instead of salary
       
SortByName sortByName = new SortByName();
        listCutomers.Sort(sortByName);

        
Console.WriteLine("Customers after sorting by Name");
       
foreach (Customer customer in listCutomers)
        {
            
Console.WriteLine(customer.Name + " - " + customer.Salary);
        }
    }
}

Part 79 - Sort a list of complex types using Comparison delegate


Suggested Videos 
Part 76 - Working with generic list class and ranges in c#
Part 77 - Sort a list of simple types in c#
Part 78 - Sort a list of complex types in c#



This is continuation to
Part 78. Please watch Part 78, before proceeding.

One of the overloads of the Sort() method in List class expects Comparison delegate to be passed as an argument. Let us understand using this overloaded version.
public void Sort(Comparison<T> comparison)



Approach 1:
Step 1: Create a function whose signature matches the signature of System.Comparison delegate. This is the method where we need to write the logic to compare 2 customer objects.
private static int CompareCustomers(Customer c1, Customer c2)
{
   
return c1.ID.CompareTo(c2.ID);
}

Step 2: Create an instance of System.Comparison delegate, and then pass the name of the function created in Step1 as the argument. So, at this point "Comparison" delegate is pointing to our function that contains the logic to compare 2 customer objects.
Comparison<Customer> customerComparer = new Comparison<Customer>(CompareCustomers);

Step 3: Pass the delegate instance as an argument, to Sort() function.
listCutomers.Sort(customerComparer);

At this point, listCutomers should be sorted using the logic defined in CompareCustomers() function.

Approach 2:
In Approcah1 this is what we have done
1. Created a private function that contains the logic to compare customers
2. Created an instance of Comparison delegate, and then passed the name of the private function to the delegate.
3. Finally passed the delegate instance to the Sort() method.

Do we really have to follow all these steps. Isn't there any other way?
The above code can be simplified using delegate keyword as shown below.
listCutomers.Sort(
delegate(Customer c1, Customer c2)
                    {
                       
return (c1.ID.CompareTo(c2.ID));
                    });

Approach 3: The code in Approach 2, can be further simplified using lambda expression as shown below.
listCutomers.Sort((x, y) => x.ID.CompareTo(y.ID));

Example:
public class Program
{
   
public static void Main()
    {
       
Customer customer1 = new Customer()
        {
            ID = 101,
            Name =
"Mark",
            Salary = 4000
        };

        
Customer customer2 = new Customer()
        {
            ID = 103,
            Name =
"John",
            Salary = 7000
        };

        
Customer customer3 = new Customer()
        {
            ID = 102,
            Name =
"Ken",
            Salary = 5500
        };

       
List<Customer> listCutomers = new List<Customer>();
        listCutomers.Add(customer1);
        listCutomers.Add(customer2);
        listCutomers.Add(customer3);

       
Console.WriteLine("Customers before sorting");
       
foreach (Customer customer in listCutomers)
        {
           
Console.WriteLine(customer.ID);
        }

       
// Approach 1
        // Step 2: Create an instance of Comparison delegate
        //Comparison<Customer> customerComparer = 
        //    new Comparison<Customer>(CompareCustomers);

        // Step 3: Pass the delegate instance to the Sort method

        //listCutomers.Sort(customerComparer);

        // Approach 2: Using delegate keyword

        //listCutomers.Sort(delegate(Customer c1, Customer c2)
        //{
        //    return (c1.ID.CompareTo(c2.ID));
        //});
           
       
// Aaproach 3: Using lambda expression
        listCutomers.Sort((x, y) => x.ID.CompareTo(y.ID));

       
Console.WriteLine("Customers after sorting by ID");
       
foreach (Customer customer in listCutomers)
        {
           
Console.WriteLine(customer.ID);
        }

        listCutomers.Reverse();
       
Console.WriteLine("Customers in descending order of ID");
       
foreach (Customer customer in listCutomers)
        {
           
Console.WriteLine(customer.ID);
        }
    }

    // Approach 1 - Step 1
    // Method that contains the logic to compare customers
   
private static int CompareCustomers(Customer c1, Customer c2)
    {
       
return c1.ID.CompareTo(c2.ID);
    }
}

public class Customer
{
   
public int ID { get; set; }
   
public string Name { get; set; }
    
public int Salary { get; set; }
}

 

Part 80 - Some useful methods of List collection class


Suggested Videos 
Part 77 - Sort a list of simple types in c#
Part 78 - Sort a list of complex types in c#
Part 79 - Sort a list of complex types using Comparison delegate



This is continuation to
Part 79. Please watch Part 79, before proceeding.

In this video, we will discuss the following methods
1. TrueForAll() - Returns true or false depending on whether if every element in the list matches the conditions defined by the specified predicate.

2. AsReadOnly() - Returns a read-only wrapper for the current collection. Use this method, if you don't want the client code to modify the collection i.e add or remove any elements from the collection. The ReadOnlyCollection will not have methods to add or remove items from the collection. You can only read items from this collection.

3. TrimExcess() - Sets the capacity to the actual number of elements in the List, if that number is less than a threshold value.



According to MSDN: 
This method can be used to minimize a collection's memory overhead if no new elements will be added to the collection. The cost of reallocating and copying a large List<T> can be considerable, however, so the TrimExcess method does nothing if the list is at more than 90 percent of capacity. This avoids incurring a large reallocation cost for a relatively small gain. The current threshold is 90 percent, but this could change in the future.

public class Program
{
   
public static void Main()
    {
       
Customer customer1 = new Customer()
        {
            ID = 101,
            Name =
"Mark",
            Salary = 5200
        };

        
Customer customer2 = new Customer()
        {
            ID = 103,
            Name =
"John",
            Salary = 7000
        };

        
Customer customer3 = new Customer()
        {
            ID = 102,
            Name =
"Ken",
            Salary = 5500
        };

       
List<Customer> listCutomers = new List<Customer>(100);
        listCutomers.Add(customer1);
        listCutomers.Add(customer2);
        listCutomers.Add(customer3);

       
Console.WriteLine("Are all salaries greater than 5000: "
            + listCutomers.TrueForAll(x => x.Salary > 5000));

       
// ReadOnlyCollection will not have Add() or Remove() methods
        System.Collections.ObjectModel.
ReadOnlyCollection<Customer>
            readOnlyCustomers = listCutomers.AsReadOnly();

       
Console.WriteLine("Total Items in ReadOnlyCollection = " +
            readOnlyCustomers.Count);

       
// listCutomers list is created with an initial capacity of 100
        // but only 3 items are in the list. The filled percentage is 
        // less than 90 percent threshold.
        
Console.WriteLine("List capacity before invoking TrimExcess = " +
                listCutomers.Capacity);
       
// Invoke TrimExcess() to set the capacity to the actual 
        // number of elements in the List
        listCutomers.TrimExcess();
       
Console.WriteLine(listCutomers.Capacity);
    }
}

public class Customer
{
   
public int ID { get; set; }
   
public string Name { get; set; }
    
public int Salary { get; set; }
}

Part 81 - When to use a dictionary over list in c#


Suggested Videos 
Part 78 - Sort a list of complex types in c#
Part 79 - Sort a list of complex types using Comparison delegate
Part 80 - Some useful methods of List collection class



Find() method of the List class loops thru each object in the list until a match is found. So, if you want to lookup a value using a key, dictionary is better for performance over list. So, use dictionary when you know the collection will be primarily used for lookups.



Example code used in the demo
public class Program
{
   
public static void Main()
    {
       
Country country1 = new Country()
        {
            Code = "AUS",
            Name = "AUSTRALIA",
            Capital = "Canberra"
        };

        
Country country2 = new Country()
        {
            Code = "IND",
            Name = "INDIA ",
            Capital = "New Delhi"
        };

        
Country country3 = new Country()
        {
            Code = "USA",
            Name = "UNITED STATES",
            Capital = "Washington D.C."
        };

        
Country country4 = new Country()
        {
            Code = "GBR",
            Name = "UNITED KINGDOM",
            Capital = "London"
        };

        
Country country5 = new Country()
        {
            Code = "CAN",
            Name = "CANADA",
            Capital = "Ottawa"
        };

        //List<Country> listCountries = new List<Country>();
        //listCountries.Add(country1);
        //listCountries.Add(country2);
        //listCountries.Add(country3);
        //listCountries.Add(country4);
        //listCountries.Add(country5);

        
Dictionary<stringCountry> dictionaryCountries = new Dictionary<string, Country>();
        dictionaryCountries.Add(country1.Code, country1);
        dictionaryCountries.Add(country2.Code, country2);
        dictionaryCountries.Add(country3.Code, country3);
        dictionaryCountries.Add(country4.Code, country4);
        dictionaryCountries.Add(country5.Code, country5);

       
string strUserChoice = string.Empty;
       
do
        {
           
Console.WriteLine("Please enter country code");
           
string strCountryCode = Console.ReadLine().ToUpper();

           
// Find() method of the list class loops thru each object in the list until a match
            // is found. So, if you want to lookup a value using a key dictionary is better 

            // for performance over list. 
            // Country resultCountry = listCountries.
            //                                    Find(country => country.Code == strCountryCode);

           
Country resultCountry = dictionaryCountries.ContainsKey(strCountryCode) ?                 dictionaryCountries[strCountryCode] : null;

           
if (resultCountry == null)
            {
               
Console.WriteLine("The country code you enetered does not exist");
            }
           
else
            {
               
Console.WriteLine("Name = " + resultCountry.Name + " Captial =" + resultCountry.Capital);
            }

           
do
            {
               
Console.WriteLine("Do you want to continue - YES or NO?");
                strUserChoice =
Console.ReadLine().ToUpper();
            }
           
while (strUserChoice != "NO" && strUserChoice != "YES");
        }
       
while (strUserChoice == "YES");
    }
}

public class Country
{
   
public string Name { get; set; }
    
public string Code { get; set; }
    
public string Capital { get; set; }
}

No comments:

Post a Comment