Reputation: 6489
Consider the following code:
public dynamic DataGrid { get; private set; }
public DataGridForm<TData, TGrid> GridConfig<TData, TGrid>() where TData : class
{
return DataGrid = new DataGridForm<TData, TGrid>();
}
I'm trying to keep an instance of a generic class in a property
for later usage, but as you know:
Properties, events, constructors etc can't be generic - only methods and types can be generic. Most of the time that's not a problem, but I agree that sometimes it's a pain (Jon Skeet)
I want to know is this a good way to round this situation?
Upvotes: 6
Views: 361
Reputation: 902
As the answer in the comment indicated, you can do this with a base class or an interface:
class DataGridForm {}
class DataGridForm<TData, TGrid> : DataGridForm {}
class GridConfigurator
{
public DataGridForm DataGrid { get; private set; }
public DataGridForm<TData, TGrid> GridConfig<TData, TGrid>() where TData : class
{
return DataGrid = new DataGridForm<TData, TGrid>();
}
}
A ton of types and interfaces in C# were expanded this way when generics were added. However, I would probably re-evaluate your design so that perhaps whatever called GridConfig() was caching the DataGridForm since it knows the types. As an example, I do a very similar thing in my code:
class Vector<T> { ... }
static class Vector
{
public static Vector<T> Create<T>(T value)
{
return new Vector<T>(value);
}
}
class OtherClass
{
public static Vector<int> MyVector = Vector.Create(1);
}
Your specific use case may not support this style though.
Upvotes: 1
Reputation: 617
In this case your type itself has to be generic.
class GridConfigurator<TData, TGrid>
where TData : class
{
public DataGridForm<TData, TGrid> DataGrid { get; private set; }
public DataGridForm<TData, TGrid> GridConfig<TData, TGrid>()
{
return DataGrid = new DataGridForm<TData, TGrid>();
}
}
But I don't understand the purpose of this class. The GridConfig method has a non-obvious side effect of setting the DataGrid property (which has a private setter). If I were using this class, I would never guess that the value that GridConfig() returns to me is also set as the DataGrid property. In other words:
var configurator = new GridConfigurator();
var firstGrid = configurator.GridConfig();
var firstReference = configurator.DataGrid;
var secondGrid = configurator.GridConfig();
var secondReference = configurator.DataGrid;
I would assume the following would return false:
object.ReferenceEquals(firstGrid, secondGrid);
But I would assume this would return true:
object.ReferenceEquals(firstReference, secondReference);
Because at no point in the above code do I ever assign the DataGrid property. It is not clear that a method called GridConfig() would have that effect.
Making the enclosing type (GridConfigurator) also generic seems to defeat the purpose of what you're trying. Why would anyone use this type when they could just use a direct reference to DataGridForm instead?
If the GridConfig method is supposed to do something more than just assign a new default instance of DataGridForm, then make it a static factory class like this:
static class GridConfigurator
{
public static DataGridForm<TData,TGrid> GridConfig<TData, TGrid>(...) where TData: class
{
var grid = new DataGridForm<TData,TGrid>();
// do something with the parameters to this method to initialize the instance.
return grid;
}
}
I would also name the method something other than GridConfig. Like Configure() or Create().
Upvotes: 0