While doing a code review I noticed the following code inside an ASP.NET(Core) controller:
// GET api/products | |
[HttpGet] | |
public ActionResult<IEnumerable<Product>> Get() | |
{ | |
_logger.LogInformation("Getting all products"); | |
using (var uow = _unitOfWorkFactory.Create()) | |
{ | |
var products = _repository.GetProducts(); | |
return products; | |
} | |
} |
public interface IProductRepository: IRepository<Product> | |
{ | |
List<Product> GetProducts(); | |
} |
Do you notice something special?
No? Let’s give you a hint. Take a look at the return type; ActionResult<IEnumerable<Product>> and then take a look at the type that is actually returned; List<Product>. Although both types don’t match this code compiles and runs perfectly.
What is the magic happening that is happening here? This all works thanks to the fact the ActionResult<T> type supports implicit casting.
Now what happens if we update the code to the following:
[HttpGet] | |
public ActionResult<IEnumerable<Product>> Get() | |
{ | |
_logger.LogInformation("Getting all products"); | |
using (var uow = _unitOfWorkFactory.Create()) | |
{ | |
var products = _repository | |
.GetProducts() | |
.Where(p=> p.Discontinued=false); | |
return products; | |
} | |
} |
public interface IProductRepository: IRepository<Product> | |
{ | |
List<Product> GetProducts(); | |
} |
This time you get a compiler exception:
|
Whoops! Why this no longer works?
The reason is that where before we were returning a concrete type (List<T>), now we are returning an interface (IEnumerable<T>). C# doesn't support implicit cast operators on interfaces.
To fix this we can add a ToList() to convert the interface to a concrete type.