【问题标题】:Are "proxy properties" good style?“代理属性”是好风格吗?
【发布时间】:2008-09-17 20:43:07
【问题描述】:
我有一个带有字符串属性的类,它实际上是几个用分隔符连接的字符串。
我想知道拥有这样的代理属性是否是一种好的形式:
public string ActualProperty
{
get { return actualProperty; }
set { actualProperty = value; }
}
public string[] IndividualStrings
{
get { return ActualProperty.Split(.....); }
set
{
// join strings from array in propval .... ;
ActualProperty = propval;
}
}
有没有我忽略的风险?
【问题讨论】:
标签:
c#
coding-style
properties
【解决方案1】:
在我看来,将两个可设置的属性链接在一起是不好的。如果这确实是您想要的,请切换到使用显式 get/set 方法而不是属性。具有不明显副作用的代码以后几乎总是会咬你。尽可能让事情简单明了。
此外,如果您有一个属性是包含子字符串的格式化字符串,那么看起来您真正想要的是该属性的单独结构/类,而不是滥用原始类型。
【解决方案2】:
似乎数组是真实的数据,单字符串的东西是一种方便。这很好,但我会说要注意序列化和成员克隆之类的东西,它们将获取和设置两个可写属性。
我想我会的;
- 将数组保留为属性
- 提供
GetJoinedString(string seperator) 方法。
- 提供
SetStrings(string joined, string seperator) 或Parse(string joined, string seperator) 方法。
实际上,字符串中的分隔符并不是真正的类的一部分,而是一个短暂的细节。明确引用它,例如,CSV 应用程序可以传递逗号,而制表符分隔的应用程序可以传递一个制表符。这将使您的应用程序更易于维护。此外,它消除了对于相同的实际数据有两个 getter 和 setter 的讨厌问题。
【解决方案3】:
定义“好”。它不应该中断(除非您未能正确保证传递给 Split() 的分隔符绝不允许在各个字符串本身中出现),但如果 IndividualStrings 的访问频率高于 ActualProperty 您将结束比你应该更频繁地解析actualProperty。当然,如果反过来是真的,那么你做得很好......如果两者都被频繁调用以至于任何不必要的解析或连接都是不可接受的,那么只需存储两者并在值更改时重新解析。
【解决方案4】:
属性旨在成为类的非常简单的成员;获取或设置属性的值应该被认为是一个简单的操作没有明显的副作用。
如果设置属性会导致分配属性以外的类的公共值发生更改,这比基本分配更重要,并且可能不再适合该属性。
“复杂”属性是危险的,因为它违背了调用者的期望。属性被解释为字段(具有副作用),但作为您希望能够分配一个值然后检索该值的字段。通过这种方式,调用者应该能够分配多个属性并在以后再次检索它们的值。
在您的示例中,我无法为这两个属性分配值并检索它们;一个值会影响另一个值。这打破了对该物业的基本预期。如果您创建一个方法来同时为这两个属性分配值并将这两个属性设为只读,则更容易理解值的设置位置。
另外,顺便说一句:
从属性返回临时数组通常被认为是不好的做法。数组可能是不可变的,但它们的内容不是。这意味着您可以更改数组中的值,该值将与对象一起存在。
例如:
YourClass i = new YourClass();
i.IndividualStrings[0] = "Hello temporary array!";
这段代码看起来像是在更改IndividualStrings属性中的一个值,但实际上数组是由该属性创建的并且没有分配到任何地方,因此数组和更改将立即超出范围。
public string ActualProperty { get; set; }
public string[] GetIndividualStrings()
{
return ActualProperty.Split(.....);
}
public void SetFromIndividualStrings(string[] values)
{
// join strings from array .... ;
}
【解决方案5】:
好吧,我会说您的“设置”是高风险的,如果有人不知道他们必须传递一个已经连接的值序列,或者您上面的示例可能错过了这一点。如果字符串已经包含分隔符怎么办 - 你会中断。
我确信性能不是很好,具体取决于此属性的使用频率。
【解决方案6】:
我不确定这种设计有什么好处。我认为拆分在扩展方法中会更好。
至少,我会删除 IndividualStrings 属性上的设置器,或者将其移动到两个方法中:string[] SplitActualProperty() 和 void MergeToActualProperty(string[] parts)。