8 things every .NET developer must understand

You’ve been in your current job for a while now, and you’re really starting to get good at what you do.  You’re perhaps thinking about finding something new, and you’re wondering what sort of questions a potential new employer might ask.  I’ve been interviewing a lot recently and I have noticed there are 8 questions that get asked a lot.  Spend some time and make sure that you understand each point in turn, doing so will help make that dream job become a reality.

SOLID Principals

The ultimate acronym of acronyms.  You’ve heard of it, but do you know what it stands for? Do you really understand what each principal means? Yeah thought so.  This awesome video by Derick Bailey will clear things up a lot for you;

Garbage Collection & IDisposable

One of the best features of developing with any .NET language is the lack of effort you have to put in to garbage collection.  You generally don’t have to care too much about 1st/2nd/3rd gen collection cycles, de-allocating memory or anything like that.  Its still a very important topic, however, and every .NET developer should understand how it works.

Once you become a more experienced developer (and I’m especially talking to WPF developers here) you quickly learn that memory management isn’t a forgotten topic.  Failure to unsubscribe from events, failure to close streams, and keeping hold of large objects (say instantiating them in a loop that never ends) is a sure-fire way to balloon up your apps memory usage eventually resulting in a crash (commonly referred to as Memory Leaks).

A useful way of ensuring that managed resources are correctly cleaned up in a timely manner is to implement the IDisposable interface (and actually use it within a using block) on your objects.  Make sure you understand how this works how to implement it.

Example:

private Boolean disposed;

protected virtual void Dispose(Boolean disposing)
{
    if (disposed)
    {
        return;
    }

    if (disposing)
    {
        //TODO: Managed cleanup code here, while managed refs still valid
    }
    //TODO: Unmanaged cleanup code here

    disposed = true;
}

public void Dispose()
{
    Dispose(true);
    GC.SuppressFinalize(this);
}

~Program()
{
    Dispose(false);
}

Code snippet taken from SideWaffle.  Its not enough to simply implement IDisposable, you have to take it a step further by adding a second Dispose method to ensure that both managed and unmanaged resources are properly disposed.

Useful resources:

Three Common Causes of Memory Leaks in Managed Applications (DavidKlineMS)

Garbage Collector Basics and Performance Hints (MSDN)

Writing High-Performance .NET Code (Ben Watson)

Explain why you might use MVC over WebForms?

Another curve ball that employers might throw at you is “Why might you decide to use ASP .NET MVC over something like WebForms”.  I stuttered for a good 30 seconds before I eventually came up with a decent answer to this one, because simply saying “because MVC is better” is not a good enough argument.

Here are some things that come to mind;

  • MVC generates much simpler HTML code, which will be easier to style and maintain over time.
  • MVC arguably has a smaller learning curve, because Razor is very intuitive and developers get to reuse their existing knowledge of HTML/CSS without having to learn how specific user controls work.
  • Due to MVC’s simplified page lifecycle, overhead on the server is reduced potentially resulting in better performance.

There is endless argument about this on the web (the only example you need). I think in reality the employer is trying to establish two things here;

  • How well do you know your frameworks
  • But more importantly, can you assess the benefits and drawbacks of different frameworks and make an informed, unbiased decision regarding which one to use.  I.e. don’t just use it because everybody else is.

No-SQL databases

If you think that SQL server is the be-all-and-end-all, then its time to wake up! Its the year 2014 and the tech world has moved on.  I’m not suggesting for a second that companies are abandoning SQL Server, I believe that it will continue to play a major role in our industry for at least the next 5 years.  However, No-SQL databases are gaining massive traction because of their general speed, ease of use, and scalability benefits (not to mention the fact that SQL Server is very expensive, whereas RavenDB and MongoDB are much more affordable).

I’d recommend that you look at, and understand, each of the following;

Boxing and Un-boxing

It simply amazes me just how many developers don’t understand boxing and un-boxing.  Granted, its been less of an issue since generics was introduced in .NET 2.0 but done wrong, your application’s performance and memory usage will be seriously affected. 

Useful resources:

Also note, when a prospective employer asks you to explain this problem, they may also ask you to explain the difference between reference types and value types.  Reference types of course are classes, whereas value types are structs.  A value type can be thought of as the actual value of an object, whereas a reference type typically contains the address of the actual value, or null (value types are not nullable).

