“代理属性”是一种好的编程风格吗?

3

我有一个类,其中有一个字符串属性,实际上是使用分隔符连接起来的多个字符串。

我想知道是否有必要创建一个代理属性,例如:

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;
    }
}

我有没有忽略掉任何风险?
6个回答

2
链接两个可设置属性在我看来是不好的做法。如果这确实是你想要的,那么请改用显式的get / set方法而不是属性。具有非明显副作用的代码几乎总会在以后给你带来麻烦。尽可能保持简单和直接。
另外,如果您有一个包含子字符串的格式化字符串属性,那么看起来您真正想要的是一个单独的结构体/类,而不是误用基本类型。

2

似乎数组是真正的数据,而单个字符串只是方便之处。这很好,但我想说要注意序列化和成员克隆等问题,它们将获取和设置可写属性。

我认为我会:

  • 保留数组作为属性
  • 提供一个GetJoinedString(string seperator)方法。
  • 提供一个SetStrings(string joined, string seperator)Parse(string joined, string seperator)方法。

实际上,字符串中的分隔符并不真正属于类,而是一个短暂的细节。明确引用它,以便例如CSV应用程序可以传递逗号,而制表符分隔的应用程序可以传递制表符。这将使您的应用程序更易于维护。此外,它还消除了对同一实际数据具有两个getter和setter的麻烦问题。


1

属性应该是类的非常简单的成员;获取或设置属性的值应该被认为是一个微不足道的操作没有重大的副作用

如果设置属性会导致类的公共值发生变化,而不仅仅是分配的属性,那么这比基本赋值更重要,可能不再适合属性。

“复杂”属性是危险的,因为它违反了调用者的期望。属性被解释为字段(带有副作用),但是作为字段,您希望能够分配一个值,然后稍后检索该值。通过这种方式,调用者应该期望能够分配多个属性并稍后再次检索它们的值。

在您的示例中,我无法为两个属性分配值并检索它们;一个值将影响另一个值。这打破了属性的基本期望。如果您创建一个方法来同时分配值给两个属性,并使两个属性只读,那么就更容易理解值的设置位置。

此外,顺便提一下:

通常认为从属性返回临时数组是不好的做法。数组可能是不可变的,但它们的内容不是。这意味着您可以更改数组中的值,这些更改将与对象一起持续。

例如:

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 .... ;
}

1
“好”的定义是什么?它不应该出错(除非你未能正确保证传递给Split()的分隔符在字符串本身中绝对不会出现),但如果IndividualStrings的访问频率高于ActualProperty,那么解析actualProperty的次数将远远超过理想情况。当然,如果反之亦然,那么你的表现很好...而且,如果两者都被频繁调用以至于任何不必要的解析或拼接都是不可接受的,那么就将它们都存储起来,并在值改变时重新进行解析。

0

我认为你的“set”是高风险的,如果有人不知道他们必须传递一个已经连接的值序列,或者你上面的示例可能缺失了这个条件,那该怎么办呢?如果字符串已经包含分隔符-你会出错。

我确定性能取决于此属性使用的频率,可能不太好。


0

我不确定这种设计的好处是什么。我认为拆分最好在扩展方法中实现。

至少,我会移除IndividualStrings属性上的setter,或将其拆分成两个方法:string[] SplitActualProperty()和void MergeToActualProperty(string[] parts)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接