Thursday, April 24, 2008

C#. No21- Anonymous Methods

/resource from http://www.csharp-station.com/

How Do Anonymous Methods Benefit Me?

An anonymous method is a method without a name - which is why it is called anonymous. You don't declare anonymous methods like regular methods. Instead they get hooked up directly to events. You'll see a code example shortly.

To see the benefit of anonymous methods, you need to look at how they improve your development experience over using delegates. Think about all of the moving pieces there are with using delegates: you declare the delegate, write a method with a signature defined by the delegate interface, delcare the event based on that delegate, and then write code to hook the handler method up to the delegate. With all this work to do, no wonder programmers, who are new to C# delegates, have to do a double-take to understand how they work.

Because you can hook an anonymous method up to an event directly, a couple of the steps of working with delegates can be removed. The next section shows you how this works.

Implementing an Anonymous Method

An anonymous method uses the keyword, delegate, instead of a method name. This is followed by the body of the method. Typical usage of an anonymous method is to assign it to an event. Example 1 shows how this works.

Example 1. Implementing an Anonymous Method
using System.Windows.Forms;

public partial class Form1 : Form
{
public Form1()
{
Button btnHello = new Button();
btnHello.Text = "Hello";

btnHello.Click +=
delegate
{
MessageBox.Show("Hello");
};

Controls.Add(btnHello);
}
}

The code in Example 1 is a Windows Forms application. It instantiates a Button control and sets its Text to "Hello". Notice the combine, +=, syntax being used to hook up the anonymous method. You can tell that it is an anonymous method because it uses the delegate keyword, followed by the method body in curly braces. Remember to terminate anonymous methods with a semi-colon.

Essentially, you have defined a method inside of a method, but the body of the anonymous method doesn't execute with the rest of the code. Because you hook it up to the event, the anonymous method doesn't execute until the Click event is raised. When you run the program and click the Hello button, you'll see a message box that say's "Hello" - courtesy of the anonymous method.

Using Controls.Add, adds the new button control to the window. Otherwise the window wouldn't know anything about the Button and you wouldn't see the button when the program runs.

Using Delegate Parameters with Anonymous Methods

Many event handlers need to use the parameters of the delegate they are based on. The previous example didn't use those parameters, so it was more convenient to not declare them, which C# allows. Example 2 shows you how to use parameters if you need to.

Example 2. Using Parameters with Anonymous Methods
using System;
using System.Windows.Forms;

public partial class Form1 : Form
{
public Form1()
{
Button btnHello = new Button();
btnHello.Text = "Hello";

btnHello.Click +=
delegate
{
MessageBox.Show("Hello");
};

Button btnGoodBye = new Button();
btnGoodBye.Text = "Goodbye"
;
btnGoodBye.Left = btnHello.Width + 5;

btnGoodBye.Click +=
delegate
(object sender, EventArgs e)
{
string message = (sender as Button).Text;
MessageBox.Show(message);
};


Controls.Add(btnHello);
Controls.Add(btnGoodBye);
}
}

The bold parts of Example 2 show another Button control added to the code from Example 1. Besides changing the text, btnGoodBye is moved to the right of btnHello by setting it's Left property to 5 pixels beyond the right edge of btnHello. If we didn't do this, btnGoodBye would cover btnHello because both of thier Top and Left properties would default to 0.

Beyond implementation details, the real code for you to pay attention to is the implementation of the anonymous method. Notice that the delegate keyword now has a parameter list. this parameter list must match the delegate type of the event that the anonymous method is being hooked up to. The delegate type of the Click event is EventHandler, which has the following signature:

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

Notice the EventHandler parameters. Now, here's how the Button control's Click event is defined:

public event EventHandler Click;

Notice that the delegate type of the Click event is EventHandler. This is why the anonymous method, assigned to btnGoodBye.Click in Example 2, must have the same parameters as the EventHandler delegate.



Read more!!!

C#. No20- Introduction to Generic Collections

/resource from http://www.csharp-station.com/

What Can Generics Do For Me?

Throughout this tutorial, you've learned about types, whether built-in (int, float, char) or custom (Shape, Customer, Account). In .NET v1.0 there were collections, such as the ArrayList for working with groups of objects. An ArrayList is much like an array, except it could automatically grow and offered many convenience methods that arrays don't have. The problem with ArrayList and all the other .NET v1.0 collections is that they operate on type object. Since all objects derive from the object type, you can assign anything to an ArrayList. The problem with this is that you incur performance overhead converting value type objects to and from the object type and a single ArrayList could accidentally hold different types, which would cause a hard to find errors at runtime because you wrote code to work with one type. Generic collections fix these problems.

A generic collection is strongly typed (type safe), meaning that you can only put one type of object into it. This eliminates type mismatches at runtime. Another benefit of type safety is that performance is better with value type objects because they don't incur overhead of being converted to and from type object. With generic collections, you have the best of all worlds because they are strongly typed, like arrays, and you have the additional functionality, like ArrayList and other non-generic collections, without the problems.

The next section will show you how to use a generic List collection.

Creating Generic List Collections

The pattern for using a generic List collection is similar to arrays. You declare the List, populate it's members, then access the members. Here's a code example of how to use a List:

     List<int> myInts = new List<int>();

myInts.Add(1);
myInts.Add(2);
myInts.Add(3);

for (int i = 0; i < family="Microsoft Sans Serif" style="color:red;">"MyInts: {0}", myInts[i]);
}

The first thing you should notice is the generic collection List, which is referred to as List of int. If you looked in the documentation for this class, you would find that it is defined as List, where T could be any type. For example, if you wanted the list to work on string or Customer objects, you could define them as List or List and they would hold only string or Customer objects. In the example above, myInts holds only type int.

Using the Add method, you can add as many int objects to the collection as you want. This is different from arrays, which have a fixed size. The List class has many more methods you can use, such as Contains, Remove, and more.

There are two parts of the for loop that you need to know about. First, the condition uses the Count property of myInts. This is another difference between collections and arrays in that an array uses a Length property for the same thing. Next, the way to read from a specific position in the List collection, myInts[i], is the exact same syntax you use with arrays.

The next time you start to use a single-dimension array, consider using a List instead. That said, be sure to let your solution fit the problem and use the best tool for the job. i.e. it's common to work with byte[] in many places in the .NET Framework.

Working with Dictionary Collections

Another very useful generic collection is the Dictionary, which works with key/value pairs. There is a non-generic collection, called a Hashtable that does the same thing, except that it operates on type object. However, as explained earlier in this lesson, you want to avoid the non-generic collections and use thier generic counterparts instead. The scenario I'll use for this example is that you have a list of Customers that you need to work with. It would be natural to keep track of these Customers via their CustomerID. The Dictionary example will work with instances of the following Customer class:

     public class Customer
{
public Customer(int id, string name)
{
ID = id;
Name = name;
}

private int m_id;

public int ID
{
get { return m_id; }
set { m_id = value; }
}

private string m_name;

public string Name
{
get { return m_name; }
set { m_name = value; }
}
}

The Customer class above has a constructor to make it easier to initialize. It also exposes it's state via public properties. It isn't very sophisticated at this point, but that's okay because its only purpose is to help you learn how to use a Dictionary collection. The following example populates a Dictionary collection with Customer objects and then shows you how to extract entries from the Dictionary:

     Dictionary<int, Customer> customers = new Dictionary<int, Customer>();

Customer cust1 = new Customer(1, "Cust 1");
Customer cust2 = new Customer(2, "Cust 2");
Customer cust3 = new Customer(3, "Cust 3");

customers.Add(cust1.ID, cust1);
customers.Add(cust2.ID, cust2);
customers.Add(cust3.ID, cust3);

foreach (KeyValuePair<int, Customer> custKeyVal in customers)
{
Console.WriteLine(
"Customer ID: {0}, Name: {1}",
custKeyVal.Key,
custKeyVal.Value.Name);
}

The customers variable is declared as a Dictionary. Considering that the formal declaration of Dictionary is Dictionary, the meaning of customers is that it is a Dictionary where the key is type int and the value is type Customer. Therefore, any time you add an entry to the Dictionary, you must provide the key because it is also the key that you will use to extract a specified Customer from the Dictionary.

I created three Customer objects, giving each an ID and a Name. I'll use the ID as they key and the entire Customer object as the value. You can see this in the calls to Add, where custX.ID is added as the key (first parameter) and the custX instance is added as the value (second parameter).

Extracting information from a Dictionary is a little bit different. Iterating through the customers Dictionary with a foreach loop, the type returned is KeyValuePair, where TKey is type int and TValue is type Customer because those are the types that the customers Dictionary is defined with.

Since custKeyVal is type KeyValuePair it has Key and Value properties for you to read from. In our example, custKeyVal.Key will hold the ID for the Customer instance and custKeyVal.Value will hold the whole Customer instance. The parameters in the Console.WriteLine statement demonstrate this by printing out the ID, obtained through the Key property, and the Name, obtained through the Name property of the Customer instance that is returned by the Value property.

The Dictionary type is handy for those situations where you need to keep track of objects via some unique identifier. For your convenience, here's below, shows how both the List and Dictionary collections work.

Introduction to Using Generic Collections with an Example of the List and Dictionary Generic Collections
using System;
using System.Collections.Generic;

public class Customer
{
public Customer(int id, string name)
{
ID = id;
Name = name;
}

private int m_id;

public int ID
{
get { return m_id; }
set { m_id = value; }
}

private string m_name;

public string Name
{
get { return m_name; }
set { m_name = value; }
}
}

class Program
{
static void Main(string[] args)
{
List<int> myInts = new List<int>();

myInts.Add(1);
myInts.Add(2);
myInts.Add(3);

for (int i = 0; i < family="Microsoft Sans Serif" style="color:red;">"MyInts: {0}", myInts[i]);
}

Dictionary<int, Customer> customers = new Dictionary<int, Customer>();

Customer cust1 = new Customer(1, "Cust 1");
Customer cust2 = new Customer(2, "Cust 2");
Customer cust3 = new Customer(3, "Cust 3");

customers.Add(cust1.ID, cust1);
customers.Add(cust2.ID, cust2);
customers.Add(cust3.ID, cust3);

foreach (KeyValuePair<int, Customer> custKeyVal in customers)
{
Console.WriteLine(
"Customer ID: {0}, Name: {1}",
custKeyVal.Key,
custKeyVal.Value.Name);
}

Console.ReadKey();
}
}

Whenever coding with the generic collections, add a using System.Collections.Generic declaration to your file, just as in above example.



Read more!!!

C#. No19 - Encapsulation

/resource from http://www.csharp-station.com/

What is Encapsulation and How Does It Benefit Me?

In object-oriented programming, you create objects that have state and behavior. An object's state is the data or information it contains. For example, if you have a BankAccount object, its state could be Amount and CustomerName. Behavior in an object is often represented by methods. For example, the BankAccount object's behavior could be Credit, Debit, and GetAmount. This sounds like a nice definition of an object, and it is, but you must also consider how this object will be used.

When designing an object, you must think about how others could use it. In a best-case scenario any program using the object would be well designed and the code would never change. However, the reality is that programs do change often and in a team environment many people touch the same code at one time or another. Therefore, it is beneficial to consider what could go wrong as well as the pristine image of how the object *should* be used.

In the case of the BankAccount object, examine the situation where code outside of your object could access a decimal Amount field or a string CustomerName field. At the point of time that the code is written, everything would work well. However, later in the development cycle, you realize that the BankAccount object should keep track of an int CustomerID rather than string CustomerName because you don't want to duplicate relationships between information (or some other valid reason to alter the definition of internal state). Such changes cause a rippling effect in your code because it was built to use the BankAccount class, as originally designed (with CustomerName being a string), and you must now change code that accesses that state throughout your entire application.

The object-oriented principle of Encapsulation helps avoid such problems, allowing you to hide internal state and abstract access to it though type members such as methods, properties, and indexers. Encapsulation helps you reduce coupling between objects and increases the maintainability of your code.

Type Member Access Modifiers

An access modifier allows you to specify the visibility of code outside a type or assembly. Access modifiers can be applied to either types or type members. A later section on Type Access Modifiers discusses modifiers that can be applied to types. This section discusses those modifiers that apply to type members and how they affect visibility.

Generally, you should hide the internal state of your object from direct access from outside code. Then implement other members, such as methods and properties, that wrap that state. This allows the internal implementation of the state to change at will, while the members wrapping the state can still return a representation of the state that doesn't change. This means that outside code will access your object via members that wrap state and be guaranteed that the type of information extracted is consistent. Additionally, because external code doesn't have access to the internal state of your object, they can't alter that state in an inconsistent manner that could break the way your object works.

The first step in encapsulating object state is to determine what type of access that outside code should have to the members of your type. This is performed with access modifiers. The type of access granted varies from no external access at all to full public access and a few variations in between the extremes. table 19-1 lists all of the type member access modifiers and explains their meaning.

Type member access modifiers control what code has access to a specified type member.

Access Modifier Description (who can access)
private Only members within the same type. (default for type members)
protected Only derived types.
internal Only code within the same assembly. Can also be code external to object as long as it is in the same assembly. (default for types)
protected internal Either code from derived type or code in the same assembly. Combination of protected OR internal.
public Any code. No inheritance, external type, or external assembly restrictions.

As you've learned from previous lessons of the C# Tutorial, types contain several types of members, including constructors, properties, indexers, methods, and others. Rather than show you an exhaustive list of all of the permutations of access modifiers you can use with these members, I'll take a more practical approach and describe a sub-set of access modifiers used on properties and methods.

Opening Type Members to public Access

You've seen the public access modifier used in earlier parts of the C# Tutorial. Any time the public access modifier is used on a type member, calling code will be able to access the type member. If you make your type member public, you are giving everyone permission to use it. Listing 19-1 shows an example of using the public access modifier on a method.

Declaring a Method with a public Access Modifier: BankAccountPublic.cs

using System;

class BankAccountPublic
{
public decimal GetAmount()
{
return 1000.00m;
}
}

The GetAmount() method in BankAccountPublic.cs is public meaning that it can be called by code that is external to this class. Now, you can write the following code, elsewhere in your program, to use this method:

BankAccountPublic bankAcctPub = new BankAccountPublic();

// call a public method
decimal
amount = bankAcctPub.GetAmount();

All you need to do, as shown above, is create an instance of the class that contains the method and then call the method through that instance. Because it is public, you won't have a problem. Remember that the default access for a type member is private, which we'll talk about next. This means that if you forget the public modifier, and didn't use any modifier at all, you would receive a compiler error.

Hiding Type Members with private Access

A private type member is one that can only be accessed by members within the same type. For example, if the BankAccount class has a private member, only other members of the BankAccount class can access or call that member.

Although the default access for type members is private, I prefer to be explicit about my intentions when declaring type members and include the access modifier, rather than rely on defaults. I think it makes the code easier to read and makes it clear to other developers what my true intention is. BankAccountPrivate.cs shows how to use the private access modifier and offers an example of why you would want to use it.

Declaring a private Field: BankAccountPrivate.cs

using System;

class
BankAccountPrivate
{
private string m_name;

public string CustomerName
{
get { return m_name; }
set { m_name = value; }
}
}

It's common to encapsulate the state of your type with properties. In fact, I always wrap my type state in a property. In BankAccountPrivate.cs, you can see how the name of the customer is held in the m_name field, but it is wrapped (encapsulated) with the CustomerName property. Because m_name is declared as private, code outside the BankAccountPrivate class can't access it directly. They must use the public CustomerName property instead.

Now you can change the implementation of m_name in any way you want. For example, what if you wanted it to be an ID of type int and the CustomerName property would do a search to find the name or what if you wanted to have first and last name values that the CustomerName property could concatenate. There are all kinds of things happening to your code in maintenance that will causes implementation to change. The point is that private members allow the implementation to change without constraining the implementation or causing rippling effects throughout your code base that would have occurred if that external code had access to the members of your type.

The private and public access modifiers are at the two extremes of access, either denying all external access or allowing all external access, respectively. The other access modifiers are like different shades of gray between these two extremes, including the protected modifier, discussed next.

Access for Derived Types with the protected Access Modifier

In some ways, the protected access modifier acts like both the private and public access modifiers. Like private, it only allows access to members within the same type, except that it acts like public only to derived types. Said another way, protected type members can only be accessed by either members within the same type or members of derived types.

Returning to the BankAccount example, what if you needed to call code to close an account? Furthermore, what if there were different types of accounts? Each of these different account types would have their own logic for closing, but the basic process would be the same for all account types. If this sounds to you like the description of Polymorphism, you would be on the right track. Back in Lesson 9 we discussed polymorphism and how it allows us to treat different classes the same way. You may want to refer to Lesson 9 for a refresher before looking at the next example.

In the case of closing an account, there are several things that need to be done like calculating interest that is due, applying penalties for early withdrawal, and doing the work to remove the account from the database. Individually, you don't want any code to call methods of the BankAccount class unless all of the methods are called and each method is called in the right order. For example, what if some code called the method to delete the account from the database and didn't calculate interest or apply penalties? Someone would loose money. Also, if the calling code were to delete the account first then the other methods wouldn't run into errors because the account information isn't available. Therefore, you need to control this situation and BankAccountProtected.cs shows how you can do it.

Declaring protected Methods: BankAccountProtected.cs

using System;

class
BankAccountProtected
{
public void CloseAccount()
{
ApplyPenalties();
CalculateFinalInterest();
DeleteAccountFromDB();
}

protected virtual void ApplyPenalties()
{
// deduct from account
}

protected virtual void CalculateFinalInterest()
{
// add to account
}

protected virtual void DeleteAccountFromDB()
{
// send notification to data entry personnel
}
}

The most important parts of BankAccountProtected.cs are that the CloseAccount method is public and the other methods are protected. Any calling code can instantiate BankAccountProtected, but it can only call the CloseAccount method. This gives you protection from someone invoking the behavior of your object in inappropriate ways. Your business logic is sound.

At the end of this section, you'll see an example of how to call the code in BankAccountProtected.cs. For now, it is essential that you see how the other pieces fit together first.

If you only wanted the BankAccountProtected class to operate on its own members, you could have made the protected methods private instead. However, this code supports a framework where you can have different account types such as Savings, Checking, and more. You will be able to add new account types in the future because the BankAccountProtected class is designed to support them with protected virtual methods. SavingsAccount.cs and CheckingAccount.cs show you the SavingsAccount and CheckingAccount classes that derive from the BankAccountProtected class.

Derived SavingsAccount Class Using protected Members of its Base Class: SavingsAccount.cs

using System;

class
SavingsAccount : BankAccountProtected
{
protected override void ApplyPenalties()
{
Console.WriteLine("Savings Account Applying Penalties");
}

protected override void CalculateFinalInterest()
{
Console.WriteLine("Savings Account Calculating Final Interest");
}

protected override void DeleteAccountFromDB()
{
base.DeleteAccountFromDB();

Console.WriteLine("Savings Account Deleting Account from DB");
}
}

Notice how SavingsAccount derives from BankAccountProtected. SavingsAccount can access any of the protected members of the BankAccountProtected class which is its base class. It demonstrates this fact via the call to base.DeleteAccountFromDB in it's DeleteAccountFromDB method. If the inheritance part of SavingsAccount.cs is a little confusing, you can visit Lesson 8for a refresher and better understanding. Each method of SavingsAccount has the protected access modifier also, which simply means that classes derived from SavingsAccount can access those SavingsAccount members with the protected access modifier. The same situation exists with the CheckingAccount class, shown in CheckingAccount.cs.

Derived CheckingAccount Class Using protected Members of its Base Class: CheckingAccount.cs

using System;

class
CheckingAccount : BankAccountProtected
{
protected override void ApplyPenalties()
{
Console.WriteLine("Checking Account Applying Penalties");
}

protected override void CalculateFinalInterest()
{
Console.WriteLine("Checking Account Calculating Final Interest");
}

protected override void DeleteAccountFromDB()
{
base.DeleteAccountFromDB();
Console.WriteLine("Checking Account Deleting Account from DB");
}
}

If you were writing this, the difference would be that the methods of each class would have unique implementations. For example, the business rules associated with the final interest calculation would differ, depending on whether the account type was checking or savings.

Notice the call to the base class method in the DeleteAccountFromlDB method in CheckingAccount. Just like SavingsAccount, CheckingAccount has access to BankAccountProtected's protected method because it is a derived class. This is a common pattern in polymorphism because derived classes often have a responsibility to call virtual base class methods to ensure critical functionality has the opportunity to execute. You would consult the method documentation to see if this was necessary. Without a protected access modifier, your only option would have been to make the base class method public; which, as explained earlier, is dangerous.

To use the code from BankAccountProtected.cs, SavingsAccount.cs, and CheckingAccount.cs, you can implement the following code:

BankAccountProtected[] bankAccts = new BankAccountProtected[2];
bankAccts[0] =
new SavingsAccount();
bankAccts[1] =
new CheckingAccount();

foreach (BankAccountProtected acct in bankAccts)
{
// call public method, which invokes protected virtual methods
acct.CloseAccount();
}

Since both SavingsAccount and CheckingAccount derive from BankAccountProtected, you can assign them to the bankAccts array. They both override the protected virtual methods of BankAccountProtected, so it is the SavingsAccount and CheckingAccount methods that are called when CloseAccount in BankAccountProtected executes. Remember that the only reason the methods of SavingsAccount and CheckingAccount can call their virtual base class methods, as in the case of DeleteAccountFromDB, is because the virtual base class methods are marked with the protected access modifier.

A Quick Word on internal and protected internal Access Modifiers

In practice, most of the code you write will involve the public, private, and protected access modifiers. However, there are two more access modifiers that you can use in more sophisticated scenarios: internal and protected internal.

You would use internal whenever you created a separate class library and you don't want any code outside of the library to access the code with internal access. The protected internal is a combination of the two access modifiers it is named after, which means either protected or internal.

Access Modifiers for Types

So far, the discussion of access modifiers has only applied to the members of types. However, the rules are different for the types themselves. When talking about types, I'm referring to all of the C# types, including classes, structs, interfaces, delegates, and enums. Nested types, such as a class defined within the scope of a class, are considered type members and fall under the same access rules as other type members.

Types can have only two access modifiers: public or internal. The default, if you don't specify the access modifier, is internal. Looking at all of the classes used in this lesson, you can see that they are internal because they don't have an access modifier. You can explicitly specify internal like this:

internal class InternalInterestCalculator
{
// members go here
}

Perhaps the InternalInterestCalculator, shown above, has special business rules that you don't want other code to use. Now, it is in a class library of its own and can only be accessed by other code inside of that same class library (DLL).

Note: To be more specific, internal means that only code in the same assembly can access code marked as internal. However, discussing the definition of an assembly is outside the scope of this lesson, so I am simplifying the terminology.

If you declared a class inside of a class library that you wanted other code to use, you would give it a public access modifier. The following code shows an example of applying the public access modifier to a type:

public class BankAccountExternal
{
// members go here
}

Clearly, a bank account is something you would want to access from outside of a class library. Therefore, it only makes sense to give it a public access modifier as shown in the BankAccountExternal class above.

Tip: A common gottcha in Visual Studio 2005 occurs when you create a new class in a class library. The default template doesn't include an access modifier. Then, when you try to write code that uses the new class in your program (which references the class library), you get a compiler error saying that the class doesn't exist. Well, you know it exists because you just wrote it and are looking at the page. If you've already seen the clue I've given you so far, you'll key on the fact that the default template left out the access modifier on the type. This makes the class default to internal, which can't be seen outside of the assembly. The fix is to give the class a public modifier, like the BankAccountExternal class above.



Read more!!!

Wednesday, April 23, 2008

C#. No18 - Overloading Operators

/resource from http://www.csharp-station.com/

About Operator Overloading

In Lesson 2, you learned what operators were available in C#, which included + (plus), - (minus), ^ (exclusive or), and others. Operators are defined for the built-in types, but that's not all. You can add operators to your own types, allowing them to be used much like the operators with the built-in C# types.

To understand the need for operator overloading, imagine that you need to perform matrix math operations in your program. You could instantiate a couple 2-dimensional arrays and do what you need. However, add the requirement for the matrix behavior to be reusable.& Because you need to do the same thing in other programs and want to take advantage of the fact that you have already written the code, you will want to create a new type.

So, you create a Matrix type, which could be a class or a struct. Now consider how this Matrix type would be used. You would want to initialize two or more Matrix instances with data and then do a mathematical operation with them, such as add or get a dot product. To accomplish the mathematical operation, you could implement an Add(), DotProduct(), and other methods to get the job done. Using the classes would look something like this:

Matrix result = mat1.Add(mat2);  // instance

or

Matrix result = Matrix.Add(mat1, mat2);  // static

or even worse

Matrix result = mat1.DotProduct(mat2).DotProduct(mat3); // and so on...

The problem with using methods like this is that it is cumbersome, verbose, and unnatural for the problem you are trying to solve. It would be much easier to have a + operator for the add operation and a * operator for the dot product operation. The following shows how the syntax appears using operators:

Matrix result = mat1 + mat2;

or

Matrix result = mat1 * mat2;

or even better

Matrix result = mat1 * mat2 * mat3 * mat4;

This is much more elegant and easier to work with. For a single operation, one could argue that the amount of work to implement one syntax over the other is not that great. However, when chaining multiple mathematical operations, the syntax is much simpler. Additionally, if the primary users of your type are mathematicians and scientists, operators are more intuitive and natural.

When Not to Use Operator Overloading

A lot of the discussion, so far, has emphasized the need to write code and implement types in the simplest and most natural way possible. A very important concept to remember is that although operators are simple, they are not always natural. In the example above it made sense to use operators with the Matrix type. This is similar to the reason why operators make sense with the built-in types such as int and float. However, it is easy to abuse operators and create convoluted implementations that are hard for anyone, including the original author, to understand.

For an example of a bad implementation, consider a Car class that needs an implementation allowing you to park the car in a garage. It would be a mistake to think that the following implementation was smart:

