Search code examples
c#msbuild-15

MSBuild15 CS0121 ambiguous 'List<T>.List(params T[])' and 'List<T>.List(params List<T>[])'


The following code will compile in MSBuild12, but will fail in MSBuild15

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

namespace Example
{
    public class List<T> : IEnumerable<T>
    {
        private readonly T[] _items;

        public List(params T[] items)
        {
            _items = items;
        }

        public List(params List<T>[] args)
        {
            _items = args.SelectMany(t => t).ToArray();
        }

        public static List<T> New
        {
            get { return new List<T>(); }
        }


        public IEnumerator<T> GetEnumerator()
        {
            foreach (var item in _items)
                yield return item;
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return _items.GetEnumerator();
        }
    }
}

Result

CS0121 The call is ambiguous between the following methods or properties: 'List.List(params T[])' and 'List.List(params List[])' Example D:\Example\Test.cs

In MSBuild 12, this constructor is defaulted to. Shows default constructor called


Solution

  • The problem is at the following line:

    public static List<T> New
    {
        get { return new List<T>(); }
    }
    

    and it is caused it's is ambiguous which of the two constructors should be used. You could overcome this by either specifying which one of the two you want to use by providing an appropriate parameter:

    public static List<T> New => new List<T>(new T[]{});
    

    or

    public static List<T> New => new List<T>(new List<T>{});
    

    Another approeach it would be to declare a parameterless constructor

    public List()
    { 
        _items = new T[0];
    }
    

    and then have this:

    public static List<T> New => new List<T>();