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?
@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