While mentoring a junior developer and trying to help them understand dependency injection, I came across a topic that I didn’t find a really great explanation out there on the internet. That is, when you end up with circular references while using dependency injection.

I found that there was some great resources at understanding circular references in general, and obviously great articles on the .NET Core dependency injection system, but not so many options when trying to jam them together. These were my explanations and example classes on how things work, so that hopefully they help someone else!

The Problem

Imagine a “simple” piece of code like below.

public class UserService
{
    private readonly PhoneService _phoneService;

    public UserService(PhoneService phoneService)
    {
        _phoneService = phoneService;
    }

    public string GetUserPhoneNumber()
    {
        var userId = 123;
        return _phoneService.GetPhoneNumberById(userId);
    }
}

public class PhoneService
{
    private readonly UserService _userService;

    public PhoneService(UserService userService)
    {
        _userService = userService;
    }

    public string GetPhoneNumberById(int phoneNumberId)
    {
        return "+64123123123";
    }

    public string GetUserPhoneNumber()
    {
        return _userService.GetUserPhoneNumber();
    }
}

Now the circular reference in this case is rather.. idiotic and I don’t expect anyone to realistically run into this sort of code in production, but it demonstrates the issue quite well.

You see, first someone created a UserService. This dealt with everything about a user. Next came a PhoneService, that dealt with everything to do with phone numbers. A smart developer then said, well given I have a UserService, and I want to get the phone number of a user, I’ll inject the PhoneService into the UserService, and then get the current users phone number.

But then along comes another developer. They say, well, if I have the phone number service, since I am dealing only with phone numbers, then I want to get the current users phone number. They noticed that there is already a method called “GetUserPhoneNumber” on the UserService, so they just inject that and call it. Remember, they may not even know that the way that UserService actually finds the phone number is by calling the PhoneService itself, but alas, it does.

And now we have a problem. For the UserService to be constructed, we need a PhoneService. But for a PhoneService to be constructed, we need a UserService. This is a circular reference. Luckily for us, .NET Core is pretty good at picking these issues up at the earliest possible runtime (But not compile time), and we usually end up with an exception.

A circular dependency was detected for the service of type 'UserService'.
UserService -> PhoneService -> UserService

It even directly points out the exact services which depend on each other. Note that in some cases, the circle could be much larger. For example

UserService -> PhoneService -> AnotherService -> UserService

But as long as the circle is enclosed, then you will get an exception.

The “Lazy” Fix / Service Locator

This is a terrible bandaid and I never recommend using this. Ever. It’s simply a bandaid to a problem that is very very easy to get wrong. Previously in .NET, you could do something like :

public class UserService
{
    private readonly Lazy<PhoneService> _phoneService;

    public UserService(Lazy<PhoneService> phoneService)
    {
        _phoneService = phoneService;
    }


    public string GetUserPhoneNumber()
    {
        var userId = 123;
        return _phoneService.Value.GetPhoneNumberById(userId);
    }
}

All the Lazy modifier did was not try and request the service until it was actually required. This meant that the UserService could be created without actually needing the PhoneService until the actual execution path was called, and so theoretically, while the constructors were running, they did not enter an infinite loop.

.NET Core now picks this up however and if you try any sort of the above with Lazy, it will stop you from doing so.

A circular dependency was detected for the service of type 'UserService'.
UserService -> System.Lazy -> PhoneService -> UserService

So then, people would just inject some sort of ServiceLocator. For example :

public class UserService
{
    private readonly ServiceLocator _serviceLocator;

    public UserService(ServiceLocator serviceLocator)
    {
        _serviceLocator = serviceLocator;
    }


    public string GetUserPhoneNumber()
    {
        var userId = 123;
        return _serviceLocator.Get<PhoneService>().GetPhoneNumberById(userId);
    }
}

This does compile and actually run, but again is simply a band aid to the problem. You still have a circular reference, it’s just that at some point you are killing the circle by using a ServiceLocator. Ugh.

I would put the use of “Factories” in here as well. I’ve seen people get around the problem by using a “PhoneServiceFactory” that itself uses a ServiceLocator or similar to construct the PhoneService for the UserService, so again you are breaking the circle. But again, you still have a circular reference you are just hacking your way out of it.

Kill The Reference

Far and away the best option for digging your way out of this hole is to not reference each other at all and if at all possible, have a one way reference between the services. So we *could* change our code to simple remove the GetUserPhoneNumber method from the PhoneService, and if you want a users phone number, you have to use UserService to get it.

public class UserService
{
    private readonly PhoneService _phoneService;

    public UserService(PhoneService phoneService)
    {
        _phoneService = phoneService;
    }

    public string GetUserPhoneNumber()
    {
        var userId = 123;
        return _phoneService.GetPhoneNumberById(userId);
    }
}

public class PhoneService
{
    public string GetPhoneNumberById(int phoneNumberId)
    {
        return "+64123123123";
    }
}

In our example, we really only had a circular reference out of convenience and not because we actually needed the method on both services. In some cases simply having a one way reference doesn’t work in which case…

Create A “Joining” Service

While not a great working example, what you’ll often have to do is create a “JoiningService”, for example a “UserPhoneNumberService”, where either the UserService and PhoneService both reference this service, or vice versa.

Often you can put all the shared functionality that both services need into this service. Or you can have this as an entry point to then call both the UserService and the PhoneService to get data instead of them calling each other.

Runtime Stack Overflows

If you have a circular reference that you attempt to get around using Factories, Lazy’s, ServiceLocators, or some other bandaid. What you might find is that you end up with one of the following errors.

System.InsufficientExecutionStackException
The program '[4176] iisexpress.exe' has exited with code -1073741819 (0xc0000005) 'Access violation'.

The most common reason is because you have registered a service as a factory in .NET Core DI :

services.AddTransient(s => new UserService(s.GetService()));

This is essentially a form of Lazy that the .NET Core DI container cannot pickup early on at runtime. What you are basically saying is “When you create the UserService, run this method”. Now “This method” is constructoring a new UserService, and trying to pull the PhoneService from the ServiceCollection. But because PhoneService references the UserService, we loop back on ourselves and execute this method again.

There aren’t really any safeguards against this because it’s hard to know at compile time exactly how things will be executed, but it’s a circular reference none the less.

ENJOY THIS POST?
Join over 3.000 subscribers who are receiving our weekly post digest, a roundup of this weeks blog posts.
We hate spam. Your email address will not be sold or shared with anyone else.

Cloning objects in any programming language is tricky, but I think in C# that’s taken up an extra notch by giving you a couple of tools that look like they would probably solve your problem, but then not letting you know that it’s likely to only solve a very slim use case and nothing else. This guide is going to be half a guide on cloning, but also a quick refresher on what “cloning” actually means in the context of C#.

Shallow Clone vs Deep Clone

It’s worth starting at the basics. What is the difference between a shallow clone and a deep clone? (Also sometimes known as a shallow copy and a deep copy).

A shallow clone is a copy of an object that duplicates as little as possible. In C# this generally means that value types are duplicated, but reference types are not. Or as an example, let’s take the following object :

class Person
{
    public int Age { get; set; }
    public Person Father { get; set; }
    public Person Mother { get; set; }
}

If I made a shallow clone of this object and changed the age, the original object would not have it’s age changed. However, if I then changed a property on the cloned object’s father, then I would also affect the original object’s father because the reference isn’t cloned.

That may be a little confusing so thinking of it another way, in C#, when you do a shallow clone of an object, you are going “one level deep”, hence shallow. Any objects inside the object you want to clone are not themselves recursively cloned as well.

A deep clone is obviously the opposite. It keeps going down the tree and tries to clone all properties of your object, then the properties of that property etc.

Memberwise Clone

So if you’ve done any research at all into cloning in C#, you’ve probably come across the “memberwise” clone method. It’s available to every class but *only inside that class* as it’s a protected method of Object. You cannot call it on an object from another class.

For example :

class Person
{
    public string Name { get; set; }
    public Person Father { get; set; }
    public Person Mother { get; set; }

    public Person Clone()
    {
        return (Person)this.MemberwiseClone();
    }
}

However a quick look at the intellisense tells us something…

Creates a shallow copy of the current Object.

A shallow copy. Oof! So calling clone on this object will only shallow clone it, and not do a deep clone. If your object is purely primitives, then this can actually work for you and you can stop right here. But in most cases, we are looking to a deep clone. Even if for the sole reason that should someone add a property of another class here, then everything doesn’t suddenly break.

ICloneable Interface

So you might have also come across this interface called “ICloneable”. Unfortunately, it doesn’t really solve any problems an infact the documentation has this to say :

Because callers of Clone() cannot depend on the method performing a predictable cloning operation, we recommend that ICloneable not be implemented in public APIs.

Pretty stern words but it makes sense because if we look at how we might implement ICloneable.

class Person : ICloneable
{
    public string Name { get; set; }
    public Person Father { get; set; }
    public Person Mother { get; set; }

    public object Clone()
    {
        return this;
    }
}

Here we haven’t even cloned our object, we’ve just returned the same exact instance. While yes, we may expect a developer to know better, the point is that a caller doesn’t have any idea how the deep the clone goes, or if it’s even a clone at all. For this reason, people tend to stay away from the ICloneable interface.

Even if you get past that… It returns an object rather than a Person object which is annoying!

But with all that said, ICloneable doesn’t actually provide implementation details for cloning anyway. It just tells a caller “maybe call this and try your luck at getting a clone back”, but it doesn’t help a developer actually do a clone, shallow or deep.

Manually Deep Cloning

A sure fire way to know that you are deep cloning an object is to manually deep clone it yourself!

class Person
{
    public string Name { get; set; }
    public Person Father { get; set; }
    public Person Mother { get; set; }

    public Person Clone()
    {
        return new Person
        {
            Name = this.Name,
            Father = this.Father == null ? null : new Person { Name = this.Father.Name },
            Mother = this.Mother == null ? null : new Person { Name = this.Mother.Name }
        };
    }
}

In our clone method we are now creating new objects to completely clone our object and have no references to the original. This works great but it is time consuming. Any new property on this object means we have to modify our Clone method and re-test everything again.

On top of that, we are only going one level deep, for example we are not cloning our Father’s father, or our Mother’s mother.We may not need them for whatever we are then doing with our clones, but it’s also not a true “clone”. It’s just a clone of whatever we could be bothered mapping across!

With all those complaints out of the way however, it’s really not a bad option if it’s only a couple of classes that you really want to clone and they aren’t going to be modified that often.

Binary Serializer Cloning

An exceptionally common way of doing deep clones (Or atleast, more than just a shallow clone) is by serialising the data to another format and then back again.

Take this example of using a Binary Serializer on our Person class :

[Serializable]
class Person
{
    public string Name { get; set; }
    public Person Father { get; set; }
    public Person Mother { get; set; }

    public Person Clone()
    {
        IFormatter formatter = new BinaryFormatter();
        using (stream = new MemoryStream())
        {
            formatter.Serialize(stream, this);
            stream.Seek(0, SeekOrigin.Begin);
            return (Person)formatter.Deserialize(stream);
        }
    }
}

One very important thing to notice is that we’ve had to decorate our class with a [Serializable] attribute, without it we get :

Type 'Person' is not marked as serializable.

It’s also somewhat annoying to have to add this code to every class, so it’s far more likely that we create a static cloning service like this :

public static class CloningService
{
	public static T Clone<T>(this T source)
	{
		// Don't serialize a null object, simply return the default for that object
		if (Object.ReferenceEquals(source, null))
		{
			return default(T);
		}
		
		IFormatter formatter = new BinaryFormatter();
		using (stream = new MemoryStream())
		{
			formatter.Serialize(stream, source);
			stream.Seek(0, SeekOrigin.Begin);
			return (T)formatter.Deserialize(stream);
		}
	}
}

We still however have that issue of marking things as [Serializable].

JSON Serializer Cloning

This method is… Well.. a little rough but I’ve honestly found it works the best. You’ll first need to install the Newtonsoft.Json nuget package.

Install-Package Newtonsoft.Json

Then you can modify our cloning service like so :

public static class CloningService
{
	public static T Clone<T>(this T source)
	{
		// Don't serialize a null object, simply return the default for that object
		if (Object.ReferenceEquals(source, null))
		{
			return default(T);
		}

		var deserializeSettings = new JsonSerializerSettings { ObjectCreationHandling = ObjectCreationHandling.Replace };
		var serializeSettings = new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Ignore };
		return JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(source, serializeSettings), deserializeSettings);
	}
}

And can I just say, everytime I’ve had to do this I think “Converting this to JSON and back again really isn’t great….”. But it just works. It handles everything you throw at it and is pretty much faultless.

In my opinion, if you are looking for a sure fire, re-useable way to clone objects in your code. This is it.

Reference Loops When Cloning

Eagle eyed readers will notice that in the above JSON cloning service, we have a line to handle reference looping. This is a very very common occurence, especially in models that are used as part of a DataModel where the two classes will reference each other. No matter how you decide to clone objects, you will always have issues where objects reference each other and any attempt to clone just spirals into an endless loop.

So even though in the above code, we solve it using a setting, it’s worth pointing out that no matter which way you decide to clone objects, this is going to always be a problem.

What’s Your Solution?

Think this page is full of hacks (it is!), and have a much better way to clone objects? Feel free to drop a comment below.

ENJOY THIS POST?
Join over 3.000 subscribers who are receiving our weekly post digest, a roundup of this weeks blog posts.
We hate spam. Your email address will not be sold or shared with anyone else.

Lately I seem to have run into a tonne of these types of errors when trying to host .NET Core applications inside IIS

HTTP Error 502.5 - ANCM Out-Of-Process Startup Failure

and

HTTP Error 500.30 - ANCM In-Process Start Failure

And to be honest, they have been incredibly hard to debug. If you search for these errors on Google, you’ll find hundreds of stack overflow posts detailing people running into them, often with very little follow up on how they solved the issue. Sometimes they’ll even go as far to say “I re-installed everything and now it works” which in most cases, is not going to be viable. “Hey boss, let me just wipe this server real quick” generally doesn’t cut it.

But hopefully, fingers crossed, this will be the last blog post you’ll ever have to read on these error messages!

Why Are There Two Error Messages?

So first let’s touch on why there are two different messages (And error codes). Essentially, they are the exact same error but refer to different hosting models when running IIS infront of .NET Core. We won’t dive too deep into what these hosting models are, as at some point (.NET Core 2.1+ I believe) the default hosting model got swapped from Out-Of-Process to In-Process, so it very well could depend entirely on the version of .NET Core you are running.

