Reputation: 619
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.
typeof( List<object> )
does not work either.
So how can I find out if what I have is a list of any kind?
Upvotes: 0
Views: 1866
Reputation: 553
If you just want to check if it's an List I would go with @Ali Ezzat Odeh approach and just check for
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. 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. It will leave you with more design choices in the future and you can better adapt.
Upvotes: 1
Reputation: 2163
Why don't you test if object implements "IEnumerable" then check the type inside the collection(For genric collections) like the following:
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 tempList = o as IList;
if (tempList != null)
{
//Then handle the list as needed.
}
Hope this was useful.
Upvotes: 1
Reputation: 117323
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:
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;
}
}
Upvotes: 0
Reputation: 24846
As far as I know, there's no way to get the "List" part of a list object from the Type object. 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:
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";
Upvotes: 0