2011-01-19 9 views
5

Tengo una interfaz y dos clases que la implementan. Estoy obteniendo un error de compilación, y no estoy muy seguro de por qué.Interfaz como propiedad

interface IPerson 
{ 
    ICollection<string> NickNames{get;set;} 
} 
class ObservablePerson : IPerson 
{ 
    ObservableCollection<string> NickNames{get;set;} 
} 
class ListPerson : IPerson 
{ 
    List<string> NickNames{get;set;} 
} 

estoy teniendo un poco de problemas para entender por qué esto no va a funcionar, lista e implementar ObservableCollection tanto ICollection.

+0

Indique el error del compilador. –

+0

@Robert, sería "ObservablePerson no implementa el miembro de interfaz IPerson.NickNames" y más cosas sobre tipos de devolución que no coinciden. Y, para el caso, las implementaciones también deben ser públicas. –

+0

Este es un duplicado de cientos de preguntas de varianza. –

Respuesta

6

Estoy teniendo problemas para entender por qué esto no funciona, ya que List y ObservableCollection implementan ICollection.

Sí, pero la interfaz indica que se devuelve ICollection<string>. El tipo subyacente puede ser ObservableCollection<string> o List<string>, pero la firma debe ajustarse a la interfaz. Un ObservableCollection<string> es un ICollection<string>, pero un ICollection<string> no es necesariamente un ObservableCollection<string>.

Además, sus métodos deben ser públicos (actualmente son privados). Las interfaces no tratan con métodos privados o protegidos, sino que define la interfaz public.

+0

Derecha. Para más, mira el hecho de que la propiedad tiene un setter.Un consumidor de 'IPerson' debería pensar que puede establecer la propiedad en * cualquier *' ICollection ', pero claramente no es el caso si el código provisto pudiera compilarse realmente. –

+0

Sí, buen punto. –

+0

Sí, olvidé agregar el modificador público. – user582181

0

Su problema es que el compilador espera que ambas subclases devuelvan un tipo de ICollection. Puede devolver una Lista o ObservableCollection a través del acceso de obtención, pero el tipo de miembro declarado debe permanecer como ICollection.

1

Debe ser

interface IPerson 
{ 
    ICollection<string> NickNames{get;set;} 
} 
class ObservablePerson : IPerson 
{ 
    ICollection<string> NickNames{get;set;} 
} 
class ListPerson : IPerson 
{ 
    ICollection<string> NickNames{get;set;} 
} 

Y dentro de la aplicación, se puede devolver un objeto de lista o código Editado ObservableCollection

interface IPerson 
    { 
     ICollection<string> NickNames{get;set;} 
    } 

public class ObservablePerson : IPerson 
    { 
     ICollection<string> nickNames = new ObservableCollection<string>(); 

     public ICollection<string> IPerson.NickNames 
     { 
      get 
      { 
       return nickNames; 
      } 
      set 
      { 
       nickNames = value; 
      } 
     } 
    } 
    public class ListPerson : IPerson 
    { 
     ICollection<string> nickNames = new List<string>(); 

     public ICollection<string> IPerson.NickNames 
     { 
      get 
      { 
       return nickNames; 
      } 
      set 
      { 
       nickNames = value; 
      } 
     } 
    } 
+0

Entonces, ¿alguien que use la clase ObservablePerson debería saber lanzar los NickNames a una ObservableCollection? ¿O habría una mejor manera? – user582181

+0

He actualizado mi código por lo que no habría necesidad de transmitir contenido. – Divi

0

El compilador va a insistir en partidos tipo exacto, pero puede sombrear la propiedad cuando se accede a ella en la clase (en lugar de a través de la interfaz). Tenga en cuenta, sin embargo, que al configurar a través de la interfaz, alguien puede asignar un tipo diferente de ICollection<string>, por lo que esto daría lugar a una excepción.

interface IPerson 
{ 
    ICollection<string> NickNames { get; set; } 
} 
class ObservablePerson : IPerson 
{ 
    public new ObservableCollection<string> NickNames { get; set; } 
    ICollection<string> IPerson.NickNames 
    { 
     get { return NickNames; } 
     set { NickNames = (ObservableCollection<string>)value; } 
    } 
} 
class ListPerson : IPerson 
{ 
    public new List<string> NickNames { get; set; } 
    ICollection<string> IPerson.NickNames 
    { 
     get { return NickNames; } 
     set { NickNames = (List<string>)value; } 
    } 
} 
0

Me encontré con un problema similar, y un amigo mío sugirió una excelente solución: tipos genéricos. Esto es lo que puede hacer:

public interface IPerson<CollectionType> where CollectionType : ICollection<string> 
{ 
    CollectionType NickNames { get; set; } 
} 

class ObservablePerson : IPerson<ObservableCollection<string>> 
{ 
    public ObservableCollection<string> NickNames { get; set; } 
} 

public class ListPerson : IPerson<List<string>> 
{ 
    public List<string> NickNames { get; set; } 
} 

aquí, "CollectionType" es un genérico, y se puede nombrar lo que quieras (A menudo se llama T en todo el .NET Framework, pero lo que le da un nombre significativo que siento es útil) Esto le permitirá implementar una interfaz en esos ObservablePerson y ListPerson, mientras que todavía tiene diferentes tipos para la propiedad NickNames en cada uno (aunque cualquier tipo que use para CollectionType necesitará implementar ICollection).

Cuestiones relacionadas