Not all string comparisons will perform the same but I was interested in seeing what exactly the differences were. Regardless of whether I was just performing 1 string comparison or 1 million, using the instance Equals() method was BY FAR the fastest. Of course the danger there is it will fail if the first string is null. Using == will always work regardless of nulls and for a million comparisons was almost as fast as Equals() and WAY faster than any other method (although it should be noted that using == is identical to using the static String.Equals() method). However, for 1 comparison it was by far the slowest. Note, for case-insensitive comparisons it is much faster to use the Compare() method with the case insensitive switch. Here are results below:

Incidentally, a look at the instance Equals() method in Reflector: [MethodImpl(MethodImplOptions.InternalCall)] public extern bool Equals(string value);

Doing a million string comparisons in a loop might not be your common every day programming task and the timing difference will obviously not be perceptible to a human.But let's say you have a web page that does a single string comparison - if that page is accessed in a high volume environment (by thousands of browsers at once), then every little performance enhancement you can make is quite important.

With the advent of .NET 2.0, Generics is undoubtedly the single most important language enhancement.However, to use generics to the full potential, developers should understand both the capabilities and limitations of generics as they relate specifically to polymorphism.In short, while generics do support some polymorphic behavior, the use of Interfaces should still be the preferred polymorphic mechanism in many cases.

First, an example of polymorphic capabilities,

abstractclassPerson

{

publicstring FirstName;

publicstring LastName;

publicvoid Speak();

}

classFireman : Person

{

publicint NumFiresExtinguished;

}

classPoliceman : Person

{

publicint NumArrestsMade;

}

Using System.Collections.Generics.List<>, one could consume like this:

List<Person> list = newList<Person>();

list.Add(newFireman());

list.Add(newPoliceman());

Since both Fireman and Policeman inherit from Person, this compiles just fine.

Futher, with constraints we can define our own generic sub-classes:

classPersonActionwhere T : Person

{

publicvoid DoAction(T item);

}

Like the example above, we can consume like this:

PersonAction<Person> personAction = newPersonAction<Person>();

personAction.DoAction(newFireman());

personAction.DoAction(newPoliceman());

PersonAction<Fireman> fireAction = newPersonAction<Fireman>();

fireAction.DoAction(newFireman());

//fireAction.DoAction(new Policeman()); <--Does not compile which is good

So far, everything is as we expect.However, if we try to push generic polymorphic behavior one step further, this is where things gets interesting.

One would think that these two previous statements would be legal.After all, we specified that the PersonAction must be and PersonAction certainly seems to satisfy this at first glance.However, the compiler does not allow this because when we use generics in this way, the compiler is expecting the exact type – Person.

The good news is that this situation is easily rectified by using Interfaces.

interfaceIAction

{

void DoAction(Person item);

}

And we’ll change PersonAction to:

classPersonAction : IActionwhere T : Person

{

publicvoid DoAction(T item);

publicvoid DoAction(Person item)

{this.DoAction((T)item); }

}

Now we can simply do this for polymorphic behavior with generic classes:

List<IAction> personActionList2 = newList<IAction>();

personActionList2.Add(newPersonAction<Fireman>());

personActionList2.Add(newPersonAction<Policeman>());

While there is no doubt that generics is one of the most important language enhancements we’ve seen in a while, there are many situation where traditional OOP with Interfaces should be the preferred implementation to support generics.