Search code examples
c#genericsnullabletype-mismatch

About Nullable of C# generic parameter


Now I have a SomeClass<T> with a constructor SomeClass(IList<T?> list). But when I use a List<int?> to construct it, the compiler told me:

Cannot resolve constructor SomeClass(System.Collections.Generic.List<System.Nullable<int>>), candidates are: SomeClass(System.Collections.Generic.IList<int>)

I find it means that I have to add "struct" to T's base class list to make sure that T is a value type, but why does this happen and how can make this class avoid using only value type as generic parameter?


Solution

  • @canton7 explains why this does not work in a comment.

    You cannot solve this with a constructor, as you will have to introduce a new type parameter and constructors cannot declare type parameters. Therefore I suggest using a factory method.

    public class SomeClass<T>
    {
        public IList<T> List { get; private set; }
    
        public static SomeClass<T> Create<U>(IList<Nullable<U>> list)
            where U : struct, T
        {
            return new SomeClass<T> {
                List = list
                    .OfType<T>()
                    .ToList()
            };
        }
    }
    

    Introducing the type parameter U allows us to add a type constraint that is limited to this method, while the type parameter T of the class remains unconstrained.

    Note that a null value does not have a type. Therefore, OfType<T>() filters out nulls.

    You can test it like this:

    var ints = new List<int?> { 1, 2, null, 3 };
    var sut = SomeClass<int>.Create(ints);
    foreach (int item in sut.List) {
        Console.WriteLine(item);
    }
    

    Prints:

    1
    2
    3