Documente Academic
Documente Profesional
Documente Cultură
A delegate is a type-safe object that can point to another method (or possibly multiple methods) in the
application, which can be invoked at later time.
Defining a Delegate in C#
when you want to create a delegate in C# you make use of delegate keyword.
The name of your delegate can be whatever you desire. However, you must define the delegate to match
the signature of the method it will point to. For example the following delegate can point to any method
taking two integers and returning an integer.
namespace MyFirstDelegate
//This delegate can point to any method, taking two integers and returning an integer.
return x + y;
{
return x * y;
class Program
Console.ReadLine();
}
}
Delegate's ability to multicast means that a delegate object can maintain a list of methods to call, rather
than a single method.
if you want to add a method to the invocation list of a delegate object , you simply make use of the
overloaded += operator, and if you want to remove a method from the invocation list you make use of the
overloaded operator -= .
Note: The Multicast delegate here contain methods that return void, if you want to create a
multicast delegate with return type you will get the return type of the last method in the invocation list.
namespace MyMulticastDelegate
//method at once
class Program
//invocation list.
del(5, 5);
del(5, 5);
Events are members of the class that raises them. When some thing happens a class can raise an event,
which have a message that contain information about the event (event arguments) and send them out to
the rest of the application, other parts of the application can respond to the event by executing methods
called event handlers.
Event handler is a method that has the same signature as the event and this method is executed when the
event occurs.
To define an event you need first to define a delegate that contains the methods that will be called when
the event raised, and then you define the event based on that delegate.
Example
if (MyEvent != null)
MyEvent(message);
So far so good, in the previous section you saw how to define an event and the delegate associated with it
and how to raise this event.
Now you will see how the other parts of the application can respond to the event. To do this you just need
to register the event handlers.
when you want to register an event handler with an event you must follow this pattern:
namespace EventsInCSharp
{
public class MyClass
{
public delegate void MyDelegate(string message);
public event MyDelegate MyEvent;
we are doing great, but what if you want to define your event and it's associated delegate to mirrors
Microsoft's recommended event pattern. To do so you must follow this patten:
As you can see the first parameter of the delegate is a System.Object, while the second parameter is a type
deriving from System.EventArgs.
The System.Object parameter represents a reference to the object that sent the event(such as MyClass),
while the second parameter represents information regarding the event.
If you define a simple event that is not sending any custom information, you can pass an instance of
EventArgs directly.
let's see an example:
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
namespace MicrosoftEventPattern
{
public class MyClass
{
public delegate void MyDelegate(object sender, MyEventArgs e);
public event MyDelegate MyEvent;
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
There is this thing in C# called a delegate, which is going to be crucial to build interactions between our
objects. What's a delegate, you ask? Good question. A delegate is a pointer to a method. What's that
mean? Just like you can pass variable by reference, you can pass a reference to a method. Let me give
you an example.
Let's say we have a class with two methods that have the same signature (same return type and same
parameter configuration).
We can point to either of the methods in our class by using a delegate declared as follows:
Now, if we have another class and want to execute either of the methods in MyObject, we can do it
through the delegate as in the "Do()" method in the class below. As a matter of fact, we can pass any
method with the same signature (not JUST the methods in MyObject). Check out the
MySecondObject.Subtract() method.
{
MyObject obj;
int a, b;
public MySecondObject()
{
a=4;
b=5;
obj = new MyObject();
}
switch(pMethod)
{
case"Add":
del = new MyMethodDelegate(obj.Add);
break;
case"Multiply":
del = new MyMethodDelegate(obj.Multiply);
break;
case "Subtract":
del = new MyMethodDelegate(this.Subtract);
break;
}
return del(a,b);
}
Hopefully this gives you a better idea of what delegates are and how they are implemented.
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Delegates are the function to pointer. A delegate keeps the reference of function. Like as pointer in C/C+
+, same in C# we have delegates. Delegates in C# are reference types. They are type safe, managed
function pointers in C# that can be used to invoke a method that the delegate refers to. The signature of
the delegate should be the same as the signature of the method to which it refers.
Let us see the working of delegates with this simple example. Here in this example, I am using a
button click event. A message appears when the button is clicked.
Creation a button control can be seen below.
//Here we see that on clicking on button a Event Handler is calling named as button1_click
this.button1.Click += new System.EventHandler(this.button1_Click);
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace AnApplicationOfDelagatesNEvent
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
}
}
}
Here on the button click event a message appears. Here I also write a method.
Figure 1.
Now I am calling MyMessage on the click of Button. Here we see that now if user click on button then
the defination of button1_click will not be called because here Event is calling from MyMessage.
Delegates Tutorial
This tutorial demonstrates the delegate types. It shows how to map delegates to static and instance
methods, and how to combine them (multicast).
A delegate in C# is similar to a function pointer in C or C++. Using a delegate allows the programmer to
encapsulate a reference to a method inside a delegate object. The delegate object can then be passed to
code which can call the referenced method, without having to know at compile time which method will
be invoked. Unlike function pointers in C or C++, delegates are object-oriented, type-safe, and secure.
A delegate declaration defines a type that encapsulates a method with a particular set of arguments and
return type. For static methods, a delegate object encapsulates the method to be called. For instance
methods, a delegate object encapsulates both an instance and a method on the instance. If you have a
delegate object and an appropriate set of arguments, you can invoke the delegate with the arguments.
An interesting and useful property of a delegate is that it does not know or care about the class of the
object that it references. Any object will do; all that matters is that the method's argument types and return
type match the delegate's. This makes delegates perfectly suited for "anonymous" invocation.
Note Delegates run under the caller's security permissions, not the declarer's permissions.
The use of delegates promotes good separation of functionality between the bookstore database and
the client code. The client code has no knowledge of how the books are stored or how the bookstore code
finds paperback books. The bookstore code has no knowledge of what processing is done on the
paperback books after it finds them.
// bookstore.cs
using System;
// A set of classes for handling a bookstore:
namespace Bookstore
{
using System.Collections;
// Describes a book in the book list:
public struct Book
{
public string Title; // Title of the book.
public string Author; / Author of the book.
public decimal Price; // Price of the book.
public bool Paperback; // Is it paperback?
public Book(string title, string author, decimal price, bool paperBack)
{
Title = title;
Author = author;
Price = price;
Paperback = paperBack;
}
}
// Declare a delegate type for processing a book:
public delegate void ProcessBookDelegate(Book book);
// Maintains a book database.
public class BookDB
{
// List of all books in the database:
ArrayList list = new ArrayList();
// Add a book to the database:
public void AddBook(string title, string author, decimal price, bool paperBack)
{
list.Add(new Book(title, author, price, paperBack));
}
// Call a passed-in delegate on each paperback book to process it:
public void ProcessPaperbackBooks(ProcessBookDelegate processBook)
{
foreach (Book b in list)
{
if (b.Paperback)
// Calling the delegate:
processBook(b);
}
}
}
}
// Using the Bookstore classes:
namespace BookTestClient
{
using Bookstore;
// Class to total and average prices of books:
class PriceTotaller
{
int countBooks = 0;
decimal priceBooks = 0.0m;
internal void AddBookToTotal(Book book)
{
countBooks += 1;
priceBooks += book.Price;
}
internal decimal AveragePrice()
{
return priceBooks / countBooks;
}
}
// Class to test the book database:
class Test
{
// Print the title of the book.
static void PrintTitle(Book b)
{
Console.WriteLine(" {0}", b.Title);
}
// Execution starts here.
static void Main()
{
BookDB bookDB = new BookDB();
// Initialize the database with some books:
AddBooks(bookDB);
// Print all the titles of paperbacks:
Console.WriteLine("Paperback Book Titles:");
// Create a new delegate object associated with the static
// method Test.PrintTitle:
bookDB.ProcessPaperbackBooks(new ProcessBookDelegate(PrintTitle));
// Get the average price of a paperback by using
// a PriceTotaller object:
PriceTotaller totaller = new PriceTotaller();
// Create a new delegate object associated with the nonstatic
// method AddBookToTotal on the object totaller:
bookDB.ProcessPaperbackBooks(new ProcessBookDelegate(totaller.AddBookToTotal));
Console.WriteLine("Average Paperback Book Price: ${0:#.##}",
totaller.AveragePrice());
}
// Initialize the book database with some test books:
static void AddBooks(BookDB bookDB)
{
bookDB.AddBook("The C Programming Language", "Brian W. Kernighan and Dennis M. Ritchie",
19.95m, true);
bookDB.AddBook("The Unicode Standard 2.0", "The Unicode Consortium", 39.95m, true);
bookDB.AddBook("The MS-DOS Encyclopedia", "Ray Duncan", 129.95m, false);
bookDB.AddBook("Dogbert's Clues for the Clueless", "Scott Adams", 12.00m, true);
}
}
}
Output
Code Discussion
• Declaring a delegate
declares a new delegate type. Each delegate type describes the number and types of the
arguments, and the type of the return value of methods that it can encapsulate. Whenever a new
set of argument types or return value type is needed, a new delegate type must be declared.
• Instantiating a delegate: Once a delegate type has been declared, a delegate object must be
created and associated with a particular method. Like all other objects, a new delegate object is
created with a new expression. When creating a delegate, however, the argument passed to the
new expression is special - it is written like a method call, but without the arguments to the
method.
bookDB.ProcessPaperbackBooks(new ProcessBookDelegate(PrintTitle));
creates a new delegate object associated with the static method Test.PrintTitle. The following
statement:
bookDB.ProcessPaperbackBooks(new ProcessBookDelegate(totaller.AddBookToTotal));
creates a new delegate object associated with the nonstatic method AddBookToTotal on the
object totaller. In both cases, this new delegate object is immediately passed to the
ProcessPaperbackBooks method.
Note that once a delegate is created, the method it is associated with never changes - delegate
objects are immutable.
• Calling a delegate: Once a delegate object is created, the delegate object is typically passed to
other code that will call the delegate. A delegate object is called by using the name of the delegate
object, followed by the parenthesized arguments to be passed to the delegate. An example of a
delegate call is:
processBook(b);
This example demonstrates composing delegates. A useful property of delegate objects is that they can be
composed using the "+" operator. A composed delegate calls the two delegates it was composed from.
Only delegates of the same type can be composed.
The "-" operator can be used to remove a component delegate from a composed delegate.
// compose.cs
using System;
delegate void MyDelegate(string s);
class MyClass
{
public static void Hello(string s)
{
Console.WriteLine(" Hello, {0}!", s);
}
public static void Goodbye(string s)
{
Console.WriteLine(" Goodbye, {0}!", s);
}
public static void Main()
{
MyDelegate a, b, c, d;
// Create the delegate object a that references
// the method Hello:
a = new MyDelegate(Hello);
// Create the delegate object b that references
// the method Goodbye:
b = new MyDelegate(Goodbye);
// The two delegates, a and b, are composed to form c:
c = a + b;
// Remove a from the composed delegate, leaving d,
// which calls only the method Goodbye:
d = c - a;
Console.WriteLine("Invoking delegate a:");
a("A");
Console.WriteLine("Invoking delegate b:");
b("B");
Console.WriteLine("Invoking delegate c:");
c("C");
Console.WriteLine("Invoking delegate d:");
d("D");
}
}
Output
Invoking delegate a:
Hello, A!
Invoking delegate b:
Goodbye, B!
Invoking delegate c:
Hello, C!
Goodbye, C!
Invoking delegate d:
Goodbye, D!
Delegates are ideally suited for use as events — notifications from one component to "listeners" about
changes in that component.
Delegates and interfaces are similar in that they enable the separation of specification and
implementation. Multiple independent authors can produce implementations that are compatible with an
interface specification. Similarly, a delegate specifies the signature of a method, and authors can write
methods that are compatible with the delegate specification. When should you use interfaces, and when
should you use delegates?
Indexers In C#
By Rajesh
C# introduces a new concept known as Indexers which are used for treating an object as an array. The
indexers are usually known as smart arrays in C# community. Defining a C# indexer is much like
defining properties. We can say that an indexer is a member that enables an object to be indexed in the
same way as an array.
// C#: INDEXER
// Author: rajeshvs@msn.com
using System;
using System.Collections;
class MyClass
{
private string []data = new string[5];
public string this [int index]
{
get
{
return data[index];
}
set
{
data[index] = value;
}
}
}
class MyClient
{
public static void Main()
{
MyClass mc = new MyClass();
mc[0] = "Rajesh";
mc[1] = "A3-126";
mc[2] = "Snehadara";
mc[3] = "Irla";
mc[4] = "Mumbai";
Console.WriteLine("{0},{1},{2},{3},{4}",mc[0],mc[1],mc[2],mc[3],mc[4]);
}
}
The indexers in C# can be overloaded just like member functions. The formal parameter list of an indexer
defines the signature of the indexer. Specifically, the signature of an indexer consists of the number and
types of its formal parameters. The element type is not part of an indexer's signature, nor is the names of
the formal parameters. The signature of an indexer must differ from the signatures of all other indexers
declared in the same class. C# do not have the concept of static indexers. If we declare an indexer static,
the compiler will show a compilation time error.
Just like any other class members, indexers can also participate in inheritance. A base class indexer is
inherited to the derived class.
}
class MyClient
{
public static void Main()
{
Derived d1 = new Derived();
d1[0] = 10;
Console.WriteLine(d1[0]);//Displays 'Base SET Base GET 10'
}
}
A Base class indexer can be polymorphicaly overridden in a Derived class. But remember that the
modifiers like virtual, override etc are using at property level, not at accessor level.
using System;
class Base
{
public virtual int this[int index]
{
get
{
Console.Write("Base GET");
return 10;
}
set
{
Console.Write("Base SET");
}
}
}
class MyClient
{
public static void Main()
{
Base b1 = new Derived();
b1[0]= 10;
Console.WriteLine(b1[0]);//Displays 'Derived SET Derived GET 10'
}
}
Abstract Indexers
An indexer inside a class can be declared as abstract by using the keyword abstract. Remember that an
abstract indexer in a class carries no code at all. The get/set accessors are simply represented with a
semicolon. In the derived class we must implement both set and get assessors.
If the abstract class contains only set accessor, we can implement only set in the derived class.
using System;
class MyClient
{
public static void Main()
{
Concrete c1 = new Concrete();
c1[0] = 10;
Console.WriteLine(c1[0]);//Displays 'SET GET 10'
}
}
Indexers & Properties
Conclusion
The indexer is one of the key concepts of C# and are very interesting aspects of the language. I've given
you enough information to use indexer in your code and shown you some examples. The feedback is
always welcome. Feel free to contact me for any questions or comments you may have about this article
at rajeshvs@msn.com.
Property Indexer
Identified by its name. Identified by its signature.
Accessed through a simple name or a member Accessed through an element access.
access.
Can be a static or an instance member. Must be an instance member.
A get accessor of a property has no A get accessor of an indexer has the same formal
parameters. parameter list as the indexer.
A set accessor of a property contains the A set accessor of an indexer has the same formal parameter
implicit value parameter. list as the indexer, in addition to the value parameter.
Properties
Properties are named members of classes, structs, and interfaces. They provide a flexible mechanism to
read, write, or compute the values of private fields through accessors.
Property Declaration
Properties are an extension of fields and are accessed using the same syntax. Unlike fields, properties do
not designate storage locations. Instead, properties have accessors that read, write, or compute their
values.
where:
attributes (Optional)
Additional declarative information. For more information on attributes and attribute classes, see
C# Attributes.
modifiers (Optional)
The allowed modifiers are new, static, virtual, abstract, override, and a valid combination of the
four access modifiers.
type
The property type, which must be at least as accessible as the property itself. For more
information on accessibility levels, see Access Modifiers.
identifier
The property name. For more information on interface member implementation, see interface.
accessor-declaration
Declaration of the property accessors, which are used to read and write the property.
interface-type
Remarks
Unlike fields, properties are not classified as variables. Therefore, it is not possible to pass a property as a
ref or out parameter.
A property declared using the static modifier is classified as a static property; otherwise, it is classified as
an instance property. Like other static members, a static property is not associated with a specific instance
and cannot be referenced through an instance. Instead, it is associated with the type and can only be
referenced through the type name. For example, in the following statements:
Button okButton = new Button();
// Using an instance property:
string s = okButton.Caption;
the Caption property is associated with the instance okButton. If Caption is declared as a static property,
the class name (Button) must be used instead:
An instance of a class can be accessed using this in the accessors of an instance property, but it is an error
to use this in the accessors of a static property.
This example demonstrates instance, static, and read-only properties. It accepts the name of the employee
from the keyboard, increments numberOfEmployees by 1, and displays the Employee name and number.
// property.cs
// Properties
using System;
public class Employee
{
public static int numberOfEmployees;
private static int counter;
private string name;
Output
Employee number: 101
Employee name: Claude Vige
Indexers
Indexers permit instances of a class or struct to be indexed in the same way as arrays. Indexers are similar
to properties except that their accessors take parameters.
Indexer Declaration
Indexers allow you to index a class or a struct instance in the same way as an array. To declare an
indexer, use the following:
where:
attributes (Optional)
Additional declarative information. For more information on attributes and attribute classes, see
C# Attributes.
modifiers (Optional)
Allowed modifiers are new, virtual, sealed, override, abstract, extern, and a valid combination
of the four access modifiers. For details, see Access Modifiers.
indexer-declarator
Includes the type of the element introduced by the indexer, this, and the formal-index-parameter-
list. If the indexer is an explicit interface member implementation, the interface-type is included.
type
A type name.
interface-type
formal-index-parameter-list
Specifies the parameters of the indexer. The parameter includes optional attributes, the index
type, and the index identifier. At least one parameter must be specified. The parameter modifiers
out and ref are not allowed.
accessor-declarations
The indexer accessors, which specify the executable statements associated with reading and
writing indexer elements.
identifier
get Accessor
The get accessor body of an indexer is similar to a method body. It returns the type of the indexer. The
get accessor uses the same formal-index-parameter-list as the indexer. For example:
get
{
return myArray[index];
}
set Accessor
The set accessor body of an indexer is similar to a method body. It uses the same formal-index-
parameter-list as the indexer, in addition to the value implicit parameter. For example:
set
{
myArray[index] = value;
}
Remarks
The type of an indexer and each of the types referenced in the formal-index-parameter-list must be at
least as accessible as the indexer itself. For more information on accessibility levels, see Access
Modifiers.
The signature of an indexer consists of the number and types of its formal parameters. It does not include
the indexer type or the names of the formal parameters.
If you declare more than one indexer in the same class, they must have different signatures.
An indexer value is not classified as a variable; therefore, it is not possible to pass an indexer value as a
ref or out parameter.
To provide the indexer with a name that other languages can use for the default indexed property, use a
name attribute in the declaration. For example:
[System.Runtime.CompilerServices.CSharp.IndexerName("MyItem")]
public int this [int index] // Indexer declaration
{
}
This indexer will have the name MyItem. Without providing the name attribute, the default name will be
Item.
Example
The following example shows how to declare a private array field, myArray, and an indexer. Using the
indexer allows direct access to the instance b[i]. The alternative to using the indexer is to declare the array
as a public member and access its members, myArray[i], directly.
// cs_keyword_indexers.cs
using System;
class IndexerClass
{
private int [] myArray = new int[100];
public int this [int index] // Indexer declaration
{
get
{
// Check the index limits.
if (index < 0 || index >= 100)
return 0;
else
return myArray[index];
}
set
{
if (!(index < 0 || index >= 100))
myArray[index] = value;
}
}
}
Output
Element #0 = 0
Element #1 = 0
Element #2 = 0
Element #3 = 256
Element #4 = 0
Element #5 = 1024
Element #6 = 0
Element #7 = 0
Element #8 = 0
Element #9 = 0
Element #10 = 0
Notice that when an indexer's access is evaluated (for example, in a Console.Write statement) the get
accessor is invoked. Therefore, if no get accessor exists, a compile-time error occurs.
Defining an indexer allows you to create classes that act like "virtual arrays." Instances of that class can
be accessed using the [] array access operator. Defining an indexer in C# is similar to defining operator []
in C++, but is considerably more flexible. For classes that encapsulate array- or collection-like
functionality, using an indexer allows the users of that class to use the array syntax to access the class.
For example, suppose you want to define a class that makes a file appear as an array of bytes. If the file
were very large, it would be impractical to read the entire file into memory, especially if you only wanted
to read or change a few bytes. By defining a FileByteArray class, you could make the file appear similar
to an array of bytes, but actually do file input and output when a byte was read or written.
In addition to the example below, an advanced topic on Creating an Indexed Property is discussed in this
tutorial.
In this example, the class FileByteArray makes it possible to access a file as if it were a byte array. The
Reverse class reverses the bytes of the file. You can run this program to reverse the bytes of any text file
including the program source file itself. To change the reversed file back to normal, run the program on
the same file again.
// indexer.cs
// arguments: indexer.txt
using System;
using System.IO;
file.Close();
}
}
Input: indexer.txt
To test the program you can use a text file with the following contents (this file is called Test.txt in the
Indexers Sample).
To reverse the bytes of this file, compile the program and then use the command line:
indexer indexer.txt
Type indexer.txt
Sample Output
}
}
;)"!dlroW ,olleH"(eniLetirW.elosnoC.metsyS
{
)(niaM diov citats cilbup
{
1olleH ssalc cilbup
Code Discussion
• Since an indexer is accessed using the [] operator, it does not have a name. For indexer
declaration syntax, see Indexers.
• In the example above, the indexer is of type byte and takes a single index of type long (64-bit
integer). The Get accessor defines the code to read a byte from the file, while the Set accessor
defines the code to write a byte to the file. Inside the Set accessor, the predefined parameter value
has the value that is being assigned to the virtual array element.
• An indexer must have at least one parameter. Although it is comparatively rare, an indexer can
have more than one parameter in order to simulate a multidimensional "virtual array." Although
integral parameters are the most common, the indexer parameter can be of any type. For example,
the standard Dictionary class provides an indexer with a parameter of type Object.
• Although indexers are a powerful feature, it is important to use them only when the array-like
abstraction makes sense. Always carefully consider whether using regular method(s) would be
just as clear. For example, the following is a bad use of an indexer:
class Employee
{
// VERY BAD STYLE: using an indexer to access
// the salary of an employee.
public double this[int year]
{
get
{
// return employee's salary for a given year.
}
}
}
Although legal, an indexer with only a Get accessor is rarely good style. Strongly consider using
a method in this case.
Properties Tutorial
This tutorial shows how properties are an integral part of the C# programming language. It demonstrates
how properties are declared and used.
This tutorial includes two examples. The first example shows how to declare and use read/write
properties. The second example demonstrates abstract properties and shows how to override these
properties in subclasses.
Example 1
This sample shows a Person class that has two properties: Name (string) and Age (int). Both properties
are read/write.
// person.cs
using System;
class Person
{
private string myName ="N/A";
private int myAge = 0;
// Print out the name and the age associated with the person:
Console.WriteLine("Person details - {0}", person);
Output
Simple Properties
Person details - Name = N/A, Age = 0
Person details - Name = Joe, Age = 99
Person details - Name = Joe, Age = 100
Code Discussion
• Notice the way that the properties are declared, for example, consider the Name property:
The Set and Get methods of a property are contained inside the property declaration. You can
control whether a property is read/write, read-only, or write-only by controlling whether a Get or
Set method is included.
• Once the properties are declared, they can be used as if they were fields of the class. This allows
for a very natural syntax when both getting and setting the value of a property, as in the following
statements:
person.Name = "Joe";
person.Age = 99;
• Note that in a property Set method a special value variable is available. This variable contains the
value that the user specified, for example:
myName = value;
• Notice the clean syntax for incrementing the Age property on a Person object:
person.Age += 1;
person.SetAge(person.GetAge() + 1);
Notice that ToString is not explicitly used in the program. It is invoked by default by the
WriteLine calls.
Example 2
The following example shows how to define abstract properties. An abstract property declaration does not
provide an implementation of the property accessors. The example demonstrates how to override these
properties in subclasses.
This sample consists of three files. In the Properties Sample, these files are compiled into a single
compilation but in this tutorial, each file is compiled individually and its resulting assembly referenced by
the next compilation:
File 1 - abstractshape.cs
This file declares the Shape class that contains the Area property of the type double
// abstractshape.cs
// compile with: /target:library
// csc /target:library abstractshape.cs
using System;
public Shape(string s)
{
Id = s; // calling the set accessor of the Id property
}
public string Id
{
get
{
return myId;
}
set
{
myId = value;
}
}
Code Discussion
• Modifiers on the property are placed on the property declaration itself, for example:
• When declaring an abstract property (such as Area in this example), you simply indicate what
property accessors are available, but do not implement them. In this example, only a Get accessor
is available, so the property is read-only.
File 2 - shapes.cs
The following code shows three subclasses of Shape and how they override the Area property to provide
their own implementation.
// shapes.cs
// compile with: /target:library /reference:abstractshape.dll
public class Square : Shape
{
private int mySide;
The following code shows a test program that creates a number of Shape-derived objects and prints out
their areas.
// shapetest.cs
System.Console.WriteLine("Shapes Collection");
foreach(Shape s in shapes)
{
System.Console.WriteLine(s);
}
}
}
Output
Shapes Collection
Square #1 Area = 25.00
Circle #1 Area = 28.27
Rectangle #1 Area = 20.00
namespace Programming_CSharp
{
using System;
public class StringTester
{
static void Main( )
{
// create some strings to work with
string s1 = "abcd";
string s2 = "ABCD";
string s3 = @"Liberty Associates, Inc.provides custom .NET development,on-site Training &Dev”;
// concatenation method
string s6 = string.Concat(s1,s2);
Console.WriteLine("s6 concatenated from s1 and s2: {0}", s6);
// use the overloaded operator
string s7 = s1 + s2;
Console.WriteLine("s7 concatenated from s1 + s2: {0}", s7);
Output
compare s1: abcd, s2: ABCD, result: -1
compare insensitive
s4: abcd, s2: ABCD, result: 0
s6 concatenated from s1 and s2: abcdABCD
s7 concatenated from s1 + s2: abcdABCD
s8 copied from s7: abcdABCD
s9 = s8: abcdABCD
Does s9.Equals(s8)?: True
Does Equals(s9,s8)?: True
Does s9==s8?: True
String s9 is 8 characters long.
The 5th character is A
s3:Liberty Associates, Inc.
provides custom .NET development,on-site Training and Dev
Ends with Training?: False
Ends with Dev?: True
The first occurrence of Training in s3 is 101
s10: Liberty Associates, Inc.provides custom .NET development, on-site excellent Training and Dev
s11: Liberty Associates, Inc.provides custom .NET development,on-site excellent Training and
Dev
Example 8 : EXCEPTION
namespace Programming_CSharp
{
using System;
public class Test
{
public static void Main( )
{
Test t = new Test( );
t.TestFunc( );
}
// try to divide two numbers
// handle possible exceptions
public void TestFunc( )
{
try
{
double a = 5;
double b = 0;
Console.WriteLine ("{0} / {1} = {2}",a, b, DoDivide(a,b));
}
// most derived exception type first
catch (System.DivideByZeroException)
{
Console.WriteLine("DivideByZeroException caught!");
}
catch (System.ArithmeticException)
{
Console.WriteLine("ArithmeticException caught!");
}
// generic exception type last
catch
{
Console.WriteLine("Unknown exception caught");
}
}
// do the division if legal
public double DoDivide(double a, double b)
{
if (b == 0)
throw new System.DivideByZeroException( );
if (a == 0)
throw new System.ArithmeticException( );
return a/b;
}
}
}
Output:
DivideByZeroException caught!
using System;
using System.Windows.Forms;
namespace ProgCSharp
{
public class HandDrawnClass : Form
{
// a cancel button
private System.Windows.Forms.Button btnCancel;
public HandDrawnClass( )
{
// create the objects
this.lblOutput =new System.Windows.Forms.Label ( );
this.btnCancel =new System.Windows.Forms.Button ( );
1. Operator Overloading
2. Indexer
3. Inheritance
4. Polymorphism
5. Properties
6. Delegates
7. Multicasting
8. Events