【发布时间】:2014-04-13 05:25:20
【问题描述】:
我正在尝试模拟一个lastminute.com.au 克隆。当我尝试创建IProductSearchServices 的集合时,我得到所有关于(我猜)方差与协方差等的奇怪错误。
我认为如果任何具体类型实现相同的接口并且集合被强类型化到相同的接口,我可以任何具体类型(集合)。
这是我正在尝试做的代码。
private static void Main(string[] args)
{
// Expected: 3 services in this list.
var productServices = CreateProductServices();
// Return all Hotel services.
// Expected: 2 items in this list.
var hotelServices = productServices.OfType<??????>();
// for each hotel service, call SearchAsync.
// wait for all the finish before continuing....
Console.WriteLine("Found {0} products.", ....);
}
// Full code found in gist....
这是我的主要错误信息:
那么问题出在哪里?
- 尝试将 3 个搜索服务添加到集合中。
- 鉴于该列表,我不知道该怎么说:给我所有的酒店服务,这样我就可以
SearchAsync他们。
注意:我不想使用dynamic 等。我想尝试将其用作强类型集合等。
【问题讨论】:
-
这里的一个问题是
Task<T>是一个类,而不是一个接口。协方差只能在接口上实现,因此Task<Derived>不能转换为Task<Base>。您可以通过使用IObservable而不是Task来解决此问题,Task是协变的,并提供类似的功能。此外,IList不是协变的,因此您可以改用IEnumerable。 -
然而,最大的问题是
TSearchOptions,它是逆变的。IProductSearchService<T, HotelSearchOptions>可以分配给IProductSearchService<T, ISearchOptions>是不正确的,因为前者需要SearchAsync中的更多 特定参数,而不是不太特定的参数。因此,IProductSearchService的列表没有意义。 -
嗨@RuudvA - 谢谢你看这个。不过,我不明白你在说什么 :( 我并不是说你错了——我只是不明白。我认为我的 derived 类
HotelProductSearchService1是两个泛型两者都是派生的。因此,如果两者都是派生的,那么两者都应该自动转换为它们的基数?我很困惑。有什么代码可以帮助吗? -
其他人已经提到协方差等。如果您需要在两种类型的列表之间进行转换,一种快速而肮脏的方法是使用“productServices.Cast
()”() 可以抛出无效的强制转换异常,但不应该。