关于c#:如何判断我的泛型类型是否支持某个接口,并为该函数的接口转换?

How can I tell if my generic type supports a certain interface and convert back and forthto that interface for a function?

本问题已经有最佳答案,请猛点这里访问。

我有一个方法看起来像这样:

1
2
3
4
5
private IEnumerable<T> QueryCollection<T>() where T : BaseObj
{
      IEnumerable<T> items = query<T>();
      return items;
}

如果"t"支持某个接口,我现在就需要筛选这个items集合(可能不是这样,所以我不能简单地将它添加为t的约束)。所以我想要这样的东西:

1
2
3
4
5
6
7
8
9
10
private IEnumerable<T> QueryCollection<T>() where T : BaseObj
{
     IEnumerable<T> items = query<T>();

     if (typeOf(T).GetInterface(ITeamFilterable) != null)
     {
           items = FilterByTeams(items);
     }
     return items;
}

检查我的泛型类型是否支持某个接口**的建议方法是什么,如果支持,那么

  • 在方法中使用它来筛选集合
  • 但仍在整体方法中返回类型为"t"的集合
  • 注意:filterbyteams接受一个:

    1
       IEnumerable<ITeamFilterable>

    然后返回

    1
       IEnumerable<ITeamFilterable>

    是否需要对集合进行两次强制转换(一次转换为接口列表,然后再次转换回T列表?)


    在这种情况下,恐怕您不能使用is/as,除非您可以开始枚举查询。

    您可以使用这样的反射:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    private IEnumerable<T> QueryCollection<T>() where T : BaseObj
    {
         IEnumerable<T> items = query<T>();

         if (typeof(ITeamFilterable).IsAssignableFrom(typeof(T)))
               items = (IEnumerable<T>)(object)FilterByTeams(items.Cast<ITeamFilterable>());

         return items;
    }

    但是,如果可以枚举查询,则可以这样做以避免反射(假设没有null项):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    private IEnumerable<T> QueryCollection<T>() where T : BaseObj
    {
         IEnumerable<T> items = query<T>();
         ICollection<T> itemsCollection = items as ICollection<T> ?? items.ToList();

         if (itemsCollection.Count > 0)
         {
             var firstItem = itemsCollection.First();
             if (firstItem is ITeamFilterable)
                 return (IEnumerable<T>)(object)FilterByTeams(itemsCollection.Cast<ITeamFilterable>());
         }

         return itemsCollection;
    }

    由于ITeamFilterableTIEnumerable是协变的,因此强制转换将起作用,但必须在两者之间强制转换到object,以满足泛型约束。使用这些强制转换,不需要复制周围的项目。