Search code examples
c#.netgenerics

How to add numbers of a generic type


I have a collection of objects that have a unique key. That key could be numbers or a string, it's generic and most of the class doesn't care because it's stored in a Dictionary<TKey, TItem>.

Now the class should provide a method to return a new unique key for an item to be added. That's where I can't find a solution. I've tried to read up on the new generic math feature of C# but that doesn't make any sense to me.

I'm looking for something like the GetUniqueKey method below:

// Restrict TKey to numbers or strings: https://stackoverflow.com/a/30660880
class MyCollection<TKey, TObject>
    where TObject : class
    where TKey : notnull, IComparable, IConvertible, IEquatable<TKey>
{
    private Dictionary<TKey, TObject> items;

    public TKey GetUniqueKey()
    {
        if (TKey is INumber)
            return items.Keys.Max() + 1;
        if (TKey is string)
            return Guid.NewGuid().ToString();
        throw new NotSupportedException("Key type not supported.");
    }
}

Can this be done at all?


Solution

  • This is what I came up with:

    // Restrict TKey to numbers or strings: https://stackoverflow.com/a/30660880
    public class MyCollection<TObject, TKey>
        where TObject : class
        where TKey : notnull, IComparable, IConvertible, IEquatable<TKey>
    {
        private readonly Dictionary<TKey, TObject> objects = [];
    
        public TKey GetUniqueKey()
        {
            switch (Type.GetTypeCode(typeof(TKey)))
            {
                case TypeCode.SByte:
                case TypeCode.Byte:
                case TypeCode.Int16:
                case TypeCode.UInt16:
                case TypeCode.Int32:
                case TypeCode.UInt32:
                case TypeCode.Int64:
                    if (Count == 0)
                        return (TKey)Convert.ChangeType(1, typeof(TKey));
                    return (TKey)Convert.ChangeType(Convert.ToInt64(objects.Keys.Max()) + 1, typeof(TKey));
                case TypeCode.UInt64:
                    if (Count == 0)
                        return (TKey)Convert.ChangeType(1, typeof(TKey));
                    return (TKey)Convert.ChangeType(Convert.ToUInt64(objects.Keys.Max()) + 1, typeof(TKey));
                case TypeCode.String:
                    return (TKey)(object)Guid.NewGuid().ToString();
                default:
                    throw new NotSupportedException($"Key type {typeof(TKey).Name} not supported.");
            }
        }
    }
    

    I makes use of IConvertible for all numbers to convert the types, any also IComparable for Max().