C#学习教程:协变对象初始化器?分享


协变对象初始化器?

假设我有一个具有字典的属性的类,使用对象初始化器我可以使用这种语法(我觉得看起来很干净):

new MyClass() { Table = { {"test",true},{"test",false} } } 

但是,在初始化程序之外我不能这样做:

 this.Table = { {"test",true},{"test",false} }; 

为什么初始化器是特例? 我猜测它与LINQ要求,协方差或诸如此类的东西有关,但感觉有点不一致,无法在任何地方使用这种初始化器……

这个问题有些令人困惑,因为这个问题与LINQ无关,与generics方差无关,并且具有集合初始值设定项以及对象初始值设定项。 真正的问题是,据我所知,“ 为什么在对象创建表达式之外使用集合初始化器是不合法的?

这里的相关设计原则是,一般来说,我们希望创建和初始化对象的操作在其中包含单词“new”作为向读者发出的信号,即此处发生了对象创建。 (是的,这个规则在C#中有一些例外。作为读者的练习,看看你是否可以将它们全部命名。)

按照自己的方式做事会让人更难理解代码。 快,这是做什么的?

 d = new List() { 10, 20, 30 }; d = { 40, 50, 60 }; 

第二行是否 40,50,60 附加到现有列表中? 或者它用新的列表替换旧列表? 那里没有“新”,读者是否期望创建一个新对象?

当你说

 q = new Whatever() { MyList = { 40, 50, 60 } }; 

这不会创建新列表; 它将40,50,60附加到构造函数分配的现有列表中。 因此,您建议的语法是否含糊不清,并且是否创建了新列表。

建议的function既令人困惑又不必要,因此不太可能很快实施。

这个限制远比LINQ早。 即使回到C,你也可以写

 int numbers[5] = {1, 2, 3, 4, 5}; 

但您无法使用此语法为数组赋值。

我猜测C#背后的原因是通常你不应该对两个不同的对象使用相同的引用。 如果您需要为现有引用分配新集合,很可能您没有很好地设计代码,您可以根据定义初始化集合,也可以使用两个单独的引用而不是一个。

考虑您的语法在运行时抛出NullReferenceException – 您确定可以使用它吗?

 public class Test { public Dictionary Table {get; set;} } public void TestMethod() { Test t = new Test { Table = { {"test", false} } }; //NullReferenceException } 

这将编译为以下(通过reflection器):

 Test <>g__initLocal3 = new Test(); <>g__initLocal3.Table.Add("test", 0.0M); 

如您所见, Table未初始化,因此在运行时产生NullReferenceException

如果在Test的ctor中创建Dictionary,则类初始化程序会生成一系列Add语句,这是初始化程序中的语法糖(对于IEnumerable s)。

由于我们无法看到或想象的不可预见的副作用,这可能不是正常代码引入的。 Eric Lippert可能会提供帮助,因为他可能对手头的问题有了更多的了解。

上述就是C#学习教程:协变对象初始化器?分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—猴子技术宅(www.ssfiction.com)

本文来自网络收集,不代表猴子技术宅立场,如涉及侵权请点击右边联系管理员删除。

如若转载,请注明出处:https://www.ssfiction.com/ckf/1032027.html

发表评论

邮箱地址不会被公开。 必填项已用*标注