Reading through the new features introduced in .NET 6, something that I repeatedly glossed over was the new MaxBy and MinBy LINQ statements. I kept glossing over them because at first look, it doesn’t seem to be anything new but in reality.. They are actually extremely helpful!

Getting Setup With .NET 6 Preview

At the time of writing, .NET 6 is in preview, and is not currently available in general release. That doesn’t mean it’s hard to set up, it just means that generally you’re not going to have it already installed on your machine if you haven’t already been playing with some of the latest fandangle features.

To get set up using .NET 6, you can go and read out guide here : https://dotnetcoretutorials.com/2021/03/13/getting-setup-with-net-6-preview/

Remember, this feature is *only* available in .NET 6. Not .NET 5, not .NET Core 3.1, or any other version you can think of. 6.

Max/MinBy vs Max/Min

So it’s actually brutally simple.

I can run a simple Max statement like so across a list of numeric values :

List<int> myList = new List<int> { 1, 2, 3 };
myList.Max(); //Returns 3

Seems simple, and we output the maximum numeric value.

If I have a complex type, like a class of “Person”, then you might think I need to do something rinky dink to find the max age of those people (as shown below). I actually at first thought this was what “MaxBy” was all about. Like “Max By Property XYZ”. But infact, the regular max statement works just fine like so :

List<Person> people = new List<Person>
{
    new Person
    {
        Name = "John Smith", 
        Age = 20
    }, 
    new Person
    {
        Name = "Jane Smith", 
        Age = 30
    }
};

Console.Write(people.Max(x => x.Age)); //Outputs 30

class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}

So what happens if we change that same statement to MaxBy?

List<Person> people = new List<Person>
{
    new Person
    {
        Name = "John Smith", 
        Age = 20
    }, 
    new Person
    {
        Name = "Jane Smith", 
        Age = 30
    }
};

Console.Write(people.MaxBy(x => x.Age)); //Outputs Person (Jane Smith)

Instead of outputting the max property value, we output the entire object that has the max value. So instead of returning “30” we return the entire Person object of Jane Smith.

Another way to look at it, is it’s more or less a shortening of the following statement :

people.OrderByDescending(x => x.Age).First(); //Outputs Person (Jane Smith)

This is the crux of MaxBy/MinBy and is a pretty nifty addition that I totally didn’t know I needed until now.

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.

For a long time now (Actually, almost since forever), we have been stuck with the DateTime type in .NET. By “stuck”, it hasn’t been like it’s always been a problem, and you can go months, if not years of using DateTime without any issue. But every now and again, those gremlins creep in when trying to use DateTime as either only a Date, or only a Time.

In the case of using only a Date, this is extremely common when storing things such as birthdays, anniversary dates, or really any calendar date that doesn’t have a specific time associated with it. But in .NET, you were forced to use a DateTime object, often with a time portion of midnight. While this worked, often the time portion would get in the way when comparing dates or wanting to manipulate a date without really worrying about the time. It was especially weird when working with a SQL database that has the concept of a “date” type (with no time), but when loading the data into C#, you had to deal with a DateTime.

If you only wanted to store a time, then you were really in trouble. Imagine wanting to set an alarm for a recurring time, every day. What type would you use? Your best bet was of course to use the “TimeSpan” type, but this was actually designed to store elapsed time, not a particular clock time. As an example, a TimeSpan can have a value of 25 hours because it’s a measure of time, not the actual time of day. Another problem was time wrapping. If something started at 11PM, and went for 2 hours. How would you know to “wrap” the end time around to be 1AM? This often meant using some sort of rinky dink DateTime object that now ignored the date portion, ugh.

And that’s why .NET 6 has introduced DateOnly and TimeOnly!

Getting Setup With .NET 6 Preview

At the time of writing, .NET 6 is in preview, and is not currently available in general release. That doesn’t mean it’s hard to set up, it just means that generally you’re not going to have it already installed on your machine if you haven’t already been playing with some of the latest fandangle features.

To get set up using .NET 6, you can go and read out guide here : https://dotnetcoretutorials.com/2021/03/13/getting-setup-with-net-6-preview/

Remember, this feature is *only* available in .NET 6. Not .NET 5, not .NET Core 3.1, or any other version you can think of. 6.

Using DateOnly

Using DateOnly is actually pretty easy. I mean.. Check the following code out :

DateOnly date = DateOnly.MinValue;
Console.WriteLine(date); //Outputs 01/01/0001 (With no Time)

An important distinction to make is that a DateOnly object never has a Timezone component. After all, if your birthday is on the 10th of May, it’s the 10th of May no matter where in the world you are. While this might seem insignificant, there are things like DateTimeKind and DateTimeOffset dedicated to solving timezone problems, of which, when we are using DateOnly we are uninterested in.

