Arrays
Arrays in C# are much better than C++. Arrays are allocated in heap and thus are reference types. You can't access an out of bound element in an array. So C# prevents you from that type of bugs. Also some helper functions to iterate array elements are provided. foreach is the statement for such iteration. The difference between the syntax of C++ and C# array is:
The square brackets are placed after the type and not after the variable name
You create element locations using new operator.
C# supports single dimensional, multi dimensional, and jagged arrays (array of array).
Examples:
Quote:
int[] array = new int[10]; // single-dimensional array of int
for (int i = 0; i < array.Length; i++)
array[i] = i;
int[,] array2 = new int[5,10]; // 2-dimensional array of int
array2[1,2] = 5;
int[,,] array3 = new int[5,10,5]; // 3-dimensional array of int
array3[0,2,4] = 9;
int[][] arrayOfarray = new int[2]; // Jagged array - array of array of int
arrayOfarray[0] = new int[4];
arrayOfarray[0] = new int[] {1,2,15};
Indexers
Indexer is used to write a method to access an element from a collection, by straight way of using [], like an array. All you need is to specify the index to access an instance or element. Syntax of Indexer is same as that of class properties, except they take the input parameter, that is the index of the element.
Example:
Note: CollectionBase is the library class used for making collections. List is the protected member of CollectionBase which stores the collection list.
Quote:
class Shapes: CollectionBase
{
public void add(Shape shp)
{
List.Add(shp);
}
//indexer
public Shape this[int index]
{
get {
return (Shape) List[index];
}
set {
List[index] = value ;
}
}
}
Boxing/Unboxing
The idea of boxing is new in C#. As mentioned above, all data types, built-in or user defined, are derived from a base class object in the System namespace. So the packing of basic or primitive type into an object is called boxing, whereas the reverse of this known as unboxing.
Example:
Quote:
class Test
{
static void Main()
{
int myInt = 12;
object obj = myInt ; // boxing
int myInt2 = (int) obj; // unboxing
}
}
Example shows both boxing and unboxing. An int value can be converted to object and back again to int. When a variable of a value type needs to be converted to a reference type, an object box is allocated to hold the value, and the value is copied into the box. Unboxing is just the opposite. When an object box is cast back to its original value type, the value is copied out of the box and into the appropriate storage location.
Function parameters
Parameters in C# are of three types:
By-Value/In parameters
By-Reference/In-Out parameters
Out parameters
If you have an idea of COM interface and it's parameters types, you will easily understand the C# parameter types.
By-Value/In parameters
The concept of value parameters is same as in C++. The value of the passed value is copied into a location and is passed to the function.
Example:
Quote:
SetDay(5);
...
void SetDay(int day)
{
....
}
By-Reference/In-Out parameters
The reference parameters in C++ are passed either through pointers or reference operator &. In C# reference parameters are less error prone. Reference parameters are also called In-Out parameters because you pass a reference address of the location, so you pass an input value and get an output value from that function.
You can not pass an un-initialized reference parameter into a function. C# uses a keyword ref for the reference parameters. You also have to use keyword ref with an argument while passing it to a function demanding reference parameter.
Example:
Quote:
int a= 5;
FunctionA(ref a); // use ref with argument or you will get compiler error
Console.WriteLine(a); // prints 20
Quote:
void FunctionA(ref int Val)
{
int x= Val;
Val = x* 4;
}
Out parameter
Out parameter is the parameter which only returns value from the function. The input value is not required. C# uses a keyword out for the out parameters
Example:
Quote:
int Val;
GetNodeValue(Val);
bool GetNodeValue(out int Val)
{
Val = value;
return true;
}
Variable number of parameters and arrays
Arrays in C# are passed through a keyword params. An array type parameter should always be the right most argument of the function. Only one parameter can be of array type. You can pass any number of elements as an argument of type of that array. You can better understand it from example below:
Note: This is the only way C# provides for optional or variable number of parameters, that is using array.
Example:
Quote:
void Func(params int[] array)
{
Console.WriteLine("number of elements {0}", array.Length);
}
Func(); // prints 0
Func(5); // prints 1
Func(7,9); // prints 2
Func(new int[] {3,8,10}); // prints 3
int[] array = new int[8] {1,3,4,5,5,6,7,5};
Func(array); // prints 8
Operators and expressions
Operators are exactly the same as of C++ and thus the expression also. However some new and useful operators are also added. Some of them are discussed here.
is operator
is operator is used to check whether the operand types are equal or convert-able. The is operator is particularly useful in the polymorphism scenarios. is operator takes two operands and the result is a boolean. See the example:
Quote:
void function(object param)
{
if(param is ClassA)
//do something
else if(param is MyStruct)
//do something
}
}
as operator
as operator checks if the type of the operands are convert-able or equal (as is done by is operator) and if it is, the result is a converted or boxed object (if the operand can be boxed into the target type, see boxing/unboxing). If the objects are not convert-able or box-able, the return is a null. Have a look at the example below to better understand the concept.
Quote:
Shape shp = new Shape();
Vehicle veh = shp as Vehicle; // result is null, types are not convertable
Circle cir = new Circle();
Shape shp = cir;
Circle cir2 = shp as Circle; //will be converted
object[] objects = new object[2];
objects[0] = "Aisha";
object[1] = new Shape();
string str;
for(int i=0; i&< objects.Length; i++)
{
str = objects[i] as string;
if(str == null)
Console.WriteLine("can not be converted");
else
Console.WriteLine("{0}",str);
}
Output:
Aisha
can not be converted
Statements
Statements in C# are just like in C++ except some additions of new statements and modifications in some statements.
Followings are new statements:
foreach
For iteration of collections like arrays etc.
Example:
Quote:
foreach (string s in array)
Console.WriteLine(s);
lock
Used in threads for locking a block of code making it a critical section.
checked/unchecked
The statements are for overflow checking in numeric operations.
Example:
Quote:
int x = Int32.MaxValue; x++; // Overflow checked
{
x++; // Exception
}
unchecked
{
x++; // Overflow}
}
Following statements are modified:
Switch
Switch statement is modified in C#.
1. Now after executing a case statement, program flow can not jump to next case which was previously allowed in C++.
Example:
Quote:
int var = 100;
switch (var)
{
case 100: Console.WriteLine("<Value is 100>"); // No break here
case 200: Console.WriteLine("<Value is 200>"); break;
}
Output in C++:
Quote:
<Value is 100><Value is 200>
In C# you get compile time error:
Quote:
error CS0163: Control cannot fall through
from one case label ('case 100:') to another
2. However you can do this similar to how you do it in C++:
Quote:
switch (var)
{
case 100:
case 200: Console.WriteLine("100 or 200<VALUE is 200>"); break;
}
You can also use constant variables for case values:
Example:
Quote:
const string WeekEnd = "Sunday";
const string WeekDay1 = "Monday";
....
string WeekDay = Console.ReadLine();
switch (WeekDay )
{
case WeekEnd: Console.WriteLine("It's weekend!!"); break;
case WeekDay1: Console.WriteLine("It's Monday"); break;
}
Delegates
Delegates let us store function references into a variable. In C++, this is like using and storing function pointer for which we usually use typedef.
Delegates are declared using a keyword delegate. Have a look at this example, and you will understand what delegates are:
Example:
Quote:
delegate int Operation(int val1, int val2);
public int Add(int val1, int val2)
{
return val1 + val2;
}
public int Subtract (int val1, int val2)
{
return val1- val2;
}
public void Perform()
{
Operation Oper;
Console.WriteLine("Enter + or - ");
string optor = Console.ReadLine();
Console.WriteLine("Enter 2 operands");
string opnd1 = Console.ReadLine();
string opnd2 = Console.ReadLine();
int val1 = Convert.ToInt32 (opnd1);
int val2 = Convert.ToInt32 (opnd2);
if (optor == "+")
Oper = new Operation(Add);
else
Oper = new Operation(Subtract);
Console.WriteLine(" Result = {0}", Oper(val1, val2));
}
Inheritance and polymorphism
Only single inheritance is allowed in C#. Multiple inheritance can be achieved using interfaces.
Example:
Quote:
class Parent{
}
class Child : Parent
Virtual functions
Virtual functions to implement the concept of polymorphism are same in C#, except you use the override keyword with the virtual function implementation in the child class. The parent class uses the same virtual keyword. Every class which overrides the virtual method will use override keyword.
Quote:
class Shape
{
public virtual void Draw()
{
Console.WriteLine("Shape.Draw") ;
}
}
class Rectangle : Shape
{
public override void Draw()
{
Console.WriteLine("Rectangle.Draw");
}
}
class Square : Rectangle
{
public override void Draw()
{
Console.WriteLine("Square.Draw");
}
}
class MainClass
{
static void Main(string[] args)
{
Shape[] shp = new Shape[3];
Rectangle rect = new Rectangle();
shp[0] = new Shape();
shp[1] = rect;
shp[2] = new Square();
shp[0].Draw();
shp[1].Draw();
shp[2].Draw();
}
}
Output:
Shape.Draw
Rectangle.Draw
Square.Draw
Hiding parent functions using "new"
You can define in a child class a new version of a function, hiding the one which is in base class. A keyword new is used to define a new version. Consider the example below, which is a modified version of above example and note the output this time, when I replace the keyword override with a keyword new in Rectangle class.
Quote:
class Shape
{
public virtual void Draw()
{
Console.WriteLine("Shape.Draw") ;
}
}
class Rectangle : Shape
{
public new void Draw()
{
Console.WriteLine("Rectangle.Draw");
}
}
class Square : Rectangle
{
//wouldn't let u override it here
public new void Draw()
{
Console.WriteLine("Square.Draw");
}
}
class MainClass
{
static void Main(string[] args)
{
Console.WriteLine("Using Polymorphism:");
Shape[] shp = new Shape[3];
Rectangle rect = new Rectangle();
shp[0] = new Shape();
shp[1] = rect;
shp[2] = new Square();
shp[0].Draw();
shp[1].Draw();
shp[2].Draw();
Console.WriteLine("Using without Polymorphism:");
rect.Draw();
Square sqr = new Square();
sqr.Draw();
}
}
Output:
Using Polymorphism
Shape.Draw
Shape.Draw
Shape.Draw
Using without Polymorphism:
Rectangle.Draw
Square.Draw
See how the polymorphism doesn't take the Rectangle class's Draw method as a polymorphic form of the Shape's Draw method, instead it considers it a different method. So in order to avoid the naming conflict between parent and child, we have used new modifier.
Note: you can not use in the same class the two versions of a method, one with new modifier and other with override or virtual. Like in above example, I can not add another method named Draw in Rectangle class which is a virtual or override method. Also in the Square class, I can't override the virtual Draw method of Shape class.
Calling base class members
If the child class has the data members with same name as that of base class, in order to avoid naming conflicts, base class data members and functions are accessed using a keyword base. See in examples how the base class constructors are called and how the data members are used.
Quote:
public Child(int val) :base(val)
{
myVar = 5;
base.myVar;
}
OR
public Child(int val)
{
base(val);
myVar = 5 ;
base.myVar;
}
Future additions
This article is just a quick overview of the C# language so that you can just become familiar with the language features. Although I have tried to discuss almost all the major concepts in C# in a brief and comprehensive way with code examples, yet I think there is lot much to be added and discussed.
In future, I would like to add more commands and concepts not yet discussed, including events etc. I would also like to write for beginners, about Windows programming using C#.
References:
Our most commonly known MSDN
Inside C# by Tom Archer
A Programmer's Introduction to C# by Eric Gunnerson
Beginning C# by Karli Watson
Programming C# (O'Reilly)
Modifications:
June 12, 2003: By-Reference/In-Out Parameters- added ref keyword while calling a function with reference parameters
June 20, 2003: Added a note for the optional parameters, corrected typo mistake of assignment operator in example of jagged array
About Aisha Ikram