Вопрос о наследовании интерфейса в .NET - PullRequest
3 голосов
/ 21 января 2011

Давайте возьмем интерфейс IQueryable<T>, например:

public interface IQueryable<T> : IQueryable, IEnumerable;

Поскольку IQueryable в свою очередь реализует IEnumerable:

public interface IQueryable : IEnumerable;

, почему в первом объявлении IQueryable должен явно реализовывать IEnumerableтакже?Это отличается от наследования классов, когда вам не нужно явно наследовать от «прародителя»?

Ответы [ 4 ]

3 голосов
/ 21 января 2011

Упоминание прародителя (и высших предков) в объявлении не является строго обязательным, но , поскольку родительский элемент, являющийся интерфейсом, на самом деле не реализует дедушка, лучше упомянуть дедушку в объявлении внука , чтобы улучшить документацию для возможного исполнителя.

Вот почему, в случае конкретных реализаций в наследстве, вы видите следующее в MSDN :

public class Button : ButtonBase,IButtonControl

, а не следующее ...

public class Button : ButtonBase,Control,Component,MarshalByRefObject,Object
2 голосов
/ 21 января 2011

Это не правда.Я подозреваю, что вы щелкаете правой кнопкой мыши по этим классам / интерфейсам в 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.* Viola! Вот почему вы видите то, что видите на MSDN. Они показывают метаданные, а не то, как их кодеры написали код.

1 голос
/ 21 января 2011

Это потому, что наследование интерфейса - это чистая языковая вещь. При компиляции в 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
{
}

И поскольку большая часть документации генерируется автоматически из метаданных, а не из исходного исходного кода, в конечном итоге сигнатура будет отображаться как реализующая все интерфейсы напрямую, а не через наследование. Что в принципе так и есть. Единственная причина, по которой ВЫ можете воспользоваться преимуществами наследования, заключается в том, что компилятор в итоге создаст для вас правильную подпись, явно подключив все интерфейсы.

0 голосов
/ 21 января 2011

Правильное определение:

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 
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...