Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot cast a generic type to list in C#

Tags:

c#

generics

I am trying to do a simple test, in which I pass in two generic objects to a test function, see if they can be cast to List<S>, and further, check if the counts of the lists are equal.

The following code works:

private static void Test<T> (T obj1, T obj2) {
    if (typeof(T).IsGenericType) {
        var genericTypeParam1 = typeof(T).GetGenericArguments().First();
        Console.WriteLine(genericTypeParam1);

        // LINE MARKER 1
        // var obj1AsList = (obj1 as IEnumerable<genericTypeParam1>);
    }
}

static void Main(string[] args) {
    Test(Enumerable.Range(0, 5).ToList(), Enumerable.Range(0, 5).ToList());
    Console.ReadLine();
}

But if I uncomment the line marked with LINE MARKER 1, I get the following error:

The type or namespace name 'genericTypeParam1' could not be found (are you missing a using directive or an assembly reference?)

I do not know beforehand that Test will receive Lists. But my intention is to first check if obj1 and obj2 can be taken as lists, and then to compare

var obj1AsList = obj1 as List<genericTypeParam1>;
var obj2AsList = obj2 as List<genericTypeParam1>;
var flag = (obj1AsList != null) && (obj2AsList != null) && (obj1AsList.Count() == obj2AsList.Count());

Thanks in advance for your help.

like image 644
Shredderroy Avatar asked Jan 08 '14 04:01

Shredderroy


2 Answers

I am trying to do a simple test, in which I pass in two objects to a test function, see if they can be cast to List<S>, and further, check if the counts of the lists are equal.

The correct way to do that is:

static bool Test<T>(object obj1, object obj2)
{
    List<T> list1 = obj1 as List<T>;
    List<T> list2 = obj2 as List<T>;
    return list1 != null && list2 != null && list1.Count == list2.Count;
}
...
bool result = Test<int>(Enumerable.Range(0, 5).ToList(), Enumerable.Range(0, 5).ToList());

This takes two objects and a type, and returns true if the objects are equally-sized lists of that type.

like image 60
Eric Lippert Avatar answered Sep 22 '22 07:09

Eric Lippert


Type provided as generic type parameter has to be known at compile time. You're trying to pass Type typed variable instead, and that's why you're getting compile type error.

You can make the fact, that only List<T> instances can be passed as method parameters check by compiler during compilation time:

private static void Test<T>(List<T> obj1, List<T> obj2)
{
    var flag = obj1 != null && obj2 != null && obj1.Count == obj2.Count;
}

If you want that test to be done during runtime you should use solution provided by Eric.

like image 35
MarcinJuraszek Avatar answered Sep 22 '22 07:09

MarcinJuraszek