1

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?

Mechanic Pig
  • 6,756
  • 3
  • 10
  • 31
  • 6
    [Cannot reproduce](https://dotnetfiddle.net/SP4iyY). Note that `T?` as a generic type parameter when nullable reference types are enabled means "defaultable", not "nullable". When `T` is unconstrained, this means effectively "When `T` is a reference type, this can be null. When `T` is a value type, this has no meaning". If you constrain `T` to be a value type, the meaning changes, and `T?` then means `Nullable` – canton7 Jan 20 '22 at 17:22

1 Answers1

1

@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

Olivier Jacot-Descombes
  • 104,806
  • 13
  • 138
  • 188