Car mySedan = new Car();
Garage parkingGarage = new Garage();
mySedan = mySedan + parkingGarage; // park car in the garage

This is bad code. If you ever have the temptation to do something like this - don't. No one will truly understand what it means and they will not think it is clever. Furthermore, it hurts the maintainability of the application because it is so hard to understand what the code does. Although the comment is there, it doesn't help much and if it wasn't there, it would be even more difficult to grasp the concept of adding a ding a Car and a Garage.

The idea is this: Use operators where they lend understanding and simplicity to a type. Otherwise, do not use them.

Implementing an Overloaded Operator

The syntax required to implement an overloaded operator is much the same as a static method with a couple exceptions. You must use the operator keyword and specify the operator symbol being overloaded. Here's a skeleton example of how the dot product operator could be implemented:

public static Matrix operator *(Matrix mat1, Matrix mat2)
{
// dot product implementation
}

Notice that the method is static. Use the keyword operator after specifying the return type, Matrix in this case. Following the operator keyword, the actual operator symbol is specified and then there is a set of parameters to be operated on. See Matrix.cs for a full example of how to implement and use an overloaded operator.

Implementing an Overloaded Operator: Matrix.cs
using System;

class Matrix
{
public const int DimSize = 3;
private double[,] m_matrix = new double[DimSize, DimSize];

// allow callers to initialize
public double this[int x, int y]
{
get { return m_matrix[x, y]; }
set { m_matrix[x, y] = value; }
}

// let user add matrices
public static Matrix operator +(Matrix mat1, Matrix mat2)
{
Matrix newMatrix = new Matrix();

for (int x=0; x < family="Microsoft Sans Serif" style="color:blue;">for (int y=0; y < family="Microsoft Sans Serif" style="color:blue;">return newMatrix;
}
}

class MatrixTest
{
// used in the InitMatrix method.
public static Random m_rand = new Random();

// test Matrix
static void Main()
{
Matrix mat1 = new Matrix();
Matrix mat2 = new Matrix();

// init matrices with random values
InitMatrix(mat1);
InitMatrix(mat2);

// print out matrices
Console.WriteLine("Matrix 1: ");
PrintMatrix(mat1);

Console.WriteLine("Matrix 2: ");
PrintMatrix(mat2);

// perform operation and print out results
Matrix mat3 = mat1 + mat2;

Console.WriteLine();
Console.WriteLine("Matrix 1 + Matrix 2 = ");
PrintMatrix(mat3);

Console.ReadLine();
}

// initialize matrix with random values
public static void InitMatrix(Matrix mat)
{
for (int x=0; x < family="Microsoft Sans Serif" style="color:blue;">for (int y=0; y < family="Microsoft Sans Serif" color="green">// print matrix to console
public static void PrintMatrix(Matrix mat)
{
Console.WriteLine();
for (int x=0; x < family="Microsoft Sans Serif" style="color:red;">"[ ");
for (int y=0; y < family="Microsoft Sans Serif" color="green">// format the output
Console.Write("{0,8:#.000000}", mat[x, y]);

if ((y+1 % 2) < family="Microsoft Sans Serif" style="color:red;">", ");
}
Console.WriteLine(" ]");
}
Console.WriteLine();
}
}

Similar to the skeleton example of the dot product operator, the Matrix class in Matrix.cs contains an operator overload for the + operator. For your convenience, I've extracted the pertinent overload implementation in the code below:

// let user add matrices public static Matrix operator +(Matrix mat1, Matrix mat2) { Matrix newMatrix = new Matrix(); for (int x=0; x < family="Microsoft Sans Serif" style="color:blue;">for (int y=0; y < family="Microsoft Sans Serif" color="blue">return newMatrix; }

The operator is static, which is the only way it can and should be declared because an operator belongs to the type and not a particular instance. The return type is Matrix - its enclosing type. What designates this as an operator is the use of the keyword operator symbol. The parameter types are both of the enclosing type, Matrix. The implementation of the operator overload creates a new instance of the return type and performs a matrix add.

Basically, it is that easy. There are just a few rules you have to follow when implementing operator overloads. ng type. What designates this as an operator is the use of the keyword operator, followed by the + symbol. The parameter types are both of the enclosing type, Matrix. The implementation of the operator overload creates a new instance of the return type and performs a matrix add.

Operator Rules

C# enforces certain rules when you overload operators. One rule is that you must implement the operator overload in the type that will use it. This is sensible because it makes the type self-contained.

Another rule is that you must implement matching operators. For example, if you overload ==, you must also implement !=. The same goes for <= and >=.

When you implement an operator, its compound operator works also. For example, since the + operator for the Matrix type was implemented, you can also use the += operator on Matrix types.



Read more!!!

C#. No17 - Enums

/resource from http://www.csharp-station.com/

Enums Defined

Enums are strongly typed constants. They are essentially unique types that allow you to assign symbolic names to integral values. In the C# tradition, they are strongly typed, meaning that an enum of one type may not be implicitly assigned to an enum of another type even though the underlying value of their members are the same. Along the same lines, integral types and enums are not implicitly interchangable. All assignments between different enum types and integral types require an explicit cast.

Enums lend themselves to more maintainable code because they are symbolic, allowing you to work with integral values, but using a meaningful name to do so. For example, what type of code would you rather work with - a set of values named North, South, East, and West or the set of integers 0, 1, 2, and 3 that mapped to the same values, respectively? Enums make working with strongly typed constants via symbolic names easy.

Enums are value types, which means they contain their own value, can't inherit or be inherited from, and assignment copies the value of one enum to another. You will see in this lesson and elsewhere that enums are used and referred to with both lower case, enum, and upper case, Enum. Strangely enough, the relationship between the two is that the C# type, enum, inherits the Base Class Library (BCL) type, Enum. Use the C# type, enum, to define new enums and use the BCL type, Enum, to implement static enum methods.

Creating an Enum

The .NET Framework Class Library contains many enums and examples of how they are used. For example, every time you put an icon on a MessageBox, you use the MessageBoxIcons enum. For a list of available enums in the .NET Framework Class Library, look at the documentation for the Enum class and click on the Derived Classes link.

Whenever there are situations where you are using a set of related numbers in a program, consider replacing those numbers with enums. It will make a program more readable and type safe. EnumSwitch.cs contains an enum definition and code that uses that enum in a switch statement. Instead of using the numbers 0, 1, and 2 in the switch statement, the code is more meaningful through the use of the Volume enum.

Creating and Using an Enum: EnumSwitch.cs

using System;

// declares the enum
public enum Volume
{
Low,
Medium,
High
}

// demonstrates how to use the enum

class
EnumSwitch
{
static void Main()
{
// create and initialize
// instance of enum type
Volume myVolume = Volume.Medium;

// make decision based
// on enum value
switch (myVolume)
{
case Volume.Low:
Console.WriteLine("The volume has been turned Down.");
break;
case Volume.Medium:
Console.WriteLine("The volume is in the middle.");
break;
case Volume.High:
Console.WriteLine("The volume has been turned up.");
break;
}
Console.ReadLine();
}
}

EnumSwitch.cs contains a definition for an enum. Notice that it is declared with the enum keyword, has a type identifier (Volume), and contains a comma separated list of values enclosed within curly braces.

This enum is of type Volume and we use it to declare the myVolume variable in the Main method. Since an enum is a value type, we can assign a value (Volume.Medium) to it directly, similar to the simple types such as int or double. Once the myVolume variable is declared and initialized, it is used in the switch statement.Each of the case statements represent a unique member of the Volume enum.

Any time a member of the Volume enum is used, it is fully qualified with the "Volume" identifier to guarantee type safety. For example, if there were a Meat enum in scope, then Meat.Medium would definitely have different semantics than Volume.Medium. With both enums in scope, it would be ambiguous to just use the Medium identifier without type qualification. Using the type identifier ensures such mistakes are not made.

Using Enums

An enum is typically specified as shown in EnumSwitch.cs, but may be customized by changing its base type and member values. By default, the underlying type of an enum is int. This default may be changed by specifying a specific base when declaring the enum. You would specify a different base if the enum was used extensively and there was an opportunity for space savings by selecting a smaller type. Another reason may be if you wanted the underlying type of the enum to correspond to another type in your program and you wanted to explicitly cast between the two without loss of precision. Valid base types include byte, sbyte, short, ushort, int, uint, long, and ulong.

Another modification you can make to an enum is to set the value of any enum member. By default, the first member of an enum takes the value of zero. If this value doesn't make sense for your enum, you can change it to one or some other number. Additionally, you can change any of the members of an enum to any value that is valid for its base type. Unassigned enum members have a value that is one more than their predecessor. EnumBaseAndMemebers.cs shows how to modify the base type and member values of an enum.

Setting the Enum Base and Initializing Members: EnumBaseAndMembers.cs

using System;

// declares the enum
public enum Volume : byte
{
Low = 1,
Medium,
High
}

class EnumBaseAndMembers
{
static void Main()
{
// create and initialize
// instance of enum type
Volume myVolume = Volume.Low;

// make decision based
// on enum value
switch (myVolume)
{
case Volume.Low:
Console.WriteLine("The volume has been turned Down.");
break;
case Volume.Medium:
Console.WriteLine("The volume is in the middle.");
break;
case Volume.High:
Console.WriteLine("The volume has been turned up.");
break;
}
Console.ReadLine();
}
}

The Volume enum in EnumBaseAndMemebers.cs shows how to modify the base type and members of an enum.Its base type is changed to byte with the : syntax following the enum identifier, Volume.This ensures that the Volume enum may only have members with values that are valid for type byte.

The first member of the Volume enum, Low, has its value changed to 1. The same syntax, = , may be applied to any member of the enum. You are restricted from creating forward references, circular references, and duplicate references in enum members.

The default values of the Volume enum are Low=0, Medium=1, and High=2 because the first member of an enum defaults to 0 and the following members default to one more than their predecessor. However, the Volume enum in EnumBaseAndMemebers.cs has its Low member set to 1, which means that Medium=2 and High=3.

Enum tricks

Enum types implicitly inherit the System.Enum type in the Base Class Library (BCL). This also means that you can use the members of System.Enum to operate on enum types. This section does just that, showing some useful tips and tricks to use with enums in your programs.

A common requirement with enums is to convert between the enum and a variable of its base type. For example, if you are getting input in the form of an int from a user or a file stream, then you can cast it to an enum and use it in a meaningful way in your program. You can also get a complete list of enum member names or enum values, which is useful if you have logic that needs to iterate through every enum member. EnumTricks.cs shows how to perform conversions between enums and their base types and how to use some of the System.Enum type members.

Enum Conversions and using the System.Enum Type: Enumtricks.cs

using System;

// declares the enum
public enum Volume : byte
{
Low = 1,
Medium,
High
}


// shows different ways
// to work with enums
class Enumtricks
{
static void Main(string[] args)
{
// instantiate type
Enumtricks enumtricks = new Enumtricks();

// demonstrates explicit cast
// of int to Volume
enumtricks.GetEnumFromUser();

// iterate through Volume enum by name
enumtricks.ListEnumMembersByName();

// iterate through Volume enum by value
enumtricks.ListEnumMembersByValue();

Console.ReadLine();
}

// demonstrates explicit cast
// of int to Volume
public void GetEnumFromUser()
{
Console.WriteLine("\n----------------");
Console.WriteLine("Volume Settings:");
Console.WriteLine("----------------\n");

Console.Write(@"
1 - Low
2 - Medium
3 - High

Please select one (1, 2, or 3): ");

// get value user provided
string volString = Console.ReadLine();
int volInt = Int32.Parse(volString);

// perform explicit cast from
// int to Volume enum type
Volume myVolume = (Volume)volInt;

Console.WriteLine();

// make decision based
// on enum value
switch (myVolume)
{
case Volume.Low:
Console.WriteLine("The volume has been turned Down.");
break;
case Volume.Medium:
Console.WriteLine("The volume is in the middle.");
break;
case Volume.High:
Console.WriteLine("The volume has been turned up.");
break;
}

Console.WriteLine();
}

// iterate through Volume enum by name
public void ListEnumMembersByName()
{
Console.WriteLine("\n---------------------------- ");
Console.WriteLine("Volume Enum Members by Name:");
Console.WriteLine("----------------------------\n");

// get a list of member names from Volume enum,
// figure out the numeric value, and display
foreach (string volume in Enum.GetNames(typeof(Volume)))
{
Console.WriteLine("Volume Member: {0}\n Value: {1}",
volume, (
byte)Enum.Parse(typeof(Volume), volume));
}
}

// iterate through Volume enum by value
public void ListEnumMembersByValue()
{
Console.WriteLine("\n----------------------------- ");
Console.WriteLine("Volume Enum Members by Value:");
Console.WriteLine("-----------------------------\n");

// get all values (numeric values) from the Volume
// enum type, figure out member name, and display
foreach (byte val in Enum.GetValues(typeof(Volume)))
{
Console.WriteLine("Volume Value: {0}\n Member: {1}",
val, Enum.GetName(
typeof(Volume), val));
}
}
}

The code in EnumTricks.cs includes three method calls to GetEnumFromUser, ListEnumMembersByName, and ListEnumMembersByValue. Each of these methods demonstrate a different aspect of using System.Enum to work with enums.

The GetEnumFromUser method shows how to obtain int input and translate it to an appropriate enum type. Converting an int to an enum makes the code more readable and type safe. The following is an excerpt from EnumTricks.cs that shows the pertinent part of the code that performs the conversion:

// get value user provided
string volString = Console.ReadLine();
int volInt = Int32.Parse(volString);

// perform explicit cast from
// int to Volume enum type
Volume myVolume = (Volume)volInt;

After the program displays a menu, it prompts the user for a selection in the form of a number (1, 2, or 3). When the user makes a selection and presses the Enter key, the code reads the value with Console.ReadLine, which returns the value as a string type. Since you can only cast an int to a Volume enum type, the user's input must be converted from a string to an int with the Int32.Parse method. Converting the int to a Volume enum type is simply a matter of applying a cast operation during assignment.

To get all the members of an enum at the same time, you can use the GetNames method of the System.Enum type, which returns a string array of the names of all an enum's members. An excerpt from the ListEnumMembersByName method in EnumTricks.cs that shows this appears below:

// get a list of member names from Volume enum,
// figure out the numeric value, and display
foreach (string volume in Enum.GetNames(typeof(Volume)))
{
Console.WriteLine("Volume Member: {0}\n Value: {1}",
volume, (
byte)Enum.Parse(typeof(Volume), volume));
}

Because GetNames returns an array of strings, it is easy to use in a loop statement such as foreach. Something you may be curious about in the code above is the second parameter to the WriteLine method's format string. Given the enum type and a string representation of the member name, you can use the Enum.Parse method to get the underlying value of that member. Because the Volume enum's base type is byte, the return value from Enum.Parse must be cast to a byte before assignment, forcing the numeric representation of the enum value to appear. If we would have omitted the byte cast, the output would be the Volume enum member, which would then be converted to a string representation of the member name, which is not what the code intended to show.

Instead of getting names of all the members of an enum, you may have a reason to get all the values of the enum at one time. The code below, from the ListEnumMembersByValue method inEnumTricks.cs, shows how to accomplish this:

// get all values (numeric values) from the Volume
// enum type, figure out member name, and display
foreach (byte val in Enum.GetValues(typeof(Volume)))
{
Console.WriteLine("Volume Value: {0}\n Member: {1}",
val, Enum.GetName(
typeof(Volume), val));
}

Given the type of the enum, the GetValues method of System.Enum will return an array of the given enum's base type, which in this case is byte. While iterating through this list, each member is printed to the console showing its value and name. The name is obtained by using the GetName method of System.Enum, which accepts an enum type and value for which to get the corresponding name of.


Read more!!!