The thing to note here is that even if you didn’t intend to deal with timezones previously, you might have been conned into it. For example :

DateTime date = DateTime.Now;
Console.WriteLine(date.Kind); //Outputs "Local"

The “Kind” of our DateTime object is “Local”. While this may seem insignificant, it could actually become very painful when converting the DateTime, or even serializing it.

All in all, DateOnly gives us a way to give a very precise meaning to a date, without being confused about timezones or time itself.

Using TimeOnly

While DateOnly had fairly simple examples, TimeOnly actually has some nifty features that suddenly make this all the more a needed feature.

But first, a simple example :

TimeOnly time = TimeOnly.MinValue;
Console.WriteLine(time); //Outputs 12:00 AM

Nice and simple right! What about if we use our example from above, and we check how time is wrapped. For example :

TimeOnly startTime = TimeOnly.Parse("11:00 PM");
var hoursWorked = 2;
var endTime = startTime.AddHours(hoursWorked);
Console.WriteLine(endTime); //Outputs 1:00 AM

As we can see, we no longer have to account for “overflows” like we would when using a TimeSpan object.

Another really cool feature is the “IsBetween” method on a TimeOnly object. As an example :

TimeOnly startTime = TimeOnly.Parse("11:00 PM");
var hoursWorked = 2;
var endTime = startTime.AddHours(hoursWorked);

var isBetween = TimeOnly.Parse("12:00 AM").IsBetween(startTime, endTime); //Returns true. 

This is actually very very significant. In a recent project I was working on, we needed to send emails only in a select few hours in the evening. To check whether the current time was between two other datetimes is actually significantly harder than you may think. What would often happen is that we would have to take the time, and assign it to an arbitrary date (For example, 01/01/0001), and then do the comparison. But then the midnight wrap around would always choke us in the end.

In my view DateOnly and TimeOnly are significant additions to .NET, and ones that I think will be used right from release. On top of this, it doesn’t mean DateTime will be a relic of the past, instead, DateTime can be used only when you want to point to a specific date and time past, present or future, and not one or the other.

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.

A fairly common interview question I have for any C#/.NET Developer revolves around the difference between First and FirstOrDefault LINQ statements. There’s a general flow to the questions that basically go something like :

What’s the difference between First and FirstOrDefault

When answered, I follow it up with :

So when FirstOrDefault can’t find a value, what does it return?

Commonly, I actually have people say things like it always returns null. Which is incorrect, it returns the “default” value for that type. Essentially, doing something like default(T). But if they get this part right, then I follow it up with things like

So what is the default value then? What would be the default value for a type of integer?

The correct answer to the above is 0. I’m not sure if it’s a difficult set of questions or not (Certainly many get it wrong), but it’s definitely something you will run into a lot in your career if you develop in C# for any length of time.

One of the main reasons I ask this question, is often I see code across all levels that works something like this :

var hayStack = new List { 1, 2, 2 };
var needle = 3;

var foundValue = hayStack.FirstOrDefault(x => x == needle);
if(foundValue == 0)
{
    Console.WriteLine("We couldn't find the value");
}

This works of course, but what if needle actually is the number 0? You have to do a bit of a dance to work out was it truly not found, or is the value you are looking for actually the default value anyway. You have a couple of options :

  • Run a LINQ Any statement beforehand to ensure that your list does indeed contain the item
  • Cast the list to a nullable variant of the type if not already, so you can ensure you get null back if not found
  • Use First instead of FirstOrDefault and catch the exception

You might think this is only really an issue in edge cases where you are using primitives that typically aren’t nullable, but with the introduction of Nullable Reference types in C# 8, this is actually going to become a very common scenario.

.NET 6 introduces the concept of being able to pass in what the default value should be, should the item not be found. So for example, this code is now valid in .NET 6.

var hayStack = new List<int?> { 1, 2, 2 };
var needle = 3;

var foundValue = hayStack.FirstOrDefault(x => x == needle, -1);
if(foundValue == -1)
{
    Console.WriteLine("We couldn't find the value");
}

But… Hold on. All we are doing here is saying instead of returning 0, return -1. Oof!

As it turns out, the IEnumerable method still must return a valid integer. And because our type is not nullable, even with this extension method, we can’t force it to return null. This goes for FirstOrDefault, SingleOrDefault and LastOrDefault.

The reason for this article I guess is to first and foremost to introduce the new extension, but also secondly to say, it doesn’t quite solve the problem that I thought it would at first look. You still must return a valid type. It doesn’t make it as useful as I first thought, but at the very least, it may help in some very edge scenarios, for example upserting values.

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.

In a previous post, we talked about the coming ability to use global using statements in C# 10. The main benefit being that you were now able to avoid the clutter of declaring namespaces over and over (Things like using System etc) in every single file. I personally think it’s a great feature!

So it only makes sense that when you create a new .NET 6 project, that global usings are implemented right off the bat. After all, if you create a new web project, there are many many files auto generated as part of the template that will call upon things like System or System.IO, and it makes sense to just use GlobalUsings straight away from the start right?

Well… .NET 6 have solved the problem in a different way. With Implicit Using statements, your code will have almost invisible using statements declared globally! Let’s take a look at this new feature, and how it works.

Getting Setup With .NET 6 Preview

At the time of writing, .NET 6 is in preview, and is not currently available in general release. That doesn’t mean it’s hard to set up, it just means that generally you’re not going to have it already installed on your machine if you haven’t already been playing with some of the latest fandangle features.

To get set up using .NET 6, you can go and read out guide here : https://dotnetcoretutorials.com/2021/03/13/getting-setup-with-net-6-preview/

Remember, this feature is *only* available in .NET 6. Not .NET 5, not .NET Core 3.1, or any other version you can think of. 6.

Implicit Global Usings

Implicit Global Usings are actually a hidden auto generated file, inside your obj folder, that declares global using statements behind the scenes. Again, this is only the case for .NET 6 and C# 10. In my case, if I go to my project folder then go obj/Debug/net6.0, I will find a file titled “RandomNumbers.ImplicitNamespaceImports.cs”.

Opening this file, I can see it contains the following :

global using global::System;
global using global::System.Collections.Generic;
global using global::System.IO;
global using global::System.Linq;
global using global::System.Net.Http;
global using global::System.Threading;
global using global::System.Threading.Tasks;

Note the fact this is an auto generated file, and we can’t actually edit it here. But we can see that it declares a whole heap of global using statements for us.

The project I am demoing this from is actually a console application, but each main project SDK type has their own global imports.

Console/Library

System
System.Collections.Generic
System.IO
System.Linq
System.Net.Http
System.Threading
System.Threading.Tasks

Web

In addition to the console/library namespaces :

System.Net.Http.Json
Microsoft.AspNetCore.Builder
Microsoft.AspNetCore.Hosting
Microsoft.AspNetCore.Http
Microsoft.AspNetCore.Routing
Microsoft.Extensions.Configuration
Microsoft.Extensions.DependencyInjection
Microsoft.Extensions.Hosting
Microsoft.Extensions.Logging

Worker

In addition to the console/library namespaces :

Microsoft.Extensions.Configuration
Microsoft.Extensions.DependencyInjection
Microsoft.Extensions.Hosting
Microsoft.Extensions.Logging

Of course, if you are unsure, you can always quickly create a project of a certain type and check the obj folder for what’s inside.

If we try and import a namespace that previously appeared in our implicit global usings, we will get the usual warning.

Opting Out

As previously mentioned, if you are using .NET 6 and C# 10 (Which in a years time, the majority will be), then this feature is turned on by default. I have my own thoughts on that, but what if you want to turn this off? This might be especially common when an automatically imported namespace has a type that conflicts with a type you yourself are wanting to declare. Or what if you just don’t like the hidden magic full stop?

The only way to turn off implicit using statements completely is to add the following line to your .csproj file :

<PropertyGroup>
  <OutputType>Exe</OutputType>
  <TargetFramework>net6.0</TargetFramework>
  <LangVersion>preview</LangVersion>
  <DisableImplicitNamespaceImports>true</DisableImplicitNamespaceImports>
</PropertyGroup>

This turns off all implicit imports. However, there is also another option to selectively remove (and add) implicit namespaces like so :

<ItemGroup>
  <Import Remove="System.Threading" />
  <Import Include="Microsoft.Extensions.Logging" />
</ItemGroup>

Here we are removing System.Threading and adding Microsoft.Extensions.Logging to the global implicit using imports.

This can also be used as an alternative to using something like a GlobalUsings.cs file in your project of course, but it is a somewhat “hidden” feature.

Is This A Good Feature? / My Thoughts

I rarely comment on new features being good or bad. Mostly because I presume that people much smarter than me know what they are doing, and I’ll get used to it. I’m sure when things like generics, lambdas, async/await got introduced, I would have been saying “I don’t get this”.

On the surface, I like the idea of project types having some sort of implicit namespace. Even imports that I thought were kinda dumb to be global such as “System.Threading.Tasks”, I soon realized are needed in every single file if you are using async/await since your methods must return a type of Task.

