"代理属性"是好的样式吗?

时间:2020-03-05 19:00:00  来源:igfitidea点击:

我有一个带有字符串属性的类,实际上是几个用分隔符连接的字符串。

我想知道具有这样的代理属性是否是一种很好的形式:

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

我有没有忽略任何风险?

解决方案

回答

好吧,我想说"组合"是高风险的,如果有人不知道他们必须传递已经加入的值序列,或者我们上面的示例可能会遗漏该怎么办?如果字符串已经包含分隔符,该怎么办?

我确信取决于此属性的使用频率,性能不是很好。

回答

定义"好"。它不应该中断(除非我们未能正确保证传递给Split()的定界符永远不允许在各个字符串中使用),但是如果IndividualStrings的访问频率比ActualProperty的访问频率高,那么我们'最终解析actualProperty的频率要比我们应有的要高得多。当然,如果相反是正确的,那么我们就做得很好...并且如果经常调用两者,以至于任何不必要的解析或者连接都不可接受,那么只需存储两者并在值更改时重新解析即可。

回答

我不确定这种设计的好处是什么。我认为使用扩展方法可以更好地实现拆分。

至少,我将删除IndividualStrings属性上的设置器,或者将其移入两个方法:string [] SplitActualProperty()和void MergeToActualProperty(string []部分)。

回答

在我看来,将两个可设置的属性链接在一起并不是一件好事。如果确实需要,请切换到使用显式的get / set方法而不是属性。具有明显作用的代码以后几乎总是会咬你。尽可能使事情简单明了。

另外,如果我们有一个属性,该属性是一个包含子字符串的格式化字符串,则看起来我们真正想要的是该属性的单独struct /类,而不是滥用原始类型。

回答

似乎数组是真实的数据,单字符串的东西很方便。很好,但是我想说要注意诸如序列化和成员克隆之类的事情,它们将获取并设置两个可写属性。

我想我会的。

  • 将数组保留为属性
  • 提供一个GetJoinedString(string Seperator)方法。
  • 提供一个" SetStrings(连接字符串,字符串分隔符)"或者" Parse(连接字符串,字符串分隔符)"方法。

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

回答

属性旨在成为类的非常简单的成员。获取或者设置属性的值应该被认为是微不足道的操作,而没有明显的副作用。

如果设置属性导致除分配的属性以外的类的公共值发生更改,则这比基本分配更重要,并且可能不再适合该属性。

"复杂"属性很危险,因为它超出了呼叫者的期望。属性被解释为字段(具有副作用),但是我们希望将其解释为可以分配值并随后检索该值的字段。这样,调用者应该期望能够分配给多个属性,并在以后再次检索它们的值。

在示例中,我无法为两个属性都赋值并检索它们;一个值会影响另一个。这打破了对该物业的基本期望。如果我们创建了一种同时为这两个属性分配值并使两个属性都为只读的方法,则可以更轻松地了解在何处设置值。

另外,顺便说一句:

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

例如:

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