C# Tutorial

As a programmer looking for work I'm not in bad shape as Java is in high demand. The other big language is C#, which I don't know. I figured it's like a tweaked version of Java but it's best to check it out. Let's start with minimal working example.

	
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Tutorial
{
    class Program
    {
        static void Main(string[] args)
        {
        }
    }
}
	

Now a printline to see if the console-interaction works.

	
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Tutorial
{
    class Program
    {
        static void Main(string[] args)
        {
			Console.WriteLine("This is a test.");
        }
    }
}
	

Very well. So what have we learnt so far? Well, first I should explain that the imports at the beginning are Visual Studio 2010 default imports and aren't entirely necessary for this example(I assume). Namespaces are comparable to Java packages but not connected to directory hierarchies like Java packages. Along with "partial" descriptions(I've read about them), namespaces give C#-programmers the ability to divide code into different files and tie them together during compilation.

	
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Tutorial
{
	class Example
    {
        public int number = 0;
    }

    class Program
    {
        static void Main(string[] args)
        {
			Example num = new Example();
            Console.WriteLine("This is a test. {0}", num.number);
        }
    }
}
	

Classes are not very difficult at this stage. Note the unusual way of feeding in variables into strings. I'm surprised they didn't use the old C printf methodology but I'm grateful for it. I can't remember the notation and it does't fit well with a properly object oriented language.

	
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Tutorial
{
	class Example
    {
        public int Number { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
			Example num = new Example();
            num.Number = 1;
            Console.WriteLine("This is a test. {0}", num.Number);
        }
    }
}
	

This setup uses so-called properties, more specifically auto-implemented properties. This would be a good initial setup but let's see how this works if we want to add some custom logic to our Example class and its Number.

	
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Tutorial
{
	class Example
    {
        private int num = 0;
        public int Number
        {
            set
            {
                if (value == 1)
                {
                    num = 2;
                }
                else
                {
                    num = value;
                }
            }

            get
            {
                return num;
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
			Example num = new Example();
            num.Number = 1;
            Console.WriteLine("This is a test. {0}", num.Number);
        }
    }
}
	

Now we've decided to change things around so that whenever we try to set an Example-objects Number to 1, we actually set it to 2. Thus the example above prints out:

	
This is a test. 2
	

Notice how we haven't changed anything in the Program class for this thing. Encapsulation! Let's try something with file IO.

	
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace Tutorial
{
    internal class FileHandler
    {
        String fileA = "FileA.txt";
        String fileB = "FileB.txt";
        String currFile;

        internal FileHandler()
        {
            currFile = fileA;
        }

        internal void writeSecurely(IEnumerable text)
        {
            try
            {
                File.WriteAllLines(currFile, text);
                currFile = currFile.StartsWith("FileA") ? fileB : fileA;
            }
            catch (IOException exc)
            {
                Console.WriteLine("IOException");
            }
        }
    }


    class Example
    {
        private int num = 0;

        public int Number
        {
            set
            {
                if (value == 1)
                {
                    num = 2;
                }
                else
                {
                    num = value;
                }
            }

            get
            {
                return num;
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Example num = new Example();
            num.Number = 3;
            Console.WriteLine("This is a test. {0}", num.Number);

            FileHandler handler = new FileHandler();
            String line = " ";
            IList proxy = new List();
            while (line.Length > 0)
            {
                line = Console.ReadLine();
                proxy.Add(line);
                handler.writeSecurely(proxy);
            }
        }
    }
}
	

This is an implementation of an idea I had for a program called Robust Downloader and the point of this is to make sure that you can write metadata without risking to lose previous data. You would think that wouldn't be a problem but I've used Video-on-Demand services where downloads suffered from this problem. You could go to 23%, the downloader crashed. You start again, from 23% to 55%, then another crash. Next time around you start at 55% up to 73% at which point it crashes. NOW when you restart the download starts at 23%!

By writing metadata in a round-robin fashion we avoid these kinds of problem. I'm thinking about how to assure that the data itself isn't lost during writes without using this approach. A VoD download can be in the order of 1,3 GB so at the end of the download we would have amost 2,6 GB of space being used because of the two copies being used. Anyway, the main(String args[]) method reads lines from the console and writes them using the robust metadata method into files FileA.txt and FileB.txt.

Virtual and override

C# uses C++ style polymorphism which means that object methods are called based on the declared class(Employee e = new Boss(); e.getTitle() -> employee). This phenomenon is called method hiding and is the default inheritance strategy. The above notation assumes something like this:

	
class Employee {
	public String getTitle() {
		return "Employee";
	}
}

class Boss : Employee { // A boss is a form of employee
	public new String getTitle() {
		return "Boss";
	}
}
	

To get Java-style inheritance(what I call _proper inheritance_) can be achieved by this setup:

	
class Employee {
	public virtual String getTitle() {
		return "Employee";
	}
}

class Boss : Employee { // A boss is still a form of employee
	public override String getTitle() {
		return "Boss";
	}
}
	

This means that:

	
Employee e1 = new Employee();
e1.getTitle(); // returns "Employee"
Employee e2 = new Boss();
e2.getTitle(); // returns "Boss"
	

Delegates

A delegate is a method pointer.

	
class Alpha
{
	public static Boolean eins()
	{
		return true;
	}
}

class Beta
{
	public static Boolean zwei()
	{
		return false;
	}
}

aHandler alpha = Alpha.eins;
Console.WriteLine("Delegate test one: {0}", alpha());
alpha = Beta.zwei;
Console.WriteLine("Delegate test two: {0}", alpha());
	

This prints:

	
Delegate test one: True
Delegate test two: False
	

I got this explanation from a Shay Friedman(http://www.ironshay.com/post/My-Leading-Candidate-for-Worst-C-Feature-e28093-Method-Hiding.aspx) who doesn't like this C# feature any more than I do. Presumably the feature was included to maintain compatibility with C++ and also gives some performance benefits but I'll try to avoid it as best I can.

More stuff: