检查类的泛型参数是否实现了一个接口。

3

我有一个以下的通用类:

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

我还有一个名为的类,实现了IFlyble接口:

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

public interface IFlyable
{
    void Fly();
}

我还有一个类型为object的变量res

如何判断res是否为SearchResult<IFlyable>

我尝试了以下方法:

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

并且这样做:

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

但它似乎不起作用。

@mjwills 我想要检查特定的 object 是否是一个 SearchResult<Flyable> - koryakinp
res 的实际具体类型是什么?它是 object res = new SearchResult<IFlyable>() 还是实际上是 object res = new SearchResult<Bird>() - juharr
@juharr object res = new SearchResult<Bird>() @juharr object res = new SearchResult<Bird>() - koryakinp
为什么您的属性是可设置的?如果我手头有一个 SearchResult<Bird>,为什么我可以将结果计数设置为 -100 呢? - Eric Lippert
@EricLippert 我同意,你可能不应该被允许改变它们,但我不明白这与问题有什么关系。在那个特定的问题背景下,你为什么认为这很重要? - koryakinp
显示剩余3条评论
2个回答

15
你遇到的问题可能是因为SearchResult<Bird>无法转换为SearchResult<IFlyable>,因为SearchResult<T>T上是不变的。
C#只允许接口和委托中的泛型类型变化。你需要定义一个在其泛型类型上是协变的ISearchResult<>接口。
在你的情况下,如果T仅用作输出是可接受的,你可以按照以下方式定义这样的接口:
public interface ISearchResult<out T>
{
     int ResultCount { get; }
     IEnumerable<T> Result { get; }
}

现在,一个 `ISearchResult` 是一个 `ISearchResult`,因为你提供了足够的信息给编译器,以便它可以验证这个转换是安全的。

1
非常好的解释,我给你点赞。 - Christos
重申InBetween的答案,用不太技术性的术语来说:假设out不是必需的。那么C#将允许您将IList<Bird>转换为IList<IFlyable>,这将使您能够将Airplane添加到IList<Flyable>中。 - Brian

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接