[go: up one dir, main page]

0% found this document useful (0 votes)
59 views23 pages

Unit II

The document discusses object oriented programming concepts in C# including structs, enums, classes, inheritance, abstract classes, polymorphism and operator overloading. It provides examples and explanations of each concept.

Uploaded by

Sujala Patnaik
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
59 views23 pages

Unit II

The document discusses object oriented programming concepts in C# including structs, enums, classes, inheritance, abstract classes, polymorphism and operator overloading. It provides examples and explanations of each concept.

Uploaded by

Sujala Patnaik
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 23

Unit II: File Handling and Threads-Structure, Enums, Classes, Inheritance, Abstract class,

Polymorphism, Operator Overloading, Interfaces, Namespaces, Pre-processor Directives,


Exception Handling, Garbage collection, Threads-Life cycle, creation and managing threads,
File Handling.
Learning Outcomes: Student will be able to
● Understand object oriented concepts with real time applications. (L2)
● Implement Threads and file handling for synchronous data processing. (L4)
● Understand error and exception handling strategies. (L2)

Struct or structure
A struct type is a value type that is typically used to encapsulate small groups of related
variables such as the coordinates of a rectangle and all. They are basically for light-weighted
objects. Unlike class, structs in C# are value type than a reference type. It is useful if you
have data that is not intended to be modified after the creation of the struct. Structs contain
methods, properties, indexers, and so on. It can not contain default constructors.
Example:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp15
{

internal class Program


{
struct Student
{
public int sno;
public string sname;
}
struct Emp
{
int empId;
public void setEmpId(int empId)
{
this.empId = empId;
}
public int getEmpId()
{ return this.empId; }
}
static void Main(string[] args)
{
Student s;
s.sno = 111;
s.sname = "SURESH";
Console.WriteLine(s.sname);
Console.WriteLine(s.sno);
Emp emp = new Emp();
emp.setEmpId(111);
Console.WriteLine(emp.getEmpId());
}
}
}
However, structs are always value types, while classes are always referenced types.
Structs are quite similar to classes, but there is are a few important differences between them.
Structs can not have a parameterless constructor and structs do not support inheritance.
Structs are value types so in order to create an instance of struct we have to pass to it values
for each of its properties. This can be done in three ways.
Relying on default values of the properties in the struct.
Passing values for each public property during instantiation.
Using a constructor method on the struct to give default values.
NOTE: To make an immutable struct whose values can only be set at instantiation, we
declare it with read only keyword.

Enum:
The enum is a keyword that is used to declare an enumeration. Enumeration is a type that
consists of a set of named constant called enumerators.

By default the first enumerator has the value of “0” and the value of each successive
enumerator is increased by one.

Like:

enum days {Mon, Tue, …}


It is not necessary to follow the general index number to be given to the enums. We can
provide different values to the enums too.
Enum Day { Monday, Tuesday = 4, Wednesday…..}
In the above example “Monday” will have index value as 0 whereas “Tuesday” will have
index value as 4 and then everything following this will have one value increased index
value, which means “Wednesday” will have value 5 for index eventually.
Note: Now, if the data member of the enum member has not been initialized, then its value is
set according to rules.
Rules:
if it is the first member, then its value is set to 0 otherwise
It set out the value which is obtained by adding 1 to the previous value of enum data member
We can change the type of Enum’s data member since it has a default data type. C Sharp has
a default data type of integer for enumerators. However, you can change the data type to
anything such as bool, long, double, etc.
Enums can be used inside many things,

• A class is a blueprint of an object that contains variables for storing data and functions
to
perform operations on the data.
• Or
• A class is a collection of member variables and member functions.
• A class will not occupy any memory space and hence it is only a logical
representation of data.
Class:
A class definition starts with the keyword class followed by the class name; and
the class body enclosed by a pair of curly braces. Following is the general form of a class
definition:
class class_name
{
Variable declaration;
Methods declaration;
}
 Class is keyword
 Class name is any C# valid identifier.
 Everything inside the square brackets is called body of the class .It is optional.
Inheritance:

