我在下面有以下代码。我有两个主要界面IWatch
和IWatchService
。原来Watch()
在IWatchService
中,但没有IWatch
,但是由于CollectionService
无法使用Watch()
方法,我决定(ISP
)创建{还需要{1}}接口。在IWatch
中,我想在ctor中传递CollectionService
或DatabaseWatchService
,因此当在{{1}中时,我仍将参数类型作为RemoteFilesWatchService
放置在ctor中}方法初始化IWatchService<IEntity> watchService
变量,它表示:
无法将类型'RemoteFilesWatchService'隐式转换为 “ IWatchService”。存在显式转换(您是 缺少演员表?)
DoIt()
答案 0 :(得分:6)
这个问题几乎每天都会发布。再有一次!
一盒苹果不是一盒水果。为什么不呢?
您可以将香蕉放入一盒水果中,但是不能将香蕉放入一盒苹果中,因此一盒苹果不是一盒水果,因为您可以对它们执行的操作是不同的。同样,一盒水果不是一盒苹果。
您正尝试使用IWatchService
(苹果)的IFileEntity
(盒子)作为IWatchService
(水果)的IEntity
,这是不合法的。 / p>
现在,您可能会注意到,在C#中,可以在预期IEnumerable<Apple>
的地方使用IEnumerable<Fruit>
。这样做很好,因为无法将香蕉放入IEnumerable<Fruit>
中。在IEnumerable<T>
和IEnumerator<T>
的每个成员中,T
都是 ,而不是 in 。
如果您处于这种情况,则可以将界面标记为
interface IWatchService<out T> ...
编译器将验证接口中的每个T
是否都在“出”位置使用,然后允许您进行所需的转换。
该转换称为通用协变转换,仅在以下情况下可用:
out
,编译器会验证该参数是否安全答案 1 :(得分:2)
您的RemoteFilesWatchService
实现了接口IWatchService<IFileEntity>
,而您的CollectionService
则期望IWatchService<IEntity>
。两种类型不同,这就是为什么它不能转换。
修改您的CollectionService
使其接受IWatchService<IFileEntity>
,或使RemoteFilesWatchService
实现IRemoteFilesWatchService<IEntity>
。或改为在CollectionService
中使用非通用接口。
您不能拥有IWatchService<IFileEntity>
并将其视为IWatchService<IEntity>
。例如,将其与List<T>
进行比较。您不能期望能够做到这一点:
class Animal {}
class Bird : Animal {}
class Elephant : Animal {}
var birds = new List<Bird>();
// compiler does not allow this...
List<Animal> animals = birds;
// ...because there is no point in adding elephants to a list of birds.
animals.Add(new Elephant());
答案 2 :(得分:0)
进行一些小的更改以获取差异支持,应该按以下步骤解决您的问题:
public interface IEntity
{
}
public interface IFileEntity : IEntity
{
...
}
public interface IWatchService<out TDataEntity> where TDataEntity : IEntity //note the "out" keyword here.
{
}
您可以在通用接口Here
中了解有关差异的更多信息