我们以接口IQueryable<T>
为例:
public interface IQueryable<T> : IQueryable, IEnumerable;
因为IQueryable反过来实现IEnumerable:
public interface IQueryable : IEnumerable;
为什么在第一个声明中,IQueryable还必须显式实现IEnumerable?这与类继承不同,您不必显式继承“祖父母”?
答案 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
}