IEnumerable.GetEnumerator()和IEnumerable <t> .GetEnumerator()</t>

时间:2010-03-14 12:57:38

标签: .net inheritance ienumerable

在.net框架中,有一个通用的IEnumerable<T>接口,它继承自非通用IEnumerable,并且它们都有GetEnumerator()方法。这两个GetEnumerator()之间的唯一区别是返回类型。 现在我有一个类似的设计,但是当我编译代码时,编译器说:

MyInterface<T>.GetItem()'隐藏了继承的成员“MyInterface.GetItem()”。如果打算隐藏,请使用新关键字。

MyInterface<T>.GetItem()返回具体类型T,而MyInterface.GetItem()返回System.Object类型。

所以我认为如果BCL团队成员编译.net框架,他们会得到同样的警告。

我认为编译器警告不好,你怎么看?我该如何解决这个问题?我的意思是我想在调用MyInterface<T>.GetItem()时获取具体类型T而不仅仅是System.Object类型的实例。

提前致谢! : - )

补充: 我说接口是他们自己的:IMyInterface 继承自 IMyInterface,他们都有GetItem()方法(IMyInterface.GetItem()返回类型T,而IMyInterface.GetItem()返回类型System。宾语)。问题是,如果我们的代码只有这两个接口,即没有派生的具体类,我们将在编译源代码后遇到编译器警告。

2 个答案:

答案 0 :(得分:10)

它们不是因为它们将一个版本编译为显式接口方法实现。它看起来像这样:

public class SomeClassThatIsIEnumerable<T> : IEnumerable<T>
{
    public IEnumerator<T> GetEnumerator()
    {
       // return enumerator.
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return ((IEnumerable<T>)this).GetEnumerator();
    }
}

这种类型的构造所做的是使第一个GetEnumerator方法成为默认方法,而另一个GetEnumerator方法只有在调用者首次将SomeClassThatIsIEnumerable转换为IEnumerator类型时才可访问,因此它避免了这个问题。

编辑:根据上面的补充,您需要使用新关键字:

public interface IMyInterface
{
   object GetObject();
}

public interface IMyInterface<T> : IMyInterface
{
   new T GetObject();
}

// implementation:

public class MyClass : IMyInterface<string>
{
    public string GetObject() 
    {
        return "howdy!";
    }

    object IMyInterface.GetObject()
    {
        return GetObject();
    }
}

答案 1 :(得分:3)

区别在于IEnumerable<T>IEnumerable是接口。在具体类型中,它实现了两个接口,其中至少有一个必须明确实现。

在具体类型继承中,必须使用new关键字指示要从基类型覆盖方法。在应用新关键字时,不会继承该方法。这意味着myTypeInstance.Method将调用MyType上定义的方法,而((MyBaseType) myTypeInstance).Method将调用基类型上定义的方法。

public interface Interface1 {
    object GetItem();
}

public interface Interface2<T> : Interface1 {
    T GetItem();
}

public class MyBaseType : Interface1 {
    public object GetItem() {
        // implements Interface1.GetType()
        return null;
    }
}

public class MyType<T> : Interface1, Interface2<T> {
    public new T GetItem() {
        // Implements Interface2<T>.GetItem()
        return default(T);
    }

    object Interface1.GetItem() {
        // implements Interface1.GetItem()
        return this.GetItem();   // calls GetItem on MyType
    }
}

var myType = new MyType();
var myTypeResult = myType.GetItem(); // calls GetItem on MyType
var myBaseTypeResult = new ((MyBaseType) myType).GetItem(); // calls GetItem on MyBaseType