That being said, I don’t like the “hidden”-ness of everything. I’m almost certain that stackoverflow will be overwhelmed with people asking why their compiler is saying that System previously appeared in the namespace when it clearly didn’t. It’s not exactly intuitive to go into the obj folder and check what’s in there. In fact, I can’t think of a time I have in the past 15 years. Remember, if you upgrade an existing .NET 5 solution to .NET 6, you will automatically be opted in.

I feel like a simpler idea would have been to edit the Visual Studio/Command Line templates that when you create a new web project, it automatically creates a GlobalUsings.cs file in the root of the project with the covered implicit namespaces already in there. To me, that would be a heck of a lot more visible, and wouldn’t lead to so much confusion over where these hidden imports were coming from.

That being said, maybe in a years time we just get used to it and it’s just “part of .NET” like so many other things. What’s your thoughts?

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.

For a long time now, I’ve been searching for a middle ground when it comes to Optical Character Recognition/OCR in .NET/C#. You might have heard of a little C++ library called “Tesseract” which many have tried to write wrappers around or interop in their C# code. I myself have followed tutorials and guides on how to do this and it’s always ended in pain. Most notably, when you are working with C++ libraries in C#, you have to be extremely careful about how memory is allocated otherwise there is a sure fire chance you’re going to end up with a memory leak somewhere along the way. Almost without fail when I’ve tried to use Tesseract in C++, I’ve ended up leaking memory all over the place and having my screen turn into a jigsaw requiring a PC restart.

The alternative has always been “enterprise” type OCR libraries with their hidden pricing that they then hoist on you at the last minute (I really have a distaste for these sorts of tactics if I’m being honest), and even then, they usually have some sort of limited feature set but you pay for it anyway just so you don’t end up losing sleep over memory issues.

Well, then in comes IronOCR. An OCR library that takes the headaches out of C++ interoperability, but with upfront (and very very reasonable) pricing. I’ve been playing around with this little OCR library for some time now and I’ve got to say, the ease in which this thing gets up and running is really a dream. Let’s get started!

What We Are Looking For In An OCR Library?

Before we jump to deep into the code, let me map out my thought process of what I wanted to get out of any OCR or computer vision library.

  • I know that there are API services out there that do this (For example for Azure OCR, there is Azure Cognitive Services which is essentially a computer vision API), but I wanted to make sure that I could run this without making API calls, and without having to pay more as I scale up. IronOCR is a one time fee and that’s it.
  • Support multiple languages, many libraries I looked at supported English only.
  • Is there some level of “cleanup” smarts there. If the scanned document or image is a bit scratchy, does the library come with a way to clean things up?
  • Does this work for both printed and handwritten text? This is more a nice to have, but it’s also a huge feature to have!
  • Can I use this in the cloud (Specifically, will this work in Azure)? Usually this means no “installs” that need to be made because I may not be using a VM at all and instead be entirely serverless.

IronOCR ticks all of these boxes, but let’s take a dive into how it might look in code.

Simple OCR Example

Let’s start off with something really easy. I took this screenshot from the Google Books page on Frankenstein by Mary Shelly.

I then took my C#/.NET Console Application, and ran the following in the nuget package manager to install IronOCR

Install-Package IronOcr

And then onto the code. I literally OCR’d this image to extract text, including line breaks and everything, using 4 lines of code.

var ocr = new IronTesseract();
using (var Input = new OcrInput("Frankenstein.PNG"))
{
    var result = ocr.Read(Input);
    Console.WriteLine(result.Text);
}

And the output?

Frankenstein
Annotated for Scientists, Engineers, and Creators of All Kinds

By Mary Wollstonecraft Shelley - 2017

Literally perfect character recognition in just a few lines of code! When I said that using Iron was like computer vision on “easy mode”, I wasn’t lying.

Running IronOCR In An Azure Function

I know this might seem like an obvious thing to say, but there has been countless times where I’ve used libraries that require some sort of dedicated VM, either through an installation on the machine or because of licensing “per machine”. In this day and age, you should not be using any library that can’t work in any sort of serverless environment.

Since in most of my recent projects, we are using Azure Functions in a microservices architecture, let’s create a really simple function that can take a parameter of an image, OCR it, and return the text.

public static class OCRFunction
{
    public static HttpClient _httpClient = new HttpClient();

    [FunctionName("OCRFunction")]
    public static async Task<IActionResult> Run([HttpTrigger] HttpRequest req, ExecutionContext context)
    {
        var imageUrl = req.Query["image"];
        var imageStream = await _httpClient.GetStreamAsync(imageUrl);

        var ocr = new IronTesseract();
        using (var input = new OcrInput(imageStream))
        {
            var result = ocr.Read(input);
            return new OkObjectResult(result.Text);
        }
    }
}

