【问题标题】:Why this confusing syntax exists?为什么存在这种令人困惑的语法?
【发布时间】:2018-09-02 03:51:40
【问题描述】:

我刚刚阅读了this question

如果我们有字典类型的属性:

public class Test
{
    public Dictionary<string, string> Dictionary { get; set; } = new Dictionary<string, string>
    {
        {"1", "1" },
        {"2", "2" },
    };
}

然后我们可以构造对象并为其添加价值

 var test = new Test { Dictionary = { { "3", "3" } } };
 Console.WriteLine(test.Dictionary.Count); // 3

而且我不明白为什么存在这样一种令人困惑的语法添加项目?在查看其他人的代码时,很容易将其与 非常相似的外观

混淆
 var test = new Test { Dictionary = new Dictionary<string, string> { { "3", "3" } } };
 Console.WriteLine(test.Dictionary.Count); // 1

如果可以进行以下操作,我会更好(但事实并非如此):

var dictionary = new Dictionary<string, string> { { "1", "1" } };
...
// adding a new value
dictionary = { { "2" , "2"} }; // invalid expression term '{'

那么为什么需要并存在这种添加形式?面试?

【问题讨论】:

  • 为了让代码更简洁 - docs.microsoft.com/en-us/dotnet/csharp/programming-guide/… 。我同意,在实践中,您希望避免使用它(没有new)。
  • 我也有同样的想法,很好的问题......不过非常基于意见。
  • 应该注意,它只有在嵌套在另一个初始化器中时才会起作用。基本上,如果正确完成,您可以初始化一个复杂的对象,并且它是“一行”中的依赖项,避免了很多重复的语法。
  • @TimSchmelter 那不会创建字典。这只有在Test 在构造期间创建字典时才有效,然后{ { "", "" } } 只是在该实例上调用Add
  • 所以初始化有一些在赋值中没有意义的快捷方式(或者没有实现)。

标签: c# collections object-initializers


【解决方案1】:

Thing 的构造函数创建StuffStuff 的构造函数创建Foo 列表为例

var thing = new Thing();
thing.Stuff.Foo.Add(1);
thing.Stuff.Foo.Add(2);
thing.Stuff.Foo.Add(3);

现在您可以使用初始化器将其简化为以下内容。

var thing = new Thing 
{
    Stuff.Foo = { 1, 2, 3 }
};

在嵌套时,您只能对集合使用这种类型的初始化,而无需首先更新集合,因为在这种情况下集合可以存在,但在直接分配给变量时不能存在。

当语言设计者看到他们认为可以简化的代码模式时,最终可能会添加这种类型的语法糖。

【讨论】:

    【解决方案2】:

    集合初始值设定项语法只是一种使用对象初始值设定项将集合(包括字典)作为复杂对象模型的一部分进行初始化的简便方法。例如:

    var model = new SomeModel {
       Name = "abc",
       Id = 42,
       SpecialMaps = {
           { "foo", "bar" },
           { "magic", "science" },
       }
    };
    

    如果您不喜欢它:就不要使用它;但是手动.Add 的等效项在 IMO 中就没有那么优雅了——很多事情都是自动处理的,比如只读取一次属性。实际同时创建集合的较长版本的工作方式非常相似。

    请注意,现在还有一个索引器变体:

    var model = new SomeModel {
       Name = "abc",
       Id = 42,
       SpecialMaps = {
           ["foo"] = "bar",
           ["magic"] ="science",
       }
    };
    

    这非常相似,但不是使用collection.Add(args);,而是使用collection[key] = value;。同样,如果它让你感到困惑或冒犯了你:不要使用它。

    【讨论】:

    • 那个赋值= 的意思是 Add 我会说有点令人困惑,但我认为可以派上用场。
    • @Magnus,没错。这是一个赋值,它不是从右侧分配对象,而是像一个联合,它没有足够独特的语法。缺少new 很容易错过。如果 union 的语法在构造对象之外是可能的,我不会抱怨。我会接受这个答案,但我希望有一些有趣的背景来说明为什么会这样。
    • 他们应该改用+= :-)
    • @Magnus,是的,dictionary += { {"2", "2"}, {"3", "3"} }; 会很方便,而不是多个dictionary.Add()。值得request a feature?但这不会改变已经完成的事情。 /掌脸
    猜你喜欢
    • 1970-01-01
    • 2014-11-24
    • 1970-01-01
    • 1970-01-01
    • 2015-05-02
    • 2018-06-08
    • 2021-01-16
    • 1970-01-01
    • 2011-09-12
    相关资源
    最近更新 更多