Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I detect that an object is a generic collection, and what types it contains?

I have a string serialization utility that takes a variable of (almost) any type and converts it into a string. Thus, for example, according to my convention, an integer value of 123 would be serialized as "i:3:123" (i=integer; 3=length of string; 123=value).

The utility handles all primitive type, as well as some non-generic collections, like ArrayLists and Hashtables. The interface is of the form

public static string StringSerialize(object o) {}

and internally I detect what type the object is and serialize it accordingly.

Now I want to upgrade my utility to handle generic collections. The funny thing is, I can't find an appropriate function to detect that the object is a generic collection, and what types it contains - both of which pieces of information I need in order to serialize it correctly. To date I've been using coding of the form

if (o is int) {// do something}

but that doesn't seem to work with generics.

What do you recommend?


EDIT: Thanks to Lucero, I've gotten closer to the answer, but I'm stuck at this little syntactical conundrum here:

if (t.IsGenericType) {
  if (typeof(List<>) == t.GetGenericTypeDefinition()) {
    Type lt = t.GetGenericArguments()[0];
    List<lt> x = (List<lt>)o;
    stringifyList(x);
  }
}

This code doesn't compile, because "lt" is not allowed as the <T> argument of a List<> object. Why not? And what is the correct syntax?

like image 232
Shaul Behr Avatar asked Apr 16 '09 08:04

Shaul Behr


1 Answers

Use the Type to gather the required information.

For generic objects, call GetType() to get their type and then check IsGenericType to find out if it is generic at all. If it is, you can get the generic type definition, which can be compared for instance like this: typeof(List<>)==yourType.GetGenericTypeDefinition(). To find out what the generic types are, use the method GetGenericArguments, which will return an array of the types used.

To compare types, you can do the following: if (typeof(int).IsAssignableFrom(yourGenericTypeArgument)).


EDIT to answer followup:

Just make your stringifyList method accept an IEnumerable (not generic) as parameter and maybe also the known generic type argument, and you'll be fine; you can then use foreach to go over all items and handle them depending on the type argument if necessary.

like image 158
Lucero Avatar answered Sep 27 '22 18:09

Lucero