为什么要呼吁:这种()上一个结构来使用自动性质在c#?
-
07-07-2019 - |
题
如果我定义是一个结构中的C#使用自动性是这样的:
public struct Address
{
public Address(string line1, string line2, string city, string state, string zip)
{
Line1 = line1;
Line2 = line2;
City = city;
State = state;
Zip = zip;
}
public string Line1 { get; protected set; }
public string Line2 { get; protected set; }
public string City { get; protected set; }
public string State { get; protected set; }
public string Zip { get; protected set; }
}
当我试图建立的文件,我得到一个编辑错误说 The 'this' object cannot be used before all of its fields are assigned to
.这可以解决改变的构造,使一个链接电话到默认的构造是这样的:
public Address(string line1, string line2, string city, string state, string zip): this()
{
Line1 = line1;
Line2 = line2;
City = city;
State = state;
Zip = zip;
}
我的问题是,为什么这项工作中,并发生了什么事?我猜猜,我试图证明它看IL,但我只是开玩笑,我自己如果我想我可以打破IL。但是我猜是自动性的工作,通过具有的编译器生成的领域为你的属性。这些领域无法通过访问代码,所有的设定和取得必须通过的特性。在创建一个结构,一个默认的构造不能明确定义。所以幕后,编译器必须产生一种默认的构造,将价值观的领域,开发人员不能看到。
任何和所有的IL向导的欢迎来证明或反驳我的理论。
解决方案
注意:从C#6开始,这不是必需的 - 但您应该使用C#6的只读自动实现的属性...
this()
确保在编译器方面明确分配字段 - 它将所有字段设置为其默认值。在开始访问任何属性之前,您必须拥有一个完全构造的结构。
这很烦人,但就是这样。你确定你真的希望这是一个结构吗?为什么在结构上使用受保护的setter(不能从中派生出来)?
其他提示
一个酒店有什么比一封装的 Get
方法和/或 Set
法。CLR有的元数据,它表示,特定的方法应该被视为一个属性、意义的编纂者应该允许一些结构,这将不允许与方法。例如,如果 X
是一个读写酒店的 Foo
, 一个编译器将翻译 Foo.X += 5
入 Foo.SET_X_METHOD(Foo.GET_X_METHOD() + 5)
(虽然该方法不同的名称,而不是通常可通过名)。
虽然autoproperty实现对get/set方法的其访问一个私人领域,在这样一种方式的行为或多或少像一个领域,从任何代码之外的财产,一个autoproperty是一对get/set方法,就像任何其他财产。因此,这样的声明 Foo.X = 5;
被翻译为 Foo.SET_X_METHOD(5)
.由于C#编译器只是认为,作为一种方法,呼叫,并且由于方法不包括任何元数据以表明哪些领域他们阅读或写,编译器将禁止的方法的呼吁,除非它知道每个现场的 Foo
已经编写的。
就个人而言,我的建议是避免使用autoproperties与结构类型。Autoproperties意义上课,因为这是可能的类属性,以支持功能,如更新的通知。即使早期版本的一类不支持更新的通知的,具有这些版本使用autoproperty而不是一场意味着,未来的版本可以加入更新的通知的功能,而不要求消费者的类重新设计。结构,但是,不能有意义地支持大多数类型的特点,人们可能希望添加到领域的性能。
另外,绩效之间的差异领域和特性要大得多大的结构比它与类型。事实上,很多的建议,以避免大型结构,是因为这种差异。大的结构实际上可以非常有效,如果一个可以避免复制的他们不必要的。即使一个已经一个巨大的结构 HexDecet<HexDecet<HexDecet<Integer>>>
, ,哪里 HexDecet<T>
包含暴露的领域 F0
..F15
的类型 T
, 发言喜欢 Foo = MyThing.F3.F6.F9;
将只需要阅读一个的整数 MyThing
和储存它 Foo
, 虽然 MyThing
将通过巨大的结构标准(4096整数占领16K).另外,一个可能的更新,这件很容易的,例如 MyThing.F3.F6.F9 += 26;
.相比之下,如果 F0
..F15
是自动性质,该声明 Foo = MyThing.F3.F6.F9
需要复制1K的数据 MyThing.F3
临时(称呼它 temp1
, 然后64字节的数据 temp1.F6
要 temp2
),最后才得到读4个字节的数据 temp2.F9
.Ick.更糟糕的是,在努力增加26的价值 MyThing.F3.F6.F9
将需要一些东西喜欢 var t1 = MyThing.F3; var t2 = t1.F6; t2.F9 += 26; t1.F6 = f2; MyThing.F3 = t1;
.
许多长期投诉的关于"可变的结构类型"是真正的投诉有关的结构类型,具有读写性质。只是替代性的领域和问题消失。
PS:有时它可以是有用的,有一个结构,其属性访问的一类对象它拥有一个参考。例如,这将是很好有一个版本 ArraySegment<T>
类,它允许一个来说 Var foo[] = new int[100]; Var MyArrSeg = New ArraySegment<int>(foo, 25, 25); MyArrSeg[6] += 9;
, 和最后一句添加到九元(25+6) foo
.在旧版本的C#一个能做到这一点。不幸的是,经常使用的autoproperties在该框架中的领域将有更多的适当导致普遍的抱怨编译器,允许财产者被称为无益于只读结构;因此,呼吁任何财产定者在一个只读结构是现在被禁止的,是否或不属装定实际上将修改的任何领域的结构。如果人们根本没有制结构的可变通性制定者(作领域直接访问的时候可变性是适当的)编译器永远不会有实现这种限制。