C# 强制转换 Action 泛型

C# casting Action generics

提问人:Apache81 提问时间:10/18/2023 更新时间:10/18/2023 访问量:58

问:

我有我的第一堂课,喜欢

public abstract class A
{
    protected event Action<A> onCompleted;

    public void CompleteExecution()
    {
        // doing something...
        onCompleted?.Invoke(this);
    }
}

还有另一个类,比如

public class B : A
{
    private Action<B> _callback;

    public void Initialize(Action<B> callback)
    {
        _callback = callback;
    }

    public void Execute()
    {
        onCompleted += (Action<A>)callback;
        // doing something specific.
    }
}

然后我使用 B 和类似的东西:

public class Executor
{
    private B _inst;

    public Executor
    {
        _inst = new B();
        _inst.Initialize(Callback);
    }

    public void Execute()
    {
        _inst.Execute();
    }

    public void Finalize()
    {
        _inst.CompleteExecution();
    }

    private void Callback(B inst)
    {
        // completed !!!
    }
}

如果参数相关,我以为我可以强制转换 Action,但我在

onCompleted += (Action<A>)callback;

在 B 类的 Execute 方法中。

我通过将该行替换为

onCompleted += _ => callback?.Invoke(this);

但我觉得它很丑陋。

有没有更好的方法来实现演员表?

C# 泛型 强制转换 操作

评论

3赞 Fildor 10/18/2023
Action<A>并且是两种完全不相关的类型。虽然是-a,但不是-a,因此它们不能只是相互铸造。Action<B>BAAction<B>Action<A>
0赞 Fildor 10/18/2023
相反,您可能希望创建一个单独的类型(或两者都实现的接口)。EventArgs
0赞 MakePeaceGreatAgain 10/18/2023
想象一下,你可以这样做:.这将使我们能够向委托人提供任何任意的 A 实例,而不仅仅是 .所以这也是有效的:(假设也派生自 ,但不是 ) 当你的委托类型为 时,它需要 的实例 ,而不是 的实例。Action<A> a = (Action<A>) myBDelegate;Ba.Invoke(new C())CABAction<B>BC
0赞 nalka 10/18/2023
这回答了你的问题吗?泛型和强制转换 - 无法将继承的类强制转换为基类

答:

1赞 JonasH 10/18/2023 #1

有没有更好的方法来实现演员表?

不。 是逆变的,这意味着您可以转换为 .这之所以有效,是因为继承自 ,可以使用 的实例作为参数调用相同的原因。Action<T>Action<A>Action<B>BAvoid MyMethodA(A a)B

但它不是协变的,所以你不能做相反的事情。出于同样的原因,不能使用 作为参数的实例调用。void MyMethodB(B b)A

如果您当前的解决方法有效,则可以使用它。您还可以使用泛型执行某些操作,请参阅奇怪的重复模板模式。但请注意,这可能会增加解决方案的复杂性。或者,可以在两个类中声明具有相同名称的事件,并使用 new 修饰符隐藏继承的成员。