I ran into an interesting problem when I tried to use Entity Framework Core with the new nullable reference types in C# 8.0.
The Entity Framework (various flavors) allows me to declare DBSet properties that I never initalize. For example:
public class ApplicationDbContext : IdentityDbContext
{
#pragma warning disable nullable
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{ }
#pragma warning restore nullable
public DbSet<Probe> Probes { get; set; }
public DbSet<ProbeUnitTest> ProbeUnitTests { get; set; }
}
The DbContext constructor reflects over the type and initializes all of the DbSet properties, so I know that all the properties will be non-null by the conclusion of the constructor. If I omit the #pragma's i get the expected warnings because my code does not initialize these properties.
Data\ApplicationDbContext.cs(10,12,10,32): warning CS8618: Non-nullable property 'Probes' is uninitialized.
Data\ApplicationDbContext.cs(10,12,10,32): warning CS8618: Non-nullable property 'ProbeUnitTests' is uninitialized.
Turning off the warnings seems like a blunt instrument when all I want to do is inform the compiler that a property will not be null?
If turns out I can fool the compiler like this:
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
Probes = Probes;
ProbeUnitTests = ProbeUnitTests;
}
This code has the advantage that it is very narrow -- it only applies to the specific property's initialization and will not suppress other warnings. The disadvantage is that this is nonsense code because assigning a property to itself really ought to do nothing.
Is there a preferred idiom for informing the compiler that it just does not know that the property has been initialized?
Probes = Probes
should be okay (you're assigningProbes
with something that's non-nullable:Probes
), but we know that it's actually not okay, at this pointProbes
is stillnull
, so you've probably actually found a bug in the compiler's nullable analysis. – Mccowyn