Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Non-nullable reference types (yet again)

There have been many questions around support for non-nullable reference types in .NET. The great hope was code contracts, but it is limited to runtime checking for those who have limited budget.

As for approaches other than Code Contracts, Jon Skeet wrote a blog post about this a few years ago, and one of the commenters provided a useful looking NonNull struct that had the IL modified to disable the default constructor. This seems like an excellent approach, and I can imagine extending it to provide all sorts of non-nullable microtypes. The IL manipulation could be a post-build step triggered by an attribute on the struct e.g.

//Microtype representing a non-zero age, so we want to disable the default ctor
[NoDefaultConstructor]
public struct Age
{
    public Age(int age)
    {
        // Implementation (including validation) elided
    }
} 

Before I investigate this further it I'd like to ask if anyone knows of any problems this might cause? I haven't been able to think of any.

like image 955
Akash Avatar asked Oct 10 '11 13:10

Akash


1 Answers

This can be defeated quite easily - the run-time doesn't try to call the parameterless constructor of a struct (if present) in every scenario.

In particular, it won't get called when creating an array of the struct-type.

Age[] ages = new Age[3];

// This guy skips your "real" ctor as well as the "invalid" parameterless one.
Age age = ages[0];

...or in default(structType) expressions:

// Invalid state here too.
Age age = default(Age);

From Jon Skeet's empirical research into this stuff, here's a list of other operations that don't call the constructor:

  • Just declaring a variable, whether local, static or instance
  • Boxing
  • Using default(T) in a generic method
  • Using new T() in a generic method

Now the situation that leaves you in is that you have to somehow test for every Age instance whether or not the instance was created by working around your fence - which isn't much better than not having erected the fence in the first place.

like image 100
Ani Avatar answered Oct 14 '22 01:10

Ani