Reflector is a utility program that you can use to examine any .Net assembly and look into the actual code. It has many uses and add-ins, but my favorite thing is to look into the Framework's implementation of various Classes and Methods. It is a great way to understand how certain functionality is implemented in the .Net Framework, how to use them efficiently, and also how to extend these functionality in the proper way.
For example, here is the implementation of IEnumerable.Cast<T> Extension Method:
As you can see, the implementation first checks if the passed in Collection is already an IEnumerable<T>, and if so, it avoids any further processing and returns the source cast as an IEnumerable<T>.
I am not sure who really created the Reflector. It is now acquired by Red Gate and being developed into a Visual Studio Integrated Tool that allows you to examine, debug and step through third party assemblies. The original Reflector is still available for free, so get it before Red Gate changes it's mind.
Posted on January 20, 2010 04:35 by
Haider
The Generic Dictionary<TKey,TValue> was introduced in .Net 2.0 as a replacement for the Hashtable. However, the implementation and behavior of the generic Dictionary is not exactly the same as a Hashtable, and it always bothered me. I felt that the generic Dictionary was not going to be as fast and efficient as a raw Hashtable. When speed was the utmost concern, I chose to use a Hashtable despite the lack of strongly typed Key and Value. And it kept bothering me, why was a different implementation chosen for the Dictionary, why not just wrapping around a Hashtable?
So finally I took the time to write some test code and compare the speed of Dictionary vs Hashtable. To my surprise, the Dictionary is faster! It is not only faster than the Hashtable, but also more consistent in the lookup times compared to a Hashtable. My focus here is look-up time, no comparison was done for the time it takes to add items.
Without going into the details, I will just outline the test setup:
A set of about 16,000 objects were added to a Hashtable and a Dictionary, with string of various length as the Key. Time was clocked for 50,000 lookups with the same Key from both Dictionary and Hashtable. This process was repeated with Keys of different length, as well as for items towards the beginning, middle and end of the list. In all cases, the Dictionary showed better performance (speed). Depending on the size of the key, and to which end of the list that item was located, the difference in speed varied, but I was able to clock anywhere between 10% to 40% faster lookups on the Dictionary.
Also, as I mentioned before, besides being faster, the Dictionary showed more consistent result while the Hashtable's speed varied over multiple runs. Don't ask me why.
Bottom line, there is no reason not to use the Dictionary over the concern of speed. Now I know.
Posted on January 15, 2010 05:03 by
Haider
If a Method or Property returns IEnumerable or Inumerable<T> Types, the only thing that is inherently possible on them is to Loop through (foreach{}). Sometimes it helps to know if the Collection has any items, without having to initiate a loop. The IEnumerable Interface is bare minimum for a collection and does not expose any properties at all. LINQ provides a convenient Extension Method called Any(), that you can call on any IEnumerable Type. Internally, this Method checks if any item is available in the Collection using the following code:
If you do not have LINQ in the project, or want a shortcut of this without having to call the Any() method, here is an alternative:
However, if we know the underlying Type of the Collection also implements ICollection Interface, we can simply cast it to ICollection and check the Count Property:
bool hasItems = ((ICollection)products).Count > 0;
The Count Property is maintained very efficiently by the Framework Collection classes. It would be preferable than having to call any Method.
Combining these two approach, here is another Extension Method that can be used for the same purpose:
//An alternate to the IEnumerable.Any() Method
public static bool HasItem(this IEnumerable source)
{
if (source == null)
{
throw new ArgumentNullException("source");
}
if( source is ICollection)
return ((ICollection)source).Count > 0;
else
return source.GetEnumerator().MoveNext();
}
Ideally, an IEnumerator should be wrapped within a using{...} block, like it is shown in the Framework's implementation of Any() Method above. Also note that there is an overload of the IEnumerable.Any() Method. It takes a Func<TSource, bool> and returns true only if any of the Collection items match the given condition. Here is an example:
//Lets assume there is a variable called products, with a collection of Product objects
//Product object has a boolean property called OnBackOrder
//We want to find out if any of the products is on back order
bool IsAnyOnBackorder = products.Any(p => p.OnBackOrder);
Posted on January 8, 2010 09:51 by
Haider
Sometimes there are properties on Objects that are meant to provide a Read Only set of items. For example, lets say the Customer Object has a LoginHistory Property that is meant to be Read Only. Internally the values may be populated in a List<T>, but returning the List<T> would make the Collection Read/Write. One solution is to make the property an IEnumerable<T>. Here is an example:
While this approach exposes a Read Only Collection, there are a couple of problems with the IEnumberable<T> interface. On the other side of the code, it is now difficult to know how many items are there in this collection, or if there is any item at all (Except with the help of Linq's Any() and Count() Extension Methods)! Having a Count Property would be helpful. Besides, the Collection is not really Read Only in this case. You could Cast this LoginHistory Property to a List<T> and Add Items to it:
A better approach would be to return the generic ReadOnlyCollection<T> instead if IEnumerable<T>. This class is in the System.Collections.ObjectModel Namespace, and List<T> has a Method called AsReadOnly() that returns a ReadOnlyCollection<T> Object. The LoginHistory Property would be implemented as follows:
There is a Count Property now, and Customer.LoginHistory is truly Read Only!
Posted on January 6, 2010 10:04 by
Haider
A Linq to SQL DataContext by default tracks all changes to Entities/Objects that are retrieved through it. In order to track the changes, the DataContext subscribes to the Events exposed by INotifyPropertyChanging Interface and INotifyPropertyChanged Interface of each Entity.
Often the result of a query is not intended for modification. For example, when a search query returns potentially hundreds or thousands of items to be displayed in a paged list, subscribing to Events of each item is unnecessary and will affect performance.
The solution to this is turning Object Tracking off on the DataContext, before executing the read only queries. It is accomplished by setting ObjectTrackingEnabled = false. Here is an example:
//Assuming the name of our custom DataContext is dbContext
dbContext context = new dbContext();
context.ObjectTrackingEnabled = false;
//Now query the database as usual
var q = context.Customers.Where(c => c.Name.StartsWith("John"));
Since it is very common to perform Read Only Queries like this. I prefer to have a static Property on the DataContext that returns a Read Only instance. This way setting ObjectTrackingEnabled every time can be avoided. Here is the ReadOnly static property:
/* Author: Abu Haider
/* January 2010
/* www.haiders.net
/* Adds a static method on a DataContext to return a ReadOnly instance */
public partial class dbContext //Your DataContext Class
{
public static dbContext ReadOnly
{
get { return new dbContext() { ObjectTrackingEnabled = false }; }
}
}
/* That's it */
Now the Read only instance can be queried as follows:
var q = dbContext.ReadOnly.Customers.Where( c => c.Name.StartsWith("John"));
No more having to create new instances of the DataContext and explicitly setting the ObjectTrackingEnabled. Besides, I think it also makes the code more readable by clearly indicating that the result set is intended for Read Only operations.
Posted on January 4, 2010 11:01 by
Haider