问题描述
我确实想知道为什么不允许这种构造
public interface IComplexDecorator<Item,Component> : IComponent<Item>
where Component : IComplexComponent<Item,IComplexDecorator<Item,Component>>
{
}
public interface IComplexComponent<Item,Decorator> : IComponent<Item>
where Decorator : IComplexDecorator<Item,IComplexComponent<Item,Decorator>>
{
}
public interface IComponent<Item>
{
}
装饰器错误消息
IComplexDecorator
- '不能用作类型参数 通用类型或方法“ IComplexComponent
- 。没有来自的隐式引用转换 'Component.IComplexDecorator
- '到 'Component.IComplexDecorator
- >>'。
组件错误消息
'Component.IComplexComponent
- '不能用作类型参数'Component' 泛型类型或方法'IComplexDecorator
- '。有 没有来自的隐式引用转换 'Component.IComplexComponent '至 'Component.IComplexComponent >>'
解决方法
您的示例太复杂而无法使用,但是我在想的是问题不在于循环引用本身,而在于循环引用导致了什么。因此,让我们考虑以下示例:
public interface IBaseManager<TComponent>
where TComponent : IBaseComponent<TComponent>
{ }
public interface IBaseComponent<TManager>
where TManager : IBaseManager<TManager>
{ }
如果添加具体的类来实现接口,则更容易理解:
public class Manager : IBaseManager<Component> { }
public class Component : IBaseComponent<Manager> { }
如果您查看IBaseManager<Component>
中的TComponent
和IBaseManager
的类型约束,您会发现TComponent
应该隐式转换为{{1} },其中IBaseComponent<TComponent>
是我们的课程TComponent
。因此,事实证明应该将Component
强制转换为Component
,但是我们的IBaseComponent<Component>
仅实现Component
。因此无法进行投射。
您可以说IBaseComponent<Manager>
可以实现接口Component
,但也会导致相同的问题,因此,如果您想了解为什么它,我鼓励您尝试一下。不起作用。
就像我之前说的,如果您使用它,您将了解添加第二个接口的实现无济于事,因此可以通过添加第二个通用参数来解决问题。
IBaseComponent<Component>
现在,如果遵循相同的逻辑,我们将看到 public interface IBaseManager<TComponent,TManager>
where TComponent : IBaseComponent<TComponent,TManager>
where TManager : IBaseManager<TComponent,TManager>
{}
public interface IBaseComponent<TComponent,TManager>
{}
public class Manager : IBaseManager<Component,Manager> { }
public class Component : IBaseComponent<Component,Manager> { }
(在我们的示例中为TComponent
)应隐式转换为Component
(即IBaseComponent<TComponent,TManager>
在我们的示例中),这就是我们所拥有的。我们的IBaseComponent<Component,Manager>
实现了Component
。
您还可以查看以下question,其中Jon Skeet显示了如何解决问题(我实际上从问题中举了一些例子):
,我能够使用第3个泛型解决此问题。但是由于第三个通用解决方案还包含循环谓词,所以我不确定为什么它真正起作用。
public interface IComplexDecorator<Item,Component,Decorator> : IComponent<Item>
where Component : IComplexComponent<Item,Decorator,Component>
where Decorator : IComplexDecorator<Item,Decorator>
{
}
public interface IComplexComponent<Item,Component> : IComponent<Item>
where Decorator : IComplexDecorator<Item,Decorator>
where Component : IComplexComponent<Item,Component>
{
}