2009-04-27 12 views
21

que tiene el código C#:abstracta implementación de interfaz explícita en C#

abstract class MyList : IEnumerable<T> 
{ 
    public abstract IEnumerator<T> GetEnumerator(); 

    //abstract IEnumerator IEnumerable.GetEnumerator(); 
} 

Como es, me sale:

'Tipo' no implementa miembro de interfaz 'System.Collections.IEnumerable.GetEnumerator() '.

eliminar el comentario y me sale:

El modificador 'abstracta' no es válido para este artículo

¿Cómo hago un resumen aplicación explícita

+0

Este es un defecto el compilador de C# en mi humilde opinión. Hay muchos casos de uso donde tendrá que agregar una implementación ficticia "solo porque". Además, si elige que el miembro no sea abstracto, el compilador permitirá subclases sin implementación, lo que expone el riesgo de invocar la implementación ficticia. –

Respuesta

29

Interesante - No estoy seguro de que puedas. Sin embargo, si este es su código real, ¿alguna vez desea implementar el GetEnumerator() no genérico de alguna manera otro que llamando al genérico?

que haría esto:

abstract class MyList<T> : IEnumerable<T> 
{ 
    public abstract IEnumerator<T> GetEnumerator(); 

    IEnumerator IEnumerable.GetEnumerator() 
    { 
     return GetEnumerator(); 
    } 
} 

Eso le ahorra el tedio de tener que ponerlo en práctica en cada clase derivada - que sin duda todos utilizan la misma aplicación.

+2

No tengo ninguna razón para pensar que se implementará de otra manera ... pero nunca se sabe. +1 – BCS

+2

Re tu comentario - Puede que haya leído mal ...editado para arreglarlo, y encontré el código idéntico al suyo, así lo he eliminado ;-p –

14

Mientras que un miembro de interfaz explícita puede no ser abstracta (o virtual), que puede implementarse en términos de un resumen (o virtual) miembro de 1:

public abstract class Foo: IEnumerable { 
    IEnumerator IEnumerable.GetEnumerator() { 
     return getEnumerator();  
    } 

    protected abstract IEnumerator getEnumerator(); 
} 

public class Foo<T>: Foo, IEnumerable<T> { 
    private IEnumerable<T> ie; 
    public Foo(IEnumerable<T> ie) { 
     this.ie = ie; 
    } 

    public IEnumerator<T> GetEnumerator() { 
     return ie.GetEnumerator(); 
    } 

    protected override IEnumerator getEnumerator() { 
     return GetEnumerator(); 
    } 

    //explicit IEnumerable.GetEnumerator() is "inherited" 
} 

he encontrado la necesidad de esto en fuertemente tipado ASP.NET MVC 3 vistas parciales, que no admiten modelos genéricos de definición de tipo (hasta donde yo sé).

+0

Me encontré teniendo que usar esta solución también. ¡Gracias! (La respuesta de Jon Skeets tiene sentido en el ejemplo proporcionado, pero si no existe una relación tan simple, esta parece ser la mejor solución que yo sepa). – AnorZaken

0

Tuve un caso un poco más complicado en el que quería que una clase base implementara explícitamente la interfaz no genérica y una clase derivada implementara la interfaz genérica.

Interfaces:

public interface IIdentifiable<TKey> : IIdentifiable 
{ 
    TKey Id { get; } 
} 

public interface IIdentifiable 
{ 
    object Id { get; } 
} 

Lo resuelto por la que se declara un método getter resumen en la clase base y dejar que la aplicación explícita llamarlo:

public abstract class ModelBase : IIdentifiable 
{ 
    object IIdentifiable.Id 
    { 
     get { return GetId(); } 
    } 

    protected abstract object GetId(); 
} 

public class Product : ModelBase, IIdentifiable<int> 
{ 
    public int ProductID { get; set; } 

    public int Id 
    { 
     get { return ProductID; } 
    } 

    protected override object GetId() 
    { 
     return Id; 
    } 
} 

Tenga en cuenta que la clase base no tiene la la versión mecanografiada de Id podría llamar.

1

En realidad puede hacerlo, al obligar a una clase, que se deriva de una clase abstracta, para implementar una interfaz, y aún así permitir que se elija la forma de aplicar esa interfaz - implícita o explícitamente:

namespace Test 
{ 
    public interface IBase<T> 
    { 
     void Foo(); 
    } 

    public abstract class BaseClass<T> 
     where T : IBase<T> // Forcing T to derive from IBase<T> 
    { } 

    public class Sample : BaseClass<Sample>, IBase<Sample> 
    { 
     void IBase<Sample>.Foo() { } 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      Sample sample = new Sample(); 

      // Error CS1061 'Sample' does not contain a definition for 'Foo' 
      // and no extension method 'Foo' accepting a first argument of type 'Sample' 
      // could be found(are you missing a using directive or an assembly reference ?) 
      sample.Foo(); 

      (sample as IBase<Sample>).Foo(); // No Error 
     } 
    } 
} 
Cuestiones relacionadas