A question about interface inheritance in .NET

前端 未结 4 923
慢半拍i
慢半拍i 2021-01-06 18:11

Let\'s take the interface IQueryable for example:

public interface IQueryable : IQueryable, IEnumerable;

Sin

相关标签:
4条回答
  • 2021-01-06 18:11

    This is not true. I suspect you are right-clicking on these classes/interfaces in Visual Studio and clicking on "Go to definition," and this is what the metadata is telling you. If you want to really understand what's happening, here's an example:

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

    Note that the last class only has to implement one interface (but that you get a compiler error if you leave off either method.

    Create the above as a class library, add a reference by BROWSING to the resulting DLL (not by adding a reference to the project), and view the metadata for AddTwoOrThree. You will see

    AddTwoOrThree : IAddTwoOrThree, IAddTwo
    

    Viola! This is why you see what you are seeing on MSDN. They show the metadata, not the way their coders wrote the code.

    0 讨论(0)
  • 2021-01-06 18:24

    Mentioning the grandparent (and higher ancestors) in the declaration is not strictly necessary, but since the parent, being an interface, didn't actually implement the grandparent, its better to mention the grandparent in the declaration of the grandchild to improve documentation for the eventual implementer.

    Thats why, in case of concrete implementations in the ancestry , you see the following in MSDN:

    public class Button : ButtonBase,IButtonControl
    

    and not the following ...

    public class Button : ButtonBase,Control,Component,MarshalByRefObject,Object
    
    0 讨论(0)
  • 2021-01-06 18:29

    Its because Interface inheritance is a pure language sugar thing. When compiling to IL, the interface explicitly implements all the interfaces in the chain so looking at the signature for IQueryable<T> will end up looking like

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

    And since most documentation is auto generated from metadata, and not the original sourcecode, it will end up showing the signature as its implementing all the interfaces directly, and not via inheritance. Which is basically how it is. The only reason YOU can take advantage of inheritance is because the compiler will end up creating the right signature for you, wiring up all the interfaces explicitly.

    0 讨论(0)
  • 2021-01-06 18:37

    The correct definition is:

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

    The following was taken from Microsoft's Source 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 
        }
    
    0 讨论(0)
提交回复
热议问题