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

时间:2014-01-08 04:29:48

标签: c# generics

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

以下代码有效:

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();
}

但如果我取消注释标有LINE MARKER 1的行,我会收到以下错误:

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

我事先不知道Test会收到List。但我的目的是首先检查obj1obj2是否可以作为列表,然后进行比较

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

提前感谢您的帮助。

3 个答案:

答案 0 :(得分:4)

  

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

正确的方法是:

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());

这需要两个对象和一个类型,如果对象是该类型的大小相同的列表,则返回true。

答案 1 :(得分:2)

作为泛型类型参数提供的类型必须在编译时知道。你试图传递Type类型的变量,这就是你得到编译类型错误的原因。

您可以证明,在编译期间,编译器只能传递List<T>个实例作为方法参数进行检查:

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

如果您希望在运行期间完成该测试,则应使用Eric提供的解决方案。

答案 2 :(得分:1)

如果真正的目标是确保两个项都可以转换为某种通用列表类型,那么只需将对象转换为非通用IList接口。然后你可以比较计数:

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 (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);
    }