2010-02-01 21 views
5

tengo la siguiente jerarquía de clases:C# inicializador de objeto que deseen utilizar equivocada Añadir método

public class Row : ICloneable, IComparable, IEquatable<Row>, 
    IStringIndexable, IDictionary<string, string>, 
    ICollection<KeyValuePair<string, string>>, 
    IEnumerable<KeyValuePair<string, string>>, 
    System.Collections.IEnumerable 
{ } 

public class SpecificRow : Row, IXmlSerializable, 
    System.Collections.IEnumerable 
{ 
    public void Add(KeyValuePair<MyEnum, string> item) { } 
} 

Sin embargo, tratando de hacer lo siguiente da un error:

var result = new SpecificRow 
    { 
     {MyEnum.Value, ""}, 
     {MyEnum.OtherValue, ""} 
    }; 

consigo este error:

The best overloaded Add method 'Row.Add(string, string)' for the collection initializer has some invalid arguments

¿Cómo puedo hacerlo de modo que el uso de un inicializador de objeto en la clase derivada de una SpecificRow llows tipo MyEnum? Parece que debería ver el método Add en SpecificRow.

Actualización: que implementan una interfaz adicional en SpecificRow por lo que ahora se ve así:

public class SpecificRow : Row, IXmlSerializable, 
    System.Collections.IEnumerable, 
    ICollection<KeyValuePair<MyEnum, string>> 
{ } 

Sin embargo, sigo teniendo el mismo error Add. Voy a intentar implementar IDictionary<MyEnum, string> a continuación.

+1

@JonH: incorrecta, el mensaje de error que indica que el " mejor sobrecarga "que se puede encontrar para el sitio de llamada dado es Agregar (cadena, cadena), y esto no coincide con los argumentos que realmente se pasan. –

Respuesta

7

Un inicializador de colecciones no necesariamente considera ningún método ICollection.Add (x). Más específicamente, para un inicializador de colección

new SpecificRow { 
    { ? } 
} 

C# mira cualquier método Agregar con firma Agregar (?); Si ? contiene coma, C# mira un método Agregar con argumentos múltiples. El compilador no tiene ningún manejo especial de KeyValuePair <,> en absoluto. La razón { string, string } funciona, es porque su clase base tiene una sobrecarga Add(string, string) y no, ya que tiene una sobrecarga de Add(KeyValuePair<string, string>).

Así que para apoyar su sintaxis para

new SpecificRow { 
    { MyEnum.Value, "" } 
}; 

necesita una sobrecarga de la forma

void Add(MyEnum key, string value) 

Eso es todo lo que hay que hacer.

+0

¡Gracias! Estoy tan impresionado de no tener que implementar una interfaz completa solo para obtener las capacidades de inicialización de objetos. Agregando su sobrecarga sugerida a 'SpecificRow' funcionó. –

5

parece que es porque sólo se va a implementar IDictionary<string, string>, y todas las otras interfaces asociadas con ella. Su método Add(KeyValuePair<MyEnum, string>) no está implementando ningún miembro de la interfaz, es solo otro miembro de la clase SpecificRow, que ocurre que se llama Add, por lo que se ignora.

Usted debe ser capaz de hacer uno de los siguientes, dependiendo de lo que sus requisitos son:

  1. Implementar IDictionary<MyEnum, string> además de IDictionary<MyEnum, string>, incluyendo las interfaces dependientes (ICollection<KeyValuePair<MyEnum, string>>, etc.).
  2. Implementar IDictionary<MyEnum, string> en lugar de IDictionary<MyEnum, string>, de nuevo incluyendo las interfaces dependientes.
  3. Cambie la declaración de -Row<T>, e implementar IDictionary<T, string>, incluyendo las interfaces dependientes. SpecificRow implementaría Row<MyEnum> en lugar de solo .
+0

Obviamente, la mejor respuesta. Añadiré que algunas refactorizaciones en la clase Row podrían ser útiles (¿no hay demasiada implementación de interfaz?) –

+1

Bueno, muchos de ellos serían implementados implícitamente ... IIRC, 'IDictionary ' requiere 'ICollection >', IEnumerable > 'y' IEnumerable'. Para el resto de ellos, existen muchos escenarios en los que la implementación de todas esas interfaces sería razonable, aceptable e incluso deseable. –

+1

No estoy seguro de si esto es correcto. La sección 7.5.10.3 de la especificación de lenguaje C# indica que las colecciones solo deben implementar IEnumerable para inicializarse de esta manera, y "... para cada elemento especificado en orden, el inicializador de colección invoca un método Add en el objeto de destino ... aplicando normal resolución de sobrecarga para cada invocación ". En otras palabras, si la colección tiene un método Add() que coincide con KeyValuePair , esperaría que se llamara, al igual que el póster original. –

1

respuesta de Ruben es sin duda la mejor, pero si no desea agregar Add(MyEnum key, string value) entonces también podría inicializar la colección de este modo:

var result = new SpecificRow 
{ 
    new KeyValuePair<MyEnum, string>(MyEnum.Value, ""}), 
    new KeyValuePair<MyEnum, string>(MyEnum.OtherValue, ""}) 
}; 
Cuestiones relacionadas