如何在“GenericType”的基本类型的Action中分配“GenericType”的Action?

时间:2013-12-17 19:46:18

标签: c# generics casting

我需要在“GenericType”的基本类型的Action中分配Action“GenericType”。 因此,我将有几个操作,每个操作都有不同的ModelMapNode类型。

public class ModelMapNode { }

public class ModelMapNode<TModelMap> : ModelMapNode { }

public class Class1
{
    private List<Action<ModelMapNode>> Actions { get; set; }

    public void AddAction<T>(Action<ModelMapNode<T>> childConfigurer)
    {
        this.Actions.Add((Action<ModelMapNode>)childConfigurer);
    }
}

此类型广播不起作用。

3 个答案:

答案 0 :(得分:2)

这基本上是不安全的 如果这是合法的,你将能够传递Action<ModelMapNode<SomeClass>>,然后将其转换为Action<ModelMapNode>并传递一个它无法处理的错误类。

相反,您应该将整个类设为通用,然后将字段更改为Action<ModelMapNode<T>>

答案 1 :(得分:2)

因此,基于your comment,您知道Action<ModelMapNode<T>>对象无法安全地转换为(Action<ModelMapNode>)。要么你在其他地方做某事以确保它不会在运行时失败,或者你希望在传递给action的实际参数不是ModelMapNode<T>的情况下在运行时抛出一些异常。 / p>

你不能通过强制转换Action来做到这一点,因为编译器知道它不安全,但你可以做的是创建一个新的包装器函数来转换参数,然后调用另一个动作:

public void AddAction<T>(Action<ModelMapNode<T>> childConfigurer)
{
    this.ActionOne = node => childConfigurer((ModelMapNode<T>)node);
}

答案 2 :(得分:1)

泛型类型Action<in T>在其类型参数in中是逆变(“T”)。

所以你可以说:

Action<ModelMapNode> a1 = XXX;
Action<ModelMapNode<T>> a2 = a1;

它会正常工作。因为如果某个操作a1可以接受任何 ModelMapNode,那么特别是它可以包含ModelMapNode<T>,因为任何ModelMapNode<>都是{{1}通过继承(基类)。

您正在尝试使用ModelMapNode,就好像它是协变,而不是逆变,并且这永远不会有效。