2

给定

        int foo = 1;
        Type unboundType = typeof(List<>);
        Type w = unboundType.MakeGenericType(typeof(int));

        if (w == typeof(List<int>))
        {
            Console.WriteLine("Yes its a List<int>");

            try
            {
                ((List<int>)(object)w).Add(foo);
            }
            catch(InvalidCastException)
            {
                Console.WriteLine("No you can't cast Type");
            }
        }   

我可以验证该类型确实与构造类型匹配并基于所述构造类型执行操作。但是,我不能将Type其转换为classusingas或显式转换。允许开发人员创建未绑定类型是否有实际目的,Type或者此功能是否仅以某种方式支持该语言?

4

3 回答 3

4

在您发布的代码中,您实际上并没有在任何地方实例化该类型的对象。您只是试图将一个实例转换为System.Type没有List<int>意义的实例。如果您更新代码以实际创建实例,则它可以工作:

int foo = 1;
Type unboundType = typeof(List<>);
Type w = unboundType.MakeGenericType(typeof(int));

if (w == typeof(List<int>))
{
    Console.WriteLine("Yes its a List<int>");
    object obj = Activator.CreateInstance(w);

    try
    {
        ((List<int>)obj).Add(foo);
        Console.WriteLine("Success!");
    }
    catch(InvalidCastException)
    {
        Console.WriteLine("No you can't cast Type");
    }
}

也许我只是错过了你问题的症结所在。当然,根据您的逻辑,您可以根据编译时不知道的某些类型进行 if/else 检查(在您的示例中,您知道您正在使用int,但可能在运行时可能是其他类型的所需)

编辑:只是为了提供一个真正的运行时使用示例,请考虑以下内容:

public object CreateList(Type elementType, object initialValue)
{
    if (!elementType.IsAssignableFrom(initialValue.GetType()))
        throw new ArgumentException("Incompatible types!");

    Type unboundType = typeof(List<>);
    Type listType = unboundType.MakeGenericType(elementType);
    object list = Activator.CreateInstance(listType);
    var addMethod = listType.GetMethod("Add");
    addMethod.Invoke(list, new []{initialValue});
    return list;
}

这让我们可以在运行时创建一个List<T>未知类型/对象。一些用法:

object intList = CreateList(typeof(int), 1);
object stringList = CreateList(typeof(string), "asdf");

object objectFromSomewhere = GetMyUnknownObject();
object someUnknownListType = CreateList(objectFromSomewhere.GetType(), objectFromSomewhere);

因此,您可能无法按原样处理对象;可能IEnumerable至少可以对待他们。但这取决于您的系统需要做什么。

编辑:忘记了IList界面:

public IList CreateList(Type elementType, object initialValue)
{
    if (!elementType.IsAssignableFrom(initialValue.GetType()))
        throw new ArgumentException("Incompatible types!");

    Type unboundType = typeof(List<>);
    Type listType = unboundType.MakeGenericType(elementType);
    IList list = (IList)Activator.CreateInstance(listType);
    list.Add(initialValue);
    return list;
}
于 2013-02-01T19:50:51.333 回答
4

并非所有事情都可以在编译时完成。有时,特别是在库代码中,您需要获取所提供的内容。object在只给你一个或一个并且需要做一些聪明的处理的场景中Type,未绑定的类型真的很有帮助;例如:

object obj = NoIdeaWhatThisReturns();
IList list = (IList)Activator.CreateInstance(
                 typeof(List<>).MakeGenericType(obj.GetType()));
list.Add(obj);

基本上; 使用大量反射或元编程的场景可能会在某些时候发现自己使用未绑定类型。

于 2013-02-01T19:57:34.377 回答
0

Type不是给定类型的占位符 - 它是描述其他类型的特定类型本身。尝试将其转换为不同的、不相关的类型是没有意义的,因为元数据(显然)不能针对该特定类型起作用。

元数据类型用于检查特定类型的各个方面,而不是创建一个。如果您想以通用方式创建类型的实例,您可以使用Activator该类。

Type oType = ...; // get a Type instance here about a type
object[] oArgs = { oParam1, oParam2 }; // constructor parameters (if any)

return ( Activator.CreateInstance ( oType, oArgs ) );

例如,这使您能够基于字符串创建类型。您可以获取(或从类似的函数调用)的Type实例,然后创建该类型的实例。(直接支持只获取一个字符串,但在内部,它用于查找需要实例化的类型。)System.StringGetTypeNameFromUser(...)ActivatorType

由于所有类型都是平等的,因此您可以Type像任何其他类型一样为未绑定的泛型类型创建一个实例 - 至少,它允许您检查其属性和方法。(正如公认的答案所示,您还可以使用Type实例来创建专用的泛型类型MakeGenericType。)

于 2013-02-01T19:55:39.343 回答