Just know that for all practical purposes, these two error messages are the same so if you are following some blog post that is talking about one of these error messages, but you have the other, you can still follow along as it may well solve your problem.

Solution #1 – Incorrect Or Non-Existent .NET Core Hosting Bundle

So if you’re using something like Azure App Services that abstract away all the server management for you, then you can probably skip this, but if you are managing the server yourself (Or you’re trying to run a .NET Core application on your PC), then definitely read on.

If you followed our guide to running .NET Core on IIS (Which you definitely should) you would know that you need to install the .NET Core “Hosting Bundle” for .NET Core web apps to work inside IIS. This is also required even if you use self contained deployments. It is also required even if you install the .NET Core runtime on the machine. I’ll repeat, you cannot host .NET Core web applications inside IIS unless you install the hosting bundle.

If you are on your server and you aren’t sure if you have the hosting bundle installed, go to Add/Remove Programs in Windows and search for hosting :

If you don’t have this, then you can go here : https://dotnet.microsoft.com/download/dotnet-core/3.1 and download the hosting bundle :

It’s also important to note. Download the hosting bundle that matches the version of .NET Core you are running. I would presume that things are backwards compatible and if you download a newer version, it will work with older versions of .NET Core, but it’s super important to have atleast the same version as your actual code.

And finally. Restart your machine. I cannot make that any more clear. I cannot tell you how many people install everything under the sun and nothing seems to “work”, but it’s because they haven’t restarted. For the most part, you can get away with just an IISReset, but restarting the machine is often easier and just makes sure that you are restarting absolutely everything you need to.

For Shared Hosting, you may need to open a ticket with your provider. Again, I’ve seen providers only have the .NET Core 2 Hosting Bundle and people are trying to deploy .NET Core 3.1 applications. It pays to ask!

Still not working? Move onto Solution #2.

Solution #2 – .NET Core Startup Process Fails

This one took me an absolute lifetime to workout, but as it turns out, the .NET Core startup process has to start successfully before IIS can take over. That means if certain startup routines of .NET Core fail, then IIS doesn’t know how to handle the exception and just gives a generic error. Infact, that’s why it’s called an “ANCM Startup Failure”!

So what sort of things are we talking? Well for me, the most common one has been integrating with KeyVault. If you follow the official documentation here, it tells you to add it to your CreateHostBuilder method. CreateHostBuilder is ran on startup and needs to complete *before* IIS can take over, if for some reason your app cannot connect to KeyVault (Firewall, permissions etc), then your applicaiton will crash and IIS will have no option but to bail out as well.

Generally speaking, most of the times I see these ANCM startup failures has been when I’ve added code to the CreateHostBuilder method in my program.cs. Truth be told, it’s actually 100% of the time.

But how can we diagnose them? The easiest way is to actually run our application via Kestrel direct on the server. On a metal server (e.g. One you can RDP to), this means simply going to the folder where our application dlls are, and running “dotnet myapplication.dll” and seeing if it runs. What you should see is that the startup error is printed to the console and should point you in the right direction. Remember, in production configuration, firewalls, keys, and secrets could all be completely different so just because the application starts up fine on your local machine, on a remote machine it could completely blow up.

For sites hosted inside things like Azure App Services, you need to find a way to run the application manually yourself. On Azure, this means using Kudu, but on shared hosting services, you might be completely out of luck. If that’s you, you really have two options :

  • Open a support ticket to see if they can run your application manually in Kestrel like above, and hand you the error. (Again, this might be worth it to see if they even support the version of .NET Core you are intending to run).
  • Guess. Yes guess. Check your applications program.cs and how your HostBuilder is created. Start removing things and redeploying until you find the thing that is breaking it. If possible, create a simple hello world application and deploy it, if it also breaks, then it points more towards the hosting bundle than anything wrong with your startup code.

Debugging With stdout

Still need further debugging. Here’s another tip!

After publishing a .NET Core app, you will find in the publish directory there is a web.config with minimal information, but you should see something like so :

<aspNetCore processPath="dotnet" arguments=".\MyTestApplication.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" hostingModel="inprocess" />

Pretty obvious here, we just change stdoutLogEnabled=”false” to stdoutLogEnabled=”true” and redeploy. This should enable additional IIS logging to ./logs and allow us to debug further. Honestly, I’ve found this really really hit and miss. I’ve found that running the application directly from the console on the server to be much more helpful, but this is also an option if you have no other way.

Still Not Working?

Still not working? Or solved it a different way? Drop a comment below with a link to a GIT Repo and let the community help. This is honestly an infuriating error and I’ve had 20 year veteran programmers pull their hair out trying to solve it, so seriously drop a line. If you aren’t comfortable leaving a comment to your code, try wade[at]dotnetcoretutorials.com and I’ll see what I can do!

ENJOY THIS POST?
Join over 3.000 subscribers who are receiving our weekly post digest, a roundup of this weeks blog posts.
We hate spam. Your email address will not be sold or shared with anyone else.

Getting Setup With C# 9

If you aren’t sure you are using C# 9 and/or you want to start using some of the new shiny features in the C# language, be sure to read our quick guide on getting setup with C# 9 and .NET 5. Any feature written about here is available in the latest C# 9 preview and is not a “theoretical” feature, it’s ready to go!

C# 9 Features

We are slowly working our way through all new C# 9 features, if you are interested in other new additions to the language, check out some of the posts below.

A Console Application Today

Start any new console application today from Visual Studio, and you’ll see something like this :

using System;

namespace TestTopLevelPrograms
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
        }
    }
}

A bog standard console application that says Hello World. Not a heck of a lot going on here. But in many ways, it’s ever so slightly over engineered. Show this to a new programmer as their “first” program. And they’ll say “But what’s this namespace thing?” “What does static mean?” “What are args? Do I use them or?”. There’s just ever so much going on for such a simple program.

And taking it further, this isn’t limited to newbie programmers. It can be frustrating when you just want to “script” something, and you have all this boiler plate. And that’s what Top Level Programs solves.

Top Level Programs

Top level programs (also referred to as Top Level Statements) does away with this. We can take our simple application and turn it into :

using System;

Console.WriteLine("Hello World!");

That’s it! No more namespace, no more program class, just a bog standard simple script. In some ways, if you are a fan of using things like Linqpad, this is a very similar experience.

And I mean.. That’s it.. That’s top level programs! There really isn’t much more to it!

If you want to get started, as of today, there isn’t a Visual Studio template for writing everything top level (Well.. I mean that would just be a blank file). But if you create a new console application, then ensure you are using C# 9 by editing your .csproj to match the below :

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net5.0</TargetFramework>
    <LangVersion>9.0</LangVersion>
  </PropertyGroup>
</Project>

Then you should be able to essentially delete everything in your program.cs and start fresh.

Using Async

Want to use an sync method, no problem. Check this out :

using System;
using System.Threading.Tasks;

await MyAsyncMethod();
Console.WriteLine("Hello World!");

async Task MyAsyncMethod()
{
    await Task.Yield();
}

Using await tells the compiler that the compiled main entry point should also be async. And we are also showing off the fact that you can add in local method to this top level file to. It may just be the return of the one file wonder!

Using Args

Missing Args? No problem.

