关于.NET中的接口继承的问题

时间:2011-01-21 02:49:38

标签: .net asp.net linq inheritance

我们以接口IQueryable<T>为例:

public interface IQueryable<T> : IQueryable, IEnumerable;

因为IQueryable反过来实现IEnumerable:

public interface IQueryable : IEnumerable;

为什么在第一个声明中,IQueryable还必须显式实现IEnumerable?这与类继承不同,您不必显式继承“祖父母”?

4 个答案:

答案 0 :(得分:3)

提及声明中的祖父母(和更高的祖先)并非绝对必要,但是,因为父作为接口,实际上并没有实现祖父母,更好在孙子的声明中提及祖父母以改善最终实施者的文件

这就是为什么,如果在祖先的具体实施中,你会在MSDN中看到以下内容:

public class Button : ButtonBase,IButtonControl

而不是以下......

public class Button : ButtonBase,Control,Component,MarshalByRefObject,Object

答案 1 :(得分:2)

事实并非如此。我怀疑您在Visual Studio中右键单击这些类/接口并单击“转到定义”,这就是元数据告诉您的内容。如果你想真正了解正在发生的事情,这里有一个例子:

    public interface IAddTwo
    {
        int AddTwo(int x);
    }

    public interface IAddTwoOrThree : IAddTwo
    {
        int AddThree(int y);
    }

    public class AddTwoOrThree : IAddTwoOrThree
    {
        public int AddTwo(int q)
        {
            return q + 2;
        }

        public int AddThree(int z)
        {
            return z + 3;
        }
    }

请注意,最后一个类只需实现一个接口(但如果不使用任何一种方法,则会出现编译器错误。

将上述内容创建为类库,将BROWSING的引用添加到生成的DLL中(不是通过添加对项目的引用),并查看AddTwoOrThree的元数据。你会看到

AddTwoOrThree : IAddTwoOrThree, IAddTwo

中提琴!这就是为什么你看到你在MSDN上看到的。它们显示元数据,而不是编码器编写代码的方式。

答案 2 :(得分:1)

因为Interface继承是纯语言糖的事情。在编译为IL时,接口显式实现了链中的所有接口,因此查看IQueryable<T>的签名将最终看起来像

.class public interface abstract auto ansi IQueryable<+ T>
    implements [mscorlib]System.Collections.Generic.IEnumerable`1<!T>, System.Linq.IQueryable, [mscorlib]System.Collections.IEnumerable
{
}

由于大多数文档是从元数据自动生成的,而不是原始源代码,因此最终会将签名显示为直接实现所有接口,而不是通过继承。基本上是这样的。您可以利用继承的唯一原因是编译器最终会为您创建正确的签名,明确地连接所有接口。

答案 3 :(得分:0)

正确的定义是:

public interface IQueryable<out T> : IEnumerable<T>, IQueryable { }

以下摘自Microsoft的源RTMRel \ ndp \ fx \ src \ Core \ System \ Linq \ IQueryable.cs \ 1305376 \ IQueryable.cs

    public interface IQueryable : IEnumerable {
        Expression Expression { get; } 
        Type ElementType { get; } 

        // the provider that created this query 
        IQueryProvider Provider { get; }
    }

#if SILVERLIGHT 
    public interface IQueryable<T> : IEnumerable<T>, IQueryable {
#else 
    public interface IQueryable<out T> : IEnumerable<T>, IQueryable { 
#endif
    } 

    public interface IQueryProvider{
        IQueryable CreateQuery(Expression expression);
        IQueryable<TElement> CreateQuery<TElement>(Expression expression); 

        object Execute(Expression expression); 

        TResult Execute<TResult>(Expression expression);
    } 

    public interface IOrderedQueryable : IQueryable {
    }

#if SILVERLIGHT
    public interface IOrderedQueryable<T> : IQueryable<T>, IOrderedQueryable { 
#else 
    public interface IOrderedQueryable<out T> : IQueryable<T>, IOrderedQueryable {
#endif 
    }