简体   繁体   English

无法在C#中将通用类型转换为列表

[英]Cannot cast a generic type to list in C#

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. 我正在尝试进行一个简单的测试,在其中我将两个通用对象传递给测试函数,看看它们是否可以转换为List<S> ,并进一步检查列表的计数是否相等。

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: 但如果我取消注释标有LINE MARKER 1 ,我会收到以下错误:

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 List s. 我事先不知道Test会收到List But my intention is to first check if obj1 and obj2 can be taken as lists, and then to compare 但我的目的是首先检查obj1obj2可以作为列表,然后进行比较

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. 在此先感谢您的帮助。

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. 我正在尝试进行一个简单的测试,其中我将两个对象传递给测试函数,看看它们是否可以转换为List<S> ,并进一步检查列表的计数是否相等。

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. 这需要两个对象和一个类型,如果对象是该类型的大小相同的列表,则返回true。

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. 你试图传递Type typed变量,这就是你得到编译类型错误的原因。

You can make the fact, that only List<T> instances can be passed as method parameters check by compiler during compilation time: 您可以确定,在编译期间,只有List<T>实例可以作为方法参数检查由编译器进行检查:

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. 如果您希望在运行时完成该测试,则应使用Eric提供的解决方案。

If the true goal is to ensure that both items can be cast to some generic list type, then just as-cast the objects into the non-generic IList interface. 如果真正的目标是确保两个项都可以转换为某种通用列表类型,那么只需将对象转换为非通用IList接口。 Then you can compare the count: 然后你可以比较计数:

private static bool Test<T>(T obj1, T obj2)
{
    if (typeof(T).IsGenericType)
    {
        var obj1List = obj1 as System.Collections.IList;
        var obj2List = obj2 as System.Collections.IList;

        if (obj1List != null && obj2List != null && obj1List.Count == obj2List.Count)
            return true;
    }
    return false;
}

If you really want to use reflection it you might make something like this work: 如果你真的想使用反射,你可能会做出像这样的工作:

if (typeof(T).IsGenericType) {
        var genericTypeParam1 = typeof(T).GetGenericArguments().First();
        Console.WriteLine(genericTypeParam1);

        // LINE MARKER 1
        // var obj1AsList = (obj1 as IEnumerable<genericTypeParam1>);
        var genericListType = typeof(IEnumerable<>).MakeGenericType(genericTypeParam1);

        Convert.ChangeType(obj1,genericListType);
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM