只获取直接接口而不是全部?

发布于 2024-10-22 07:11:25 字数 303 浏览 1 评论 0原文

我有一个像下面这样的课程。 GetInterfaces() 说

如果当前Type代表一个类型 a 定义中的参数 泛型类型或泛型方法,这 方法搜索接口 约束和任何接口 从类或接口继承 限制条件。

我有可能得不到任何继承的接口吗?当我在 ABC 上使用 GetInterfaces 时,我只想查看 DEF,而不是 DEF 和 GHI。

interface DEF : GHI {...}
class ABC : DEF {...}

I have a class like the below. GetInterfaces() says

If the current Type represents a type
parameter in the definition of a
generic type or generic method, this
method searches the interface
constraints and any interfaces
inherited from class or interface
constraints.

Is it possible for me to not get any inherited interface? When i use GetInterfaces on ABC i only want to see DEF, not DEF and GHI.

interface DEF : GHI {...}
class ABC : DEF {...}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

晌融 2024-10-29 07:11:26

这是来自 重复问题

public static class TypeExtensions {
   public static IEnumerable<Type> GetInterfaces(this Type type, bool includeInherited)
   {
      if (includeInherited || type.BaseType == null)
         return type.GetInterfaces();
      else
         return type.GetInterfaces().Except(type.BaseType.GetInterfaces());
   }
}

和用法:

foreach(Type ifc in typeof(Some).GetInterfaces(false)) {
   Console.WriteLine(ifc);
}

This is a nice piece from a duplicate question:

public static class TypeExtensions {
   public static IEnumerable<Type> GetInterfaces(this Type type, bool includeInherited)
   {
      if (includeInherited || type.BaseType == null)
         return type.GetInterfaces();
      else
         return type.GetInterfaces().Except(type.BaseType.GetInterfaces());
   }
}

And usage:

foreach(Type ifc in typeof(Some).GetInterfaces(false)) {
   Console.WriteLine(ifc);
}
山有枢 2024-10-29 07:11:26

据我所知,所发布的解决方案均不适用于下面示例中的 typeof(C1)typeof(I3)

我认为正确的答案是不可能使用开箱即用的框架调用来获取直接实现的接口。

private interface I1 { }

private interface I2 : I1 { }

private interface I3 : I2, I1 { }

public class C1 : I3, I1 { }

As far as I can tell, none of the posted solutions work for typeof(C1) and typeof(I3) in the example below.

I think the correct answer is that it is not possible to get the directly implemented interfaces using out-of-the-box framework calls.

private interface I1 { }

private interface I2 : I1 { }

private interface I3 : I2, I1 { }

public class C1 : I3, I1 { }
吐个泡泡 2024-10-29 07:11:26

对于接口继承层次来说,这怎么样?

    public static Map GetTypeInheritance(Type type)
    {
        //get all the interfaces for this type
        var interfaces = type.GetInterfaces();

        //get all the interfaces for the ancestor interfaces
        var baseInterfaces = interfaces.SelectMany(i => i.GetInterfaces());

        //filter based on only the direct interfaces
        var directInterfaces = interfaces.Where(i => baseInterfaces.All(b => b != i));

        Map map = new Map
            {
                Node = type,
                Ancestors = directInterfaces.Select(GetTypeInheritance).ToList()
            };

        return map;
    }

    public class Map
    {
       public Type Node { get; set; }
       public List<Map> Ancestors { get; set; }
    }

How about this for interface inheritance heirachy?

    public static Map GetTypeInheritance(Type type)
    {
        //get all the interfaces for this type
        var interfaces = type.GetInterfaces();

        //get all the interfaces for the ancestor interfaces
        var baseInterfaces = interfaces.SelectMany(i => i.GetInterfaces());

        //filter based on only the direct interfaces
        var directInterfaces = interfaces.Where(i => baseInterfaces.All(b => b != i));

        Map map = new Map
            {
                Node = type,
                Ancestors = directInterfaces.Select(GetTypeInheritance).ToList()
            };

        return map;
    }

    public class Map
    {
       public Type Node { get; set; }
       public List<Map> Ancestors { get; set; }
    }
夏至、离别 2024-10-29 07:11:26

同一个 MSDN 页面说

GetInterfaces 方法不
返回特定接口
顺序,例如按字母顺序或
申报单。你的代码一定不能
取决于其中的顺序
返回接口,因为
顺序各不相同。

所以不,你不能跳过界面。

The same MSDN page says

The GetInterfaces method does not
return interfaces in a particular
order, such as alphabetical or
declaration order. Your code must not
depend on the order in which
interfaces are returned, because that
order varies.

So no, you can't skip interfaces.

木森分化 2024-10-29 07:11:26

此问题在此处此处。无论如何,这是我的简洁代码,考虑了 @Ani 和 @Mikael 在此线程中提出的观点:

var actualInterfaces = type.GetInterfaces();
foreach ( var result in actualInterfaces
    .Except( type.BaseType?.GetInterfaces() ?? Enumerable.Empty<Type>() ) //See https://stackoverflow.com/a/1613936
    .Except( actualInterfaces.SelectMany( i => i.GetInterfaces() ) ) //See https://stackoverflow.com/a/5318781
) yield return result;

This question is duplicated both here and here. In any case, here's my concise code that considers the points raised on this thread by @Ani and @Mikael:

