Wednesday, April 23, 2008

Delegates

The word "delegate" means "to represent another". A delegate in .NET is just another type, like class or string is a type. A delegate "represents another" method. I'll give examples of using a delegate next to a class so you can see some similarities in how they are used.

Declaring
// 1. Declare it.
public delegate int PerformCalculation(int x, int y);
public class Person
{
    public string GetName()
    {
        return "Mark";
    }
}
So it is like declaring any other type except instead of a variable name, you will be using a method signature. The method name (PerformCalculation) is how you reference the delegate.
You declare the variable "PerformCalculation" as the type "delegate". Think of it as defining a method signature (just like you would in an interface) and then putting the word "delegate" in front of it.

Assigning a Value
public void CreateAndUse()
{
    // 2. Assign a value.
    PerformCalculation calc = AddNumbers;
    Person person = new Person();
}

public int AddNumbers(int number1, int number2)
{
    return number1 + number2;
}
See how methods, like AddNumbers, are treated just like objects here? I assign it to my PerformCalculation delegate type. Make sure the signatures are similar.

Using It
// 3. Use it.
int sum = calc(1, 2);
string name = person.GetName();
Remember, your delegate is used to "represent another" method. So when you go to use it, you use it (call it) like a method.

Passing It
Like any object, you can pass it into methods or return it from methods. Here is an example of passing it into a method:
// 4. Pass it.
calc = SubtractNumbers;
string result = CalculateFreeSpace(calc, person);

//...

private int SubtractNumbers(int number1, int number2)
{
    return number1 - number2;
}

private string CalculateFreeSpace(PerformCalculation calc, Person person)
{
    int maxLength = 50;
    int freeSpace = calc(maxLength, person.GetName().Length);
    return string.Format("Free Space Left: {0}", freeSpace);
}
Before I passed as a parameter into the CalculateFreeSpace method, I decided to have it represent a different method with a similar signature.
Pretty interesting, huh? Here, I am injecting customized functionality into the method.
This opens up possibilities to you. You can use this as a way of doing your unit testing. Perhaps the delegate you pass in really calls a SQL Server. So before your unit test calls the method to be tested, you create your delegate to return a hard-coded result instead of calling your SQL Server.

I will be talking more about delegates tomorrow as well.

More Info: MSDN: Delegates

Tuesday, April 22, 2008

Formatting DateTime Strings

The DateTime object has some handy built in methods to format your date like .ToShortDateString() or .ToLongTimeString(). But often you need to combine two formats. Here are some ideas.
string format1 = string.Format("{0} {1}", DateTime.Now.ToShortDateString(), DateTime.Now.ToLongTimeString());
Here, I am just concatenating the output from two methods. There must be an easier way! To get the same exact output, you can customize the format of your ToString() output:
string format2 = DateTime.Now.ToString("M/dd/yyyy h:mm:ss tt");
You could also encapsulate this functionality into an extension method if you use it enough:
public static class DateTimeExtensions
{
    public static string ToShortDateLongTimeString(this DateTime d)
    {
        return d.ToString("M/dd/yyyy h:mm:ss tt");
    }
}
// ...
// To consume this extension method:
string format3 = DateTime.Now.ToShortDateLongTimeString();

More Info: MSDN: DateTime.ToString
More Info: List of ToString Formats

Monday, April 21, 2008

StartsWith, EndsWith

Here are a couple of useful methods that the string class provides. String.StartsWith and String.EndsWith.
List<string> names = new List<string>();
names.Add("Moeykens");
names.Add("Agee");
names.Add("Talbot");
names.Add("major");

foreach (string name in names)
{
    if (name.StartsWith("M", true, null))
        Console.WriteLine(name);
}

foreach (string name in names)
{
    if (name.EndsWith("e"))
        Console.WriteLine(name);
}
The first foreach loop will return:
Moeykens
major
The second parameter for the StartsWith method is set to "true" which tells the class to ignore case.

The second foreach will return:
Agee

More Info: MSDN: String.StartsWith
MSDN: String.EndsWith

Friday, April 18, 2008

SortedList and SortedDictionary Generics

The SortedList and SortedDictionary generic classes are very similar. They are strongly typed at declaration time and as you add items to the collections they become sorted.
SortedList<string, int> list = new SortedList<string, int>();
list.Add("Jake", 2);
list.Add("Rich", 4);
list.Add("Aaron", 1);
list["Mark"] = 3; // Adds entry if not found.

foreach (KeyValuePair<string, int> pair in list)
{
    Console.WriteLine(pair.Value + " - " + pair.Key);
}
The result of the foreach looks like this:
1 - Aaron
2 - Jake
3 - Mark
4 - Rich

The code above can be swapped out with a SortedDictionary with no problems.

One of the main differences between the SortedList and the SortedDictionary is that SortedList also contains an index value in addition to a key and a value for each item in the collection. Therefore it has methods and properties around this feature.
int index = list.IndexOfKey("Aaron");
int index2 = list.IndexOfValue(3);
list.RemoveAt(3);
The SortedDictionary cannot be used in substitution of the SortedList in the code above. Because SortedList has indexes it also comes with additional overhead. So if you do not have the need for the indexes, I would stick with the SortedDictionary.
More Info: MSDN: SortedList and SortedDictionary Collection Types

Thursday, April 17, 2008

Dictionary - Collection

The Dictionary is class that can hold a collection of strongly typed key value pairs.
Dictionary<int, string> dictionary = new Dictionary<int, string>();
dictionary.Add(1, "Mark Moeykens");
dictionary.Add(2, "Jake Agee");
// Will add "Rich Talbot" if indexer (3) not found.
dictionary[3] = "Rich Talbot";

string person = dictionary[3]; // Rich Talbot
In this example I made the key an int and the value a string.

Not all the time will you know if a key exists when you look up a value in your Dictionary. Two ways you can go about trying to get a name:
string name;
if (dictionary.TryGetValue(4, out name))
    name = "Found: " + name;
else
    name = "No name found.";
TryGetValue method returns true if the key is found and puts the found value into the "name" variable in this case.
string name2;
if (dictionary.ContainsKey(4))
    name2 = "Found: " + dictionary[4];
else
    name2 = "No name found.";
This example just checks to see if it exists and then gets the value on a seperate line if true.

More Info: MSDN: Dictionary<TKey, TValue> Generic Class

Wednesday, April 16, 2008

Enum Class

An enum is a constant that contains words to represent numbers basically. For example, your program might refer to days of the week with numbers 1 to 7, but to make your code more readable you can create an enum to show that 1 is equal to "Sunday". Here is an example: Before:
private void DoWork(int today)
{
    if (today == 1  today == 2)
        TakeABreak();
    else
        GetToWork();
}
After:
public enum Day
{
    Sunday = 1,
    Monday = 2,
    Tuesday = 3,
    Wednesday = 4,
    Thursday = 5,
    Friday = 6,
    Saturday = 7
}

private void DoWork(Day today)
{
    if (today == Day.Sunday  today == Day.Saturday)
        TakeABreak();
    else
        GetToWork();
}
But say you have an outside program that refers to days of week by actual names and not numbers, you can still use your enum:
private void DoWork(string today)
{
    if (today == Day.Sunday.ToString() 
        today == Day.Saturday.ToString())
        TakeABreak();
    else
        GetToWork();
}
More Info: MSDN: Enum Class

Tuesday, April 15, 2008

Overloading Constructors

You have a class that you can initialize with different data. The consumer of your class might not have all the data though. You could solve this problem with multiple constructors.
public class Person
{
    private string _firstName;
    private string _lastName;

    public Person (string firstName)
    {
        _firstName = firstName;
    }

    public Person (string firstName, string lastName)
    {
        _firstName = firstName;
        _lastName = lastName;
    }
}
But you will notice you have some repeated code here, where _firstName is getting set to the parameter passed into both constructors. We can minimize duplicate code a couple ways.

One way is to have one constructor call another constructor:
public class Person2
{
    private string _firstName;
    private string _lastName;

    public Person2(string firstName)
        : this(firstName, string.Empty) {}

    public Person2(string firstName, string lastName)
    {
        _firstName = firstName;
        _lastName = lastName;
    }
}
Some people prefer to have all constructors call a single method:
public class Person3
{
    private string _firstName;
    private string _lastName;

    public Person3(string firstName)
    {
        Constructor(firstName, string.Empty);
    }

    public Person3(string firstName, string lastName)
    {
        Constructor(firstName, lastName);
    }

    private void Constructor(string firstName, string lastName)
    {
        _firstName = firstName;
        _lastName = lastName;
    }
}