C# Programming:
OOPs(Object-Oriented Programming)
·
Classes and Objects
·
Class Members
o Properties and Fields
o Methods
o Constructors
o Destructors
o Events
o Nested Classes
·
Access Modifiers and Access Levels
·
Instantiating Classes
·
Static (Shared) Classes and Members
·
Anonymous Types
·
Inheritance
o Overriding Members
·
Interfaces
·
Abstract
·
Generics
·
Extension Methods
·
Delegates
Object-Oriented
Programming is a technique to think a real word in term of objects.
Classes and Objects
--------------------------------------------------------------------------------
The terms class and object are sometimes used
interchangeably, but in fact, classes describe the type of objects, while
objects are usable instances of classes. So, the act of creating an object is
called instantiation. Using the blueprint analogy, a class is a blueprint, and
an object is a building made from that blueprint.
To define a class:
class SampleClass
{ }
Both Visual Basic and C# also provide a light version
of classes called structures that are useful when you need to create large
array of objects and do not want to consume too much memory for that.
To define a structure:
struct SampleStruct
{
}
Class Members
Each class can have different class members that
include properties that describe class data, methods that define class
behavior, and events that provide communication between different classes and
objects.
Properties and Fields
Fields and properties represent information that an
object contains. Fields are like variables because they can be read or set
directly.
To define a field:
class SampleClass{
public
string sampleField;
}
Properties have get and set procedures, which provide
more control on how values are set or returned.
Both C# and Visual Basic allow you either to create a
private field for storing the property value or use so-called auto-implemented
properties that create this field automatically behind the scenes and provide
the basic logic for the property procedures.
To define an auto-implemented property:
class SampleClass{
public int
SampleProperty { get; set; }
}
If you need to perform some additional operations for
reading and writing the property value, define a field for storing the property
value and provide the basic logic for storing and retrieving it:
class SampleClass{
private int
_sample;
public int
Sample
{ // Return the value stored in a field.
get {
return _sample; }
// Store
the value in the field.
set {
_sample = value; }
}
}
Most properties have methods or procedures to both set
and get the property value. However, you can create read-only or write-only
properties to restrict them from being modified or read. In Visual Basic you
can use ReadOnly and WriteOnly keywords. In C#, you can omit the get or set
property method. However, in both Visual Basic and C#, auto-implemented
properties cannot be read-only or write-only.
For more information, see
Ø get
Ø set
Methods
A method is an action that an object can perform.
To define a method of a class:
class SampleClass
{
public int
sampleMethod(string sampleParam)
{ // Insert code here
}
}
A class can have several implementations, or overloads,
of the same method that differ in the number of parameters or parameter types.
To overload a method:
public int sampleMethod(string sampleParam) {};
public int sampleMethod(int sampleParam) {}
In most cases you declare a method within a class
definition. However, both Visual Basic and C# also support extension methods
that allow you to add methods to an existing class outside the actual
definition of the class.
For more information, see:
Ø Methods
Ø Extension Methods
Extension
Methods
Extension methods enable you to "add" methods
to existing types without creating a new derived type, recompiling, or
otherwise modifying the original type. Extension methods are a special kind of
static method, but they are called as if they were instance methods on the
extended type. For client code written in C# and Visual Basic, there is no
apparent difference between calling an extension method and the methods that
are actually defined in a type.
The most common extension methods are the LINQ standard
query operators that add query functionality to the existing
System.Collections.IEnumerable and System.Collections.Generic.IEnumerable(Of T)
types. To use the standard query operators, first bring them into scope with a
using System.Linq directive. Then any type that implements IEnumerable(Of T)
appears to have instance methods such as GroupBy, OrderBy, Average, and so on.
You can see these additional methods in IntelliSense statement completion when
you type "dot" after an instance of an IEnumerable(Of T) type such as
List(Of T) or Array.
The following example shows how to call the standard
query operator OrderBy method on an array of integers. The expression in
parentheses is a lambda expression. Many standard query operators take lambda
expressions as parameters, but this is not a requirement for extension methods.
For more information, see Lambda Expressions (C# Programming Guide).
class ExtensionMethods2
{
static void
Main()
{
int[]
ints = { 10, 45, 15, 39, 21, 26 };
var
result = ints.OrderBy(g => g);
foreach
(var i in result)
{
System.Console.Write(i + " ");
}
}
}
//Output: 10 15 21 26 39 45
Extension methods are defined as static methods but are
called by using instance method syntax. Their first parameter specifies which
type the method operates on, and the parameter is preceded by the this
modifier. Extension methods are only in scope when you explicitly import the
namespace into your source code with a using directive.
The following example shows an extension method defined
for the System.String class. Note that it is defined inside a non-nested,
non-generic static class:
namespace ExtensionMethods
{
public static
class MyExtensions
{
public static int WordCount(this String str)
{
return str.Split(new char[] { ' ', '.', '?' },
StringSplitOptions.RemoveEmptyEntries).Length;
}
}
}
The WordCount extension method can be brought into
scope with this using directive:
using ExtensionMethods;
And it can be called from an application by using this
syntax:
string s = "Hello Extension Methods";
int i = s.WordCount();
In your code you invoke the extension method with
instance method syntax. However, the intermediate language (IL) generated by
the compiler translates your code into a call on the static method. Therefore,
the principle of encapsulation is not really being violated. In fact, extension
methods cannot access private variables in the type they are extending.
For more information, see How to: Implement and Call a
Custom Extension Method (C# Programming Guide).
In general, you will probably be calling extension methods
far more often than implementing your own. Because extension methods are called
by using instance method syntax, no special knowledge is required to use them
from client code. To enable extension methods for a particular type, just add a
using directive for the namespace in which the methods are defined. For
example, to use the standard query operators, add this using directive to your
code:
using System.Linq;
(You may also have to add a reference to
System.Core.dll.) You will notice that the standard query operators now appear
in IntelliSense as additional methods available for most IEnumerable(Of T)
types.
Note
Although standard query operators do not appear in
IntelliSense for String, they are still available.
Binding
Extension Methods at Compile Time
________________________________________
You can use extension methods to extend a class or
interface, but not to override them. An extension method with the same name and
signature as an interface or class method will never be called. At compile
time, extension methods always have lower priority than instance methods
defined in the type itself. In other words, if a type has a method named
Process(int i), and you have an extension method with the same signature, the
compiler will always bind to the instance method. When the compiler encounters
a method invocation, it first looks for a match in the type's instance methods.
If no match is found, it will search for any extension methods that are defined
for the type, and bind to the first extension method that it finds. The
following example demonstrates how the compiler determines which extension
method or instance method to bind to.
Example
________________________________________
The following example demonstrates the rules that the
C# compiler follows in determining whether to bind a method call to an instance
method on the type, or to an extension method. The static class Extensions
contains extension methods defined for any type that implements IMyInterface.
Classes A, B, and C all implement the interface.
The MethodB extension method is never called because
its name and signature exactly match methods already implemented by the
classes.
When the compiler cannot find an instance method with a
matching signature, it will bind to a matching extension method if one exists.
// Define an interface named IMyInterface.
namespace DefineIMyInterface
{
using System;
public
interface IMyInterface
{
// Any
class that implements IMyInterface must define a method
// that
matches the following signature.
void
MethodB();
}
}
// Define extension methods for IMyInterface.
namespace Extensions
{
using System;
using
DefineIMyInterface;
// The
following extension methods can be accessed by instances of any
// class that
implements IMyInterface.
public static
class Extension
{
public
static void MethodA(this IMyInterface myInterface, int i)
{
Console.WriteLine
("Extension.MethodA(this IMyInterface myInterface, int i)");
}
public
static void MethodA(this IMyInterface myInterface, string s)
{
Console.WriteLine
("Extension.MethodA(this IMyInterface myInterface, string
s)");
}
// This method is never called in
ExtensionMethodsDemo1, because each
// of the
three classes A, B, and C implements a method named MethodB
// that
has a matching signature.
public
static void MethodB(this IMyInterface myInterface)
{
Console.WriteLine
("Extension.MethodB(this IMyInterface myInterface)");
}
}
}
// Define three classes that implement IMyInterface,
and then use them to test
// the extension methods.
namespace ExtensionMethodsDemo1
{
using System;
using
Extensions;
using
DefineIMyInterface;
class A :
IMyInterface
{
public
void MethodB() { Console.WriteLine("A.MethodB()"); }
}
class B :
IMyInterface
{
public
void MethodB() { Console.WriteLine("B.MethodB()"); }
public
void MethodA(int i) { Console.WriteLine("B.MethodA(int i)"); }
}
class C :
IMyInterface
{
public
void MethodB() { Console.WriteLine("C.MethodB()"); }
public
void MethodA(object obj)
{
Console.WriteLine("C.MethodA(object obj)");
}
}
class
ExtMethodDemo
{
static
void Main(string[] args)
{
//
Declare an instance of class A, class B, and class C.
A a =
new A();
B b =
new B();
C c =
new C();
//
For a, b, and c, call the following methods:
// -- MethodA with an int argument
// -- MethodA with a string
argument
// -- MethodB with no
argument.
// A
contains no MethodA, so each call to MethodA resolves to
//
the extension method that has a matching signature.
a.MethodA(1); // Extension.MethodA(object, int)
a.MethodA("hello");
// Extension.MethodA(object, string)
// A
has a method that matches the signature of the following call
// to
MethodB.
a.MethodB(); // A.MethodB()
// B
has methods that match the signatures of the following
//
nethod calls.
b.MethodA(1); //
B.MethodA(int)
b.MethodB(); //
B.MethodB()
// B
has no matching method for the following call, but
//
class Extension does.
b.MethodA("hello");
// Extension.MethodA(object, string)
// C
contains an instance method that matches each of the following
//
method calls.
c.MethodA(1); //
C.MethodA(object)
c.MethodA("hello");
// C.MethodA(object)
c.MethodB(); //
C.MethodB()
}
}
}
/* Output:
Extension.MethodA(this IMyInterface myInterface, int i)
Extension.MethodA(this IMyInterface myInterface, string s)
A.MethodB()
B.MethodA(int
i)
B.MethodB()
Extension.MethodA(this IMyInterface myInterface, string s)
C.MethodA(object obj)
C.MethodA(object obj)
C.MethodB()
*/
General
Guidelines
________________________________________
In general, we recommend that you implement extension
methods sparingly and only when you have to. Whenever possible, client code
that must extend an existing type should do so by creating a new type derived
from the existing type. For more information, see Inheritance (C# Programming
Guide).
When using an extension method to extend a type whose
source code you cannot change, you run the risk that a change in the
implementation of the type will cause your extension method to break.
If you do implement extension methods for a given type,
remember the following two points:
• An extension
method will never be called if it has the same signature as a method defined in
the type.
• Extension
methods are brought into scope at the namespace level. For example, if you have
multiple static classes that contain extension methods in a single namespace
named Extensions, they will all be brought into scope by the using Extensions;
directive.
Anonymous Types
Anonymous types provide a convenient way to encapsulate
a set of read-only properties into a single object without having to explicitly
define a type first. The type name is generated by the compiler and is not
available at the source code level. The type of each property is inferred by
the compiler.
You create anonymous types by using the new operator
together with an object initializer. For more information about object
initializers, see Object and Collection Initializers (C# Programming Guide).
The following example shows an anonymous type that is
initialized with two properties named Amount and Message.
var v = new { Amount = 108, Message = "Hello"
};
// Rest the mouse pointer over v.Amount and v.Message
in the following
// statement to verify that their inferred types are
int and string.
Console.WriteLine(v.Amount + v.Message);
Anonymous types typically are used in the select clause
of a query expression to return a subset of the properties from each object in
the source sequence. For more information about queries, see LINQ Query
Expressions (C# Programming Guide).
Anonymous types contain one or more public read-only
properties. No other kinds of class members, such as methods or events, are
valid. The expression that is used to initialize a property cannot be null, an
anonymous function, or a pointer type.
The most common scenario is to initialize an anonymous
type with properties from another type. In the following example, assume that a
class exists that is named Product. Class Product includes Color and Price
properties, together with other properties that you are not interested in.
Variable products is a collection of Product objects. The anonymous type
declaration starts with the new keyword. The declaration initializes a new type
that uses only two properties from Product. This causes a smaller amount of
data to be returned in the query.
If you do not specify member names in the anonymous
type, the compiler gives the anonymous type members the same name as the
property being used to initialize them. You must provide a name for a property
that is being initialized with an expression, as shown in the previous example.
In the following example, the names of the properties of the anonymous type are
Color and Price.
var productQuery =
from prod in
products
select new {
prod.Color, prod.Price };
foreach (var v in productQuery)
{
Console.WriteLine("Color={0}, Price={1}", v.Color, v.Price);}
Typically, when you use an anonymous type to initialize
a variable, you declare the variable as an implicitly typed local variable by
using var. The type name cannot be specified in the variable declaration
because only the compiler has access to the underlying name of the anonymous
type. For more information about var, see Implicitly Typed Local Variables (C#
Programming Guide).
You can create an array of anonymously typed elements
by combining an implicitly typed local variable and an implicitly typed array,
as shown in the following example.
var anonArray = new[] { new { name = "apple",
diam = 4 }, new { name = "grape", diam = 1 }};
Remarks
________________________________________
Anonymous types are class types that derive directly
from object, and that cannot be cast to any type except object. The compiler
provides a name for each anonymous type, although your application cannot
access it. From the perspective of the common language runtime, an anonymous
type is no different from any other reference type.
If two or more anonymous types in the same assembly
have the same number and type of properties, in the same order, the compiler
treats them as the same type. They share the same compiler-generated type
information.
You cannot declare a field, a property, an event, or
the return type of a method as having an anonymous type. Similarly, you cannot
declare a formal parameter of a method, property, constructor, or indexer as
having an anonymous type. To pass an anonymous type, or a collection that
contains anonymous types, as an argument to a method, you can declare the
parameter as type object. However, doing this defeats the purpose of strong typing.
If you must store query results or pass them outside the method boundary,
consider using an ordinary named struct or class instead of an anonymous type.
Because the Equals and GetHashCode methods on anonymous
types are defined in terms of the Equals and GetHashcode methods of the
properties, two instances of the same anonymous type are equal only if all
their properties are equal.
Constructors
Constructors are class methods that are executed
automatically when an object of a given type is created. Constructors usually
initialize the data members of the new object. A constructor can run only once
when a class is created. Furthermore, the code in the constructor always runs
before any other code in a class. However, you can create multiple constructor
overloads in the same way as for any other method.
Constructors are class methods that are executed when
an object of a class or struct is created. They have the same name as the class
or struct, and usually initialize the data members of the new object.
A class or struct may have multiple constructors that
take different arguments. Constructors enable the programmer to set default
values, limit instantiation, and write code that is flexible and easy to read.
If you do not provide a constructor for your object, C#
will create one by default that instantiates the object and sets member
variables to the default values as listed in Default Values Table (C#
Reference). Static classes and structs can also have constructors.
To define a constructor for a class:
public class SampleClass
{
public
SampleClass()
{ // Add code here }
}
For more information, see:
Destructors
Destructors are used to destruct instances of classes.
In the .NET Framework, the garbage collector automatically manages the allocation
and release of memory for the managed objects in your application. However, you
may still need destructors to clean up any unmanaged resources that your
application creates. There can be only one destructor for a class.
For more information about destructors and garbage
collection in the .NET Framework, see Garbage Collection.
Events
Events enable a class or object to notify other classes
or objects when something of interest occurs. The class that sends (or raises)
the event is called the publisher and the classes that receive (or handle) the
event are called subscribers. For more information about events, how they are
raised and handled, see Handling and Raising Events.
• C#
• To declare an
event in a class, use the event (C# Reference) keyword.
• To raise an
event, invoke the event delegate.
• To subscribe
to an event, use the += operator; to unsubscribe from an event, use the -=
operator.
Nested Classes
A class defined within another class is called nested.
By default, the nested class is private.
class Container
{
class Nested
{
// Add
code here.
}
}
To create an instance of the nested class, use the name
of the container class followed by the dot and then followed by the name of the
nested class:
Container.Nested nestedInstance = new
Container.Nested()
Access Modifiers and Access Levels
All classes and class members can specify what access
level they provide to other classes by using access modifiers.
The following access modifiers are available:
Public
The type or member can be accessed by any other code in
the same assembly or another assembly that references it.
Private
The type or member can only be accessed by code in the
same class.
Protected
The type or member can only be accessed by code in the
same class or in a derived class.
Internal
The type or member can be accessed by any code in the
same assembly, but not from another assembly.
Protected internal
The type or member can be accessed by any code in the
same assembly, or by any derived class in another assembly.
For more information, see Access Levels in Visual Basic
and Access Modifiers (C# Programming Guide).
Instantiating Classes
To create an object, you need to instantiate a class,
or create a class instance.
SampleClass sampleObject = new SampleClass();
After instantiating a class, you can assign values to
the instance's properties and fields and invoke class methods.
// Set a property value.
sampleObject.sampleProperty = "Sample
String";
// Call a method.
sampleObject.sampleMethod();
To assign values to properties during the class
instantiation process, use object initializers:
// Set a property value.
SampleClass sampleObject = new SampleClass
{
FirstProperty = "A", SecondProperty = "B" };
For more information, see:
• new Operator
• Object and Collection Initializers
Static
(Shared) Classes and Members
A static (shared in Visual Basic) member of the class
is a property, procedure, or field that is shared by all instances of a class.
To define a static (shared) member:
static class SampleClass
{
public static
string SampleString = "Sample String";
}
To access the static (shared) member, use the name of
the class without creating an object of this class:
Console.WriteLine(SampleClass.SampleString);
Static (shared) classes in C# and modules in Visual
Basic have static (shared) members only and cannot be instantiated. Static
(shared) members also cannot access non-static (non-shared) properties, fields
or methods
For more information, see:
• C#
• static (C# Reference)
Anonymous Types
Anonymous types enable you to create objects without
writing a class definition for the data type. Instead, the compiler generates a
class for you. The class has no usable name and contains the properties you
specify in declaring the object.
To create an instance of an anonymous type:
// sampleObject is an instance of a simple anonymous
type.
var sampleObject =
new {
FirstProperty = "A", SecondProperty = "B" };
For more information, see:
• C#: Anonymous
Types
Inheritance
________________________________________
Inheritance enables you to create a new class that
reuses, extends, and modifies the behavior that is defined in another class.
The class whose members are inherited is called the base class, and the class
that inherits those members is called the derived class. However, all classes
in both C# and Visual Basic implicitly inherit from the Object class that
supports .NET class hierarchy and provides low-level services to all classes.
Note
Managed languages in the .NET Framework do not support
multiple inheritance, i.e. you can specify only one base class for a derived
class.
To inherit from a base class:
class DerivedClass:BaseClass{}
By default all classes can be inherited. However, you
can specify whether a class must not be used as a base class, or create a class
that can be used as a base class only.
To specify that a class cannot be used as a base class:
public sealed class A { }
To specify that a class can be used as a base class
only and cannot be instantiated:
public abstract class B { }
For more information, see:
• sealed
• abstract
Sealed
When applied to a class, the sealed modifier prevents
other classes from inheriting from it. In the following example, class B
inherits from class A, but no class can inherit from class B.
class A
{}
sealed class
B : A {}
You can also use the sealed modifier on a method or
property that overrides a virtual method or property in a base class. This
enables you to allow classes to derive from your class and prevent them from
overriding specific virtual methods or properties.
Example
________________________________________
In the following example, Z inherits from Y but Z
cannot override the virtual function F that is declared in X and sealed in Y.
class X
{
protected
virtual void F() { Console.WriteLine("X.F"); }
protected
virtual void F2() { Console.WriteLine("X.F2"); }
}
class Y : X
{ sealed protected override void F() {
Console.WriteLine("Y.F"); }
protected
override void F2() { Console.WriteLine("X.F3"); }
}
class Z : Y
{
//
Attempting to override F causes compiler error CS0239.
//
protected override void F() { Console.WriteLine("C.F"); }
//
Overriding F2 is allowed.
protected
override void F2() { Console.WriteLine("Z.F2"); }
}
When you define new methods or properties in a class,
you can prevent deriving classes from overriding them by not declaring them as
virtual.
It is an error to use the abstract modifier with a
sealed class, because an abstract class must be inherited by a class that
provides an implementation of the abstract methods or properties.
When applied to a method or property, the sealed
modifier must always be used with override.
Because structs are implicitly sealed, they cannot be
inherited.
For more information, see Inheritance (C# Programming
Guide).
For more examples, see Abstract and Sealed Classes and
Class Members (C# Programming Guide).
sealed class
SealedClass
{
public
int x;
public
int y;
}
class
SealedTest2
{
static
void Main()
{
SealedClass sc = new SealedClass();
sc.x
= 110;
sc.y
= 150;
Console.WriteLine("x = {0}, y = {1}", sc.x, sc.y);
}
} // Output: x = 110, y = 150
In the previous example, you might try to inherit from
the sealed class by using the following statement:
class MyDerivedC: SealedClass {} // Error
The result is an error message:
'MyDerivedC' cannot inherit from sealed class
'SealedClass'.
abstract (C# Reference)
The abstract modifier indicates that the thing being
modified has a missing or incomplete implementation. The abstract modifier can
be used with classes, methods, properties, indexers, and events. Use the
abstract modifier in a class declaration to indicate that a class is intended
only to be a base class of other classes. Members marked as abstract, or
included in an abstract class, must be implemented by classes that derive from
the abstract class.
Example
________________________________________
In this example, the class Square must provide an
implementation of Area because it derives from ShapesClass:
C#
Copy
abstract class ShapesClass
{
abstract
public int Area();
}
class Square : ShapesClass
{ int side =
0;
public
Square(int n)
{ side = n;
}
// Area
method is required to avoid
// a
compile-time error.
public
override int Area()
{
return
side * side;
}
static void
Main()
{
Square sq
= new Square(12);
Console.WriteLine("Area of the square = {0}", sq.Area());
}
interface I
{
void M();
} abstract class C : I
{ public abstract void M();
}
}
// Output: Area of the square = 144
Abstract classes have the following features:
• An abstract
class cannot be instantiated.
• An abstract
class may contain abstract methods and accessors.
• It is not
possible to modify an abstract class with the sealed (C# Reference) modifier
because the two modifers have opposite meanings. The sealed modifier prevents a
class from being inherited and the abstract modifier requires a class to be
inherited.
• A
non-abstract class derived from an abstract class must include actual
implementations of all inherited abstract methods and accessors.
Use the abstract modifier in a method or property
declaration to indicate that the method or property does not contain
implementation.
Abstract methods have the following features:
• 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 curly braces ({ }) following the signature. For example:
public abstract void MyMethod();
The implementation is provided by an overriding
methodoverride (C# Reference), 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.
For more information about abstract classes, see
Abstract and Sealed Classes and Class Members (C# Programming Guide) and
Abstract Class Design.
An abstract class must provide implementation for all
interface members.
An abstract class that implements an interface might
map the interface methods onto abstract methods. For example:
interface I
{
void M();
}
abstract class C : I
{
public
abstract void M();
}
In this example, the class DerivedClass is derived from
an abstract class BaseClass. The abstract class contains an abstract method,
AbstractMethod, and two abstract properties, X and Y.
abstract
class BaseClass // Abstract class
{
protected
int _x = 100;
protected
int _y = 150;
public
abstract void AbstractMethod(); //
Abstract method
public
abstract int X { get; }
public
abstract int Y { get; }
}
class
DerivedClass : BaseClass
{
public override void AbstractMethod()
{
_x++;
_y++;
}
public
override int X // overriding property
{
get
{
return _x + 10;
}
}
public override int Y // overriding property
{
get
{
return _y + 10;
}
}
static
void Main()
{
DerivedClass o = new DerivedClass();
o.AbstractMethod();
Console.WriteLine("x = {0}, y = {1}", o.X, o.Y);
}
}
// Output: x
= 111, y = 161
In the preceding example, if you attempt to instantiate
the abstract class by using a statement like this:
BaseClass bc = new BaseClass(); // Error
you will get an error saying that the compiler cannot
create an instance of the abstract class 'BaseClass'.
Overriding Members
By default, a derived class inherits all members from
its base class. If you want to change the behavior of the inherited member, you
need to override it. That is, you can define a new implementation of the
method, property or event in the derived class.
The following modifiers are used to control how
properties and methods are overridden:
C# Modifier
virtual (C#
Reference)
Allows a class member to be overridden in a derived
class.
override (C#
Reference)
Overrides a virtual (overridable) member defined in the
base class.
Not
supported Prevents a member from being
overridden in an inheriting class.
abstract (C#
Reference)
Requires that a class member to be overridden in the
derived class.
new Modifier
(C# Reference)
Hides a member inherited from a base class
Interfaces
Interfaces, like classes, define a set of properties,
methods, and events. But unlike classes, interfaces do not provide
implementation. They are implemented by classes, and defined as separate
entities from classes. An interface represents a contract, in that a class that
implements an interface must implement every aspect of that interface exactly
as it is defined.
To define an interface:
interface ISampleInterface
{
void
doSomething();
}
To implement an interface in a class:
class SampleClass : ISampleInterface
{ void
ISampleInterface.SampleMethod()
{ // Method implementation. }
}
For more information, see:
• Interfaces
• interface
Generics
________________________________________
Classes, structures, interfaces and methods in the .NET
Framework can type parameters that define types of objects that they can store
or use. The most common example of generics is a collection, where you can
specify the type of objects to be stored in a collection.
To define a generic class:
Public class SampleGeneric<T>
{ public T
Field;}
To create an instance of a generic class:
SampleGeneric<string> sampleObject = new
SampleGeneric<string>();
sampleObject.Field = "Sample string";
For more information, see:
• Generics in the .NET Framework
• Generics (C# Programming Guide)
Generics in the .NET Framework
Generics let you tailor a method, class, structure, or
interface to the precise data type it acts upon. For example, instead of using
the Hashtable class, which allows keys and values to be of any type, you can
use the Dictionary(Of TKey, TValue) generic class and specify the type allowed
for the key and the type allowed for the value. Among the benefits of generics
are increased code reusability and type safety.
This topic provides an overview of generics in the .NET
Framework and a summary of generic types or methods. It contains the following
sections:
• Defining and Using Generics
• Generics Terminology
• Class Library and Language Support
• Nested Types and Generics
• Related Topics
• Reference
Defining and Using
Generics
________________________________________
Generics are classes, structures, interfaces, and
methods that have placeholders (type parameters) for one or more of the types
that they store or use. A generic collection class might use a type parameter
as a placeholder for the type of objects that it stores; the type parameters
appear as the types of its fields and the parameter types of its methods. A
generic method might use its type parameter as the type of its return value or
as the type of one of its formal parameters. The following code illustrates a
simple generic class definition.
public class Generic<T>
{
public T
Field;
}
When you create an instance of a generic class, you
specify the actual types to substitute for the type parameters. This
establishes a new generic class, referred to as a constructed generic class,
with your chosen types substituted everywhere that the type parameters appear.
The result is a type-safe class that is tailored to your choice of types, as
the following code illustrates.
public static void Main()
{
Generic<string> g = new Generic<string>();
g.Field =
"A string";
//...
Console.WriteLine("Generic.Field = \"{0}\"", g.Field);
Console.WriteLine("Generic.Field.GetType() = {0}",
g.Field.GetType().FullName);
}
Generics
Generics were added to version 2.0 of the C# language
and the common language runtime (CLR). Generics introduce to the .NET Framework
the concept of type parameters, which make it possible to design classes and
methods that defer the specification of one or more types until the class or
method is declared and instantiated by client code. For example, by using a
generic type parameter T you can write a single class that other client code
can use without incurring the cost or risk of runtime casts or boxing
operations, as shown here:
// Declare the generic class.
public class GenericList<T>
{
void Add(T
input) { }
}
class TestGenericList
{
private class
ExampleClass { }
static void
Main()
{
//
Declare a list of type int.
GenericList<int> list1 = new GenericList<int>();
//
Declare a list of type string.
GenericList<string> list2 = new GenericList<string>();
//
Declare a list of type ExampleClass.
GenericList<ExampleClass> list3 = new
GenericList<ExampleClass>();
}
}
Generics
Overview
________________________________________
• Use generic
types to maximize code reuse, type safety, and performance.
• The most
common use of generics is to create collection classes.
• The .NET
Framework class library contains several new generic collection classes in the
System.Collections.Generic namespace. These should be used whenever possible
instead of classes such as ArrayList in the System.Collections namespace.
• You can
create your own generic interfaces, classes, methods, events and delegates.
• Generic
classes may be constrained to enable access to methods on particular data
types.
• Information
on the types that are used in a generic data type may be obtained at run-time
by using reflection
Benefits of Generics
Generics provide the solution to a limitation in earlier
versions of the common language runtime and the C# language in which
generalization is accomplished by casting types to and from the universal base
type Object. By creating a generic class, you can create a collection that is
type-safe at compile-time.
The limitations of using non-generic collection classes
can be demonstrated by writing a short program that uses the ArrayList
collection class from the .NET Framework class library. ArrayList is a highly
convenient collection class that can be used without modification to store any
reference or value type.
// The .NET Framework 1.1 way to create a list:
System.Collections.ArrayList list1 = new
System.Collections.ArrayList();
list1.Add(3);
list1.Add(105);
System.Collections.ArrayList list2 = new System.Collections.ArrayList();
list2.Add("It is raining in Redmond.");
list2.Add("It is snowing in the mountains.");
But this convenience comes at a cost. Any reference or
value type that is added to an ArrayList is implicitly upcast to Object. If the
items are value types, they must be boxed when they are added to the list, and
unboxed when they are retrieved. Both the casting and the boxing and unboxing
operations decrease performance; the effect of boxing and unboxing can be very
significant in scenarios where you must iterate over large collections.
The other limitation is lack of compile-time type
checking; because an ArrayList casts everything to Object, there is no way at
compile-time to prevent client code from doing something such as this:
System.Collections.ArrayList list = new
System.Collections.ArrayList();
// Add an integer to the list.
list.Add(3);
// Add a string to the list. This will compile, but may
cause an error later.
list.Add("It is raining in Redmond.");
int t = 0;
// This causes an InvalidCastException to be returned.
foreach (int x in list)
{
t += x;
}
Although perfectly acceptable and sometimes intentional
if you are creating a heterogeneous collection, combining strings and ints in a
single ArrayList is more likely to be a programming error, and this error will
not be detected until runtime.
In versions 1.0 and 1.1 of the C# language, you could
avoid the dangers of generalized code in the .NET Framework base class library
collection classes only by writing your own type specific collections. Of
course, because such a class is not reusable for more than one data type, you
lose the benefits of generalization, and you have to rewrite the class for each
type that will be stored.
What ArrayList and other similar classes really need is
a way for client code to specify, on a per-instance basis, the particular data
type that they intend to use. That would eliminate the need for the upcast to
T:System.Object and would also make it possible for the compiler to do type checking.
In other words, ArrayList needs a type parameter. That is exactly what generics
provide. In the generic List(Of T) collection, in the
N:System.Collections.Generic namespace, the same operation of adding items to
the collection resembles this:
// The .NET Framework 2.0 way to create a list
List<int> list1 = new List<int>();
// No boxing, no casting:
list1.Add(3);
// Compile-time error:
// list1.Add("It is raining in Redmond.");
For client code, the only added syntax with List(Of T)
compared to ArrayList is the type argument in the declaration and
instantiation. In return for this slightly more coding complexity, you can
create a list that is not only safer than ArrayList, but also significantly
faster, especially when the list items are value types.
Delegates
________________________________________
A delegate is a type that defines a method signature,
and can provide a reference to any method with a compatible signature. You can
invoke (or call) the method through the delegate. Delegates are used to pass
methods as arguments to other methods.
Note
Event handlers are nothing more than methods that are
invoked through delegates. For more information about using delegates in event
handling, see Events and Delegates.
To create a delegate:
public delegate void SampleDelegate(string str);
To create a reference to a method that matches the
signature specified by the delegate:
class SampleClass
{ // Method
that matches the SampleDelegate signature.
public static
void sampleMethod(string message)
{ // Add code
here.}
// Method
that instantiates the delegate.
void
SampleDelegate()
{ SampleDelegate sd = sampleMethod;
sd("Sample string");
}
}
Polymorphism
Through inheritance, a class can be used as more than
one type; it can be used as its own type, any base types, or any interface type
if it implements interfaces. This is called polymorphism. In C#, every type is
polymorphic. Types can be used as their own type or as a Object instance,
because any type automatically treats Object as a base type.
Polymorphism is important not only to the derived
classes, but to the base classes as well. Anyone using the base class could, in
fact, be using an object of the derived class that has been cast to the base
class type. Designers of a base class can anticipate the aspects of their base
class that are likely to change for a derived type. For example, a base class
for cars might contain behavior that is subject to change when the car in
question is a minivan or a convertible. A base class can mark those class
members as virtual, allowing derived classes representing convertibles and
minivans to override that behavior.
For more information, see Inheritance.
What is Polymorphism?
What is Polymorphism?
Polymorphism means same operation may behave differently on different classes.
Example of Compile Time Polymorphism: Method Overloading
Example of Run Time Polymorphism: Method Overriding
Example of Compile Time Polymorphism
Method Overloading
- Method with same name but with different arguments is called method overloading.
- Method Overloading forms compile-time polymorphism.
- Example of Method Overloading:
class A1
{
void hello()
{ Console.WriteLine(“Hello”); }
void hello(string s)
{ Console.WriteLine(“Hello {0}”,s); }
}
Example of Run Time Polymorphism
Method Overriding
- Method overriding occurs when child class declares a method that has the same type arguments as a method declared by one of its superclass.
- Method overriding forms Run-time polymorphism.
- Note: By default functions are not virtual in C# and so you need to write “virtual” explicitly. While by default in Java each function are virtual.
- Example of Method Overriding:
Class parent
{
virtual void hello()
{ Console.WriteLine(“Hello from Parent”); }
}
Class child : parent
{
override void hello()
{ Console.WriteLine(“Hello from Child”); }
}
static void main()
{
parent objParent = new child();
objParent.hello();
}
//Output
Hello from Child.
Polymorphism
Overview
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:
C#
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; }
}
}
When the new keyword is used, the new class members are
called instead of the base class members that have been replaced. Those base
class members are called hidden members. Hidden class members can still be
called if an instance of the derived class is cast to an instance of the base
class. For example:
C#
DerivedClass B = new DerivedClass();
B.DoWork(); //
Calls the new method.
BaseClass A = (BaseClass)B;
A.DoWork(); //
Calls the old method.
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 the override keyword, instead of new, to replace the base class
implementation with its own. For example:
C#
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; }
}
}
Fields cannot be virtual; only methods, properties,
events and indexers can be virtual. When a derived class overrides a virtual
member, that member is called even when an instance of that class is being
accessed as an instance of the base class. For example:
C#
DerivedClass B = new DerivedClass();
B.DoWork(); //
Calls the new method.
BaseClass A = (BaseClass)B;
A.DoWork(); //
Also calls the new method.
Virtual
methods and
properties allow you to plan ahead for future expansion. Because a virtual
member is called regardless of which type the caller is using, it gives derived
classes the option to completely change the apparent behavior of the base
class.
Virtual members remain virtual indefinitely, no matter
how many classes have been declared between the class that originally declared
the virtual member. If class A declares a virtual member, and class B derives
from A, and class C derives from B, class C inherits the virtual member, and
has the option to override it, regardless of whether class B declared an
override for that member. For example:
C#
public class A
{
public
virtual void DoWork() { }
}
public class B : A
{
public
override void DoWork() { }
}
C#
public class C : B
{
public
override void DoWork() { }
}
A derived class can stop virtual inheritance by
declaring an override as sealed. This requires putting the sealed keyword
before the override keyword in the class member declaration. For example:
C#
public class C : B
{
public sealed
override void DoWork() { }
}
In the previous example, the method DoWork is no longer
virtual to any class derived from C. It is still virtual for instances of C,
even if they are cast to type B or type A. Sealed methods can be replaced by
derived classes using the new keyword, as the following example shows:
C#
public class D : C
{
public new
void DoWork() { }
}
In this case, if DoWork is called on D using a variable
of type D, the new DoWork is called. If a variable of type C, B, or A is used
to access an instance of D, a call to DoWork will follow the rules of virtual
inheritance, routing those calls to the implementation of DoWork on class C.
A derived class that has replaced or overridden a
method or property can still access the method or property on the base class
using the base keyword. For example:
C#
public class A
{
public
virtual void DoWork() { }
}
public class B : A
{
public
override void DoWork() { }
}
C#
public class C : B
{
public
override void DoWork()
{
// Call
DoWork on B to get B's behavior:
base.DoWork();
// DoWork
behavior specific to C goes here:
// ...
}
}
There are two types of polymorphism
1.runtime
2.compiletime
to achieve the runtime polymorphism there are three
ways
1.Function
overloading
2.Operator
Overloading
3.Constructor
Overloading
When a message can be processed in different ways is
called polymorphism. Polymorphism means many forms.
Polymorphism is one of the fundamental concepts of OOP.
Polymorphism
provides following features:
• It allows you
to invoke methods of derived class through base class reference during runtime.
• It has the
ability for classes to provide different implementations of methods that are
called through the same name.
Polymorphism
is of two types:
1. Compile time polymorphism/Overloading
2. Runtime polymorphism/Overriding
Compile Time Polymorphism
Compile time polymorphism is method and operators
overloading. It is also called early binding.
In method overloading method performs the different
task at the different input parameters.
Runtime Time Polymorphism
Runtime time polymorphism is done using inheritance and
virtual functions. Method overriding is called runtime polymorphism. It is also
called late binding.
When overriding a method, you change the behavior of
the method for the derived class.
Overloading a method simply involves having another method with the same
prototype.
Caution: Don't confused method overloading with method
overriding, they are different, unrelated concepts. But they sound similar.
Method overloading has nothing to do with inheritance
or virtual methods.
Following are examples of methods having different
overloads:
void area(int side);
void area(int l, int b);
void area(float radius);
Practical example of Method Overloading (Compile Time
Polymorphism)
using System;
namespace method_overloading
{
class Program
{
public
class Print
{
public void display(string name)
{
Console.WriteLine("Your name is : " + name);
}
public void display(int age, float marks)
{
Console.WriteLine("Your age is : " + age);
Console.WriteLine("Your marks are :" + marks);
}
}
static
void Main(string[] args)
{
Print
obj = new Print();
obj.display("George");
obj.display(34, 76.50f);
Console.ReadLine();
}
}
}
Note: In the code if you observe display method is
called two times. Display method will work according to the number of
parameters and type of parameters.
When
and why to use method overloading
Use method overloading in situation where you want a
class to be able to do something, but there is more than one possibility for
what information is supplied to the method that carries out the task.
You should consider overloading a method when you for
some reason need a couple of methods that take different parameters, but
conceptually do the same thing.
Method
Overloading showing many forms.
using System;
namespace method_overloading_polymorphism
{
class Program
{
public
class Shape
{
public void Area(float r)
{
float a = (float)3.14 * r;
// here we have used funtion overload with 1 parameter.
Console.WriteLine("Area of a circle: {0}",a);
}
public void Area(float l, float b)
{
float x = (float)l* b;
// here we have used funtion overload with 2 parameters.
Console.WriteLine("Area of a rectangle: {0}",x);
}
public void Area(float a, float b, float c)
{
float s = (float)(a*b*c)/2;
// here we have used funtion overload with 3 parameters.
Console.WriteLine("Area of a circle: {0}", s);
}
}
static
void Main(string[] args)
{
Shape
ob = new Shape();
ob.Area(2.0f);
ob.Area(20.0f,30.0f);
ob.Area(2.0f,3.0f,4.0f);
Console.ReadLine();
}
}
}
Things to keep in mind while method overloading
If you use overload for method, there are couple of
restrictions that the compiler imposes.
The rule is that overloads must be different in their
signature, which means the name and the number and type of parameters.
There is no limit to how many overload of a method you
can have. You simply declare them in a class, just as if they were different
methods that happened to have the same name.
Difference between Struct and Class
Struct are Value type and are stored on stack, while Class are Reference type and are stored on heap.
Struct “do not support” inheritance, while class supports inheritance. However struct can implements interface.
Struct should be used when you want to use a small data structure, while Class is better choice for complex data structure.
No comments:
Post a Comment