I'm writing up a generic method that needs to internally use a Dictionary
keyed by the generic parameter.
I don't want to impose any constraint on the generic parameter itself, in particular no notnull
constraint. However, the method would be capable of handling nulls explicitly, and of course not adding any null keys to the dictionary it's using.
Is there any best practice for doing so?
By default, the compiler warns that the generic key type doesn't match the notnull
constraint of Dictionary<,>
.
See an example below. Unless I'm missing something, this should be perfectly safe. But how can I best convey this to the compiler? Is there any way other than suppressing the compiler warning here?
public static int CountMostFrequentItemOrItems<T>(params T[] values)
{
var counts = new Dictionary<T, int>(); // The type 'T' cannot be used as type parameter 'TKey' in the generic type or method 'Dictionary<TKey, TValue>'
var nullCount = 0;
foreach(var value in values)
if (value is null)
++nullCount;
else if (counts.TryGetValue(value, out var count))
counts[value] = count+1;
else
counts[value] = 1;
// ... combine results etc ...
}
T
is nullable, the dictionary will never be given a null key – CrumpCountMostFrequentItemOrItems
method could be optimized with theCollectionsMarshal.GetValueRefOrAddDefault
API (usage example). – BuckleDictionary<>
at all. I would useGroupBy
to group, thenWhere
to remove any null, and then aMax
in combination withCount
to get the most frequent item. Should be a oneliner. – BiotopeGroupBy
is an inefficient solution for this problem. What you need is theCountBy
, which is currently just a proposal. – Bucklewhere TKey : notnull
, so if you can bypass it, you also break the c# constraints. – Fabozzi<nullable>enable</nullable>
– HeterogeneousMaybeNull
/NotNull
on the type parameter itself (so not as a constraint), as that's the usual way to work around situations where you know better than the compiler, but .NET doesn't currently offer this (support for attributes on type parameters was added at some point, though, so this could be done). Suppressing the warning is the correct approach here -- that's why nullability analysis is warnings in the first place, since we know the compiler can't do this perfectly with the approach C# has chosen. – Tensionnew Dictionary<T!, int>()
would be yet another "proper" solution. – Ponytail