2012-07-13 21 views
9

Me encuentro con muchas situaciones en las que he declarado una interfaz genérica y luego necesité una versión no genérica de esta interfaz, o al menos una versión no genérica de algunos de los métodos o propiedades en esa interfaz. Normalmente declaro una nueva interfaz no genérica y la heredo de la interfaz genérica. El problema que estoy en en espectáculos en el ejemplo siguiente:Interfaces genéricas y no genéricas

public abstract class FormatBase { } 

public interface IBook<F> where F : FormatBase 
{ 
    F GetFormat(); 
} 

public interface IBook 
{ 
    object GetFormat(); 
} 

public abstract class BookBase : IBook<FormatBase>, IBook 
{ 
    public abstract FormatBase GetFormat(); 

    object IBook.GetFormat() 
    { 
     return GetFormat(); 
    } 
} 

Dado que la única manera de declarar la interfaz IBook (no genérico) es explícitamente, ¿cómo ir ustedes acerca de lo que es abstracto?

+1

esto no soluciona el problema, pero ¿no te parece que podría tener sentido para que sea 'BookBase : IBook , IBook donde T: FormatBase'? De lo contrario, en su ejemplo simple, al menos, hay poco o ningún beneficio con 'IBook ' en lugar de simplemente 'IBook'. –

+0

Tienes razón. Actualizo el código. Pero el problema con el resumen no genérico aún existe. – BlueChameleon

+0

También obtendrá un "'IBook . GetFormat()' oculta el miembro heredado 'IBook.GetFormat()'. Use la nueva palabra clave si se intentó ocultar". advertencia. Esto probablemente se deba a una decisión de diseño deficiente en alguna parte, pero sin más información es difícil decir qué diseño sería mejor. –

Respuesta

4

¿Por qué no se puede escribir implementación de interfaz explícita, en lugar de declarar que abstracto?

public abstract class BookBase : IBook<FormatBase>, IBook 
{     
    public abstract FormatBase GetFormat(); 

    object IBook.GetFormat() 
    { 
     return GetFormat(); 
    } 
} 
+0

¡Perfecto! Esto es exactamente lo que estaba buscando. – BlueChameleon

+0

¡Ja! Estamos [incluso] (http://stackoverflow.com/a/11472335/31158) ahora, vaquero ... –

+0

@ Jordão suelta el gatillo :) –

7

Sólo delegado:

public abstract class BookBase : IBook<FormatBase> { 
    public abstract FormatBase GetFormat(); 

    object IBook.GetFormat() { 
    return GetFormat(); 
    } 
} 

O, si todavía quiere diferenciar ambos métodos, delegar a un nuevo método:

public abstract class BookBase : IBook<FormatBase> { 
    public abstract FormatBase GetFormat(); 

    public abstract object IBook_GetFormat(); 

    object IBook.GetFormat() { 
    return IBook_GetFormat(); 
    } 
} 

También es necesario new para esquivar un "miembro heredado ocultar" advertencia:

public interface IBook<F> : IBook 
where F : FormatBase { 
    new F GetFormat(); 
} 

Además, podría tener más sentido dejar clases concretas de cida en el concreto FormatBase:

public abstract class BookBase<F> : IBook<F> 
where F : FormatBase { 
    public abstract F GetFormat(); 

    object IBook.GetFormat() { 
    return GetFormat(); 
    } 
} 
+1

Usar' new' rara vez es la respuesta correcta. – spender

+0

@spender, no veo una mejor manera de hacerlo, ¿verdad? –

+0

@spender: use 'new' o cambie el nombre ... Como OP quiere el mismo nombre, o usa' new' u obtiene una advertencia .... No sé ustedes, pero yo no como ser advertido acerca de las decisiones _intencionales_ que hice ... –

Cuestiones relacionadas