【问题标题】:Check if generic parameter of a class implements an interface检查类的泛型参数是否实现了接口
【发布时间】:2018-07-26 17:29:36
【问题描述】:

我有以下通用类:

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&lt;IFlyable&gt;

我试过这样:

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

这样:

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

但它似乎不起作用。

【问题讨论】:

  • @maccettura res 是 object 并且没有 Result 属性。
  • @mjwills 我想检查特定的object 是否是SearchResult&lt;Flyable&gt;
  • res 的具体具体类型是什么?是object res = new SearchResult&lt;IFlyable&gt;() 还是实际上是object res = new SearchResult&lt;Bird&gt;()
  • 另一方面,如果您必须在使用泛型时进行类型检查,那么您很可能做出了错误的设计决定,因此解释您为什么要这样做可能会让我们建议另一种方法。
  • @juharr object res = new SearchResult&lt;Bird&gt;()

标签: c# generics interface casting


【解决方案1】:

您遇到的问题可能是因为SearchResult&lt;Bird&gt; 不可转换SearchResult&lt;IFlyable&gt;,因为SearchResult&lt;T&gt;T 中是不变的。

C# 只承认接口和委托中的泛型类型差异。您需要定义一个在其泛型类型中协变的ISearchResult&lt;&gt; 接口。

在您的情况下,如果可以接受 T 仅用作输出,您可以定义如下接口:

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

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

【讨论】:

  • 我的解释非常好(+1)。
  • 用较少的技术术语重申 InBetween 的回答:假设不需要out。然后 C# 将允许您将 IList&lt;Bird&gt; 转换为 IList&lt;IFlyable&gt;,这将允许您将 Airplane 添加到 IList&lt;Flyable&gt;
【解决方案2】:

您也可以使用反射来尝试这个,它也可以工作,无需创建另一个接口。

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

【讨论】:

    猜你喜欢
    • 2013-08-16
    • 1970-01-01
    • 2011-02-01
    • 1970-01-01
    • 2016-09-29
    • 2010-09-21
    • 2012-09-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多