简体   繁体   English

我应该在声明该属性的类中使用公共属性的私有字段吗?

[英]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 : ISettingsBaseUserControlSettings : 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.

相关问题 我应该使用带有公共获取方法的私有属性/字段还是直接使用公共属性进行正确封装? - Should I use a private property/field with a public getter method or directly use a public property for proper encapsulation? 如果我的课程有一个带有私有字段用于存储的属性,我应该使用私有字段还是该属性在构造函数中对其进行初始化? - If my class has a property with a private field for storage, should i use the private field or the property to initialize it in the constructor? 我应该使用田地还是财产? - Should I use a field or a property? 我应该在类中使用Field或Property来设置值 - Should I use a Field or Property within the class to set values 为什么我需要通过公共财产公开的私人领域? - Why do I need a private field that is exposed via public property? 私人阶层的公共财产 - Public property of private class 为什么我应该在属性访问器中使用私有变量? - Why should I use a private variable in a property accessor? 为什么我不能在静态类中访问公共属性字段 - Why can't I access public property field in static class 什么时候应该宣布私人或公共课程? - When should you declare a class private or public? 什么时候使用公共或私有财产? - When to use the public or private property?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM