英文:
Does C# have a short-hand syntax for creating key/value pairs?
问题
I have a C# method declared like so:
public void Process<K, V>(params KeyValuePair<K, V>[] items)
{
...
}
Usage of this method looks kind of ugly; for example:
Process(
new KeyValuePair("key", "value"),
new KeyValuePair(123, Guid.NewGuid())
);
In Kotlin, you can create pairs using the to
infix function; for example:
val pair1 = "key" to "value"
val pair2 = 123 to UUID.randomUUID()
So the equivalent method usage looks a little tidier; for example:
process("key" to "value", 123 to UUID.randomUUID())
C# doesn't have infix functions, but something nearly equivalent could be achieved with extension methods; for example:
public static KeyValuePair<K, V> To<K, V>(this K key, V value) where K : notnull
{
return new KeyValuePair(key, value);
}
var pair1 = "key".To("value");
var pair2 = 123.To(Guid.NewGuid());
Process("key".To("value"), 123.To(Guid.NewGuid()));
That doesn't seem like the most elegant solution, so the other thing I was considering was that C# has dictionary initializer syntax; for example:
new Dictionary<object, object>()
{
["key"] = "value",
[123] = Guid.NewGuid()
}
or
new Dictionary<object, object>()
{
{ "key", "value" },
{ 123, Guid.NewGuid() }
}
So I was wondering whether dictionary initializer syntax could be applied to a method parameter; for example:
Process({ ["key"] = "value", [123] = Guid.NewGuid() });
or
Process({{ "key", "value" }, { 123, Guid.NewGuid() }});
Questions
Is dictionary initializer syntax as a method parameter possible, or is it syntactic sugar provided by the compiler when using a dictionary?
Are there any other elegant ways to create params
of KeyValuePair<K, V>
?
英文:
I have a C# method declared like so:
public void Process<K, V>(params KeyValuePair<K, V>[] items)
{
...
}
Usage of this method looks kind of ugly; for example:
Process(
new KeyValuePair("key", "value"),
new KeyValuePair(123, Guid.NewGuid())
);
In Kotlin, you can create pairs using the to
infix function; for example:
val pair1 = "key" to "value"
val pair2 = 123 to UUID.randomUUID()
So the equivalent method usage looks a little tidier; for example:
process("key" to "value", 123 to UUID.randomUUID())
C# doesn't have infix functions, but something nearly equivalent could be achieved with extension methods; for example:
public static KeyValuePair<K, V> To<K, V>(this K key, V value) where K : notnull
{
return new KeyValuePair(key, value);
}
var pair1 = "key".To("value");
var pair2 = 123.To(Guid.NewGuid());
Process("key".To("value"), 123.To(Guid.NewGuid()));
That doesn't seem like the most elegant solution, so the other thing I was considering was that C# has dictionary initializer syntax; for example:
new Dictionary<object, object>()
{
["key"] = "value",
[123] = Guid.NewGuid()
}
or
new Dictionary<object, object>()
{
{ "key", "value" },
{ 123, Guid.NewGuid() }
}
So I was wondering whether dictionary initializer syntax could be applied to a method parameter; for example:
Process({ ["key"] = "value", [123] = Guid.NewGuid() });
or
Process({{ "key", "value" }, { 123, Guid.NewGuid() }});
Questions
Is dictionary initializer syntax as a method parameter possible, or is it syntactic sugar provided by the compiler when using a dictionary?
Are there any other elegant ways to create params
of KeyValuePair<K, V>
?
答案1
得分: 9
这是目前(截至2023年,C# 11)C#原生支持的最佳方式。
正如您自己所写,C# 3引入了使用花括号的简化初始化,C# 6引入了命名参数初始化,而C# 9允许在可以推断出实例化类型时使用 new()
。
这意味着您可以执行以下操作:
// C# 3+
CallMethod(new Dictionary<string, string> { { "ka", "a" }, { "kb", "b" } });
// C# 6+
CallMethod(new Dictionary<string, string> { ["ka"] = "a", ["kb"] = "b" });
// C# 9+
CallMethod(new() { { "ka", "a" }, { "kb", "b" } });
如果您真的想要使用 params,减少一些按键次数的一种方法是使用 ValueTuple
,类似于以下方式:
public static Dictionary<K, V> CallMethod<K, V>(params (K key, V value)[] values)
{
var dict = new Dictionary<K, V>();
foreach (var kvp in values)
{
dict[kvp.key] = kvp.value;
}
return dict;
}
然后您可以执行以下操作:
// C# 7+,返回类型被推断为 Dictionary<string, string>
CallMethod(("ka", "a"), ("kb", "b"));
[更新]
还有一个关于C# 12的提议更新,允许您使用以下语法:
// C# 12+ 提议
CallMethod(["ka": "a", "kb": "b"]);
英文:
This is currently (as of 2023, C# 11) the best you can get with C# out of the box.
As you wrote yourself, C# 3 introduced shorthand init using curly brackets, C# 6 introduced named parameters init, and C# 9 allows you to use new()
when the instantiated type can be inferred.
Meaning that you can do:
// C# 3+
CallMethod(new Dictionary<string, string> { { "ka", "a" }, { "kb", "b" } });
// C# 6+
CallMethod(new Dictionary<string, string> { ["ka"] = "a", ["kb"] = "b" });
// C# 9+
CallMethod(new() { { "ka", "a" }, { "kb", "b" } });
If you really want to use params, one way to reduce some keystrokes would be to use ValueTuple
s, something like
public static Dictionary<K, V> CallMethod<K, V>(params (K key, V value)[] values)
{
var dict = new Dictionary<K, V>();
foreach (var kvp in values)
{
dict[kvp.key] = kvp.value;
}
return dict;
}
and then you can do
// C# 7+, return type is inferred to be Dictionary<string, string>
CallMethod(("ka", "a"), ("kb", "b"));
[Update]
There is also a proposed update for collection literals in C#12 which would allow you to use the following syntax:
// C# 12+ proposal
CallMethod(["ka": "a", "kb": "b"]);
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论