Reputation: 249
I have a problem with the signature of generic method that I am trying to create.
The class is as follows:
public class MarketDataRepository : IRepository
{
MarketWatchEntities _dbContext = new MarketWatchEntities();
public MarketDataRepository(){}
public MarketDataRepository(MarketWatchEntities dbContext)
{
_dbContext = dbContext;
}
public IEnumerable<T> GetMarketData<T>(DateTime startDateTime, DateTime endDateTime ) where T : MarketDataPoint
{
return _dbContext.MarketDataPoints.Where(x => x.ReferenceDateTime >= startDateTime && x.ReferenceDateTime <= endDateTime).ToList();
}
}
public interface IRepository
{
IEnumerable<T> GetMarketData<T>(DateTime startDateTime, DateTime endDateTime) where T : MarketDataPoint;
}
Additional information:
MarketWatchEntities
extends DbContext
(generated by Entity Framework).
I get this compile time exception:
Cannot implicitly convert type 'System.Collections.Generic.List<MarketWatcher.Domain.MarketDataPoint>' to 'System.Collections.Generic.IEnumerable<T>'. An explicit conversion exists (are you missing a cast?)
I was expecting this to be OK on the basis that I'm constraining T
to be inherited from MarketDataPoint
. So, I thought I would be able to return an IEnumerable
of MarketDataPoint
.
Any pointers as to what is wrong with the above and what I should do instead would be hugely appreciated!
Solution (Thanks Everyone):
public class MarketDataMarketDataRepository : IMarketDataRepository
{
MarketWatchEntities _dbContext = new MarketWatchEntities();
public MarketDataMarketDataRepository(){}
public MarketDataMarketDataRepository(MarketWatchEntities dbContext)
{
_dbContext = dbContext;
}
public IQueryable<T> GetMarketData<T>(DateTime startDateTime, DateTime endDateTime ) where T : MarketDataPoint
{
return _dbContext.MarketDataPoints.Where(x => x.ReferenceDateTime >= startDateTime && x.ReferenceDateTime <= endDateTime).OfType<T>();
}
}
Upvotes: 0
Views: 730
Reputation: 50114
The reason this doesn't work is because T
can be more specific than MarketDataPoint
.
If you have class S
that derives from MarketDataPoint
and someone calls GetMarketData<S>
, how can you give them an IEnumerable<S>
when all you have is a collection of MarketDataPoint
s?
EDIT: As Matt himself points out, you can chain a call to OfType<T>()
that will weed out the non-T
elements and return the correct type of IEnumerable
.
return _dbContext.MarketDataPoints
.Where(
x => x.ReferenceDateTime >= startDateTime &&
x.ReferenceDateTime <= endDateTime)
.OfType<T>()
.ToList();
Upvotes: 5
Reputation: 21004
And if you follow the error and manually cast it IEnumerable<T>
?
public IEnumerable<T> GetMarketData<T>(DateTime startDateTime, DateTime endDateTime) where T : MarketDataPoint
{
return (IEnumerable<T>)_dbContext.MarketDataPoints.Where(x => x.ReferenceDateTime >= startDateTime && x.ReferenceDateTime <= endDateTime).ToList();
}
The problem is that IEnumerable<MarketDataPoint>
is not the same as IEnumerable<T>
.
Upvotes: 0