何时应在诸如KeyValuePair之类的预构建结构上使用2属性类?


31

什么时候应该将键/值类型的数据放在其自己的类中,而不是使用诸如a KeyValuePair或a 之类的预构建通用结构Tuple

例如,我创建的大多数ComboBox都包含一个DisplayName和一个Value。这是我要决定何时放入新类以及何时仅使用KeyValuePair的数据类型。

我目前正在使用进行某些操作,iCalendar最终将所选用户的数据合并为一种key1=value1;key2=value2;字符串。我首先将数据放入KeyValuePair<string,string>,但现在我想知道那是否应该是它自己的类。

总的来说,我很想知道在决定使用现有的结构/类(如KeyValuePair2属性对象)时使用什么准则,以及在哪种情况下您应该使用哪种准则。


3
什么语言?在Python中,我们没有这个难题,因为我们有tuple类型。
S.Lott

3
@ S.Lott-自v 4.0起,.NET BCL具有元组。
奥德


1
@Oded在这种情况下,我正在使用构建iCalendar对象,BYDAY并且我需要和的对象BYSETPOS。它们出现在ComboBoxes中,但是实际数据被组合到重复的规则字符串中,这是key=value;字符串的一种
Rachel

4
@Rachel:请更新问题以更具体。一堆评论不是澄清事情的最佳方法。
S.Lott

Answers:


26

在大多数情况下,我通常使用对象而不是KeyValuePair或Tuple。首先,当您六个月后来进行更改时,要弄清楚自己的初衷是很容易的,而不是想知道是什么Tuple t以及为什么它具有这些有趣的价值观。其次,随着事情的发展和变化,您可以轻松地根据需要为简单的数据传输对象提供行为。是否需要两种名称格式?简单,只需添加适当的ToString()重载即可。需要它来实现一些接口吗?没问题。最后,创建简单对象的开销几乎为零,尤其是具有自动属性和代码完成功能时。

额外的提示:如果您想防止这些对象污染您的名称空间,则在类内创建私有类是使情况保持秘密并防止奇怪的依赖的好方法。


1
DTO = 数据传输对象?-我讨厌的TLA ;-)

3
@Ben-TFTFY。。。
Wyatt Barnett

7

定义新类的规则很简单:“ Occam的剃刀”对此进行了总结。

http://c2.com/cgi/wiki?OccamsRazor

没有充分的理由就不要引入新的课程。或尽可能使用预构建的类。或尽可能少发明。但是,您可以轻松编写更少的代码。

如果必须为对象分配一些唯一的责任并且该责任未在预构建类中定义,则不能使用预构建类。通常这是一种独特的方法。

tuple或者KeyValuePair是优选的。

直到。

您需要一些不属于A tuple或A的功能KeyValuePair。然后,您必须定义自己的类。


3
从不设计您可以窃取的东西 ”是我最喜欢的措辞方式。
SingleNegationElimination 2011年

1
您是否认为语义是“不属于tuple或的功能KeyValuePair”?KeyValuePair至少具有某种形式的语义,但是元组很少(可能是依赖于上下文)做恕我直言。当然,引入一个新类应该为您提供清晰的语义。
马尔·罗斯,

+1如果可以插入插头,请不要用胶带将船上的整体打补丁。
Evan Plaice 2012年

4
我认为这是Occam剃刀的错误使用。其次,重要的是要知道变量中包含哪些信息。-1。
弯曲

4

如果您编写自己的类,则可以轻松地放置有关这两个值是什么的文档。特别是因为两个字符串的定义不是很明确。但是你可以写类似

 public class MyPair : Tuple<string, string>

我喜欢这样做是因为MyPair定义了元组值是什么以及它们的用途。
IAbstract

2
但是随后您的属性将被称为Item1Item2!定义整个类不是很容易吗?public class SideStrings { public string Left { get; set; } public string Right { get; set; } }
配置器

@configurator我对此写了一个回复,并且注意到Tuple是只读的,所以我同意,我认为这很重要。尽管您可以包装元组来命名值,但可以使用任何名称。
签署

2
@Sign:但是有什么意义呢?创建自己的课程比包装元组要
配置器

2
@configurator提供了一些相等和比较的东西,这些东西比自定义对象更好,但是如果需要设置,则元组绝对是错误的方法。
签署

4

洛特写道

没有充分的理由就不要引入新的课程。或尽可能使用预构建的类。尽可能少地发明。

如果必须将某些唯一职责分配给未在预构建类中定义的对象,则不能使用预构建类。

让我说为什么我对此有一个严重的问题。以来

KeyValuePair [字符串,字符串]

似乎还可以.... KeyValue [string,KeyValue [string,KeyValuePair [string,string]]]也可以吗?我不知道美国洛特会说这个,但我的老板认为这好的。

我不敢不同意。这就是为什么:它降低了后续代码的可读性。填充此类数据结构的功能将更加复杂,并且容易出错(错误……异常)(还可以想象至少还有一些业务逻辑)。我并没有与老板争执不休,但是我会在这里说:可读性胜过节省微小的空间(这是他的观点)。所以不会有一些领域的类对象; 但是有些人有时还是空着会更好?

PS:我是Ultra_Noob,所以请告诉我我是否错。


2
我认为这KeyValuePair<string,string>很好,假设所放内容确实是键和值。在这里,重用现有的类是一个胜利,因为您可以节省编写代码并获得互操作性。OTOH,KeyValuePair<string,KeyValuePair<string,string>>在大多数情况下使用的都是复杂的东西,太复杂了以至于无法实用。有时可能是正确的-当您不需要其他功能时,含义很明显,并且可以与其他类很好地配合使用时。YMMV,这只是权衡利弊。
maaartinus 2011年

如果您使用的是C#,则这是Tuple vs KeyValuePair性能。您可能想与老板分享一些东西吗?

3

当我们说键/值对时,我通常会想到哈希表关联数组,或者只是一个KeyValuePair对象。我使用了所有这些,使用它们的时间也没有区别。

我认为关于键/值对列表最重要的是,应该是唯一的(因为毕竟它是键),并且所有上述结构确实为我提供了该功能。

除此之外,我想按键进行搜索,或者执行诸如推和弹出之类的列表(数组)样式的操作。

因此,我的回答是,NO,并且我没有为键/值对显式创建对象,因为许多内置结构已经为我做到了。


3

干净代码的第六章很好地描述了何时使用数据结构与类。简而言之,当您最期望添加新功能以对该数据进行操作时,便可以使用数据结构。当您最希望添加新数据类型以使用现有功能时,可以使用类。您的ComboBox是后者的一个示例。您有一组功能(ComboBox实现)可对许多不同的数据类型(不同小部件的不同类型的数据)进行操作。


2

在这里,我也许会同意Wilding的观点,但是对于这种事情,我还是有点不满意。

我建议内置类型通常是 机制对象。例如,KeyValuePair是字典和哈希表机制的一部分,有助于确保唯一键,并且它们具有在机制本身的上下文中具有有意义名称的属性。

另一方面,使用定制数据对象可以更好地表示数据,并提供许多好处,包括可读性和可扩展性。正如Sign所建议的那样,没有什么可以停止重用自定义构建对象中的现有代码,,但是我会尝试隐藏包装好的类,并避免抽象泄漏,以便您可以在以后更改基础实现,而不影响其余代码。

所以真正的问题是: 您是表示数据还是在某种机制中使用数据?(我不建议将这些概念混合在一起)。

以我的经验,没有什么比看到Tuple [string,string]传递到方法中并且没有立即知道Item1和Item2应该是什么的方法更糟糕的了。最好在方法内或仅作为类的私有成员使用元组。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.