12

Coming from a javascript background, collections like dictionaries are often implemented as objects because their properties can be referenced by association:

// js example
var myDict = {
  key1 : "value1",
  key2 : "value2"
};

myDict.key1;    // "value1"
myDict["key1"]; // "value1"

However, in C# it seems we have to choose between static singleton classes and generic dictionaries for each effect. While I like that classes are strongly typed and give intellisense support, Dictionary methods offer flexibility I'm hesitant to give up. Are there performance considerations so great in C# that I should choose one over the other?

Daniel Szabo
  • 7,181
  • 6
  • 48
  • 65
  • What sort of strings? What would you be using them for? – James Montagne Jan 13 '12 at 01:41
  • Performance is generally the last concern when discussing using properties/fields on an object compared to a single generic dictionary property. Type-safety should always be considered more valuable than performance in this situation (though they tend to be the same answer here). – M.Babcock Jan 13 '12 at 01:42
  • @James:I'm creating column mappings for a data conversion project between two datasources whose column names change based on the party that generates the data. – Daniel Szabo Jan 13 '12 at 01:45
  • @ajax81 - BTW which version of the framework are you targeting? – M.Babcock Jan 13 '12 at 02:03
  • @ajax81 - Then you can accomplish the equivalent of your JS object with the DLR `DynamicObject` class and the new C# 4 `dynamic` keyword. That is by far closer (and if implemented properly has better performance) than the `DataTable` as suggested. It'll provide the loose typing you're accustomed to. Even so, type safety should still be considered advantageous in this circumstance because of the additional performance benefits and intellisense support. – M.Babcock Jan 13 '12 at 02:13

8 Answers8

7

In fact, a class would be several orders of magnitude faster than a Dictionary. If you feel it's more convenient, that's even better :) So if you're able to make classes for it, do so. If the objects you represent really should be classes (i.e. are fundamentally objects and not key/value pairs) then all the more reason.

Ry-
  • 218,210
  • 55
  • 464
  • 476
4

Your javascript example does not correspond to dictionary as well as:

var myDictionary = [];
myDictionary["namevalue1"] = "value1";
myDictionary["namevalue2"] = "value2";

Now, we can do everything with my code that we can do with yours, but it's not really modelling the same thing. Yours defines properties while mine associates values with keys. You've semantically created a structured object, I've created a flatter object though I have a bit more flexibilty in the case where I don't know what string I will use as the key (not that much more in js, since js's runtime flexibility means it's not too hard to dynamically add new properties if the key is a valid label.

Just like in Javascript, in C#:

If you've a small set of properties that are known at compile time, then a class with such properties most closely models your intent.

If you've a large set of properties or do not know them at compile time, then a dictionary will most closely model your intent.

The fact that these are likely to be the most performant for either cases is just a bonus, model your intent as best as the language allows first, think about stepping away from what does so later if absolutely necessary.

No different to JS really, except it's a bit stricter as to just which you're doing at a time (we can get around that strictness if we really need to, but do you?).

Jon Hanna
  • 110,372
  • 10
  • 146
  • 251
  • +1 - Thank you for this bit of advice. I agree with everything in your response, and your implementation certainly more closely agrees resembles 'Dictionary' -- I just figured my example more closely resembled a C# class and would look a little more familiar to all the C# experts out there. :) – Daniel Szabo Jan 13 '12 at 05:21
  • Both would be pretty familiar, my point is that while your question suggets the JS given matches both C# approaches equally, it actually matches one more closely than the other. – Jon Hanna Jan 13 '12 at 10:06
  • Ah, I see what you mean. Thank you for pointing that out -- I hadn't thought of it that way, but you are absolutely right. – Daniel Szabo Jan 13 '12 at 19:23
2

If you want to do the kind of duck typing that you do in javascript, but in C#, you could use the ExpandoObject. This is a .Net 4 class. You can dynamically set its properties like:

dynamic myObject = new ExpandoObject();
myObject.namevalue1 = "value1";
myObject.namevalue2 = "value2";

The nice trick that comes in handy with the ExpandoObject in reference to what you are trying to do is that you can access the properties on the ExpandoObject in the same manner as you would access a dictionary value:

var myDictionary = myObject as IDictionary<string, object>;
Console.WriteLine(myDictionary["namevalue1"]); // value1
Console.WriteLine(myDictionary["namevalue2"]); // value2

Keep in mind you are coming from a dynamic language(javascript) to a static language(C#) and the standards and paradigms are very different. Creating a class that represents the data model would be much faster and in general, better form than dynamic objects spewn about.

doogle
  • 3,376
  • 18
  • 23
1

Classes are significantly faster than Dictionaries. However, Dictionaries are still very fast. Here is a .NET Fiddle comparing their performance: https://dotnetfiddle.net/NbFw4s

The results:

Dictionary read:  24,544,154 ops/sec
Object read:     383,327,796 ops/sec
-------------------------------------------
Dictionary write: 22,017,208 ops/sec
Object write:    228,458,287 ops/sec

As you can see, classes are an order of magnitude faster than Dictionaries. However, at 24 million operations per second, Dictionaries are still completely acceptable for all but the most performance-sensitive applications (and even then, I would be skeptical that Dictionaries would be the source of performance issues).

The code from the dotnetfiddle:

using System;
using System.Diagnostics;
using System.Collections.Generic;

public class Program
{
    public static void Main()
    {
        Stopwatch stopwatch;
        var operations = 15000000;
        var dict = new Dictionary<string, string>() {{"Name", "Bob"}};
        var obj = new Person { Name = "Bob" };

        stopwatch = new Stopwatch();
        stopwatch.Start();
        for (var i = 0; i < operations; i++)
        {
            var firstName = dict["Name"];
        }
        stopwatch.Stop();
        Console.WriteLine("Dictionary read: " + (operations / stopwatch.Elapsed.TotalSeconds).ToString("N0") + " ops/sec");
        
        stopwatch = new Stopwatch();
        stopwatch.Start();
        for (var i = 0; i < operations; i++)
        {
            var firstName = obj.Name;
        }
        stopwatch.Stop();
        Console.WriteLine("Object read:    " + (operations / stopwatch.Elapsed.TotalSeconds).ToString("N0") + " ops/sec");
        
        Console.WriteLine("-------------------------------------------");
        
        stopwatch = new Stopwatch();
        stopwatch.Start();
        for (var i = 0; i < operations; i++)
        {
            dict["Name"] = "Jim";
        }
        stopwatch.Stop();
        Console.WriteLine("Dictionary write: " + (operations / stopwatch.Elapsed.TotalSeconds).ToString("N0") + " ops/sec");
        
        stopwatch = new Stopwatch();
        stopwatch.Start();
        for (var i = 0; i < operations; i++)
        {
            obj.Name = "Jim";
        }
        stopwatch.Stop();
        Console.WriteLine("Object write:    " + (operations / stopwatch.Elapsed.TotalSeconds).ToString("N0") + " ops/sec");
        
    }
    
    class Person {
        public string Name;
    }
}
TwitchBronBron
  • 2,783
  • 3
  • 21
  • 45
1

The C# Dictionary class is strongly typed using generics. You specify both the type of the keys and the values when using it.

I'd recommend learning about the dictionary class as you are very likely to find it useful for many purposes.

It's hard to comment further without knowing more about your use case, but in general I wouldn't worry about performance of the Dictionary class until you know it's an issue, and refactor later if it is. (I bravely predict that it won't be).

Ergwun
  • 12,579
  • 7
  • 56
  • 83
1

since you are using it for Data.... a "DataTable" which is a microsoft abstraction of exactly this, is basically a big dictionary. You may want to investigate DataTable as it has a whole lot of toys that come with it that MAY make your life a lot easier.

Keith Nicholas
  • 43,549
  • 15
  • 93
  • 156
1

It really depends on your use case. C# dictionaries are a lot more performant than you might generally expect from your JavaScript code. Plus, as The Don points out, "We should forget about small efficiencies, say about 97% of the time; premature optimization is the root of all evil". I've provided a couple of examples that provide the same output as your sample JavaScript:

enum DictKeys
{
    nameValue1,
    nameValue2,
}

void Main()
{
    var myDictionary = new Dictionary<string, string>();
    myDictionary.Add("namevalue1", "value1");
    myDictionary.Add("namevalue2", "value2");

    Console.WriteLine(myDictionary["namevalue1"]); // "value1"

    var myDict2 = new Dictionary<DictKeys, string>();
    myDict2.Add(DictKeys.nameValue1, "value1");
    myDict2.Add(DictKeys.nameValue2, "value2");

    Console.WriteLine(myDict2[DictKeys.nameValue1]); // "value1"
}
David Clarke
  • 12,888
  • 9
  • 86
  • 116
0

Class with properties will give you a performance boost and intellisense support. On the other hand, dictionary can give you more flexibility, if you need it.

Aleksandar Vucetic
  • 14,715
  • 9
  • 53
  • 56