C
C#•11mo ago
Camster

Generics without Casting

Is there any possible way to do what the code below is doing with generics, but without the casting?
public interface IItemCollection
{
int AddItem<T>(T item);
T GetItem<T>(int id);
}

public class ItemCollection : IItemCollection {
private Dictionary<Type, Dictionary<int, object>> _items = new();

public int AddItem<T>(T item)
{
var dictionary = GetDictionary<T>();
int next = dictionary.Keys.Max() + 1;
dictionary.Add(next, item);
return next;
}

public T GetItem<T>(int id)
{
var dictionary = GetDictionary<T>();
return (T)dictionary[id];
}

private Dictionary<int, object> GetDictionary<T>()
{
if (!_items.ContainsKey(typeof(T)))
_items.Add(typeof(T), new Dictionary<int, object>());
return _items[typeof(T)];
}
}
public interface IItemCollection
{
int AddItem<T>(T item);
T GetItem<T>(int id);
}

public class ItemCollection : IItemCollection {
private Dictionary<Type, Dictionary<int, object>> _items = new();

public int AddItem<T>(T item)
{
var dictionary = GetDictionary<T>();
int next = dictionary.Keys.Max() + 1;
dictionary.Add(next, item);
return next;
}

public T GetItem<T>(int id)
{
var dictionary = GetDictionary<T>();
return (T)dictionary[id];
}

private Dictionary<int, object> GetDictionary<T>()
{
if (!_items.ContainsKey(typeof(T)))
_items.Add(typeof(T), new Dictionary<int, object>());
return _items[typeof(T)];
}
}
14 Replies
DaVinki
DaVinki•11mo ago
Use T for the dictionary instead of object
Camster
CamsterOP•11mo ago
But the class ItemCollection isn't generic, only the methods.
Jimmacle
Jimmacle•11mo ago
i don't think there's a way around it
Camster
CamsterOP•11mo ago
I had a feeling 😢
mtreit
mtreit•11mo ago
So make it generic Something like this instead:
using System.Collections.Generic;
using System;
using System.Linq;

public interface IItemCollection<T>
{
int AddItem(T item);
T GetItem(int id);
}

public class ItemCollection<T> : IItemCollection<T>
{
private Dictionary<Type, Dictionary<int, T>> _items = new();

public int AddItem(T item)
{
var dictionary = GetDictionary();
int next = dictionary.Keys.Max() + 1;
dictionary.Add(next, item);
return next;
}

public T GetItem(int id)
{
var dictionary = GetDictionary();
return dictionary[id];
}

private Dictionary<int, T> GetDictionary()
{
if (!_items.ContainsKey(typeof(T)))
{
_items.Add(typeof(T), new Dictionary<int, T>());
}

return _items[typeof(T)];
}
}
using System.Collections.Generic;
using System;
using System.Linq;

public interface IItemCollection<T>
{
int AddItem(T item);
T GetItem(int id);
}

public class ItemCollection<T> : IItemCollection<T>
{
private Dictionary<Type, Dictionary<int, T>> _items = new();

public int AddItem(T item)
{
var dictionary = GetDictionary();
int next = dictionary.Keys.Max() + 1;
dictionary.Add(next, item);
return next;
}

public T GetItem(int id)
{
var dictionary = GetDictionary();
return dictionary[id];
}

private Dictionary<int, T> GetDictionary()
{
if (!_items.ContainsKey(typeof(T)))
{
_items.Add(typeof(T), new Dictionary<int, T>());
}

return _items[typeof(T)];
}
}
Note that this code isn't thread safe.
Jimmacle
Jimmacle•11mo ago
i think the point is that the outer collection isn't generic it's more like a bag of objects grouped by type not really sure what the goal is
mtreit
mtreit•11mo ago
Yes, not really clear.
Camster
CamsterOP•11mo ago
I basically have several objects where I want to manually create Id's for. With them all being different types, I'd like to have one class to do it. But I suppose it's not too bad just to create a generic class similar to @mtreit, and I can create an implementation for each type. Thanks for your help
Omnissiah
Omnissiah•11mo ago
can i say that this int next = dictionary.Keys.Max() + 1; is a bit awkward
Camster
CamsterOP•11mo ago
Yes you can! How would you do it?
Omnissiah
Omnissiah•11mo ago
it depends what this thing it has to be but at least i would just keep an autoincrement id as a field of the class so that there's no need to duplicate and examine all the keys of the dictionary to get a value
Camster
CamsterOP•10mo ago
Thanks for the tips. In retrospect, I was thinking along similar lines. In fact, Max() causes an exception when the are no values 😄 In my particular case, there won't be very many items added, so I wasn't too worried about performance.
Omnissiah
Omnissiah•10mo ago
i can understand that, but to me it's kind of a yellow flag i could maybe accept that if say there was an exception when trying add more than 10~15 items, for example like throw new Exception("don't use this class for large collections")
Camster
CamsterOP•10mo ago
Oh I'll definitely go the route of having an autoincrement id. I agree it's better. I was mainly trying to figure out if there's a generics trick I wasn't aware of. Thanks for your input
Want results from more Discord servers?
Add your server