koryakinp
koryakinp

Reputation: 4125

Check if generic parameter of a class implements an interface

I have a following generic class:

public class SearchResult<T>
{
    public int ResultCount { get; set; }
    public IEnumerable<T> Result { get; set; }
}

I also have a Bird class, which implements IFlyble interface:

public class Bird : IFlyable
{
    public void Fly() {}
}

public interface IFlyable
{
    void Fly();
}

I also have a variable res of type object. How do I check if res is a SearchResult<IFlyable> ?

I tryied this way:

if (res.GetType().IsAssignableFrom(typeof(SearchResult<IFlyable>)))
{
    ///
}

And this way:

if(res is SearchResult<IFlyable>)
{
    ///
}

But it does not seems to work.

Upvotes: 3

Views: 301

Answers (2)

InBetween
InBetween

Reputation: 32760

The problem you are having is probably due to the fact that SearchResult<Bird> is not convertible to SearchResult<IFlyable> because SearchResult<T> is invariant in T.

C# only admits generic type variance in interfaces and delegates. You need to define an ISearchResult<> interface that is covariant in its generic type.

In your case, if it’s acceptable that T is only used as an output you could define such interface as follows:

public interface ISearchResult<out T>
{
     int ResultCount { get; }
     IEnumerable<T> Result { get; }
}

And now a ISearchResult<Bird> is a ISearchResult<IFlyable> because you’ve given the compiler enough information so that it can verify that the conversion is in fact safe.

Upvotes: 15

Student222
Student222

Reputation: 3061

You can also try this using reflection, which also works and no need to create another interface.

static void Main()
{
    var sr = new SearchResult<Bird>();
    Console.WriteLine(IsSearchResultIFlyable(sr.GetType())
        ? "sr is SearchResult<IFlyable>"
        : "sr is Not SearchResult<IFlyable>");

    Console.ReadLine();
}

public static bool IsSearchResultIFlyable(Type t)
{
    if (!t.IsGenericType) return false;
    if (t.GetGenericTypeDefinition() != typeof(SearchResult<>)) return false;

    var gr = t.GetGenericArguments();
    return gr.Length == 1 && typeof(IFlyable).IsAssignableFrom(gr[0]);
}

Upvotes: 1

Related Questions