在返回之前测试属性是否为空
我有以下财产
public MyType MyProperty {get;set;}
我想更改此属性,以便如果值为null,它将首先填充该值,然后返回它…但不使用私有成员变量。
例如,如果我这样做:
public MyType MyProperty { get { if (_myProperty != null) return _myProperty else _myProperty = XYZ; return _myProperty; } set { _myProperty = value; } }
这可能吗? 或者我需要成员变量才能完成它?
您需要一个成员变量和一个完整的属性声明。 自动实现的属性仅在它们是字段周围的无关包装时才适用,不涉及逻辑。 你可以稍微简化你的getter代码,顺便说一下:
get { if (_myProperty == null) { _myProperty = XYZ; } return _myProperty; }
(注意,如果没有额外的锁定,这些都不是线程安全的,但我认为没关系。)
顺便说一句,如果你使用自动实现的属性,你已经有了一个私有成员变量 – 只是编译器为你生成它。
return _myProperty?? (_myProperty = XYZ);
你能做的最好的事情就是在构造函数中给它一个值。 我知道这样你就失去了“延迟加载”,但你不能同时拥有自动属性和延迟加载。
你的代码:
public MyType MyProperty {get;set;}
请参阅“ 自动属性 ”,这只是“语法糖”,你可以在这里查看 。
编译器为属性生成字段,并在get集中生成指向该字段的代码。
internal class ClassName { // Fields [CompilerGenerated] private MyType
k__BackingField; // Properties public MyType MyProperty { [CompilerGenerated] get { return this. k__BackingField; } [CompilerGenerated] set { this. k__BackingField = value; } } }
因此,您的代码将始终由编译器生成的字段支持。
你将需要一个私有变量来实现它,因为你的getter / setter中有逻辑。
如果您希望对获取或设置属性的行为进行任何修饰,那么您将丢失编译器生成的存储位置,因此您必须自己将值存储在某处。 私有成员变量在大多数情况下最有意义。
我建议考虑使用Lazy初始化 。 它不会帮助你避免成员变量,对此抱歉,但该代码将帮助您避免成员变量的内存预留,直到您的类需要该变量:
public class MyType { public MyType() { XYZ(); } public void XYZ() { //some kind of initialization } } public class TestType { private Lazy _myProperty; public MyType MyProperty { get { return _myProperty.Value; }//_myProperty will be null until some code will try to read it } }
要指出或实际提醒的另一件事是,你将无法绝对没有成员变量。 因为窗帘后面.Net编译器会创建该成员变量而不是你。 它只是不会通知您这一步骤。 但正如其他人所提到的那样,如果查看生成的MSIL,您将看到为您创建的成员变量。
您需要使用成员变量来完成它:
public class MyClass { MyType _myProperty = null; public MyType MyProperty { get { if(_myProperty == null) _myProperty = XYZ; return _myProperty; } } }
通过“成员变量”我假设你的意思是在属性get中定义的变量。 是的,您当然不需要本地定义的变量。 保存代码行代码的更常见模式是:
if (_myProperty == null) _myProperty = XYZ; return _myProperty;
如果通过“成员变量”表示支持字段,那么是的,您确实需要一个。 只有完全简单的“传递”字段/属性关系才能实现,而无需显式创建支持字段。 (即便如此,它也是由编译器创建的。)要实例化-if-null,您需要显式定义它。
是的,这是可能的。 但是你必须自己实现它,而不是自动属性。 您的属性不一定只需要使用成员变量,尽管这是默认值。
请记住,属性实际上已转换为Getter和Setter方法,您可以在其范围内执行大量工作。 虽然这种做法通常是气馁的。 良好实践表明,属性访问应该是快速的,并且不会长时间阻止客户端代码。
你可以这样做:
public MyType MyProperty { get { if (_myProperty != null) return _myProperty else return XYZ; } set { _myProperty = value; } }
仅当您使用成员变量时。
通常,我将延迟加载与IDisposable的实现结合起来,以便可以在Dispose方法中处理任何需要清理的变量。
如果需要该属性,那么一些检查可以使其防弹。 我倾向于使用类似的东西:
public MyType MyProperty { get { if (_myProperty == null) _myProperty == XYZ; return _myProperty; } set { if(value == null) throw InvalidArgumentException(); _myProperty = value; } }
使TDD更简单。
试试这个
Public Class MyClass { Public MyType Alfa { If(this._Alfa == null) this.SetAlfa(); return _Alfa; } private MyType _Alfa {get;set;} private void SetAlfa() { //Somenthing to valorize _Alfa } }