Nice and simple! We take the query parameter of image, download it and OCR it immediately. The great thing about doing this directly inside an Azure Function is that immediately it can service different parts of our application in a microservice architecture without us having to copy and paste the code everywhere.

If we run the above code on our Frankenstein image above :

Super easy!

Another thing I want to point out about this approach is that if you’re currently paying for some service that charges a per OCR fee. Things can appear cheap but at scale, the monthly fee can quickly spiral out of control. Compare this to a one time fee with IronOCR, and you’re getting what is essentially a callable API all hosted in the Azure Cloud, without the ongoing costs.

Non-English Support

One thing I noticed with even the “Enterprise” level OCR libraries is that they often supported English only. It would come with some caveat like “But you can train it yourself on any language you want”. But that’s not really good enough when you are paying through the nose already.

However, IronOCR supports 125 languages currently, and you can add as many or as few as you like by simply installing the applicable Nuget language pack.

Iron Azure OCR Language Support

I was going to write more on the language availability in IronOCR, but it just works, and it’s all right there in a nifty package!

Cleaning Up Skewed Scans For OCR

The thing is, most of the time when you need OCR, it’s because of scanned documents. It’s very rare that you’re going to be using OCR for some pixel perfect screenshot from a website. Some OCR libraries shy away from this and sort of “avoid” the topic. IronOCR jumps right in to the deep end and gives us some out of the box options for fixing up poor scans.

Let’s use this as an example. A scanned page from the book Harry Potter.

There’s a bit of noise here but more importantly the text is heavily skewed. Two issues that are very very common when scanning in paper. If I run this through the OCR with no “fixes” in play, the only things I get back are :

Chapter Eight

The Deathday Party

That’s because the page is just too skewed and noisy to make out smaller characters correctly. All we have to do is add the ability to correct the skew of the scan. We can do that with a single line of code :

var ocr = new IronTesseract();
using (var input = new OcrInput("HarryPotter.png"))
{
    input.Deskew(); //Deskew the image
    var result = ocr.Read(input);
    Console.WriteLine(result.Text);
}

And instantly, with no other changes, we actually get things working 100% :

Chapter Eight

The Deathday Party

October arrived, spreading a damp chill over the grounds and into the castie. Madam Pomfrey, the nurse,
was kept busy by a sudden spate of colds among the staff and students. Her Pepperup potion worked
instantly, though it left the drinker smoking at the ears for several hours afterward. Ginny Weasley, who had
been looking pale, was bullied into taking some by Percy. The steam pouring from under her vivid hair gave
the impression that her whole head was on fire.

There are actually a tonne of other options for cleaning up images/documents too including :

  • DeNoise
  • Rotating images a set amount of degrees
  • Manually controlling contrast, greyscale, or simply turning the image black and white
  • Enchancing the solution/image sharpening
  • Erode and Dilate images
  • And even more like color inversion and deep cleaning of background noise.

The thing is, if I’m being honest. I did play around with these but I just never really needed to. De-skewing my documents generally was enough to get everything coming out literally character perfect, but it’s great that IronOCR give you even more knobs to play with to really fine tune your OCR requirements.

Advanced Text Results

It might surprise you that other OCR libraries I tested simply output text and that was it. There was no structure to it, and you essentially had to work out based on counting line breaks or whitespace how each paragraph worked.  IronOCR however not only can read text from your documents, but can work out the structure too!

For example, let’s use our Harry Potter image and instead use the following code :

var ocr = new IronTesseract();
using (var input = new OcrInput("HarryPotter.png"))
{
    input.Deskew();
    var result = ocr.Read(input);
    foreach(var paragraph in result.Paragraphs)
    {
        Console.WriteLine($"Paragraph : {paragraph.ParagraphNumber}");
        Console.WriteLine(paragraph.Text);
    }
}

Notice how instead of simply spitting out the text, I want to go paragraph by paragraph, to really understand the blocks of text I’m working with. And the result?

Paragraph : 1
Chapter Eight
Paragraph : 2
The Deathday Party
Paragraph : 3
October arrived, spreading a damp chill over the grounds and into the castie. Madam Pomfrey, the nurse,
was kept busy by a sudden spate of colds among the staff and students. Her Pepperup potion worked
instantly, though it left the drinker smoking at the ears for several hours afterward. Ginny Weasley, who had
been looking pale, was bullied into taking some by Percy. The steam pouring from under her vivid hair gave
the impression that her whole head was on fire.

Again, character perfect recognition split into the correct blocks. There’s a tonne of options around this too including reading line by line, or even reading only certain sections of the text a time by drawing a rectangle over the document. The latter is extremely helpful when you only need to use computer vision on a particular section of the document, and don’t need to worry about the rest.

