C# 中字典的字面表示法?

发布于 2024-10-17 06:45:45 字数 460 浏览 3 评论 0原文

我目前在 JavaScript 和用 C# 编程的服务器之间有一个 WebSocket。在 JavaScript 中,我可以使用关联数组轻松传递数据:

var data = {'test': 'val',
            'test2': 'val2'};

为了在服务器端表示此数据对象,我使用 Dictionary,但这比“打字成本更高” JavaScript 中:

Dictionary<string, string> data = new Dictionary<string,string>();
data.Add("test", "val");
data.Add("test2", "val2");

C# 中的关联数组/字典有某种文字表示法吗?

I currently have a WebSocket between JavaScript and a server programmed in C#. In JavaScript, I can pass data easily using an associative array:

var data = {'test': 'val',
            'test2': 'val2'};

To represent this data object on the server side, I use a Dictionary<string, string>, but this is more 'typing-expensive' than in JavaScript:

Dictionary<string, string> data = new Dictionary<string,string>();
data.Add("test", "val");
data.Add("test2", "val2");

Is there some kind of literal notation for associative arrays / Dictionarys in C#?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

陌伤ぢ 2024-10-24 06:45:45

您使用 集合初始值设定项 语法,但您仍然需要创建 < code>new Dictionary对象首先作为快捷语法转换为一堆 Add() 调用(如您的代码):

var data = new Dictionary<string, string>
{
    { "test", "val" }, 
    { "test2", "val2" }
};

在 C# 6 中,您现在拥有可以选择对字典以及支持索引器<的任何其他类型使用更直观的语法/a>.上面的语句可以重写为:

var data = new Dictionary<string, string>
{
    ["test"] = "val",
    ["test2"] = "val2"
};

与集合初始值设定项不同,这会在幕后调用索引器设置器,而不是适当的 Add() 方法。

You use the collection initializer syntax, but you still need to make a new Dictionary<string, string> object first as the shortcut syntax is translated to a bunch of Add() calls (like your code):

var data = new Dictionary<string, string>
{
    { "test", "val" }, 
    { "test2", "val2" }
};

In C# 6, you now have the option of using a more intuitive syntax with Dictionary as well as any other type that supports indexers. The above statement can be rewritten as:

var data = new Dictionary<string, string>
{
    ["test"] = "val",
    ["test2"] = "val2"
};

Unlike collection initializers, this invokes the indexer setter under the hood, rather than an appropriate Add() method.

好菇凉咱不稀罕他 2024-10-24 06:45:45

虽然字典初始值设定项的答案是完全正确的,但我会指出另一种方法(但我可能不推荐它)。如果您的目标是提供简洁的 API 使用,则可以使用匿名对象。

var data = new { test1 = "val", test2 = "val2"};

那么“data”变量就是“无法形容的”匿名类型,因此您只能将其作为 System.Object 传递。然后,您可以编写可以将匿名对象转换为字典的代码。此类代码将依赖于反射,这可能会很慢。但是,您可以使用 System.Reflection.Emit 或 System.Linq.Expressions 来编译和缓存委托,这将使后续调用速度更快。

我见过 Asp.net MVC API 在很多地方都使用了这种技术。许多 Html Helpers 都有接受对象或字典的重载。我认为他们的 API 设计目标和你所追求的目标是一样的;方法调用时的语法简洁。

While, the dictionary initializer answer is totally correct, there is another approach to this that I would point out (but I might not recommend it). If your goal is to provide terse API usage, you could use anonymous objects.

var data = new { test1 = "val", test2 = "val2"};

The "data" variable is then of an "unspeakable" anonymous type, so you could only pass this around as System.Object. You could then write code that can transform an anonymous object into a dictionary. Such code would rely on reflection, which would potentially be slow. However, you could use System.Reflection.Emit, or System.Linq.Expressions to compile and cache a delegate that would make subsequent calls much faster.

Asp.net MVC APIs use this technique in a number of places that I've seen. A lot of the Html Helpers have overloads that accept either an object or a dictionary. I assume the goal of their API design is the same as what you are after; terse syntax at the method call.

苍景流年 2024-10-24 06:45:45

