指定委托参数的特定类型

时间:2009-08-04 12:18:06

标签: c#

假设我有以下代表

public delegate void ControlInitializer(Control control);

指定委托时是否有办法指定输入参数的控制类型? e.g。

而不是

ControlInitializer one = c => ((TextBox)c).Text = "Init Value"
ControlInitializer two = c => ((DropDownList)c).SelectedValue= "-1"

我可以做点什么吗

ControlInitializer one = (TextBox c) => c.Text = "Init Value"
ControlInitializer two = (DropDownList c) => c.SelectedValue= "-1"

在这种情况下,Textbox是Control的子类吗?

更新:我还需要将这两个ControlInitialiser委托存储在例如

Dictionary<string, ControlInitializer>

将指定

Dictionary<string, ControlInitializer<Control>>

在这种情况下工作,因为我似乎无法让它发挥作用。

提前致谢。

3 个答案:

答案 0 :(得分:10)

您可以使委托具有通用性:

public delegate void ControlInitializer<TControl>(TControl control)
    where TControl : Control;

然后像这样使用它:

ControlInitializer<TextBox>      one = c => c.Text = "Init Value";
ControlInitializer<DropDownList> two = c => c.SelectedValue = "-1";

我想你的目标是这样的:

var init = new Init();

init.RegisterInitializer<TextBox>(c => c.Text = "Init Value");
init.RegisterInitializer<DropDownList>(c => c.SelectValue = "-1");

foreach (var c in Controls)
{
    init.ApplyInitializer(c);
}

由于 David B 的回答中提到的原因,这有点困难。但是,你可以做的是隐藏抽象背后的类型,如下所示:

public class Init
{
    private readonly Dictionary<Type, Action<Control>> initializers;
    ...

    public void RegisterInitializer<TControl>(Action<TControl> i)
        where T Control : Control
    {
        initializers.Add(typeof(TControl), c => i((TControl)c));
    }

    public void ApplyInitializer(Control c)
    {
       initializers[c.GetType()](c);
    }
}

答案 1 :(得分:3)

首先,使用预定义的委托Action。关于指定类型,请使用泛型参数:

Action<TextBox, string> one = (c,v) => c.Text = v;

Action委托最多需要4个参数,不会返回任何内容(void)。

答案 2 :(得分:2)

您无法将ControlInitializer<TextBox>添加到包含ControlInitializer<Control> 的词典,因为第一种类型不会继承第二种类型(即使{{1}继承自TextBox。)这是关于泛型中缺乏协方差和逆变的全部内容。

您可以编写自己的集合,以您期望的方式行事。这是一种可能性:

Control

可以这样使用:

public class CustomStorage
{
  private Dictionary<string, object> storage = new Dictionary<string, object>();

  public void Remember(string key, object value)
  {
    storage[key] = value;
  }

  public object Retrieve(string key)
  {
    object x = storage[key];
    return x;
  }

  public U Retrieve<U>(string key)
  {
    U u = (U) storage[key];
    return u;
  }
}