IEnumerable.GetEnumerator() and IEnumerable<T>.GetEnumerator()

社会主义新天地 提交于 2021-01-27 05:44:52

问题


In the .net framework, there's a generic IEnumerable<T> interface which inherits from the not-generic IEnumerable, and they both have a GetEnumerator() method. The only differents between these two GetEnumerator() is the return type. Now I have a similar design, but when I compile the code, the compiler said:

MyInterface<T>.GetItem()' hides inherited member 'MyInterface.GetItem()'. Use the new keyword if hiding was intended.

The MyInterface<T>.GetItem() returns a concrete type T, while MyInterface.GetItem() returns type System.Object.

So I think if the BCL team guys compile the .net framework, they will get the same warning.

I think having compiler warnings is not good, what do you think? And how can I solve this problem? I mean I want to get the concrete type T when calling the MyInterface<T>.GetItem() not just a instance of type System.Object.

Thanks in advance! :-)

Supplement: I'm saying the interfaces theirselves: IMyInterface inherits from IMyInterface, and they both have the GetItem() method (the IMyInterface.GetItem() returns type T, while IMyInterface.GetItem() returns type System.Object). The problem is that, if our code only have these two interfaces, that is, no derived concrete classes, we will encounter the compiler warning after compile the source code.


回答1:


They don't because they compile one version as an Explicit Interface Method Implementation. It looks like this:

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

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

What this type of construct does is make the first GetEnumerator method become the default method, while the other GetEnumerator method is only accessible if the caller first casts SomeClassThatIsIEnumerable to the type IEnumerator, so it avoids the problem.

Edit: based on the supplement above, you would want to use the new keyword:

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



回答2:


The difference is that IEnumerable<T> and IEnumerable are interfaces. In a concrete type, that implements both interfaces, at least one of them has to be implemented explicitly.

In a concrete type inheritance you must use the new keyword to indicate that you want to overwrite the method from the base type. When appplying the new keyword the method is not inherited. This means that myTypeInstance.Method will call the method defined on MyType, while ((MyBaseType) myTypeInstance).Method will call the method defined on the base type.

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


来源:https://stackoverflow.com/questions/2442192/ienumerable-getenumerator-and-ienumerablet-getenumerator

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!