My code looks something like this:
#nullable enable
class MyClass<KEY, ITEM>
{
readonly Dictionary<KEY, ITEM> Map = new Dictionary<KEY, ITEM>();
public void Process(KEY key, ITEM item)
{
if (key != null)
{
Map[key] = item;
}
}
}
#nullable disable
The compiler is not thrilled with this, it gives me the warning
type 'KEY' cannot be used as type parameter 'TKey' in the generic type or method 'Dictionary<TKey, TValue>
which I can certainly understand. The problem is, sending null for the 'key' parameter to Process() is perfectly valid so I can't add the "where KEY: notnull" constraint to the class. (and MyClass needs to accept both classes and structs for the KEY type parameter)
The only thing I can think of is this:
#nullable enable
class MyClass<KEY, ITEM>
{
#nullable disable
readonly Dictionary<KEY, ITEM> Map = new Dictionary<KEY, ITEM>();
#nullable enable
public void Process(KEY key, ITEM item)
{
if (key != null)
{
Map[key] = item;
}
}
}
#nullable disable
Which keeps the compiler happy, but then I don't have all those nice C# 8 null checks. For example, it allows me to write this code:
Map[default] = item;
and the compiler doesn't bat an eye.
How can I tell the compiler that the 'KEY' type parameter to Dictionary<> should disallow nulls, but still allow KEY values to be null in the outer class?
EDIT
I want to use the new C# 8 nullability features so that I catch as many null pointers at compile time as possible (instead of waiting for runtime exceptions).
FURTHER EDIT
The direction I'm headed right now, is to put a thin layer around Dictionary to enforce the null restrictions and use it instead of Dictionary<>
#nullable enable
public class CheckDictionary<KEYTYPE, VALUETYPE>
{
#nullable disable
readonly Dictionary<KEYTYPE, VALUETYPE> Dictionary = new Dictionary<KEYTYPE, VALUETYPE>();
#nullable enable
public VALUETYPE this[[DisallowNull] KEYTYPE key]
{
get { return Dictionary[key]; }
set { Dictionary[key] = value; }
}
public bool Remove([DisallowNull] KEYTYPE key)
{ return Dictionary.Remove(key); }
public bool TryGetValue([DisallowNull] KEYTYPE key, out VALUETYPE value)
{ return Dictionary.TryGetValue(key, out value); }
public List<VALUETYPE> Values => Dictionary.Values.ToList();
}