10 common traps and mistakes in C#

C#.NET

Please contribute by voting. Thanks!
9

1) Using the wrong type of collection

.Net has a lot of collection classes and they are all specialized on specific tasks. Make sure to select the right one with care. Making the wrong choice can make your code inefficient, have unexpected consequences as well as making your code's intent unclear.

Read more here: https://msdn.microsoft.com/en-us/library/6tc79sx1%28v=vs.110%29.aspx

2) Not using yield return

When enumerating over objects for another caller you should use yield return instead of creating a return collection. Some benefits of this pattern are that:
* You don't have to keep the whole collection in memory (it might be pretty big)
* Yield return immediately returns control to the caller after each iteration
* You only process results that actually are used (why iterate the whole collection if the caller just wants the first item?)

3) Parsing ambiguous dates

Be sure to specify a format provider when you parse ambiguous dates. For example, it is not clear what part of the date string "03/04/05" that are the month, day, and year and it can lead to serious errors for a user. Use DateTime.ParseExact / DateTimeOffset.ParseExact to provide the specific format:

var date = DateTime.ParseExact("01/12/2000", "MM/dd/yyyy", null)

4) Rethrowing Exceptions with an exception instance

If you want to catch and rethrow an exception, be sure to use the simple throw; syntax. If you use throw ex; it will not preserve the exception call stack.

DO:
catch(SomeException ex)
{
    logger.log(ex);
    throw;
}


DON'T:
catch(SomeException ex)
{
    logger.log(ex);
    throw ex;
}


5) Accessing virtual members in a constructor

The virtual keyword allows members of a class to be overridden in a derived class. Constructors are run from the base class to the most derived class. So if you call an overridden method from the constructor of a base class you may be executing code that is not ready for execution (it might depend on initialization done in it's own constructor).

Example:

public class Parent
{
  public Parent()
  {
    Console.WriteLine("Parent Ctor");
    Method();
  }

  public virtual void Method()
  {
    Console.WriteLine("Parent method");
  }
}

public class Child : Parent
{
  public Child()
  {
    Console.WriteLine("Child Ctor");
  }

  public override void Method()
  {
    Console.WriteLine("Child method");
  }
}

Instantiating the Child class will print the following:
Parent Ctor
Child method
Child Ctor

I.e. Child method is called before Child constructor.

6) Exceptions in static constructors

If a class throws an exception in a static constructor, it renders the class useless. Even a non-static construction will not be possible. The class will keep throwing a System.TypeInitializationException whenever it is referenced (static or not).

7) Optional parameters in external assemblies

Optional parameters may not work like expected when referenced from external assemblies.  Let's say that you provide some functionality packed in a DLL. Now let's say that you want to make a minor change in your code (changing an optional parameter to another value). The consumer of the DLL must recompile their application in order for your change to take effect.

Read more here: http://www.blackwasp.co.uk/DefaultParameterProblem.aspx

8) Generic methods with a non-generic overload

Let's say you have a generic method that takes a parameter of type T and another method with the same name but with a parameter of a specific type. The compiler will select the most specific method for each parameter type, and the specified type is more specific than the generic one.

Let's say you have the following class:
class GenericTest
{
  public void Test<T>(T parameter)
  {
    Console.WriteLine("Generic method!");
  }

  public void Test(string parameter)
  {
    Console.WriteLine("Non-generic method!");
  }
}

The following code...
var instance = new GenericTest();
instance.Test(7);
instance.Test("foo");

Will print the following result:
Generic method!
Non-generic method!

I.e. the compiler selected the more specific string method for the second call.

9) Changing the hash code after adding an object to a dictionary

Dictionaries depends on the keys' return value of Object.GetHashCode(). This means that the hash code of a key must not be changed after it has been added to the dictionary.

10) ValueType.Equals will be slow if the struct contains reference members

Be sure to not have any reference-members in your struct if you want to use the ValueType.Equals-method to compare two instances. This is due to the fact that ValueType.Equals will resort to Reflection to determine the equality of the reference members and this might be a bit slower than expected.


Article created: Mar 8 '16. Edited Mar 9 '16.

Your comment

You need to sign up / log in to comment this article

Author

Created by Robert Bengtsson [107] Mar 8 '16

Share article

Do you know about

TFS?

Write an article