I'm pretty new to C#. Currently I am working on some code left behind by someone else and it might have never worked before. There is a method that accepts two string values as parameters.
public void Update(string area, string value)
{
//Perform operation
}
The above method was being called like this and this result in - "The best overloaded method match for..." error being thrown. The dynamic values can consist of bool, int and string.
public void UpdateAll(Dictionary<string, dynamic> values)
{
foreach (var entry in values)
{
Update(entry.Key, entry.Value);
}
}
My solution was to convert the Dictionary<string, dynamic> to Dictionary<string, string> within UpdateAll method first as shown below as I thought it will require the least amount of change. However I'm getting the error "Cannot convert type 'int' to 'string'" or "Cannot convert type 'bool' to 'string'"
public void UpdateAll(Dictionary<string, dynamic> values)
{
var convertedValues = values.ToDictionary(row => (string) row.Key, row => (string) row.Value);
foreach (var entry in convertedValues)
{
Update(entry.Key, entry.Value);
}
}
What would be the best way to resolve and go about it?
CodePudding user response:
Just do this
Update(entry.Key, entry.Value.ToString());
Be wary of interesting types that don't create an expected representation for ToString(). (eg classes will often just give you a hash value.)
If you just have base types you should be fine.
CodePudding user response:
The problem here is that dynamic
can be any type at runtime and you (and compiler) don't know the actual type until runtime. See this
var values = new Dictionary<string, dynamic>();
values.Add("key1", 5);
values.Add("key2", true);
values.Add("key3", "value");
That code is compiled and executed nicely. The dictionary behaves similarly as this has object
as its type argument for values.
Therefore when you iterate this dictionary, entry.Value
might have different types for different elements of dictionary: int
, bool
, string
, whatever. And when this has, for example, type int
, the overload resolution process just can't find the method Update(string, int)
, therefore the exception occurs. You can fix this by simply converting it to string with a simple call ToString()
. Hopefully all the types in .NET have ToString
method, therefore it's pretty safe:
Update(entry.Key, entry.Value.ToString())
But be careful, entry.Value
still can be null
, so that it might be useful first to check against null
and then convert it to string
.
Another way of fixing this is to have overloads of Update
method for different types which can be part of your dictionary. This is not very feasible if you don't really know what the dictionary might contain, but might be pretty good if you know the types for sure and they won't be extended too often. And of course if this is possible to write different versions of the Update
method:
void Update(string area, string value) { ... }
void Update(string area, int value) { ... }
void Update(string area, bool value) { ... }
Also, I don't know your client code which calls UpdateAll
, but you can also consider this dictionary to have an object
type argument instead of dynamic
. The behavior will be the same, but in the case of object you have a help from the compiler about ToString
method.
void UpdateAll(Dictionary<string, object> values)
Note that this way of declaring the dictionary (with object
) doesn't allow using the method overloads described above.