C# object initializer wanting to use wrong Add method
I have the following class hierarchy:
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) { }
}
However, trying to do the following gives an error:
var result = new SpecificRow
{
{MyEnum.Value, ""},
{MyEnum.OtherValue, ""}
};
I get this error:
The best overloaded Add method 'Row.Add(string, string)' for the collection initializer has some invalid arguments
How can I make it so that using an object initializer on the derived class SpecificRow
allows type MyEnum
? It seems like it should see the Add
method in SpecificRow
.
Update: I implemented an extra interface on SpecificRow
so it now looks like this:
public class SpecificRow : Row, IXmlSerializable,
Syste开发者_JS百科m.Collections.IEnumerable,
ICollection<KeyValuePair<MyEnum, string>>
{ }
However, I still get the same Add
error. I'm going to try implementing IDictionary<MyEnum, string>
next.
A collection initializer does not necessarily look at any ICollection.Add(x) method. More specifically, for a collection initializer
new SpecificRow {
{ ? }
}
C# looks at any Add method with signature Add(?); if ? contains comma's, C# looks at an Add method with multiple arguments. The compiler does not have any special handling of KeyValuePair<,> at all. The reason { string, string }
works, is because your base class has an overload Add(string, string)
, and not because it has an overload for Add(KeyValuePair<string, string>)
.
So to support your syntax for
new SpecificRow {
{ MyEnum.Value, "" }
};
you need an overload of the form
void Add(MyEnum key, string value)
That's all there is to it.
It looks like it's because you're only implementing IDictionary<string, string>
, and all the other interfaces associated with it. Your Add(KeyValuePair<MyEnum, string>)
method isn't implementing any interface member, it's just another member of the SpecificRow
class, which happens to be named Add
, which is why it is getting ignored.
You should be able to do one of the following, depending on what your requirements are:
- Implement
IDictionary<MyEnum, string>
in addition toIDictionary<MyEnum, string>
, including the dependent interfaces (ICollection<KeyValuePair<MyEnum, string>>
, etc). - Implement
IDictionary<MyEnum, string>
instead ofIDictionary<MyEnum, string>
, again including the dependent interfaces. - Change the declaration of
Row
toRow<T>
, and implementIDictionary<T, string>
, including the dependent interfaces.SpecificRow
would then implementRow<MyEnum>
instead of justRow
.
Ruben's answer is definitely the best, but if you didn't want to add Add(MyEnum key, string value)
then you could also initialize the collection like so:
var result = new SpecificRow
{
new KeyValuePair<MyEnum, string>(MyEnum.Value, ""}),
new KeyValuePair<MyEnum, string>(MyEnum.OtherValue, ""})
};
精彩评论