Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

When should you put Key/Value type of data in it's own class instead of using a pre-built generic structure, such as a KeyValuePair or a Tuple?

For example, most ComboBoxes I create contain a DisplayName and a Value. This is the kind of data I am trying to decide when to put in a new class, and when to just use a KeyValuePair.

I am currently working on something that uses iCalendar, and the selected user's data ultimately gets combined into a key1=value1;key2=value2; type of string. I started out by putting the data in a KeyValuePair<string,string>, but now I am wondering if that should be it's own class instead.

Overall, I am interested in finding out what guidelines are used when deciding to use an existing structure/class like a KeyValuePair over a 2-property object, and in what kind of situations you would use one over another.

share|improve this question
2  
What language? In Python, we don't have this dilemma, because we have tuple type. –  S.Lott Sep 13 '11 at 13:30
2  
@S.Lott - The .NET BCL has tuples since v 4.0. –  Oded Sep 13 '11 at 13:35
1  
.NET 4 also has the tuple type. msdn.microsoft.com/en-us/library/system.tuple.aspx –  DaveNay Sep 13 '11 at 13:36
1  
@Oded In this case, I am building something with iCalendar and I wanted objects for BYDAY and BYSETPOS. They appear in the ComboBoxes, but the actual data is combined into the recurring rule string, which is a key=value; type of string –  Rachel Sep 13 '11 at 13:39
4  
@Rachel: Please update the question to be more specific. A bunch of comments aren't the best way to clarify things. –  S.Lott Sep 13 '11 at 13:39

6 Answers 6

up vote 9 down vote accepted

I'd generally use an object rather than a KeyValuePair or Tuple in most cases. First, when you come in 6 months later to make changes, it is alot easier to figure out what your intent was earlier rather than wondering what Tuple t is and why it has those funny values. Second, as things grow and change you can easily give your simple DTOs behavior as required. Need to have two name formats? Easy, just add appropriate ToString() overloads. Need it to implement some interface? No problem. Finally, there really is nearly zero overhead to creating a simple object, especially with automatic properties and code completion.

Bonus Protip: if you want to keep these objects from polluting your namespace, making private classes inside of classes is a great way to keep things under wraps and prevent strange dependencies.

share|improve this answer

The rule for defining a new class is simple: It's summarized by "Occam's Razor".

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

Do not introduce new classes without a good reason. Or use pre-built classes as much as possible. Or invent as little as possible. However you're comfortable writing less code.

You cannot use a pre-built class if you have to assign some unique responsibility to the object and that responsibility is not defined in the pre-built class. Often this is a unique method.

A tuple or KeyValuePair is preferred.

Until.

You need some functionality that's not part of A tuple or KeyValuePair. Then you have to define your own class.

share|improve this answer
1  
"Never design what you can steal" Is about my favorite way of phrasing this. –  TokenMacGuy Sep 13 '11 at 17:43
    
Would you consider semantics to be "functionality that's not part of a tuple or KeyValuePair"? KeyValuePair at least has some limited form of semantics, but tuples rarely do (might be possible, depending on context) imho. Introducing a new class should give you clear semantics as a matter of course. –  Mal Ross Nov 29 '11 at 13:47
    
+1 Don't patch a whole in a boat with duct tape if it can fit a plug. –  Evan Plaice Jan 17 '12 at 4:27

If you write your own class you have a clear place to put the documentation about what the two values are. Especially since two strings isn't a very clear definition. However you could write something like

 public class MyPair : Tuple<string, string>
share|improve this answer
    
I like this because MyPair defines what the Tuple values are and what they are used for. –  IAbstract Sep 13 '11 at 15:47
    
But then your properties would be called Item1 and Item2! Isn't it just as easy to define the entire class? public class SideStrings { public string Left { get; set; } public string Right { get; set; } } –  configurator Sep 13 '11 at 18:03
    
@configurator I was writing a response to that and noticed that Tuple is read only so I agree which I think moots the whole thing. Although you could wrap the tuple to name the values whatever you want. –  Sign Sep 13 '11 at 19:05
1  
@Sign: But what's the point? Creating your own class is less work than wrapping a tuple. –  configurator Sep 13 '11 at 19:37
    
@configurator you get some equality and comparison stuff that works better than a custom object, but if setting is required the tuple is definitely the wrong way to go. –  Sign Sep 13 '11 at 20:00

Chapter six of Clean Code has a good description of when to use a data structure versus a class. In a nutshell, you use a data structure when you mostly anticipate adding new functions to operate on that data. You use a class when you mostly anticipate adding new data types to be operated on by existing functions. Your ComboBox is an example of the latter. You have one set of functions (the ComboBox implementation) operating on many different data types (different kinds of data for different widgets).

share|improve this answer

When we say key/value pair, I usually think of hash tables, or associative arrays, or simply a KeyValuePair object. I use all of them and there is no difference in when I use which.

I think the most important thing about a list of key/value pairs is that, keys should be unique (since it's a key after all), and all of the aforementioned structures really provide me with that functionality.

Other than that, I want to search by keys, or to do list (array) style actions like push and pop.

So, my answer is, NO, and I don't create objects explicitly for key/value pairs, since lots of built-in structures already do that for me.

share|improve this answer

S.Lott wrote

Do not introduce new classes without a good reason. Or use pre-built classes as much as possible. Invent as little as possible.

You cannot use a pre-built class if you have to assign some unique responsibility to the object that is not defined in the pre-built class.

Let me say why I have a serious issue with this. Since

KeyValuePair [string,string]

seems to be okay .... is KeyValue [string, KeyValue [string, KeyValuePair [string, string]]] also okay ? I don't know what S.Lott will say to this, but my boss thinks it is okay.

I dare to disagree. And here's why : It reduces Readability of the code that will follow. The function that will fill up such a data structure will be much more complex and error (err .. exception) prone (just imagine at least some business logic as well). I didn't argue with my boss too much, but i will say it here : Readability trumps minute space savings (which was his argument). So wouldn't a class object in which there are some fields ; but some remain empty at some times be better ?

P.S. I am an Ultra_Noob so please tell me if I am wrong.

share|improve this answer
1  
I think that KeyValuePair<string,string> is fine, assuming the things put in are indeed keys and values. Here, reusing an existing class is a win, since you save writing code and gain interoperability. OTOH, using something as complicated as KeyValuePair<string,KeyValuePair<string,string>> is most of the time simply too complicated to be practical. Sometimes it may be right -- when you need no additional functionality, when the meaning is obvious, and when it works nicely with other classes. YMMV, this is just weighting the pros and contras. –  maaartinus Sep 13 '11 at 19:57

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.