字典中值的协方差

问题描述 投票:0回答:1

我正在尝试将更派生的类型作为值添加到字典中<..., base>但出现以下错误: 无法从

HandleIntegrationEvent<TR>
转换为
HandleIntegrationEvent<IBaseEvent>

示例

using System.Threading.Tasks;
using System.Collections.Generic;

public interface IBaseEvent
{
    string Name { get; }
}

public class UserCreatedEvent: IBaseEvent
{
    public string Name { get; } = "UserCreatedEvent";
}

public delegate Task HandleIntegrationEvent<in TR>(TR @event) where TR: IBaseEvent;

public class IntegrationBus
{
  private readonly IDictionary<string, HandleIntegrationEvent<IBaseEvent>> _listeners = new Dictionary<string, HandleIntegrationEvent<IBaseEvent>>();

  public void RegisterEventListener<TR>(string @event, HandleIntegrationEvent<TR> listener) where TR: IBaseEvent
  {
   // ERROR: cannot convert from HandleIntegrationEvent<TR> to HandleIntegrationEvent<IBaseEvent>
    _listeners.Add(@event, listener);
  } 
}

我只是无法理解它,并且已经尝试理解这个问题有一段时间了。 据我了解,通用约束应该确保实例已实现 IBaseEvent 接口。

我只是暂时有心理障碍

编辑 发现另一篇很棒的文章https://stackoverflow.com/a/12841831解释了字典协方差和逆变的原因。 但我还是有点迷茫

c# dictionary generics interface covariance
1个回答
0
投票

您需要更改字典以存储

Func<IBaseEvent, Task>
而不是
HandleIntegrationEvent<IBaseEvent>
。然后,在添加到字典时,用
Func<IBaseEvent, Task>
包装侦听器以将事件转换为适当的类型。

更新代码:

private readonly IDictionary<string, Func<IBaseEvent, Task>> _listeners = new Dictionary<string, Func<IBaseEvent, Task>>(); //add using System; if you get an Func<> error

public void RegisterEventListener<TR>(string @event, HandleIntegrationEvent<TR> listener) where TR : IBaseEvent
{
    _listeners.Add(@event, (e) => listener((TR)e));
}
© www.soinside.com 2019 - 2024. All rights reserved.