[英]Should I use a private field of a public property inside a class where I declare that property?
Let say I have a class like this: 假设我有一个这样的课程:
public class A
{
private BaseSettings fieldA;
public ISettings PropertyA
{
get {return fieldA;}
set {fieldA= value as BaseSettings;}
}
}
where BaseSettings implements ISettings. 其中BaseSettings实现ISettings。 Inside class A, if I want to access BaseSettings' property called PropertyB, which of this is a good practice:
在类A内,如果我想访问BaseSettings的名为PropertyB的属性,这是一个好习惯:
fieldA.PropertyB;
or 要么
((BaseSettings)PropertyA).PropertyB;
One may say the first approach may hide the hint to when a property changed. 可能有人说第一种方法可能会将提示隐藏在属性更改时。 For example, a code may listen to PropertyChangedEvent and then the value for property changed without raising the event.
例如,代码可以侦听PropertyChangedEvent,然后在不引发事件的情况下更改属性的值。
Another one may say the second approach may expose a risk that when a person who is not familiar with current code modify it, he may cast the PropertyA to different type that implements ISettings. 另一个人可能会说,第二种方法可能会带来这样的风险:当不熟悉当前代码的人对其进行修改时,他可能会将PropertyA强制转换为实现ISettings的其他类型。
Both approaches have its downside. 两种方法都有其缺点。 In a good programming practice, which one should be more preferable?
在良好的编程习惯中,哪一个更可取?
EDIT: Added based on the comments belows: 编辑:根据以下评论添加:
I agree that setting the backing-field as ISettings makes absolute sense. 我同意将后备字段设置为ISettings是绝对有意义的。 But what should I do to make sure that the PropertyA is always type of BaseSettings.
但是,我应该怎么做才能确保PropertyA始终是BaseSettings的类型。 That will raise a question: "Then why don't you set both property and backing-field to BaseSettings?".
这将引发一个问题:“那为什么不同时将属性和后备字段都设置为BaseSettings?”。
The reason behind why property and its backing field are different is that class A also implement an interface like this 属性及其支持字段不同的原因在于,类A也实现了这样的接口
public interface IControlWithSettings
{
ISettings OwnerSettings
{
get;
set;
}
ISettings Settings
{
get;
set;
}
}
So the actual classA would look like this 所以实际的classA看起来像这样
public class BaseForm: Form, IControlWithSettings
{
private BaseFormSettings settings;
public ISettings Settings
{
get {return settings;}
set {settings= value as BaseFormSettings;}
}
}
And I have another class B would also implement IControlWithSettings 我还有另一个B类也可以实现IControlWithSettings
public class BaseUserControl: UserControl, IControlWithSettings
{
private BaseUserControlSettings settings;
public ISettings Settings
{
get {return settings;}
set {settings= value as BaseUserControlSettings ;}
}
}
Both BaseFormSettings : ISettings
and BaseUserControlSettings : ISettings
. BaseFormSettings : ISettings
和BaseUserControlSettings : ISettings
。 This is actual ISettings interface 这是实际的ISettings界面
public interface ISettings
{
Dictionary<string, ISettings> Children { get; set; }
}
the 'as' casting is a side effect I put into the setter so that it will ignore and return null if the setting is set to wrong one. 我将“ as”强制转换是设置器中的一个副作用,如果设置设置为错误的设置,它将忽略并返回null。 I read somewhere saying I shouldn't throw exception in a setter.
我在某处读到说我不应该在二传手中抛出异常。 So making it null is my way to inform there is something wrong has been done.
因此,将其设为null是我告知发生了某些错误的方式。
So what is the better approach. 那么什么是更好的方法。 Did I design it wrong?
我设计错了吗?
As you stated, both approaches have their downsides, and it also depends on whether the property setter may contain some additional logic (eg validation), and you may use or circumvent this additional logic from inside the class. 如您所述,这两种方法都有其缺点,并且还取决于属性设置器是否可能包含某些其他逻辑(例如,验证),您可以在类内部使用或规避此其他逻辑。
If there's nothing that speaks against it, I'll use direct access to the field. 如果没有什么可以反对的,我将使用直接访问该字段的方法。 It's neater and it avoids all this typecasting stuff.
它更加整洁,并且避免了所有此类转换。
But generally: Why would you back your property with the derived type, while the property itself has the interface type? 但是通常:为什么在属性本身具有接口类型的情况下,为什么要使用派生类型来支持属性? This doesn't make much sense.
这没有多大意义。 Why not just:
为什么不只是:
public class A
{
public ISettings PropertyA { get; set; }
}
This would be much cleaner, and your question wouldn't even arise. 这样会更清洁,甚至您的问题也不会出现。
Edit (based on the answer's edit) 编辑 (基于答案的编辑)
In case of the 'double use' of the backing field the typecasting makes sense. 在“双重使用”支持字段的情况下,类型转换是有意义的。 But I don't think (and never heard that before) that it's a bad thing to throw an exception from a property setter.
但是我不认为(以前从未听说过)从属性设置器中引发异常不是一件坏事。 On the contrary: Validating a value and throwing an exception if it doesn't pass is a very common pattern.
相反:验证值并在不通过时抛出异常是非常常见的模式。
So, in your concrete case, I would validate the value for the correct type, throw if it's not correct, and use the backing field internally to bypass this type check. 因此,在您的具体情况下,我将验证正确类型的值,如果该值不正确则抛出该异常,并在内部使用后备字段绕过此类型检查。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.