当前位置: 首页 > 编程语言 > C#

可在构造函数外赋值的只读字段分享

时间:2023-04-10 12:57:10 C#

可在构造函数外赋值的只读字段有没有办法在一个类中有一个私有的只读字段,可以被类中的任何地方赋值,但只赋值一次?也就是说,我在寻找一个私有只读类型的字段,它只能被赋值一次,但不一定在构造函数中。因此,如果您将一个值重新分配给一个字段,那么它将显示一个编译时错误(我敢肯定这是要求太多了)。真的很想知道是否有任何模式(不是语言功能)可以完成同样的工作。感谢您的关注。最简短的回答是否定的。唯一可以进行编译器检查的一次性赋值的地方是在构造函数中。您可以创建一个系统,如果多次尝试分配但没有C#构造来执行此操作,该系统将导致运行时错误。您不会遇到编译时错误,但您可以使用属性完成您要查找的内容。在setter中,仅当内部bool/flag为false时才设置值。第一次设置后,将标志设置为真。如果另一段代码再次调用setter,你可以抛出一个InvalidOperationException让他们知道它已经被初始化了privateboolfieldAlreadySet=false;私有字符串字段;publicstringField{get{returnfield;}set{if(fieldAlreadySet)thrownewInvalidOperationException("fieldalreadyset");this.field=值;fieldAlreadySet=true;您可以创建一个通用结构来自动执行该过程:publicstructWriteOnce{privateT?_价值;公共T值{获取{返回值;}set{if(_value.HasValue)thrownewInvalidOperationException();_value=值;}}}编辑我刚刚意识到上面的甚至不会编译。编译器不允许_value为Nullable类型,因为Nullable中的T必须是不可为null的类型。这是一个效果更好的实现:publicstructWriteOnce{privateT_value;私人布尔_hasValue;publicboolHasValue{get{return_hasValue;}}publicTValue{get{return_value;}set{if(HasValue)thrownewInvalidOperationException();_value=值;_hasValue=真;}}publicstaticimplicitoperatorT(WriteOncex){returnx.Value;}publicWriteOnce(Tval){_value=val;_hasValue=真;我说它会更好——并不是说它会很好用。使用它也有一些问题:首先,如果编译器检测到你试图在没有先给它赋值的情况下使用它,它就会报错。像这样初始化它会解决这个问题:WriteOncefoo=default(WriteOnce);其次,即使它在修改时抛出异常,C#仍然会很乐意让您重写它。因此,虽然这确实封装了一些功能;如果它最终暴露在对象的接口中,您仍然应该将它包装在一个属性中以防止滥用。私人WriteOnce_someInt=默认值(WriteOnce);publicintSomeInt{得到{返回_someInt;}设置{_someInt.Value=值;然而,这仍然没有真正修复我在原始代码段中提交的最后一个严重错误,该错误创建了一个可变结构。如果你做了很多这样的事情,为了不重蹈覆辙,违反这个原则可能是值得的,但这绝对是一个潜在的陷阱,需要仔细注释掉并远离任何公共接口。但是,其他人建议的直接实现该属性的方法如果只是一次性的,则不那么复杂和安全。您可以使用私有属性来检查它是否已分配给它,并且只有在未分配时才分配值。诠释?_writeOnceField;私人诠释?WriteOnce{设置{如果(!_writeOnceFiled.HasValue){writeOnceFiled=值;}else{//Throwexception}}}没有语言支持,但是你可以创建一个实现你想要的行为的setter。显然,这不会给您带来编译时错误,但如果没有语言支持,这可能是您能做的最好的事情。这看起来很适合声明赋值或单例。publicclassSomeClass{privatereadonlyTypet=typeof(SomeClass);或者正如其他人所说,只需使用setter创建一个内部或该属性,然后为其分配一个值。公共类SomeClass{私有类型t;内部类型类型{设置{if(t==null)t=value;如果在构造函数中完成,我想我已经实现了一个方法。它也可以在变量声明行上。如果在这些上下文之外完成,你会得到错误:Cannotassignread-onlyfield(exceptconstructororvariableinitialiser)如果对你有用,需要了解更多C#学习教程,希望你多多关注——publicclassBillLine{publicBillLine(Billbill){m_Bill=bill;}privatereadonlyBillm_Bill;公共账单Bill{get{returnm_Bill;}//应该只在构造函数中设置}//(...)}本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处: