编译错误。将属性与结构一起使用
请解释以下有关结构构造函数的错误。如果我将结构更改为类 错误消失了。
public struct DealImportRequest
{
public DealRequestBase DealReq { get; set; }
public int ImportRetryCounter { get; set; }
public DealImportRequest(DealRequestBase drb)
{
DealReq = drb;
ImportRetryCounter = 0;
}
}
- 之前,无法使用该对象
- 错误CS0188:在将“this”对象的所有字段分配给错误CS0843:自动实现的属性的支持字段 在控制权返回给调用者之前,必须完全分配“DealImportRequest.DealReq”。考虑从构造函数初始值设定项调用默认构造函数。
Please explain the following error on struct constructor. If i change struct to class
the erros are gone.
public struct DealImportRequest
{
public DealRequestBase DealReq { get; set; }
public int ImportRetryCounter { get; set; }
public DealImportRequest(DealRequestBase drb)
{
DealReq = drb;
ImportRetryCounter = 0;
}
}
- error CS0188: The 'this' object cannot be used before all of its fields are assigned to
- error CS0843: Backing field for automatically implemented property
'DealImportRequest.DealReq' must be fully assigned before control is returned to the caller. Consider calling the default constructor from a constructor initializer.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
正如错误消息所建议的,您可以通过从构造函数初始值设定项调用默认构造函数来解决此问题。
从语言规范来看:
,另一种(更详细)替代方案是手动实现属性并在构造函数中自行设置支持字段。
请注意,您拥有的结构是可变的。 不建议这样做。我建议您要么将类型设置为类(您的编译问题应该立即消失),要么将类型设置为不可变。实现此目的的最简单方法是假设您提供的代码是整个结构,则将设置器设置为私有(
get; private set;
)。当然,您还应该确保之后不会向结构添加任何依赖私有访问来修改字段的变异方法。或者,您可以使用readonly
支持字段来支持属性,并完全删除 setter。As the error message recommends, you can resolve this by calling the default constructor from a constructor initializer.
From the language specification:
The other (more verbose) alternative, of course, is to manually implement the properties and set the backing fields yourself in the constructor.
Do note that the struct you have there is mutable. This is not recommended. I suggest you either make the type a class (your compilation problems should go away immediately) or make the type immutable. The easiest way to accomplish this, assuming the code you have presented is the entire struct, would be to make the setters private (
get; private set;
). Of course, you should also make sure that you don't add any mutating methods to the struct afterwards that rely on private access to modify the fields. Alternatively, you could back the properties withreadonly
backing fields and get rid of the setters altogether.您拥有的代码相当于以下代码:
现在,我在这里所做的就是删除以下语法糖:
this
处理哪些成员。struct
提供默认的无参数构造函数。前两个是可选的(如果您愿意,您可以显式地编写它们),但第三个不是 - 我们不允许为
struct
的无参数构造函数编写自己的代码,我们必须这样做与上面代码中的代码类似的代码会自动提供给我们。现在,看看这里,两个错误的含义突然变得清晰起来 - 您的构造函数在分配字段之前隐式使用
this
(错误 188),而这些字段是支持自动属性的字段(错误 843 )。它是不同自动功能的组合,通常我们不必考虑,但在这种情况下效果不佳。我们可以通过遵循 843 错误消息中的建议并调用默认构造函数作为显式构造函数的一部分来解决此问题:
考虑到这与我上面代码的扩展版本相关,您可以看到这是如何解决问题的,因为它在继续之前调用分配给支持字段的构造函数。
The code you have is equivalent to the following code:
Now, all I have done here is remove the syntactic sugar that:
this
.struct
s a default no-parameter constructor.The first two are optional (you could write them explicitly if you wished) but the third is not - we aren't allowed to write our own code for a
struct
's parameterless constructor, we have to go with one that works like the one in the code above being given to us automatically.Now, looked at here, suddenly the meaning of the two errors becomes clear - your constructor is implicitly using
this
before it's fields are assigned (error 188) and those fields are those backing the automatic properties (error 843).It's a combination of different automatic features that normally we don't have to think about, but in this case don't work well. We can fix this by following the advice in the error message for 843 and calling the default constructor as part of your explicit constructor:
Considering this in relation to my expanded version of your code above, you can see how this solves the problem, because it calls the constructor that assigns to the backing fields before it proceeds.
我建议不要将自动属性与结构一起使用,除非您有充分的理由使用它们。将类字段包装在读写属性中非常有用,因为它使实例可以控制可以读取或写入的环境,并在发生读取或写入时采取操作。此外,对象实例内的代码可以识别被操作的实例,并且因此可以仅在读取和写入特定实例时执行特殊操作。在类的早期版本中使用自动属性将使该类的未来版本可以使用手动实现的属性,包括上述优点,同时保留与已编译的客户端代码的兼容性。不幸的是,将结构体字段包装在读写属性中并不能提供同样的好处,因为一个结构体实例的字段可以复制到另一个结构体实例,而任一实例对此没有任何发言权。如果结构体的语义允许在大多数情况下使用任意值写入属性(就像自动属性的情况一样),那么任何合法的替换在语义上都等同于字段。
I would recommend not using auto-properties with structures unless you have a good reason to use them. Wrapping a class field in a read-write property is useful because it makes it possible for an instance to control the circumstances where it may be read or written, and take action when a read or write takes place. Further, code within an object instance can identify the instance being acted upon, and may thus perform a special action only when reading and writing a particular instance. Using an auto-property in an early version of a class will make it possible for future versions of the class to use a manually-implemented property including the aforementioned benefits while retaining compatibility with already-compiled client code. Unfortunately, wrapping a struct field in a read-write property doesn't offer those same benefits because the fields of one struct instance can be copied to another without either instance having any say in the matter. If the semantics of a struct allow a property to be written with arbitrary values in most instances [as would be the case for an auto-property], then any legitimate replacement would be semantically equivalent to a field.