Search code examples
c#.netnull.net-8.0c#-12.0

Nullable strings and other reference types in C# 12


I am working on a code generator and trying to map CLR types to SQL types.

Example:

using System.Data;
using System.Data.SqlTypes;

var dictionaryCtsToSql = new Dictionary<Type, SqlDbType>();

dictionaryCtsToSql.Add(typeof(Boolean), SqlDbType.Bit);
dictionaryCtsToSql.Add(typeof(Boolean?), SqlDbType.Bit);
...
dictionaryCtsToSql.Add(typeof(Byte), SqlDbType.TinyInt);
dictionaryCtsToSql.Add(typeof(Byte?), SqlDbType.TinyInt);
dictionaryCtsToSql.Add(typeof(Int32), SqlDbType.Int);
dictionaryCtsToSql.Add(typeof(Int32?), SqlDbType.Int);
dictionaryCtsToSql.Add(typeof(UInt32), SqlDbType.BigInt);
dictionaryCtsToSql.Add(typeof(UInt32?), SqlDbType.BigInt);
dictionaryCtsToSql.Add(typeof(Single), SqlDbType.Real);
dictionaryCtsToSql.Add(typeof(Single?), SqlDbType.Real);
...
dictionaryCtsToSql.Add(typeof(DateTime), SqlDbType.DateTime2);
dictionaryCtsToSql.Add(typeof(DateTime?), SqlDbType.DateTime2);
dictionaryCtsToSql.Add(typeof(DateTimeOffset), SqlDbType.DateTimeOffset);
dictionaryCtsToSql.Add(typeof(DateTimeOffset?), SqlDbType.DateTimeOffset);
...

This works fine for primitives / value-types but not on a nullable string as follows:

dictionaryCtsToSql.Add(typeof(String), SqlDbType.NVarChar);
dictionaryCtsToSql.Add(typeof(String?), SqlDbType.NVarChar); // Error.

Reference type nullability error.

Now, I completely understand WHY this would cause an error on reference types, but I am targeting .NET 8 that uses C# 12, and the project has its nullability setting enabled:

<PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <Nullable>enable</Nullable>
</PropertyGroup>

So, consider the following class:

using System.Data;
using System.Data.SqlTypes;

public class Entity
{
    public long Id { get; set; }

    public string NameGiven { get; set; } = string.Empty;
    public string? NameMiddle { get; set; }
    public string NameFamily { get; set; } = string.Empty;

    public DateTime DateTimeFrom { get; set; } = SqlDateTime.MinValue.Value;
    public DateTime? DateTimeUntil { get; set; }
}

I checked the reflected property and it appears the Type is still String with an added NullableAttribute:

Nullable string.

Value types, on the other hand, are wrapped in another struct Nullable<TValueType>. This means that string? is not a new type at all as opposed to int?.

So, the question against this long-winded explanation is: I would very much like to use the existing dictionary Dictionary<Type, SqlDbType> if possible, without having to check for nullability attributes in code. Is this possible? If not, shouldn't it be?

I suppose I am a bit sad to know that nullable reference types seem to be designed for code-quality rather than runtime functionality.


Solution

  • "I suppose I am a bit sad to know that nullable reference types seem to be designed for code-quality rather than runtime functionality" - To your disappointment, this is true.