【问题标题】:How can I find out if an object is a List of any type?如何确定一个对象是否是任何类型的列表?
【发布时间】:2023-04-08 09:22:01
【问题描述】:

我正在编写一个脚本,我可以提供各种对象并告诉它以各种方式修改它们。这适用于许多类型,但我不知道如何处理列表(和其他集合)。 这不起作用:

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

也不行。

那么我怎样才能知道我所拥有的是否是任何类型的列表呢?

【问题讨论】:

  • 我必须直截了当,你在那里做的事情不好。为什么需要MyFunction,不能直接调用DoInt/Color/ListStuff吗?
  • 这是一个过于简单的例子。在实际脚本中,我可以放入任何游戏对象,它通过反射获取所有组件上的所有字段,然后脚本过滤它们并根据它在其 UI 中的设置方式修改值。
  • 因为它是一个编辑器脚本,你还不如有一个用于拖动的插槽和一个用于类型的下拉菜单。然后你有一个字典 Enum、Action 并根据所选的枚举类型调用操作。如果一个类型可以是两个,那么检查类型的想法可能会导致问题。假设您最终检查了 Dog 和 Animal。您的 if 订单也必须考虑这一点。你会遇到很多麻烦。

标签: c# unity3d types


【解决方案1】:

你为什么不测试对象是否实现“IEnumerable”然后检查集合内的类型(对于通用集合),如下所示:

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.
        }

希望这是有用的。

【讨论】:

  • 有很多非List类实现了IEnumerable
  • 还有很多其他的集合也实现了IList,比如ArrayListObservableCollection,更不用说普通的旧数组了。
【解决方案2】:

如果你只是想检查它是否是一个列表,我会使用@Ali Ezzat Odeh 方法并检查

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

扩展处理各种列表,也包括数组。在我看来,最好不要只寻找 List 的类型。这样,您可以将列表替换为备用容器,例如用于性能的数组或可观察的集合(如果您要进入 UI)。它将在未来为您提供更多设计选择,您可以更好地适应。

【讨论】:

    【解决方案3】:

    据我所知,没有办法从 Type 对象中获取列表对象的“列表”部分。这是因为根据代码,没有“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";
    

    【讨论】:

      【解决方案4】:

      假设您想检查您的类型是/继承自 List&lt;T&gt; 的某些 T(而不仅仅是实现 IList&lt;T&gt; 的某些 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;
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-12-04
        • 2012-10-23
        • 1970-01-01
        • 1970-01-01
        • 2010-12-18
        • 1970-01-01
        • 2011-08-21
        • 1970-01-01
        相关资源
        最近更新 更多