我正在尝试创建一个函数列表,但我正在努力。这是一个简化版本:
public 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);
}
}
当我尝试将该功能添加到集合时,问题就出现了。我可以通过我能够做到这一点,因为T是一个控件但是这不能编译。
有没有办法可以将函数添加到此集合中?
答案 0 :(得分:1)
那是不可能的。
虽然T
是Control
,但并非所有Control
都是T
。
如果您向列表中添加Func<TextBox, bool>
,然后使用Func<Control, string>
将其称为Button
,会发生什么?
您可以使用covariance将Func<Control, string>
投射到Func<T, string> where T : Control>
,因为任何可能的T
也是Control
。
答案 1 :(得分:1)
您应该将该类声明为通用:
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);
}
}
答案 2 :(得分:1)
这不起作用,因为您最终会在列表中找到Func<Button, string>
,但最终可能会使用Label
来调用它。什么是期望Button
的函数,期望Label
?
你可以这样做:
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);
}
}
换句话说,对每种控件类型都有单独的ValueGetter
。
编辑:另一个想法:您可以添加一个仅在类型正确时才允许操作的功能,例如:
public void Map<T>(Func<T, string> valueGetter) where T : Control
{
this.Operations.Add(control => (control is T) ? valueGetter((T) control) : null);
}
在这种情况下,如果Button
- 期望函数被赋予Label
,它将只返回null。