简体   繁体   English

如何确定对象是否为任何类型的列表?

[英]How can I find out if an object is a List of any type?

I'm working on a script that I can feed all sorts of objects and tell it to modify them in all sorts of ways. 我正在编写一个脚本,可以提供各种对象,并告诉它以各种方式对其进行修改。 This works really well with many types, but I don't know how to go about handling Lists (and other Collections). 这对于许多类型确实很有效,但是我不知道如何处理列表(和其他集合)。 This doesn't work: 这不起作用:

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

I can't do 我做不到

typeof( List<T> )

because T doesn't exist in there of course. 因为T当然不存在

typeof( List<object> ) 

does not work either. 也不起作用。

So how can I find out if what I have is a list of any kind? 那么,如何确定我所拥有的是任何种类的清单?

Why don't you test if object implements "IEnumerable" then check the type inside the collection(For genric collections) like the following: 为什么不测试对象是否实现“ 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.
            }            
        }

If only List type is needed check for "IList" like the following : 如果仅需要列表类型,请检查“ IList”,如下所示:

IList tempList = o as IList;

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

Hope this was useful. 希望这是有用的。

If you just want to check if it's an List I would go with @Ali Ezzat Odeh approach and just check for 如果您只是想检查它是否为列表,我可以使用@Ali Ezzat Odeh方法,然后检查

else if(o is IList) DoListStuff();

If you need to find out the containing type to handle lists with different elements you could try this extension method: 如果您需要找出包含类型来处理具有不同元素的列表,则可以尝试以下扩展方法:

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

You can use it like 你可以像这样使用它

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

The extension handles all kinds of lists, also arrays. 该扩展程序可以处理各种列表,也可以处理数组。 In my opinion it would be better not to only look for types of List. 我认为最好不要仅查找List类型。 This way you could replace your list with an alternate container like with an array for performance or with an observable collection if you're going into the UI. 这样,您可以将列表替换为备用容器,例如具有性能的数组或如果要进入UI则使用可观察的集合。 It will leave you with more design choices in the future and you can better adapt. 将来它将为您提供更多设计选择,并且您可以更好地适应。

Assuming you want to check that your type is/inherits from a List<T> for some T (rather than just implements IList<T> for some T ) you could use the following extension method: 从假设你要检查你的类型/继承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;
    }
}

As far as I know, there's no way to get the "List" part of a list object from the Type object. 据我所知,没有办法从Type对象中获取列表对象的“ List”部分。 This is because according to the code, there is no "List" type, but actually a number of different generated types that correspond to every kind of generic that "List" receives throughout the course of your program. 这是因为根据代码,没有“列表”类型,但实际上有许多不同的生成类型,这些类型与“列表”在您的整个程序过程中接收的每种泛型相对应。 For example, if your program contained the following: 例如,如果您的程序包含以下内容:

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

Your compiled program will essentially contain the following classes, each with the T in its code replaced with the corresponding type: 您的编译程序实质上将包含以下类,每个类的代码中的T均被相应的类型替换:

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

However, you could trick it a bit. 但是,您可以欺骗一下。 Since the generic name will always follow the above pattern, you can use the name to perform your check: 由于通用名称将始终遵循上述模式,因此您可以使用该名称执行检查:

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

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

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