Can someone please explain why I am getting a compile error asking for an explicit cast? Since I'm constraining the output, I thought this would be allowed without any开发者_Go百科 brute force.
** THANK YOU EVERYONE. IT WAS CONFUSING THE WAY I PRESENTED THE QUESTION. **
public interface IQuery<TInput, TOutput>
{
TOutput Execute(TInput input);
}
public abstract class PagedQuery<TInput, TOutput> : IQuery<TInput, TOutput>
where TOutput : IEnumerable<TOutput>
{
public TOutput Execute(TInput input)
{
return Enumerable.Empty<TOutput>(); // error here..
}
}
Enumerable.Empty<TOutput>()
returns an implementation of IEnumerable<TOutput>
. Just because TOutput
also implements IEnumerable<TOutput>
doesn't mean that you can convert any IEnumerable<TOutput>
value to TOutput
.
I agree with the commentators who say that constraining TOutput
to return a sequence of itself is pretty odd, by the way.
I suspect you actually want something like this:
public abstract class PagedQuery<TInput, TElement>
: IQuery<TInput, IEnumerable<TElement>>
{
public IEnumerable<TElement> Execute(TInput input)
{
return Enumerable.Empty<TElement>();
}
}
That makes a lot more sense to me.
EDIT: I've renamed the type parameter to make it clearer. So for IQuery<,>
, TOutput=IEnumerable<TElement>
- so a PagedQuery
returns a sequence of elements, not a sequence of pages, each of which itself is a sequence of pages, each of which itself is a sequence of pages ad infinitum.
The compiler is expecting you to return TOutput
instead of an IEnumerable<TOutput>
, it doesn't matter that your constraint specifies that TOutput
inherits from IEnumerable<TOutput>
, as the types aren't the same.
If you can, changing the type in the interface and abstract class on the Execute
method to IEnumerable<TOutput>
solves the compiler issue.
Consider moving TOutput to be the payload of the IEnumerable you're returning:
public interface IQuery<TInput, TOutput>
{
IEnumerable<TOutput> Execute(TInput input);
}
public abstract class PagedQuery<TInput, TOutput> : IQuery<TInput, TOutput>
{
public IEnumerable<TOutput> Execute(TInput input)
{
return Enumerable.Empty<TOutput>();
}
}
I think what you try to do is create a generic class PagedQuery
where the output is always enumerable, while the generic IQuery
interface doesn't necessarily produce enumerable ouput.
I guess you could write this to accomplish that:
// Define other methods and classes here
public interface IQuery<TInput, TOutput>
{
TOutput Execute(TInput input);
}
public class PagedQuery<TInput, TOutput> : IQuery<TInput, IEnumerable<TOutput>>
{
public IEnumerable<TOutput> Execute(TInput input)
{
return Enumerable.Empty<TOutput>();
}
}
Now you can write
var query = new PagedQuery<int, int>();
IEnumerable<int> output = query.Execute(0);
精彩评论