在 C# 中将委托强制转换为泛型委托

本文关键字:转换 泛型 | 更新日期: 2023-09-27 18:11:23

简介

我正在使用委托来传递和存储单个表单Control样式逻辑。例如,我有一个委托,其中包含一些Button样式逻辑,如下所示:

button.BackColor = Color.Red;
button.ForeColor = Color.White;
button.FlatStyle = FlatStyle.Flat;

当然,还有许多不同类型的控件,如标签、面板等。因此,为了存储所有这些委托,我使用Dictionary<Type, Delegate>

虽然,委托本身看起来像这样:

delegate void StyleDel<in T>(T control) where T : Control;

因此,为了使用字典中的逻辑,必须首先将Delegate转换为StyleDel<T> - 无论当时T是什么。


A. 情况

初始化并存储所有样式后,必须应用样式(使用 StyleDel s(。为此,我做了一个函数StyleControl(control).

这个函数查看控件的类型(例如Button(,并从Dictionary中找到相应的StyleDel,而又应用(Button-(样式。

public void StyleControl<T>(T control) where T : Control
{
    Delegate storedDel;
    if (_dict.TryGetValue(control.GetType(), out storedDel))
    {
        // Cast Delegate to StyleDel
        var styleDel = (StyleDel<T>) storedDel;
        // Execute StyleDel
        styleDel(control);
    }
}

StyleDel s 通过下面的Add函数添加到字典中:

public bool Add<T>(StyleDel<T> styleDel) where T : Control
{
    var inDict = _dict.ContainsKey(typeof(T)); 
    if (!inDict) _dict[typeof(T)] = styleDel;
    return !inDict;
}

StyleControl函数由另一个函数调用,该函数确保所有内容都以递归方式设置样式:

public void Style<T>(T parent) where T : Control
{
    StyleControl(parent);
    // The problem might have to do with this
    foreach (Control child in parent.Controls) Style(child);
}

问题所在

抛出InvalidCastException,说StyleDel<Button>不能转换为StyleDel<Control>。所以我相信这是在说T在这一点上被视为一种Control,而实际上它是一个Button

如何成功地将此Delegate转换为StyleDel<Button>

在 C# 中将委托强制转换为泛型委托

您可以通过添加不固定级别来实现此目的; 创建一个 lambda,该 lambda 调用您的委托将参数转换为正确的类型:

Dictionary<Type, StyleDel<Control>> _dict = ...
public bool Add<T>(StyleDel<T> styleDel) where T : Control
{
    var inDict = _dict.ContainsKey(typeof(T)); 
    if (!inDict) _dict[typeof(T)] = d => StyleDel((T)d);
    return inDict;
}

乍一看,这似乎不是类型安全的,但在这种特殊情况下,这是因为委托存储在字典中,参数的真实类型作为键。因此,预期用法将始终确保始终使用正确类型的参数调用委托,并且不会发生运行时强制转换异常。