Introduction
This is the sixth day of "Learn a Tiny Bit of C# in 7 days" In this series we will extend our topics try to cover basics of those topics.
What did we learn last time?
In the last article we covered the following topics:
- Reflection
- Early Binding/ Late Binding
- Stringbuilder/ System.String
- Var Keyword
- Extension Method
Before moving further let us focus on the previous article of the series:
Agenda for Day 6
- Partial classes
- Indexers
- Optional Parameter in C#
- Collection
Partial classes- Partial class allows us to split our class into two or more files. All these parts are then combined into a single class at compile time. The partial keyword is also applicable to Interface and Struct as well.
Let’s try to implement them practically.
Create a New Console Application.
Figure 1: Creating a new Console Application
Add a new class Library to the solution,
Figure 2: Creating a new Class Library
Figure 3: Name your new Class Library to Customer.
Create the methods and properties of the Class,
- namespace Customer
- {
- public class Customer
-
- {
-
- public Customer(int customerId, string customerName, string customerAddress)
- {
- this.Id = customerId;
- this.Name = customerName;
- this.Address = customerAddress;
- }
-
- private int _Id;
- public int Id
- {
- get
- {
- return _Id;
- }
- set
- {
- _Id = value;
- }
- }
- private string _Name;
- public string Name
- {
- get
- {
- return _Name;
- }
- set {
- _Name = value;
- }
- }
- private string _Address;
- public string Address
- {
- get {
- return _Address;
- }
- set {
- _Address = value;
- }
- }
-
-
-
-
- public string PrintCustomerDetails()
- {
- return "The Details are Customer Id= " + Id + "Customer Name= " + Name + " Customer Address= " + Address;
- }
- }
- }
When we want to use the class functionality we first add the reference of the class in console application and then create object of the class as shown below-
Figure 4: Referencing the customer class library.
- using System;
- using CustomerClass;
- namespace PartialClass
- {
- class Program
- {
- static void Main(string[] args)
- {
-
- Customer customer = new Customer(1, "Saillesh", "Dehradun");
- string customerDetails = customer.PrintCustomerDetails();
- Console.WriteLine(customerDetails.ToString());
- Console.ReadLine();
- }
- }
- }
Now let’s create a partial class. A partial class can be created with the help of a partial keyword. Partial keyword helps us to split our class in more than one file as shown below.
Add a new class named CustomerPartialClass,
Declare some properties in this class and declare this class as partial.
Syntax - Partial Class ClassName
- namespace Customer
- {
- partial class CustomerPartialClass
- {
-
- private int _Id;
- public int Id
- {
- get
- {
- return _Id;
- }
- set
- {
- _Id = value;
- }
- }
- private string _Name;
- public string Name
- {
- get
- {
- return _Name;
- }
- set
- {
- _Name = value;
- }
- }
- private string _Address;
- public string Address
- {
- get {
- return _Address;
- }
- set {
- _Address = value;
- }
- }
- }
- }
Now again create one more class,
Figure 5: Creating a new CustomerPartialClass2
Common definition will appear as shown below-
- namespace Customer
- {
- class CustomerPartialClass2
- {
- }
- }
Change the name to the same as above declared partial class and create a parameterized constructor for the same as we have created in Customer Class.
- namespace Customer
- {
- partial class CustomerPartialClass
- {
- public CustomerPartialClass(int id, string customerName, string customerAddress)
- {
- this._Id = id;
- this._Name = customerName;
- this._Address = customerAddress;
- }
- }
- }
As soon as we try to access private properties in our second CustomerPartialClass we will see the intelisense window as shown below with all the properties.
Figure 6: Demonstrating that private properties are accessible in the other Partial Class.
Let’s create one more class and create the PrintCustomerDetails Method in it.
- namespace Customer
- {
- partial class CustomerPartialClass
- {
-
-
-
-
- public string PrintCustomerDetails()
- {
- return "The Details are Customer Id= " + Id + "Customer Name= " + Name + " Customer Address= " + Address;
- }
- }
- }
Now try to create instance of the CustomerPartialClass in our main program
Figure 7: Demonstrating creating instance of Partial Class passing value to the constructor.
Parameterized constructor.
- using System;
- using CustomerClass;
- namespace PartialClass
- {
- class Program
- {
- static void Main(string[] args)
- {
-
- CustomerPartialClass customerPartialClass = new CustomerPartialClass(1, "Nishant", "Lonavla");
- string customerDetails = customerPartialClass.PrintCustomerDetails();
- Console.WriteLine(customerDetails);
- Console.ReadLine();
- }
- }
- }
Figure 8: Output Demonstrating calling PrintCustomerDetails from the partial class.
Partial Classes real time example in asp.net web form in asp.net web forms visual studio uses partial classes to separate automatically generated code when we add a web form two files are created
1 .aspx.cs
2 .aspx.designer.cs
Figure 9: Demonstrating partial class concept in ASP.NET Web Forms.
Figure 10: Demonstrating partial class Default.
.aspx.cs file contains the developer code that developers writes. While if we see .aspx.designer.cs it contains the code generated by the system i.e. if drag and drop any control the system generates the code eg-
If I drag and drop the button control the system will generate the class for that control as shown below,
Figure 11: Demonstrating Code generated
Figure 12: Demonstrating Code generated
While in .aspx.cs we can write our code on button click etc. as shown below-
Figure 13: Our Events code.
Same we can see in windows form application as well.
Advantages of using Partial Classes
When we are working in a project and we want to finish it as early as possible then we can create partial classes and share the functionality of class among the developers
When working with automatically generated code eg asp.net webforms, windows form application, entity framework data model etc.
Partial Methods
Partial methods are created using a partial keyword. Now for this demo we will use our Partial class project.
Syntax - partial void Details();
Demo
- using System;
- namespace CustomerClass
- {
- public partial class CustomerPartialClass
- {
- public CustomerPartialClass(int id, string customerName, string customerAddress)
- {
- this._Id = id;
- this._Name = customerName;
- this._Address = customerAddress;
- }
-
- partial void Details();
- public void Method()
- {
- Console.WriteLine("Calling partial method");
- Details();
- }
- }
- }
If we try to compile the project we will get no errors and if we run our program we will get a below output.
Figure 14: Demonstrating the partial class and partial method.
What we learned
- If we just declare a partial method without the definition it will get compiled without any error.
- If we try to call the partial method with no definition compiler will remove the signature and call to that method( Implementation of partial method is optional).
Now let’s implement the definition of the partial method in another partial class CustomerPartialClass as shown below,
- using System;
- namespace CustomerClass
- {
- public partial class CustomerPartialClass
- {
-
- private int _Id;
- public int Id
- {
- get
- {
- return _Id;
- }
- set
- {
- _Id = value;
- }
- }
- private string _Name;
- public string Name
- {
- get
- {
- return _Name;
- }
- set
- {
- _Name = value;
- }
- }
- private string _Address;
- public string Address
- {
- get
- {
- return _Address;
- }
- set
- {
- _Address = value;
- }
- }
- partial void Details()
- {
- Console.WriteLine("Partial Method Details definition");
- Console.WriteLine("The Details are Customer Id= " + Id + "Customer Name= " + Name + " Customer Address= " + Address);
- }
- }
- }
Now if we try to call the Partial Method we will get the appropriate output as shown below-
Figure 15: Demonstrating the partial class and partial method.
Note*
- Partial method are by default private.
- You cannot apply access modifiers on partial methods.
- Signature of the partial class declaration must match with partial class implementation.
- Partial method should be declared inside a Partial class or structure i.e. we cannot define partial class inside a non-partial class.
- We cannot have multiple implementation.
- Indexers
- Indexers help us to access the collection present within a class. In .net we use Indexers to retrieve data from session state and application state. Indexer allow our class to be like an array i.e. as we access the value of an array Array[2] in the same way we can access the value in our class.
Indexer are kind of properties but they accept parameters.
Eg - Let take an example of a List of Integer type
- List<int> listInt = new List<int>();
- for(int i=1;i<50;i++)
- {
- listInt.Add(i);
- }
Here I am adding numbers from 1 to 49 to the list. Once we are done with adding the list of integers we will try to access the last element of the list the same way we do in array.
Figure 16: Demonstrating the input type of Indexer.
We can see as soon as I press [. The intellisense show me the input type for this index, it is asking me the index which I want to retrieve. So I will enter 48, as shown below and check the output on the screen.
Figure 17: Output after calling Indexer.
If we go to List definition we will find the index as shown below-
We can see that this indexer has get and set accessors i.e. indexer can have get and set accessors same as properties. Let’s try to implement the same in demo.
We will have a one to many relationship i.e. one customer that can have multiple addresses.
I will be using entity framework in order to retrieve data from database using code first approach.
So we first create our Database Tables.
- We will create a Table named TblCustomer with following columns as shown in figure.
Figure 18: Table design of TblCustomer.
Second table named TblAddress with following mentioned Columns.
Figure 19: Table design of TblAddress.
Records present in table tblCustomer
Figure 20: Records in table TblCustomer.
Figure 21: Records in table tblAddress.
Now let’s create our classes,
- public class Customer
- {
- public int Id
- {
- get;
- set;
- }
- public String Name
- {
- get;
- set;
- }
- [ForeignKey("AddressId")]
- public virtual List < Address > Addresses
- {
- get;
- set;
- }
- }
- public class Address
- {
- public int AddressId
- {
- get;
- set;
- }
- public int pincode
- {
- get;
- set;
- }
- public string building
- {
- get;
- set;
- }
- public string area
- {
- get;
- set;
- }
- }
Now we will create our DAL which will communicate with DB server,
- public class DAL: DbContext
- {
-
-
- public DbSet < Customer > customers
- {
- get;
- set;
- }
- public DbSet < Address > address
- {
- get;
- set;
- }
- protected override void OnModelCreating(DbModelBuilder modelBuilder)
- {
-
- modelBuilder.Entity < Customer > ().ToTable("TblCustomer");
- modelBuilder.Entity < Address > ().ToTable("TblAddress");
- }
- }
Now in app.config add the connection string,
- <add name="DAL" connectionString="Data Source=.;Initial Catalog=EnitySample;Integrated Security=True" providerName="System.Data.SqlClient"/>
Now we will create a simple indexer which will take pincode as input and will return the area based on the pincode passed.
- public string this[int pincode]
- {
- get
- {
-
- DAL _context = new DAL();
-
- return _context.address.Single(add => add.pincode == pincode).area;
- }
- }
Here as we can see how simple and easy it’s to create index. We just have to write the input parameter. Return type and get or set methods whichever is required.
So let’s try to run our program and retrieve an area with the help of Indexer.
- namespace Indexer
- {
- class Program
- {
- static void Main(string[] args)
- {
- Customer customer = new Customer();
-
- Console.WriteLine(customer[248001]);
- Console.ReadLine();
- }
- }
- }
Let’s run our application,
Figure 22: Demonstrating implementation of Indexer using EF.
Breakpoints hits on the Indexer and parameter has been passed to the indexer. Now DAL object will be created and it will be responsible for retrieving single area based on the passed pincode by the user.
Figure 23: Output to the screen.
As we can see the retrieved area from the db. Let try set accessor and in set accessor we will pass the pincode and based upon that pincode passed we will set the area passed by the user as shown below-
- set
- {
- DAL _context = new DAL();
-
- _context.address.Single(add => add.pincode == pincode).area = value;
-
- }
Now we will call the set accessor when we want to set the area based on the pin code passed by the user.
Figure 24: Saving the new value to the database using Indexer.
Once the area is found,
Figure 25: Saving the new value to the database using Indexer.
Once the save changes happen we will retrieve the updated area once we call the get indexer as shown below
Figure 26: Retrieving the saved value from the database.
Retrieving get indexer.
Figure 27: Output
Now here we can see the updated value retrieved from the get indexer.
Few point to be note down
a. Use This keyword to create an indexer.
b. Indexer can have get and set properties.
Overloading Indexer,
I hope all of you will be aware of Overloading feature in csharp the concept of overloading is also implemented in indexer which means we can have more than one indexer with same name but with different numbers of parameter and type.
Let overload and Indexer now in our overloaded indexer we will create an indexer which will return the name of the customer based on the Customer Id passed as shown below-
Figure 28: Overloading Constructor.
Showing two overloads one takes pincode while other takes Empid and Name.
Figure 29: Overloading Constructor.
Let’s run our Application.
Breakpoint hit and we have passed empId and Name,
Figure 30: Executing Indexer with two parameter.
Figure 31: Output.
We can see the desired output on the screen.
- Optional Parameter in C#
- Use Parameter arrays
Use OptionalAttribute
Optional parameter is beneficial when we want to create a single method that is able to perform operations based on the no of inputs passed by the User.
Parameter Arrays (Params)
Params keyword allows our method to receive variable numbers of input parameter. The word params is to be used with arrays and it allows us to pass as many numbers of parameters with declaring an array. Params declaration is required in the method declaration or we can say signature. With params, the arguments passed to a method are changed by the compiler to elements in a temporary array.
Syntax - public void MethodName(Params object[]objectArray)
We can call the method
MethodName(123,’Learn Tiny bit of C# in 7 days’,”day 6”);
Let’s try to unleash it practically.
- using System;
- namespace ParmeterLessMethod
- {
- class Program
- {
-
- static void Main(string[] args)
- {
-
- Sum(10, 20, 20, 30);
- }
-
-
-
-
-
-
- public static void Sum(int number1, int number2, params int[] restofNumbers)
- {
- int Result = number1 + number2;
- if (restofNumbers != null) {
- foreach(int num in restofNumbers)
- {
- Result += num;
- }
- }
- Console.WriteLine("The sum result is " + Result);
- Console.ReadLine();
- }
- }
- }
Figure 32: Demonstrating Optional Parameter in C#.
Params keyword should always be last parameters.
Figure 33: Demonstrating Optional Parameter should always be last.
Params can only take single dimension array.
Figure 34: Demonstrating Optional Parameter param only takes single dimensional array.
Optional Attribute Class
Optional Attribute Class is present in System.Runtime.InteropServices. OptionalAttribute is used to indicate that a parameter is optional.
- using System;
- using System.Runtime.InteropServices;
- namespace OptionalAttributeSample
- {
- class Program
- {
- static void Main(string[] args)
- {
- Multiplication(10, 20);
- }
-
-
-
-
-
-
- public static void Multiplication(int num1, int num2, [Optional] int[] restOfNumbers) {
- int result = num1 * num2;
- if (restOfNumbers != null)
- {
- foreach(int num in restOfNumbers)
- {
- result *= num;
- }
- }
- Console.WriteLine("Multiplication is =" + result);
- Console.ReadLine();
- }
- }
- }
Output
Figure 35: Demonstrating Optional attribute class.
Here we need to pass the int array rather than parameters as in Param keyword as shown below-
If we try to just pass the parameter we get the compile time error as shown below-
Figure 36: Demonstrating Optional attributeonly accepts array.
Passing an array
- using System;
- using System.Runtime.InteropServices;
- namespace OptionalAttributeSample
- {
- class Program
- {
- static void Main(string[] args)
- {
- Multiplication(10, 20, new int[]
- {
- 1,
- 2,
- 3
- });
- }
-
-
-
-
-
-
- public static void Multiplication(int num1, int num2, [Optional] int[] restOfNumbers)
- {
- int result = num1 * num2;
- if (restOfNumbers != null)
- {
- foreach(int num in restOfNumbers)
- {
- result *= num;
- }
- }
- Console.WriteLine("Multiplication is =" + result);
- Console.ReadLine();
- }
- }
- }
Output
Figure 37: Multiplication operation using Optional attribute class..
- Collection
Collections are the group of records/ related objects that can be termed as a one logical unit. If the number of elements are dynamic i.e. we are not aware of the no of records than we should use collection class instead of Array.
Eg.
Customer Collection
1.Customer Id
2.Customer Name
3.Customer Address
4.Customer MobileNo
Let’s try to unleash them one by one.
- Index Based
Index Based as the name specify the Index Based collection helps you to access the row of the collection by the help of the generated index. Index based collection are of two types-
a. Array
b. List
Eg-
-
-
-
- string[] names = new string[7];
- names[0] = "Learn";
- names[1] = "Tiny";
- names[2] = "Bit";
- names[3] = "of";
- names[4] = "C#";
- names[5] = "6th";
- names[6] = "day";
-
- Console.WriteLine("The value of index 0 is"+names[0].ToString() );
- Console.ReadLine();
Using List
-
-
-
- List<string> lString = new List<string>();
- lString.Add("Learn");
- lString.Add("Tiny");
- lString.Add("Bit");
- lString.Add("of");
- lString.Add("C#");
- lString.Add("6th");
- lString.Add("day");
-
-
- Console.WriteLine("The value of list for index 0 is " +lString[0].ToString());
- Console.ReadLine();
List<T> Type collection can be compared with each other. But in c# we have wide variety of collections.
Most of the collection can be found in the system.collection and system.collection.generics. The system.collection.generics contains the generic collection.
Lists - A list collection can be used to create a collection of any type i.e. we can create a list of string, double or even complex types (classes). The object stored in the list can be accessed via index.
Let’s take a class called cricketer which has following properties
- namespace Sample
- {
- public class Cricketer
- {
- public int Id { get; set; }
- public string Name { get; set; }
- public string Country { get; set; }
- }
- }
Figure 38: Demonstrating List as a Strongly Typed.
When we declare a List it asks for the Type i.e. string, int, complex type class. Here we are going to create a list of type Cricketer i.e. complex type.
Syntax-
List<Cricketer> lCricketers = new List<Cricketer>();
var lCricketers =new List<Cricketer>();
Figure 39: Creating list with n limit.
There are three overloaded constructors to create a list.
1 As stated above in Syntax where it doesn’t take any values.
2 Passing a length/capacity of the List as shown below.
Figure 40: Demonstrating List with a capacity.
- List<Cricketer> lCricketers = new List<Cricketer>(2);
Which means the lCricketers can take only 2 records of Cricketer.
Figure 41: Demonstrating creating instance of a list.
Adding elements to a List:
You can add elements to the using Add method as shown below,
- static void Main(string[] args)
- {
-
- Cricketer cricketer = new Cricketer()
- {
- Id = 1,
- Country = "India",
- Name = "Virat Kohli"
- };
-
- Cricketer cricketer2 = new Cricketer()
- {
- Id = 1,
- Country = "India",
- Name = "Virat Kohli"
- };
- List < Cricketer > lCricketers = new List < Cricketer > ();
- lCricketers.Add(cricketer);
- lCricketers.Add(cricketer2);
- }
Retrieving an item from a list-
- Cricketer player = lCricketers[0];
- Console.WriteLine("Player Details are as follows ID={0},Name={1},Country={2}",player.Id,player.Name,player.Country);
- Console.ReadLine();
Figure 42: Demonstrating Retrieving an item from a list with index 0.
//Iterating threw all the list
Using Foreach Loop -
- Console.WriteLine("Players Details");
- foreach (Cricketer player in lCricketers)
- {
-
- Console.WriteLine("Player Details are as follows ID={0},Name={1},Country={2}", player.Id, player.Name, player.Country);
-
- }
- Console.ReadLine();
Output
Figure 43: Looping threw the list.
Using for loop-
- Console.WriteLine("Players Details");
- for(int i=0;i<lCricketers.Count;i++)
- {
- Console.WriteLine("Player Details are as follows ID={0},Name={1},Country={2}", lCricketers[i].Id, lCricketers[i].Name, lCricketers[i].Country);
- }
-
- Console.ReadLine();
Output
Figure 44: Looping threw the list using for loop.
In a list we cannot add object of different type which means we can add only object of type Cricketer as shown below:
Figure 45: Demonstrating that we can add only object of type Cricketer.
What if we try to add an object which implements the Cricketer Class? Let’s try practically
Let’s create a class Umpire and inherit from Cricketer class,
- public class Umpire:Cricketer
- {
-
-
- }
Now let’s try to add Umpire object to the Cricketer list
- Umpire umpire = new Umpire()
- {
-
- Id=5,
- Country="New Zealand",
- Name="Billi Bowden",
- };
-
- lCricketers.Add(umpire);
Output
Figure 46: Demonstrating that we can add object of derive class.
Inserting the type to the defined index in the list
We can insert the type in the list at the defined position by us by using Insert function of list as shown below-
- Cricketer cricketer3 = new Cricketer()
- {
- Id = 3,
- Country = "India",
- Name = "Sir Jadeja"
-
- };
-
-
- lCricketers.Insert(0, cricketer3);
Figure 47: Demonstrating inserting the object to the desired index.
We can clearly see the index of the added Cricketer object to the desired position specified by us. I.e. at 0 index. When we insert the object at specific position all the objects are pushed forward of their index.
Functions in the List
Contains - Contains function check if item exists in the list and if it does it returns true else false.
Create a Simple Student class
- class Student
- {
- public int Id
- {
- get;
- set;
- }
- public string Name
- {
- get;
- set;
- }
- public string MobileNo
- {
- get;
- set;
- }
- }
- class Program {
- static void Main(string[] args)
- {
- List < Student > students = new List < Student > ();
- Student stud1 = new Student
- {
- Id = 1,
- Name = "Saillesh",
- MobileNo = "9012134556"
- };
- students.Add(stud1);
- Student stud2 = new Student
- {
- Id = 2,
- Name = "Raul",
- MobileNo = "8012134256"
- };
- students.Add(stud2);
- Student stud3 = new Student
- {
- Id = 3,
- Name = "Rohit",
- MobileNo = "7012134556"
- };
- students.Add(stud3);
- Student stud4 = new Student
- {
- Id = 4,
- Name = "Rakesh",
- MobileNo = "9012134616"
- };
- students.Add(stud4);
-
- if (students.Contains(stud4))
- {
- Console.WriteLine("Rakesh Exists in the list");
- } else
- {
- Console.WriteLine("Rakesh doesn't Exists in the list");
- }
- }
- }
Figure 48: Demonstrating Contains method.
If you want to check whether student exists in a list using a lambda expression you need to use Exists Function as shown below:
Exists - function checks if item exists in the list or not based upon a condition and returns respective true or false for the same.
We will use same class as shown in Contains demo.
Check the student whose id is 4,
-
-
- if (students.Exists(stud => stud.Id == 4))
- {
- Console.WriteLine("Rakesh Exists in the list");
-
- }
- else
- {
- Console.WriteLine("Rakesh doesn't Exists in the list");
- }
Output
Figure 49: Demonstrating Exists method.
Find Function - This function matches for the condition and return the first item from the list.
Add one more student object to the list.
- Student stud5 = new Student
- {
- Id = 5,
- Name = "Rakesh",
- MobileNo = "9997373111"
- };
- students.Add(stud5);
-
- Student student = students.Find(stud => stud.Name == "Rakesh");
- Console.WriteLine("The details of Student retrieved from list are");
- Console.WriteLine("Student id {0} \nStudent Name {1} \nStudent MobileNo {2}", student.Id, student.Name, student.MobileNo);
Output
Figure 50: Printing the details of student after Find function.
FindLast - FindLast function search for the element that matches the condition defined in the lambda expression and returns the last occurrence in the list.
-
- Student student = students.FindLast(stu => stu.Name == "Rakesh");
- Console.WriteLine("The details of Student retrieved from list are");
- Console.WriteLine("Student id {0} \nStudent Name {1} \nStudent MobileNo {2}",student.Id,student.Name,student.MobileNo);
Figure 51: Printing the details of student after FindLast function.
FindAll - FindAll function searches for the elements that match the condition defined in the lambda expression and returns all the occurrences in the list.
-
- var studentLst = students.FindAll(stu => stu.Name == "Rakesh");
- foreach(Student stu in studentLst)
- {
- Console.WriteLine("The details of Student retrieved from list are");
- Console.WriteLine("Student id {0} \nStudent Name {1} \nStudent MobileNo {2}", stu.Id, stu.Name, stu.MobileNo);
- }
Output
Figure 52: Printing the details of student after FindAll function.