How to add Func<T, string> of constrained Ts to a collection using that constrained type
I'm trying to create a list of Functions but I'm struggling. Here is a simplified version:
publ开发者_运维技巧ic class ValueGetter
{
public List<Func<Control, string>> Operations { get; set; }
public ValueGetter()
{
this.Operations = new List<Func<Control, string>>();
}
public void Map<T>(Func<T, string> valueGetter) where T : Control
{
this.Operations.Add(valueGetter);
}
}
The issue comes when I try to add the function to the collection. I would have through I'd be able to do this as T is a control however this doesn't compile.
Is there a way I can add the function to this collection?
That's not possible.
Although T
is a Control
, not all Control
s are T
s.
What happens if you add a Func<TextBox, bool>
to the list, then call it (as a Func<Control, string>
) with a Button
?
You can use covariance to cast a Func<Control, string>
to a Func<T, string> where T : Control>
, because any possible T
is also a Control
.
You shoud declare the class as generic:
public class ValueGetter<T> where T : Control
{
public List<Func<T, string>> Operations { get; set; }
public ValueGetter()
{
this.Operations = new List<Func<T, string>>();
}
public void Map(Func<T, string> valueGetter)
{
this.Operations.Add(valueGetter);
}
}
This wouldn’t work, because you would end up having, for example, a Func<Button, string>
in your list, but you could end up calling it with, say, a Label
. What is the function, which expects a Button
, expected to do with a Label
?
You could do something like this:
public class ValueGetter<T> where T : Control
{
public List<Func<T, string>> Operations { get; set; }
public ValueGetter()
{
this.Operations = new List<Func<T, string>>();
}
public void Map(Func<T, string> valueGetter)
{
this.Operations.Add(valueGetter);
}
}
In other words, have separate ValueGetter
s for each Control type.
Edit: Another idea: You could add a function that simply allows the operation only if the type is right, for example:
public void Map<T>(Func<T, string> valueGetter) where T : Control
{
this.Operations.Add(control => (control is T) ? valueGetter((T) control) : null);
}
In this case, if the Button
-expecting function is given a Label
, it would simply return null.
精彩评论