【发布时间】:2014-01-10 11:25:30
【问题描述】:
假设我有这样的课程:
public class A
{
private BaseSettings fieldA;
public ISettings PropertyA
{
get {return fieldA;}
set {fieldA= value as BaseSettings;}
}
}
BaseSettings 实现 ISettings 的地方。在 A 类中,如果我想访问 BaseSettings 的名为 PropertyB 的属性,这是一个好习惯:
fieldA.PropertyB;
或
((BaseSettings)PropertyA).PropertyB;
有人可能会说第一种方法可能会隐藏属性更改时间的提示。例如,代码可能会侦听 PropertyChangedEvent,然后更改属性的值而不引发事件。
另一个人可能会说第二种方法可能会暴露一个风险,即当不熟悉当前代码的人修改它时,他可能会将 PropertyA 转换为实现 ISettings 的不同类型。
这两种方法都有其缺点。在良好的编程实践中,哪个更可取?
编辑: 基于以下cmets添加:
我同意将支持字段设置为 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 : ISettings 和 BaseUserControlSettings : ISettings 。这是实际的ISettings界面
public interface ISettings
{
Dictionary<string, ISettings> Children { get; set; }
}
'as' 转换是我放入 setter 的副作用,因此如果设置设置为错误,它将忽略并返回 null。我在某处读到说我不应该在 setter 中抛出异常。因此,将其设为 null 是我通知有错误发生的方式。
那么更好的方法是什么。是不是我设计错了?
【问题讨论】:
-
为什么要使用特定类型来支持属性,而使用泛型类型来公开属性?这对您班级的消费者来说充其量是个问题。
-
同意@JustinNiessner。您可以采用另一种方式(私有字段的接口,公共属性的特定类型),但这样做会导致问题。
-
您最好将 ISettings 用于支持字段和属性声明。如果 A 类需要使用 PropertyB,那么它应该由接口公开
-
另见我关于这个主题的文章。 blogs.msdn.com/b/ericlippert/archive/2009/01/14/…
标签: c#