.comment-link {margin-left:.6em;}
My Photo
Name:
Location: Unspecified, Mauritius

I too, am a bug within Māyā.

My Other Blog(s) and Site(s)
Friend sites and blogs
My Recent Posts
Tutorials
Best Articles
My C-Sharp Ideas
Archives
Blog Directories

Tuesday, July 26, 2005

 

Free Gmail Invites

Yup, 50 free invites
[rowy loves you all, even if you don't C#]

I managed to set up Google Ads on my blog. Wasn't easy to make firefox and ie agree on a common template.

While strolling on the beach (yeah, I live at the beach. See my other blog), I've been cooking up some other really interesting C# projects (well, I'm still designing the recipe in my head). I was a bit pissed off about my console thingy - something like that already exists (thanks to Peter Jausovec for letting me know) but hey, there still are interesting things to do :D

Btw, for you guys out there... I'm giving out free Gmail invites. It's been nearly a year that I'm on Gmail, and I'm kinda tired of seeing all those invites... If you're interested, please leave a comment, or mail me at:

hehehe at gmail.com

[replace "hehehe" by "rowan.rishi" and "at" by "@"]
[you'll get the invite if you're smart enough to do that simple text replace]


Sunday, July 24, 2005

 

An Interesting C# Project

Missing the good ol' DOS console?
Let's revive the past!

I'm pretty nostalgic of MS-DOS... I was quite young when I first saw and used MS-DOS, which came with Basic. I used to copy examples from a Basic book, and then test them. That's when I began coding. I was five years old.

Languages have greatly evolved since Basic. C, C++, Pascal... and many many others. We're at a time when it'd take only a few months to develop a *really* cool console. However, when I say "cool", I don't mean a console using a single line Edit box, and a Multi line Edit box with a background on it. Hell, no.

I want a simple console, which is displayed on a real .Net console, with only a few inbuilt commands. The console would have a "Commands" directory, which would contain compiled .Net assemblies. The console, upon starting, would reflect inside of those dll's, and list out the commands available within them.

Of course, all commands would have to implement a "Command" interface, with an Execute method, which would accept as parameters an array of string (the list of arguments which the command should process), a Help method accepting a string as parameter and returning a string (which would provide help on a certain parameter), and a Description read-only property.

Does that sound too ambitious?

There are loads of problems that might arise during development of such a program. For example: what happens if there are two commands of the same name that exist?

Example:
Search.dll implements a Delete command
Files.dll Implements a Delete command

Could this issue be solved just like .Net deals with ambiguous names?

Does Search.Delete "expression" sound weird? Hmmm... it's something to look into. But for the moment, let me try to reflect inside assemblies, which aren't my own programs. That might be useful.


Saturday, July 23, 2005

 

Explicit Typecasts

Or also known as tranny-casts
[intermediate]

Implicit Typecasts are casts which occur when the compiler cannot directly treat one data type as another, and require "user intervention". By user intervention, I mean, user code :)

Trying to typecast a StreamReader into an ArrayList would be a bad idea. That's a typecasting that's not "meant to be" (would raise an InvalidCast Exception), and that's why the user should kick in his/her own code for it to happen.

As usual, I made another one of my useless classes, for the purpose of this tutorial. The Data class simply holds a name (string) and a DataValue (int). Also, I kicked in a few lines of code which would allow the data class to be typecasted as string (thus returning the name), or typecast as int (returning the DataValue). Check it out below:




/// <summary>
/// Simple class which holds a name (string) and a
/// value (int).
/// </summary>
public class Data
{
private string name;
private int dataValue;

/// <summary>
/// Instantiates a new Data class
/// </summary>
/// <param name="name">The name the data class
/// will hold</param>
/// <param name="dataValue">The value the data
/// class will hold</param>
public Data(string name, int dataValue)
{
this.name = name;
this.dataValue = dataValue;
}

/// <summary>
/// Gets or Sets the name
/// </summary>
public string Name
{
get
{
return this.name;
}
set
{
this.name = value;
}
}

/// <summary>
/// Gets or sets the Data Value
/// </summary>
public int DataValue
{
get
{
return this.dataValue;
}
set
{
this.dataValue = value;
}
}

/// <summary>
/// Allow typecasting into string
/// </summary>
/// <param name="someData">The data class
/// which needs to be typecasted</param>
/// <returns>The name of the data class</returns>
public static explicit operator string(Data someData)
{
string retValue = someData.name;
return retValue;
}

/// <summary>
/// Allow typecasting into int
/// </summary>
/// <param name="someData">The data class
/// which needs to be typecasted</param>
/// <returns>The value of the data class</returns>
public static explicit operator int(Data someData)
{
int retValue = someData.dataValue;
return retValue;
}
}



