I frequently find myself needing to wri开发者_开发技巧te APIs that involve key value pairs, when I work with this generally I'll end up with a List<KeyValuePair<string,string>>
or similar type collection object which lets me write operations very easily.
The only downside I've come across is adding multiple items to this collect usually results in a very noisy code block such as
MyDictionary.Put(new KeyValuePair<string, string>("a","1"),
new KeyValuePair<string, string>("b","2"),
new KeyValuePair<string, string>("c","3"))
I would much rather be able to do
MyDictionary.Put( {"a","1"}, {"b","2"}, {"c","3"})
A few times I've tried to accomplish and always end up stumbling over what C# expects exactly as the syntax for this.
Collection initialisers allow much of that;
var data = new Dictionary<string,string> {
{"a","1"},
{"b","2"},
{"c","3"}
};
Another way to approach this is to pass just object
an use reflection, passing (for example):
new { a = "1", b = "2", c = "3" }
A nice feature of the last option is that you can also pass in your domain entities, and you can perhaps use richer metadata (attributes etc) - but when used in high volume reflection by itself can be slow unless you take steps to optimise for it. If you aren't using it in a tight loop it should be ok even with reflection (and without optimisation).
For literals, how about ...
MyDictionary.Put("a=1", "b=2", "c=3");
implemented something like ...
void Put(params string[] nameEqualValues)
{
foreach (string nameEqualValue in nameEqualValues)
{
int iEquals = nameEqualValue.IndexOf('=');
if (iEquals < 0)
{
throw new ApplicationException(...);
}
string name = nameEqualValue.Substring(0, iEquals);
string val = nameEqualValue.Substring(iEquals + 1);
this.PutNameValue(name, val);
}
}
Combining and then splitting strings is a bit of overhead, but it doesn't sound as though performance is a critical concern.
Mind you this breaks down if you're not dealing with literals, worse than what you started with ...
MyDictionary.Put(d + "=" + x, e + "=" + y);
MyDictionary.Put(String.Format("{0}={1}", d, x), ...);
I'd probably suck it up and stick with "params string[]", or call Put multiple times. (Or use python ;)
Require that params come in pairs and treat evens (zero, two, ...) as keys and odds as values:
void Put(params string[] items)
{
if (items.Length % 2 != 0) throw new ArgumentException("Expected even number");
for (int i = 0; i < items.Length; i += 2)
{
this.myDict[items[i]] = items[i+1];
}
}
I cannot figure out a very clean way of doing this, but one workaround for lesser typing can be:
public class MyDictionary : List<KeyValuePair<string, string>>
{
...
public void Put(params string[][] p)
{
foreach (var a in p)
Add(new KeyValuePair<string, string>(a[0], a[1]));
}
}
which can be called like this:
MyDictionary.Put(new[] {"a", "1"}, new[] {"b", "2"}, new[] {"c", "3"});
But this is a definite memory waste and also very inefficient coding.
精彩评论