2016-12-22 33 views
0

我正在处理一个脚本,我可以提供各种对象并告诉它以各种方式修改它们。这对很多类型都非常有效,但我不知道如何去处理List(和其他Collections)。 这不起作用:如何找出对象是否为任何类型的列表?

List<Transform> transformList = new List<Transform>(); 

void MyFunction(object o) { 
    if(o.GetType() == typeof(int) DoIntStuff(); //Easy 
    else if(o.GetType() == typeof(Color) DoColorStuff(); //Also Easy 
    else if(o.GetType() == typeof(List<>)) DoListStuff(); //Not as easy :(
} 

void Start() { 
    MyFunction(transformList); 
} 

我不能做

typeof(List<T>) 

,因为T没有在那里当然存在。

typeof(List<object>) 

也不起作用。

那么我怎么才能知道我所拥有的是什么类型的列表?

+2

我一直挺直,你在那里做的不好。为什么你需要MyFunction,你不能直接调用DoInt/Color/ListStuff吗? – Everts

+0

这是一个过于简单的例子。在实际的脚本中,我可以放入任何GameObject中,并通过Reflection获取所有组件上的所有字段,然后脚本通过它们进行过滤并根据它在UI中的设置修改值。 – col000r

+0

由于它是一个编辑器脚本,您可能还有一个用于拖动的插槽和一个用于该类型的下拉列表。然后你有一个字典枚举,行动和基于选定的枚举类型,它调用该行动。检查类型的想法可能会导致问题,如果一个类型可以是两个。假设你最终检查狗和动物。你的命令也必须考虑。你会遇到很多麻烦。 – Everts

回答

0

假设你要检查你的类型/从List<T>继承了一些T(而不是仅仅实现IList<T>一些T),你可以使用下面的扩展方法:

public static class TypeExtensions 
{ 
    public static bool IsGenericList(this Type type) 
    { 
     return type.GetGenericListItemType() != null; 
    } 

    public static Type GetGenericListItemType(this Type type) 
    { 
     while (type != null) 
     { 
      if (type.IsGenericType) 
      { 
       var genType = type.GetGenericTypeDefinition(); 
       if (genType == typeof(List<>)) 
        return type.GetGenericArguments()[0]; 
      } 
      type = type.BaseType; 
     } 
     return null; 
    } 
} 
0

至于我知道,无法从Type对象获取列表对象的“List”部分。这是因为根据代码,不存在“List”类型,但实际上有许多不同的生成类型,它们对应于程序整个过程中“List”接收的每种通用类型。例如,如果你的程序中包含以下内容:

var a = new List<bool>(); 
var b = new List<int>(); 
var c = new List<char>(); 

你编译的程序将主要包含以下类,每一个在其代码T与相应型号的电池替换:

List`1 // bool List 
List`2 // int List 
List`3 // char List 

但是,可以欺骗一下。由于通用名称将始终遵循上面的图案,您可以使用名称来执行你的检查:

var list = new List<int>(); 
var type = list.GetType(); 
bool isList = list.GetType().Name.Split('`')[0] == "List"; 
1

你为什么不测试,如果对象实现“IEnumerable的”再检查内部集合类型(genric集合)像下面这样:

IEnumerable tempList = o as IEnumerable; 
     if (tempList != null) 
     { 
      IEnumerable<DumyClass> items = tempList.OfType<DumyClass>(); 

      if(items.Count() != 0) 
      { 
       //Then handle the list of the specific type as needed. 
      }    
     } 

如果只有列表类型需要检查“的IList”这样的:

IList tempList = o as IList; 

     if (tempList != null) 
     { 
       //Then handle the list as needed. 
     } 

希望这是有益的。

+0

有很多实现IEnumerable的非List类。 – Abion47

+0

感谢您的反馈,我更新了答案。 –

+0

还有很多其他实现'IList'的集合,比如'ArrayList'和'ObservableCollection',更不用提普通的旧数组了。 – Abion47

1

如果你只是要检查它是否是一个列表我会去与@Ali伊扎特奥德方法,只需要检查

else if(o is IList) DoListStuff(); 

如果你需要找出含有类型来处理不同的元素列表你可以试试这个扩展方法:

public static class TypeExtensions 
    { 
      /// <summary> 
      /// Gets the inner type of the given type, if it is an Array or has generic arguments. 
      /// Otherwise NULL. 
      /// </summary> 
      public static Type GetInnerListType(this Type source) 
      { 
       Type innerType = null; 

       if (source.IsArray) 
       { 
        innerType = source.GetElementType(); 
       } 
       else if (source.GetGenericArguments().Any()) 
       { 
        innerType = source.GetGenericArguments()[0]; 
       } 

       return innerType; 
      } 
    } 

您可以使用它像

else if(o.GetType().GetInnerListType() == typeof(Transform)) DoTransformListStuff(); 

钍e扩展可以处理各种列表,也可以是数组。在我看来,最好不要只查找List的类型。通过这种方式,如果要进入用户界面,可以使用替代容器来替换列表,例如使用数组进行性能或使用可观察集合。它将为您留下更多未来的设计选择,并且您可以更好地适应。

相关问题