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

C#中字典的文字表示法?,c#,dictionary,literals,C#,Dictionary,Literals,我目前在JavaScript和用C#编程的服务器之间有一个WebSocket。在JavaScript中,我可以使用关联数组轻松传递数据: var data = {'test': 'val', 'test2': 'val2'}; 为了在服务器端表示此数据对象,我使用了一个字典,但这比JavaScript中的输入更“昂贵”: Dictionary<string, string> data = new Dictionary<string,string>

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

var data = {'test': 'val',
            'test2': 'val2'};
为了在服务器端表示此数据对象,我使用了一个
字典
,但这比JavaScript中的输入更“昂贵”:

Dictionary<string, string> data = new Dictionary<string,string>();
data.Add("test", "val");
data.Add("test2", "val2");
字典数据=新字典();
数据。添加(“测试”、“val”);
添加数据(“test2”、“val2”);
C#中的关联数组/
字典
s是否有某种文字符号?

您使用了语法,但仍然需要先创建一个
新字典
对象,因为快捷语法被转换为一系列
Add()
调用(如您的代码):

var数据=新字典
{
{“test”,“val”},
{“test2”,“val2”}
};
在C#6中,您现在可以选择使用更直观的语法与Dictionary以及支持的任何其他类型。上述声明可以改写为:

var data = new Dictionary<string, string>
{
    ["test"] = "val",
    ["test2"] = "val2"
};
var数据=新字典
{
[“测试”]=“val”,
[“test2”]=“val2”
};

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

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

var data = new { test1 = "val", test2 = "val2"};
“data”变量是一种“无法说出的”匿名类型,因此您只能将其作为
System.Object
传递。然后可以编写代码,将匿名对象转换为字典。这样的代码将依赖于反射,这可能会很慢。但是,您可以使用
System.Reflection.Emit
System.Linq.Expressions
来编译和缓存委托,从而使后续调用更快


Asp.NETMVCAPI在我见过的许多地方都使用这种技术。许多Html帮助程序都有接受对象或字典的重载。我假设他们的API设计目标与您所追求的目标相同;在方法调用时使用简洁的语法。

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

假设您要调用以下方法

void PrintDict(IDictionary<string, object> dict) {
    foreach(var kv in dict) {
        Console.WriteLine ("  -> " + kv.Key + " = " + kv.Value);
    }
}
这可以通过创建这样的动态对象来实现

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;
    }
}
动态Dict{
得到{
返回新的DynamicDictFactory();
}
}
私有类DynamicDictFactory:dynamicbject
{
public override bool TryInvoke(InvokeBinder绑定器,对象[]args,输出对象结果)
{
var res=newdictionary();
变量名称=binder.CallInfo.ArgumentNames;
对于(变量i=0;i
使用字典文字(C#9提案)[被拒绝] C#9引入了一种更简单的语法来创建初始化的
Dictionary
对象,而无需指定Dictionary类型名称或类型参数。使用用于数组类型推断的现有规则推断字典的类型参数

// C# 1..8    
var x = new Dictionary <string,int> () { { "foo", 4 }, { "bar", 5 }};   
// C# 9    
var x = ["foo":4, "bar": 5];  
/C#1..8
var x=新字典(){{“foo”,4},{“bar”,5};
//C#9
变量x=[“foo”:4,“bar”:5];
这个synthax使得使用C#中的字典的工作更简单,并且删除了冗余代码

你可以继续关注这个问题(这里是答案)

编辑:此提案当前被拒绝:

[…]我们认为在初始化数据方面有许多有趣的用例,特别是对于不可变字典之类的东西。我们没有发现用于初始化字典的现有语法如此繁重,也没有将其视为代码中的常见模式,从而从语言特性中获益匪浅。我们认为,初始化数据的一般区域应该在我们做记录和删除之后再次检查。[……]

当前里程碑:


请注意,严格地说,它不是文字符号。。。这只是初始化的快捷方式。只有字符串和某些基本类型具有文字表示如果您的意思是要删除其中一个“字符串”-它们不是冗余的-一个用于键类型,另一个用于值类型。没有专门针对字典的文字,这个答案中使用的符号对于所有带有Add方法的类来说都是通用的,Add方法包含两个字符串(并实现IEnumerable)。@Markus Johnsson:他的字面意思是,
Dictionary
。我的代码最初声明了该类型,在他的评论之后,我刚刚将其更改为
var
。关于c#6语法的警告-重复的键条目不会引发任何异常。相反,“最新”的键/值对将始终优先。只有当键集是静态的时,这才有帮助。您也可以出于同样的目的使用元组。C#9包含字典文本的建议。我发了一封信。我们的梦想成真了!好主意,希望它能实现,似乎不需要动脑筋
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;
    }
}
// C# 1..8    
var x = new Dictionary <string,int> () { { "foo", 4 }, { "bar", 5 }};   
// C# 9    
var x = ["foo":4, "bar": 5];