开发者

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 Controls are Ts.
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 ValueGetters 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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