Archive

Archive for the ‘C# .NET’ Category

C# .NET Tutorial 4: Converting between Types

December 30, 2008 scerrimark Leave a comment

Hello there! How are you? I hope you are all well. In this tutorial I will explain how we can convert between different types. It is important that you read tutorial 3 before attempting to read this tutorial. So let’s start.

C# unlike Visual Basic prohibits implicit conversion that lose precision. This means that in C# one cannot convert a double to an int. Implicit conversion is allowed only if the destination type can accomodate all possible values of the source type. This is called widening conversion:

double d = 1.0000001;
int i = 1;
d = i; //conversion allowed

If the range of the source type exceeds that of the destination type a narrowing conversion will take place or an explicit conversion. To perform explicit conversion in C# you need to use one of the following:

  • System.Convert – this can be used on types that implement the System.IConvertible interface.
  • (type) cast operator – used on types that define conversion operators.
  • type.ToString / type.Parse – between strings and base types; throws exception if conversion is not possible.
  • type.Parse / type.ParseExact – from string to a base type. Returns false if conversion is not possible.

Narrowing conversions fail if the source value exceeds the destination type range or if a conversion between the types is not defined.

Boxing and Unboxing

Boxing converts a value type to a reference type. Unboxing as you may have guessed correctly is converting a reference type to a value type. This example demonstrates how boxing work. We will convert an int (value type) to an Object (reference type):

int i = 29;
object o = (object) i;

Here is an example of unboxing:

object o = 123;
int i = (int) o;

Boxing and unboxing incur overhead so you should avoid them as much as possible. Boxing also occurs when you call virtual methods that a structure inherits from System.Object such as ToString. To avoid boxing:

  • Implement type-specific versions (overloads) for procedures that accept various value types.
  • Use generics whenever possible
  • Override the ToString, Equals, and GetHash virtual members when using structures.

Implementing Conversion in Custom Types

To define conversion on custom types you can do one of the following:

  • Define conversion operators to simplify narrowing and widening conversions between numeric types.
  • Override ToString and Parse to provide conversion between string and type.
  • Implement the System.IConvertible interface to allow conversions through System.Convert. Use this technique to enable culture-specific conversions.

Please not that conversion operators are new as from .NET 2.0.

In this example we will see how to define conversion operators:

struct TypeA
{
    public int value;

    //Allows implicit conversion from an integer
    public static implicit operator TypeA(int arg)
    {
        TypeA temp = new TypeA();
        temp.value = arg;
        return temp;
    }

    //Allows explicit conversion to an integer
    public static explicit operator int(TypeA arg)
    {
        return arg.value;
    }

    //Provides string conversion to avoid boxing
    public override string ToString()
    {
        return this.value.ToString();
    }
}

Now one can assign integers to the type directly as show here:

TypeA a;
int i;
//Widening conversion
a = 42;
//Narrowing conversion (must be explicit)
i = (int) a;
Console.WriteLine("a = {0} and i = {1}", a.ToString(), i.ToString());

To implement the System.IConvertible interface, add the IConvertible interface to the type definition. Then use Visual Studio to generate the 17 methods required by this interface. Automatically Visual Studio will include a throw exception for all the methods. You can leave them as they are and only change those methods you wish to implement. After you implement IConvertible, the custom type can be converted using the System.Convert as shown here:

TypeA a;
bool b;
a = 42;
//Convert using ToBoolean
b = Convert.ToBoolean(a);

Ok that’s it for today hope it was of interest to you. As always do leave your comments. In the next 4 tutorials we will be seeing input and output in C#. Until then enjoy!!!!

Categories: C# .NET

C# .NET Tutorial 3: Classes

December 29, 2008 scerrimark 1 comment

Hey welcome back to the third tutorial to this series on C#. To be able to follow this tutorial I am assuming that you have a basic grasp of the C# syntax and most importantly that you have good knowledge of the object oriented approach. I also recommend that you go through my first and second tutorial. In this tutorial I am going to discuss how classes are constructed.

Inheritance

In the .NET framework each class has a method, ToString, which performs the same task for each class. Other classes support the same operators, such as comparing two instances of a class for equality. This consistency is achieved through inheritance and interfacing. Let’s start with inheritance. Through inheritance you can create classes from existing ones and inherit their functionality plus adding your (new) functionality. Let’s get dirty straight away. In this example I will create a custom exception class that inherits from System.ApplicationException:

class CustomException : System.ApplicationException // : means that it will inherit from another class
{
    public override string Message
    {
        get {return "A custom error occurred in the application";}
    }
}

Because this new custom exception inherits from the base class you can throw and catch this exception as shown here:

try
{
    throw new CustomException();
}
catch (CustomException ce)
{
    Console.WriteLine(ce.Source + " " + ce.Message);
    //note that the Source was inherited from the base class while the Message was overridden in the new
    //custom exception we created
}

Another benefit of inheritance is that you can use classes that inherit from the same base class interchangeably. For example the System.Drawing.Brush is the base class for five other classes, which are HatchBrush, LinearGradientBrush, PathGradientBrush, SolidBrush, and TextureBrush. The Graphics.DrawRectangle method requires an instance of a Brush as one of the parameters. Any one instance of the five brushes mentioned can be used as a parameter.

Interface

An interface provides sort of an agreement or contract that defines a set of members that all classes that implement that interface must provide. For example the IComparable interface defines a CompareTo method, which enables two instances of the class to be compared for equality. Every class that implements the IComparable interface needs to have the CompareTo method. For a class to implement a particular interface you use the following:

class ExampleClass : IExampleInterface
{
}

Note that Visual Studio (or Visual C# Express Edition) can generate the methods that you need to implement from the Interface. This is done by right clicking the Interface declaration, then click on Implement Interface, and then on Implement Interface again.

The most commonly used interfaces in .NET are the following:

  • IComparable – implemented by types whose values can be ordered such as int and string.
  • IDisposable – contains methods that are used to dispose of the objects.
  • IConvertible – enables a class to be converted to a base type such as boolean, double, string, etc.
  • ICloneable – supports copying of objects.
  • IEquatable – allows you to compare two instances of a class for equality.
  • IFormattable – enables you to convert an object to a formatted string.

Let us create an interface now:

interface IShape
{
    double Area(); //computes the area of a shape
    double Volume(); //computes the volume of a shape
    string Name { get; }
}

This is an interface for shape classes. Each shape must have a name and it must have methods to compute the area and volume.

In Visual Studio you can create a class and then extract an interface from it. Right-click the class, click Refactor, and then click Extract Interface.

Classes can also implement multiple interfaces.

Partial Classes

Partial classes are new in .NET 2.0. They allow you to split a class into multiple source files. The Windows form is an exmple of a partial class in .NET. The code generated by the form designer (while designing a windows form) is “hidden” in a partial class named  form.Designer.cs (where form is the name of your windows form).

Generics

Generics were also introduced in .NET 2.0 and are part of the .NET type system that allows you to define a type while leaving some of the details unspecified. Instead of specifying the types of parameters or member classes, you can allow the code that uses your type to specify it. This allows your code to tailor your type to its own specific needs. The .NET framework contains generic classes in the System.Collections.Generic such as the Dictionary, Queue, SortedDictionary, and SortedList. These classes work similar to the non-generic counterparts in System.Collections but they have better performance and type safety.

In the previous .NET versions developers used the Object to cast other classes. Generics offer advantages over the Object class:

  • Improved performance – casting requires boxing and unboxing, which we will cover in future tutorials, that require the processor’s attention therefore it slows performance. Generics do not require these.
  • Reduced run-time errors – the compile will not detect type errors when casting to and from an Object. For example if a string is cast to an Object and then that Object is cast to an integer an error occurs at run-time. Generics allow the compiler to catch this type of error.

To better understand generics let us build an example. We will create two classes, one that uses the Object and the other that uses generics:

class Obj //using Object
{
    public Object a;
    public Object b;

    public Obj(Object a, Object b)
    {
        this.a = a;
        this.b = b;
    }
}

class Gen<A,B> //using generics
{
    public A a;
    public B b;

    public Gen(A a, B b)
    {
        this.a = a;
        this.b = b;
    }
}

Note that generic code is valid only if it will compile for every possible constructed instance of the generic. This means that you are limited to the capabilities of the base Object class. Therefore you can call the ToString method (because this is implemented by all types) but you cannot use the + and > operators.

To understand further how generics are used I will present an application that uses the Obj and Gen classes we created above:

//add 2 strings using the Obj class
Obj o = new Obj("Hello","Blog");
Console.WriteLine((string)o.a + (string)o.b);

//add 2 strings using the Gen class
Gen<string,string> g = new Gen<string,string&gt("Hello", "Blog");
Console.WriteLine(g.a + g.b);

//adding an int and a double with Obj class
Obj o2 = new Obj(1, 1.2905);
Console.WriteLine((int)o2.a + (double)02.b); 

//adding an int and a double with Gen class
Gen<int,double> g2 = new Gen<int,double>(1, 1.2905);
Console.WriteLine(g2.a + g2.b);

As such the two classes do the same thing. However when we use a generic class we do not need to cast and therefore it is much more efficient. With the generic class we also ensure that any type errors occur at run-time.

By now you may be saying: Generics are limited if we can write code based on the capabilities of the Object base class. Well that is where constraints come into play. Constraints place requirements on the types that the consuming code can substitute for the generic.

Generics support four types of constraints:

  • Interface – allow only types that implement a certain interface.
  • Base class – allow only types that inherit from a particular base class.
  • Constructor – requires types that use your generic to implement a parameterless constructor.
  • Reference or value type – require types to be either a reference or value type.

To apply generics we use the where clause. In the following example we will create a generic that will allow types that implement the IComparable interface:

class CompareGeneric<T> where T : IComparable
{
    public T t1;
    public T t2;

    public CompareGeneric (T t1, T t2)
    {
        this.t1 = t1;
        this.t2 = t2;
    }

    public T Max()
    {
        if (t2.CompareTo(t1) < 0)
        {
            return t1;
        }
        else
        {
            return t2;
        }
    }
}

This code will only work because of the statement where T : IComparable. If we remove it the compiler will return an error indicating that generic type T does not contain a definition for CompareTo.

Events

Most applications are not linear. They respond to events such as a user clicking a button or when an incoming message is received on a server, etc.

An event is a message sent by an object to indicate the occurrence of an action. The action can be caused by user interaction, or it could be triggered by some other program logic. The object that raises the event is called the event sender. The object that handles the event is the event receiver.

The event sender class does not know which object or method will receive the event. We need an intermediary to act as a pointer between the sender and the receiver. The .NET framework defines a special type that provides the functionality of a function pointer. This is called a delegate.

A delegate is a class that can hold a reference to a method. A delegate has a signature and can hold references to methods with the same signature. It is equivalent to a type-safe function pointer or callback. The following shows a delegate function declaration:

public delegate void ClickEventHandler(object sender, EventArgs e);

The standard signature for an event handler delegate defines a method that does not return a value (void), whose first parameter is of type Object (referring to the instance that raised the event), and the second parameter is derived from the EventArgs and holds the event data.

To associate the event with a method to handle the event, add an instance of the delegate to the event. The event handler is called whenever the event occurs.

Here is an example to make things clearer. We will see how to respond to an event:

  • Create a method to respond to the event. It must match the Delegate signature:
    private void button_click(object sender, EventArgs e)
    {
        //put code here
    }
  • Add the event handler as an instance of the delegate:
    this.button1.click += new System.EventHandler(this.button_click); //System.EventHandler is the delegate
  • When the event occurs that method will be called.

To raise an event you must do the following steps:

  • Create a delegate:
    public delegate void MyEventHandler(object sender, EventArgs e);
  • Create an event member:
    public event MyEventHandler MyEvent;
  • Invoke the delegate within a method when you need to raise the event:
    MyEventHandler handler = MyEvent;
    EventArgs e = new EventArgs();
    
    if (handler != null)
    {
        //Invokes the delegate
        handler(this, e);
    }
    //C# checks whether handler is null

Attributes

Attributes describe a type, method, or property in a way that can be programmatically queried using a technique called Reflection.  Some common uses of attributes are to:

  • specify which security privileges a class requires
  • specify security privileges to refuse to reduce security risk
  • declare the assembly by providing a title, description, and copyright notice
  • declare capabilities, such as supporting serialization.

Attribute types derive from the System.Attribute base class and are specified using [ and ]. The following shows how to add  assembly attributes:

[assembly: AssemblyTitle("blog")]
[assembly: AssemblyDescription("This is a blog")]
[assembly: AssemblyCompany("scerrimark.com")]
[assembly: AssemblyProduct("C# tutorial")]
[assembly: AssemblyTrademark("")]

Visual Studio automatically creates some standard attributes for your assembly when you create a project, including title, company, description, guide, and version.

Attributes can also declare requirements and capabilities. For example to enable a class to be serialized you must add the Serializable attribute:

[Serializable]
class Account
{
}

The following code uses attributes to declare that it needs to read the C:\boot.ini file. Because of this attribute, the run-time will throw an exception if it lacks the specified privilege:

using System;
using System.Security.Permissions;

[assembly: FileIOPermissionAttribute(SecurityAction.RequestMinimum, Read=@"C:\boot.ini"]
namespace DeclarativeExample
{
    class ExampleClass
    {
    }
}

Type Forwarding

Suppose you have created an assembly named MyLibrary which contains a class named MyClass. Let’s say, some of your applications refer to the MyLibrary assembly and utilizes MyClass. In a later phase, you decide to move MyClass from MyLibrary to a newly created assembly called MyAdvancedLibrary. If you ship a new version of MyLibrary (which now doesn’t have MyClass), along with MyAdvancedLibrary, then your existing applications looking for MyClass in MyLibrary will not find the MyClass and end up with errors. The solution is type forwarding.

Type forwarding is an attribute that allows you to move a type from one assembly into another assembly, and to do so in such a way that it is not necessary to recompile clients that consume the first assembly. After a component ships and is being used by client applications, you can use type forwarding to move a type from the component into another assembly and ship the updated component, and the client applications will still work without being recompiled. To move a type from one class library to another:

  • Add a TypeForwardedTo attribute to the source class library assembly.
  • Cut the type definition from the source class library.
  • Paste the definition into the destination class library.
  • Rebuild both libraries.

The following code shows the attribute declaration used to move MyClass to the MyAdvancedLibrary class library.

using System.Runtime.CompileServices;
[assembly: TypeForwardedTo(typeof(MyAdvancedLibrary.MyClass))]

Well for today that’s enough!! So how are you feeling? Are you finding these tutorials good? Well leave a comment below. I ‘ll see you for the next tutorial: Converting between types.

Categories: C# .NET

C# .NET Tutorial 2: Reference Types

December 27, 2008 scerrimark 1 comment

Hello there welcome to the second tutorial on C#. If you haven’t read the first tutorial then I suggest that you read it. So let’s start straight away.

Reference types provide a lot of flexibility and offer better performance when they are passed to methods. But what is really a reference type? Unlike value-types reference types store an address of the data (aka pointer) on the stack. The actual data will be found at that address on heap. The heap is managed at runtime and items on the heap that are not needed anymore are removed by the garbage collector.

To better understand let us compare reference-type variables with value-type variables.

The first difference is this. Because reference-type variables only contain the address of memory where the data is stored if you assign this variable to another variable you will have another variable pointing to the same address in memory. Therefore these two variables are pointing to the same data on heap. This implies that if you change the value of one variable the value of the second variable will be changed automatically because they are both pointing to the same thing! Let us see through an example:

NumberClass c1 = new NumberClass(4);
Console.WriteLine(c1.Value); //This will display 4.

NumberClass c2 = c1;
Console.WriteLine(c2.Value); //This will display 4.

c1.Value += 1;
Console.WriteLine(c1.Value); //This will display 5.

Console.WriteLine(c2.Value); //This will display 5 because both c1 and c2 point to the same thing.

Built-In Reference Types

In .NET everything that is not derived from System.ValueType is a reference type. So as you can imagine there are a lot. Here I list the six most common (and the most you will use):

  • System.Object: This is the most general. You can convert any type to System.Object. Because of this any type in .NET will have the ToString, GetType, and Equals members inherited from this type.
  • System.String: used to store text.
  • System.Array: this keeps an array of data and is the base class of all arrays.
  • System.Text.StringBuilder: used to store dynamic text data.
  • System.Exception: it handles system and application-defined exceptions. Any exception (even user defined) inherits from this.
  • System.IO.Stream: This is an abstract base class and it defines a buffer for file, network I/O, device I/O, etc.

In the next sections we look at each of these built-in references.

Strings and String Builders

The System.String provides a number of members that can be used to manipulate text. For example to search and replace in a string you use the following:

string s = "This blog contains C sharp tutorials";
s = s.replace("sharp", "#");

So what happens when the contents of a string change? Strings in .NET are immutable. When a string changes a new string is created and the old one is discarded. This is invisible to the programmer however it is important that one knows because creating extra strings means the garbage collector needs to spend more time collected unreferenced (not used) strings. Consider this example:

string s = "This";
s += " is";
s += " a";
s += " blog";

This example has caused 3 temporary strings, which the garbage collector has to remove during runtime. Avoiding these temporary strings will improve performance. To avoid temporary strings:

  • Use the String class’ Concat, Join, and Format methods, and
  • Use the StringBuilder to create dynamic (mutable) strings.

With the StringBuilder you can specify the size of the string. The default created by the constructor is 16 bytes long. You can specify an initial size and the maximum size. For example:

System.Text.StringBuilder s = new System.Text.StringBuilder(30) // 30 bytes long
s.Append("This ");
s.Append("is a ");
s.Append("blog");
string message = s.ToString(); //convert to a string

The String class overrides operators from System.Object. These are:

  • Addition (+) – concatenates two strings.
  • Equality (==) – returns true if content of two strings are the same else it returns false.
  • Inequality (!=) – the opposite of equality.
  • Assignment (=) – copies the contents of one string to another (acts like value types even though they are reference types).

How to create and sort Arrays

As with the string type the System.Array provides members that can be used to work on the data present in the array. In C# arrays are declared using square brackets []. For example in the code below we will create an array and sort it:

//create a int array
int[] arr = {22,1,85,19,29,0,5};
//sort the array by calling a static method
Array.sort(arr);

Using Streams

Streams can be used to read and write to disk and communicating over a network. For whatever reason you use a stream all streams are derived from System.IO.Stream. Network streams can be found in System.Network.Sockets, and encrypted streams can be found in System.Security.Cryptography. The following are the most common streams that you will use:

  • FileStream – used to write or read, to or from files.
  • MemoryStream – used to write or read, to or from memory.
  • StreamReader – reads from a stream.
  • StreamWriter – writes to a stream.

The StreamReader and the StreamWriter accept the path of a text file as a parameter in the constructor. The following code, which needs the System.IO namespace, shows how to read and write to a text file:

//write to a text file
StreamWriter sw = new StreamWriter("blog.txt");
sw.WriteLine("C# tutorial!");
sw.Close();

//read from a text file
StreamReader sr = new StreamReader("blog.txt");
//display on screen
Console.WriteLine(sr.ReadToEnd());
sr.Close();

Later on in this series of tutorials I will dedicate a number of tutorials solely for I/O.

Exceptions

Exceptions are events that occur unexpectedly. For example a typical exception is when an application is trying to perform a mathematical division and the divisor is 0 like 4/0. Another typical example that will cause an exception is when an applilcation is trying to read from a file that does not exist on disk.

A good programmer will anticipate such exceptions and thus handle them in his/her code so that the application does not stop abruptly. In the following code we handle an exception that may occur while reading from a file (this code requires System.IO namespace):

try
{
    StreamReader sr = new StreamReader("test.txt");
    Console.WriteLine(sr.ReadToEnd());
}
catch (Exception ex)
{
    Console.WriteLine("Error reading file");
}

If any type of error occurs while reading the file the code goes in the catch block. If no error occurs the code will not go in the catch block. In this particular example any error that may occur will be caught. This is because we used the Exception class which is the base of all possible exception. Other more specific exceptions exist all deriving from System.SystemException. You can create your own more specific exceptions by deriving them from System.ApplicationException. One can also have multiple exception handlers to do different things according to the excption that occured. Here is an example that displays different error messages if a file is not found, if the user does not have the sufficient privileges, and any other type of error:

try
{
    StreamReader sr = new StreamReader("test.txt");
    Console.WriteLine(sr.ReadToEnd());
}
catch (System.IO.FileNotFoundException ex)
{
    Console.WriteLine("File not found!");
}
catch (System.UnauthorizedAccessException ex)
{
    Console.WriteLine("You do not have sufficient privileges to open this file!");
}
catch (Exception ex)
{
    Console.WriteLine("An error occurred while reading from file!");
}

While handling exceptions one can also include a finally section with the try catch block. The finally block is always executed irrespective whether an exception has occurred or not. Therefore the finally block should be used to do some clean up after your code. For example in the previous examples we were opening a stream but never closing it. We should close the stream in the finally block. This means that whether data is read successfully from the stream or not we will close the stream at the end:

//Stream declaration was moved outside so that it is available to both the try and finally blocks
StreamReader sr;

try
{
    sr = new StreamReader("test.txt");
    Console.WriteLine(sr.ReadToEnd());
}
catch (Exception ex)
{
    Console.WriteLine("Error reading from file!");
}
finally
{
    sr.Close(); //stream is closed
}

Typically all code except for variable declarations should occur between try..catch blocks. Exception handling improves the user experience and will even help you while debugging your code. However always keep in mind that it incurs a slight performance penalty.

Hope you liked this second tutorial. Please leave comments if you have any queries or if you want to change something. Until then see you for the next tutorial: Creating Classes. Bye Bye!

Categories: C# .NET

C# .Net Tutorial 1: Value Types

December 26, 2008 scerrimark 1 comment

Value types are the simplest type in the .NET Framework. Value types are variables that contain data not a reference to data stored somewhere else. The data stored in value types are kept in the stack. The .NET Framework has 3 general value types:

  • Built-in types,
  • User-defined types, and
  • Enumerations.

All these types are derived from the System.Value base type in .NET. Let’s start by looking at the built-in types.

Built-In Value Types

Built-in types can be used to built other types. The following is a list of all the numeric built-in types in .NET:

  • sbyte – 1 byte; stores values from -128 to 127.
  • byte – 1 byte; stores values from 0 to 255.
  • short – 2 bytes; stores values from -32768 to 32767.
  • int – 4 bytes; stores values from -2147483648 to 2147483647.
  • uint – 4 bytes; stores values from 0 to 4294967295.
  • long – 8 bytes; stores values from -9223372036854775808 to 9223372036854775807 (half my monthly salary :) ).
  • float – 4 bytes; stores values from -3.402823E+38 to 3.402823E+38.
  • double – 8 bytes; stores values from -1.79769313486232E+308 to 1.79769313486232E+308.
  • decimal – 16 bytes; stores values from -79228162514264337593543950335 to 79228162514264337593543950335 (whew!!).

Note: The last three types are used for floating point operations. For optimal performance, the runtime optimizes the performance of int and uint. For floating point operations double is the most efficient because it is optimized by hardware.

The other non-numeric types are the following:

  • char – 2 bytes; stores single unicode characters.
  • bool – 4 bytes; stores True/False values.
  • DateTime – 8 bytes; stores a moment in time.
  • IntPtr – size is platform dependent; contains a pointer to memory.

When you assign one value type variable to another, the values are stored in two different locations on the stack.

It is important to note that value-types can still function like objects. For example each value-type has a method ToString that is used to represent the value of a variable in string type. This method is overridden from the System.Object type (why? Simple! All types are derived from System.Object).

How to Declare Value types

To declare value types you use the following syntax:

type name;     or     type name = value;

For example:

bool isAdult; or int num = 15;

In the first example we are just declaring a variable, while in the second example we are declaring a variable and assigning a value. If a value is not assigned the constructor of the value-type will assign a default value (normally null or 0). It is recommended that you always initialize variables when you declare them. Also note that C# unlike Visual Basic is case sensitive therefore these two variables are not the same variable:

char letter = ‘a’; is not the same as    char Letter = ‘a’;

You can declare a variable to be null ( or nullable) if you want to determine whether a value has not been assigned.  The following example shows how to declare a nullable Boolean variable:

Nullable<bool> b = null;

A short hand notation exists for C#:

bool? b = null;

The Nullable type has been introduced in .NET Framework 2.0. But you may ask what will achieve through this? When you declare a Nullable variable, the variable will have two additional members. These are HasValue and Value members. The following piece of code will help you understand better:

if (b.HasValue)
    Console.WriteLine("b has a value of {0}",b.Value);
else
    Console.WriteLine("b is not set");

Don’t worry if you did not understand all the code. But what we are doing here is to check if b has a value or  not (using the HasValue member). If it has it will print the value on screen. If it does not have then it will print the following message: b is not set.

Creating User-defined Types

User-defined types are called structures or structs. Structures are made up of other value-types. Structures make it easier to work with related data. For example a structure in .NET is the System.Drawing.Point which contains two integers for the x and y coordinates. Working with this structure is relatively easy as shown in the following code:

System.Drawing.Point pt = new System.Drawing.Point(1,3);  //assigning the x and y coordinates through the System.Drawing.Point constructor (that is why there is the new keyword)

pt.offset(2,2); //moves the point
Console.WriteLine("New point is ({0},{1})", pt.X, pt.Y); //displays the new point on screen

To create your own structure you use the struct keyword in C#. Here comes an example of a strange struct called StrangeInt. This struct stores an integer. But when you add two StrangeInt variables it will return double the sum and if you subtract two StrangeInt variables it will return half the difference:

struct StrangeInt
{
    int _val; //private members

    //Constructor
    public StrangeInt(int value)
    {
        this._val = value;
    }

    public int Value
    {
        get { return this._val; }
    }

    public override string ToString()
    {
        return Value.ToString();
    }

    public static StrangeInt operator +(StrangeInt arg1, StrangeInt arg2)
    {
        int temp = arg1.Value + arg2.Value;
        return new StrangeInt(temp * 2);
    }

    public static StrangeInt operator -(StrangeInt arg1, StrangeInt arg2)
    {
        int temp = arg1.Value - arg2.Value;
        return new StrangeInt(temp/2);
    }
}

The Operator keyword is new in .NET 2.0 and is used to determine the (new/unusual) behaviour of operators (+, – ,*, /). Here is an example of how the  StrangeInt structure will be used:

StrangeInt s1 = new StrangeInt(20);
StrangeInt s2 = new StrangeInt(15);

StrangeInt sum = s1 + s2;
StrangeInt difference = s1 - s2;

Console.WriteLine("The sum of {0} and {1} is {2}",s1.ToString(), s2.ToString(), sum.ToString());
Console.WriteLine("The difference of {0} and {1} is {2}",s1.ToString(), s2.ToString(), difference.ToString());

This code will give a sum of 70 (20 + 15 = 35 * 2 = 70) and a difference of 2 (20 – 15 = 5 / 2 = 2 in non floating point representation).

This struct can be easily changed into a class. If this change is made the variables will be stored on heap. This will be covered in the next tutorial.

So when are we to use structures instead of classes? Structures are more efficient than classes and these should be used when:

  • Logically it represents a single value,
  • Will not be changed after it is created, and it
  • Will not be cast to a reference type.

How to create Enumerations

Enumerations are symbols that have fixed values. These are created mainly to improve code readability by using meaningful symbols. An example will help more:

enum Days : int {Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday};

Days dayToday = Days.Friday;
Console.WriteLine("Today is {0}", dayToday); //displays Friday

Ok I think it is enough for today. Hope you liked my first tutorial. Please leave comments to tell me if you liked it, what you want to improve, and if you have any queries.

Until then stay tuned for the next tutorial: Reference types. CU

Categories: C# .NET

C# .NET Tutorial: Introduction

December 24, 2008 scerrimark 2 comments

As I promised in my first post I will start uploading a series of C# tutorials for those of you who want to dirty their hands in this fabulous language. In this introductory post I will explain how I will divide this series of tutorials. But before I do that I will tell you what you will gain after reading this series of tutorials.

After you have finished this series of tutorials you will be able to create .NET applications that:

  • use system types and collections,
  • implement multi-threading,
  • use classes that can be serialized so that they can be easily stored and transferred,
  • are able to communicate with other applications (even applications written in old languages),
  • are able to send e-mail messages,
  • are secure,
  • are multilingual and can be used in different languages, and finally
  • contain multimedia such as videos, images, charts and the rest.

It is very important to note that in this series of tutorials I am assuming that you have some knowledge (not a lot) in application development using any object-oriented language (preferably C# or Visual Basic), and that you have some basic knowledge of how Microsoft Windows works. It would be great if you go over the basic syntax of C# (nothing complex).

Before you can start this series of tutorials make sure that you have the following software requirments:

  • Operating System (any of the following): Windows 2000 with Service Pack 4, Windows XP Service Pack 2, Windows XP x64, Windows Server 2003 Service Pack 1, Windows Server 2003 x64, Windows Server 2003 R2, or Windows Vista.
  • Additional Software: Microsoft Visual C# Express Edition, which you can get from here.

In the first 4 tutorials we will be going through the .NET fundamentals mainly using value and reference types, constructing classes, and converting between types.

So it looks exciting doesn’t it? Well stay tuned for the first tutorial that I will upload in the coming days. By that time if you have any comments or any queries just leave a comment. CU soon!!!

Categories: C# .NET