Hoisting and Closures

Developers now are required to have a broader range of skills than has typically been the case.  Its usually not enough to have just SQL and C# on your CV, employers are increasingly looking for more well rounded developers, with a range of skills including (but not limited to); HTML, CSS, JavaScript, KnockoutJS, TDD, AngularJS and so on.

You may never have realised it, but when writing JavaScript code variable scope is not exactly black and white.

Take the following example (pinched and adapted from here)

(function(){

    x = 5; 
 
    alert(x);

    var x;

})();

What is the value of x? No tricks here, the answer is of course 5, but why does this work?  Because the variable declaration is pulled (hoisted) to the top of the current scope.  So regardless of where you declare your variables inside a function, they will always be hoisted to the top.  Be sure that you understand this, as its a basic concept but often misunderstood.

Similarly, closures are another confusing concept of JavaScript that you may be asked about.  In the simplest terms, when you have a function inside another function, the inner function has access to any declared variables in the outer function. 

Example:

(function(){

    var x = "Hello";

    var f = function(){
        alert(x + ", World!");
    }

    f();

})();

What is the result? Hello, World! of course, again no tricks.  The code in the inner function always has access to variables declared in the outer function.

That explanation should pass the Albert Einstein test.

If you can’t explain it to a six year old, you don’t understand it yourself.

Is a string a reference type or a value type?

The one I used to dread the most, until I learnt it properly and understood it.  A string is a reference type, but it behaves like a value type!  Unlike most other reference types, a string is immutable, meaning that the object itself cannot be changed.  When you call a method such as Remove or Substring, you are creating a copy of the string with the new value.  The original string remains intact until it is de-referenced.

The primary reason for this is because the size of strings means that they are too big to be allocated on the stack.

As a side note, take the following code;

string c = "hello";
string d = "hello";

Console.WriteLine(c == d);

Why is the result true?  Well this is a .NET optimization to reduce the memory footprint.  Under the hood each variable has the same pointer (0x021x15ec in this case) to the actual value.  You should always use String.Equals when comparing strings to ensure that the actual value of each string is equality checked, instead of the pointer.

Summary

We looked at 8 concepts that every decent .NET developer should understand, especially when interview for a new role.  Whilst these may seem like simple concepts, they are often misunderstood and this will quickly be picked up by even the most inexperienced interviewer.  It’s important for .NET developers to know their language and their tools inside out to ensure that they have every chance of landing that next dream job.

.NET developers, utilize Git better using the command prompt

I’ve been using Git in Visual Studio for quite some time now (since not long after it was released) and I’ve really grown to like it.  I particularly like the speed and general ease of use.  I find TFS/TFVC (weather that be a local instance or TFS online) to be slow and unreliable and it really has poor command line support (sorry guys!). It’s fair to say that I’ve been a little bit intimidated by Git and have rarely (OK never!) strayed away from the UI available through Visual Studio.  Until now.

Visual Studio barely scratches the surface when it comes to the wealth of additional functionality available via the command prompt.  This post looks at some of the most commonly used commands (and how to use them).

10 Git commands for .NET developers

The easiest way to get started is;

  1. Open Visual Studio (and ideally open/create a project)
  2. Open the Team Explorer
  3. Click Changes, and then from the Actions drop down click Open Command Prompt.

VisualStudio

As an additional win, you can also bring up extensive formal documentation about any Git command as follows;

git help {command}

Terminology Comparison

There are some slight differences in terminology between Git and TFVC, here are some of them;

Git

TFVC

Commit

Commit

Clone

Snapshot

Commit id (the SHA1 checksum)

HEAD

Repository

Author / Contributor

Fork (take a copy of)

Changeset

Check In

Map

 

Changeset number (sequential number)

Current branch

Team Project

User

Branch

Git Add

AddedReadMeAdds a given file to the tracked (uncommitted) list, or adds all untracked files under the given directory.  By default, new files are not tracked by Git, they have to be added to the index.

Scenario

1. Add a new file to the root directory called ReadMe
2. Run git add ReadMe
3. File is added to the Included Changes list
4. Alternatively, run git add . to add all untracked files in the current directory (recursively scans through each sub directory)

 

Git Branch

