C#是否有用于创建键/值对的简化语法?

huangapple go评论189阅读模式
英文:

Does C# have a short-hand syntax for creating key/value pairs?

问题

I have a C# method declared like so:

  1. public void Process<K, V>(params KeyValuePair<K, V>[] items)
  2. {
  3. ...
  4. }

Usage of this method looks kind of ugly; for example:

  1. Process(
  2. new KeyValuePair("key", "value"),
  3. new KeyValuePair(123, Guid.NewGuid())
  4. );

In Kotlin, you can create pairs using the to infix function; for example:

  1. val pair1 = "key" to "value"
  2. val pair2 = 123 to UUID.randomUUID()

So the equivalent method usage looks a little tidier; for example:

  1. 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:

  1. public static KeyValuePair<K, V> To<K, V>(this K key, V value) where K : notnull
  2. {
  3. return new KeyValuePair(key, value);
  4. }
  5. var pair1 = "key".To("value");
  6. var pair2 = 123.To(Guid.NewGuid());
  7. 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:

  1. new Dictionary<object, object>()
  2. {
  3. ["key"] = "value",
  4. [123] = Guid.NewGuid()
  5. }

or

  1. new Dictionary<object, object>()
  2. {
  3. { "key", "value" },
  4. { 123, Guid.NewGuid() }
  5. }

So I was wondering whether dictionary initializer syntax could be applied to a method parameter; for example:

  1. Process({ ["key"] = "value", [123] = Guid.NewGuid() });

or

  1. 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:

  1. public void Process&lt;K, V&gt;(params KeyValuePair&lt;K, V&gt;[] items)
  2. {
  3. ...
  4. }

Usage of this method looks kind of ugly; for example:

  1. Process(
  2. new KeyValuePair(&quot;key&quot;, &quot;value&quot;),
  3. new KeyValuePair(123, Guid.NewGuid())
  4. );

In Kotlin, you can create pairs using the to infix function; for example:

  1. val pair1 = &quot;key&quot; to &quot;value&quot;
  2. val pair2 = 123 to UUID.randomUUID()

So the equivalent method usage looks a little tidier; for example:

  1. process(&quot;key&quot; to &quot;value&quot;, 123 to UUID.randomUUID())

C# doesn't have infix functions, but something nearly equivalent could be achieved with extension methods; for example:

  1. public static KeyValuePair&lt;K, V&gt; To&lt;K, V&gt;(this K key, V value) where K : notnull
  2. {
  3. return new KeyValuePair(key, value);
  4. }
  5. var pair1 = &quot;key&quot;.To(&quot;value&quot;);
  6. var pair2 = 123.To(Guid.NewGuid());
  7. Process(&quot;key&quot;.To(&quot;value&quot;), 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:

  1. new Dictionary&lt;object, object&gt;()
  2. {
  3. [&quot;key&quot;] = &quot;value&quot;,
  4. [123] = Guid.NewGuid()
  5. }

or

  1. new Dictionary&lt;object, object&gt;()
  2. {
  3. { &quot;key&quot;, &quot;value&quot; },
  4. { 123, Guid.NewGuid() }
  5. }

So I was wondering whether dictionary initializer syntax could be applied to a method parameter; for example:

  1. Process({ [&quot;key&quot;] = &quot;value&quot;, [123] = Guid.NewGuid() });

or

  1. Process({{ &quot;key&quot;, &quot;value&quot; }, { 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&lt;K, V&gt;?

答案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&gt();
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:

  1. // C# 3+
  2. CallMethod(new Dictionary&lt;string, string&gt; { { &quot;ka&quot;, &quot;a&quot; }, { &quot;kb&quot;, &quot;b&quot; } });
  3. // C# 6+
  4. CallMethod(new Dictionary&lt;string, string&gt; { [&quot;ka&quot;] = &quot;a&quot;, [&quot;kb&quot;] = &quot;b&quot; });
  5. // C# 9+
  6. CallMethod(new() { { &quot;ka&quot;, &quot;a&quot; }, { &quot;kb&quot;, &quot;b&quot; } });

If you really want to use params, one way to reduce some keystrokes would be to use ValueTuples, something like

  1. public static Dictionary&lt;K, V&gt; CallMethod&lt;K, V&gt;(params (K key, V value)[] values)
  2. {
  3. var dict = new Dictionary&lt;K, V&gt;();
  4. foreach (var kvp in values)
  5. {
  6. dict[kvp.key] = kvp.value;
  7. }
  8. return dict;
  9. }

and then you can do

  1. // C# 7+, return type is inferred to be Dictionary&lt;string, string&gt;
  2. CallMethod((&quot;ka&quot;, &quot;a&quot;), (&quot;kb&quot;, &quot;b&quot;));

[Update]

There is also a proposed update for collection literals in C#12 which would allow you to use the following syntax:

  1. // C# 12+ proposal
  2. CallMethod([&quot;ka&quot;: &quot;a&quot;, &quot;kb&quot;: &quot;b&quot;]);

huangapple
  • 本文由 发表于 2023年2月18日 19:33:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/75493041.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定