The only part of this code that interests us is:



/// <summary>
/// Allow typecasting into string
/// </summary>
/// <param name="someData">The data class
/// which needs to be typecasted</param>
/// <returns>The name of the data class</returns>
public static explicit operator string(Data someData)
{
string retValue = someData.name;
return retValue;
}

/// <summary>
/// Allow typecasting into int
/// </summary>
/// <param name="someData">The data class
/// which needs to be typecasted</param>
/// <returns>The value of the data class</returns>
public static explicit operator int(Data someData)
{
int retValue = someData.dataValue;
return retValue;
}



Note that those two methods are static, and marked with the explicit and operator keywords. The first method simply contains code that is going to be executed if the user decides to typecast into a string. Note that the return type (i.e. the operation of the casting) is a string. The value in parameters is a Data class, i.e. the data class that's being typecasted into a string. The next lines of code are pretty easy. The name of the Data class is extracted by looking into the Data class passed into parameters, and this value returned (it's a string anyway).

And that's all there is to explicit typecasting. The second method does pretty much the same, but allows typecasting into an int (notice: the return type's an int). Here's how I explicitly typecasted my Data class into a string, and then an int.


/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
Data myData = new Data("Bebs", 19);

Console.WriteLine((string)myData);
Console.WriteLine(((int)myData).ToString());

Console.ReadLine();

}

Yup... and it works :) The complete source code can be found below:



using System;


namespace UselessStuff
{
/// <summary>
/// MultiParam App
/// </summary>
class UselessMain
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
Data myData = new Data("Bebs", 19);

Console.WriteLine((string)myData);
Console.WriteLine(((int)myData).ToString());

Console.ReadLine();

}
}

/// <summary>
/// Simple class which holds a name (string) and a
/// value (int).
/// </summary>
public class Data
{
private string name;
private int dataValue;

/// <summary>
/// Instantiates a new Data class
/// </summary>
/// <param name="name">The name the data class
/// will hold</param>
/// <param name="dataValue">The value the data
/// class will hold</param>
public Data(string name, int dataValue)
{
this.name = name;
this.dataValue = dataValue;
}

/// <summary>
/// Gets or Sets the name
/// </summary>
public string Name
{
get
{
return this.name;
}
set
{
this.name = value;
}
}

/// <summary>
/// Gets or sets the Data Value
/// </summary>
public int DataValue
{
get
{
return this.dataValue;
}
set
{
this.dataValue = value;
}
}

/// <summary>
/// Allow typecasting into string
/// </summary>
/// <param name="someData">The data class
/// which needs to be typecasted</param>
/// <returns>The name of the data class</returns>
public static explicit operator string(Data someData)
{
string retValue = someData.name;
return retValue;
}

/// <summary>
/// Allow typecasting into int
/// </summary>
/// <param name="someData">The data class
/// which needs to be typecasted</param>
/// <returns>The value of the data class</returns>
public static explicit operator int(Data someData)
{
int retValue = someData.dataValue;
return retValue;
}
}
}


 

A few typeof(System.Random) thoughts

I thought up of the advantages of coding vs. going out with someone:

Why is coding better than going out with someone?

1. Your programs use only your processing time.
2. Your programs use only your pc's resources.
3. Problems with a program can be solved by debugging.
4. Programs can be terminated any time you wish.
5. Programs don't mind when they execute with other programs.
6. Programs carry out all the commands you give them. Without bitching you.
7. Programs don't lie.
8. Big programming mistakes at worse end up with a system reboot or re-install.


I just went through shit to fix my blog's template. I added a few meta tags, and suddenly decided that maybe I should try viewing it in Internet Explorer. Yeah, well, hehe, I use Firefox.

The template was totally fucked up, with my menu below the main posts... Jesus Christ... spent about half an hour trying to find a balance between "good looking", "IE Compatible" and "Firefox Compatible". Well, template's fixed, and it all looks fine. I even managed to stretch the orange seperator...

I got a few ideas for new tutorials. I wonder when I'll have time to write them down though. I'll write about chaining constructors, implicit and explicit typecasts, some beginner's stuff about Interfaces, and maybe Datasets.

Ah, yeah. Datasets. Would that be beginner or intermediate? Hmm... Maybe I can cook up several tutorials on datasets - one for beginners and one for intermediates.

Also, I wanted to write something about NUnit, and good programming practises. Hmm... I'll do that soon enough.

