2010-02-01 13 views
5

Mam następujące klasy Hierarchia:C# inicjator obiektu chcąc skorzystać źle Dodaj metodę

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) { } 
} 

jednak, starając się wykonać następujące czynności daje błąd:

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

otrzymuję ten błąd:

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

Jak mogę to zrobić, aby za pomocą inicjalizatora obiektu w klasie pochodnej SpecificRow a pufy typu MyEnum? Wygląda na to, że powinien on zobaczyć metodę Add w SpecificRow.

Aktualizacja: I wdrożone dodatkowy interfejs na SpecificRow tak to teraz wygląda następująco:

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

Jednak wciąż otrzymuję ten sam Add błąd. Zamierzam teraz spróbować wprowadzić IDictionary<MyEnum, string>.

+1

@JonH: nieprawidłowe, pojawi się komunikat o błędzie informujący, że " najlepsze przeciążenie ", które można znaleźć dla danej witryny wywołania to Add (ciąg, ciąg), a to nie pasuje do argumentów faktycznie przekazywanych. –

Odpowiedz

7

Inicjator kolekcji niekoniecznie wygląda na jakąkolwiek metodę ICollection.Add (x). Bardziej konkretnie, w przypadku inicjatora kolekcji:

C# wygląda na dowolną metodę Add z podpisem Add (?); gdyby ? zawiera przecinek, C# analizuje metodę dodawania z wieloma argumentami. Kompilator nie ma żadnej specjalnej obsługi KeyValuePair <,> w ogóle. Przyczyna: { string, string } działa, ponieważ twoja klasa bazowa ma przeciążenie Add(string, string) i nie, ponieważ ma przeciążenie dla Add(KeyValuePair<string, string>).

więc wspierać swoją składnię

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

trzeba przeciążenie postaci

void Add(MyEnum key, string value) 

To wszystko jest do niego.

+0

Dziękujemy! Bardzo się cieszę, że nie muszę implementować całego interfejsu, aby uzyskać możliwości inicjatora obiektu. Dodanie sugerowanego przeciążenia do 'SpecificRow' zadziałało. –

5

Wygląda na to, że implementujesz tylko IDictionary<string, string> i wszystkie inne interfejsy z nim powiązane. Twoja metoda Add(KeyValuePair<MyEnum, string>) nie implementuje żadnego elementu interfejsu, jest to po prostu kolejny element klasy SpecificRow, który zdarza się na nazwę Add, dlatego też jest ignorowany.

powinien być w stanie wykonać jedną z następujących czynności, w zależności od tego, co twoje wymagania to:

  1. Wdrożenie IDictionary<MyEnum, string> oprócz IDictionary<MyEnum, string>, w tym interfejsów zależnych (ICollection<KeyValuePair<MyEnum, string>>, etc).
  2. Implementuje IDictionary<MyEnum, string> zamiast IDictionary<MyEnum, string>, ponownie włączając zależne interfejsy.
  3. Zmień deklarację na Row<T> i zaimplementuj IDictionary<T, string>, w tym zależne interfejsy. SpecificRow wdrożył następnie Row<MyEnum> zamiast tylko .
+0

Oczywiście najlepsza odpowiedź. Dodam, że niektóre refaktoryzacje w klasie Row mogą być przydatne (czy nie ma za dużo implementacji interfejsu?) –

+1

Wiele z nich byłoby implicite zaimplementowanych ... IIRC, 'IDictionary ' wymaga 'ICollection >', IEnumerable > 'i' IEnumerable'. W przypadku pozostałych istnieje wiele scenariuszy, w których wdrożenie wszystkich tych interfejsów byłoby rozsądne, akceptowalne i prawdopodobnie nawet pożądane. –

+1

Nie jestem pewien, czy to jest poprawne. Sekcja 7.5.10.3 specyfikacji języka C# stwierdza, że ​​kolekcje muszą implementować tylko IEnumerable, aby zostać zainicjalizowane w ten sposób, i "... dla każdego podanego elementu w kolejności, inicjator kolekcji wywołuje metodę Add na obiekcie docelowym ... stosując normalne rozdzielczość przeciążania dla każdej inwokacji ". Innymi słowy, jeśli kolekcja ma metodę Add(), która pasuje do KeyValuePair , oczekiwałbym, że zostanie wywołana, tak jak oryginalny plakat. –

1

odpowiedź Ruben jest zdecydowanie najlepszy, ale jeśli nie chcesz dodać Add(MyEnum key, string value) następnie można również zainicjować kolekcję tak:

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