Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p><a href="https://stackoverflow.com/a/74648/1968">The previously accepted answer</a> is nice but it is wrong. Thankfully, the error is a small one. Checking for <code>IEnumerable</code> is not enough if you really want to know about the generic version of the interface; there are a lot of classes that implement only the nongeneric interface. I'll give the answer in a minute. First, though, I'd like to point out that the accepted answer is overly complicated, since the following code would achieve the same under the given circumstances:</p> <pre><code>if (items[key] is IEnumerable) </code></pre> <p>This does even more because it works for each item separately (and not on their common subclass, <code>V</code>).</p> <p>Now, for the correct solution. This is a bit more complicated because we have to take the generic type <code>IEnumerable`1</code> (that is, the type <code>IEnumerable&lt;&gt;</code> with one type parameter) and inject the right generic argument:</p> <pre><code>static bool IsGenericEnumerable(Type t) { var genArgs = t.GetGenericArguments(); if (genArgs.Length == 1 &amp;&amp; typeof(IEnumerable&lt;&gt;).MakeGenericType(genArgs).IsAssignableFrom(t)) return true; else return t.BaseType != null &amp;&amp; IsGenericEnumerable(t.BaseType); } </code></pre> <p>You can test the correctness of this code easily:</p> <pre><code>var xs = new List&lt;string&gt;(); var ys = new System.Collections.ArrayList(); Console.WriteLine(IsGenericEnumerable(xs.GetType())); Console.WriteLine(IsGenericEnumerable(ys.GetType())); </code></pre> <p>yields:</p> <pre><code>True False </code></pre> <p>Don't be overly concerned by the fact that this uses reflection. While it's true that this adds runtime overhead, so does the use of the <code>is</code> operator.</p> <p>Of course the above code is awfully constrained and could be expanded into a more generally applicable method, <code>IsAssignableToGenericType</code>. The following implementation is slightly incorrect<sup>1</sup> and I’ll leave it here <em>for historic purposes only</em>. <strong>Do not use it</strong>. Instead, <a href="https://stackoverflow.com/a/1075059/1968">James has provided an excellent, correct implementation in his answer.</a></p> <pre><code>public static bool IsAssignableToGenericType(Type givenType, Type genericType) { var interfaceTypes = givenType.GetInterfaces(); foreach (var it in interfaceTypes) if (it.IsGenericType) if (it.GetGenericTypeDefinition() == genericType) return true; Type baseType = givenType.BaseType; if (baseType == null) return false; return baseType.IsGenericType &amp;&amp; baseType.GetGenericTypeDefinition() == genericType || IsAssignableToGenericType(baseType, genericType); } </code></pre> <p><sup>1</sup> It fails when the <code>genericType</code> is the same as <code>givenType</code>; for the same reason, it fails for nullable types, i.e.</p> <pre><code>IsAssignableToGenericType(typeof(List&lt;int&gt;), typeof(List&lt;&gt;)) == false IsAssignableToGenericType(typeof(int?), typeof(Nullable&lt;&gt;)) == false </code></pre> <p>I’ve created a <a href="https://gist.github.com/4174727" rel="nofollow noreferrer">gist with a comprehensive suite of test cases</a>.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload