7 things you didn’t know about .NET code

Written by clm160 | Published 2018/03/21
Tech Story Tags: dotnet | software-development | csharp | aspnet | code

TLDRvia the TL;DR App

These are a few things (in no specific order) I found out during many hours of work, discussions with colleagues and a-ha moments. And I would like to share them with everyone and don’t be ashamed if you don’t know some or even all of them. In some cases it took me years to get to know them. So embrace them and it might make you a better .NET developer.

Geeky stuff

Number 1: Out parameter always changes value

Here is some simple code and a simple question:

int testParameter = -1;

Int32.TryParse(“abc”, out testParameter);

What will the value of testParameter be after the TryParse executes?

Easy to try for yourself, just put this in console application and display the value of testParameter. If you expected it to be -1 then you are wrong. Even if the TryParse will not succeed, the value of the int will become the default value, so it will be 0 (zero). This is what MSDN says about the out parameter: This parameter is passed uninitialized; any value originally supplied in result will be overwritten.

Number 2: Enums can have extension methods

We had a big Enum in code with the possible values of a variable. I am not getting into details why we need it or if it was the best choice for us, it’s not the case here. Lets say it looked something like this (trust me, it was bigger, this is just a smaller similar example):

enum Day {Sat=1, Sun, Mon, Tue, Wed, Thu, Fri};

Now imagine that if you would like to see if it is weekend, your code will be similar to this:

if (dayParameter == Day.Sun || dayParameter == Day.Sat) ….

So I created a method called IsItWeekend(dayParameter). Then one colleague said why don’t we create an extension method, instead of having the above method in every class we might need it?

And to be honest I didn’t think it would be possible to create an extension method on Enums, but 2 days later I came back to him and said: ‘sorry, I was wrong, it is possible to do it’. And I found that it really is powerful because the most used alternative is to create a Helper class and I don’t like them at all. I am not getting into details on how to create such an extension method because there is a very good article on MSDN about it. I believe it is more important to remember that it can be done.

Number 3: Use HashSet for distinct items

I find this code quite a lot in many projects:

List<string> uniqueItems = new List<string>();if(!uniqueItems.Contains(parameter)){uniqueItems.Add(parameter);}

So is there a problem with this? It works, but Contains performs a linear search on the list and that is O(n). Which can translate into performance issues in production if you end up having many of these (usually big CPU usage). Until .NET 3.0 people were creating Dictionaries with the key collection used for distinct lists and with the values set as NULL. But since .NET Framework 3.5 we have a new class called HashSet<T>. This is a collection without any duplicate elements and Contains method is O(1) operation. So our code quickly becomes:

HashSet<string> uniqueItems = new HashSet<string>();if(!uniqueItems.Contains(parameter)){uniqueItems.Add(parameter);}

Even more, we can remove the Contains call because Add will not add the element if it already exists, it just returns false (or true if it will be added). So again the code becomes like this:

HashSet<string> uniqueItems = new HashSet<string>();uniqueItems.Add(parameter);

Number 4: Many value types don’t live on the Stack

Value types are allocated on the Stack and reference types are allocated on the Heap. That’s what we learned, that’s what we say in interviews and we get away with it. Probably a lot of .NET books that are for beginners are saying this, so we read it from our first steps with C#. But it is wrong, it is just a myth, there are so many value types saved on the heap and here are two important examples of when that happens.

  • If the value type is a instance variable of an object then it gets saved on the Heap. Simple because that is where the whole object lives, so that’s where the value types get allocated too.
  • Another case is for static variables: a value type static variable is allocated on the Heap. And it makes sense because there is only one instance of that variable.

So what is the difference between value types and reference types, you might ask? That’s very simple: value types are passed by value (even if it is an instance variable of a reference type) while reference types are passed by reference. Which means that next time in an interview you can give a more accurate answer.

For more details on the subject of value types and reference types here is a great article by Jon Skeet.

Number 5: Response.Redirect on out of process sessions

This is one of my favorites because I found it around 2014 when we wanted to change an existing application to use out of process session. Our aim was to support multiple servers, but we didn’t want to use sticky sessions — we were deploying on AWS so using sticky sessions meant loosing all the advantage of auto scaling. We did learn a lot from going out of process with the session and using Response.Redirect was one of the outcomes. Lets say we have some simple code like this:

Session[“FlowId”] = Guid.NewGuid();//more code goes hereResponse.Redirect(Url.Action(“Account”, “Login”));

This works perfectly when the session is in process, but when it goes out of process that Session[“FlowId”] item will not get saved. It happens because Response.Redirect throws a ThreadAbort exception and because of that the thread never gets to the part where it saves the Session object in the outside store. When the Session is used in process all the changes are done on spot, which means that throwing the exception doesn’t affect the saving.

So what is the solution for making it work? Simple, Response.Redirect has an overload that takes a second parameter endResponse, just pass false and the exception will not get thrown. It is even recommended to set it to false because of performance reasons.

Session[“FlowId”] = Guid.NewGuid();//more code goes hereResponse.Redirect(Url.Action(“Account”, “Login”), false);

Number 6: A generic type creates different classes

We have the following class:

public class GenericCache<T>{public static int ctorCalls = 0;private List<T> list;public GenericCache(){ctorCalls++;list = new List<T>();}}

The implementation is pretty dumb, just for education purposes (so don’t ask me why ctorCalls is a public field). But such a class can be found quite frequently in a big application. There always has to be a Cache class (so you can save expensive I/O calls) and it will be a matter of time until it becomes generic (because you will use it for many of your classes).

GenericCache<string> genericCache = new GenericCache<string>();GenericCache<int> genericCacheInt = new GenericCache<int>();Console.WriteLine(GenericCache<DateTime>.ctorCalls);

In the lines above the constructor of the generic Cache class is called twice and then we want to print the value of ctorCalls to the console.

So what value will it display? Well if you say 2 then you are wrong. It is what generic does behind the curtains: GenericCache<string> will be a different type (class) than GenericCache<int> and GenericCache<DateTime>. Which means the static variable ctorCalls will have 3 instances, one for each generic type. So the value displayed to the console will be 0.

Number 7: Order of logical operations (AND and OR)

Ending with an easy and powerful one. This can create you a lot of headaches if not handled properly: && (AND) is more powerful than || (OR). Lets take a few examples to see what that means and how it can affect your code:

bool result;

result = (true || true) && false; //this gives false

result = true || (true && false); //this gives true

result = true || true && false;// what will be the result of this?

L̵i̵k̵e̵ ̵I̵ ̵s̵a̵i̵d̵ ̵a̵b̵o̵v̵e̵ ̵A̵N̵D̵ ̵i̵s̵ ̵m̵o̵r̵e̵ ̵p̵o̵w̵e̵r̵f̵u̵l̵ ̵t̵h̵a̵n̵ ̵O̵R̵,̵ ̵w̵h̵i̵c̵h̵ ̵m̵e̵a̵n̵s̵ ̵i̵t̵ ̵w̵i̵l̵l̵ ̵b̵e̵ ̵r̵u̵n̵ ̵f̵i̵r̵s̵t̵,̵ ̵e̵v̵e̵n̵ ̵i̵f̵ ̵i̵t̵ ̵i̵s̵ ̵t̵h̵e̵ ̵s̵e̵c̵o̵n̵d̵ ̵o̵p̵e̵r̵a̵t̵i̵o̵n̵.̵ ̵S̵o̵ ̵t̵h̵e̵ ̵t̵h̵i̵r̵d̵ ̵c̵a̵s̵e̵ ̵a̵f̵t̵e̵r̵ ̵w̵e̵ ̵d̵o̵ ̵t̵h̵e̵ ̵A̵N̵D̵ ̵o̵p̵e̵r̵a̵t̵i̵o̵n̵ ̵w̵i̵l̵l̵ ̵b̵e̵c̵o̵m̵e̵:̵ ̵r̵e̵s̵u̵l̵t̵ ̵=̵ ̵t̵r̵u̵e̵ ̵|̵|̵ ̵f̵a̵l̵s̵e̵ ̵s̵o̵ ̵i̵t̵ ̵w̵i̵l̵l̵ ̵g̵i̵v̵e̵ ̵y̵o̵u̵ ̵t̵r̵u̵e̵.̵ ̵S̵o̵ ̵i̵t̵ ̵i̵s̵ ̵e̵x̵a̵c̵t̵l̵y̵ ̵t̵h̵e̵ ̵s̵a̵m̵e̵ ̵w̵i̵t̵h̵ ̵t̵h̵e̵ ̵s̵e̵c̵o̵n̵d̵ ̵o̵p̵e̵r̵a̵t̵i̵o̵n̵.̵ ̵N̵o̵w̵ ̵m̵y̵ ̵s̵u̵g̵g̵e̵s̵t̵i̵o̵n̵ ̵i̵s̵ ̵t̵o̵ ̵a̵l̵w̵a̵y̵s̵ ̵u̵s̵e̵ ̵p̵a̵r̵e̵n̵t̵h̵e̵s̵i̵s̵ ̵f̵o̵r̵ ̵t̵h̵e̵ ̵o̵r̵d̵e̵r̵ ̵o̵f̵ ̵o̵p̵e̵r̵a̵t̵i̵o̵n̵s̵ ̵t̵o̵ ̵l̵o̵o̵k̵ ̵m̵o̵r̵e̵ ̵c̵l̵e̵a̵r̵.̵

The above explanation is not correct, the result will be true, but not because of the operator precedence, but because short circuit is applied. It knows the first value is true so it doesn’t go to execute the || and && operators it just stops and returns true.

Until I find a better example I will just put here the link to C# operators, that says AND conditional parameter is above OR. And thanks to @kabtoffe for pointing this out.

That’s it and I hope it is helpful to you. And please leave a comment if you know other interesting things that should be on the list of gotchas for .NET/C# code.

If you liked this and want more food for thought you can also register for my newsletter for software developers interested in .NET technologies. I am planning to send that twice a month, starting June 2018.


Published by HackerNoon on 2018/03/21