注意:exists in this .NET Fiddle下方的所有代码。
我很难(再次)试图理解泛型/协方差/逆变。 :(
它杀了我 - 所以请善待我。
所以,我有这个虚构的宠物店,我试图轻松在我们的宠物库存中搜索宠物。
主要搜索类SearchMagic
是我所有的格雷夫。我试图说出以下内容:
var pet = searchMagic.SearchForAPet("Fido");
它将......在这种情况下返回一个Dog
即Fido。
现在,踢球者是我实施班级SearchMagic
的方式。这是智能首先搜索Cat
,然后是Dog
的地方。问题是,我似乎无法找到一种方法来返回猫或狗实例,如果找到了。它一直在抱怨Cannot implicitly convert...
我一直试图对代码说:至少,我需要返回SearchResult<IAnimal>
。因此,如果那是具体的Cat
或Dog
,那就太棒了。否则,为null 。然后,对于调用该方法并获取返回结果的代码,我可以对该结果执行的唯一事情是SearchResult<IAnimal>
中定义的任何内容。因此,如果我的Cat
实例具有某些特定于cat的属性或方法,那么运气不好,我无法在result
上调用它们,因为结果是SearchResult<IAnimal>
且仅{ {1}}东西暴露出来。
这里是代码,其中一些注释为INLINE,以显示错误发生的位置......
IAnimal
答案 0 :(得分:2)
如果您希望SearchForAPet
方法能够返回&#34;搜索结果&#34;这可能是一个&#34;狗搜索结果&#34;或者一个&#34; cat搜索结果&#34;,它需要返回一个协变接口,而不是具体类型:
public interface ISearchResult<out TAnimal> where TAnimal: IAnimal
{
TAnimal Pet { get; }
decimal Price { get; }
}
public class SearchResult<TAnimal> : ISearchResult<TAnimal> where TAnimal : IAnimal
{
public TAnimal Pet { get; set; }
public decimal Price { get; set; }
}
...
public ISearchResult<IAnimal> SearchForAPet(string query)
{
...
}
答案 1 :(得分:0)
没有找到任何其他方法来保持结构的完整性。您需要以下内容来获取您的SearchResult:
public interface ISearchResult<out TAnimal> where TAnimal : IAnimal
{
TAnimal Pet { get; }
decimal Price { get; }
}
在任何情况下,如果您想退出out
,您需要在返回时进行相应的投射。
原因是:
这看起来像另一个经典的协方差,逆变和不变性问题。根据{{3}},您可以使用可以使您使用比最初指定的派生类型更多的派生类型,反之亦然,但是您可以预期这样做:
public class Program
{
public static void Main()
{
List<Derived> dlist = new List<Derived>();
List<Base> bIEnum = dlist;
}
}
但是你可以:
public class Program
{
public static void Main()
{
List<Derived> dlist = new List<Derived>();
IEnumerable<Base> bIEnum = dlist;
}
}
因此,拥有ISearchResult或ISearchResult是您最好的选择