Who Is This Library For?

As always, when I look at these sorts of libraries I try and think about who is this actually aimed at. Is it a hobbyist library, is it for enterprises only. And honestly, I struggle to place this one. Computer vision and optical character recognition is on the rise, and in the past couple of years, I’ve been asked about libraries to extract text from images more than all previous years combined. Azure obviously has their own offering, but it’s on a per call basis and over time, that all adds up. Add to the fact that you really don’t have control over how it’s trained and it’s not an easy sell.

However, going with IronOCR you have all of the control, with a single one time price tag. Add to the fact that you can download this library today and test to your hearts content before buying, it really makes it a no brainer if you are looking for any sort of text extraction/OCR features.


This is a sponsored post however all opinions are mine and mine alone. 

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 came across a feature that was introduced in C# 8. It actually threw me through a loop because I first saw it used in some code I was reviewing. In a moment of “confidently incorrect”, I told the developer that they definitely had to change the code because clearly it wouldn’t work (If it would compile at all).

Of course the egg on my face ensued with a quick link to the documentation and a comment along the lines of “Shouldn’t you have written this on that blog?”.

Oof.

The feature I am talking about is “Using Declarations”. I think every time I’ve seen this feature mentioned, I’ve thought it referred to your standard usings at the top of your .cs file. Something like this :

using System;
using System.IO;

But in fact, it revolves around the use of using to automatically call dispose on objects. The code in question that I was reviewing looked something like this (And note, this is a really dumb example so don’t read into the code too much).

static int countLines()
{
    using var fileStream = File.OpenRead("myfile.txt");
    using var fileReader = new StreamReader(fileStream);
    var lineCount = 1;
    var line = string.Empty;
    while((line = fileReader.ReadLine()) != null)
    {
        lineCount++;
    }
    return lineCount;
}

I mentioned to the developer…. “Well how does that using statement work?” I had just assumed it functioned much like how an If statement works without braces. e.g. It will only affect the next line like so :

if(condition)
    DoThis();
ButThisIsNotAffectedByCondition();

But in fact this is a new way to do using statements without braces.

Now, placing a using statement like so :

using var fileStream = File.OpenRead("myfile.txt");

Actually means that the object will be disposed when control leaves the scope. The scope could be a method, a loop, a conditional block etc. In general, if it leaves an end brace } somewhere, the object will be disposed.

Why is this handy? Well without it, you would have to have large amounts of indenting, and generally that indentation is for the entire method body anyway. For example :

static int countLines()
{
    using (var fileStream = File.OpenRead("myfile.txt"))
    {
        using (var fileReader = new StreamReader(fileStream))
        {
            var lineCount = 1;
            var line = string.Empty;
            while ((line = fileReader.ReadLine()) != null)
            {
                lineCount++;
            }
            return lineCount;
        }
    }
}

Much less prettier, and it doesn’t afford us anything extra (In this case) than just doing the using declaration.

The one thing you may still want to use braces for is if you wish to really control when something is disposed, even without code leaving the current control scope. But otherwise, Using Declarations are a very nifty addition that I wish I knew about sooner.

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 don’t often get hate comments/emails on this blog, but when I do, it’s about using statements not being available in my code snippets. For me, they just clutter everything up and rarely add much value or description to the code. What does several imports from system really add? Especially when everyone these days is using a fully featured IDE that has a one click “Add Using” option when you hover over anything.

Well with .NET 6 / C#10, I now have an excuse with the introduction of global using statements. Now you can place all of your common using statements (So mostly your System imports) into a single file that will automatically be available for use within that entire project. It’s a simple and nifty change!

Getting Setup With .NET 6 Preview

At the time of writing, .NET 6 is in preview, and is not currently available in general release. That doesn’t mean it’s hard to set up, it just means that generally you’re not going to have it already installed on your machine if you haven’t already been playing with some of the latest fandangle features.

To get set up using .NET 6, you can go and read out guide here : https://dotnetcoretutorials.com/2021/03/13/getting-setup-with-net-6-preview/

Remember, this feature is *only* available in .NET 6. Not .NET 5, not .NET Core 3.1, or any other version you can think of. 6.

Additionally, you may need to edit your .csproj file to allow for the preview LangVersion like so :

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

With all of that done, you should be ready to go!

Adding Global Usings

The syntax for adding global usings is actually fairly straight forward, simply add the keyword global before any using statement, anywhere, to make it global.

global using System;

Interestingly, there isn’t a well defined place to put these yet. You can put these in any file within your project and they are immediately global everywhere (As opposed to say the standard AssembleInfo.cs we used to have).

That being said, I’ve seen many people using a file in the root of your project called GlobalUsings.cs, with something akin to the following in there :