使用字典文字(C#9 提案)[已拒绝] 或 new 语法(从 C#9 开始)

[这可能会发生,但目前已被拒绝]

C#9 引入了一种更简单的语法来创建初始化的 < code>Dictionary对象,无需指定 Dictionary 类型名称或类型参数。字典的类型参数是使用用于数组类型推断的现有规则来推断的。

// C# 1..8    
var x = new Dictionary <string,int> () { { "foo", 4 }, { "bar", 5 }};   
// C# 9    
var x = ["foo":4, "bar": 5];  

该合成使 C# 中的字典工作更加简单,并删除了冗余代码。

您可以在 GitHub 上关注该问题(这里是 C#9 的里程碑)。

编辑:此提案目前被拒绝

[...] 我们认为初始化数据有许多有趣的用例,特别是对于不可变字典之类的东西。我们没有发现初始化字典的现有语法那么繁重,我们也不认为它是代码中的常见模式,可以从语言功能中受益匪浅。我们认为,在我们进行记录和销毁之后,应该再次查看初始化数据的一般区域。 [...]

当前里程碑:

likely never

请注意,从 C# 9.0 开始,构造函数调用表达式是目标类型的。也就是说,如果表达式的目标类型已知,则可以省略类型名称,如以下示例所示:

Dictionary<int, List<int>> lookup = new()
{
    [1] = new() {1, 2, 3},
    [2] = new() {5, 8, 3},
    [5] = new() {1, 0, 4}
};

如前面的示例所示,您始终在目标类型的新表达式中使用括号。

如果新表达式的目标类型未知(例如,使用 var 关键字时),则必须指定类型名称。

Use Dictionary Literals (C#9 proposal) [rejected] or the new syntax (beginning with C#9)

[this may happens but is currently rejected]

C#9 introduces a simpler syntax to create initialized Dictionary<TKey,TValue> objects without having to specify either the Dictionary type name or the type parameters. The type parameters for the dictionary are inferred using the existing rules used for array type inference.

// C# 1..8    
var x = new Dictionary <string,int> () { { "foo", 4 }, { "bar", 5 }};   
// C# 9    
var x = ["foo":4, "bar": 5];  

This synthax makes the work with dictionaries in C# simpler and removing the redundant code.

You can follow the issue on GitHub (and here is the milestone for C#9).

Edit: This proposal is currently rejected:

[...] We think there are a number of interesting use cases around initializing data, particularly for things like immutable dictionaries. We don't find the existing syntax for initializing a dictionary that onerous, nor do we see it as a frequent pattern in code that would benefit much from a language feature. We thing that the general area of initializing data should be looked at again after we do records and withers. [...]

current milestone:

likely never

Note that beginning with C# 9.0, constructor invocation expressions are target-typed. That is, if a target type of an expression is known, you can omit a type name, as the following example shows:

Dictionary<int, List<int>> lookup = new()
{
    [1] = new() {1, 2, 3},
    [2] = new() {5, 8, 3},
    [5] = new() {1, 0, 4}
};

As the preceding example shows, you always use parentheses in a target-typed new expression.

If a target type of a new expression is unknown (for example, when you use the var keyword), you must specify a type name.

MSDN

若无相欠,怎会相见 2024-10-24 06:45:45

使用DynamicObject,创建一个更简单的字典初始值设定项并不困难。

调用以下方法

void PrintDict(IDictionary<string, object> dict) {
    foreach(var kv in dict) {
        Console.WriteLine ("  -> " + kv.Key + " = " + kv.Value);
    }
}

想象一下您想要使用像这样的文字语法来

var dict = Dict (Hello: "World", IAm: "a dictionary");
PrintDict (dict);

这可以通过创建像这样的动态对象来完成

dynamic Dict {
    get {
        return new DynamicDictFactory ();
    }
}

private class DynamicDictFactory : DynamicObject
{
    public override bool TryInvoke (InvokeBinder binder, object[] args, out object result)
    {
        var res = new Dictionary<string, object> ();
        var names = binder.CallInfo.ArgumentNames;

        for (var i = 0; i < args.Length; i++) {
            var argName = names [i];
            if(string.IsNullOrEmpty(argName)) throw new ArgumentException();
            res [argName] = args [i];
        }
        result = res;
        return true;
    }
}

Using DynamicObject, it is not that difficult to create a simpler dictionary initializer.

Imagine you want to call the following method

void PrintDict(IDictionary<string, object> dict) {
    foreach(var kv in dict) {
        Console.WriteLine ("  -> " + kv.Key + " = " + kv.Value);
    }
}

using a literal syntax like

var dict = Dict (Hello: "World", IAm: "a dictionary");
PrintDict (dict);

This can be accomplished by creating a dynamic object like this

dynamic Dict {
    get {
        return new DynamicDictFactory ();
    }
}

private class DynamicDictFactory : DynamicObject
{
    public override bool TryInvoke (InvokeBinder binder, object[] args, out object result)
    {
        var res = new Dictionary<string, object> ();
        var names = binder.CallInfo.ArgumentNames;

        for (var i = 0; i < args.Length; i++) {
            var argName = names [i];
            if(string.IsNullOrEmpty(argName)) throw new ArgumentException();
            res [argName] = args [i];
        }
        result = res;
        return true;
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文