gpt4 book ai didi

c# - 接口(interface)不能隐式转换类型

转载 作者:太空宇宙 更新时间:2023-11-03 18:01:57 25 4
gpt4 key购买 nike

我在下面有以下代码。我有两个主要接口(interface)IWatchIWatchService .原来Watch()IWatchService并且没有 IWatch但自那以后CollectionService不能使用 Watch()我决定 ( ISP ) 创建 IWatch 的方法接口(interface)另外。在CollectionService我想要 ctor pass DatabaseWatchServiceRemoteFilesWatchService因此,我将参数类型作为 IWatchService<IEntity> watchService 放在 ctor 中然而当在DoIt()方法初始化 fileWatcherServiceCsv它说的变量:

Cannot implicitly convert type 'RemoteFilesWatchService' to 'IWatchService'. An explicit conversion exists (are you missing a cast?)

public interface IWatch
{
void Watch();
}

public interface IWatchService<TDataEntity> where TDataEntity : IEntity
{
INotificationFactory NotificationFactory { get; }
ObservableCollection<TDataEntity> MatchingEntries { get; set; }
}

public interface IDatabaseWatchService<TDataEntity> : IWatchService<TDataEntity> where TDataEntity : IDatabaseEntity
{
IDatabaseRepository<IDbManager> DatabaseRepository { get; }
}

public interface IRemoteFilesWatchService<TDataEntity> : IWatchService<TDataEntity> where TDataEntity : IFileEntity
{
List<string> ExistingRemoteFiles { get; set; }
List<RemoteLocation> RemoteLocations { get; set; }
IWinScpOperations RemoteManager { get; set; }
IRemoteFilesRepository<IDbManager, TDataEntity> RemoteFilesRepository { get; }
}

public class RemoteFilesWatchService : IRemoteFilesWatchService<IFileEntity>, IWatch
{
public INotificationFactory NotificationFactory { get; }
public ObservableCollection<IFileEntity> MatchingEntries { get; set; }
public List<string> ExistingRemoteFiles { get; set; }
public List<RemoteLocation> RemoteLocations { get; set; }
public IWinScpOperations RemoteManager { get; set; }
public IRemoteFilesRepository<IDbManager, IFileEntity> RemoteFilesRepository { get; }

public RemoteFilesWatchService(IWinScpOperations remoteOperator,
IRemoteFilesRepository<IDbManager, IFileEntity> remoteFilesRepository,
INotificationFactory notificationFactory)
{
RemoteManager = remoteOperator;
RemoteFilesRepository = remoteFilesRepository; //csv, xml or other repo could be injected
NotificationFactory = notificationFactory;
}

public void Watch()
{
}
}

public class DatabaseWatchService : IDatabaseWatchService<DatabaseQuery>, IWatch
{
public INotificationFactory NotificationFactory { get; }
public ObservableCollection<DatabaseQuery> MatchingEntries { get; set; }
public IDatabaseRepository<IDbManager> DatabaseRepository { get; }

public DatabaseWatchService(IDatabaseRepository<IDbManager> databaseRepository,
INotificationFactory notificationFactory)
{
DatabaseRepository = databaseRepository;
NotificationFactory = notificationFactory;
}

public void Watch()
{
}
}

public class CollectionService
{
private IWatchService<IEntity> _watchService;

public CollectionService(IWatchService<IEntity> watchService)
{
_watchService = watchService;
}
}

class Run
{
void DoIt()
{
IWatchService<IEntity> fileWatcherServiceCsv = new RemoteFilesWatchService(new WinScpOperations(),
new RemoteCsvFilesRepository(new DbManager(ConnectionDbType.MySql)),
new NotificationFactory());

var coll1 = new CollectionService(fileWatcherServiceCsv);
}
}

public interface IEntity
{
}


public interface IFileEntity : IEntity
{
int Id { get; set; }
string Name { get; set; }
bool IsActive { get; set; }
bool RemoveFromSource { get; set; }
string DestinationFolder { get; set; }
RemoteLocation RemoteLocation { get; set; }
}

public interface IDatabaseEntity : IEntity
{
}

public class CsvFile : IFileEntity
{
public int ColumnHeader { get; set; }
public int ColumnsCount { get; set; }
public string Separator { get; set; }
public int ValuesRowStartposition { get; set; }
public int ColumnRowPosition { get; set; }
public int Id { get; set; }
public string Name { get; set; }
public bool IsActive { get; set; }
public bool RemoveFromSource { get; set; }
public string DestinationFolder { get; set; }
public RemoteLocation RemoteLocation { get; set; }
}

public class XmlFile : IFileEntity
{
public int Id { get; set; }
public string Name { get; set; }
public bool IsActive { get; set; }
public bool RemoveFromSource { get; set; }
public string DestinationFolder { get; set; }
public RemoteLocation RemoteLocation { get; set; }
public string SubNode { get; set; }
public string MainNode { get; set; }
}

最佳答案

这个问题几乎每天都会被发布。再来一次!

一盒苹果不是一盒水果。为什么不呢?

你可以把一根香蕉放进一盒水果里,但你不能把一根香蕉放进一盒苹果里,所以一盒苹果不是一盒水果,因为你能对它们进行的操作是不同的。同样,一盒水果不是一盒苹果。

您正在尝试使用 IWatchService (盒)IFileEntity (苹果)作为 IWatchServiceIEntity (水果),这是不合法的。

现在,您可能会注意到在 C# 中您可以使用 IEnumerable<Apple>哪里有IEnumerable<Fruit>是期待。这很好用,因为 没有办法将香蕉放入 IEnumerable<Fruit>。在IEnumerable<T>的每个成员中和 IEnumerator<T> , T 出来,而不是进来

如果您处于那种情况,那么您可以将您的界面标记为

interface IWatchService<out T> ... 

并且编译器将验证每个T在界面中使用在“out”位置,然后将允许您想要的转换。

该转换称为通用协变转换,它仅在以下情况下有效:

  • 泛型是接口(interface)或委托(delegate)
  • 类型参数标记为out , 编译器验证它是安全的
  • 变体类型(比如 Fruit 和 Apple)都是引用类型。例如,您不能进行涉及 int 和对象的协变转换。

关于c# - 接口(interface)不能隐式转换类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55357270/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com