I'm having trouble trying to convert one instance to another instance type. I thought, via inheritence, that this should just work.
Here's the error message. (sorry it's hard to read - open it in a new tab)
And here's the context.
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; }
}
So we have 2 concrete classes, which both implement the IItem
interface and a result class which contains a list of IItems
.
Now, how do we use this? We define a searching interface...
public interface ISearchService<T, in TU>
where T : IItem
where TU : ISearchOptions
{
string Name { get; }
Task<SearchResult<T>> SearchAsync(TU searchOptions);
}
So here we can see that we can search something (eg. eBay) and it will return some results (eg IItems
).
How do I implement this? Now, I have a crazy method that looks like this....
public class FooSearchService<T, TU> : ISearchService<T, TU>
where T : AuctionItem, new()
where TU : AuctionSearchOptions
{
public async Task<SearchResult<T>> SearchAsync(TU searchOptions) { .. }
}
Seems to be working fine so far ....
Until i now try this ....
<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;
}
}
See what I'm trying to do? I'm trying to say: Search ebay and return the AuctionItem
search results. Or try another service and return their BuyNowItem
's ...
I thought that, because the ebay returns a SearchResult<AuctionItem>
, the calling method wants to return a SearchResut<IItem>
which AuctionItem
implements, so I assumed it would be ok. But it's not :(
Can anyone offer any assistance?
Nearly got it all working now :) The answer from @jdphenix basically made it work. The only problem is that I'm trying to return a Task<..>
and that's not working. Here's the error message for that..
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; }
}
You are unable to return a SearchResult<AuctionItem>
from DoSearches()
because then this would be possible:
List<BuyNowItem> items = new List<SearchResult<BuyNowItem>>();
items.Add(DoSearches()); // Could be a SeachResult<AuctionItem>
What does the interface IResult
do?
<out T>
declares that any type implementing IResult
will have T
as an output. Consequently, you can do something like IResult<IItem> result = DoSearches()
and it be valid. IList<IItem>
instead of IList<T>
because the compiler can't prove that every T
would be a type safe conversion to IItem
. The fuller explanation of this would require someone which much more expertise than me. A new DoSearches()
could conceptually be this:
private IResult<IItem> DoSearches(Notification notification) {
var searchresult = _ebaySearchService.SearchAsync(auctionSearchOptions);
return searchresult;
}