需要一些帮助在两个.NET实例之间转换

时间:2014-03-16 23:31:04

标签: c# .net covariance contravariance

我在尝试将一个实例转换为另一个实例类型时遇到问题。我认为,通过继承,这应该有效。

这是错误消息。 (对不起,这很难读 - 在新标签中打开它)

enter image description here

这是上下文。

public interface IItem { ... }

public class AuctionItem : IItem { ... }

public class BuyNowItem : IItem { ... }

public class SearchResult<T> where T : IItem
{
    public IList<T> Items { get; set; }
    public int TotalCount { get; set; }
}

所以我们有两个具体的类,它们都实现了IItem接口和一个包含IItems列表的结果类。

现在,我们如何使用它?我们定义了一个搜索界面......

public interface ISearchService<T, in TU>
    where T : IItem
    where TU : ISearchOptions
{
    string Name { get; }
    Task<SearchResult<T>> SearchAsync(TU searchOptions);
}

所以在这里我们可以看到我们可以搜索某些内容(例如eBay)并返回一些结果(例如IItems)。

我该如何实现?现在,我有一个看起来像这样的疯狂方法....

public class FooSearchService<T, TU> : ISearchService<T, TU>
    where T : AuctionItem, new()
    where TU : AuctionSearchOptions
{
    public async Task<SearchResult<T>> SearchAsync(TU searchOptions) { .. }
}

到目前为止似乎工作得很好....

直到我现在试试这个......

<my console app .. and yes, i'm not awaiting this call, etc...>
private SearchResult<IItem> DoSearches(Notification notification)
{
    if (ebay)
    {
        var searchResult = _ebaySearchService.SearchAsync(auctionSearchOptions);
        return searchResult.Result;  // ** COMPILE ERROR HERE
    }
    else if (somethingElse_eg_BuyNow_1)
    { 
        ... 
        return buyNowSearchResult.Result;
    }
}

看看我想做什么?我想说:搜索ebay并返回AuctionItem搜索结果。或尝试其他服务并返回BuyNowItem的...

我认为,因为ebay返回SearchResult<AuctionItem>,调用方法想要返回SearchResut<IItem>实现的AuctionItem,所以我认为它没问题。但事实并非如此:(

有人可以提供任何帮助吗?

更新

现在几乎完成所有工作:) @jdphenix的答案基本上使它工作。唯一的问题是我正在尝试返回Task<..>但这不起作用。这是...的错误消息..

enter image description here

1 个答案:

答案 0 :(得分:2)

public interface IItem { }

public class AuctionItem : IItem { }

public class BuyNowItem : IItem { }

public interface IResult<out T> where T : IItem {
  IList<IItem> Items { get; set; }
  int TotalCount { get; set; }
}

public class SearchResult<T> : IResult<T> where T : IItem
{
  public IList<IItem> Items { get; set; }
  public int TotalCount { get; set; }
}

您无法从SearchResult<AuctionItem>返回DoSearches(),因为这样就可以了:

List<BuyNowItem> items = new List<SearchResult<BuyNowItem>>();
items.Add(DoSearches()); // Could be a SeachResult<AuctionItem>

界面IResult做了什么?

  • <out T>声明任何实现IResult的类型都会以T作为输出。因此,您可以执行IResult<IItem> result = DoSearches()之类的操作,并且它有效。
  • IList<IItem>代替IList<T>,因为编译器无法证明每个T都是IItem的类型安全转换。对此的更全面的解释将需要一些比我更专业的人。

新的DoSearches()在概念上可能是这样的:

private IResult<IItem> DoSearches(Notification notification) {
  var searchresult = _ebaySearchService.SearchAsync(auctionSearchOptions);
  return searchresult;
}