using System;
Console.WriteLine(args[0]);

Your args are still there, just not as obvious!

Who Is This For?

So finally, a quick note on who this is for. I don’t really feel like this is aimed at any one level of C# developer. While it’s helpful for newbies to find their footing in a more “scripting” environment, the fact that you can now just whip up a quick one file wonder without all the cruft of your regular console app is actually amazingly useful at any level.

I actually have a sneaking suspicion that those developers who fell in love with NodeJS with it’s simple one file APIs may also like the simplicity of this one. Imagine just being able to create a dead simple API that can return some lookup value, and it’s just a matter of opening up an empty file and typing.

Troubleshooting

If you get the following error :

The feature 'top-level statements' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version.

It means you are using a version of C# less than 9 (Or atleast not with the latest preview version). Check out our quick guide on getting setup with using C# 9 and all it’s features here : https://dotnetcoretutorials.com/2020/08/07/getting-setup-with-c-9-preview/

ENJOY THIS POST?
Join over 3.000 subscribers who are receiving our weekly post digest, a roundup of this weeks blog posts.
We hate spam. Your email address will not be sold or shared with anyone else.

Getting Setup With C# 9

If you aren’t sure you are using C# 9 and/or you want to start using some of the new shiny features in the C# language, be sure to read our quick guide on getting setup with C# 9 and .NET 5. Any feature written about here is available in the latest C# 9 preview and is not a “theoretical” feature, it’s ready to go!

C# 9 Features

We are slowly working our way through all new C# 9 features, if you are interested in other new additions to the language, check out some of the posts below.

What We Have Currently

So before we jump into C# 9 and Init Only Properties, I thought let’s take a quick look on the problem this feature is actually trying to solve. In some classes, typically “model” classes, we want to make properties publicly readable, but not be able to be set outside our class. So something like this is pretty common :

public class Person
{
    public string Name { get; private set; }
}

We can now set the property of Name anywhere inside the class, for example in a constructor or from a method pretty easily :

public class Person
{
    public Person(string name)
    {
        this.Name = name;
    }

    public void SetName(string name)
    {
        this.Name = name;
    }

    public string Name { get; private set; }
}

But what’s harder now is that we can’t use an Object Initializer instead of a constructor, even if we are “newing” up the object for the first time, for example :

var person = new Person
{
    Name = "Jane Doe" // Compile Error 
};

No bueno! We get the following error :

The property or indexer 'Person.Name' cannot be used in this context because the set accessor is inaccessible

It’s not the end of the world but pretty annoying none the less.

But there’s actually another bigger issue. That is that in some cases, we may want a property to be set inside a constructor *or* object initialization and then not be changed after being created. Essentially, an immutable property.

There’s actually nothing that stops us from modifying the property after creation from inside the class. For example a private method can be called to edit the property just fine like so :

public class Person
{
    public void SetName(string name)
    {
        this.Name = name;
    }

    public string Name { get; private set; }
}

And that’s the larger problem here. I think for many years C# developers have used “private set;” as a way to half achieve immutability by only setting that property within a constructor or similar, and that sort of works for libraries where you don’t have access to the actual source code, but there’s nothing actually signalling the intent of the original developer that this property should *only* be set on object creation and never again.

Introducing Init-Only Properties

Let’s take our Person class and modify it like so :

public class Person
{
    public string Name { get; init; }
}

Notice how we change our “set” to “init”. Pretty easy, now let’s look at how that might affect code :

var person = new Person();
person.Name = "Jane Doe"; // Compile Time Error

Immediately the compiler throws this error :

Init-only property or indexer 'Person.Name' can only be assigned in an object initializer, or on 'this' or 'base' in an instance constructor or an 'init' accessor

OK so far, pretty similar to the “private set” we were using before. But notice that object initializers now do work :

var person = new Person
{
    Name = "Jane Doe" // Works just fine!
};

How about in the constructor?

public class Person
{
    public Person(string name)
    {
        this.Name = name;
    }

    public string Name { get; init; }
}

Also compiles fine! And what about in a method on a class :

public class Person
{
    public void SetName(string name)
    {
        this.Name = name; // Compile Error
    }

    public string Name { get; init; }
}

Boom! Everything blows up. So we’ve got that immutability we’ve always been after with private set, but it’s actually enforced this time!

Init is a relatively small change on the face of it, it’s just an extra keyword for properties, but it does make complete sense why it’s been added and I’m sure will be a welcome change for all C# developers.

Comparison With Readonly Variables

So I know someone on Twitter will definitely shoot me down for saying that we “finally” have immutable properties when we’ve had the “readonly” keyword for quite some time now. But there’s some differences that really make the init change a huge quality of life addition.

So this does create an “immutable property” :

public class Person
{
    public Person(string name)
    {
        _name = name;
    }

    private readonly string _name;
    public string Name => _name;
}

However you must now use the constructor, you cannot do this using object initializers :

var person = new Person
{
    Name = "Jane Doe"
};

Also the fact that you have to create a backing variable for the property is rather annoying so… I still love the init addition.

Side note. Someone pointed out in the comments that you can create a hidden backing field just by adding a single get accessor :

public class Person
{
    public string Name { get; } 
    
    Person(string name) 
        => Name = name;
} 

So this also works and is pretty close to immutability, but again, no object initializer (And no really signally the intent I think). But shout out to Antão!

I should also note that init properties actually work well with readonly variables if you actually do need it since init is only run at object construction which fits the readonly paradigm just fine. So as an example, this compiles and runs fine :

public class Person
{
    private readonly string _name;

    public string Name
    {
        get => _name;
        init => _name = value;
    }
}

Troubleshooting

If you get the following error :

The feature 'init-only setters' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version.	

It means you are using a version of C# less than 9 (Or atleast not with the latest preview version). Check out our quick guide on getting setup with using C# 9 and all it’s features here : https://dotnetcoretutorials.com/2020/08/07/getting-setup-with-c-9-preview/

ENJOY THIS POST?
Join over 3.000 subscribers who are receiving our weekly post digest, a roundup of this weeks blog posts.
We hate spam. Your email address will not be sold or shared with anyone else.

Getting Setup With C# 9

If you aren’t sure you are using C# 9 and/or you want to start using some of the new shiny features in the C# language, be sure to read our quick guide on getting setup with C# 9 and .NET 5. Any feature written about here is available in the latest C# 9 preview and is not a “theoretical” feature, it’s ready to go!

C# 9 Features

We are slowly working our way through all new C# 9 features, if you are interested in other new additions to the language, check out some of the posts below.

What We Currently Have

I remember reading the words “relational pattern matching” and kinda skipping over the feature because I wasn’t really sure what it was (And so, my developer brain said it can’t be that important!). But when I eventually found actual examples of it in action, I couldn’t believe that C# hadn’t had this feature yet.

So first, let’s mock up a problem in C# 8 that we should be able to solve with Relational Pattern Matching in C# 9 to actually be able to see the power.

Let’s take the following code :

int myValue = 1;

if (myValue <= 0)
    Console.WriteLine("Less than or equal to 0");
else if (myValue > 0 && myValue <= 10)
    Console.WriteLine("More than 0 but less than or equal to 10");
else
    Console.WriteLine("More than 10");

