Anda di halaman 1dari 41

1.

Data Types
A Variable is a named cell of memory used for data storage. A
Variable value can be changed anytime. Every variable must have
a type and this type must be set before it is used. Qualifying a
variable with a type is called as declaration of variable. The type of
a variable is the most important aspect and it defines the behavior
of variable. All variables can be divided into seven main categories
depending on the context of usage:

1. Static variables
2. Variable of instance
3. Array's elements
4. Parameters given by reference
5. Parameters given by value
6. Returned values
7. Local variables.

Static Variables will be alive throughout the life of a program. It


can be declared using static modifier.

An Instance variable is a variable declared without static


modifier. Usually it is declared inside a class or structure definition.

Parameter Values can be viewed as input parameters into


methods:

public static void Sum(int a, int b)


{
Console.WriteLine("The sum of elements {0} and {1} is
{2}",a,b,a + b);
}

This code writes in console values of variables a, b and their


summary value. Now if the values of these parameters are
modified inside the method, this change will not be reflected inside
the main function. It is because the compiler creates copies of
them when it passes them as value types. This ensures that their
original values are not modified.

Instead if one wants to modify the parameter variables inside the


function, C# has something called Reference variables. Reference
variables also have a modifier out which can be used before their
type.

public static void SumRef(ref int a, ref int b)


{
a = 4;
b = 6;
Console.WriteLine("The sume of elements {0} and {1} is
{2}",a,b,a + b);
}

Now this method modifies the value of variables a and b with


values 4 and 6. These values are retained even after the execution
of the function gets completed.
If the parameters need to be returned then they can be
qualified with out modifier or as returned parameter in method
definition. Here is an example of both of them, in which both of
them return the same value:

public static int SumOut(int a, int b, out int sum1)


{

sum1 = a+b;
Console.WriteLine("The sum1 of elements {0} and {1} is
{2}",a,b,a+b);
return sum1;

In main function it must be called in the next manner:

int sume ;
sume = SumeOut(2,2, out sume);

Constants in C#:

Constant type of data cannot be changed. To declare a constant


the keyword const is used. An example for the constant
declaration is: const double PI = 3.1415;

Values types in C#:

Value type stores real data. When the data are queried by different
function a local copy of it these memory cells are created. It
guarantees that changes made to our data in one function don't
change them in some other function. Let see at a simple example:

public class IntClass


{
public int I = 1;
}

Here we have simple class that contains only one public data field
of integer type. Now have a look on its usage in main function:

static void Main(string[] args)


{
// test class
int i = 10;
int j = i;
j = 11;
IntClass ic1 = new IntClass();
IntClass ic2 = ic1;
ic2.I = 100;

Console.WriteLine("value of i is {0} and j is {1}",i,j);


Console.WriteLine();
Console.WriteLine("value of ic1.I is {0} and ic2.I is
{1}",ic1.I,ic2.I);
Console.WriteLine();
}

Reference Types in C#:

In the above example, assume that First we have two value type
i and j. Also assume that the second variable is initialized with the
value of the first one. It creates new copy in memory and after it
the values of these variables will be next:

i = 10;
j = i;

There are a few more things written in the above example for
explaining the Reference Types in C#. At first, the variable ic1 of
IntClass is created using dynamic memory allocation. Then we
initialize the variable ic2 with value of ic1. This makes both the
variables ic1 and ic2 referring to the same address. If we change a
value of ic2, it automatically changes the value of ic1.
Enumerated types can be used to create some set of identifiers
that can have values of simple type. Let us see at example of
enum type:

public enum Days


{

Monday,
Tuesday,
Wensday,
Thursday,
Friday,
Saturday,
Sunday

using System;

// declares the enum


public enum Volume
{
Low,
Medium,
High
}

// demonstrates how to use the enum

class EnumSwitch
{
static void Main()
{
// create and initialize
// instance of enum type
Volume myVolume = Volume.Medium;

// make decision based


// on enum value
switch (myVolume)
{
case Volume.Low:
Console.WriteLine("The volume has been turned Down.");
break;
case Volume.Medium:
Console.WriteLine("The volume is in the middle.");
break;
case Volume.High:
Console.WriteLine("The volume has been turned up.");
break;
}
Console.ReadLine();
}
}

Properties and Fields

Fields and properties represent information that an object contains. Fields are like
variables because they can be read or set directly

using System;

public class PropertyHolder


{
private int someProperty = 0;

public int SomeProperty


{
get
{
return someProperty;
}
set
{
someProperty = value;
}
}
}

public class PropertyTester


{
public static int Main(string[] args)
{
PropertyHolder propHold = new PropertyHolder();

propHold.SomeProperty = 5;

Console.WriteLine("Property Value: {0}",


propHold.SomeProperty);

return 0;
}
}

Inheritance
When we need a class that has some properties and methods common to a previously
defined class, we can inherit the new class from the previously defined class. This
way, we need to define only those properties and methods of the new class. The
common properties and methods will be inherited from the old class.

The syntax for creating the derived class is as follows:

public class derived-class-name : base-class-name


{
//members of the derived class
}

Type member access modifiers control what code has access to a


specified type member.
Access Modifier Description (who can access)
Only members within the same type. (default for
private
type members)
protected Only derived types.
Only code within the same assembly. Can also be
internal code external to object as long as it is in the same
assembly. (default for types)
Either code from derived type or code in the same
protected internal
assembly. Combination of protected OR internal.
Any code. No inheritance, external type, or external
public
assembly restrictions.
Derived SavingsAccount Class Using protected Members of its Base
Class: SavingsAccount.cs

using System;

class BankAccountPrivate
{
private string m_name;

public string CustomerName


{
get { return m_name; }
set { m_name = value; }
}
}

using System;

class BankAccountProtected
{
public void CloseAccount()
{
ApplyPenalties();
CalculateFinalInterest();
DeleteAccountFromDB();
}

protected virtual void ApplyPenalties()


{
// deduct from account
}

protected virtual void CalculateFinalInterest()


{
// add to account
}

protected virtual void DeleteAccountFromDB()


{
// send notification to data entry personnel
}
}

using System;

class SavingsAccount : BankAccountProtected


{
protected override void ApplyPenalties()
{
Console.WriteLine("Savings Account Applying Penalties");
}

protected override void CalculateFinalInterest()


{
Console.WriteLine("Savings Account Calculating Final Interest");
}

protected override void DeleteAccountFromDB()


{
base.DeleteAccountFromDB();
Console.WriteLine("Savings Account Deleting Account from DB");
}
}

Polymorphism
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; }
}
}

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:

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:

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:

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:

public class A
{
public virtual void DoWork() { }
}
public class B : A
{
public override void DoWork() { }
}

A Base Class With a Virtual Method: DrawingObject.cs

using System;

public class DrawingObject


{
public virtual void Draw()
{
Console.WriteLine("I'm just a generic drawing object.");
}
}

Listing 9-1 shows the DrawingObject class. This will be the base class
for other objects to inherit from. It has a single method named Draw().
The Draw() method has a virtual modifier. The virtual modifier indicates
to derived classes that they can override this method. The Draw() method
of the DrawingObject class performs a single action of printing the
statement, "I'm just a generic drawing object.", to the console.

Listing 9-2. Derived Classes With Override Methods: Line.cs, Circle.cs,


and Square.cs

using System;

public class Line : DrawingObject


{
public override void Draw()
{
Console.WriteLine("I'm a Line.");
}
}

public class Circle : DrawingObject


{
public override void Draw()
{
Console.WriteLine("I'm a Circle.");
}
}

public class Square : DrawingObject


{
public override void Draw()
{
Console.WriteLine("I'm a Square.");
}
}

Listing 9-2 shows three classes. These classes inherit the DrawingObject
class. Each class has a Draw() method and each Draw() method has an
override modifier. The override modifier allows a method to override the
virtual method of its base class at run-time. The override will happen
only if the class is referenced through a base class reference. Overriding
methods must have the same signature, name and parameters, as the
virtual base class method it is overriding.

Listing 9-3. Program Implementing Polymorphism: DrawDemo.cs


using System;

public class DrawDemo


{
public static int Main( )
{
DrawingObject[] dObj = new DrawingObject[4];

dObj[0] = new Line();


dObj[1] = new Circle();
dObj[2] = new Square();
dObj[3] = new DrawingObject();

foreach (DrawingObject drawObj in dObj)


{
drawObj.Draw();
}

return 0;
}
}

Abstract class and sealed class


Classes can be declared as abstract. This is accomplished by putting the keyword abstract before the
keyword class in the class definition. For example:

public abstract class A


{
// Class members here.
}
An abstract class cannot be instantiated. The purpose of an abstract class is to provide a common
definition of a base class that multiple derived classes can share. For example, a class library may
define an abstract class that is used as a parameter to many of its functions, and require
programmers using that library to provide their own implementation of the class by creating a derived
class.

Abstract classes may also define abstract methods. This is accomplished by adding the keyword
abstract before the return type of the method. For example:

public abstract class A


{
public abstract void DoWork(int i);
}
Abstract methods have no implementation, so the method definition is followed by a semicolon
instead of a normal method block. Derived classes of the abstract class must implement all abstract
methods. When an abstract class inherits a virtual method from a base class, the abstract class can
override the virtual method with an abstract method. For example:

// compile with: /target:library


public class D
{
public virtual void DoWork(int i)
{
// Original implementation.
}
}

public abstract class E : D


{
public abstract override void DoWork(int i);
}

public class F : E
{
public override void DoWork(int i)
{
// New implementation.
}
}
If a virtual method is declared abstract, it is still virtual to any class inheriting from the abstract class.
A class inheriting an abstract method cannot access the original implementation of the method—in the
previous example, DoWork on class F cannot call DoWork on class D. In this way, an abstract class
can force derived classes to provide new method implementations for virtual methods

Sealed Classes and Class Members


Classes can be declared as sealed. This is accomplished by putting the keyword sealed before the
keyword class in the class definition. For example:

public sealed class D


{
// Class members here.
}
A sealed class cannot be used as a base class. For this reason, it cannot also be an abstract class.
Sealed classes are primarily used to prevent derivation. Because they can never be used as a base
class, some run-time optimizations can make calling sealed class members slightly faster.
Interfaces
An interface looks similar to a class. It contains methods and properties but has no
implementation. We do not specify what the methods and properties will actually do.
The reason is that classes and structures inherit them and they provide the actual
implementation for each interface member defined.

The syntax for defining interface is as follows:

interface interface-name
{
//members of the interface
}

Commonly, the name of the interface starts with the prefix `I' (though it is not a strict
rule). The following example illustrates how to define an interface:

interface IMyInterface { void SomeMethod(); }

Notice that the SomeMethod() method does not have any implementation. This is
because we do not use an interface directly in our program. We need a class or
structure that will implement the interface:

class MyClass : IMyInterface { public void SomeMethod()


{ Console.WriteLine("This is a method"); } }

Here, the class MyClass implements the SomeMethod() method of the interface. An
interface is a type of contract that specifies that the class or structure inheriting the
interface must implement its members.

Interface is an abstract type. It is used only for declaring type with some abstract members. It
means members without implementations. Please, have a look at piece of code with a
declaration for a simple interface:

The members of interface can be methods, properties and indexers.

interface IMyInterface
{
void MethodToImplement();
}

class InterfaceImplementer : IMyInterface


{
static void Main()
{
InterfaceImplementer iImp = new InterfaceImplementer();
iImp.MethodToImplement();
}

public void MethodToImplement()


{
Console.WriteLine("MethodToImplement() called.");
}
}

Multiple Inheritance using C# interfaces:

Next feature that obviously needs to be explained is multiple inheritance using c# interfaces.
This can be done using child class that inherits from any number of c# interfaces. The
inheritance can also happen with a combination of a C# .Net class and c# interfaces. Now let
us see a small piece of code that demonstrate us multiple inheritance using only interfaces as
parent data types.

class ClonableNode : INode,ICloneable


{

public object Clone()


{
return null;
}

// INode members
}

The above example created a class ClonableNode. It implements all the functionality of
INode interface in the same way as it was done in Node class. Also it realizes Clone method
only one item of IClonable interface of .NET library.

Abstract Class vs. Interface


• An abstract class may contain complete or incomplete methods. Interfaces can
contain only the signature of a method but no body. Thus an abstract class can
implement methods but an interface can not implement methods.
• An abstract class can contain fields, constructors, or destructors and
implement properties. An interface can not contain fields, constructors, or
destructors and it has only the property's signature but no implementation.
• An abstract class cannot support multiple inheritance, but an interface can
support multiple inheritance. Thus a class may inherit several interfaces but
only one abstract class.
• A class implementing an interface has to implement all the methods of the
interface, but the same is not required in the case of an abstract Class.
• Various access modifiers such as abstract, protected, internal, public, virtual,
etc. are useful in abstract Classes but not in interfaces.
• Abstract classes are faster than interfaces.

Static Classes and Static Class Members


Static classes and class members are used to create data and functions that can be accessed without
creating an instance of the class. Static class members can be used to separate data and behavior
that is independent of any object identity: the data and functions do not change regardless of what
happens to the object. Static classes can be used when there is no data or behavior in the class that
depends on object identity.

Static Classes
A class can be declared static, indicating that it contains only static members. It is not possible to
create instances of a static class using the new keyword. Static classes are loaded automatically by
the .NET Framework common language runtime (CLR) when the program or namespace containing
the class is loaded.

Use a static class to contain methods that are not associated with a particular object. For example, it
is a common requirement to create a set of methods that do not act on instance data and are not
associated to a specific object in your code. You could use a static class to hold those methods.

The main features of a static class are:

• They only contain static members.

• They cannot be instantiated.

• They are sealed.

• They cannot contain Instance Constructors (C# Programming Guide).

Creating a static class is therefore much the same as creating a class that contains only static
members and a private constructor. A private constructor prevents the class from being instantiated.

The advantage of using a static class is that the compiler can check to make sure that no instance
members are accidentally added. The compiler will guarantee that instances of this class cannot be
created.

Static classes are sealed and therefore cannot be inherited. Static classes cannot contain a
constructor, although it is still possible to declare a static constructor to assign initial values or set up
some static state.

When to Use Static Classes


Suppose you have a class CompanyInfo that contains the following methods to get information
about the company name and address.

class CompanyInfo
{
public string GetCompanyName() { return "CompanyName"; }
public string GetCompanyAddress() { return "CompanyAddress"; }
//...
}
These methods do not need to be attached to a specific instance of the class. Therefore, instead of
creating unnecessary instances of this class, you can declare it as a static class, like this:

static class CompanyInfo


{
public static string GetCompanyName() { return "CompanyName"; }
public static string GetCompanyAddress() { return
"CompanyAddress"; }
//...
}
Use a static class as a unit of organization for methods not associated with particular objects. Also, a
static class can make your implementation simpler and faster because you do not have to create an
object in order to call its methods. It is useful to organize the methods inside the class in a meaningful
way, such as the methods of the Math class in the System namespace.

Static Members
A static method, field, property, or event is callable on a class even when no instance of the class has
been created. If any instances of the class are created, they cannot be used to access the static
member. Only one copy of static fields and events exists, and static methods and properties can only
access static fields and static events. Static members are often used to represent data or calculations
that do not change in response to object state; for instance, a math library might contain static
methods for calculating sine and cosine.

Static class members are declared using the static keyword before the return type of the member, for
example:

public class Automobile


{
public static int NumberOfWheels = 4;
public static int SizeOfGasTank
{
get
{
return 15;
}
}
public static void Drive() { }
public static event EventType RunOutOfGas;

//other non-static fields and properties...


}
Static members are initialized before the static member is accessed for the first time, and before the
static constructor, if any is called. To access a static class member, use the name of the class instead
of a variable name to specify the location of the member. For example:

Automobile.Drive();
int i = Automobile.NumberOfWheels;

Example
Here is an example of a static class that contains two methods that convert temperature from Celsius
to Fahrenheit and vice versa:

public static class TemperatureConverter


{
public static double CelsiusToFahrenheit(string
temperatureCelsius)
{
// Convert argument to double for calculations.
double celsius = System.Double.Parse(temperatureCelsius);

// Convert Celsius to Fahrenheit.


double fahrenheit = (celsius * 9 / 5) + 32;

return fahrenheit;
}

public static double FahrenheitToCelsius(string


temperatureFahrenheit)
{
// Convert argument to double for calculations.
double fahrenheit =
System.Double.Parse(temperatureFahrenheit);

// Convert Fahrenheit to Celsius.


double celsius = (fahrenheit - 32) * 5 / 9;

return celsius;
}
}

class TestTemperatureConverter
{
static void Main()
{
System.Console.WriteLine("Please select the convertor
direction");
System.Console.WriteLine("1. From Celsius to Fahrenheit.");
System.Console.WriteLine("2. From Fahrenheit to Celsius.");
System.Console.Write(":");
string selection = System.Console.ReadLine();
double F, C = 0;

switch (selection)
{
case "1":
System.Console.Write("Please enter the Celsius
temperature: ");
F =
TemperatureConverter.CelsiusToFahrenheit(System.Console.ReadLine());
System.Console.WriteLine("Temperature in Fahrenheit:
{0:F2}", F);
break;

case "2":
System.Console.Write("Please enter the Fahrenheit
temperature: ");
C =
TemperatureConverter.FahrenheitToCelsius(System.Console.ReadLine());
System.Console.WriteLine("Temperature in Celsius:
{0:F2}", C);
break;

default:
System.Console.WriteLine("Please select a
convertor.");
break;
}
}
}

Partial Classes and Methods (C# Programming Guide)

It is possible to split the definition of a class or a struct, an interface or a method over two or more
source files. Each source file contains a section of the type or method definition, and all parts are
combined when the application is compiled.

Partial Classes
There are several situations when splitting a class definition is desirable:

• When working on large projects, spreading a class over separate files enables multiple

programmers to work on it at the same time.


• When working with automatically generated source, code can be added to the class without

having to recreate the source file. Visual Studio uses this approach when it creates Windows
Forms, Web service wrapper code, and so on. You can create code that uses these classes
without having to modify the file created by Visual Studio.

• To split a class definition, use the partial keyword modifier, as shown here:

public partial class Employee


{
public void DoWork()
{
}
}

public partial class Employee


{
public void GoToLunch()
{
}
}

The partial keyword indicates that other parts of the class, struct, or interface can be defined in the
namespace. All the parts must use the partial keyword. All the parts must be available at compile
time to form the final type. All the parts must have the same accessibility, such as public, private,
and so on.

If any part is declared abstract, then the whole type is considered abstract. If any part is declared
sealed, then the whole type is considered sealed. If any part declares a base type, then the whole
type inherits that class.

All the parts that specify a base class must agree, but parts that omit a base class still inherit the base
type. Parts can specify different base interfaces, and the final type implements all the interfaces listed
by all the partial declarations. Any class, struct, or interface members declared in a partial definition
are available to all the other parts. The final type is the combination of all the parts at compile time.

The following example shows that nested types can be partial, even if the type they are nested within
is not partial itself.

C#
Copy Code
class Container
{
partial class Nested
{
void Test() { }
}
partial class Nested
{
void Test2() { }
}
}

Using Constructors
Constructors are class methods that are executed when an object of a given type is created.
Constructors have the same name as the class, and usually initialize the data members of the new
object.
In the following example, a class named Taxi is defined by using a simple constructor. This class is
then instantiated with the new operator. The Taxi constructor is invoked by the new operator
immediately after memory is allocated for the new object.

public class Taxi


{
public bool isInitialized;
public Taxi()
{
isInitialized = true;
}
}

class TestTaxi
{
static void Main()
{
Taxi t = new Taxi();
Console.WriteLine(t.isInitialized);
}
}

A constructor that takes no parameters is called a default constructor. Default constructors are
invoked whenever an object is instantiated by using the new operator and no arguments are provided
to new. For more information, see Instance Constructors (C# Programming Guide).
Unless the class is static, classes without constructors are given a public default constructor by the C#
compiler in order to enable class instantiation. For more information, see Static Classes and Static
Class Members (C# Programming Guide).

You can prevent a class from being instantiated by making the constructor private, as follows:

class NLog
{
// Private Constructor:
private NLog() { }

public static double e = Math.E; //2.71828...


}
Instance Constructors
Instance constructors are used to create and initialize any instance member variables when you use
the new expression to create an object of a class. To initialize a static class, or static variables in a
non-static class, you must define a static constructor.

The following example shows an instance constructor:

class CoOrds
{
public int x, y;

// constructor
public CoOrds()
{
x = 0;
y = 0;
}
}

This instance constructor is called whenever an object based on the CoOrds class is created. A
constructor like this one, which takes no arguments, is called a default constructor. However, it is
often useful to provide additional constructors. For example, we can add a constructor to the CoOrds
class that allows us to specify the initial values for the data members:
// tcA constructor with two arguments:
public CoOrds(int x, int y)
{
this.x = x;
this.y = y;
}

This allows CoOrd objects to be created with default or specific initial values, like this:

CoOrds p1 = new CoOrds();


CoOrds p2 = new CoOrds(5, 3);

If a class does not have a default constructor, one is automatically generated and default values are
used to initialize the object fields, for example, an int is initialized to 0. For more information on
default values, see Default Values Table (C# Reference). Therefore, because the CoOrds class default
constructor initializes all data members to zero, it can be removed altogether without changing how
the class works. A complete example using multiple constructors is provided in Example 1 later in this
topic, and an example of an automatically generated constructor is provided in Example 2.

Instance constructors can also be used to call the instance constructors of base classes. The class
constructor can invoke the constructor of the base class through the initializer, as follows:
C#
Copy Code
class Circle : Shape
{
public Circle(double radius)
: base(radius, 0)
{
}
}

In this example, the Circle class passes values representing radius and height to the constructor
provided by Shape from which Circle is derived. A complete example using Shape and Circle
appears in this topic as Example 3.

Example 1
The following example demonstrates a class with two class constructors, one without arguments and
one with two arguments.

C#
Copy Code
class CoOrds
{
public int x, y;

// Default constructor:
public CoOrds()
{
x = 0;
y = 0;
}

// tcA constructor with two arguments:


public CoOrds(int x, int y)
{
this.x = x;
this.y = y;
}

// Override the ToString method:


public override string ToString()
{
return (String.Format("({0},{1})", x, y));
}
}

class MainClass
{
static void Main()
{
CoOrds p1 = new CoOrds();
CoOrds p2 = new CoOrds(5, 3);

// Display the results using the overriden ToString method:


Console.WriteLine("CoOrds #1 at {0}", p1);
Console.WriteLine("CoOrds #2 at {0}", p2);
Console.ReadKey();
}
}
/* Output:
CoOrds #1 at (0,0)
CoOrds #2 at (5,3)
*/

Example 2
In this example, the class Person does not have any constructors, in which case, a default
constructor is automatically provided and the fields are initialized to their default values.

C#
Copy Code
public class Person
{
public int age;
public string name;
}

class TestPerson
{
static void Main()
{
Person person = new Person();

Console.WriteLine("Name: {0}, Age: {1}", person.name,


person.age);
// Keep the console window open in debug mode.
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}
// Output: Name: , Age: 0
Notice that the default value of age is 0 and the default value of name is null. For more information
on default values, see Default Values Table (C# Reference).

Example 3
The following example demonstrates using the base class initializer. The Circle class is derived from
the general class Shape, and the Cylinder class is derived from the Circle class. The constructor
on each derived class is using its base class initializer.

C#
Copy Code
abstract class Shape
{
public const double pi = Math.PI;
protected double x, y;

public Shape(double x, double y)


{
this.x = x;
this.y = y;
}

public abstract double Area();


}

class Circle : Shape


{
public Circle(double radius)
: base(radius, 0)
{
}
public override double Area()
{
return pi * x * x;
}
}

class Cylinder : Circle


{
public Cylinder(double radius, double height)
: base(radius)
{
y = height;
}

public override double Area()


{
return (2 * base.Area()) + (2 * pi * x * y);
}
}

class TestShapes
{
static void Main()
{
double radius = 2.5;
double height = 3.0;

Circle ring = new Circle(radius);


Cylinder tube = new Cylinder(radius, height);

Console.WriteLine("Area of the circle = {0:F2}",


ring.Area());
Console.WriteLine("Area of the cylinder = {0:F2}",
tube.Area());

// Keep the console window open in debug mode.


Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}

Private Constructors (C# Programming Guide)


A private constructor is a special instance constructor. It is generally used in classes that contain
static members only. If a class has one or more private constructors and no public constructors, other
classes (except nested classes) cannot create instances of this class. For example:

class NLog
{
// Private Constructor:
private NLog() { }

public static double e = Math.E; //2.71828...


}

The declaration of the empty constructor prevents the automatic generation of a default constructor.
Note that if you do not use an access modifier with the constructor it will still be private by default.
However, the private modifier is usually used explicitly to make it clear that the class cannot be
instantiated.

Private constructors are used to prevent creating instances of a class when there are no instance
fields or methods, such as the Math class, or when a method is called to obtain an instance of a class.
If all the methods in the class are static, consider making the complete class static. For more
information see Static Classes and Static Class Members (C# Programming Guide).

Example
The following is an example of a class using a private constructor.

C#
Copy Code
public class Counter
{
private Counter() { }
public static int currentCount;
public static int IncrementCount()
{
return ++currentCount;
}
}

class TestCounter
{
static void Main()
{
// If you uncomment the following statement, it will generate
// an error because the constructor is inaccessible:
// Counter aCounter = new Counter(); // Error

Counter.currentCount = 100;
Counter.IncrementCount();
Console.WriteLine("New count: {0}", Counter.currentCount);

// Keep the console window open in debug mode.


Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}
// Output: New count: 101

Notice that if you uncomment the following statement from the example, it will generate an error
because the constructor is inaccessible because of its protection level:

Static Constructors
A static constructor is used to initialize any static data, or to perform a particular action that needs
performed once only. It is called automatically before the first instance is created or any static
members are referenced.

C#
Copy Code
class SimpleClass
{
// Static variable that must be initialized at run time.
static readonly long baseline;

// Static constructor is called at most one time, before any


// instance constructor is invoked or member is accessed.
static SimpleClass()
{
baseline = DateTime.Now.Ticks;
}
}

Static constructors have the following


properties:
• A static constructor does not take access modifiers or have parameters.

• A static constructor is called automatically to initialize the class before the first instance is

created or any static members are referenced.

• A static constructor cannot be called directly.

• The user has no control on when the static constructor is executed in the program.

• A typical use of static constructors is when the class is using a log file and the constructor is

used to write entries to this file.

• Static constructors are also useful when creating wrapper classes for unmanaged code, when

the constructor can call the LoadLibrary method.

• If a static constructor throws an exception, the runtime will not invoke it a second time, and

the type will remain uninitialized for the lifetime of the application domain in which your
program is running.

Example
In this example, class Bus has a static constructor. When the first instance of Bus is created (bus1),
the static constructor is invoked to initialize the class. The sample output verifies that the static
constructor runs only one time, even though two instances of Bus are created, and that it runs before
the instance constructor runs.

C#
Copy Code
public class Bus
{
// Static variable used by all Bus instances.
// Represents the time the first bus of the day starts its
route.
protected static readonly DateTime globalStartTime;

// Property for the number of each bus.


protected int RouteNumber { get; set; }

// Static constructor to initialize the static variable.


// It is invoked before the first instance constructor is run.
static Bus()
{
globalStartTime = DateTime.Now;

// The following statement produces the first line of


output,
// and the line occurs only once.
Console.WriteLine("Static constructor sets global start time
to {0}",
globalStartTime.ToLongTimeString());
}

// Instance constructor.
public Bus(int routeNum)
{
RouteNumber = routeNum;
Console.WriteLine("Bus #{0} is created.", RouteNumber);
}

// Instance method.
public void Drive()
{
TimeSpan elapsedTime = DateTime.Now - globalStartTime;

// For demonstration purposes we treat milliseconds as


minutes to simulate
// actual bus times. Do not do this in your actual bus
schedule program!
Console.WriteLine("{0} is starting its route {1:N2} minutes
after global start time {2}.",
this.RouteNumber,
elapsedTime.TotalMilliseconds,
globalStartTime.ToShortTimeString())
;
}
}
class TestBus
{
static void Main()
{
// The creation of this instance activates the static
constructor.
Bus bus1 = new Bus(71);

// Create a second bus.


Bus bus2 = new Bus(72);

// Send bus1 on its way.


bus1.Drive();

// Wait for bus2 to warm up.


System.Threading.Thread.Sleep(25);

// Send bus2 on its way.


bus2.Drive();

// Keep the console window open in debug mode.


System.Console.WriteLine("Press any key to exit.");
System.Console.ReadKey();
}
}
/* Sample output:
Static constructor sets global start time to 3:57:08 PM.
Bus #71 is created.
Bus #72 is created.
71 is starting its route 6.00 minutes after global start time
3:57 PM.
72 is starting its route 31.00 minutes after global start time
3:57 PM.
*/

Boxing and unboxing


all types used in C#. All these types can be cast to another type using special rules. An
implicit casting can be done with types when values of variables can be converted without
losing of any data. There is special type of implicit casting called boxing. This enables us to
convert any type to the reference type or to the object type. Boxing example:

// boxing
char ch = 'b';
object obj = ch;
Console.WriteLine("Char value is {0}",ch);
Console.WriteLine("Object value is {0}",obj);
Console.WriteLine();

This piece of code prints the same values of integer type variable and object type variable.
The opposite process to the boxing is un-boxing. An example for un-boxing is as follows.

// unboxing
float q = 4.6f;
object ob = q;
Console.WriteLine("Object value is {0}",ob);
float r = (float)ob;
Console.WriteLine("Float value is {0}",r);

So, it is main item of common data type creating and using. All sources are attached. To
compile and run it need to run .NET command line. Just type: csc DataTypes.cs. It creates
DataTypes.exe that can be run as standard executable file. You can download the sample
code here.

Exceptions
It is very difficult to find and debug the run-time errors. These
errors also called exceptions. Rules of good coding style say that
program must be able to handle any runtime error. Exception
generates an exception call at runtime. Exceptions in C# can be
called using two methods:

C# language uses many types of exceptions, which are defined in


special classes. All of them are inherited from base class named
System.Exception. There are classes that process many kinds of
exceptions: out of memory exception, stack overflow exception,
null reference exception, index out of range exception, invalid cast
exception, arithmetic exception etc. This c# tutorial deals with
DivideByZero c# exception and custom classes in c# exceptions.

C# has defined some keywords for processing exceptions. The


most important are try, catch and finally.

//Sample code for C# Exception tutorial using try , catch

// try catch exception


int zero = 0;
try
{
int div = 100/zero;
}
catch(DivideByZeroException)
{
Console.WriteLine("Division by zero exception passed");
}

Implementing a finally Block: FinallyDemo.cs

using System;
using System.IO;

class FinallyDemo
{
static void Main(string[] args)
{
FileStream outStream = null;
FileStream inStream = null;

try
{
outStream = File.OpenWrite("DestinationFile.txt");
inStream = File.OpenRead("BogusInputFile.txt");
}
catch(Exception ex)
{
Console.WriteLine(ex.ToString());
}
finally
{
if (outStream != null)
{
outStream.Close();
Console.WriteLine("outStream closed.");
}
if (inStream != null)
{
inStream.Close();
Console.WriteLine("inStream closed.");
}
}
}
}

Reflection
Reflection is the feature in .Net, which enables us to get some
information about object in runtime. That information contains data
of the class. Also it can get the names of the methods that are
inside the class and constructors of that object.

To write a C# .Net program which uses reflection, the


program should use the namespace System.Reflection.
To get type of the object, the typeof operator can be
used. There is one more method GetType(). This also
can be used for retrieving the type information of a
class. The Operator typeof allow us to get class name of
our object and GetType() method uses to get data about
object?s type. This C# tutorial on reflection explains this
feature with a sample class

10.Reflection
Reflection is the feature in .Net, which enables us to get some
information about object in runtime. That information contains data
of the class. Also it can get the names of the methods that are
inside the class and constructors of that object.

To write a C# .Net program which uses reflection, the program


should use the namespace System.Reflection. To get type of the
object, the typeof operator can be used. There is one more method
GetType(). This also can be used for retrieving the type
information of a class. The Operator typeof allow us to get class
name of our object and GetType() method uses to get data about
object?s type. This C# tutorial on reflection explains this feature
with a sample class.

public class TestDataType


{

public TestDataType()
{
counter = 1;
}

public TestDataType(int c)
{
counter = c;
}

private int counter;


public int Inc()
{
return counter++;
}
public int Dec()
{
return counter--;
}

At first we should get type of object that was created. The following
C# .Net code snippet shows how to do it.

TestDataType testObject = new TestDataType(15);


Type objectType = testObject.GetType();

Now objectType has all the required information about class


TestDataType. We can check if our class is abstract or if it is a
class. The System.Type contains a few properties to retrieve the
type of the class: IsAbstract, IsClass. These functions return a
Boolean value if the object is abstract or of class type. Also there
are some methods that return information about constructors and
methods that belong to the current type (class). It can be done in a
way as it was done in next example:

Type objectType = testObject.GetType();

ConstructorInfo [] info = objectType.GetConstructors();


MethodInfo [] methods = objectType.GetMethods();

// get all the constructors


Console.WriteLine("Constructors:");
foreach( ConstructorInfo cf in info )
{
Console.WriteLine(cf);
}

Console.WriteLine();
// get all the methods
Console.WriteLine("Methods:");
foreach( MethodInfo mf in methods )
{
Console.WriteLine(mf);
}

Now, the above program returns a list of methods and


constructors of TestDataType class.

Reflection is a very powerful feature that any programming


language would like to provide, because it allows us to get some
information about objects in runtime. It can be used in the
applications normally but this is provided for doing some advanced
programming. This might be for runtime code generation (It goes
through creating, compilation and execution of source code in
runtime).

The Sample code can be downloaded from here. The attached


example can be compiled using .NET command line csc
command. Type csc Reflection.cs. This will create the executable
Reflection.exe, which can be run as a normal executable.

Delegates and Events

This lesson introduces delegates and events. Our objectives are as


follows:

• Understand What a Delegate Is


• Understand What an Event Is
• Implement Delegates
• Fire Events
Delegates

During previous lessons, you learned how to implement reference types


using language constructs such as classes and interfaces. These reference
types allowed you to create instances of objects and use them in special
ways to accomplish your software development goals. Classes allow you
to create objects that contained members with attributes or behavior.
Interfaces allowed you to declare a set of attributes and behavior that all
objects implementing them would publicly expose. Today, I'm going to
introduce a new reference type called a delegate.
A delegate is a C# language element that allows you to reference a
method. If you were a C or C++ programmer, this would sound familiar
because a delegate is basically a function pointer. However, developers
who have used other languages are probably wondering, "Why do I need
a reference to a method?". The answer boils down to giving you
maximum flexibility to implement any functionality you want at runtime.

Think about how you use methods right now. You write an algorithm that
does its thing by manipulating the values of variables and calling methods
directly by name. What if you wanted an algorithm that was very flexible,
reusable, and allowed you to implement different functionality as the
need arises? Furthermore, let's say that this was an algorithm that
supported some type of data structure that you wanted to have sorted, but
you also want to enable this data structure to hold different types. If you
don't know what the types are, how could you decide an appropriate
comparison routine? Perhaps you could implement an if/then/else or
switch statement to handle well-known types, but this would still be
limiting and require overhead to determine the type. Another alternative
would be for all the types to implement an interface that declared a
common method your algorithm would call, which is actually a nice
solution. However, since this lesson is about delegates, we'll apply a
delegate solution, which is quite elegant.

You could solve this problem by passing a delegate to your algorithm and
letting the contained method, which the delegate refers to, perform the
comparison operation. Such an operation is performed in Listing 14-1.

Listing 14-1. Declaring and Implementing a Delegate:


SimpleDelegate.cs

using System;

// this is the delegate declaration


public delegate int Comparer(object obj1, object obj2);

public class Name


{
public string FirstName = null;
public string LastName = null;

public Name(string first, string last)


{
FirstName = first;
LastName = last;
}

// this is the delegate method handler


public static int CompareFirstNames(object name1, object name2)
{
string n1 = ((Name)name1).FirstName;
string n2 = ((Name)name2).FirstName;

if (String.Compare(n1, n2) > 0)


{
return 1;
}
else if (String.Compare(n1, n2) < 0)
{
return -1;
}
else
{
return 0;
}
}

public override string ToString()


{
return FirstName + " " + LastName;
}
}

class SimpleDelegate
{
Name[] names = new Name[5];

public SimpleDelegate()
{
names[0] = new Name("Joe", "Mayo");
names[1] = new Name("John", "Hancock");
names[2] = new Name("Jane", "Doe");
names[3] = new Name("John", "Doe");
names[4] = new Name("Jack", "Smith");
}

static void Main(string[] args)


{
SimpleDelegate sd = new SimpleDelegate();

// this is the delegate instantiation


Comparer cmp = new Comparer(Name.CompareFirstNames);

Console.WriteLine("\nBefore Sort: \n");

sd.PrintNames();

// observe the delegate argument


sd.Sort(cmp);

Console.WriteLine("\nAfter Sort: \n");

sd.PrintNames();
}

// observe the delegate parameter


public void Sort(Comparer compare)
{
object temp;

for (int i=0; i < names.Length; i++)


{
for (int j=i; j < names.Length; j++)
{
// using delegate "compare" just like
// a normal method
if ( compare(names[i], names[j]) > 0 )
{
temp = names[i];
names[i] = names[j];
names[j] = (Name)temp;
}
}
}
}

public void PrintNames()


{
Console.WriteLine("Names: \n");
foreach (Name name in names)
{
Console.WriteLine(name.ToString());
}
}
}
13.Events

Traditional Console applications operate by waiting for a user to press a


key or type a command and press the Enter key. Then they perform some
pre-defined operation and either quit or return to the original prompt that
they started from. This works, but is inflexible in that everything is hard-
wired and follows a rigid path of execution. In stark contrast, modern
GUI programs operate on an event-based model. That is, some event in
the system occurs and interested modules are notified so they can react
appropriately. With Windows Forms, there is not a polling mechanism
taking up resources and you don't have to code a loop that sits waiting for
input. It is all built into the system with events.

A C# event is a class member that is activated whenever the event it was


designed for occurs. I like to use the term "fires" when the event is
activated. Anyone interested in the event can register and be notified as
soon as the event fires. At the time an event fires, registered methods will
be invoked.

Events and delegates work hand-in-hand to provide a program's


functionality. It starts with a class that declares an event. Any class,
including the same class that the event is declared in, may register one of
its methods for the event. This occurs through a delegate, which specifies
the signature of the method that is registered for the event. The delegate
may be one of the pre-defined .NET delegates or one you declare
yourself. Whichever is appropriate, you assign the delegate to the event,
which effectively registers the method that will be called when the event
fires. Listing 14-2 shows a couple different ways to implement events.

Listing 14-2. Declaring and Implementing Events: Eventdemo.cs

using System;
using System.Drawing;
using System.Windows.Forms;

// custom delegate
public delegate void Startdelegate();
class Eventdemo : Form
{
// custom event
public event Startdelegate StartEvent;

public Eventdemo()
{
Button clickMe = new Button();

clickMe.Parent = this;
clickMe.Text = "Click Me";
clickMe.Location = new Point(
(ClientSize.Width - clickMe.Width) /2,
(ClientSize.Height - clickMe.Height)/2);

// an EventHandler delegate is assigned


// to the button's Click event
clickMe.Click += new EventHandler(OnClickMeClicked);

// our custom "Startdelegate" delegate is assigned


// to our custom "StartEvent" event.
StartEvent += new Startdelegate(OnStartEvent);

// fire our custom event


StartEvent();
}

// this method is called when the "clickMe" button is pressed


public void OnClickMeClicked(object sender, EventArgs ea)
{
MessageBox.Show("You Clicked My Button!");
}

// this method is called when the "StartEvent" Event is fired


public void OnStartEvent()
{
MessageBox.Show("I Just Started!");
}

static void Main(string[] args)


{
Application.Run(new Eventdemo());
}
}

Anda mungkin juga menyukai