如何使用约束类型将约束Ts的Func <t,string =“”>添加到集合中</t,>

时间:2011-01-21 00:02:16

标签: c# generics collections casting expression

我正在尝试创建一个函数列表,但我正在努力。这是一个简化版本:

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是一个控件但是这不能编译。

有没有办法可以将函数添加到此集合中?

3 个答案:

答案 0 :(得分:1)

那是不可能的。

虽然TControl,但并非所有Control都是T。 如果您向列表中添加Func<TextBox, bool>,然后使用Func<Control, string>将其称为Button,会发生什么?

您可以使用covarianceFunc<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。