C# Tips and Tricks

Local Type Inference

Local type inference was also the subject of another prior article, but again is worth mentioning here as it is very handy to have a solid understanding. You define variables with the var keyword and the compiler will figure out the type for you at compile time and replace it. It is great for results from query expressions as show in the example below. It may appear that it is untyped or even give the impression it is a variant. It is not. It is a strongly typed object whose type is set at compile time.

Object and Collection Initializers

Initializers introduce a concise syntax that combines object creation and initialization in a single step. It even allows for parentheses to be optional for paramaterless constructors as you'll see in the first line of the example below.

This functionality is great for demos where you are building collections of objects to do things like LINQ queries against. However, I caution you to consider real life initialization of large sets of data and whether code over a database is the proper place to store such information.

Initializers work very well with constructors. The example below shows an instance where a parameterized constructor is called along with remaining properties initialized. The constructor should commonly take all of the parameters so it isn't an ideal setup, but it illustrates the point well.

Extension Methods

Extension methods allow you to create new functionality on existing types. Even if the types are sealed. They are declared like static methods and called like instance methods. They are valid for use on interfaces or constructed types. The trailing sample code illustrates the use of extension methods to add a Triple and Half method on the decimal type.

Extension methods can be a very powerful tool. They can also be a very annoying tool if not used with some care. You should consider a separate namespace to allow them to be optional to the other developers that may be working within your codebase. Resist the temptation to put them on all objects by extending the object class. For consistency you should also make them behave like other instance methods.

The following code sample illustrates very bad form that should not be practiced. The namespace is System, which means the scope of this extension is any code that comes in contact with it. It extends ALL objects. It also does not behave like a normal instance method. Normally calling an instance method on a null object would result in a NullReferenceException and not a Boolean true or false value. This is a code example of what is not advisable.

LINQ Performance Tip

I'm not going to cover much on LINQ here as those are articles in and of themselves. Here is a LINQ performance tip that I experienced first hand on a project. Consider carefully the use of Table.ToList().Find(). Table.Where() is commonly a better option. ToList().Find() returns all records from a table and then runs the filter in memory. Table.Where() is performed in SQL and returns only the rows requested.

An additional tip is there is a handy tool known as LINQPad that allows you to perform interactive queries of databases using LINQ. It is a code snippet IDE that will execute any C# expression or statement block, which is very handy for testing out LINQ.