How to determine IDeclaredType representing a generic List type?


I'm newbie in R# API and I would ask you to help make my code better. Let's assume we have declaredType variable implementing IDeclaredType interface. How to check is declaredType actually representing List<Foo>, IList<Foo> or not?

My solution is:

ITypeElement element = declaredType.GetTypeElement();

string fullName = element.GetClrName().FullName;

bool isGenericList = fullName == "System.Collections.Generic.List`1"
                  || fullName == "System.Collections.Generic.IList`1";

It works but looks bad! I'm sure a correct way to compare generic types exists in R# API instead of this string comparison. Any advice is appreciated!

ReSharper SDK 9.2 is used.
Comment actions Permalink

Any ideas, guys?

Comment actions Permalink

You want to do something like this. The PredefinedType class has a number of properties to get the IDeclaredType of IEnumerable<T>, List<T>, IList<T> and so on. Once you've got this, you can use TypeFactory to create a type and EmptySubstitution.Extend to create a closed generic type (e.g. IList<string>) if you wish. If you're working with a closed generic, you can use a type conversion rule (e.g. new CSharpTypeConversionRule(declaredElement.Module)) to see if another type can be converted to it - in other words, if another type implements IList<string>. If you're looking to see if a given type is an open generic, such as IList<T> or List<T>, you can compare the two declared elements with a simple equals.

Comment actions Permalink

Matt Ellis, thanks!

This is the solution how to detect is IDeclaredType derived from closed List<T> or not, and it is based on code you gave:

IMethod declaredElement = method.DeclaredElement;
IDeclaredType declaredType = declaredElement?.ReturnType as IDeclaredType;
ISubstitution sub = declaredType.GetSubstitution();
IType  parameterType = sub.Apply(sub.Domain[0]);
IType realType = declaredElement.Type();
PredefinedType predefinedType = declaredElement.Module.GetPredefinedType();
ITypeElement generic = predefinedType.GenericList.GetTypeElement();
IType sampleType = EmptySubstitution.INSTANCE
     .Extend(generic.TypeParameters, new IType[] { parameterType })
bool good = realType.IsImplicitlyConvertibleTo(sampleType, new CSharpTypeConversionRule(declaredElement.Module));

Please sign in to leave a comment.