C# 9 in-process Azure Functions
John Reilly
July 1, 2021
C9 has some amazing features. Azure Functions are have two modes: isolated and in-process. Whilst isolated supports .NET 5 (and hence C9), in-process supports .NET Core 3.1 (C8). This post shows how we can use C9 with in-process Azure Functions running on .NET Core 3.1.
Azure Functions: in-process and isolated
Historically .NET Azure Functions have been in-process. This changed with .NET 5 where a new model was introduced named "isolated". To quote from the roadmap:
> Running in an isolated process decouples .NET functions from the Azure Functions host—allowing us to more easily support new .NET versions and address pain points associated with sharing a single process.
However, the initial launch of isolated functions does not have the full level of functionality enjoyed by in-process functions. This will happen, according the roadmap:
> Long term, our vision is to have full feature parity out of process, bringing many of the features that are currently exclusive to the in-process model to the isolated model. We plan to begin delivering improvements to the isolated model after the .NET 6 general availability release.
In the future, in-process functions will be retired in favour of isolated functions. However, it will be .NET 7 (scheduled to ship in November 2022) before that takes place:
As the image taken from the roadmap shows, when .NET 5 shipped, it did not support in-process Azure Functions. When .NET 6 ships in November, it should.
In the meantime, we would like to use C9.
Setting up a C8 project
We're have the Azure Functions Core Tools installed, so let's create a new function project:
The above command scaffolds out a .NET Core 3.1 Azure function project which contains a single Azure function. The --worker-runtime dotnet parameter is what causes an in-process .NET Core 3.1 function being created. You should have a .csproj file that looks like this:
We're running with C8 and .NET Core 3.1 at this point. What does it take to get us to C9?
What does it take to get to C9?
There's a great post on Reddit addressing using C9 with .NET Core 3.1 which says:
> You can use 9.0, and VS even includes support for suggesting a language upgrade.
>
> However, there are three categories of features in C#:
>
> 1. features that are entirely part of the compiler. Those will work.
> 2. features that require BCL additions. Since you're on the older BCL, those will need to be backported. For example, to use init; and record, you can use https://github.com/manuelroemer/IsExternalInit.
> 3. features that require runtime additions. Those cannot be added at all. For example, default interface members in C8, and covariant return types in C9.
Of the above, 1 and 2 add a tremendous amount of value. The features of 3 are great, but more niche. Speaking personally, I care a great deal about Record types. So let's apply this.
Adding C9 to the in-process function
To get Cinto the mix, we want to make two changes:
- add a 9.0 to the element of our .csproj file
- add a package reference to the IsExternalInit
The applied changes look like this:
If we used dotnet add package IsExternalInit, we might be using a different syntax in the .csproj. Be not afeard - that won't affect usage.
Making a C9 program
Now we can theoretically use C9.... Let's use C9. We'll tweak our HelloRecord.cs file, add in a simple record named MessageRecord and tweak the Run method to use it:
If we kick off our function with func start:
We can see we can compile, and output is as we might expect and hope. Likewise if we try and debug in VS Code, we can:
Best before...
So, we've now a way to use C9 (or most of it) with in-process .NET Core 3.1 apps. This should serve until .NET 6 ships in November 2021 and we're able to use C9 by default.
Discussion in the ATmosphere