How could we improve it? Well, I would probably still use the If/Else jumble from above in most cases just for it’s simplicity, but if you wanted to, you could use the Pattern Matching introduced in C# 7 with a switch statement. That would look something like this :

switch(myValue)
{
    case int value when value <= 0:
        Console.WriteLine("Less than or equal to 0");
        break;
    case int value when value > 0 && value <= 10:
        Console.WriteLine("More than 0 but less than or equal to 10");
        break;
    default:
        Console.WriteLine("More than 10");
        break;
}

Not bad but we don’t really add anything to the If/Else statements, in fact we actually add even more complexity. If we are using C# 8, then we can use Switch Expressions (A great introduction here if you’ve never seen Switch Expressions before : https://dotnetcoretutorials.com/2019/06/25/switch-expressions-in-c-8/). That would instead look something like :

var message = myValue switch
{
    int value when value <= 0 => "Less than or equal to 0",
    int value when value > 0 && value <= 10 => "More than 0 but less than or equal to 10",
    _ => "More than 10"
};

Console.WriteLine(message);

This actually looks pretty good. But there is *so* much verbose stuff going on here that surely we can clean up right?

Adding The “is”/”and” Keywords

This actually isn’t specific to our example, but C# 9 has introduced the “is” and “and” keywords (We’re going to do an entire article on these in the future because there is actually some really cool stuff you can do). And these can actually help us here, we can now change this :

if (myValue > 0 && myValue <= 10)
    Console.WriteLine("More than 0 but less than or equal to 10");

To this :

if (myValue is > 0 and <= 10)
	Console.WriteLine("More than 0 but less than or equal to 10");

It’s just some sugar around saying “take this value and then I can do 1 to N statements on it all at once”. In long IF statements where you check multiple different options for a single variable/property, this is a huge help.

So obviously we can rewrite our If/Else statement from above to look like so :

if (myValue <= 0)
    Console.WriteLine("Less than or equal to 0");
else if (myValue is > 0 and <= 10)
    Console.WriteLine("More than 0 but less than or equal to 10");
else
    Console.WriteLine("More than 10");

And while that middle statement is a bit tidier, overall we are still writing quite a bit.

Relational Pattern Matching In Switch Statements/Expressions

Now we are cooking with gas. In C# 9, we can now turn this big case statement :

case int value when value > 0 && value <= 10:

Into this :

case > 0 and <= 10:

So we can do away with setting our variable for the pattern, and then add in our new “and” keyword to make things even tidier. That turns our entire switch statement into this :

switch(myValue)
{
    case <= 0:
        Console.WriteLine("Less than or equal to 0");
        break;
    case > 0 and <= 10:
        Console.WriteLine("More than 0 but less than or equal to 10");
        break;
    default:
        Console.WriteLine("More than 10");
        break;
}

Pretty tidy! But we can take it further with our switch expression :

var message = myValue switch
{
    <= 0 => "Less than or equal to 0",
    > 0 and <= 10 => "More than 0 but less than or equal to 10",
    _ => "More than 10"
};

Console.WriteLine(message);

Holy moly that’s tidy! And that’s relational pattern matching with C# 9!

Troubleshooting

If at any point you get the following errors :

The feature 'and pattern' is currently in Preview and *unsupported*. 
The feature 'relational pattern' is currently in Preview and *unsupported*. 

It means you are using a version of C# less than 9. Check out our quick guide on getting setup with using C# 9 and all it’s features here : https://dotnetcoretutorials.com/2020/08/07/getting-setup-with-c-9-preview/

ENJOY THIS POST?
Join over 3.000 subscribers who are receiving our weekly post digest, a roundup of this weeks blog posts.
We hate spam. Your email address will not be sold or shared with anyone else.

Getting Setup With C# 9

If you aren’t sure you are using C# 9 and/or you want to start using some of the new shiny features in the C# language, be sure to read our quick guide on getting setup with C# 9 and .NET 5. Any feature written about here is available in the latest C# 9 preview and is not a “theoretical” feature, it’s ready to go!

C# 9 Features

We are slowly working our way through all new C# 9 features, if you are interested in other new additions to the language, check out some of the posts below.

What Is Target Typing?

I’m going to be honest, before C# 9 where they talk about “Improved” Target Typing, I had never actually heard of the term before. But it’s actually very simple. It’s basically a way to say “given the context of what I’m doing, can we infer the type”. The use of the “var” keyword is an example of target typing. The use of var is actually a good example here because it’s actually almost the reverse of the improvements to target typing in C# 9, but let’s jump into those.

Target Typed New Expressions

Target Typed New Expressions is basically just a fancy way of saying that we don’t have to say the type after the new() expression…. That probably doesn’t make it anymore clearer, but in here’s a sample piece of code :

class Person
{
    public string FirstName { get; set; }
}

class MyClass
{
    void MyMethod()
    {
        Person person = new Person();
    }
}

Now in C# 9, you can do :

class Person
{
    public string FirstName { get; set; }
}

class MyClass
{
    void MyMethod()
    {
        Person person = new(); //<-- This!
    }
}

Since you’ve already defined the type for your variable, it can infer that when you call new() without a type, you’re trying to new up the exact type.

It even works with constructors with parameters!

class Person
{
    public Person(string firstName)
    {
        this.FirstName = firstName;
    }
    public string FirstName { get; set; }
}

class MyClass
{
    void MyMethod()
    {
        Person person = new("John");
    }
}

Unfortunately there is a really big caveat. Constructors (I feel anyway) have almost become the minority in my code, especially because of the heavy use of Dependency Injection in todays coding. So typically when I am newing up an object, I am setting properties at the same time like so :

Person person = new Person
{
    FirstName = "John"
};

But of course this doesn’t work :

Person person = new
{
    FirstName = "John"
};

Because writing new like that without a type, then straight into curly’s tells C# you are creating an “anonymous” object. Interestingly in the current C#9 Preview with Visual Studio, you can do the “double up” approach like so :

Person person = new()
{
    FirstName = "test"
};

Intellisense *does not* work right now when doing this (e.g. It won’t auto complete “FirstName” for me), but once it’s written, it will compile. I chuckle because at the moment if you tried this in C#8, it would gray out the () because they aren’t needed. And typically in a code review someone will add a nit that “Hey, you don’t need the parenthesis”, but now I guess there is a reason to have them!

Another huge caveat is the use of the “var” keyword. For obvious reasons, this doesn’t work :

var person = new();

As I mentioned earlier, this is almost like using var, but coming from the other side. If your code doesn’t use the var keyword that often, then this may be of use, but for me, I almost exclusively use var these days when newing up objects, so it’s not going to be a common tool in my arsenal.

That being said, cases where you cannot use var (Class level properties, returning new objects from a method etc), this fits perfectly.

Target Typing Conditional Operators

What we are about to talk about *should* work in C# 9, but under the current preview doesn’t. Apparently in a previous preview version it did but.. Right now it’s a bit busted. Frustrating! But we’ll still talk about it anyway because it’s under the umbrella of “Target Typing”.

Target typed conditional operators are basically the compiler looking for ways to make your null-coalescing operator (??) work. For example the following code :

class Program
{
    static void Main(string[] args)
    {
        Cat cat = null;
        Dog dog = new Dog();
        IAnimal animal = cat ?? dog;
    }
}

interface IAnimal
{

}

class Dog : IAnimal
{

}

class Cat : IAnimal
{

}

Notice how Cat and Dog both inherit from the same interface (IAnimal), and we are checking if Cat is null, then return Dog into a variable with a type of “IAnimal”. Right now in C# 8 (And.. C# 9 Preview 7), this doesn’t work and the compiler complains. But it makes total sense for this code to work because the developers intent is clear, and it doesn’t break any existing paradigms with the language.

For example doing this does work in all versions of C#:

Cat cat = null;
Dog dog = new Dog();
IAnimal animal = cat;
if (animal == null)
    animal = dog;

So it’s really just allowing the ?? operator to do this for us.

Another example not using classes would be something such as :

Dog dog = null;
int? myVariable = dog == null ? 0 : null;

This fails because there is no conversion between 0 and null. But we are casting it back to a nullable integer so clearly there is a common base here and the developers intent is pretty clear. In fact this does work if you do something such as :

Dog dog = null;
int? myVariable = dog == null ? 0 : default(int?);

Or even

Dog dog = null;
int? myVariable = dog == null ? (int?)0 : null;

So again, this is all about wrapping some sugar around this to do things we already do and make developers lives easier.

Again I must stress that the improved target typing for conditional operators are not quite in the preview yet, but should be there very soon.

Troubleshooting

Just a quick note for this feature. If you see :

The feature 'target-typed object creation' is currently in Preview and *unsupported*.

Then you *must* have the latest preview SDK installed and your csproj file updated to handle C# 9. More info here : https://dotnetcoretutorials.com/2020/08/07/getting-setup-with-c-9-preview/

 

ENJOY THIS POST?
Join over 3.000 subscribers who are receiving our weekly post digest, a roundup of this weeks blog posts.
We hate spam. Your email address will not be sold or shared with anyone else.

As .NET 5 is rolled out, so too is another version of C#, this time being C# 9. I’m actually pretty excited for some of the features that, fingers crossed, should make it into the final release. But as always, I don’t want to wait till the official release, and instead jump in early and play with all the new shiny things.

So in actual fact, getting setup with C# 9 is basically the same as getting setup with .NET Preview 5. And luckily for you, we have a shiny guide right here : https://dotnetcoretutorials.com/2020/05/22/getting-started-with-net-5-and-the-msbuild-net-5-cliffnotes/. But for the cliffnotes of that post :

  • Download and install the latest .NET 5 SDK from here : https://dotnet.microsoft.com/download/dotnet/5.0
  • Ensure that your version of Visual Studio 2019 is atleast 16.7 by clicking Help => Check For Updates inside Visual Studio. If in doubt, update.
  • Go Tools => Options inside Visual Studio, then select “Preview Features” and tick the box that says “Use previews of the .NET Core SDK”. Then restart Visual Studio.

Once the .NET 5 Preview SDK is installed and setup, then the only thing you need to do is edit your .csproj file and add a lang element like so :

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net5.0</TargetFramework>
    <LangVersion>9.0</LangVersion>
  </PropertyGroup>
</Project>

Troubleshooting

If you’ve done all of that and you get either of these errors :

The reference assemblies for .NETFramework,Version=v5.0 were not found. 

Or

Invalid option '9.0' for /langversion. Use '/langversion:?' to list supported values.

Then here’s your quick and easy troubleshooting list :

  • Are you sure you’ve got the latest .NET 5 SDK installed? Remember it’s the SDK, not the runtime, and it’s .NET 5.
  • Are you sure you’re Visual Studio is up to date? Even if you have the SDK installed, Visual Studio plays by it’s own rules and needs to be updated.
  • Are you using Visual Studio 2019? Any version lower will not work.
  • Are you sure you enabled Preview SDKs? Remember Tools => Options, then “Preview Feature”

Keeping Up To Date

A new preview version of .NET 5/C#9 comes out every few months. So if you’re reading about a new C# 9 or .NET 5 feature that someone is using but you can’t seem to get it to work, then always head back to https://dotnet.microsoft.com/download/dotnet/5.0 and download the latest preview version and install. Similar for Visual Studio, while typically less of an issue, try and keep it up to date as so often latest features not working are simply that I’m on a version that was perfectly fine a month ago, but is now out of date.

C# 9 Features

We are slowly working our way through all new C# 9 features, if you are interested in other new additions to the language, check out some of the posts below.

All of these will be covered in detail coming soon!

ENJOY THIS POST?
Join over 3.000 subscribers who are receiving our weekly post digest, a roundup of this weeks blog posts.
We hate spam. Your email address will not be sold or shared with anyone else.

If you’ve ever taken part in an AI challenge or contest over the years, you’ve probably had to work out a path finding algorithm along the way. I remember many moons ago, as part of the Google AI Challenge (ended a few years ago which is a real shame), I actually swapped my solution to use Java just so I could use an A* search algorithm that I found on the internet. C# can be a bit weird in that for business applications, you can find a million examples on how to talk to Sharepoint, but when it comes to AI, Machine Learning, or even just data structures and algorithms in general, it can be a bit bare. So I thought I would quickly whip up a post on a dead simple implementation of the A* path finding algorithm in C#.

What Is A* Search?

It probably makes sense to rewind a little bit and ask, what exactly is the A* algorithm? A* Search is a path finding algorithm. Or in simpler terms, given a map, starting at one location, what is the most efficient way of getting to a second location, walking around walls, obstacles and ignoring dead ends.

For example if we had a map that looked like so :

A           |
--| |-------|
            | 
   |-----|  | 
   |     |  |
---|     |B |

How do we get from point A to point B? Obviously we can’t walk through walls, but a human can easily trace a nice easy path with your eye, so why can’t a computer do it? Well it can using A*!

The main thing about using A* Search is that it’s cost based. That is that it tries to find the optimal path to take, even if that may take additional processing.

Wikipedia will obviously explain a heck of a lot better than me! https://en.wikipedia.org/wiki/A*_search_algorithm

Jumping into the Code

While I’ll walk through the code in this post, you can get the entire gist here : https://gist.github.com/DotNetCoreTutorials/08b0210616769e81034f53a6a420a6d9 which has a complete working example. But I do recommend following along in this post anyway as I try and explain it as we go so it may be a bit easier to digest.

The first thing we want to do is create a “Tile” object. This essentially represents a square on a grid.

class Tile
{
	public int X { get; set; }
	public int Y { get; set; }
	public int Cost { get; set; }
	public int Distance { get; set; }
	public int CostDistance => Cost + Distance;
	public Tile Parent { get; set; }

	//The distance is essentially the estimated distance, ignoring walls to our target. 
	//So how many tiles left and right, up and down, ignoring walls, to get there. 
	public void SetDistance(int targetX, int targetY)
	{
		this.Distance = Math.Abs(targetX - X) + Math.Abs(targetY - Y);
	}
}

To walk through the properties for this object :

  • X,Y are locations on a grid that we will use.
  • Cost is how many tiles we had to traverse to reach here. So for example if this is right next to the starting tile, it would be a cost of “1”. If it was two tiles to the right, it would be a cost of 2 etc.
  • Distance is the distance to our destination (e.g. the target tile). This is worked out using the SetDistance method where it’s basically, ignoring all walls, how many tiles left/right and up/down would it take to reach our goal.
  • CostDistance is essentially the Cost + the Distance. It’s useful later on because given a set of tiles, we work out which one to “work on” by ordering them by the CostDistance. e.g. How many tiles we’ve moved so far + how many tiles we think it will probably take to reach our goal. This is important!
  • Parent is just the tile we came from to get here.

Inside our main method (We are doing this inside a console app but you are welcome to edit this to your needs). We set up some basic code :

static void Main(string[] args)
{
	List<string> map = new List<string>
	{
		"A          ",
		"--| |------",
		"           ",
		"   |-----| ",
		"   |     | ",
		"---|     |B"
	};

	var start = new Tile();
	start.Y = map.FindIndex(x => x.Contains("A"));
	start.X = map[start.Y].IndexOf("A");

	var finish = new Tile();
	finish.Y = map.FindIndex(x => x.Contains("B"));
	finish.X = map[finish.Y].IndexOf("B");
	
	start.SetDistance(finish.X, finish.Y);

	var activeTiles = new List<Tile>();
	activeTiles.Add(start);
	var visitedTiles = new List<Tile>();
}
  • Set up the “map” which is essentially a grid. In our example we use a list of strings but this grid or map can be made up any way you like.
  • We record the “Start” tile, e.g. where we start,
  • We record the “End” tile, e.g. where we finish
  • And we create a list of “ActiveTiles” and “VisitedTiles”. We populate the “ActiveTiles” with our start block. These are tiles that we will essentially work on.

The next thing we need to do is a little helper method. What this does is that, given a particular tile (and the target tile), we want to get all the tiles around itself. It’s used to find the next set of tiles we can try and walk on. We actually don’t do many checks inside of here (For example, if it’s even optimal to walk to the tile beside us, we may be walking the wrong way!), but we do check whether it’s a valid tile to walk on.

The code looks like so :

private static List<Tile> GetWalkableTiles(List<string> map, Tile currentTile, Tile targetTile)
{
	var possibleTiles = new List<Tile>()
	{
		new Tile { X = currentTile.X, Y = currentTile.Y - 1, Parent = currentTile, Cost = currentTile.Cost + 1 },
		new Tile { X = currentTile.X, Y = currentTile.Y + 1, Parent = currentTile, Cost = currentTile.Cost + 1},
		new Tile { X = currentTile.X - 1, Y = currentTile.Y, Parent = currentTile, Cost = currentTile.Cost + 1 },
		new Tile { X = currentTile.X + 1, Y = currentTile.Y, Parent = currentTile, Cost = currentTile.Cost + 1 },
	};

	possibleTiles.ForEach(tile => tile.SetDistance(targetTile.X, targetTile.Y));

	var maxX = map.First().Length - 1;
	var maxY = map.Count - 1;

	return possibleTiles
			.Where(tile => tile.X >= 0 && tile.X <= maxX)
			.Where(tile => tile.Y >= 0 && tile.Y <= maxY)
			.Where(tile => map[tile.Y][tile.X] == ' ' || map[tile.Y][tile.X] == 'B')
			.ToList();
}

So we generate the tile above, below, left and right of us. We set the distance value to the goal on each tile. Then we check whether the tile is within the bounds of our map (e.g. X is not less than 0). Finally, we ensure that the tile we want to walk to is either empty (e.g. No wall), or it’s actually our destination.

Also note that we set the “Cost” of the tile to be always +1 of the parent. This makes sense as whatever the cost of the parent was, one more step is always going to cost… one more. Kinda seems dumb to point it out but it is important!

Now we are into the meat and bones of this. Heading back to our Main method (I’ve commented where the generation of the Map was before), we are going to now loop through our tiles and actually start walking through the map!

static void Main(string[] args)
{
	//This is where we created the map from our previous step etc. 

	while(activeTiles.Any())
	{
		var checkTile = activeTiles.OrderBy(x => x.CostDistance).First();

		if(checkTile.X == finish.X && checkTile.Y == finish.Y)
		{
			Console.Log(We are at the destination!);
			//We can actually loop through the parents of each tile to find our exact path which we will show shortly. 
			return;
		}

		visitedTiles.Add(checkTile);
		activeTiles.Remove(checkTile);

		var walkableTiles = GetWalkableTiles(map, checkTile, finish);

		foreach(var walkableTile in walkableTiles)
		{
			//We have already visited this tile so we don't need to do so again!
			if (visitedTiles.Any(x => x.X == walkableTile.X && x.Y == walkableTile.Y))
				continue;

			//It's already in the active list, but that's OK, maybe this new tile has a better value (e.g. We might zigzag earlier but this is now straighter). 
			if(activeTiles.Any(x => x.X == walkableTile.X && x.Y == walkableTile.Y))
			{
				var existingTile = activeTiles.First(x => x.X == walkableTile.X && x.Y == walkableTile.Y);
				if(existingTile.CostDistance > checkTile.CostDistance)
				{
					activeTiles.Remove(existingTile);
					activeTiles.Add(walkableTile);
				}
			}else
			{
				//We've never seen this tile before so add it to the list. 
				activeTiles.Add(walkableTile);
			}
		}
	}

	Console.WriteLine("No Path Found!");
}

So how does this work?

  • First we keep looping until we have no more “active” tiles, that is, there’s basically no where we haven’t walked. If we break this loop, it means we couldn’t find any way to reach our goal (e.g. walls in the way). This is important so we don’t end up in an infinite loop.
  • Next we take a tile off our list. Note that it’s not the first tile, nor the last tile. It’s the tile with the lowest current CostDistance. This ensures that we are always working on the most cost effective path at that very moment. It also ensures that should we come across a tile that is in our VisitedList, we can be sure that the cost of that tile in the VisitedList is going to be lower than whatever we currently have (Because the cost is only going to go up each loop!).
  • If the tile we pull out matches our finish tile, then boom! We are done! I’ll add some more code in here shortly to show how to print out our entire path (Or you can check the Gist!)
  • We remove our tile from the ActiveList, and add it to the VisitedList, as we are working on it now and anyone else that comes to this tile, should just know we’ve taken care of it.
  • Next we get all the tiles adjacent to the current tile using our GetWalkableTiles method. Then we loop through them.
  • If the walkable tile has already been visited in the past, then just ignore it.
  • If the walkable tile is in the active tiles list, then that’s cool! But check that what we have now is not actually a better way to get to the same tile. In most cases this is just because of a small zigzag instead of going directly there.
  • If we’ve never seen the tile before, then add it to the active tiles list.

And that’s it! We repeat this over and over and because we are pulling the tile with the lowest cost each time and walking from it, we can be sure that whenever we find a result, we don’t have to keep processing!

Now the code I used to output a nice way of looking at the path was like so :

if(checkTile.X == finish.X && checkTile.Y == finish.Y)
{
	//We found the destination and we can be sure (Because the the OrderBy above)
	//That it's the most low cost option. 
	var tile = checkTile;
	Console.WriteLine("Retracing steps backwards...");
	while(true)
	{
		Console.WriteLine($"{tile.X} : {tile.Y}");
		if(map[tile.Y][tile.X] == ' ')
		{
			var newMapRow = map[tile.Y].ToCharArray();
			newMapRow[tile.X] = '*';
			map[tile.Y] = new string(newMapRow);
		}
		tile = tile.Parent;
		if(tile == null)
		{
			Console.WriteLine("Map looks like :");
			map.ForEach(x => Console.WriteLine(x));
			Console.WriteLine("Done!");
			return;
		}
	}
}

