接口无法隐式转换类型

时间:2019-03-26 12:31:44

标签: c#

我在下面有以下代码。我有两个主要界面IWatchIWatchService。原来Watch()IWatchService中,但没有IWatch,但是由于CollectionService无法使用Watch()方法,我决定(ISP)创建{还需要{1}}接口。在IWatch中,我想在ctor中传递CollectionServiceDatabaseWatchService,因此当在{{1}中时,我仍将参数类型作为RemoteFilesWatchService放置在ctor中}方法初始化IWatchService<IEntity> watchService变量,它表示:

  

无法将类型'RemoteFilesWatchService'隐式转换为   “ IWatchService”。存在显式转换(您是   缺少演员表?)

DoIt()

3 个答案:

答案 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,编译器会验证该参数是否安全
  • 各种类型(例如水果和苹果)都是参考类型。例如,您不能进行涉及int和object的协变转换。

答案 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

中了解有关差异的更多信息