检查类的泛型参数是否实现接口

时间:2018-02-15 20:50:48

标签: c# generics interface casting

我有以下通用类:

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

我还有一个Bird类,它实现了IFlyble接口:

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

public interface IFlyable
{
    void Fly();
}

我还有res类型的变量object。 如何检查res是否为SearchResult<IFlyable>

我试着这样做:

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

就这样:

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

但它似乎不起作用。

2 个答案:

答案 0 :(得分:15)

您遇到的问题可能是由于SearchResult<Bird> 无法转换SearchResult<IFlyable>,因为SearchResult<T>T中不变

C#只承认接口和委托中的泛型类型差异。您需要定义一个ISearchResult<>接口,该接口在其泛型类型中是协变的。

在您的情况下,如果可以接受T仅用作输出,您可以按如下方式定义此类界面:

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

现在ISearchResult<Bird>ISearchResult<IFlyable>,因为您已经为编译器提供了足够的信息,以便它可以验证转换实际上是安全的

答案 1 :(得分:1)

你也可以尝试使用反射,它也可以工作,不需要创建另一个界面。

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]);
}