Anyway, I've been reading (or trying to read) the CSharp 2.0 Specs document from Microsoft. I know, that's kinda old - I heard that CSharp 3.0 specs are coming out soon. I think that the new features of C# have been throughly detailed in many places throughout the web, but there's something I'd love to comment on, especially about the Generic types, and the Nullable types. I believe that C# code's really understandable, and pretty neat as well. However, with the introduction of the "<", ">", "?" and also "::" signs, the face of C# as we all know it is going to change. What I mean by "the face of C#" is how general C# code looks like. C# code with Generics and nullable types look pretty weird. Okay, maybe that's because I'm not used to see that kind of C# code... but there's something telling me that C# code might look very nasty in Whidbey.

On the whole, the CSharp 2.0 specs come round with loads of good news. Here's a quick summary of a few of the interesting things I saw:

1. Generics
I think that's one of the most publicized things about Whidbey. An example of the use of Generics could be an Arraylist, that's forced to accept only one kind of object, through the use of Generics. I.e. You can create an arraylist that accepts only strings, or integers. Writing generic classes, however, might get a little bit confusing.

2. Nullable types
Well, simply put, a nullable type is a data type which has, apart from its value, a boolean value indicating whether the value on it has been set or not. So you can perform checks on variables, to see whether they've been initialized or not, through the HasValue property.

3. Easier implementation of IEnumerable
Those of you who think that it's troublesome to implement IEnumerable (like me, for example), will be overjoyed to hear that there's now a much easier method to do it, thanks to the yield newly-introduced yeild break and yeild return keywords.

Hmm... well... there's more to Whidbey than what I've described here, namely anonymous methods and so on, but seriously, it's getting kinda late here. I think I'll go to sleep for a change.

Have a nice day, and may the code be with you.


Friday, July 22, 2005

 

Situation of Programmers in Mauritius

Every little kid out of high school wants to study computer science and engineering in university. However, many of them are just into comp. science because it's something popular to study. Yes, it's a "popular" subject.

I wouldn't recommend computer science and engineering to people who just don’t know what they’re going to do later. You’ll end up hating the coding, and coding is what you’ll spend your time doing.

Personally, I eat, drink, sleep and live with code. I don’t think I’ll get bored of coding someday. Coding… or designing software / classes. But you might. And you’ll hate your work, the company you work for, and your life in the end.

Anyway, you might also turn out to be a great coder, and actually enjoy coding. Who knows? But don’t rush into computer science and engineering just because it’s the only best thing to study right after agriculture.

Now, a little update for you guys. As soon as you’re out of university, you won’t be earning a lot. Nope. A certain company in Mauritius recruited a few programmers (that was last year), and paid them Rs 8000 / month. That’s about US$ 280 a month. After six months of training, their salary was raised to Rs 11, 000 – Rs 12,000 (US$ 385 - US$ 420). I’ve heard that another company (located in the cybertower) pays its programmers US$ 525 a month (Rs 15,000). Is there really a future for programming in here?

The main argument of most employers is – “Mauritian programmers just can’t code properly.”

True. Before becoming a good programmer, what you need is experience. As a friend of mine once said – “Fucking muppets need fucking training”. To all of you guys who chose comp. sci and eng. just because it’s a cool thing to study – you’re not going to go far if you don’t start moving your butt.

Also, if we didn’t have so many people studying computer science, we’d probably be off with a smaller number of programmers, but more motivated and skilled.


Good Programming

Good programming practices are what will make of you a better coder. You can either learn the hard way – i.e. code, code, and keep coding. You’ll eventually understand why people use try’s and catch’es. You’ll understand why people put comments in their code, why people use NUnit. You could also start learning about good programming practices right now. There are tips and hits everywhere on the net.

The Substandard Programming Nation

As someone previously pointed out to me, the education system in here is all about spoon-feeding. That’s why most Mauritian programmers would back off as soon as they hear that they got to implement a shortest-path algorithm on a graph.

“Hell, isn’t there a method to do that in C#?”

Jesus fucking Christ. C# does have a lot of methods, but they’re here to make your life easier, not to do all the work. What, did you expect to find a method WankMe()? Well, FuckYou(). You need to work on your coding skills. Else, Mauritius will only be a god-damned sub-standard outsourcing paradise destination, with only sub-standard programmers who don’t know that there needs to be a try and a catch statement when trying to open a file.

That said, let us not forget that there really are some good coders in this country. People who are really motivated to learn more, sharpen their skills, and become good and better coders.

It’s all about the code.



 

Sex and C#

Single 19 (soon to be 20) year old male, looking for female of the same age range for friendship or better, preferably living in Mauritius, sharing same passions about C#. Must understand polymorphism, be able to use enumerated types, must know how to chain constructors and use indexers, must have a vague idea (or better) of what MSIL could be and must know how to use different threading models in C#. Preference will be given to candidates who have knowledge of ASP.Net and to candidates who have big breasts.

Any intimate encounter will occur in XML.


 

