Saturday, 7 April 2012

C Sharp Tutorials/Lesson 18 Lesson 18: Overloading Operators


This lesson shows you how to overload C# operators. Our objectives are as follows:
  • Understand what operator overloading is
  • Determine when it is appropriate to overload an operator
  • Learn how to overload an operator
  • Familiarize yourself with rules for operator overloading

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 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 Listing 18-1 for a full example of how to implement and use an overloaded operator.
Listing 18-1. 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" color="blue">for (int y=0; y < family="Microsoft Sans Serif" 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" 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" 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" color="red">", ");
  }
  Console.WriteLine(" ]");
 }
 Console.WriteLine();
}
}
Similar to the skeleton example of the dot product operator, the Matrix class in Listing 18-1 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" 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. There are just a few rules you have to follow when implementing operator overloads. 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 onMatrix types.

C Sharp Tutorials/Lesson 19 Lesson 19: Encapsulation


Earlier in this tutorial, you learned about two of the important principles of object-oriented programming, Inheritance and Polymorphism. Now that you've seen much of the syntax of C#, I'll show you how C# supports the another of the object-oriented principles - Encapsulation. This lesson will discuss Encapsulation with the following objectives:
  • Understand the object-oriented principle of Encapsulation.
  • Learn the available modifiers for type members.
  • Protect object state through properties.
  • Control access to methods.
  • Learn how to modify types for assembly encapsulation

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 BankAccountobject, 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 intCustomerID 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.
table 19-1. Type member access modifiers control what code has access to a specified type member.
Access ModifierDescription (who can access)
privateOnly members within the same type. (default for type members)
protectedOnly derived types or members of the same type.
internalOnly 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 internalEither code from derived type or code in the same assembly. Combination of protected OR internal.
publicAny 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 thepublic 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.
Listing 19-1. Declaring a Method with a public Access Modifier: BankAccountPublic.cs
using System;
class BankAccountPublic
{
public decimal GetAmount()
{
return 1000.00m;
}
}
The GetAmount() method in Listing 19-1 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

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 theBankAccount 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. Listing 19-2 shows how to use the private access modifier and offers an example of why you would want to use it.
Listing 19-2. 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 Listing 19-2, you can see how the name of the customer is held in the m_name field, but it is wrapped (encapsulated) with the CustomerNameproperty. Because m_name is declared as private, code outside the BankAccountPrivateclass 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 theCustomerName 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 privatemembers 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 protectedmodifier, 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 Listing 19-3 shows how you can do it.
Listing 19-3. 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 Listing 19-3 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 Listing 19-3. 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 theBankAccountProtected class is designed to support them with protected virtual methods. Listings 19-4 and 19-5 show you the SavingsAccount and CheckingAccount classes that derive from the BankAccountProtected class.
Listing 19-4. 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 BankAccountProtectedSavingsAccount 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'sDeleteAccountFromDB method. If the inheritance part of Listing 19-4 is a little confusing, you can visit Lesson 8: Class Inheritance for 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 theprotected access modifier. The same situation exists with the CheckingAccount class, shown in Listing 19-5.
Listing 19-5. 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");
}
}
The CheckingAccount class in Listing 19-5 is implemented similar to SavingsAccount from Listing 19-6. 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 inCheckingAccount. Just like SavingsAccountCheckingAccount has access toBankAccountProtected'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 protectedaccess 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 Listings 19-3, 19-4, and 19-5, 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 inBankAccountProtected executes. Remember that the only reason the methods of SavingsAccount andCheckingAccount 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 publicprivate, and protectedaccess 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 eitherprotected 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 thepublic 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 theBankAccountExternal 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.

C Sharp Tutorials/Lesson 20 Lesson 20: Introduction to Generic Collections


All the way back in Lesson 02, you learned about arrays and how they allow you to add and retrieve a collection of objects. Array's are good for many tasks, but C# v2.0 introduced a new feature called generics. Among many benefits, one huge benefit is that generics allow us to create collections that allow us to do more than allowed by an array. This lesson will introduce you to generic collections and how they can be used. Here are the objectives for this lesson:
  • Understand how generic collections can benefit you
  • Learn how to create and use a generic List
  • Write code that implements a generic Dictionary