• (Acquiring (taking) the properties of one class into another class is called inheritance.
• (Or) When a new class needs same members as an existing class, then instead of
creating those members again in new class, the new class can be created from existing
class, which is called as inheritance.
• Syntax:
class derived-class-name: base-class-name
{ Members of class }
Types of inheritance: Inheritance can be classified into 5 types
1. Single Inheritance
2. Hierarchical Inheritance
3. Multi-Level Inheritance
4. Hybrid Inheritance
5. Multiple Inheritance
class Parent
{
public void Earning()
{
Console.WriteLine("Parent.Earning");
}
}
class Child : Parent
{
public void Inherit()
{
Console.WriteLine("Child..Inherit");
}
}
internal class Program
{
static void Main(string[] args)
{
Parent parent = new Parent();
Child child = new Child();
child.Earning();
child.Inherit();
}
}
}

Output : Parent..Earning
Child..Inherit

ABSTRACT CLASS:
In c sharp Abstract class is defined using "abstract" keyword.
• When a class contains at least one abstract method, then the class must be
declared as abstract class.
• If an Abstract class contain any abstract methods, then those methods must be
implemented under the child class using override modifier.
Characteristics of abstract classes:
1. Abstract Class cannot be instantiated directly.
2. Abstract Class can have both abstract methods and non-abstract methods.
3. If any child class of abstract class wants to consume non abstract method of its
parent, first
they require to implement all the abstract methods of parent otherwise consuming non
abstract methods of parent will not be possible.
4. An abstract class can consume only by child classes that to after providing the
implementation for all the abstract methods of abstract class.
5. You cannot declare an abstract method outside an abstract class
6. When a class is declared sealed, it cannot be inherited, abstract classes cannot be
declared sealed.
Syntax: abstract class class1
{
public abstract void add(int x, int y);
}

