具有通用接口的C#casting

具有通用接口的C#casting,c#,generics,interface,casting,C#,Generics,Interface,Casting,我试图理解为什么在这种情况下铸造不起作用 假设以下接口: public interface IDomainEvent { } public interface IHandler<T> where T: IDomainEvent { void Handle(T args); } 公共接口IDomainEvent{} 公共接口IHandler,其中T:IDomainEvent { 无效句柄(T参数); } 这些简单的实现: public class SomeEvent :

我试图理解为什么在这种情况下铸造不起作用

假设以下接口:

public interface IDomainEvent { }

public interface IHandler<T> where T: IDomainEvent
{
    void Handle(T args);
}
公共接口IDomainEvent{}
公共接口IHandler,其中T:IDomainEvent
{
无效句柄(T参数);
}
这些简单的实现:

public class SomeEvent : IDomainEvent
{
    public string Value { get; set; }
}

public class SomeEventHandler : IHandler<SomeEvent>
{
    public void Handle(SomeEvent args) { }
}
public类SomeEvent:IDomainEvent
{
公共字符串值{get;set;}
}
公共类SomeEventHandler:IHandler
{
公共无效句柄(SomeEvent args){}
}
我不明白为什么我不能做这个演员:

var handler = new SomeEventHandler() as IHandler<IDomainEvent>;
var handler=new SomeEventHandler()作为IHandler;
我使用Autofac来解析基于事件的处理程序列表,虽然它做得很好,但它创建的处理程序当然是完全具体的,在运行时我需要通过接口来处理它们。我可以很容易地使用反射来调用handle方法,但这似乎应该可以工作:/

这需要您的支持

公共接口IHandler:where T:IDomainEvent
但是,您的接口本身不支持此功能,因为它实际上是反变的。允许这项工作不会是类型安全的,也没有直接的解决方法。协变接口只允许返回
T
,不接受
T
作为方法的参数


有关详细信息,请参见。

您不能从概念上将
IHandler
视为
IHandler
IHandler
需要能够接受
AThirdEvent
(实现
IDomainEvent
)的实例作为
Handle
的参数,但是您的
SomeEventHandler
类型不能接受
AThirdEvent
实例,只能接受
SomeEvent
实例

编译器正确地通知您,从概念角度来看,此类型转换无效


从概念上讲,您的接口实际上是相反的。如果您有一个
IHandler
,您可以隐式地将其转换为
IHandler
(如果您调整接口的定义以通知编译器它实际上是逆变的)因为如果您的
Handle
方法可以接受任何类型的
IDomainEvent
,那么它显然可以接受每一个
SomeEvent

尝试在接口declaration中将T标记为
out
。这看起来像是一个协方差问题。是的,试着用谷歌搜索
协方差
反方差
@BradleyDotNET,那么接口定义将无法编译。这是一个天生的逆变API。@BradleyDotNET不应该在中使用它吗?@TimothyShields是的,接口在概念上是逆变的,而不是协变的,但是他试图在协变的庄园中使用它,所以即使有这种变化,使用门槛也不会起作用。但是接口在其API中不是协变的,它是反向变量。我确实尝试过,但随后出现了以下错误:无效的变量:类型参数“T”在“Testing.IHandler.Handle(T)”上必须反向有效“T”是协变的。@RyanLM是的,因为您的接口在概念上是不协变的,所以这不应该是有效的,编译器并没有告诉您,否则有效的程序是无效的。@RyanLM我更新了以提供详细信息-在我编写它时没有详细了解您试图做什么。基本上,你不能这么做:p@Servy更新内容包括:懒惰,谢谢你指出这一点。谢谢你和所有人的帮助。第一段话让我觉得很有意思。
public interface IHandler<out T> : where T : IDomainEvent