Reputation: 2281
public class ItemStore {
private Dictionary<Type, List<object>> _items = new Dictionary<Type, List<object>>();
public void AddItem(object item) {
var type = item.GetType();
if (!_items.ContainsKey(type)) {
_items[type] = new List<object>();
}
_items[type].Add(item);
}
public IEnumerable<T> GetItems<T>() {
if(!_items.ContainsKey(typeof(T))) {
return new List<T>();
}
return _items[typeof(T)].Cast<T>();
}
}
(The real scenario is more complex, and it is a library used in multiple Projects knowing nothing about the concrete types.... )
The Cast<T>()
in GetItems()
is consuming quite some time. So I would prefere to avoid it. Is there any way to avoid it in C# - because actually the list already contains the correct types?
Upvotes: 2
Views: 112
Reputation: 837
Make AddItem() method generic
public class ItemStore
{
private Dictionary<Type, IList> _items = new Dictionary<Type, IList>();
public void AddItem<T>(T item)
{
var type = typeof(T);
if (!_items.ContainsKey(type))
{
_items[type] = new List<T>();
}
_items[type].Add(item);
}
public IEnumerable<T> GetItems<T>()
{
if (!_items.ContainsKey(typeof(T)))
{
return new List<T>();
}
return (List<T>)_items[typeof(T)];
}
}
Upvotes: 4
Reputation:
You could make your method AddItem generic, which would allow you to store List<T>
instances in your dictionary (whose generic TValue parameter should be IList
in this case).
public class ItemStore
{
private Dictionary<Type, IList> _items = new Dictionary<Type, IList>();
public void AddItem<T>(T item)
{
IList objList;
if (!_items.TryGetValue(typeof(T), out objList))
{
objList = new List<T>();
_items[typeof(T)] = objList;
}
objList.Add(item);
}
public IEnumerable<T> GetItems<T>()
{
IList objList;
return
(_items.TryGetValue(typeof(T), out objList)) ? (List<T>)objList
: new List<T>();
}
}
Upvotes: 2
Reputation: 40818
You need to modify the internal structure of this class a bit to not use generics in the items lookup because we need to underlying type of the stored list to be the correct type. This requires a little reflection when creating the list. We can also make AddItem and GetItems a little more efficient by avoiding extra lookups:
public class ItemStore {
private Dictionary<Type, IList> _items = new Dictionary<Type, IList>();
public void AddItem(object item) {
var type = item.GetType();
IList list;
if (!_items.TryGetValue(type, out list)) {
var listType = typeof(List<>).MakeGenericType(type);
list = (IList)Activator.CreateInstance(listType);
_items[type] = list;
}
list.Add(item);
}
public IEnumerable<T> GetItems<T>() {
IList list;
if(!_items.TryGetValue(typeof(T), out list)) {
return Enumerable.Empty<T>();
} else {
return (IEnumerable<T>)list;
}
}
}
If you can modify the signature of AddItem this could be even simpler (no reflection), but given you've said this is an over simplification, I will leave the public API unchanged.
Upvotes: 7