Module 4_Easy_understanding
Module 4_Easy_understanding
Example:
using System; class GetSetDemo1 { static void
namespace Chapter4_Examples{ class Main(){
Student{ Student st1 = new Student();
string name, branch, usn; st1.Studusn ="1RX12MCA01";
Console.WriteLine("USN: "+st1.Studusn);
public string Studusn{
Console.ReadKey();
set{ usn = value; } }
get{return usn;} }
} }
}
In the above example, we see the usage of Encapsulation by using properties. The property is
composed using a get block(accessor) and set block (Mutator). The get block returns the value of
some property field. The set block sets the value of some property field with the contents of “value”
token.
Example:
class Student{
string name, branch, usn;
public string Studusn{
set{usn = value;}
}
}
In this example, the property “Studusn” is having only set (mutator) but not get (accessor). So Studusn
can called as a “write-only property”.
Creating Read-Only Fields: Properties can be made read-only. This is accomplished by having only get
accessor in property implementation.
Example 2.4: In the below example, the property “Studusn” is having only get (accessor) but not set
(mutator). So can call Studusn as a “read-only property”.
Accessor methods, also known as getter methods, are methods that allow you to retrieve the value of
an object.
Mutator methods, also known as setter methods, are methods that allow you to modify the value of
an object.
Example:
using System;
class ReadOnly{ static void Main()
namespace Class_Demos{
{
class Student{ string studusn;
Student st1 = new Student();
public Student(){
Console.WriteLine("USN: "
studusn="1RX12MCA01";
+ st1.Studusn);
}
Console.ReadKey();
public string Studusn{ get{
}
return studusn;
}
}
}
}
}
“static” property: C# also supports “static” properties. The static members are accessed at the class
level, not from an instance (object) of that class. Static properties are manipulated in the same manner
as static methods, as seen here:
Example: Assume that the Student type defines a point of static data to represent the name of the
institution studying these students. You may define a static property as follows:
using System; class StaticProperty{ static void
namespace Class_Demos{ Main(){
class Student{ Student.Institution = "RNSIT";
string name, branch, usn; Console.WriteLine("InstitutionName:"
static string instName; +Student.Institution);
public static string Institution Console.ReadKey();
{ }
set { instName = value; } }
get { return instName; } }
}
}
Indexers:
Indexers allow you to use a class as an array and enable an object to access the members of a class
using an index notation.
Syntax:
<access-modifier> <Return_Type> this [argument_list] {
Where,
get { // return the value specified by index }
set { // set the value specified by index }
}
The access modifier can be private, public, protected or internal
Return type can be any valid C# data type, such as int, float, double, string….
this keyword shows that the object is of the current class.
argument list specifies the parameters of the indexer.
Must have at least one parameter; otherwise the compiler gives and error.
Allows you to have multiple parameters and each parameter can be a different type, separated
by commas.
Parameter types can be int, enum, or string.
All indexers in the same class should have different signatures.
The get and set portions accessors is the same as that of the indexer to which they belong.
Example:
using System;
namespace Class_Demos{
class Student {
string[] usn = new string[3];
public string this[int index]
{ set { usn[index] = value; }
get {
if (index < 0 || index >= usn.Length) return null;
else
return (usn[index]);
}
}}
class IndexerDemo {
public static void Main(){
Student slist = new Student();
slist[0] = "1RN12MCA01";
slist[1] = "1RN12MCA02";
slist[2] = "1RN12MCA03";
for (int i = 0; i < 3; i++)
Console.WriteLine(slist[i]);
Console.ReadKey();
}
}}
Indexer Overloading:
An indexer is used to treat an object as an array. It is used to provide index to an object to obtain
values from the object.
Implementing an indexer requires you to use brackets ([ ]) with an object to get and set a value of the
object.
Indexer are declared as properties, with the difference that in case of indexers, you do not need to
provide name to them. You need to use the “this” keyword to define an indexer.
Example:
using System;
namespace Class_Demos{
class MyClass{
string[] mydata;
int arrsize;
public MyClass(int size){
arrsize = size;
mydata = new string[size];
for (int i = 0; i < size; i++)
mydata[i] = "DataValue";
}
public string this[int position]{
set{ mydata[position] = value; }
get{return (mydata[position]); }
}
public string this[string data]{
set{
for (int i=0; i<arrsize; i++){
if (mydata[i] == data)
mydata[i] = value;
}
}
get{
int count = 0;
for (int i = 0; i < arrsize; i++){
if (mydata[i] == data)
count = count + 1;
}
return count.ToString();
}
}
}
class IndOverload{
static void Main(){
int size = 10;
MyClass obj=new MyClass(size);
obj[1] = "Hello";
obj[3] = "Good Morning";
obj[7] = "Welcome";
obj["DataValue"] = "Have a nice day";
for (int i = 0; i < size; i++)
Console.WriteLine("obj[{0}]: {1}", i, obj[i]);
Introduction Generics:
C# Generics
Generic means the general form, not specific. In C#, generic means not specific to a particular data
type.
C# allows you to define generic classes, interfaces, abstract classes, fields, methods, static methods,
properties, events, delegates, and operators using the type parameter and without the specific data
type. A type parameter is a placeholder for a particular type specified when creating an instance of the
generic type.
A generic type is declared by specifying a type parameter in an angle bracket after a type name, e.g.
TypeName<T> where T is a type parameter.
Generic Class
Generic classes are defined using a type parameter in an anglebrackets after the class name. The
following defines a generic class.
Advantages of Generics
Generics increase the reusability of the code. You don't need to write code to handle different data
types.
Generics are type-safe. You get compile-time errors if you try to use a different data type than the one
specified in the definition.
Generic has a performance advantage because it removes the possibilities of boxing and unboxing.
C# Generic Constraints
C# allows you to use constraints to restrict client code to specify certain types while instantiating
generic types. It will give a compile-time error if you try to instantiate a generic type using a type that
is not allowed by the specified constraints.
You can specify one or more constraints on the generic type using the where clause after the generic
type name.
Syntax:
GenericTypeName<T> where T : contraint1, constraint2
The following example demonstrates a generic class with a constraint to reference types when
instantiating the generic class.
Example: Declare Generic Constraints
class DataStore<T> where T : class
{
public T Data { get; set; }
}
Above, we applied the class constraint, which means only a reference type can be passed as an
argument while creating the DataStore class object. So, you can pass reference types such as class,
interface, delegate, or array type. Passing value types will give a compile-time error, so we cannot pass
primitive data types or struct types.
where T : struct
The following example demonstrates the struct constraint that restricts type argument to be non-
nullable value type only.
where T : baseclass
The following example demonstrates the base class constraint that restricts type argument to be a
derived class of the specified class, abstract class, or an interface.
There are two types of collections available in C#: non-generic collections and generic collections.
In most cases, it is recommended to use the generic collections because they perform faster than non-
generic collections and also minimize exceptions by giving compile-time errors.
C# - ArrayList
In C#, the ArrayList is a non-generic collection of objects whose size increases dynamically. It is the
same as Array except that its size increases dynamically.
An ArrayList can be used to add unknown data where you don't know the types and the size of the
data.
Create an ArrayList
The ArrayList class included in the System.Collections namespace. Create an object of the ArrayList
using the new keyword.
Example: Create an ArrayList
using System.Collections;
Accessing an ArrayList
The ArrayList class implements the IList interface. So, elements can be accessed using indexer, in the
same way as an array. Index starts from zero and increases by one for each subsequent element.
An explicit casting to the appropriate types is required, or use the var variable.
//update elements
arlist[0] = "Steve";
arlist[1] = 100;
//arlist[5] = 500; //Error: Index out of range
Iterate an ArrayList
The ArrayList implements the ICollection interface that supports iteration of the collection types. So,
use the foreach and the for loop to iterate an ArrayList. The Count property of an ArrayList returns the
total number of elements in an ArrayList.
Console.WriteLine(arList.Contains(300)); // true
Console.WriteLine(arList.Contains("Bill")); // true
Console.WriteLine(arList.Contains(10)); // false
Console.WriteLine(arList.Contains("Steve")); // false
ArrayList Class
The following diagram illustrates the ArrayList class.
C# - List<T>
The List<T> is a collection of strongly typed objects that can be accessed by index and having methods
for sorting, searching, and modifying list. It is the generic version of the ArrayList that comes under
System.Collections.Generic namespace.
List<T> Characteristics
List<T> equivalent of the ArrayList, which implements IList<T>.
It comes under System.Collections.Generic namespace.
List<T> can contain elements of the specified type. It provides compile-time type checking and doesn't
perform boxing-unboxing because it is generic.
Elements can be added using the Add(), AddRange() methods or collection-initializer syntax.
Elements can be accessed by passing an index e.g. myList[0]. Indexes start from zero.
List<T> performs faster and less error-prone than the ArrayList.
Creating a List
The List<T> is a generic collection, so you need to specify a type parameter for the type of data it can
store. The following example shows how to create list and add elements.
In the above example, List<int> primeNumbers = new List<int>(); creates a list of int type. In the same
way, cities and bigCities are string type list. You can then add elements in a list using the Add() method
or the collection-initializer syntax.
You can also add elements of the custom classes using the collection-initializer syntax. The following
adds objects of the Student class in the List<Student>.
// adding a List
favouriteCities.AddRange(popularCities);
Accessing a List
A list can be accessed by an index, a for/foreach loop, and using LINQ queries. Indexes of a list start
from zero. Pass an index in the square brackets to access individual list items, same as array. Use a
foreach or for loop to iterate a List<T> collection.
Example: Contains()
var numbers = new List<int>(){ 10, 20, 30, 40 };
numbers.Contains(10); // returns true
numbers.Contains(11); // returns false
numbers.Contains(20); // returns true
List<T> Class Hierarchy
The following diagram illustrates the List<T> hierarchy.
C# - SortedList<TKey, TValue>
The SortedList<TKey, TValue>, and SortedList are collection classes that can store key-value pairs that
are sorted by the keys based on the associated IComparer implementation. For example, if the keys are
of primitive types, then sorted in ascending order of keys.
SortedList Characteristics
SortedList<TKey, TValue> is an array of key-value pairs sorted by keys.
Sorts elements as soon as they are added. Sorts primitive type keys in ascending order and object keys
based on IComparer<T>.
Comes under System.Collection.Generic namespace.
A key must be unique and cannot be null.
A value can be null or duplicate.
A value can be accessed by passing associated key in the indexer mySortedList[key]
Contains elements of type KeyValuePair<TKey, TValue>
It uses less memory than SortedDictionary<TKey,TValue>.
It is faster in the retrieval of data once sorted, whereas SortedDictionary<TKey, TValue> is faster in
insertion and removing key-value pairs.
Creating a SortedList
The following example demonstrates how to create a generic SortedList<TKey, TValue>, and add key-
value pairs in it.
Accessing SortedList
Specify a key in the indexer sortedList[key], to get or set a value in the SortedList.
C# - Dictionary<TKey, TValue>
The Dictionary<TKey, TValue> is a generic collection that stores key-value pairs in no particular order.
Dictionary Characteristics
Dictionary<TKey, TValue> stores key-value pairs.
Comes under System.Collections.Generic namespace.
Implements IDictionary<TKey, TValue> interface.
Keys must be unique and cannot be null.
Values can be null or duplicate.
Values can be accessed by passing associated key in the indexer e.g. myDictionary[key]
Elements are stored as KeyValuePair<TKey, TValue> objects.
Creating a Dictionary
You can create the Dictionary<TKey, TValue> object by passing the type of keys and values it can store.
The following example shows how to create a dictionary and add key-value pairs.
Update Dictionary
Update the value of a key by specifying a key in the indexer. It will throw the KeyNotFoundException if
a key does not exist in the dictionary, therefore use the ContainsKey() method before accessing
unknown keys.
if(cities.ContainsKey("France")){
cities["France"] = "Paris";
}
cities.Remove("UK"); // removes UK
//cities.Remove("France"); //throws run-time exception: KeyNotFoundException
if(cities.ContainsKey("France")){ // check key before removing it
cities.Remove("France");
}
C# - Hashtable
The Hashtable is a non-generic collection that stores key-value pairs, similar to generic
Dictionary<TKey, TValue> collection. It optimizes lookups by computing the hash code of each key and
stores it in a different bucket internally and then matches the hash code of the specified key at the
time of accessing values.
Hashtable Characteristics
Hashtable stores key-value pairs.
Comes under System.Collections namespace.
Implements IDictionary interface.
Keys must be unique and cannot be null.
Values can be null or duplicate.
Values can be accessed by passing associated key in the indexer e.g. myHashtable[key]
Elements are stored as DictionaryEntry objects.
Creating a Hashtable
The following example demonstrates creating a Hashtable and adding elements.
Example: Create and Add Elements
Hashtable numberNames = new Hashtable();
numberNames.Add(1,"One"); //adding a key/value using the Add() method
numberNames.Add(2,"Two");
numberNames.Add(3,"Three");
foreach(DictionaryEntry de in numberNames)
Console.WriteLine("Key: {0}, Value: {1}", de.Key, de.Value);
foreach(DictionaryEntry de in cities)
Console.WriteLine("Key: {0}, Value: {1}", de.Key, de.Value);
Update Hashtable
You can retrieve the value of an existing key from the Hashtable by passing a key in indexer. The
Hashtable is a non-generic collection, so you must type cast values while retrieving it.
Console.WriteLine(citiesOfUK);
Console.WriteLine(citiesOfUSA);
if(!cities.ContainsKey("France")){
cities["France"] = "Paris";
}
cities.Remove("UK"); // removes UK
//cities.Remove("France"); //throws run-time exception: KeyNotFoundException
Stack is useful to store temporary data in LIFO style, and you might want to delete an element after
retrieving its value.
Stack<T> Characteristics
Stack<T> is Last In First Out collection.
It comes under System.Collection.Generic namespace.
Stack<T> can contain elements of the specified type. It provides compile-time type checking and
doesn't perform boxing-unboxing because it is generic.
Elements can be added using the Push() method. Cannot use collection-initializer syntax.
Elements can be retrieved using the Pop() and the Peek() methods. It does not support an indexer.
Creating a Stack
You can create an object of the Stack<T> by specifying a type parameter for the type of elements it can
store. The following example creates and adds elements in the Stack<T> using the Push() method.
Stack allows null (for reference types) and duplicate values.
Pop()
The Pop() method returns the last element and removes it from a stack. If a stack is empty, then it will
throw the InvalidOperationException. So, always check for the number of elements in a stack before
calling the Pop() method.
Example: Access Stack using Pop()
Stack<int> myStack = new Stack<int>();
myStack.Push(1);
myStack.Push(2);
myStack.Push(3);
myStack.Push(4);
Peek()
The Peek() method returns the lastly added value from the stack but does not remove it. Calling the
Peek() method on an empty stack will throw the InvalidOperationException. So, always check for
elements in the stack before retrieving elements using the Peek() method.
Contains()
The Contains() method checks whether the specified element exists in a Stack collection or not. It
returns true if it exists, otherwise false.
Example: Contains()
Stack<int> myStack = new Stack<int>();
myStack.Push(1);
myStack.Push(2);
myStack.Push(3);
myStack.Push(4);
C# - Queue<T>
Queue is a special type of collection that stores the elements in FIFO style (First In First Out), exactly
opposite of the Stack<T> collection. It contains the elements in the order they were added. C# includes
generic Queue<T> and non-generic Queue collection. It is recommended to use the generic Queue<T>
collection.
Queue<T> Characteristics
Queue<T> is FIFO (First In First Out) collection.
It comes under System.Collection.Generic namespace.
Queue<T> can contain elements of the specified type. It provides compile-time type checking and
doesn't perform boxing-unboxing because it is generic.
Elements can be added using the Enqueue() method. Cannot use collection-initializer syntax.
Elements can be retrieved using the Dequeue() and the Peek() methods. It does not support an
indexer.
Creating a Queue
You can create an object of the Queue<T> by specifying a type parameter for the type of elements it
can store. The following example creates and adds elements in the Queue<T> using the Enqueue()
method. A Queue collection allows null (for reference types) and duplicate values.
foreach(var id in callerIds)
Console.Write(id); //prints 1234
Retrieve Elements from a Queue
The Dequeue() and the Peek() method is used to retrieve the first element in a queue collection. The
Dequeue() removes and returns the first element from a queue because the queue stores elements in
FIFO order. Calling the Dequeue() method on an empty queue will throw the InvalidOperation
exception. So, always check that the total count of a queue is greater than zero before calling it.
Contains()
The Contains() method checks whether an item exists in a queue or not. It returns true if the specified
item exists, otherwise returns false.
Example: Contains()
Queue<int> callerIds = new Queue<int>();
callerIds.Enqueue(1);
callerIds.Enqueue(2);
callerIds.Enqueue(3);
callerIds.Enqueue(4);
callerIds.Contains(2); //true
callerIds.Contains(10); //false