private static void PrintEachItemInList<T>(T anyList)
Where T:System.Collections.Generic.List<T>
{
foreach (var t in T)
{
//Do whatever
}
}
In the above code (which is wrong) all I want to do it to set a constraint that T
is a List.
The aim is not to get this example to work, the aim is to understand how can I set a constraint that the type is a list? I am an amateur in generics and am trying to figure things out :(
Maybe you want two type parameters, as in:
private static void PrintEachItemInList<TList, TItem>(TList anyType)
where TList : System.Collections.Generic.List<TItem>
This is useful if you use classes that actually derive from List<>
. If you want anything that acts as a list, consider constraining to the interface IList<>
instead. It will then work for List<>
, single-dimensional arrays, and custom classes implementing the interface (but not necessarily deriving from List<>
).
Edit: As pointed out by the comment, this method is cumbersome to use because the compiler will not infer the two type arguments, so they will have to be given explicitly when calling the method.
Consider just using:
private static void PrintEachItemInList<TItem>(List<TItem> anyType)
Because anything which derives from a List<>
is assignable to List<>
, the method can be called with derived classes as arguments, and in many cases the type TItem
can be inferred automatically by the compiler.
Still consider using the interface IList<>
.
If all you want to do, is read from the list, use IReadOnlyList<TItem>
instead of IList<TItem>
. This signals to the caller that you won't change his list. Still no cast syntax is required when calling, for example: PrintEachItemInList(new[] { 2, 3, 5, 7, });
. The type IReadOnlyList<>
is new in .NET version 4.5.
If all you want to do is read from the list, and you don't want to use the indexer (no anyType[idx]
), and you don't want to use the .Count
property, and in fact, all you want to do is foreach
through the list, use IEnumerable<TItem>
. Again, you signal that you won't change people's lists.
Both IReadOnlyList<>
and IEnumerable<>
are covariant in their generic argument (type parameter).
Declare your input parameter as IList<T>
. If you want to make your input sequence as abstract as possible - use IEnumerable<T>
instead of IList<T>
private static void PrintEachItemInList<T>(IList<T> sequence)
{
foreach (T element in sequence)
{
//Do whatever
}
}
Your function should simply accept a list, and you don't need a constraint:
private static void PrintEachItemInList<T>(IList<T> list)
{
foreach (var t in list)
{
//Do whatever
}
}
However, if you only want to iterate the list you can make your code more general by changing the parameter type to one of these base interfaces:
IEnumerable<T>
- allows foreach
IReadOnlyCollection
- same as above and provides the count of elements in the collectionIReadOnlyList
- same as above and allows element access by indexICollection<T>
- an IEnumerable<T>
that provides an element count and methods to add and remove elementsIList<T>
- same as above and allows you to add and remove elements by indexIf you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With