Yet another cool and useful feature

The Params keyword
[Beginner]


The params keyword could be one of the coolest features of C-Sharp, if you haven't heard of it yet. Simply put, it allows you to enter multiple parameters of a same type. An alternative to this could be the use of an array - i.e. create a method that accepts an array of a certain kind of objects, but that's really troublesome. Here, check the code out - it's pretty simple and straightforward:




using System;

namespace MultiParams
{
/// <summary>
/// MultiParam App
/// </summary>
class MyClass
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
Console.WriteLine(AddAll(43, 94, 29, 958, 3283, 9285).ToString());
Console.ReadLine();
}

public static double AddAll(params int[] numbers)
{
double total = 0;

foreach(int i in numbers)
{
total += i;
}

return total;
}
}
}


What really interests us is the AddAll method. Let's have a closer look:



public static double AddAll(params int[] numbers)
{
double total = 0;

foreach(int i in numbers)
{
total += i;
}

return total;
}



There's nothing particular in that method, apart from the "params" keyword used in the parameters. It's pretty strightforward. The use of the params in the parameters allows users to pass multiple values (in this case, multiple int's) of the same type - they all get kicked into an array of that object type (in this example, an array of int, which I named "numbers"). Using this function gets really easy now. All you have to do is to call the AddAll method with as much number of integer parameters as you want! Et voilà! Rien de plus façile! I called the AddAll method, and passed in a few numbers - and called the ToString() method.

Now, think of your own ways to make a good use of the params keyword ;)


Thursday, July 21, 2005

 

A few basic things

Decimal Places
[Beginner]


There are quite a few things to know before really getting the hang of C#, and I believe that learning about how to format numbers that need to be output is something pretty basic, that many programmers disregard. However, here's a basic tutorial about controlling the number of decimal places that a decimal type displays.

Let's move on directly to the code. It's simple. Nothing complicated to understand. Check it out:


using System;
using System.Globalization;

namespace NumberFormat
{
/// <summary>
/// MultiParam App
/// </summary>
class Class1
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
NumberFormatInfo myFormat = new NumberFormatInfo();
double d = 15.6781005479;

for (int i=0; i<=10; i++)
{
myFormat.NumberDecimalDigits = i;
Console.WriteLine(i.ToString() +
" decimal digit(s): \t\t"+d.ToString("N", myFormat));
}

Console.ReadLine();
}
}
}


Notice that I've included System.Globalization in the usings. This is a namespace that is required in order to use the NumberFormatInfo class.

What I did was basically to instantiate a NumberFormatInfo class, and play with the NumberDecimalDigits property (which I kept incrementing). Watch the results on a console :) Also, note the use of the overloaded ToString() method, in which I passed two parameters, namely a string ("N"), and the NumberFormatInfo class that I instantiated.

Hope this little code snippet helps!


 

C# News

The graph below shows the number of times programmers of different languages got dates or were turned down while asking for a date.




C# programmers enjoy a more sexually-active life. Experts can only agree.

After an interview with Jack (fake name), an application optimizer (he uses ASM), we found out the real truth behind the lives of programmers who made bad choices.

"I was under a lot of stress at home. I kept having fights with my wife, Tabitha (fake name). I knew it was because of it [the programming language I used]. I had to change, but I wasn't very sure which one. I went for VB. That, I think, was the worse decision of all my life."

Like Jack, many programmers suffered the choices of their language. Ben (fake name), a C++ programmer earning US$4000 per month, was caught by his wife using Java at home. "She couldn't believe it. She sent me the divorce papers one week later," confides Ben, still trying to recover from his loss.

Some, however, seem to have understood what a programmer's life was all about. Sonya (fake name), a 24 year old hottie, agreed to share information on her programming past with us.

"Before, I couldn't even get laid. Guys wouldn't even look at me. I was a Java programmer." Her sad expression reflects her unhappy past. "Fortunately, a friend of mine introduced me to C#. I easily got the hang of it, and found the language very comfortable to use." We had doubts about Sonya's claims on her inactive sexual life, when she explained to us: "I couldn't believe it. After two months of using C#, my breasts started to grow larger, and my butt and thighs more firm. It was incredible!". Sonya now enjoys a peaceful life with Brandon (fake name), also a C# programmer. They're expecting a baby this November. "If it's a boy, we're gonna call him Whidbey," the happy couple told us.


 

Indexers

Indexers in C#
Intermediate

I've been up to nothing good on C#, and I thought I'd post something about indexers on C#. Being able to provide a collection class with an indexer could be a real cool thing, if you know how to do it :)

Indexers allow your class(es) to be treated like arrays - an "index" is passed in between square brackets, and an object is returned. Just like an arraylist. Or an array :)

