I've got a Dictionary<Type, HashSet<GenericType>>
which I use to hold my data in, and I am trying to make a function that returns one of those HashSets given the generic type T : GenericType
.
Basically
Dictionary<Type, HashSet<GenericType>> data;
public HashSet<T> Get<T>() where T : GenericType
{
var tp = typeof(T);
//....check if its in the dictionary, fill if not....
return data[tp];
}
This isn't valid of course. But I am having a very hard time figuring out what I should do instead.
I feel like returning T
is optimal though, since you then can do something like this:
Get<Derived>().Where(x => x.DerivedProperty == someValue)
But the only thing I thought of was to create a new HashSet<T>
every time Get
is called, and then using a foreach-loop cast and add every item from the already existing HashSet in the Dictionary, but this feels like such a waste?
Another idea is to skip HashSet and use another (covariant?) collection. But since these collections will hold lots of data, maybe it isn't the best idea either.
So in short I am wondering what the best approach for this problem is.
So this is the structure I got. The type which contains data
is a type of service in my code structure. It will via reflection be loaded and initialized at runtime. From there I later use a ServiceFactory of sorts to get that service.
public class foo : Service
{
public Dictionary<Type, HashSet<BaseClass>> data = new Dictionary<Type, HashSet<BaseClass>>();
public T Get<T>() where T : BaseClass
{
var tp = typeof(T);
if (!data.ContainsKey(tp))
{
data.Add(typeof(Derived), new HashSet<BaseClass>() { new Derived(), new Derived(), new Derived() });
}
return data[tp];//this wont compile.
}
}
public class Derived : BaseClass
{
public int ExampleVariable {get;set;}
}
public abstract class BaseClass
{
// some things in here.
public void DoCommonStuff()
{
}
}
class program
{
static void Main(string[] args)
{
var service = ServiceFactory.GetService<foo>();
var collection = service.Get<Derived>();
}
}
I would just change the type of the dictionary, and cast inside your Get
method. Definitely, definitely make your dictionary private though - then you can make sure that only your code (ideally only the Get
method) can access it:
// Any data[typeof(Foo)] value will be a HashSet<Foo>. Only
// the Get method should access this dictionary.
private readonly Dictionary<Type, object> data = new Dictionary<Type, object>();
public HashSet<T> Get<T>() where T : GenericType
{
var tp = typeof(T);
object value;
if (data.TryGetValue(tp, out value))
{
return (HashSet<T>) value;
}
var newSet = new HashSet<T>()
// Populate newSet here
data[tp] = newSet;
return newSet;
}
I have a bit more discussion of a closely-related issue in a blog post.
See more on this question at Stackoverflow