WHAT IS .NET ??
C#
1.
What is .NET?
·
It is a platform neutral framework.
·
It is a layer between the operating system and the programming
language.
·
It supports many programming languages, including VB.NET, C#
etc.
·
.NET provides a common set of class libraries, which can be
accessed from any .NET based programming language. There will not be separate
set of classes and libraries for each language. If you know any one .NET
language, you can write code in any .NET language!!
·
In future versions of Windows, .NET will be freely distributed
as part of operating system and users will never have to install .NET
separately.
2.
What is Not?
·
.NET is not an operating system.
·
.NET is not a programming language.
3. “.NET is a framework”
Confused with this
definition?
·
We cannot define .NET as a ‘single thing’.
·
It is a new, easy, and extensive programming platform.
·
It is not a programming language, but it supports several
programming languages.
·
By default .NET comes with few programming languages including
C# (C Sharp), VB.NET, J# and managed C++.
·
.NET is a common platform for all the supported languages. It
gives a common class library, which can be called from any of the supported
languages.
·
So, developers need not learn many libraries when they switch to
a different language. Only the syntax is different for each language.
·
When you write code in any language and compile, it will be
converted to an ‘Intermediate Language’ (Microsoft Intermediate Language –
MSIL).
·
So, your compiled executable contains the IL and not really
executable machine language.
·
When the .NET application runs, the .NET framework in the target
computer take care of the execution. (To run a .NET application, the target
computer should have .NET framework installed.)
·
The .NET framework converts the calls to .NET class libraries to
the corresponding APIs of the Operating system.
·
Whether you write code in C# or VB.NET, you are calling methods
in the same .NET class libraries.
·
The same .NET framework executes the C# and VB.NET applications.
·
So, there won’t be any performance difference based on the
language you write code.
3.1 Is it platform
independent?
Many people ask this question “Java is platform independent,
what about .NET?”.
The answer is “Yes” and “No”!
·
The code you write is platform independent, because whatever you
write is getting compiled into MSIL.
·
There is no native code, which depends on your operating system
or CPU. But when you execute the MSIL, the .NET framework in the target system
will convert the MSIL into native platform code.
·
So, if you run your .NET exe in a Windows machine, the .NET
framework for Windows will convert it into Windows native code and execute.
·
If you run your .NET application in Unix or Linux, the .NET
framework for Unix/Linux will convert your code into Unix/Linux native code and
execute.
·
So, your code is purely platform independent and runs anywhere!
·
But wait, we said it wrong… there is no .NET framework for UNIX
or Linux available now.
·
Microsoft has written the .NET framework only for Windows.
·
If you or some one else write a .NET framework for other
platforms in future, your code will run there too. So, let us wait until
someone write .NET framework for Linux before you run your .NET code in Linux.
3.2 Major Issues before .NET
·
Registration of COM components.
·
Unloading COM components
·
Versioning Problem (DLL Hell)
The .NET Platform
The .Net platform is a set of technologies. Microsoft .NET
platform simplify software development (Windows or WEB) by building
applications of XML Web services.
The .NET platform consists of the following core technologies
which are refer as components of .NET: -
·
The .NET Framework
·
The .NET Enterprise Servers
·
Building block services
·
Visual Studio .NET
A programming model (.NET framework) enables developers to build
Extensible Markup Language (XML) Web Services and applications.
Developer Tools
|
.NET Framework
|
Application
|
Libraries
|
CLR
|
.NET
Enterprise
Servers
|
.NET
Building
Block Services
|
C#, Visual Basic .NET
|
Visual Studio .NET
|
Windows OS (Win 32)
|
The .NET Platform Architecture
3.3 Components of .NET Framework
The .Net Framework consists of:
·
Common Language Runtime
·
Class Libraries
·
Support for Multiple Programming Language
.NET Compliant Languages
(VC++, VB.NET, ASP.NET, C# and other third party languages)
|
Common Language Runtime
(Memory Management, Common Type System, Garbage Collector)
|
Windows Forms
Web Forms
Web Services
|
.NET Framework Base Class Library
(ADO.NET, XML, Threading, Diagnostics, IO, Security, etc.)
|
Components of .NET Framework
4. Application Development and
Execution
.NET is a multilingual platform then any .NET based language can
be chosen to develop applications.
4.1 Choosing a Compiler
According to the language we can choose its run time aware
compiler for .NET platform. Because it is a multilingual execution environment,
the runtime supports a wide variety of data types and language features.
4.2 Compiling to MSIL
Source Code
|
Compiler
|
Class Libraries (IL & Metadata)
|
EXE/DLL (IL & Metadata)
|
Class loader
|
Security checks
|
Managed Native Code
|
Execution
|
JIT Compiler
|
Runtime Engine
|
Call to an un- compiled method
|
Trusted pre-JIT code only
|
Source code to native code and code execution
When compiling source code, the compiler translates it into an
intermediate code represented in MSIL. Before code can be run, MSIL code must
be converted to CPU-specific code, usually by a just-in-time (JIT) compiler.
When a compiler produces MSIL, it also produces metadata. Metadata includes
following information: -
·
Description of the types in your code, including the definition
of each type.
·
The signatures of each type’s members,
·
The members that your code references.
·
Other data that the runtime uses at execution time.
The MSIL and metadata are contained in a portable executable
(PE) file that is based on and extends the published Microsoft PE and Common
object file format (COFF) used historically for executable content. The file
format, which accommodates MSIL or native code as well as metadata, enables the
operating system to recognize common language runtime images.
4.3 Compiling MSIL to Native Code
Before you can run Microsoft intermediate language (MSIL), it
must be compiled against the common language runtime to native code for the
target machine architecture. The .NET Framework provides two ways to perform
this conversion:
•A .NET Framework just-in-time (JIT) compiler.
•The .NET Framework Ngen.exe (Native Image Generator).
4.4 Compilation by the JIT Compiler
JIT compilation converts MSIL to native code on demand at
application run time, when the contents of an assembly are loaded and executed.
Because the common language runtime supplies a JIT compiler for each supported
CPU architecture, developers can build a set of MSIL assemblies that can be
JIT-compiled and run on different computers with different machine
architectures. However, if your
managed code calls platform-specific native APIs or a
platform-specific class library, it will run only on that operating system.
JIT compilation takes into account the possibility that some
code might never be called during execution. Instead of using time and memory
to convert all the MSIL in a PE file to native code, it converts the MSIL as
needed during execution and stores the resulting native code in memory so that
it is accessible for subsequent calls in the context of that process. The
loader creates and attaches a stub to each method in a type when the type is
loaded and initialized. When a method is called for the first time, the stub
passes control to the JIT compiler, which converts the MSIL for that method
into native code and modifies the stub to point directly to the generated
native code. Therefore, subsequent calls to the JIT-compiled method go directly
to the native code.
Install-Time Code Generation Using NGen.exe
Because the JIT compiler converts an assembly’s MSIL to native
code when individual methods defined in that assembly are called, it affects
performance adversely at run time. In most cases, that diminished performance
is acceptable. More importantly, the code generated by the JIT compiler is
bound to the process that triggered the compilation. It cannot be shared across
multiple processes. To allow the generated code to be shared across multiple
invocations of an application or across multiple processes that share a set of
assemblies, the common language runtime supports an ahead-of-time compilation
mode. This ahead-of-time compilation mode uses the Ngen.exe (Native Image
Generator) to convert MSIL assemblies to native code much like the JIT compiler
does. However, the operation of Ngen.exe differs from that of the JIT compiler
in three ways:
•It performs the conversion from MSIL to native code before
running the application instead of while the application is running.
•It compiles an entire assembly at a time, instead of one method
at a time.
•It persists the generated code in the Native Image Cache as a
file on disk.
4.5 Summary of Managed Code Execution
Process
The process of compiling and executing managed code is given
below: -
1. When
you compile a program developed in a language that targets the CLR, instead of
compiling the source code into machine-level code, the compiler translates it
into Microsoft Intermediate Language (MSIL) or Intermediate language (IL). This
ensures language interoperability.
2. In
addition to translating the code into IL, the compiler also produces metadata
about the program during the process of compilation. Metadata contains the
description of the program, such as classes and interfaces, the dependencies
and the versions of the components used in the program.
3. The IL
and the metadata are linked in assembly.
4. The
compiler creates the .EXE or .DLL file.
5. When
you execute the .EXE or .DLL file, the code (converted to IL) and all the other
relevant information from the base class library is sent to the class loader.
The class loader loads the code in the memory.
6. Before
the code can be executed, the .NET framework needs to convert the IL into
native or CPU-specific code. The Just-in-time (JIT) compiler translates the
code from IL to managed native code. The CLR supplies a JIT compiler for each
supported CPU architecture. During the process of compilation, the JIT compiler
compiles only the code that is required during execution instead of compiling
the complete IL code. When an uncompiled method is invoked during execution,
the JIT compiler converts the IL for that method into native code. This process
saves the time and memory required to convert the complete IL into native code.
7. During
JIT compilation, the code is also checked for type safety. Type safety ensures
that objects are always accessed in a compatible way. Therefore, if you try to
pass an 8-byte value to a method that accepts a 4-byte value as a parameter,
the CLR will detect and trap such an attempt. Type safety also ensures that
objects are safely isolated from each other and are therefore safe from any
malicious corruption.
8. After
translating the IL into native code, the converted code is sent to the .NET
runtime manager.
9. The
.NET runtime manager executes the code. While executing the code, a security
check is performed to ensure that the code has the appropriate permissions for
accessing the available resources.
Common Language Infrastructure (CLI)
The Common Language Infrastructure (CLI) is an open
specification developed by Microsoft that describes the executable code and
runtime environment that allows multiple high-level languages to be used on
different computer platforms without being rewritten for specific
architectures.
The common language Infrastructure (CLI) is a theoretical model
of a development platform that provides a device and language independent way
to express data and behavior of applications.
The CLI specification describes the following four aspects: -
·
The Common Type System (CTS)
The language interoperability and .NET Class Framework are not
possible without all the language sharing the same data type. CTS is an
important part of the runtime support for cross-language integration. The CTS
performs the following functions:
·
Establishes a framework that enables cross-language integration,
type safety and high performance code execution.
·
Provides an object-oriented model that supports the complete
implementation of many programming languages.
The CTS supports two general categories of types: -
1. Value Types
Value types directly contain their data, and instances of value
types are either allocated on the stack or allocated inline in a structure.
Value types can be built-in, user-defined or enumerations types.
2. Reference Types
Reference types store a reference to the value’s memory address,
and are allocated on the heap. Reference types can be self-describing types,
pointers type or interface types. The type of a reference type can be
determined from values of self-describing types. Self-describing types are
further split into arrays and class types are user-defined classes, boxed value
types, and delegates.
A set of data types and operations that are shared by all
CTS-compliant programming languages.
·
Metadata
Information about program structure is language-agnostic, so
that it can be referenced between languages and tools, making it easy to work
with code written in a language you are not using.
·
Common Language Specification (CLS)
A set of base rules to which any language targeting the CLI
should conform in order to interoperate with other CLS-compliant languages. The
CLS rules define a subset of the Common Type System.
·
Virtual Execution System (VES)
The VES loads and executes CLI-compatible programs, using the
metadata to combine separately generated pieces of code at runtime.
The Common Language Runtime
The CLR is one of the most essential components of the .NET
framework. The CLR or the runtime provides functionality such as exception
handling, security, debugging, and versioning support to any language that
targets it. The CLR can execute programs written any language. You can use the
compilers to write the code that runs in the managed execution environment
provided by the CLR. The code that is developed with a language compiler that
targets the CLR is managed code.
On the other hand, the code that is developed without considering the
conventions and requirements of the common language run time is called unmanaged code.
CLR activates objects, performs security checks, lays them out
in memory, executes them and garbage collects these objects as well.
The CLR is a runtime engine that loads required classes,
performs just in time compilations, and enforces security checks and a bunch of
other runtime functions.
The CLR executables are either exe or DLL files that consist
mostly of metadata and code. These executables must adhere to a file format
called the Portable Executable (PE) file format.
Features Provided by CLR
Some of the features provided by the CLR are as follows: -
·
Automatic Memory Management: The CLR provides the garbage
collection feature for managing the lifetime of an object. This process
relieves a programmer of the task of manual memory management by deallocating the
blocks of memory associated with objects that are no longer being used. The
objects whose lifetime is managed by the garbage collection process are called
managed data.
·
Standard Type System: The CLR implements a formal specification
calledCommon Type System (CTS). The CTS is an important part of the
support provided by the CLR for cross-language integration because it provides
a type system that is common across all programming languages. It also defines
the rules that ensure that objects written in different languages can interact
with each other.
·
Language Interoperability: Language interoperability is the
ability of an application to interact with another application written in a
different programming language. Language interoperability helps maximize code
reuse. For example, you can write a class in Visual Basic and inherit it in a
code written in Visual C++ or c#.
·
Platform Independence: When you compile a program developed in
language that targets the CLR, the compiler translates the code into an
intermediate language. This language is CPU-independent. This means that the
code can be executed from any platform that supports the .NET CLR.
·
Security Management The traditional operating system security
model provides permissions to access resources, such as memory and data, based
on user accounts. In .NET platform security is achieved through the Code Access
Security (CAS) model. The CAS model specifies what the code can access instead
of specifying who can access resources.
·
Type Safety: This feature ensures that objects are always
accessed in compatible ways. Therefore the CLR will prohibit a code from
assigning a 10-byte value to an object that occupies 8 bytes.
Advantages of the .NET Framework
·
Consistent programming model
·
Multi-platform applications
·
Multi-Language integration
·
Automatic Resource Management
·
Ease of deployment
OOPS & C#
The skeleton of object – oriented programming is of course the
concepts of class. The C# on OOPS explains classes and their importance in implementation
of object oriented principles.
Any language can be called object oriented if it
has data and method that use data encapsulated in items named objects. An
object oriented programming method has many advantages; some of them are
flexibility and code reusability.
Key Concepts of Object Orientation
·
Abstraction
·
Encapsulation
·
Inheritance
·
Polymorphism
Abstraction is
the ability to generalize an object as a data type that has a specific set of
characteristics and is able to perform a set of actions.
Object-oriented languages provide abstraction via classes.
Classes define the properties and methods of an object type.
Examples:
You can create an abstraction of a dog with
characteristics, such as color, height, and weight, and actions such as run and
bite. The characteristics are called properties, and the actions are called
methods.
A Recordset object is an abstract representation of a set
of data.
Classes are blueprints for Object.
Objects are instance of classes.
Object References
When we work with an object we are using a reference to that
object. On the other hand, when we are working with simple data types such as
Integer, we are working with the actual value rather than a reference.
When we create a new object using the New keyword, we store a
reference to that object in a variable. For instance:
Draw MyDraw = new Draw;
This code creates a new instance of Draw. We gain access to this
new object via the MyDraw variable. This variable holds a reference to the
object.
Now we have a second variable, which also has a reference to
that same object. We can use either variable interchangeably, since they both
reference the exact same object. The thing we need to remember is that the
variable we have is not the object itself but, rather, is just a reference or
pointer to the object itself.
Early binding means
that our code directly interacts with the object, by directly calling its
methods. Since the compiler knows the object’s data type ahead of time, it can
directly compile code to invoke the methods on the object. Early binding also
allows the IDE to use IntelliSense to aid our development efforts; it allows
the compiler to ensure that we are referencing methods that do exist and that
we are providing the proper parameter values.
Late binding means
that our code interacts with an object dynamically at run-time. This provides a
great deal of flexibility since our code literally doesn’t care what type of
object it is interacting with as long as the object supports the methods we
want to call. Because the type of the object isn’t known by the IDE or
compiler, neither IntelliSense nor compile-time syntax checking is possible but
we get unprecedented flexibility in exchange.
If we enable strict type checking by using Option Strict On at
the top of our code modules, then the IDE and compiler will enforce early
binding behavior. By default, Option Strict is turned off and so we have easy
access to the use of late binding within our code.
Access Modifiers Access
Modifiers are keywords used to specify the declared accessibility of a member
of a type.
Public is visible to
everyone. A public member can be accessed using an instance of a class, by a
class’s internal code, and by any descendants of a class.
Private is hidden and
usable only by the class itself. No code using a class instance can access a
private member directly and neither can a descendant class.
Protected members
are similar to private ones in that they are accessible only by the containing
class. However, protected members also may be used by a descendant class. So
members that are likely to be needed by a descendant class should be marked
protected.
Internal/Friend is
public to the entire application but private to any outside applications.
Internal is useful when you want to allow a class to be used by other
applications but reserve special functionality for the application that
contains the class. Internal is used by C# and Friend by VB .NET.
Protected Internal may be
accessed only by a descendant class that’s contained in the same application as
its base class. You use protected internal in situations where you want to deny
access to parts of a class functionality to any descendant classes found in
other applications.
Composition of an OBJECT
We use an interface to get access to an object’s data and
behavior. The object’s data and behaviors are contained within the object, so a
client application can treat the object like a black box accessible only
through its interface. This is a key object-oriented concept called
Encapsulation. The idea is that any programs that make use of this object won’t
have direct access to the behaviors or data-but rather those programs must make
use of our object’s interface.
There are three main parts of Object:
1. Interface
2. Implementation or Behavior
3. Member or Instance variables
Interface
The interface is defined as a set of methods (Sub and Function
routines), properties (Property routines), events, and fields (variables or
attributes) that are declared Public in scope.
Implementation or Behavior
The code inside of a method is called the implementation.
Sometimes it is also called behavior since it is this code that actually makes
the object do useful work.
Client applications can use our object even if we change the
implementation-as long as we don’t change the interface. As long as our method
name and its parameter list and return data type remain unchanged, we can
change the implementation all we want.
So Method Signature depends on:
·
Method name
·
Data types of parameters
·
Either Parameter is passed ByVal or ByRef.
·
Return type of method
It is important to keep in mind that encapsulation is a
syntactic tool-it allows our code to continue to run without change. However,
it is not semantic-meaning that, just because our code continues to run,
doesn’t mean it continues to do what we actually wanted it to do.
Member or Instance Variables
The third key part of an object is its data, or state. Every
instance of a class is absolutely identical in terms of its interface and its
implementation-the only thing that can vary at all is the data contained within
that particular object.
Member variables are those declared so that they are available
to all code within our class. Typically member variables are Private in
scope-available only to the code in our class itself. They are also sometimes
referred to as instance variables or as attributes. The .NET Framework also
refers to them as fields.
We shouldn’t confuse instance variables with properties. A
Property is a type of method that is geared around retrieving and setting
values, while an instance variable is a variable within the class that may hold
the value exposed by a Property.
Interface looks like a class, but has no implementation.
The only thing it contains is definitions of events, indexers,
methods and/or properties. The reason interfaces only provide definitions is
because they are inherited by classes and structs, which must provide an
implementation for each interface member defined.
Defining an Interface: MyInterface.cs
interface IMyInterface
{
void MethodToImplement();
}
Above listing shows defines an interface named IMyInterface.
All the methods of Interface are public by default and no access
modifiers (like private, public) are allowed with any method of Interface.
Using an Interface: InterfaceImplementer.cs
class InterfaceImplementer : IMyInterface
{
public void MethodToImplement()
{
Console.WriteLine(“MethodToImplement() called.”);
}
}
The InterfaceImplementer class in above listing implements the
IMyInterface interface. Indicating that a class inherits an interface is the
same as inheriting a class. In this case, the following syntax is used:
class InterfaceImplementer : IMyInterface
Note that this class inherits the IMyInterface interface; it
must implement its all members. While implementing interface methods all those
needs to be declared public only. It does this by implementing the
MethodToImplement() method. Notice that this method implementation has the
exact same signature, parameters and method name, as defined in the
IMyInterface interface. Any difference will cause a compiler error.
Inheritance is
the idea that one class, called a subclass, can be based on another class,
called a base class. Inheritance provides a mechanism for creating hierarchies
of objects.
Inheritance is an important object-oriented concept. It allows
you to build a hierarchy of related classes, and to reuse functionality defined
in existing classes.
Inheritance is the ability to apply another class’s interface
and code to your own class.
Normal base classes may be instantiated themselves, or
inherited. Derived classes can inherit base class members marked with protected
or greater access. The derived class is specialized to provide more
functionality, in addition to what its base class provides. Inheriting base
class members in derived class is not mandatory.
C# supports two types of Inheritance mechanisms: -
1) Implementation Inheritance
2) Interface Inheritance
What is Implementation Inheritance?
- When a class (type) is derived from another class(type) such
that it inherits all the members of the base type it is Implementation
Inheritance
What is Interface Inheritance?
- When a type (class or a struct) inherits only the signatures
of the functions from another type it is Interface Inheritance
In general, Classes can be derived from another class, hence
support Implementation inheritance At the same time Classes can also be derived
from one or more interfaces Hence they support Interface inheritance Structs
can derive from one more interface, hence support Interface Inheritance Structs
cannot be derived from another class they are always derived from
SystemValueType
Types of Inheritance
1. Single
Inheritance
2. Multilevel
Inheritance
3. Multiple
Inheritance (Implementation is
possible through Interface)
4. Hierarchical
Inheritance
Multilevel Inheritance
|
Class B
|
Class B
|
Single Inheritance
|
Class A
|
Class D
|
Class C
|
Class A
|
Hierarchical Inheritance
|
Class A
|
Class B
|
Class C
|
Class A
|
Class B
|
Class C
|
Multiple Inheritance
|
Example: -
Single Inheritance:
- Multilevel Inheritance:
- Hierarchical Inheritance:
-
public class A public class A public class A
{ } { } { }
public class B : A public class B : A public class B : A
{ } { } { }
public class A public class A public class A
{ } { } { }
public class B : A public class B : A public class B : A
{ } { } { }
public class C : B
public class C : A
Multiple Inheritance:
-
{
}
{ }
public class
A
public class D : A
{
}
{ }
public class B
{ }
public class C : A, B
{ }
Polymorphism
Polymorphism is
the ability to define a method or property in a set of derived classes with
matching method signatures but provide different implementations and then
distinguish the objects’ matching interface from one another at runtime when
you call the method on the base class.
It is a feature to use one name in many forms. It can be
achieved in following ways: -
·
Method Overloading
·
Method Overriding
·
Method Hiding
Method overriding and hiding makes use of the following three
method keywords –
1. new
2. virtual
3. override
1. When a derived
class inherits from a base class, it gains all the methods, fields, properties
and events of the base class. To change the data and behavior of a base class,
you have two choices: you can replace the base member with a new derived member, or you can
override a virtual base member.
Replacing a member of a base class with a new derived member
requires the new keyword.
If a base class defines a method, field, or property, the new keyword is used
to create a new definition
of that method, field, or property on a derived class. The new keyword is placed before the
return type of a class member that is being replaced. For example:
public class BaseClass
{
public void DoWork() { }
public int WorkField;
public int WorkProperty
{
get { return 0; }
}
}
public class DerivedClass : BaseClass
{
public new void DoWork() { }
public new int WorkField;
public new int WorkProperty
{
get { return 0; }
}
}
DerivedClass B = new DerivedClass();
B.DoWork(); // Calls the new method.
BaseClass A = (BaseClass)B;
A.DoWork(); // Calls the old method.
2,3. In
order for an instance of a derived class to completely take over a class member
from a base class, the base class has to declare that member as virtual. This is accomplished by
adding the virtual keyword
before the return type of the member. A derived class then has the option of
using theoverride keyword,
instead of new, to replace the base class implementation with its own. For
example:
public class BaseClass
{
public virtual void DoWork() { }
public virtual int WorkProperty
{
get { return 0; }
}
}
public class DerivedClass : BaseClass
{
public override void DoWork() { }
public override int WorkProperty
{
get { return 0; }
}
}
DerivedClass B = new DerivedClass();
B.DoWork(); // Calls the new method.
BaseClass A = (BaseClass)B;
A.DoWork(); // Also calls the new method.
Remarks about Virtual
·
When a virtual method is invoked, the run-time type of the
object is checked for an overriding member. The overriding member in the most
derived class is called, which might be the original member, if no derived
class has overridden the member.
·
By default, methods are non-virtual. You cannot override a
non-virtual method.
·
You cannot use the virtual modifier with the static, abstract,
private or override modifiers.
·
Virtual properties behave like abstract methods, except for the
differences in declaration and invocation syntax.
·
It is an error to use the virtual modifier on a static property.
·
A virtual inherited property can be overridden in a derived
class by including a property declaration that uses the override modifier.
Remarks about Override
·
The override modifier is required to extend or modify the
abstract or virtual implementation of an inherited method, property, indexer,
or event.
·
An override method provides a new implementation of a member
inherited from a base class. The method overridden by an override declaration
is known as the overridden base method. The overridden base method must have
the same signature as the override method.
·
You cannot override a non-virtual or static method. The
overridden base method must be virtual, abstract, or override.
·
An override declaration cannot change the accessibility of the
virtual method. Both the override method and the virtual method must have the
same access level modifier.
·
You cannot use the modifiers new, static, virtual, or abstract
to modify an override method.
·
An overriding property declaration must specify the exact same
access modifier, type, and name as the inherited property, and the overridden
property must be virtual, abstract, or override.
Class and Objects
Classes
A class is a construct that enables you to create your own
custom types by grouping together variables of other types, methods and events.
A class is like a blueprint. It defines the data and behavior of a type. If the
class is not declared as static, client code can use it by creating objects or
instances which are assigned to a variable. The variable remains in memory
until all references to it go out of scope. At that time, the CLR marks it as
eligible for garbage collection. If the class is declared as static, then only
one copy exists in memory and client code can only access it through the class
itself, not an instance variable.
Declaring Class
public class Customer
{
//Fields, properties, methods and events go
here…
}
The class keyword is preceded by the access level. Because
public is used in this case, anyone can create objects from this class. The
name of the class follows the class keyword.
Objects
An object is basically a block of memory that has been allocated
and configured according to the blueprint. A program may create many objects of
the same class. Objects are also called instances, and they can be stored in
either a named variable or in an array or collection.
Creating Objects
A class and an object are different things. A class defines a
type of object, but it is not an object itself. An object is a concrete entity
based on a class, and is sometimes referred to as an instance of a class.
Objects can be created by using the new keyword followed by the
name of the class that the object will be based on, like this:
Customer object1 = new Customer();
When an instance of a class is created, a reference to the
object is passed back to the programmer. In the previous example, object1 is a
reference to an object that is based on Customer.
Class Modifiers
A class-declaration can optionally include a sequence of class
modifiers:
class-modifiers:
class-modifier
class-modifiers class-modifier
class-modifier:
new, public, protected, internal, private, abstract, sealed
The new modifier
is permitted on nested classes. The new modifier can be used to modify a nested
type if the nested type is hiding another type.
The public,
protected, internal, and private modifiers
control the accessibility of the class. Depending on the context in which the
class declaration occurs, some of these modifiers may not be permitted
The abstract modifier
is used to indicate that a class is incomplete and that it is intended to be
used only as a base class. An abstract class differs from a non-abstract class
in the following ways:
·
An abstract class cannot be instantiated directly, and it is a
compile-time error to use the new operator on an abstract class. While it is
possible to have variables and values whose compile-time types are abstract,
such variables and values will necessarily either be null or contain references
to instances of non-abstract classes derived from the abstract types.
·
An abstract class is permitted (but not required) to contain
abstract methods and members.
·
An abstract class cannot be sealed.
Features of Abstract Methods:
·
An abstract method is implicitly a virtual method.
·
Abstract method declarations are only permitted in abstract
classes.
·
Because an abstract method declaration provides no actual
implementation, there is no method body; the method declaration simply ends
with a semicolon and there are no braces ({ }) following the signature. For
example:
Copypublic abstract void MyMethod();
·
The implementation is provided by an overriding method, which is
a member of a non-abstract class.
·
It is an error to use the static or virtual modifiers in an
abstract method declaration.
Abstract properties behave like abstract methods, except for the
differences in declaration and invocation syntax.
·
It is an error to use the abstract modifier on a static
property.
·
An abstract inherited property can be overridden in a derived
class by including a property declaration that uses the override modifier.
An abstract class must provide implementation for all interface
members.
Example: -
// abstract_keyword.cs
// Abstract Classes
using System;
abstract class MyBaseC // Abstract class
{
protected int x = 100;
protected int y = 150;
public abstract void MyMethod(); //
Abstract method
public abstract int GetX // Abstract
property
{
get;
}
public abstract int GetY // Abstract
property
{
get;
}
}
class MyDerivedC: MyBaseC
{
public override void MyMethod()
{
x++;
y++;
}
public override int GetX // overriding
property
{
get
{
return x+10;
}
}
public override int GetY // overriding
property
{
get
{
return y+10;
}
}
public static void Main()
{
MyDerivedC mC = new MyDerivedC();
mC.MyMethod();
Console.WriteLine(“x = {0}, y =
{1}”, mC.GetX, mC.GetY);
}
}
The sealed modifier
is used to prevent derivation from a class. A compile-time error occurs if a
sealed class is specified as the base class of another class.
A sealed class cannot also be an abstract class.
The sealed modifier is primarily used to prevent unintended
derivation, but it also enables certain run-time optimizations. In particular,
because a sealed class is known to never have any derived classes, it is
possible to transform virtual function member invocations on sealed class
instances into non-virtual invocations.
Example: use of Sealed modifier
// cs_sealed_keyword.cs
// Sealed classes
using System;
sealed class MyClass
{
public int x;
public int y;
}
class MainClass
{
public static void Main()
{
MyClass mC = new MyClass();
mC.x = 110;
mC.y = 150;
Console.WriteLine(“x = {0}, y =
{1}”, mC.x, mC.y);
}
}
Output: x=110, y=150
Constructors
Whenever a class or struct is created, its constructor is
called. A class or struct may have multiple constructors that take different
arguments.
Constructors allow the programmer to set default values, limit
instantiation, and write code that is flexible and easy to read.
·
Constructor is used to initialize an object (instance) of a
class.
·
Constructor is a like a method without any return type.
·
Constructor has same name as class name.
·
Constructor follows the access scope (Can be private, protected,
public, Internal and external).
·
Constructor can be overloaded.
Constructors generally following types:
·
Default Constructor
·
Parameterized constructor
·
Private Constructor
·
Static Constructor
·
Copy Constructor
Default Constructor
A constructor that takes no parameters is called a default
constructor.
When a class is initiated default constructor is called which
provides default values to different data members of the class.
You need not to define default constructor it is implicitly
defined.
Example: -
class Program
{
class C1
{
int a, b;
public C1()
{
this.a = 10;
this.b = 20;
}
public void display()
{
Console.WriteLine(“Value of a: {0}”, a);
Console.WriteLine(“Value of b: {0}”, b);
}
}
static void
Main(string[] args)
{
C1 ob1 = new C1();
ob1.display();
Console.ReadLine();
}
}
Output: – Value of a: 10
Value of b: 20
Parameterized constructor
Constructor that accepts arguments is known as parameterized
constructor. There may be situations, where it is necessary to initialize
various data members of different objects with different values when they are
created. Parameterized constructors help in doing that task.
class Program
{
class C1
{
int a, b;
public C1(int x, int y)
{
this.a = x;
this.b = y;
}
public void display()
{
Console.WriteLine(“Value of a: {0}”, a);
Console.WriteLine(“Value of b: {0}”, b);
}
}
static void
Main(string[] args)
{ // Here when you
create instance of the class
// parameterized constructor will be called
C1 ob1 = new C1(10,20);
ob1.display();
Console.ReadLine();
}
}
Output: – Value of a: 10
Value of b: 20
Private Constructor
Private constructors are used to restrict the instantiation of
object using ‘new’ operator. A private constructor is a special instance
constructor. It is commonly used in classes that contain static members only.
·
If you don’t want the class to be inherited we declare its
constructor private.
·
We can’t initialize the class outside the class or the instance
of class can’t be created outside if its constructor is declared private.
·
We have to take help of nested class (Inner Class) or static method to initialize a
class having private constructor.
Example: -
class Program
{
class C1
{
int a, b;
public C1(int x, int y)
{
this.a = x;
this.b = y;
}
public static C1 create_instance()
{ return new C1(12, 20); }
public void display()
{
Console.WriteLine(“Value of a: {0}”, a);
Console.WriteLine(“Value of b: {0}”, b);
int z = a + b;
Console.WriteLine(z);
}
}
static void
Main(string[] args)
{ // Here the class is initiated using a static method of the
class than only you
can use private constructor
C1 ob1 = C1.create_instance();
ob1.display();
Console.ReadLine();
}
}
Static Constructors
C# supports two types of constructor, a class constructor static
constructor and an instance constructor (non-static constructor).
Static constructors might be convenient, but they are slow. The
runtime is not smart enough to optimize them in the same way it can optimize
inline assignments. Non-static constructors are inline and are faster.
Static constructors are used to initializing class static data
members.
Point to be remembered while creating static constructor:
1. There can be only one static constructor in the class.
2. The static constructor should be without parameters.
3. It can only access the static members of the class.
4. There should be no access modifier in static constructor
definition.
Static members are preloaded in the memory. While instance
members are post loaded into memory.
Static methods can only use static data members.
Example:
class Program
{
public class test
{
static string name;
static int age;
static test()
{
Console.WriteLine(“Using static constructor to
initialize
static data members”);
name = “John Sena”;
age = 23;
}
public static void display()
{
Console.WriteLine(“Using static function”);
Console.WriteLine(name);
Console.WriteLine(age);
}
}
static void
Main(string[] args)
{
test.display();
Console.ReadLine();
}}
Output:
Using static constructor to initialize static data members
Using static function
John Sena
23
Copy Constructor
If you create a new object and want to copy the values from an
existing object, you use copy constructor.
This constructor takes a single argument: a reference to the
object to be copied.
Example:
class Program
{
class c1
{
int a, b;
public c1(int x, int y)
{
this.a = x;
this.b = y;
}
// Copy construtor
public c1(c1 a)
{
this.a = a.a;
this.b = a.b;
}
public void display()
{
int z = a + b;
Console.WriteLine(z);
}
}
static void
Main(string[] args)
{
c1 ob1 = new c1(10, 20);
ob1.display();
// Here we are using copy
constructor. Copy constructor is
using the values already defined with ob1
c1 ob2 = new c1(ob1);
ob2.display();
Console.ReadLine();
}
}
Output:
30
30
Destructors
The .NET framework has an in built mechanism called Garbage
Collection to de-allocate memory occupied by the un-used objects. The
destructor implements the statements to be executed during the garbage
collection process. A destructor is a function with the same name as the name
of the class but starting with the character ~.
Example:
class Complex
{
public Complex()
{
// constructor
}
~Complex()
{
// Destructor
}
}
·
Remember that a destructor can’t have any modifiers like
private, public etc. If we declare a destructor with a modifier, the compiler
will show an error.
·
Also destructor will come in only one form, without any
arguments.
·
There is no parameterized destructor in C#.
Destructors are invoked automatically and can’t be invoked
explicitly. An object becomes eligible for garbage collection, when it is no
longer used by the active part of the program. Execution of destructor may
occur at any time after the instance or object becomes eligible for
destruction.
Operator Overloading
Operator overloading permits user-defined operator
implementations to be specified for operations where one or both of the
operands are of a user-defined class or struct type.
In another way, Operator overloading is a concept in which
operator can define to work with the user defined data types such as structs
and classes in the same way as the pre-defined data types.
There are many operators which can not be overloaded, which are
listed below: -
Conditional Operator &&, ||
Compound Assignment +=, -=, *=, /=, %=
Other
Operators [],
( ), =, ?:, ->, new, sizeof, typesof.
public class Item
{
public int i;
public Item(int j)
{ i = j; }
public static Item
operator +(Item x, Item y)
{
Console.WriteLine(“OPerator +” + x.i + “” + y.i);
Item z = new Item(x.i + y.i);
return z;
}
}
class Program
{
static void
Main(string[] args)
{
Item a = new Item(10);
Item b = new Item(5);
Item c;
c = a + b;
Console.WriteLine(c.i);
Console.Read();
}
}
Output: Operator + 10 5
15
·
In C#, a special function called operator function is used for
overloading purpose.
·
These special function or method must be public and static.
·
They can take only value arguments.
·
The ref and out parameters are not allowed as arguments to
operator functions.
The general form of an operator function is as follows.
public static return_type operator op (argument list)
Where the op is the operator to be overloaded and operator is
the required keyword.
Example: Overloading of Unary operator
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}\t{1}”,x,y);
}
public static Complex operator -(Complex c)
//PASSING OBJECT
{
Complex temp = new
Complex();
temp.x = -c.x;
temp.y = -c.y;
return temp;
}
}
class Program
{
static void
Main(string[] args)
{
Complex c1 = new Complex(10, 20);
c1.ShowXY(); // displays 10 & 20
Complex c2 = new Complex();
c2.ShowXY(); // displays 0 & 0
c2 = -c1; //overloading unary operator
c2.ShowXY(); // diapls -10 & -20
Console.Read();
}
}
Output:
10 20
0 0
-10 -20
Namespace:
Namespaces are C# program elements designed to help you organize
your programs. They also provide assistance in avoiding name clashes between
two sets of code.
In Microsoft .Net, Namespace is like containers of objects. They
may contain unions, classes, structures, interfaces, enumerators and delegates.
Main goal of using namespace in .Net is for creating a hierarchical
organization of program. In this case, you need not to worry about the naming conflicts of classes,
functions, variables etc., inside a project.
In Microsoft .Net, every program is created with a default
namespace. This default namespace is called as global namespace. But the
program itself can declare any number of namespaces, each of them with a unique
name. The advantage is that every namespace can contain any number of classes,
functions, variables and also namespaces etc., whose names are unique only
inside the namespace. The members with the same name can be created in some
other namespace without any compiler complaints from Microsoft .Net.
To declare namespace C# .Net has a reserved keyword namespace.
If a new project is created in Visual Studio .NET it automatically adds some global
namespaces. These namespaces can be different in different projects. But each
of them should be placed under the base namespace System. The names space must
be added and used through the using operator, if used in a different project.
A namespace has the following properties:
·
They organize large code projects.
·
They are delimited with the . operator.
·
The using directive means you do not need to specify the name of
the namespace for every class.
·
The global namespace is the “root” namespace: global::system will always refer to the .NET
Framework namespace System.
Now have a look at the example of declaring some namespace:
namespace SampleNamespace
{
class SampleClass{}
interface SampleInterface{}
struct SampleStruct{}
enum SampleEnum{a,b}
delegate void SampleDelegate(int i);
namespace SampleNamespace.Nested
{
class SampleClass2{}
}
}
Within a namespace, you can declare one or more of the following
types:
·
another namespace
·
class
·
interface
·
struct
·
enum
·
delegate
Namespaces implicitly have public access and this is not
modifiable.
It is possible to define a namespace in two or more
declarations. For example, the following example defines two classes as part of
the MyCompany namespace:
namespace MyCompany.Proj1
{
class MyClass
{
}
}
namespace MyCompany.Proj1
{
class MyClass1
{
}
}
Example: The following example shows
how to call a static method in a nested namespace:
using System;
namespace SomeNameSpace
{
public class MyClass
{
static void Main()
{
Nested.NestedNameSpaceClass.SayHello();
}
}
// a nested namespace
namespace Nested
{
public class
NestedNameSpaceClass
{
public static void SayHello()
{
Console.WriteLine(“Hello”);
}
}
}
}
Output
Hello
Example: Calling Nested
Namespace Members
// Namespace Declaration
using System;
namespace Ex_nestedNamespace
{
namespace tutorial
{
class example
{
public static void MyPrint1()
{
Console.WriteLine(“First Example of calling another namespace member.”);
}
}
}
namespace Ex_NameSpace
{
class Program
{
static void Main(string[] args)
{
tutorial.example.MyPrint1();
tutorial.example1.MyPrint2();
Console.Read();
}
}
}
}
namespace Ex_nestedNamespace.tutorial
{
class example1
{
public static void
MyPrint2()
{
Console.WriteLine(“Second Example of calling another namespace member.”);
}
}
}
Output:
First Example of calling another namespace member.
Second Example of calling another namespace member.
Interface
An Interface is a reference type and it contains only abstract
members. Interface’s members can be Events, Methods, Properties and Indexers.
But the interface contains only declaration for its members. Any implementation
must be placed in class that realizes them. The interface can not contain
constants, data fields, constructors, destructors and static members. All the
member declarations inside interface are implicitly public and they cannot
include any access modifiers.
An interface has the following properties:
·
An interface is like an abstract base class: any non-abstract
type that implements the interface must implement all its members.
·
An interface cannot be instantiated directly.
·
Interfaces can contain events, indexers, methods, and
properties.
·
Interfaces contain no implementation of methods.
·
Classes and structs can implement more than one interface.
·
An interface itself can inherit from multiple interfaces.
interface IPoint
{
int x
{ get; set; }
int y
{ get; set; }
}
namespace Ex_Interface
{
class MyPoint:IPoint
{
private int myX;
private int myY;
public MyPoint(int x,
int y)
{
myX= x;
myY=y;
}
public int x
{
get
{
return myX;
}
set
{
myX=value;
}
}
public int y
{
get
{
return myY;
}
set
{
myY=value;
}
}
}
class Program
{
private static void
PrintPoint(IPoint P)
{
Console.WriteLine(“x={0}, y={1}”,P.x,P.y);
}
static void
Main(string[] args)
{
MyPoint P = new MyPoint(2, 3);
Console.Write(“My Point::”);
PrintPoint(P);
Console.Read();
}
}
}
Output:
My Point::x=2, y=3
Another Example of Interface by
Casting Interface methods:
interface add
{ int sum();}
interface Multiply
{ int mul();}
class Calculate : add, Multiply
{
int a, b;
public Calculate(int x, int y)
{
a = x;
b = y;
}
public int sum()
{ return (a + b);}
public int mul()
{ return a * b; }
}
namespace Ex_MultipleInterface
{
class Program
{
static void
Main(string[] args)
{
Calculate cal = new Calculate(5, 10);
add A = (add)cal;
Console.WriteLine(“Sum::” + A.sum());
Multiply M = (Multiply)cal;
Console.WriteLine(“Multiplication::” + M.mul());
Console.Read();
}
}
}
Output:
Sum::15
Multiplication::50
Delegates
In .NET, you use delegates to call event procedure. Delegates
are objects that you use to call the methods of other objects. Delegates are
said to be object-oriented function pointers since they allow a function to be
invoked indirectly by using a reference to the function.
However, unlike function pointers, the delegates in .NET are
reference types, based on the class System.Delegate. In addition, delegates in
.NET can reference both shared and instance methods.
In another way, a
delegate can be defined as a type safe function pointer. You use delegates to
call the methods of other objects. They are object-oriented function pointers
since they allow a function to be invoked indirectly by using a reference to
the function.
Where are Delegates used?
The most common example of using delegates is in events.
You define a method that contains code for performing various
tasks when an event (such as a mouse click) takes place.
This method needs to be invoked by the runtime when the event
occurs. Hence this method, that you defined, is passed as a parameter to a
delegate.
Starting Threads/Parallel Processing:
You defined several methods and you wish to execute them
simultaneously and in parallel to whatever else
the application is doing. This can be achieved by starting new
threads. To start a new thread for your method you pass your method details to
a delegate.
Generic Classes: Delegates
are also used for generic class libraries which have generic functionality
defined. However the generic class may need to call certain functions defined
by the end user implementing the generic class. This can be done by passing the
user defined functions to delegates.
Creating and Using Delegates:
Using delegates is a two step process-
……….1) Define the delegate to be used
……….2) Create one or more instances of the delegate
……….1) Define the delegate to be used
……….2) Create one or more instances of the delegate
Syntax for defining a delegate:
delegate string reviewStatusofARegion();
to define a delegate we use a key word delegate followed by the
method signature the delegate represents. In the above example string
reviewStatusofARegion(); represents any method that returns a string and takes
no parameters.
Syntax for creating an instance of the delegate:
reviewStatusofARegion = new
reviewStatusofARegion(myClass.getEurope);
private string getEurope()
{
return “Doing Great in Europe”;
}
{
return “Doing Great in Europe”;
}
To create an instance of the delegate you call its constructor.
The delegate constructor takes one parameter which is the method name.
The method signature should exactly match the original
definition of the delegate. If it does not match the compiler would raise an Error.
C# provides support for Delegates through the class called
Delegate in the System namespace. Delegates are of two types.
·
Single-cast delegates
·
Multi-cast delegates
A Single-cast
delegate is one that can refer to a single method whereas a
Multi-cast delegate can refer to and eventually fire off multiple methods that
have the same signature.
The signature of a delegate type comprises are the following.
·
The name of the delegate
·
The arguments that the delegate would accept as parameters
·
The return type of the delegate
A delegate is either public or internal if no specifier is
included in its signature. Further, you should instantiate a delegate prior to
using the same.
The following is an example of how a delegate is declared.
Listing 1: Declaring a delegate
public delegate void TestDelegate(string message);
The return type of the delegate shown in the above example is
“void” and it accepts a string argument. Note that the keyword “delegate”
identifies the above declaration as a delegate to a method. This delegate can
refer to and eventually invoke a method that can accept a string argument and
has a return type of void, i.e., it does not return any value.
Listing 2:
Instantiating a delegate
TestDelegate t = new TestDelegate(Display);
Implementing Delegates in C#
This section illustrates how we can implement and use delegates
in C#.This section illustrate how we can implement and use delegates in C#.
Example 1: Single Cast Delegate
namespace Ex_Delegate
{
delegate int Operation(int x, int y);
//declaration
class Metaphor
{
public static int
Add(int a, int b)
{ return a + b; }
public static int
Sub(int a, int b)
{ return a – b; }
public static int
Mul(int a, int b)
{ return a * b; }
}
class Program
{
static void
Main(string[] args)
{ //
Delegate instances
Operation opr1 = new Operation(Metaphor.Add);
Operation opr2 = new Operation(Metaphor.Sub);
Operation opr3 = new Operation(Metaphor.Mul);
//invoking of delegates
int ans1 = opr1(200, 100);
int ans2 = opr2(200, 100);
int ans3 = opr3(20, 10);
Console.WriteLine(“\n Addition:” + ans1);
Console.WriteLine(“\n Subtract:” + ans2);
Console.WriteLine(“\n Multiplication:” + ans3);
Console.Read();
} }}
Example 2: Single Cast Delegate
namespace Ex_SingleCastDelegate
{
//Declare the delegate
public delegate void TestDelegate(string message);
class Program
{
public static void
Display(string message)
{Console.WriteLine(“The string entered is : ” + message);}
static void
Main(string[] args)
{ //Initiate the
delegate
TestDelegate t = new TestDelegate(Display);
Console.WriteLine(“Please enter a string::”);
string message = Console.ReadLine();
t(message);
Console.ReadLine();
}}}
Multicast Delegate
A multi-cast delegate is basically a list of delegates or a list
of methods with the same signature. A multi-cast delegate can call a collection
of methods instead of only a single method.
Example: Multicast Delegate
namespace Ex_MulticastDelegate
{
public delegate void TestDelegate();
class Program
{
public static void
Display1()
{
Console.WriteLine(“This is first method”);
}
public static void
Display2()
{
Console.WriteLine(“This is second method”);
}
static void
Main(string[] args)
{
TestDelegate t1 = new TestDelegate(Display1);
TestDelegate t2 = new TestDelegate(Display2);
t1 = t1 + t2; // Make t1 a multi-cast delegate
t1(); //Invoke delegate
Console.Read();
} } }
In another way, You can also assign the references of multiple
methods to a delegate and use it to invoke multiple methods. Such a delegate is
called a multi-cast delegate as multiple method references are cast to it and
then the delegate is used to invoke these methods.
What are Attributes?
An Attribute is a declarative tag which can be used to provide
information to the compiler about the behaviour of the C# elements such as
classes and assemblies.
C# provides convenient technique that will handle tasks such as
performing compile time operations , changing the behaviour of a method at
runtime or maybe even handle unmanaged code.
C# Provides many Built-in Attributes.
Some Popular ones are
·
Obsolete
·
DllImport
·
Conditional
·
WebMethod
It is also possible to create new ones by extending the
System.Attribute class.
For example:
using System;
[CLSCompliant(true)]
Public class myClass
{ // class code }
Web services also make use of attributes. The attribute
[WebMethod] is used to specify that a particular method is to be exposed as a
web service.
Why Attributes ?
The reason attributes are necessary is because many of the
services they provide would be very difficult to accomplish with normal code.
You see, attributes add what is called metadata to your programs. When your C#
program is compiled, it creates a file called an assembly, which is normally an
executable or DLL library. Assemblies are self-describing because they have
metadata written to them when they are compiled. Via a process known as
reflection, a program’s attributes can be retrieved from its assembly metadata.
Attributes are classes that can be written in C# and used to decorate your code
with declarative information. This is a very powerful concept because it means
that you can extend your language by creating customized declarative syntax
with attributes.
How it is used in C#?
Attributes are elements that allow you to add declarative
information to your programs. This declarative information is used for various
purposes during runtime and can be used at design time by application
development tools. For example, there are attributes such as DllImportAttribute
that allow a program to communicate with the Win32 libraries. Another
attribute, ObsoleteAttribute, causes a compile-time warning to appear, letting
the developer know that a method should no longer be used. When building
Windows forms applications, there are several attributes that allow visual
components to be drag-n-dropped onto a visual form builder and have their
information appear in the properties grid. Attributes are also used extensively
in securing .NET assemblies, forcing calling code to be evaluated against
pre-defined security constraints. These are just a few descriptions of how
attributes are used in C# programs.
Predefined
.NET Attribute
|
Valid
Targets
|
Description
|
AttributeUsage
|
Class
|
Specifies the valid usage
of another attribute class.
|
CLSCompliant
|
All
|
Indicates whether a
program element is compliant with the Common Language Specification (CLS).
|
DllImport
|
Method
|
Specifies the DLL
location that contains the implementation of an external method.
|
MTAThread
|
Method (Main)
|
Indicates that the
default threading model for an application is multithreaded apartment (MTA).
|
NonSerialized
|
Field
|
Applies to fields of a
class flagged as Serializable; specifies that these fields won’t be
serialized.
|
Obsolete
|
All except Assembly,
Module, Parameter, and Return
|
Marks an element
obsolete—in other words, it informs the user that the element will be removed
in future versions of the product.
|
ParamArray
|
Parameter
|
Allows a single parameter
to be implicitly treated as a params (array) parameter.
|
Serializable
|
Class, struct, enum,
delegate
|
Specifies that all public
and private fields of this type can be serialized.
|
STAThread
|
Method (Main)
|
Indicates that the
default threading model for an application is STA.
|
ThreadStatic
|
Field (static)
|
Implements thread-local
storage (TLS)—in other words, the given static field isn’t shared across
multiple threads and each thread has its own copy of the static field.
|
Predefined attributes
Example:
Pre-defined attributes are used to store external information
into metadata. For example, consider the following piece of code:
public class testAttribute {
[DllImport("sampleDLL.dll")]
public static extern sampleFunction(int sampleNo, string
sampleString );
public static void Main( ) {
string strVar;
sampleFunction(10, “Test Attribute”);
}
}
Using the example code above, you can import a method calledsampleFunction from sampleDLL.dll and use it in your
program as if it’s your own method. This is achieved using the pre-defined
attribute “DllImport”.
Multi-Threading
Multithreading forms a subset of multitasking. Instead of having
switch between programs this feature switches between different parts of the
same program. For example when you are writing words in Ms-word then spell
checking is going on background.
Thread – A thread (or “thread of execution”) is a sort of
context in which code is running. Any one thread follows program flow for
wherever it is in the code, in the obvious way.
A thread is a unit of processing, and multitasking is the
simultaneous execution of multiple threads. Multitasking comes in two flavors:
cooperative and preemptive. Very early versions of Microsoft Windows supported
cooperative multitasking, which meant that each thread was responsible for
relinquishing control to the processor so that it could process other threads.
However, Microsoft Windows NT-and, later, Windows 95, Windows
98, and Windows 2000-support the same preemptive multitasking that OS/2 does.
With preemptive multitasking, the processor is responsible for giving each
thread a certain amount of time in which to execute-a timeslice. The processor
then switches among the different threads, giving each its timeslice, and the
programmer doesn’t have to worry about how and when to relinquish control so
that other threads can run. .NET will only work only on preemptive multitasking
operating systems.
1. Starting Thread
Object thread is obtained from System.Threading namespace. With
the use object of this class we can create a new thread, delete, pause, and
resume threads. Simple a new thread is created by Thread class and started by
Thread.Start().
eg. Thread th = new Thread (new ThreadStart (somedata));
th.Start();
2. Pausing Thread
Some time the requirement to pause a thread for certain time of
interval; you can attain the same by using Sleep (n) method. This method takes
an integer value to determine how long a thread should pause or Sleep.
eg. th.Sleep(2000);
Note:
To pause or sleep a thread for an in determine time, just call
the sleep () method as: [make sure you have added System.Threading namespace]
Thread.Sleep(TimeOut.Infinite).
To Resume or interrupt this call : Thread.Interrupt () method.
3. Suspending
Thread
Of course, there is a Suspend () method which suspends the
thread. It is suspended until a Resume () method called.
eg. if (th.ThreadState = = ThreadState.Running)
th.Suspended();
4. Resuming Thread
To Resume a suspended thread, there is a Resume () method,
thread resumes if earlier suspended if not so then there is no effect of Resume
() method on the thread.
eg. if (th.ThreadState = = ThreadState.Suspended)
th.Resume();
5. Killing Thread
You can call Abort () method to kill a thread, before calling
the same method, make sure thread is alive.
eg. if (th.IsAlive)
th.Abort();
Suspend and Resume in Threading
It is similar to sleep and Interrupt. Suspend allows you to
block a thread until another thread calls Thread.Resume ().The difference
between sleep and suspend is that the later does no immediately place a thread
in the wait state. The thread does not suspend until the .Net runtime
determines that it is in a safe place to suspend it. Sleep will immediately
place a thread in a wait state.
Important:
You can change thread priority for that just supply :
th.Priority = ThreadPriority.Highest. [th – Thread name]. Priority sets the
sequence of thread in which they are running. You can set the following priority
to thread(s):
1. ThreadPriority.Highest
2. ThreadPriority.AboveNormal
3. ThreadPriority.Normal
4. ThreadPriority.BelowNormal
5. ThreadPriority.Lowest
Code Example of Multithreading
using System.Threading;
namespace Ex_ThreadExample
{
class SimpleThread
{
private Thread
thread1;
private Thread
thread2;
private void
Method1()
{
for (int i =0; i<10;i++)
{
Console.WriteLine (“i = ” +i);
Thread.Sleep (400); // 200 miliseconds pause
}
}
private void
Method2()
{
for (int i =0;i<10;i++)
{
Console.WriteLine (“i = ” + 100 * i);
Thread.Sleep (100); // 100 miliseconds pause
}
}
static void
Main(string[] args)
{
SimpleThread app = new SimpleThread ();
app.thread1 = new Thread (new ThreadStart (app.Method1)); // thread
start Delegate Method
app.thread2 = new Thread (new ThreadStart (app.Method2));
app.thread1.Start ();
app.thread2.Start ();
Console.WriteLine ();
Console.ReadLine();
}
}
}
————-x————–x————–x—————x———-
Socket Programming in C#
Network programming in windows is possible with sockets. A
socket is like a handle to a file. Socket programming resembles the file IO as
does the Serial Communication. You can use sockets programming to have two
applications communicate with each other. The application are typically on the
different computers but they can be on same computer. For the two applications
to talk to each either on the same or different computers using sockets one
application is generally a server that keeps listening to the incoming requests
and the other application acts as a client and makes the connection to the
server application.
The server application can either accept or reject the
connection. If the server accepts the connection, a dialog can begin with
between the client and the server. Once the client is done with whatever
it needs to do it can close the connection with the server. Connections are
expensive in the sense that servers allow finite connections to occur.
During the time client has an active connection it can send the data to the
server and/or receive the data.
Socket programming in .NET is made possible by Socket class
present inside the System.Net. Sockets namespace.
Socket class has several method and properties and a
constructor.
·
The first step is to create an object of this class. Since there
is only one constructor we have no choice but to use it.
Here is how to create the socket:
m_socListener = new
Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.IP);
AddressFamily is an enum defined in Sockets namespace.
·
Next we need to specify socket type: and we would use reliable
two way connection-based sockets (stream) instead of un-reliable Connectionless
sockets ( datagrams) . So we obviously specify stream as the socket type and
finally we are using TCP/IP so we would specify protocol type as TCP.
·
Once we have created a Socket we need to make a connection to
the server since we are using connection-based communication.
·
To connect to the remote computer we need to know the IP
Address and port at which to connect.
·
In .NET there is a class under System.Net namespace called
IPEndPoint which represents a network computer as an IP address and a
port number.
·
The IPEndPoint has two constructors – one that takes a IP
Address and Port number and one that takes long and port number. Since we
have computer IP address we would use the former
public IPEndPoint(System.Net.IPAddress address, int port);
·
As you can see the first parameter takes a IPAddress object. If
you examine the IPAddress class you will see that it has a static method called
Parse that returns IPAddress given a string ( of dot notation ) and second
parameter will be the port number. Once we have endpoint ready we can use
Connect method of Socket class to connect to the end point ( remote
server computer ).
Here is the code:
System.Net.IPAddress ipAdd =
System.Net.IPAddress.Parse(“10.10.101.200″);
System.Net.IPEndPoint remoteEP = new IPEndPoint (ipAdd,8221);
m_socClient.Connect (remoteEP);
Description
These three lines of code will make a connection to the remote
host running on computer with IP 10.10.101.200 and listening at port 8221. If
the Server is running and started ( listening ), the connection will succeed.
If however the server is not running an exception called SocketException will
be thrown. If you catch the exception and check the Message property of the
exception in this case you see following text:
“No connection could be made because the target machine actively
refused it.”
Similarly if you already have made a connection and the server
somehow dies, you will get following exception if you try to send data.
“An existing connection was forcibly closed by the remote host”
Assuming that the connection is made, you can send data to other
side using the Send method of the Socket class.
Send method has several overloads. All of them take a byte
array. For example if you want to send “Hello There” to host you can use
following call:
try
{
String szData = “Hello There”;
byte[] byData = System.Text.Encoding.ASCII.GetBytes(szData);
m_socClient.Send(byData);
}
catch (SocketException se)
{
MessageBox.Show ( se.Message );
}
Note that the Send method is blocking. What it means the call
will block till the data has been sent or an exception has been thrown. There
is a non-blocking version of the send which we will discuss in the next part of
this article.
Similar to send there is a Receive method on the Socket class.
You can receive data using following call:
byte [] buffer = new byte[1024];
int iRx = m_socClient.Receive (buffer);
The Receive method again is blocking. It means that if there is
no data available the call will block until some data arrives or an
exception is thrown.
Non-blocking version of Receive method is more useful than the
non-blocking version of Send because if we opt for block Receive, we are
effectively doing polling. There is no event about data arrival. This model
does not work well for serious applications. But all that is the subject of our
next part of this article. For now we will settle with the blocking version.
Server Side Code:
using System;
using System.Net.Sockets;
public class AsynchIOServer
{
public static void Main()
{
TCPListener tcpListener = new TCPListener(10);
tcpListener.Start();
Socket socketForClient = tcpListener.Accept();
if (socketForClient.Connected)
{
Console.WriteLine(“Client connected”);
NetworkStream networkStream = new
NetworkStream(socketForClient);
System.IO.StreamWriter streamWriter = new
System.IO.StreamWriter(networkStream);
System.IO.StreamReader streamReader = new
System.IO.StreamReader(networkStream);
string theString = “Sending”;
streamWriter.WriteLine(theString);
Console.WriteLine(theString);
streamWriter.Flush();
theString = streamReader.ReadLine();
Console.WriteLine(theString);
streamReader.Close();
networkStream.Close();
streamWriter.Close();
}
socketForClient.Close();
Console.WriteLine(“Exiting…”);
}
}
Client Code:
using System;
using System.Net.Sockets;
public class Client
{
static public void Main( string[] Args )
{
TCPClient socketForServer;
try
{
socketForServer = new TCPClient(“localHost”, 10);
}
catch
{
Console.WriteLine(
“Failed to connect to server at {0}:999″, “localhost”);
return;
}
NetworkStream networkStream = socketForServer.GetStream();
System.IO.StreamReader streamReader = new System.IO.StreamReader(networkStream);
System.IO.StreamWriter streamWriter = new
System.IO.StreamWriter(networkStream);
try
{
string outputString;
// read the data from the host and display it
{
outputString = streamReader.ReadLine();
Console.WriteLine(outputString);
streamWriter.WriteLine(“Client Message”);
Console.WriteLine(“Client Message”);
streamWriter.Flush();
}
}
catch
{
Console.WriteLine(“Exception reading from Server”);
}
// tidy up
networkStream.Close();
}
}
———–x—————-x————————–x————————-x—————-x—————x———-
Error Handling
Overview of Exception Handling
Exceptions are error conditions that arise when the normal flow
of a code path-that is, a series of method calls on the call stack-is
impractical. Exception handling is an in built mechanism in .NET framework to
detect and handle run time errors. The exceptions are anomalies that occur
during the execution of a program. They can be because of user, logic or system
errors. If a user (programmer) do not provide a mechanism to handle these
anomalies, the .NET run time environment provide a default mechanism, which
terminates the program execution. C# provides three keywords try, catch and
finally to do exception handling. The try encloses the statements that might
throw an exception whereas catch handles an exception if one exists. The
finally can be used for doing any clean up process.
The general form try-catch-finally in C# is shown below:
try
{
// Statement which can cause an exception.
}
catch(Type x)
{
// Statements for handling the exception
}
finally
{
//Any cleanup code
}
If any exception occurs inside the try block, the control
transfers to the appropriate catch block and later to the finally block.
But in C#, both catch and finally blocks are optional. The try
block can exist either with one or more catch blocks or a finally block or with
both catch and finally blocks.
If there is no exception occurred inside the try block, the
control directly transfers to finally block. We can say that the statements
inside the finally block is executed always. Note that it is an error to
transfer control out of a finally block by using break, continue, return or
goto.
In C#, exceptions are nothing but objects of the type Exception.
The Exception is the ultimate base class for any exceptions in C#. The C#
itself provides couple of standard exceptions. Or even the user can create
their own exception classes, provided that this should inherit from either
Exception class or one of the standard derived classes of Exception class like
DivideByZeroExcpetion ot ArgumentException etc.
The modified form of the above program with exception handling
mechanism is as follows: -
//C#: Exception Handling
using System;
class MyClient
{
public static void Main()
{
int x = 0; int div = 0;
try
{
div = 100/x;
Console.WriteLine(“Not executed line”);
}
catch(DivideByZeroException de)
{ Console.WriteLine(“Exception occured”); }
finally
{ Console.WriteLine(“Finally Block”); }
Console.WriteLine(“Result is {0}”,div);
}
}
Multiple Catch Blocks
A try block can throw multiple exceptions, which can handle by
using multiple catch blocks. Remember that more specialized catch block should
come before a generalized one. Otherwise the compiler will show a compilation
error.
//C#: Exception Handling: Multiple catch
using System;
class MyClient
{
public static void Main()
{
int x = 0;
int div = 0;
try
{
div = 100/x;
Console.WriteLine(“Not executed line”);
}
catch(DivideByZeroException de)
{ Console.WriteLine(“DivideByZeroException” ); }
catch(Exception ee)
{ Console.WriteLine(“Exception” ); }
finally
{ Console.WriteLine(“Finally Block”); }
Console.WriteLine(“Result is {0}”,div);
}
}
Catching All Exception
By providing a catch block without a brackets or arguments, we
can catch all exceptions occurred inside a try block. Even we can use a catch
block with an Exception type parameter to catch all exceptions happened inside
the try block since in C#, all exceptions are directly or indirectly inherited
from the Exception class.
//C#: Exception Handling: Handling all exceptions
using System;
class MyClient
{
public static void Main()
{
int x = 0;
int div = 0;
try
{
div = 100/x;
Console.WriteLine(“Not executed line”);
}
catch
{ Console.WriteLine(“oException” );}
Console.WriteLine(“Result is {0}”,div);
}
}
The following program
handles all exception with Exception object.
//C#: Exception Handling:
Handling all exceptions
using System;
class MyClient
{
public static void Main()
{
int x = 0;
int div = 0;
try
{
div = 100/x;
Console.WriteLine(“Not executed line”);
}
catch(Exception e)
{ Console.WriteLine(“oException” );}
Console.WriteLine(“Result is {0}”,div);
}
}
Throwing an Exception
In C#, it is possible to throw an exception programmatically.
The ‘throw’ keyword is used for this purpose. The general form of throwing an
exception is as follows.
throw exception_obj;
For example the following statement throws an ArgumentException
explicitly.
throw new ArgumentException(“Exception”);
Example
//C#: Exception Handling:
using System;
class MyClient
{
public static void Main()
{
try
{
throw new DivideByZeroException(“Invalid Division”);}
catch(DivideByZeroException e)
{ Console.WriteLine(“Exception” ); }
Console.WriteLine(“LAST STATEMENT”);
}
}
Standard Exceptions
There are two types of exceptions: exceptions generated by an
executing program and exceptions generated by the common language runtime.
System.Exception is the base class for all exceptions in C#. Several exception
classes inherit from this class including ApplicationException and
SystemException. These two classes form the basis for most other runtime
exceptions. Other exceptions that derive directly from System.Exception include
IOException, WebException etc.
The common language runtime throws SystemException. The
ApplicationException is thrown by a user program rather than the runtime. The
SystemException includes the ExecutionEngineException, StaclOverFlowException
etc. It is not recommended that we catch SystemExceptions nor is it good
programming practice to throw SystemExceptions in our applications.
·
System.OutOfMemoryException
·
System.NullReferenceException
·
Syste.InvalidCastException
·
Syste.ArrayTypeMismatchException
·
System.IndexOutOfRangeException
·
System.ArithmeticException
·
System.DevideByZeroException
·
System.OverFlowException
User-Defined Exceptions
In C#, it is possible to create our own exception class. But Exception
must be the ultimate base class for all exceptions in C#. So the user-defined
exception classes must inherit from either Exception class or one of its
standard derived classes.
//C#: Exception
Handling: User defined exceptions
using System;
class MyException : Exception
{
public MyException(string str)
{
Console.WriteLine(“User defined exception”);}
}
class MyClient
{
public static void Main()
{
try
{ throw new MyException(“RAJESH”); }
catch(Exception e)
{Console.WriteLine(“Exception cau
Comments
Post a Comment