具有通用接口的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