To begin my second C# tutorial, please take a look at the utterly useless Item class:




/// <summary>
/// Just a dummy class named Item, with a few properties.
/// </summary>
public class Item
{
//Name represents the name of the item class
private string name;
//Data represents a data value
private string data;

/// <summary>
/// Constructor for the Item class.
/// </summary>
/// <param name="name">String representing the name of the class</param>
/// <param name="data">Data the class will hold</param>
public Item(string name, string data)
{
this.name = name;
this.data = data;
}

/// <summary>
/// Gets or sets the name of the class
/// </summary>
public string Name
{
get
{
return this.name;
}
set
{
this.name = value;
}
}

/// <summary>
/// Gets or sets the it's data value
/// </summary>
public string Data
{
get
{
return this.data;
}
set
{
this.data = value;
}
}

// - Little Note -
// It's always good to use properties instead of
// directly exposing a variable as public
}



Well, as you can see, the Item class doesn't do anything particular. Of course, it's just a dummy class, created for the purpose of this tutorial. What would interest you would be the ItemHolder class - a class that can actually accept a collection of items. Check out the code below:




/// <summary>
/// A class that can hold Items
/// </summary>
public class ItemHolder
{
//This arraylist will actually contain all the items
private ArrayList itemList;

/// <summary>
/// Creates a new instance of the ItemHolder class, which is able
/// to hold multiple items.
/// </summary>
public ItemHolder()
{
itemList = new ArrayList();
}

/// <summary>
/// Indexer for the ItemHolder class
/// </summary>
public Item this[int pos]
{
get
{
//Check whether the position is within the arraylist's index bounds
if ((pos > this.itemList.Count-1) || (pos < 0))
{
Exception myExcp =
new Exception("Index was out of bounds of array");
throw myExcp;
}
else
{
//typecast to Item, and return
return ((Item)this.itemList[pos]);
}
}

set
{
//Check whether the position is within the arraylist's index bounds
if ((pos > this.itemList.Count-1) || (pos < 0))
{
Exception myExcp =
new Exception("Index was out of bounds of array");
throw myExcp;
}
else
{
//Make a type check, just in case
if (value.GetType() == typeof(Item))
{
Exception myExcp =
new Exception("You can only assign objects of the type \"Item\"");
throw myExcp;
}
else
{
this.itemList[pos] = value;
}
}
}
}

/// <summary>
/// Adds an item to the collection of Items
/// </summary>
/// <param name="someItem"></param>
public void AddItem(Item someItem)
{
//Check whether the item's not null
if (someItem != null)
{
this.itemList.Add(someItem);
}
else
{
Exception myExcp =
new Exception("Null objects are not allowed in this collection");
throw myExcp;
}
}

/// <summary>
/// Returns a count of the total number of items inside
/// the this object
/// </summary>
public int Count
{
get
{
return this.itemList.Count;
}
}
}


Do take a closer look at the indexer:




/// <summary>
/// Indexer for the ItemHolder class
/// </summary>
public Item this[int pos]
{
get
{
//Check whether the position is within the arraylist's index bounds
if ((pos > this.itemList.Count-1) || (pos < 0))
{
Exception myExcp =
new Exception("Index was out of bounds of array");
throw myExcp;
}
else
{
//typecast to Item, and return
return ((Item)this.itemList[pos]);
}
}

set
{
//Check whether the position is within the arraylist's index bounds
if ((pos > this.itemList.Count-1) || (pos < 0))
{
Exception myExcp =
new Exception("Index was out of bounds of array");
throw myExcp;
}
else
{
//Make a type check, just in case
if (value.GetType() == typeof(Item))
{
Exception myExcp =
new Exception("You can only assign objects of the type \"Item\"");
throw myExcp;
}
else
{
this.itemList[pos] = value;
}
}
}
}


This is what we're interested in. Disregard the code - it's just exceptions I couldn't resist throwing just in case the wrong type's being used (I'm forcing the use of Item types of objects inside the collection). The indexer doesn't get more complicated than





public <DataType> this[<DataType> <VariableName>]
{
get
{
}

set
{
}
}


Where the first DataType represents the return type of the indexer, the second DataType the type of the value passed into the square brackets, and VariableName the name of the variable that you want to use for the value that the user has provided. There's also a get and a set property (the accessors) which enable you to execute different code, depending on whether the user's only reading the value, or modifying it.

Now, for the code inside the indexer -

Notice that my indexer directly returns an Item (saves you the typecasting, heh), given an int - which represents the index value of the Item inside of my collection. When the user tries to get an item, the get part of the accessor is executed. I made a little check on the value of the index being passed. Passing -1 would most certainly raise an exception - as well as passing a value outside of the bounds of the collection.

In the set accessor, I had to carry out even more checks - apart from the bounds checking, I also made a little check on the type of value being set. I modified the code a little bit, because using "is" creates more solid code than using GetType() (see below). The is keyword checks for parent objects, and the GetType() only checks for the type. Below is the code that I replaced:





//Make a type check, just in case
if (value is Item)
{
Exception myExcp =
new Exception("You can only assign objects of the type \"Item\"");
throw myExcp;
}
else
{
this.itemList[pos] = value;
}



Instead of:





//Make a type check, just in case
if (value.GetType() == typeof(Item))
{
Exception myExcp =
new Exception("You can only assign objects of the type \"Item\"");
throw myExcp;
}
else
{
this.itemList[pos] = value;
}


The set accessor first checks whether the index passed resides within the collection's bounds (more than -1, less than the count of number of items), and then checks for the type being set; after modification of the code, an object derived from Item will also be accepted in the Indexer.

Note that I also implemented an AddItem method, which allows users to kick in Items into the collection (without which, this whole class would be useless), and a Count property, which allows users to get the number of total items inside of the class. Of course, I could've elaborated, implemented a Delete method and so on, but that's up to you. Below is the code that I used to make the Item and ItemHolder classes work:




[STAThread]
static void Main(string[] args)
{
Item myItem1 = new Item("Rowan",
"Shit happens");

Item myItem2 = new Item("Vidi",
"Life is a bitch, and then you die");

Item myItem3 = new Item("Natasha",
"Good girls go to heaven, Bad girls get what they want");

ItemHolder holder = new ItemHolder();
holder.AddItem(myItem1);
holder.AddItem(myItem2);
holder.AddItem(myItem3);

for (int i=0; i<=holder.Count-1; i++)
{
Console.WriteLine("Name: " + holder[i].Name);
Console.WriteLine("Quote: " + holder[i].Data);
Console.WriteLine();
}

Console.ReadLine();
}


Here's the complete code for the tutorial:



using System;
using System.Collections;

namespace Indexer
{
/// <summary>
/// Comments are pretty useful, even in tutorials
/// </summary>
class IndexerTest
{
/// <summary>
/// Main entry pt. for app.
/// </summary>
[STAThread]
static void Main(string[] args)
{
Item myItem1 = new Item("Rowan",
"Shit happens");

Item myItem2 = new Item("Vidi",
"Life is a bitch, and then you die");

Item myItem3 = new Item("Natasha",
"Good girls go to heaven, Bad girls get what they want");

ItemHolder holder = new ItemHolder();
holder.AddItem(myItem1);
holder.AddItem(myItem2);
holder.AddItem(myItem3);

for (int i=0; i<=holder.Count-1; i++)
{
Console.WriteLine("Name: " + holder[i].Name);
Console.WriteLine("Quote: " + holder[i].Data);
Console.WriteLine();
}

Console.ReadLine();
}
}

/// <summary>
/// Just a dummy class named Item, with a few properties.
/// </summary>
public class Item
{
//Name represents the name of the item class
private string name;
//Data represents a data value
private string data;

/// <summary>
/// Constructor for the Item class.
/// </summary>
/// <param name="name">String representing the name of the class</param>
/// <param name="data">Data the class will hold</param>
public Item(string name, string data)
{
this.name = name;
this.data = data;
}

/// <summary>
/// Gets or sets the name of the class
/// </summary>
public string Name
{
get
{
return this.name;
}
set
{
this.name = value;
}
}

/// <summary>
/// Gets or sets the it's data value
/// </summary>
public string Data
{
get
{
return this.data;
}
set
{
this.data = value;
}
}

// - Little Note -
// It's always good to use properties instead of
// directly exposing a variable as public
}


/// <summary>
/// A class that can hold Items
/// </summary>
public class ItemHolder
{
//This arraylist will actually contain all the items
private ArrayList itemList;

/// <summary>
/// Creates a new instance of the ItemHolder class, which is able
/// to hold multiple items.
/// </summary>
public ItemHolder()
{
itemList = new ArrayList();
}

/// <summary>
/// Indexer for the ItemHolder class
/// </summary>
public Item this[int pos]
{
get
{
//Check whether the position is within the arraylist's index bounds
if ((pos > this.itemList.Count-1) || (pos < 0))
{
Exception myExcp =
new Exception("Index was out of bounds of array");
throw myExcp;
}
else
{
//typecast to Item, and return
return ((Item)this.itemList[pos]);
}
}

set
{
//Check whether the position is within the arraylist's index bounds
if ((pos > this.itemList.Count-1) || (pos < 0))
{
Exception myExcp =
new Exception("Index was out of bounds of array");
throw myExcp;
}
else
{
//Make a type check, just in case
if (value is Item)
{
Exception myExcp =
new Exception("You can only assign objects of the type \"Item\"");
throw myExcp;
}
else
{
this.itemList[pos] = value;
}
}
}
}

/// <summary>
/// Adds an item to the collection of Items
/// </summary>
/// <param name="someItem"></param>
public void AddItem(Item someItem)
{
//Check whether the item's not null
if (someItem != null)
{
this.itemList.Add(someItem);
}
else
{
Exception myExcp =
new Exception("Null objects are not allowed in this collection");
throw myExcp;
}
}

/// <summary>
/// Returns a count of the total number of items inside
/// the this object
/// </summary>
public int Count
{
get
{
return this.itemList.Count;
}
}
}


}


Thursday, July 14, 2005

 

IComparer Interface

Sorting out your problems
[Intermediate]

I made a small but cute class for Person - there's Name, which identifies the person's name and there's Age, which represents the person's age.

Creating multiple instances of the persons class would require me to kick them all into an ArrayList - which I did. I had a precise idea in mind: I wanted the ArrayList to sort my list of Persons by either name or age.

This is when I learnt about the IComparer and IComparable interfaces. However, in this tutorial, we're going to focus on the IComparer interface. Please note that the IComparer interface requires the use of System.Collections. Below is the code for my Person class.

/// <summary>
/// The Person class contains the name of the person and the age of
/// the person.
/// </summary>
public class Person
{
//private string holding person's name
private string name;

//private int holding person's age
private int age;

/// <summary>
/// Creates a new Person object with the specified name and age.
/// </summary>
/// <param name="name">The name of the person</param>
/// <param name="age">The age of the person</param>
public Person(string name, int age)
{
this.name = name;
this.age - age;
}

/// <summary>
/// Gets or sets the name of the person
/// </summary>
public string Name
{
get
{
return this.name;
}
set
{
this.name = value;
}
}

/// <summary>
/// Gets or sets the age of the person
/// </summary>
public int Age
{
get
{
return this.age;
}
set
{
this.age = value;
}
}
}

A class implementing the IComparer interface can be passed onto the ArrayList.Sort method to provide the latter with a means of comparing two values. Why compare two values? Simple, because the QuickSort algorithm (which the arraylist obviously implements) works by consecutively comparing two values. Any quicksort algorithm can easily be adapted on a set of data, given the comparing method.

What's left to do is to create a class which implements the IComparer method. Also, we might wish to allow for "customization" of that class, i.e. allow different means of sorting. To do this, I created an enumerated type which would hold the different types of sorting. See the code below:




/// <summary>
/// Enumerator for types of person sorting
/// </summary>
public enum SortPersonsBy {byName, byAge};

/// <summary>
/// Person Sorting Class, implements IComparer
/// </summary>
public class SortPersons : IComparer
{
//Private value holding the Persons sort type
private SortPersonsBy sortType;

/// <summary>
/// Creates a new instance of the SortPersons class. Use this class to specify sorting
/// methods for arraylists filled with only persons.
/// </summary>
/// <param name="sortingType"></param>
public SortPersons(SortPersonsBy sortingType)
{
this.sortType = sortingType;
}

/// <summary>
/// Gets or sets the SortPersonsBy type.
/// </summary>
public SortPersonsBy SortType
{
get
{
return this.sortType;
}
set
{
this.sortType = value;
}
}

/// <summary>
/// Implementation of the Compare method, required for the IComparer class
/// </summary>
/// <param name="x">First object</param>
/// <param name="y">Second object</param>
/// <returns>An int, which is the value obtained when the two objects
/// have been compared.</returns>
public int Compare(object x, object y)
{
//Check whether x and y are both Person classes.
if ((x is Person) && (y is Person))
{
//Some little typecasting
Person a = (Person)x;
Person b = (Person)y;

//Check the sorting type
if (this.sortType == SortPersonsBy.byName)
{
//Use the native string.CompareTo method
return (a.Name.CompareTo(b.Name));
}
else
{
//Use the native int.CompareTo method
return (a.Age.CompareTo(b.Age));
}
}
else
{
//return 0 if x or y are of wrong type
return 0;
}
}

}

The code above contains an enumerated type and a SortPersons class, which implements the IComparer interface. The SortPersons class has a SortPersonsBy property, which allows the user to choose between sorting by name and sorting by age.

When the ArrayList.Sort() method is called with a SortPersons class, the Compare method is executed numerous times. First of all, my Compare method checks for the types of objects - i.e. whether they are persons or not. If one of them isn't a Person class, the Compare method returns 0. If they both are Person classes, the type of sorting is checked. If the type of sorting is set to "byName", the string's CompareTo method is called using the two person's names; if the type of sorting is set to "byAge", the int's CompareTo method is called using the two person's ages.

And that's it! Here's the full source code of my app:




using System;
using System.Collections;

namespace SortProject
{
/// <summary>
/// The Main Class
/// </summary>
class MainClass
{
/// <summary>
/// Con. App. Entry Pt.
/// </summary>
[STAThread]
static void Main(string[] args)
{
//Create a few persons
Person a = new Person("Rowan", 19);
Person b = new Person("Rishi", 19);
Person c = new Person("Vidisha", 18);
Person d = new Person("Dominique", 21);
Person e = new Person("Arvind", 22);
Person f = new Person("Mom", 49);
Person g = new Person("Visitor", -1);

//Create a SortPersons object, and set the sorting type to "byName"
SortPersons mySortingMethod = new SortPersons(SortPersonsBy.byName);

//Create a new arraylist and kick in the persons
ArrayList someList = new ArrayList();
someList.Add(a);
someList.Add(b);
someList.Add(c);
someList.Add(d);
someList.Add(e);
someList.Add(f);
someList.Add(g);
someList.Sort(mySortingMethod);

Console.WriteLine("Sorting persons by name: \n\n");

//Display the list of persons
for (int i=0; i<= someList.Count-1; i++)
{
Person somePerson = ((Person)someList[i]);
Console.WriteLine("Person Name: " + somePerson.Name +
"\t\tPerson Age: " + somePerson.Age);
}

Console.WriteLine("Sorting the persons by age: \n\n");

//Set the sorting type to "byAge" and resort the ilst
mySortingMethod.SortType = SortPersonsBy.byAge;
someList.Sort(mySortingMethod);

//Re-Display the list of persons
for (int i=0; i<= someList.Count-1; i++)
{
Person somePerson = ((Person)someList[i]);
Console.WriteLine("Person Name: " + somePerson.Name +
"\t\tPerson Age: " + somePerson.Age);
}

Console.ReadLine();
}
}

/// <summary>
/// The Person class contains the name of the person and the age of
/// the person.
/// </summary>
public class Person
{
//private string holding person's name
private string name;

//private int holding person's age
private int age;

/// <summary>
/// Creates a new Person object with the specified name and age.
/// </summary>
/// <param name="name">The name of the person</param>
/// <param name="age">The age of the person</param>
public Person(string name, int age)
{
this.name = name;
this.age = age;
}

/// <summary>
/// Gets or sets the name of the person
/// </summary>
public string Name
{
get
{
return this.name;
}
set
{
this.name = value;
}
}

/// <summary>
/// Gets or sets the age of the person
/// </summary>
public int Age
{
get
{
return this.age;
}
set
{
this.age = value;
}
}
}

/// <summary>
/// Enumerator for types of person sorting
/// </summary>
public enum SortPersonsBy {byName, byAge};

/// <summary>
/// Person Sorting Class, implements IComparer
/// </summary>
public class SortPersons : IComparer
{
//Private value holding the Persons sort type
private SortPersonsBy sortType;

/// <summary>
/// Creates a new instance of the SortPersons class. Use this class to specify sorting
/// methods for arraylists filled with only persons.
/// </summary>
/// <param name="sortingType"></param>
public SortPersons(SortPersonsBy sortingType)
{
this.sortType = sortingType;
}

/// <summary>
/// Gets or sets the SortPersonsBy type.
/// </summary>
public SortPersonsBy SortType
{
get
{
return this.sortType;
}
set
{
this.sortType = value;
}
}

/// <summary>
/// Implementation of the Compare method, required for the IComparer class
/// </summary>
/// <param name="x">First object</param>
/// <param name="y">Second object</param>
/// <returns>An int, which is the value obtained when the two objects
/// have been compared.</returns>
public int Compare(object x, object y)
{
//Check whether x and y are both Person classes.
if ((x is Person) && (y is Person))
{
//Some little typecasting
Person a = (Person)x;
Person b = (Person)y;

//Check the sorting type
if (this.sortType == SortPersonsBy.byName)
{
//Use the native string.CompareTo method
return (a.Name.CompareTo(b.Name));
}
else
{
//Use the native int.CompareTo method
return (a.Age.CompareTo(b.Age));
}
}
else
{
//return 0 if x or y are of wrong type
return 0;
}
}

}

}


 

Introduction

Do You See Sharp?

Welcome to my Blog! It's not exactly a blog, it's more of a tutorial-oriented consecutive series of html pages organised into a blog.

I don't really have time (nor the necessary funds :( ) to buy webspace - but hey! Blogger's here to help :)

Anyway, let me post this and move on to the first C# tutorial!

Rowy