Why does this work:
public IList<ICoupon> GetCouponsForSite(string siteSlug)
{
var coupons = _db.Coupons.Where(x => x.Site.slug == siteSlug)
.Select(x => new Coupon(x.id));
var list = new List<ICoupon>();
foreach (var coupon in coupons)
{
list.Add(coupon);
}
return list;
}
But this does does not work (error - cannot convert expression type to return type):
public IList<ICoupon> GetCouponsForSite(string siteSlug)
{
return _db.Coupons.Where(x => x.Site.slug == siteSlug)
.Select(x => new Coupon(x.id)).ToList();
}
Because db.Coupons...ToList() returns an IList<Coupon>
rather than an IList<ICoupon>
. IList<Coupon>
does not derive from IList<ICoupon>
because C# 3 doesn't support generic variance. (C# 4 does support generic variance, but it still won't derive in this case. Consider that whoever receives an IList<ICoupon>
could try to stuff a SomeEvilTypeThatImplementsICoupon into it. But an IList<Coupon>
couldn't accept that because SomeEvilTypeThatImplementsICoupon doesn't derive from Coupon. See http://hestia.typepad.com/flatlander/2008/12/c-covariance-and-contravariance-by-example.html for discussion of this convertibility issue albeit in a slightly different context, and the Eric Lippert articles linked from there.)
(Your first snippet, by contrast, explicitly constructs a List<ICoupon>
, which can contain anything that implements ICoupon, and then puts some Coupon objects into that list. Now if the receiver decides to poke SomeEvilTypeThatImplementsICoupon into it, all is well, because the List was built to hold any ICoupon, not just actual Coupon objects.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With