What Can Generics Do For Me?

Throughout this tutorial, you've learned about types, whether built-in (intfloatchar) or custom (ShapeCustomerAccount). In .NET v1.0 there were collections, such as theArrayList 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 anArrayList. 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 aList:
     List<int> myInts = new List<int>();

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

    for (int i = 0; i < myInts.Count; i++)
   {
       Console.WriteLine("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 asList, where T could be any type. For example, if you wanted the list to work on string orCustomer objects, you could define them as List or List and they would hold only string orCustomer 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 ContainsRemove, 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 theDictionary, 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 the key and the entire Customer object as the value. You can see this in the calls to Add, wherecustX.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 thecustomers 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 customersDictionary 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 andcustKeyVal.Value will hold the whole Customer instance. The parameters in theConsole.WriteLine statement demonstrate this by printing out the ID, obtained through theKey property, and the Name, obtained through the Name property of the Customerinstance 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 Listing 20-1, shows how both theList and Dictionary collections work.
Listing 20-1. 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 < myInts.Count; i++)
       {
           Console.WriteLine("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.Genericdeclaration to your file, just as in Listing 20-1.

C Sharp Tutorials/Lesson 21 Lesson 21: Anonymous Methods


In Lesson 14: Introduction to Delegates, you learned a about delegates and how they enable you to connect handlers to events. For C# v2.0, there is a new language feature, called anonymous methods, that are similar to delegates, but require less code. While you learn about anonymous methods, we'll cover the following objectives:
  • Understand the benefits of anonymous methods
  • Learn how to implement an anonymous method
  • Implement anonymous methods that use delegate parameters

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. Listing 21-1 shows how this works.
Listing 21-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 Listing 21-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 thedelegate 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. Listing 21-2 shows you how to use parameters if you need to.
Listing 21-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 Listing 21-2 show another Button control added to the code from Listing 21-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 isEventHandler, 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 Listing 21-2, must have the same parameters as the EventHandler delegate.

C Sharp Tutorials/Lesson 22 Lesson 22: Topics on C# Type


Throughout this tutorial, you've seen many different types, including those that are part of C# and custom designed types. If you've taken the samples and worked on them yourself, extending and writing your own programs, you are likely to have experienced errors associated with type. For example, you can't assign a double to an int without using a cast operator to perform the conversion. Another feature of C# concerns the semantic differences between reference and value types. Such problems should make you wonder why this is so and that's what this lesson is for. Here are the objectives for this lesson:
  • Understand the need for type safety
  • See how to convert one type to another
  • Learn about reference types
  • Learn about value types
  • Comprehend the semantic differences between reference and value types

Why Type Safety?

In untyped languages, such as scripting languages, you can assign one variable to another and the compiler/interpreter will use an intelligent algorithm to figure out how the assignment should be done. If the assignment is between two variables of the same type, all is good. However, if the assignment is between different types, you could have serious problems.
For example, if you assigned an int value to a float variable it would convert okay because the fractional part of the new float would just be zero. However, if you went the other way and assigned a float value to an int variable, that would most likely be a problem. You would lose all of the precision of the original float value. Consider the damage that could be caused if the float value represented a chemical ingredient, an engineering measurement, or a financial value. Finding such an error would be difficult and particularly expensive, especially if the error didn't show up until your application was in production (already being used by customers).

Using the Cast Operator for Conversions

In Lesson 02: Operators, Types, and Variables, you learned about C# types and operators. It explained the size and precision of the various types and there is a list of available operators. The cast operator, (x), is listed first as a primary operator in Table 2-4. When you must convert a type that doesn't fit, it must be done via what is called an explicit conversion, which uses the cast operator. Listing 22-1 has an example of an implicit conversion, which doesn't require the cast operator, and an explicit conversion.
Listing 22-1. Cast Operators
using System;

class Program
{
  static void Main()
  {
      float lengthFloat = 7.35f;

      // lose precision - explicit conversion
      int lengthInt = (int)lengthFloat;

      // no problem - implicit conversion
      double lengthDouble = lengthInt;

      Console.WriteLine("lengthInt =
          " + lengthInt);
      Console.WriteLine("lengthDouble
          = " + lengthDouble);
      Console.ReadKey();
  }
}
Here's the output:
lengthInt = 7
lengthDouble = 7
Since a floatlengthFloat, has a fractional part but an intlengthInt, doesn't; the types aren't compatible. Because of type safety, C# won't allow you to assign lengthFloat directly to lengthInt, which would be dangerous. For your protection, you must use a cast operator,(int), to force the explicit conversion of lengthFloat to lengthInt. In the output, you can see that lengthInt is 7, showing that it lost the fractional part of the 7.35f value fromlengthFloat.
The assignment from lengthInt to lengthDouble is safe because a double is 64-bit and an int is 32-bit, meaning that you won't lose information. Therefore, the conversion is implicit, meaning that you can perform the assignment without the cast operator.

Understanding Reference Types

Reference type variables are named appropriately (reference) because the variable holds a reference to an object. In C and C++, you have something similar that is called a pointer, which points to an object. While you can modify a pointer, you can't modify the value of a reference - it simply points at the object in memory.
An important fact you need to understand is that when you are assigning one reference type variable to another, only the reference is copied, not the object. The variable holds the reference and that is what is being copied. Listing 22-2 shows how this works.
Listing 22-2. Reference Type Assignment
using System;

class Employee
{
  private string m_name;

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

class Program
{
  static void Main()
  {
      Employee joe = new Employee();
      joe.Name = "Joe";

      Employee bob = new Employee();
      bob.Name = "Bob";

      Console.WriteLine("Original Employee Values:");
      Console.WriteLine("joe = " + joe.Name);
      Console.WriteLine("bob = " + bob.Name);

      // assign joe reference to bob variable
      bob = joe;

      Console.WriteLine();
      Console.WriteLine("Values After Reference Assignment:");
      Console.WriteLine("joe = " + joe.Name);
      Console.WriteLine("bob = " + bob.Name);

      joe.Name = "Bobbi Jo";

      Console.WriteLine();
      Console.WriteLine("Values After Changing One Instance:");
      Console.WriteLine("joe = " + joe.Name);
      Console.WriteLine("bob = " + bob.Name);

      Console.ReadKey();
  }
}
Here's the output:
Original Employee Values:
joe = Joe
bob = Bob

Values After Reference Assignment:
joe = Joe
bob = Joe

Values After Changing One Instance:
joe = Bobbi Jo
bob = Bobbi Jo
In Listing 22-2, I created two Employee instances, joe and bob. You can see in the output that the Name properties of both Employee instances each show their assigned values from when the objects were first created. After assigning joe to bob, the value of the Nameproperties of both instances are the same. This is what you might expect to see.
What might surprise you is the values that occur after assigning a value to the Employeeinstance variable named joe. If you look at the code closely, you'll notice that it doesn't change bob - only Joe. However, the results from the output show that the Name property in bob is the same as the Name property in joe. This demonstrates that after assigning joeto bob, both variables held references to the joe object. Only the reference was copied - not the object. This is why you see the results of printing Name in both joe and bob are the same because the change was on the object that they both refer to.
The following types are reference types:
  • arrays
  • class'
  • delegates
  • interfaces

Understanding Value Types

Value type variables, as their name (value) suggests, hold the object value. A value type variable holds its own copy of an object and when you perform assignment from one value type variable to another, both the left-hand-side and right-hand-side of the assignment hold two separate copies of that value. Listing 22-3 shows how value type assignment works.
Listing 22-3. Value Type Assignment
using System;

struct Height
{
  private int m_inches;

  public int Inches
  {
      get { return m_inches; }
      set { m_inches = value; }
  }
}

class Program
{
  static void Main()
  {
      Height joe = new Height();
      joe.Inches = 71;

      Height bob = new Height();
      bob.Inches = 59;

      Console.WriteLine("Original Height
          Values:");
      Console.WriteLine("joe = " + joe.Inches);
      Console.WriteLine("bob = " + bob.Inches);

      // assign joe reference to bob variable
      bob = joe;

      Console.WriteLine();
      Console.WriteLine("Values After
          Value Assignment:");
      Console.WriteLine("joe = " + joe.Inches);
      Console.WriteLine("bob = " + bob.Inches);

      joe.Inches = 65;

      Console.WriteLine();
      Console.WriteLine("Values After
          Changing One Instance:");
      Console.WriteLine("joe = " + joe.Inches);
      Console.WriteLine("bob = " + bob.Inches);

      Console.ReadKey();
  }
}
Here's the output:
Original Height Values:
joe = 71
bob = 59

Values After Value Assignment:
joe = 71
bob = 71

Values After Changing One Instance:
joe = 65
bob = 71
In Listing 22-3, you can see that the Inches property of bob and joe are initially set to different values. After assigning joe to bob, a value copy occurs, where both of the variables have the same value, but are two separate copies. To demonstrate value assignment results, notice what happens after setting joe to 65; The output shows thatbob did not change, which demonstrates that value types hold distinct copies of their objects.
The following types are value types:
  • enum
  • struct

Reference Type and Value Type Differences

From the previous paragraphs, you might already see that there is a difference reference type and value type assignment. Reference types copy a reference to an object and value types copy the object. If you don't know this, then the effects can be surprising in your code when performing tasks such as making assignments and passing arguments to methods.

C Sharp Tutorials/Lesson 23 Lesson 23: Working with Nullable Types


Lesson 23: Working with Nullable Types

Working with value types and data can sometimes be challenging because a value type doesn't normally hold a null value. This lesson show you how to overcome this limitation with C# nullable types. Here's what you'll learn.
  • Understand the problem that nullable types solve
  • See how to declare a nullable type
  • Learn how to use nullable types

Understanding the Problem with Value Types and Null Values

As explained in Lesson 12: Structs, the default value of a struct (value type) is some form of 0. This is another difference between reference types and value types, in addition to what was described in Lesson 22: Topics on C# Type. The default value of a reference type is null. If you're just writing C# code and managing your own data source, such as a file that holds data for your application, the default values for structs works fine.
In reality, most applications work with databases, which have their own type systems. The implications of working with database type systems is that you don't have a one-to-one mapping between C# and database types. One glaring difference is that database types can be set to null. A database has no knowledge of reference and value types, which are C# language (.NET Platform) concepts. This means that C# value type equivalents in the database, such as intdecimal, and DateTime, can be set to null.
Since a type in the database can be null, but your C# value type can't be null, you have to find some way to provide a translation in your C# code to account for null values. Effectively, the scheme you use will often be inconsistent from one program to another; something you often don't have a choice about. For example, what if you wanted to handle a null DateTime from SQL Server as the minimum DateTime value in C#. After that project, your next task would be to read data from a legacy Foxpro database, whose minimumDateTime value is different from SQL Server. Because of this lack of constency and potential confusion, C# 2.0 added nullable types, which are more elegant and natural for working with null data.

Declaring Nullable Types

To declare a value type as nullable, append a question mark, ?, to the type name. Here's how to declare a DateTime variable as a nullable type:
    DateTime? startDate;
DateTime can't normally hold a null value, but the declaration above enables startDate to hold null, as well as any legal DateTime value. The proper terminology is to refer to the type of startDate as a nullable DateTime.
You can assign a normal value to startDate like this:
    startDate = DateTime.Now;
or you can assign null, like this:
    startDate = null;
Here's another example that declares and initializes a nullable int:
    int? unitsInStock = 5;
The unitsInStock in the example above can be assigned a value of null also.

Working with Nullable Types

When you have nullable types, you'll want to check them to see if they're null. Here's an example that shows how you can check for a null value:
     bool isNull = startDate == null;

  Console.WriteLine("isNull: " + isNull);
The example above shows that you only need to use the equals operator to check for null. You could also make the equality check as part of an if statement, like this:
     int availableUnits;

  if (unitsInStock == null)
  {
      availableUnits = 0;
  }
  else
  {
      availableUnits = (int)unitsInStock;
  }
Note: Notice the cast operator in the else clause above. An explicit conversion is required when assigning from nullable to non-nullable types.
That's several lines of code for something that appears to be such a common operation. Fortunately, there's a better way to perform the same task, using the coalesce operator,??, shown below:
    int availableUnits = unitsInStock ?? 0;
The coalesce operator works like this: if the first value (left hand side) is null, then C# evaluates the second expression (right hand side).