开发者

.NET Generics Question

开发者 https://www.devze.com 2023-03-23 13:37 出处:网络
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.

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);
0

精彩评论

暂无评论...
验证码 换一张
取 消