Same concept as in TFVC, you create branches when;

  1. You create branches to make it easier when large teams are developing new functionality
  2. You are releasing the code to live or a test environment
  3. You want to fix bugs and you hate the world

There are a few useful parameters you can pass in to git branch here;

  1. {name-of-new-branch} if you just want to create a new branch
  2. --list, or no parameters, shows a list of current branches
  3. -m {new-name} renames the branch
  4. -d deletes the branch

Example:

git branch {name-of-new-branch}

 

Git Checkout

Switches the current development branch to the branch specified;

git checkout {some-branch}

All new changes will be committed to this branch.  If the branch does not already exist, you can create it and check it out using a single command;

git checkout –b {some-branch}

Can also be used to rollback to previous versions of files or specific branches as follows;

git checkout {commit-number} {file-name}

{commit-number} the specific changeset to roll back to
{file-name} optional, used to roll back a specific file

 

Git Clone

Clones (gets a copy of) the specified repository.  This example is using Visual Studio online, but should work with self-hosted instances of TFS (simply change the domain to that of your TFS instance, or the IP address of your TFS instance);

git clone https://{your-user-name}.visualstudio.com/DefaultCollection/_git/{project-name} {local-path}

Replace {your-user-name} with your TFS username and {project-name} with the name of the project you want to clone.  {local-path} is the location on your hard drive where you want to store the cloned files.

When you successfully connect, you will be prompted to enter your user name and password.  When the clone starts, you’ll will see some neat ASCII art and the progress of the operation;

GitClone

 

Git Commit

Takes a snapshot (also known as a revision) of the file/folder at the current point in time.  A snapshot cannot easily be edited.  You can roll back to specific snapshots as required.

Before you can take a snapshot, you must stage that changes that will be included.  This is done using git add (see above).  To include all files in the snapshot, use git add ..

There are a lot of options you can pass to this command, but the one you will use most often is –m, which allows you to pass a message to use to identify the commit at a later time;

git commit –m "{your-message-here}"

Git will display the first part of the commit identifier, which can be helpful for use later (rolling back the commit for example using the git reset command).  You can view a recent list of commits using the git log command.

image

 

Git Diff

Used to display the differences between the current directory/file and either the index or the most recent commit.

To display all the differences (including renames, deletes, adds, modifications etc.) against the index;

git diff

To display all the differences against the most recent commit;

git diff HEAD

Diff

The standard diff tool will display differences inline (red is the indexed/HEAD copy, green is the local copy).  To be honest, I don’t find this particularly helpful … especially when you are working with lots of differences.

Custom Diff Tool

You can easily configure Git to use a custom tool.  I use Beyond Compare (because I love it), but you can use whatever tool you like.  For a full explanation on how to configure Beyond Compare, see Git for Windows on the Scooter Software website.

Use the git config command to change the global diff setting;

git config --global diff.tool bc3
git config --global difftool.bc3.path "c:/Program Files (x86)/Beyond Compare 4/bcomp.exe"

You can also change the configuration for merging, which goes like this;

git config --global merge.tool bc3
git config --global mergetool.bc3.path "c:/Program Files (x86)/Beyond Compare 4/bcomp.exe"

To run the diff in the custom tool, run git difftool {file-to-diff}

BComp

I’m much more comfortable working with a proper GUI as I’m so used to using Visual Studio’s built in diff tool (which is also great).

 

Git Log

Displays recent commits to the current branch.  Simple but very useful command that shows a detailed list of revisions, including the SHA1 checksum, the author/contributor, the commit date and the commit message.

git log –n {number-to-display}

GitLog

The –n option is optional, but its useful as you could end up with a big list if you work with a larger team.

 

Git Pull

Grabs (pulls) the remote repository and merges it into the local copy in a single command. Git pull is actually a short-hand for git fetch followed by git merge.  To pull in all changes that have been made by other collaborators, you should use the git pull command.

git pull {remote-path}

When working with TFS, again the {remote-path} is that of the project to pull, for example;

https://{your-user-name}.visualstudio.com/DefaultCollection/_git/{project-name}

Pull Requests

A pull request is a mechanism for developers to request that their changes be merged in to the main branch.

