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

时间:2014-01-09 20:09:11

标签: c#

假设我有一个这样的课程:

public class A
{
    private BaseSettings fieldA;
    public ISettings PropertyA
    {
         get {return fieldA;}
         set {fieldA= value as BaseSettings;}
    }
}

BaseSettings实现ISettings。在A类中,如果我想访问名为PropertyB的BaseSettings属性,这是一个很好的做法:

fieldA.PropertyB;

((BaseSettings)PropertyA).PropertyB;

可以说第一种方法可能会隐藏属性更改时的提示。例如,代码可以侦听PropertyChangedEvent,然后在不引发事件的情况下更改属性值。

另一个人可能会说第二种方法可能会暴露出一种风险,即当一个不熟悉当前代码的人修改它时,他可能会将PropertyA转换为实现ISettings的不同类型。

这两种方法都有其缺点。在一个好的编程实践中,哪一个应该更优选?

修改 根据以下评论添加:

我同意将支持字段设置为ISettings是绝对有意义的。但是我该怎么做才能确保PropertyA始终是BaseSettings的类型。这将提出一个问题:“那么为什么不将属性和后备字段都设置为BaseSettings?”。

为什么属性及其支持字段不同的原因是A类也实现了这样的接口

public interface IControlWithSettings
{
     ISettings OwnerSettings
     {
         get;
         set;
     }
     ISettings Settings
     {
         get;
         set;
     }
}

所以实际的classA看起来像这样

public class BaseForm: Form, IControlWithSettings
{
    private BaseFormSettings settings;
    public ISettings Settings
    {
         get {return settings;}
         set {settings= value as BaseFormSettings;}
    }
}

我还有另一个B类也会实现IControlWithSettings

public class BaseUserControl: UserControl, IControlWithSettings
{
    private BaseUserControlSettings settings;
    public ISettings Settings
    {
         get {return settings;}
         set {settings= value as BaseUserControlSettings ;}
    }
}

BaseFormSettings : ISettingsBaseUserControlSettings : ISettings。这是实际的ISettings界面

public interface ISettings
{
    Dictionary<string, ISettings> Children { get; set; }
}

'as'强制转换是我放入setter的副作用,因此如果将设置设置为错误,它将忽略并返回null。我在某处读到说我不应该在setter中抛出异常。因此,将其设为null是告知已经出现问题的方法。

那么更好的方法是什么呢?我设计错了吗?

1 个答案:

答案 0 :(得分:1)

正如你所说,这两种方法都有它们的缺点,它还取决于属性设置器是否包含一些额外的逻辑(例如验证),并且你可以在类中使用或绕过这个额外的逻辑。
如果没有任何反对意见,我将使用直接访问该字段。它更整洁,它避免了所有这些类型转换的东西。

但一般情况下:为什么你会用派生类型支持你的属性,而属性本身有接口类型?这没有多大意义。为什么不呢:

public class A
{
    public ISettings PropertyA { get; set; }
}

这会更清洁,你的问题甚至不会出现。

编辑(根据答案的编辑)
在支持字段“双重使用”的情况下,类型转换是有意义的。但我不认为(之前从未听说过)从属性设置器中抛出异常是件坏事。相反:验证值并在未通过时抛出异常是一种非常常见的模式 因此,在您的具体情况下,我将验证正确类型的值,如果它不正确则抛出,并在内部使用支持字段来绕过此类型检查。