【问题标题】:Need some help converting between two .NET instances需要一些帮助在两个 .NET 实例之间进行转换
【发布时间】:2014-03-16 23:31:04
【问题描述】:

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

这是错误消息。 (抱歉阅读困难 - 在新标签页中打开)

这是上下文。

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; }
}

所以我们有 2 个具体的类,它们都实现了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's ...

我想,因为 ebay 返回一个SearchResult&lt;AuctionItem&gt;,所以调用方法想要返回一个SearchResut&lt;IItem&gt;,这是AuctionItem 实现的,所以我认为它会没问题。但这不是:(

谁能提供帮助?

更新

现在几乎可以正常工作了 :) @jdphenix 的回答基本上使它正常工作。唯一的问题是我正在尝试返回 Task&lt;..&gt; 但这不起作用。这是错误消息..

【问题讨论】:

  • 不要太仔细地猜测你的问题:看看Covariance and Contravariance in Generics
  • 要添加到@poke 的指针,请尝试ISearchService&lt;out T, in TU&gt;FooSearchService&lt;out T, in TU&gt;
  • @Noseratio 只有接口可以用协变和逆变来声明。
  • @Lukazoid,正确,我忽略了FooSearchService&lt;out T, in TU&gt; 不是接口。所以需要做一个接口IFooSearchService&lt;out T, in TU&gt;,然后FooSearchService应该派生出来。
  • 我总是忘记 DNF.net !很棒的伙伴:)会做的!

标签: c# .net covariance contravariance


【解决方案1】:
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; }
}

您无法从DoSearches() 返回SearchResult&lt;AuctionItem&gt;,因为这样是可能的:

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

接口IResult是做什么的?

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

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

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

【讨论】:

  • var searchresult = _ebaySearchService();
  • @Pure.Krome 对不起,我不明白你的问题,_ebaySearchService() 只是我使用的一个虚拟方法,它的签名是private SearchResult&lt;AuctionItem&gt; _ebaySearchService()
  • 我现在差不多知道了...请告诉我如何将结果添加到Task 的列表中吗?所以我可以做Task.WhenAll(tasks);
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-12-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-12
  • 1970-01-01
相关资源
最近更新 更多