global using System;
global using System.Collections.Generic;
global using System.IO;
global using System.Linq;

//Maybe even a global using of another projects folder folder for instance. 
// global using MyModelsProject.Models;

Again, there is no limit to how many usings you can place in here, nor where this file lives, but it’s generally a good idea to keep this list pretty concise only to what you need. That being said, the only downside to overloading these global usings is that your intellisense will be astronomical in every file, whether that’s actually a bad thing I don’t know.

And that’s it!

I’ll note that one of the reasons I love C# and .NET right now is that every single change has a pretty lively discussion on Github. Global Usings is no different and the discussion is out in the public here : https://github.com/dotnet/csharplang/issues/3428. But what’s your thoughts? 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.

A friend recently asked if I could help build a very simple image manipulation console app.

In short, he needed to take a folder full of RAW image files, and generate a smaller thumbnail in various formats (PNG, JPEG etc). Seemed like straight forward and (wrongly), I just assumed that .NET could handle RAW image files natively by now. As it turns out, I was very wrong.

What Image Types Can .NET Handle Natively?

From my research, .NET out of the box (Including Framework, Core and .NET 5+) could handle the following image types :

  • BMP (Bitmap)
  • EMF (Enhanced Metadata File)
  • EXIF (Exchangeable Image File)
  • GIF (Needs no explanation!)
  • ICON (Windows Icon Image Format)
  • JPEG (Again, no explanation necessary)
  • PNG
  • TIFF
  • WMF (Windows Metadata File)

Notice no “RAW” there. Raw itself actually has a few extensions including .CR2 which is Canon’s proprietary format, along with .NEF, .ORF, .ERF, .SRW and .SR2. The majority of these are just raw formats from a given camera manufacturer. The “Raw” format itself is almost just an overarching term for the images coming directly out of a camera without any processing.

Using ImageMagick

The only sensible option I found out there was to use the Magick.NET wrapper around ImageMagick. ImageMagick itself is a image processing library that is available in many languages (Especially common in PHP), and so it’s a pretty feature rich option.

Other options for .NET mostly included using command line applications, but just triggering them from .NET code using Process.Start. I want to avoid this sort of malarky (Even if at times, that’s what Magick.NET is actually doing behind the scenes).

To install Magick.NET, we first need to install the appropriate nuget package. In reality, there are packages for each CPU type (X86/X64) and different quality types (Q8, Q16, Q16HDRI). I was thinking I would try and go middle of the road and as it happens, that was also the most popular package on Nuget.

So from our Package Manager Console :

Install-Package Magick.NET-Q16-AnyCPU

From there, our code is actually extremely simple :

using (var image = new MagickImage("RAW_CANON_EOS_1DX.CR2"))
{
    var geometry = new MagickGeometry();
    geometry.IgnoreAspectRatio = false;
    geometry.Width = 500;
    image.Resize(geometry);
    image.Write("output.jpg");
}

This generates thumbnails (500px wide) from our images while keeping the same aspect ratio. Pretty nifty!

A quick note on testing all of this too. While building this, I didn’t have a camera myself that could generate raw images, so instead I used https://rawsamples.ch to check that various formats would work through ImageMagick (And they all seemed fine!). But if you aren’t sure which “raw” format you should be using, you can of course ask for the type of camera, and match it up to a couple of samples from the site. Worked a treat for me!

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.

While looking through changes mentioned in .NET 6, I noticed that there was a new “Chunk” method on IEnumerable. This method was actually kindof simple, and yet powerful. Immediately I knew of a bunch of places in my code where I would love to use this, especially where I do parallel processing.

So of course, why not a quick write up to talk a little bit more about this utility!

Getting Setup With .NET 6 Preview

At the time of writing, .NET 6 is in preview, and is not currently available in general release. That doesn’t mean it’s hard to set up, it just means that generally you’re not going to have it already installed on your machine if you haven’t already been playing with some of the latest fandangle features.

To get set up using .NET 6, you can go and read out guide here : https://dotnetcoretutorials.com/2021/03/13/getting-setup-with-net-6-preview/

Remember, this feature is *only* available in .NET 6. Not .NET 5, not .NET Core 3.1, or any other version you can think of. 6.

IEnumerable.Chunk In A Nutshell

At it’s simplest, we can write code like so :

var list = Enumerable.Range(1, 100);
var chunkSize = 10;
foreach(var chunk in list.Chunk(chunkSize)) //Returns a chunk with the correct size. 
{
    foreach(var item in chunk)
    {
        Console.WriteLine(item);
    }
}

Allowing us to “chunk” data back. I’ve often done similar code when I want to “batch” things, Especially when running things in parallel like so :