Example: When using services such as GitHub or BitBucket, public collaboration and participation is possible and encouraged due to the open source nature of the code.  Anybody can come along, fork the repository (effectively creating a copy under their own user account) and start making modifications.  A pull request is simply a means of notifying the original owner that you want them to review your changes and ultimately merge them back to the master branch.  This way anybody can make changes to a project whilst the owner maintains overall control.

 

Git Push

All changes you make are stored in your local environment until you push them to the remote repository.  This process synchronises your local repository with the remote repository.

The basic push command;

git push {remote-path} {branch-name}

Again the {remote-path} option is that of the repository in TFS and {branch-name} is the name of the branch to push.  This operation will push your commits to the remote repository.

In the event of merge conflicts, Git will tell you and give you the opportunity to resolve conflicts when appropriate.

To force the push, use the --force option.  To push all branches, use the --all option.

 

Git Status

Shows the differences between the local copy and the staging area.  Can show lists of files that added/modified/deleted.  Also shows which files are untracked (files that need adding using git add).

Usage;

git status

Not to be confused with git log, which effectively shows you the history of the branch.

Summary

Visual Studio only scratches the surface when it comes to utilising functionality available when using Git. Whilst almost all of the above commands can be executed using Visual Studio, this is the first step on the way to moving away from that.  Once you start to feel more comfortable, you can start reading the documentation and experimenting with new commands and options (and believe me, there are thousands) that are not available via the UI.

Quick tip: Avoid ‘async void’

Frustrated Developer

When developing a Web API application recently with an AngularJS front end, I made a basic mistake and then lost 2 hours of my life trying to figure out what was causing the problem … async void.

Its pretty common nowadays to use tasks to improve performance/scalability when writing a Web API controller.  Take the following code:

public async Task<Entry[]> Get()
{
    using (var context = new EntriesContext())
    {
        return await context.Entries.ToArrayAsync();
    }
}

At a high level, when ToArrayAsync is executed the call will be moved off onto another thread and the execution of the method will only continue once the operation is complete (when the data is returned from the database in this case).  This is great because it frees up the thread for use by other requests, resulting in better performance/scalability (we could argue about how true this is all day long, so lets not do this here! Smile).

So what about when you still want to harness this functionality, but you don’t need to return anything to the client? async void? Not quite

Take the following Delete method:

public async void Delete(int id)
{
    using (var context = new EntriesContext())
    {
        Entry entity = await context.Entries.FirstOrDefaultAsync(c => c.Id == id);
        if (entity != null)
        {
            context.Entry(entity).State = EntityState.Deleted;
            await context.SaveChangesAsync();
        }
    }
}

The client uses the Id property to do what it needs to do, so it doesn’t care what actually gets returned…as long as the operation (deleting the entity) completes successfully.

To help illustrate the problem, here is the client side code (written in AngularJS, but it really doesn’t matter what the client side framework is);

$scope.delete = function () {

    var entry = $scope.entries[0];

    $http.delete('/api/Entries/' + entry.Id).then(function () {
        $scope.entries.splice(0, 1);
    });

};

When the delete operation is completed successfully (i.e. a 2xx response code), the then call-back method is raised and the entry is removed from the entries collection.  Only this code never actually runs.  So why?

If you’re lucky, your web browser will give you a error message to let you know that something went wrong…

browser-error

I have however seen this error get swallowed up completely.

To get the actual error message, you will need to use a HTTP proxy tool, such as Fiddler.  With this you can capture the response message returned by the server, which should look something like this (for the sake of clarity I’ve omitted all the HTML code which collectively makes up the yellow screen of death);

An asynchronous module or handler completed while an asynchronous operation was still pending.

Yep, you have a race condition.  The method returned before it finished executing.  Under the hood, the framework didn’t create a Task for the method because the method does not return a Task.  Therefore when calling FirstOrDefaultAsync, the method does not pause execution and the error is encountered.

To resolve the problem, simply change the return type of the method from void to Task.  Don’t worry, you don’t actually have to return anything, and the compiler knows not to generate a build error if there is no return statement.  An easy fix, when you know what the problem is!

Summary

Web API fully supports Tasks, which are helpful for writing more scalable applications.  When writing methods that don’t need to return a value to the client, it may make sense to return void.  However, under the hood .NET requires the method to return Task in order for it to properly support asynchronous  functionality.