Really all we are doing here is looping through each tile, and traversing to their parent. While doing so we are adding a * on the map to indicate we walked there, and also outputting the co-ordinates.

End Result

What does the end result output?

Retracing steps backwards...
10 : 5
10 : 4
10 : 3
10 : 2
9 : 2
8 : 2
7 : 2
6 : 2
5 : 2
4 : 2
3 : 2
3 : 1
3 : 0
2 : 0
1 : 0
0 : 0
Map looks like :
A***
--|*|------
   ********
   |-----|*
   |     |*
---|     |B
Done!

Pretty damn cool!

Again if you are struggling to follow along, you can grab the entire gist as a single file from here : https://gist.github.com/DotNetCoreTutorials/08b0210616769e81034f53a6a420a6d9 . Feel free to modify for your needs!

ENJOY THIS POST?
Join over 3.000 subscribers who are receiving our weekly post digest, a roundup of this weeks blog posts.
We hate spam. Your email address will not be sold or shared with anyone else.

I recently got asked a pretty good question about EFCore (Although it does also apply in general to database concepts), and that was :

Should I use RowVersion or ConcurrencyToken for optimistic concurrency?

And the answer is “It depends” and even more specifically, “Do you know what the difference, or lack thereof, there is between the two?”

Let’s rewind a little bit and start with what exactly are Concurrency Tokens, then what is a RowVersion, then finally, how do they compare.

What Is A Concurrency Token?

A concurrency token is a value that will be “checked” every time an update occurs on a database record. By checked what I specifically mean is that the existing value will be used as part of a SQL WHERE statement, so that should it have changed from underneath you, the update will fail. This might occur if two users are trying to edit the same record at the same time.

Or in very crude lucidchart form :

When UserB is updating the same record as UserA, at worst he is overwriting details from UserA unwittingly, but even at best he is writing details to a record using knowledge from his read that may be outdated by the update from UserA.

A concurrency token fights this by simply checking that information contained in the original read, is the still there on the write. Let’s imagine that we have a database table called “User” that looks like so :

Id		int
FirstName	nvarchar(max)
LastName	nvarchar(max)
Version		int

Normally a SQL update statement without a concurrency token might look like so :

UPDATE User
SET FirstName = 'Wade'
WHERE Id = 1

But if we use the Version column as a concurrency token, it might instead look like :

UPDATE User
SET FirstName = 'Wade', Version = Version + 1
WHERE Id = 1 AND Version = 1

The Version value in our WHERE statement is the value we fetched when we read the data originally. This way, if someone has updated a record in the time it took us to read the data and then update it, the Version is not going to match and our Update statement will fail.

In Entity Framework/EF Core, we have two ways to say that a property is a ConcurrencyToken. If you prefer using DataAnnotations you can simply apply an attribute to your models.

[ConcurrencyCheck]
public int Version { get; set; }

Or if you prefer Fluent Configurations (Which you should!), then it’s just as easy

modelBuilder.Entity<People>()
	.Property(p => p.Version)
	.IsConcurrencyToken();

But There’s A Catch!

So that all sounds great! But there’s a catch, a small one, but one that can be quite annoying.

The problem is that short of some sort of database trigger (ugh!), or some sort of database auto increment field, it’s up to you, the developer, to ensure that you increment the version everytime you do an update. Now you can obviously write some EntityFramework extensions to get around this and auto increment things in C#, but it can complicated really fast.

And that’s where a RowVersion comes in.

What Is A RowVersion?

Let’s start in pure SQL Server terms what a RowVersion is. RowVersion (Also known as Timestamp, they are the same thing), is a SQL column type that uses auto generated binary numbers that are unique across that database, and stamped on records. Any time a record is inserted or updated on a table with a row version, a new unique number is generated (in binary format) and given to that record. Again, the RowVersions are unique across that entire database, not just the table.

Now in EntityFramework/EFCore it actually takes a somewhat different meaning because of what the SQL RowVersion is actually used to *achieve*.

Typically inside EF, when someone describes using a RowVersion, they are describing using a RowVersion/Timestamp column as a *ConcurrencyToken*. Now if you remember earlier the issue with just using a pure ConcurrencyToken was that we had to update/increment the value ourselves, but obviously if SQL Server is auto updating using RowVersion, then problem solved!

It actually gets more interesting if we take a look at how EFCore actually works out whether to use a RowVersion or not. The actual code is here : https://github.com/dotnet/efcore/blob/master/src/EFCore/Metadata/Builders/PropertyBuilder.cs#L152

public virtual PropertyBuilder IsRowVersion()
{
	Builder.ValueGenerated(ValueGenerated.OnAddOrUpdate, ConfigurationSource.Explicit);
	Builder.IsConcurrencyToken(true, ConfigurationSource.Explicit);

	return this;
}

Calling IsRowVersion() is actually shorthand for simply telling EFCore that the property is a ConcurrencyToken and it’s AutoGenerated. So in actual fact, if you added both of these configurations to a property manually, EF Core would actually treat it like a RowVersion even though you haven’t explicitly said it is.

We can see this by checking the code that asks if a column is a RowVersion here : https://github.com/dotnet/efcore/blob/master/src/EFCore.Relational/Metadata/IColumn.cs#L56

bool IsRowVersion => PropertyMappings.First().Property.IsConcurrencyToken
					&& PropertyMappings.First().Property.ValueGenerated == ValueGenerated.OnAddOrUpdate;

So all it actually does is interrogate whether the column is a concurrency token and auto generated. Easy!

I would note that if you actually had a column that you auto incremented some other way (DB Trigger for example), and was also a concurrency token.. I’m pretty sure EFCore would have issues actually handling this, but that’s for another day.

In EntityFramework you can setup a RowVersion on a property like so for DataAnnotations :

[TimeStamp]
public byte[] RowVersion{ get; set; }

And for Fluent Configurations:

modelBuilder.Entity<People>()
	.Property(p => p.RowVersion)
	.IsRowVersion();

Even though you specify that a column should be a RowVersion, the actual implementation of how that works (e.g. The datatype, specific settings on how that gets updated), is actually very dependent on the SQL Server (And SQL C# Adapter). Different databases can implement RowVersion how they like, but typically in SQL Server atleast, it’s a byte[] type.

Note that when using RowVersion with EntityFramework, there is nothing more you really need to do to get up and running. Anytime you update a record with a RowVersion property, it will automatically add that column to the WHERE statement giving you optimistic concurrency right out of the box.

So ConcurrencyToken vs RowVersion?

So if we go back to the original question of when you should use Concurrency Token vs when you should use a RowVersion. The answer is actually very simple. If you want to use a ConcurrencyToken as an auto incremented field, and you don’t actually care how it gets incremented or the data type, then use RowVersion. If you care about what the data type of your concurrency token should be, or you specifically want to control how and when it gets updated, then use Concurrency Token and manage the incrementing yourself.

What I’ve generally found is that when people have suggested to me to use Concurrency Token’s, typically what they actually mean is using RowVersion. Infact it’s probably easier to say that RowVersion (In the Entity Framework sense) is a *type* of Concurrency Token.

ENJOY THIS POST?
Join over 3.000 subscribers who are receiving our weekly post digest, a roundup of this weeks blog posts.
We hate spam. Your email address will not be sold or shared with anyone else.