var actualInterfaces = type.GetInterfaces();
foreach ( var result in actualInterfaces
    .Except( type.BaseType?.GetInterfaces() ?? Enumerable.Empty<Type>() ) //See https://stackoverflow.com/a/1613936
    .Except( actualInterfaces.SelectMany( i => i.GetInterfaces() ) ) //See https://stackoverflow.com/a/5318781
) yield return result;
A君 2024-10-29 07:11:25

首先,您发布的 MSDN 片段与您的实际问题没有任何关系。例如,它会处理您拥有诸如 class Foo之类的泛型类型的情况。其中 T : IEnumerable,然后尝试在类型参数 T 上调用 GetInterfaces,例如通过 typeof(Foo<>).GetGenericArguments ().Single().GetInterfaces().

其次,问题描述得有点不明确。请注意,当一个类实现一个接口时,它必须实现该接口“继承”的所有接口。它只是一个 C# 便利功能,允许您在类声明中省略继承的接口。在您的示例中,显式包含“继承的”GHI 接口是完全合法的(没有什么不同):

class ABC : DEF, GHI {...}

我假设您真正想做的是找到一个“覆盖”所有类型的已实现接口的“最小集合”接口。这会导致设置覆盖问题的稍微简化版本。

这是解决该问题的一种方法,无需任何尝试提高算法效率。这个想法是通过过滤掉那些已经由该类型实现的其他接口实现的接口来生成最小接口集。

Type type = ...

var allInterfaces = type.GetInterfaces();    
var minimalInterfaces = from iType in allInterfaces 
                        where !allInterfaces.Any(t => t.GetInterfaces()
                                                       .Contains(iType))
                        select iType;


编辑 - 这是执行上述操作的更好方法

var minimalInterfaces = allInterfaces.Except
                        (allInterfaces.SelectMany(t => t.GetInterfaces()));

:)

例如,对于List

allInterfaces: 

System.Collections.Generic.IList`1[System.Int32]
System.Collections.Generic.ICollection`1[System.Int32]
System.Collections.Generic.IEnumerable`1[System.Int32]
System.Collections.IEnumerable
System.Collections.IList
System.Collections.ICollection

minimalInterfaces:

System.Collections.Generic.IList`1[System.Int32]
System.Collections.IList

请注意,此解决方案涵盖接口'仅层次结构(这似乎是您想要的),而不是它们与类的 class 层次结构的关系。特别是,它不关心接口在类的层次结构中首先实现的何处

例如,假设我们有:

interface IFoo { }
interface IBar : IFoo { }
interface IBaz { } 

class Base : IBar {  }
class Derived : Base, IBaz {  }

现在,如果您尝试使用我描述的解决方案来获取 Derived 的最小接口集,您将获得 IBaz 以及IBar。如果您不需要 IBar,则必须付出更多努力:消除基类实现的接口。最简单的方法是从最小接口集中删除由类的直接基类实现的那些接口,正如 @MikeEast 的答案中提到的。

Firstly, the MSDN snippet you've posted doesn't have anything to do with your actual question. It deals with when you have, for example, a generic type such as class Foo<T> where T : IEnumerable, and you try calling GetInterfaces on the type-parameter T, for example through typeof(Foo<>).GetGenericArguments().Single().GetInterfaces().

Secondly, the problem is slightly ill-specified. Note that when a class implements an interface, it must implement all of the interfaces 'inherited' by that interface. It's simply a C# convenience feature that lets you omit the inherited interfaces in the class-declaration. In your example, it's perfectly legal (and no different) to explicitly include the 'inherited' GHI interface:

class ABC : DEF, GHI {...}

I've assumed that what you really want to do is find a 'minimal set' of interfaces that 'covers' all of the type's implemented interfaces. This results in a slightly simplified version of the Set cover problem.

Here's one way to solve it, without any attempt whatsoever to be algorithmically efficient. The idea is to produce the minimal interface-set by filtering out those interfaces that are already implemented by other interfaces implemented by the type.

Type type = ...

var allInterfaces = type.GetInterfaces();    
var minimalInterfaces = from iType in allInterfaces 
                        where !allInterfaces.Any(t => t.GetInterfaces()
                                                       .Contains(iType))
                        select iType;

(
EDIT - Here's a better way of doing the above:

var minimalInterfaces = allInterfaces.Except
                        (allInterfaces.SelectMany(t => t.GetInterfaces()));

)

For example, for List<int>:

allInterfaces: 

System.Collections.Generic.IList`1[System.Int32]
System.Collections.Generic.ICollection`1[System.Int32]
System.Collections.Generic.IEnumerable`1[System.Int32]
System.Collections.IEnumerable
System.Collections.IList
System.Collections.ICollection

minimalInterfaces:

System.Collections.Generic.IList`1[System.Int32]
System.Collections.IList

Do note that this solution covers interface 'hierarchies' only (which is what you appear to want), not how they relate to the class's class hierarchy. In particular, it pays no attention to where in a class's hierarchy an interface was first implemented.

For example, let's say we have:

interface IFoo { }
interface IBar : IFoo { }
interface IBaz { } 

class Base : IBar {  }
class Derived : Base, IBaz {  }

Now if you try using the solution I've described to get the minimal interface-set for Derived, you would get IBaz as well as IBar. If you don't want IBar, you would have to go to more effort: eliminate interfaces implemented by base-classes. The easiest way to do this would be to remove from the minimal interface-set those interfaces implemented by the class's immediate base-class, as is mentioned in @MikeEast's answer.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文