Example:
Class Calculator : class1{
public override void add(int x, int y){}

POLYMORPHISM: Polymorphism means one name many forms (ability to take


more than one form).
In Polymorphism poly means ―multiple and morph means ―forms‖ so
polymorphism means many.
In polymorphism we will declare methods with same name and different parameters in
same class or methods with same name and same parameters in different classes.
Polymorphism has ability to provide different implementation of methods that are
implemented with same name. Types of polymorphism:
 Compile Time Polymorphism(or)Early Binding (or) Overloading (or) static
binding
 Run Time Polymorphism(or)Late Binding (or) Overriding (or) dynamic
binding
Static Polymorphism: The mechanism of linking a function with an object during
compile time is called early binding. It is also called static binding.
C# provides two techniques to implement static polymorphism.
They are:
1. Function (or) method overloading
2. Constructor overloading.
3. Operator overloading

Method Overloading:-
Method Overloading is the common way of implementing polymorphism. It is the
ability to redefine a function in more than one form. A user can implement function
overloading by defining two or more functions in a class sharing the same name. C#
can distinguish the methods with different method signatures. i.e. the methods can
have the same name but with different parameters list (i.e. the number of the
parameters, order of the parameters, and data types of the parameters) within the
same class.
 Overloaded methods are differentiated based on the number and type of
the parameters passed as arguments to the methods.
 You can not define more than one method with the same name, Order and
the type of the arguments. It would be compiler error.
 The compiler does not consider the return type while differentiating the
overloaded method. But you cannot declare two methods with the same
signature and different return type. It will throw a compile-time error. If
both methods have the same parameter types, but different return type,
then it is not possible.
Why do we need Method Overloading?
If we need to do the same kind of the operation in different ways i.e. for different
inputs. In the example described below, we are doing the addition operation for
different inputs. It is hard to find many different meaningful names for single action.
Different ways of doing overloading methods-
Method overloading can be done by changing:
1. The number of parameters in two methods.
2. The data types of the parameters of methods.
3. The Order of the parameters of methods.
Example:
using System;
class Tester {

// adding two integer values.


public int Add(int a, int b)
{
int sum = a + b;
return sum;
}

// adding three integer values.


public int Add(int a, int b, int c)
{
int sum = a + b + c;
return sum;
}

// Main Method
public static void Main(String[] args)
{

// Creating Object
Tester ob = new Tester();

int sum1 = ob.Add(1, 2);


Console.WriteLine("sum of the two "
+ "integer value : " + sum1);

int sum2 = ob.Add(1, 2, 3);


Console.WriteLine("sum of the three "
+ "integer value : " + sum2);
}
}

Output:
sum of the two integer value : 3
sum of the three integer value : 6

Constructor overloading:

It is quite similar to the Method Overloading. It is the ability to redefine a


Constructor in more than one form. A user can implement constructor
overloading by defining two or more constructors in a class sharing the same
name. C# can distinguish the constructors with different signatures. i.e. the
constructor must have the same name but with different parameters list.
We can overload constructors in different ways as follows:
 By using different type of arguments
 By using different number of arguments
 By using different order of arguments
By changing the Data types of the parameters
Example:
public ADD (int a, float b);
public ADD (string a, int b);
Here the name of the class is ADD. In first constructor there are two
parameters, first one is int and another one is float and in second
constructor, also there is two parameters, first one is string type and another
one is int type.
Here the constructors have the same name but the types of the parameters
are different, similar to the concept of method overloading.

Using System;
Namespace ns{
class ADD {

int x, y;
double f;
string s;

// 1st constructor
public ADD(int a, double b)
{
x = a;
f = b;
}

// 2nd constructor
public ADD(int a, string b)
{
y = a;
s = b;
}

// showing 1st constructor's result


public void show()
{
Console.WriteLine("1st constructor (int + float): {0} ",
(x + f));
}

// shows 2nd constructor's result


public void show1()
{
Console.WriteLine("2nd constructor (int + string): {0}",
(s + y));
}
}

class ConstructorOverloading {

// Main Method
static void Main()
{

// Creating instance and


// passing arguments
// It will call the first constructor
ADD g = new ADD(10, 20.2);

// calling the method


g.show();

// Creating instance and


// passing arguments
// It will call the second constructor
ADD q = new ADD(10, "Roll No. is ");
// calling the method
q.show1();
}
}
}

Output:
1st constructor (int + float): 30.2
2nd constructor (int + string): Roll No. is 10

Operator Overloading:-
The concept of overloading a function can also be applied to operators. Operator
overloading gives the ability to use the same operator to do various operations. It
provides additional capabilities to C# operators when they are applied to user-
defined data types. It enables to make user-defined implementations of various
operations where one or both of the operands are of a user-defined class. Only the
predefined set of C# operators can be overloaded.
Syntax:-
access specifier className operator Operator_symbol (parameters)
{
// Code
}
Note :

Operators Overloadability
+, -, *, /, %, &, |, <<, >> All C# binary operators can be overloaded.
+, -, !, ~, ++, --, true, false All C# unary operators can be overloaded.
==, !=, <, >, <= , >= All relational operators can be overloaded, but only as pairs.

public static return_type operator op (argument list)

Run Time Polymorphism(or)Late Binding (or) Overriding (or) dynamic binding

The function call bounded to the class at the time of compilation, if the function is going to be
executed from a different class (Parent Class) at run-time rather than the class bounded at
compilation-time, then it is called Run-Time Polymorphism. This happens in the case of Method
Overriding because, in the case of Overriding, we have multiple methods with the same signature
i.e. Parent Class and the Child class having the same method implementation. So, in this case, we
will be able to know at runtime from which class the method is going to be executed.
It is also called Dynamic Polymorphism or Late Binding as at Run-time we will be able to know
from which class the method is going to be executed.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp21
{
class Parent
{
public virtual void sleepWalk()
{
Console.WriteLine("Parent..Behavior..sleep walk");
}
}
class Child: Parent
{
public override void sleepWalk()
{
Console.WriteLine("Child..Behavior..sleep walk");
}
}
internal class Program
{
static void Main(string[] args)
{
Parent parent;
parent= new Parent();
parent.sleepWalk();
parent = new Child();
parent.sleepWalk();

}
}
}

Implement unary operator –


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp16
{
class Complex
{
private int x;
private int y;
public Complex()
{
}
public Complex(int i, int j)
{
x = i;
y = j;
}
public void ShowXY()
{
Console.WriteLine("{0} {1}", x, y);
}
public static Complex operator -(Complex c)
{
Complex temp = new Complex();
temp.x = -c.x;
temp.y = -c.y;
return temp;
}
}
internal class Program
{

public static void Main()


{
Complex c1 = new Complex(10, 20);
c1.ShowXY(); // displays 10 & 20
Complex c2 = new Complex();
c2.ShowXY(); // displays 0 & 0
c2 = -c1;
c2.ShowXY(); // diapls -10 & -20
}
}

Overloading Binary Operators


An overloaded binary operator must take two arguments; at least one of them must be of the
type class or struct, in which the operation is defined. But overloaded binary operators can
return any value except the type void. The general form of a overloaded binary operator is as
follows.

1. public static return_type operator op (Type1 t1, Type2 t2)


2. {
3. //Statements
4. }
A concrete example is given below.
1. // Binary operator overloading
2. // Author: rajeshvs@msn.com
3. using System;
4. class Complex
5. {
6. private int x;
7. private int y;
8. public Complex()
9. }
10. public Complex(int i, int j)
11. {
12. x = i;
13. y = j;
14. }
15. public void ShowXY()
16. {
17. Console.WriteLine("{0} {1}", x, y);
18. }
19. public static Complex operator +(Complex c1, Complex c2)
20. {
21. Complex temp = new Complex();
22. temp.x = c1.x + c2.x;
23. temp.y = c1.y + c2.y;
24. return temp;
25. }
26. }
27. class MyClient
28. {
29. public static void Main()
30. {
31. Complex c1 = new Complex(10, 20);
32. c1.ShowXY(); // displays 10 & 20
33. Complex c2 = new Complex(20, 30);
34. c2.ShowXY(); // displays 20 & 30
35. Complex c3 = new Complex();
36. c3 = c1 + c2;
37. c3.ShowXY(); // dislplays 30 & 50
38. }
39. }
The binary operators such as = =, ! =, <, >, < =, > = can be overloaded only as pairs.
Remember that when a binary arithmetic operator is overloaded, corresponding assignment
operators also get overloaded automatically. For example if we overload + operator, it
implicitly overloads the + = operator also.

Garbage collector (GC) : It manages the allocation and release of memory. The
garbage collector serves as an automatic memory manager.

You do not need to know how to allocate and release memory or manage the lifetime
of the objects that use that memory.

An allocation is made any time you declare an object with a “new” keyword or a value
type is boxed. Allocations are typically very fast.

When there isn’t enough memory to allocate an object, the GC must collect and
dispose of garbage memory to make memory available for new allocations.

This process is known as garbage collection.

Garbage Collection in C# has the following advantages −


You don’t need to free memory manually while developing your application.
It also allocates objects on the managed heap efficiently.

When objects are no longer used then it will reclaim those objects by clearing their
memory, and keeps the memory available for future allocations.
Managed objects automatically get clean content to start with, so their constructors do
not have to initialize every data field.
interfaces:
interface <interface_name >
{
// declare Events
// declare indexers
// declare methods
// declare properties
}
Syntax for Implementing Interface:
class class_name : interface_name
To declare an interface, use interface keyword. It is used to provide total abstraction.

1. We cannot create an object of an interface, we can only create a reference or Interface


Variable.
2. An interface will have only abstract methods (method declaration).
3. Interfaces supports Inheritance, Polymorphism (Overloading, Overriding (using the
"new" keyword to hide the interface methods above)).
4. We cannot create variables in an interface.
5. Only Properties, Indexers, Methods and Events are allowed in an interface.
6. A class can inherit multiple interfaces, which is also shown in the snapshot above.
7. We cannot create any Access modifiers with Interface Members (like private, public,
protected, internal, protected internal, virtual, override, static, abstract etc.)
8. The new keyword is allowed in an interface.
9. All methods of an interface must be defined in every derived class.
10. An interface is good for small or medium level projects

A namespace
is designed for providing a way to keep one set of names separate from another. The class
names declared in one namespace does not conflict with the same class names declared in
another.

Defining a Namespace
A namespace definition begins with the keyword namespace followed by the namespace
name as follows −
namespace namespace_name {
// code declarations
}
To call the namespace-enabled version of either function or variable, prepend the namespace
name as follows −
namespace_name.item_name;
The following program demonstrates use of namespaces −
using System;

namespace first_space {
class namespace_cl {
public void func() {
Console.WriteLine("Inside first_space");
}
}
}
namespace second_space {
class namespace_cl {
public void func() {
Console.WriteLine("Inside second_space");
}
}
}
class TestClass {
static void Main(string[] args) {
first_space.namespace_cl fc = new first_space.namespace_cl();
second_space.namespace_cl sc = new second_space.namespace_cl();
fc.func();
sc.func();
Console.ReadKey();
}
}
When the above code is compiled and executed, it produces the following result −
Inside first_space
Inside second_space

The using Keyword


The using keyword states that the program is using the names in the given namespace. For
example, we are using the System namespace in our programs. The class Console is defined
there. We just write −
Console.WriteLine ("Hello there");
We could have written the fully qualified name as −
System.Console.WriteLine("Hello there");

preprocessor directives:-
The preprocessor directives give instruction to the compiler to preprocess the information
before actual compilation starts.
All preprocessor directives begin with #, and only white-space characters may appear before
a preprocessor directive on a line. Preprocessor directives are not statements, so they do not
end with a semicolon (;).

#define PI
using System;

namespace PreprocessorDAppl {
class Program {
static void Main(string[] args) {
#if (PI)
Console.WriteLine("PI is defined");
#else
Console.WriteLine("PI is not defined");
#endif
Console.ReadKey();
}
}
}
When the above code is compiled and executed, it produces the following result −
PI is defined

Using #region and #endregion #region defines a set of instructions as a block of


code and this block is compiled all at once by the compiler. #endregion marks the
end of the block. The program below depicts the same.
using System;

namespace preprocessor3
{
class Program
{
static void Main( string[] args )
{
char ch = 'y';

// Using #region to define a block of code


#region
if (ch == 'y' || ch == 'Y')
Console.WriteLine( "Value of ch is 'y'" );
else
Console.WriteLine( "Value of ch is unknown" );

Console.WriteLine( "Value of ch is unknown" );

// Ends the region


#endregion
}
}
}

Output:
Value of ch is 'y'
Using #pragma warning and #pragma checksum In the code below we use
the #pragma warning disable to disable all warnings. Inside main, we generate a
user defined warning to check if it has been disabled or not. And #pragma checksum
is used to aid the debugging of the file.
// C# program to Disables all warnings

#pragma warning disable

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Preprocessor4 {

class Program {
static void Main(string[] args)
{
// Creating a warning
#warning "This is disabled"

// Checksum is used for debugging


// the file in consideration
#pragma checksum "Program.cs"
}
}
}

The error list for the above code:

Exception Handling:

An exception is a problem that arises during the execution of a program.

A C# exception is a response to an exceptional circumstance that arises while a program is


running, such as an attempt to divide by zero.

C# exception handling is built upon four keywords: try, catch, finally, and throw.

try − A try block identifies a block of code for which particular exceptions is activated. It is
followed by one or more catch blocks.
catch − A program catches an exception with an exception handler at the place in a program
where you want to handle the problem. The catch keyword indicates the catching of an
exception.

finally − The finally block is used to execute a given set of statements, whether an exception
is thrown or not thrown. For example, if you open a file, it must be closed whether an
exception is raised or not.

throw − A program throws an exception when a problem shows up. This is done using a
throw keyword.

Example:

int[] arr = { 1, 2, 3, 4, 5 };

// Display values of array elements


for (int i = 0; i < arr.Length; i++) {
Console.WriteLine(arr[i]);
}
// Try to access invalid index of array
Console.WriteLine(arr[7]);
// An exception is thrown upon executing
// the above line
Output:
12345

Unhandled Exception: System.IndexOutOfRangeException: Index was outside the bounds of


the array.

at Preprocessor.Program.Main(String[] args) in D:\C#-


Programs\Preprocessor\Program.cs:line 47

Press any key to continue .

Threads:- A thread is defined as the execution path of a program. Each thread defines a unique
flow of control. If your application involves complicated and time consuming operations, then it is
often helpful to set different execution paths or threads, with each thread performing a particular job.

Thread creation & Managing :

class program
{
public void WorkThreadFunction()
{
for (int i = 0; i < 5; i++)
{
Console.WriteLine("Simple Thread");
}
}
}
class threprog
{
public static void Main()
{
program pg = new program();
Thread thread = new Thread(new ThreadStart(pg.WorkThreadFunction));
thread.Start();
Console.Read();
}
}
Explanation
This C# Program, we are creating a new ThreadStart delegate. The delegate points to a method
that will be executed by the new thread. Pass this delegate as a parameter when creating a new
Thread instance. Finally, call the Thread.Start method to run the method.

Stream
When you open a file for reading or writing, it becomes stream. Stream is a sequence of bytes
traveling from a source to a destination over a communication path.

The two basic streams are input and output streams. Input stream is used to read and output
stream is used to write.

The System.IO namespace includes various classes for file handling.

The parent class of file processing is stream. Stream is an abstract class, which is used as the
parent of the classes that actually implement the necessary operations.

The primary support of a file as an object is provided by a .NET Framework class called File.
This static class is equipped with various types of (static) methods to create, save, open, copy,
move, delete, or check the existence of a file.

Diagram to represent file-handling class hierarchy


Note
FileIno, DirectoryInfo and DriveInfo classes have instance methods. File, Directory, Path
classes have static methods.

The following table describes some commonly used classes in the System.IO namespace.

Class Name Description

FileStream It is used to read from and write to any location within a file

BinaryReader It is used to read primitive data types from a binary stream

BinaryWriter It is used to write primitive data types in binary format


StreamReader It is used to read characters from a byte Stream
StreamWriter It is used to write characters to a stream.

StringReader It is used to read from a string buffer


StringWriter It is used to write into a string buffer
DirectoryInfo It is used to perform operations on directories
FileInfo It is used to perform operations on files

Reading and writing in the text file


StreamWriter Class

The StreamWriter class in inherited from the abstract class TextWriter. The TextWriter class
represents a writer, which can write a series of characters.

The following table describes some of the methods used by StreamWriter class.

Methods Description
Close Closes the current StreamWriter object and the underlying stream

Clears all buffers for the current writer and causes any buffered data to be written
Flush
to the underlying stream

Write Writes to the stream

WriteLine Writes data specified by the overloaded parameters, followed by end of line

Program to write user input to a file using StreamWriter Class


1. using System;
2. using System.Text;
3. using System.IO;
4. namespace FileWriting_SW
5. {
6. class Program
7. {
8. class FileWrite
9. {
10. public void WriteData()
11. {
12. FileStream fs = new FileStream("c:\\test.txt", FileMode.Append, File
Access.Write);
13. StreamWriter sw = new StreamWriter(fs);
14. Console.WriteLine("Enter the text which you want to write to the fil
e");
15. string str = Console.ReadLine();
16. sw.WriteLine(str);
17. sw.Flush();
18. sw.Close();
19. fs.Close();
20. }
21. }
22. static void Main(string[] args)
23. {
24. FileWrite wr = new FileWrite();
25. wr.WriteData();
26. }
27. }
28. }

StreamReader Class
The StreamReader class is inherited from the abstract class TextReader. The TextReader
class represents a reader, which can read series of characters.

The following table describes some methods of the StreamReader class.

Methods Description
Closes the object of StreamReader class and the underlying stream, and release any
Close
system resources associated with the reader
Peek Returns the next available character but doesn't consume it

Read Reads the next character or the next set of characters from the stream
ReadLine Reads a line of characters from the current stream and returns data as a string
Seek Allows the read/write position to be moved to any position with the file

You might also like