GKalnytskyi
GKalnytskyi

Reputation: 629

Jagged array T[][] to IEnumerable<T[]>

I'm trying to understand why implicit conversion in the following code causes StackOverflowException. I think it is a covariance/contravariance issue, but I cannot explain why at the moment.

Crashes NUnit:

private List<T[]> _NodesContent = new List<T[]>();
private UnrolledLinkedListBuilder<T> AddNodes(IEnumerable<T[]> nodes)
{
    _NodesContent.AddRange(nodes);
    return this;
}

public UnrolledLinkedListBuilder<T> AddNodes(params T[][] nodes)
{
    return AddNodes(nodes);
}

Works:

private List<T[]> _NodesContent = new List<T[]>();
private UnrolledLinkedListBuilder<T> AddNodes(IEnumerable<T[]> nodes)
{
    _NodesContent.AddRange(nodes);
    return this;
}

public UnrolledLinkedListBuilder<T> AddNodes(params T[][] nodes)
{
    return AddNodes((IEnumerable<T[])nodes);
}

As I understand from this answer https://stackoverflow.com/a/275107/761755 conversion should be performed implicitly. Moreover, if in the first example you directly call _NodesContent.AddRange(nodes) from AddNodes(T[][]) there will be no exception.

Upvotes: 0

Views: 323

Answers (1)

Tim Schmelter
Tim Schmelter

Reputation: 460058

I'm trying to understand why implicit conversion in the following code causes StackOverflowException.

Well, there is no implicit conversion necessary. But isn't it obvious? Your first method calls itself because you pass the argument as it is:

public UnrolledLinkedListBuilder<T> AddNodes(params T[][] nodes)
{
    return AddNodes(nodes);
}

It was a compiler bug if that would not cause a StackOverflowException in any case:

public SomeReturnType AnyMethod(AnyType x)
{
    return AnyMethod(x); // StackOverflowException
}

It doesn't matter that the parameter is using params because it's not possible to have another method with the same parameter type without params because that was ambiguous. So this will always be the best candidate.

Upvotes: 1

Related Questions