var list = Enumerable.Range(1, 100);
var chunkSize = 10;
foreach(var chunk in list.Chunk(chunkSize)) //Returns a chunk with the correct size. 
{
    Parallel.ForEach(chunk, (item) =>
    {
        //Do something Parallel here. 
        Console.WriteLine(item);
    });
}

You’re probably thinking, well why not use Skip and Take? Which is true, I think this is just a bit more concise and makes things just that little bit more readable.

I was thinking that this would be a guide full of examples, and I actually had more here, but there’s nothing really to it. Chunk just does what it says on the tin, and is a welcome addition to the LINQ family.

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.

True randomness has always been something I struggled to get my head around. Even how we might get closer to being “true random” is also slightly befuddling to me. And that’s why when I was recently asked “What’s the best way to generate a random number in .NET”, a shiver went down my spine remembering the chat boards back in the day flaming people because “The Random class in .NET is not truly random!!”.

What does it mean to be truly random? Or atleast close to it? In practical terms, it means that if we generated a billion numbers in a row, there would be no predictability or uniform to them. They wouldn’t bias in any particular direction overall, but they also wouldn’t be predictable (even within a range) on what the next number would be.

So how do we achieve this in .NET?

The Random Class

For a long time now, we’ve been able to use the Random class to generate “random” numbers. For example :

var randomGenerator = new Random();
randomGenerator.Next(1, 1000000);

This generates us a random number between 1 and 1 million.

However, the Random in C# uses a “seed” value that then uses an algorithm to generator numbers from that seed. Given the same seed value, you would end up with the same number. For example :

var randomGenerator = new Random(123);
var random1 = randomGenerator.Next(1, 1000000);

randomGenerator = new Random(123);
var random2 = randomGenerator.Next(1, 1000000);

Console.WriteLine(random1 + " - " + random2); //Will output the same number. 

And so you probably say, well then just don’t give it the same seed? Easy enough right? Well actually it always has a seed whether you like it or not. When the Random constructor is not given a seed, in .NET Framework it uses the millisecond portion of the time as a seed, and in .NET Core/.NET 5+, it uses a pseudo random number generator.

What this means in .NET Framework according to the documentation :

On most Windows systems, Random objects created within 15 milliseconds of one another are likely to have identical seed values

But this only occurs if you construct your random generator multiple times, if you instead use the same instance of random each time, then this type of “collision” won’t occur :

var randomGenerator = new Random();
var random1 = randomGenerator.Next(1, 1000000);
var random2 = randomGenerator.Next(1, 1000000); //Different number because we are using the same Random instance

I may have been waffling here. But the point is that the Random class in .NET is “good” but not “truly random”. If you are using the same instance of Random in your code to generate multiple random numbers, chances are you will be fine, but it’s still not ideal.

So what can we use if you want more randomness?

Using The RandomNumberGenerator Class

Instead of using the Random class, you can use the RandomNumberGenerator class… Which admittedly is a little annoying to have two. But let’s take a look!

This class has actually been around in all versions of .NET, but in .NET Core 3+,  it got some love with additional helper methods added. So instead of working with random bytes, you can get your random numbers handed right back to you.

var random = RandomNumberGenerator.GetInt32(1, 1000000);

This random number generator is built ontop of the cryptography API’s to be as truly random as possible. I could go on about this (And probably get it all wrong), but if you need something secured by randomness (For example password salt), then you should be using the RandomNumberGenerator and not the Random class.

Performance

So that probably leaves you thinking, why even bother ever using the Random class? Surely if I can get *more* randomness from the RandomNumberGenerator, I should always just use that. Well, it does come at a cost.

Using the following benchmark setup :

public class RandomBenchmark
{
    private static Random _random = new Random();

    [Benchmark]
    public int RandomRecreate() => new Random().Next(1, 1000000);

    [Benchmark]
    public int RandomReuse() => _random.Next(1, 1000000);

    [Benchmark]
    public int RandomGenerator() => RandomNumberGenerator.GetInt32(1, 1000000);
}

We get the following results :

MethodMeanErrorStdDev
RandomRecreate1,631.14 ns8.217 ns7.284 ns
RandomReuse12.02 ns0.001 ns0.001 ns
RandomGenerator74.81 ns0.473 ns0.395 ns

I’ve included the “Recreate” benchmark here just to show how expensive it is to new up a new Random class (Even though, as I’ve already explained, you do not want to do so). But what we are really looking at is RandomReuse vs RandomGenerator. Between the two, using RandomGenerator is 6x slower than using the Random class. We are still talking about nanoseconds between the two so for most use cases, it’s not going to make a difference, but it is something to be aware of.

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.