Using C# 3.0 Anonymous Types as Dictionaries

During a design meeting for a new feature in ASP.NET we had a requirement that a new method accept a dictionary of name/values pairs. An obvious solution is to have the method accept a parameter of type IDictionary (or its generic cousin):

public static string GetHtmlLink(string text, IDictionary<string, string> properties) {
...
}

While it looks nice and neat from the perspective of our function, the caller of this function has a real mess to deal with. Creating dictionaries is definitely somewhat of a pain. Since Dictionary<TKey, TValue> doesn't have an Add() method with one parameter you can't use C# 3.0's collection initializer syntax. This is some ugly code:

Dictionary<string, string> values = new Dictionary<string, string>();
values.Add("key1", "value1");
values.Add("key2", "value2");
values.Add("key3", "value3");
GetHtmlLink("Click me", values);

My proposal: Have the method accept a parameter of type object. Callers could pass in a type that has properties with the appropriate names and values. They can use C#'s object initializer syntax to save some space:

MyParams myParams = new MyParams { Key1 = "value1", Key2 = "value2", Key3 = "value3" };
GetHtmlLink("Click me", myParams);

However, there was the added work of defining the MyParams type. Admittedly, it wasn't that hard with C# 3.0's automatic properties, but I hate defining types that are used in only one place. If the user can pass in an arbitrary object with properties, why not let that object be of an anonymous type? Here's the final code:

GetHtmlLink("Click me", new { Key1 = "value1", Key2 = "value2", Key3 = "value3" });

Woah! We went from five lines of code with dictionaries to two lines of code with object initializers (minus the type definition), to just one line of code with anonymous types!

So what does the GetHtmlLink method look like, anyway? Download the code from the attachment. You can now use the two helpers like so:

Sample link: <%= HtmlHelpers.GetHtmlLink("My Site", new { @class = "someStyle", href = "http://www.example.org" })%>
<br />
Sample URL: <%= HtmlHelpers.GetUrl("http://www.example.org/search", new { query = "kitten's mittens", mode = "details" })%>

And it'll render this HTML:

Sample link: <a class="someStyle" href="http://www.example.org">My Site</a>
<br />
Sample URL: http://www.example.org/search?query=kitten's+mittens&mode=details

So, what do you think?

I'm obviously ignoring certain aspects of this technique such as performance. There are certainly ways to optimize the performance with some clever caching. Performance might not be an issue anyway, depending on where this code is used.

Have you come up with a novel way to use a new language feature that you'd like to share?

Published Monday, September 24, 2007 2:00 PM by Eilon
Filed under:

Comments

# JSON-style dictionary parameters in C#?

Monday, September 24, 2007 6:26 PM by Tales from the Evil Empire

Eilon has an interesting post about using the new anonymous object initializer syntax in APIs that take

# re: Using C# 3.0 Anonymous Types as Dictionaries

Monday, September 24, 2007 6:28 PM by Bertrand Le Roy

How does this work with other languages?

# JSON-style dictionary parameters in C#?

Monday, September 24, 2007 6:51 PM by Top ASP.NET Items

Eilon has an interesting post about using the new anonymous object initializer syntax in APIs that take

# re: Using C# 3.0 Anonymous Types as Dictionaries

Monday, September 24, 2007 7:24 PM by Fabrice Marguerie

What about doing it the following way:

1) Create a class with an Add method

public class Pairs : List<KeyValuePair<String, String>>

{

 public void Add(String key, String value)

 {

   Add(new KeyValuePair<string,string>(key, value));

 }

}

2) Create a simple GetHtmlLink method

public static string GetHtmlLink(string text, Pairs pairs)

{

   StringBuilder sb = new StringBuilder();

   sb.Append("<a");

   foreach (var pair in pairs)

   {

       sb.Append(" ");

       sb.Append(pair.Key);

       sb.Append("=\"");

       sb.Append(pair.Value);

       sb.Append("\"");

   }

   sb.Append(">");

   sb.Append(text);

   sb.Append("</a>");

   return sb.ToString();

}

3) Use the GetHtmlLink method

String url = GetHtmlLink("My Site", new Pairs { {"class", "someStyle"}, {"href", "http://www.example.org"} })

This way, no reflection and no untyped parameter. I think you went for difficult solutions first. You don't need dictionaries or anonymous types.

# re: Using C# 3.0 Anonymous Types as Dictionaries

Monday, September 24, 2007 7:41 PM by Wilco Bauwer

You can use collection initializers with Dictionaries too if you want. The following should work:

<%= GetUrl("http://www.example.com", new Dictionary<string, string>()

           {

               { "query", "foo" },

               { "mode", "bar" }

           }) %>

Your approach is interesting, but when using a language that doesn't support anonymous types, such as C# 2.0, it'd suck if you'd have to create an entire type just so you can call "GetUrl".

# re: Using C# 3.0 Anonymous Types as Dictionaries

Monday, September 24, 2007 9:01 PM by reader

Do you really need to limit the content through your RSS feed?  Since you haven't monetized your blog, how about you display the full content in your RSS feed??

# re: Using C# 3.0 Anonymous Types as Dictionaries

Monday, September 24, 2007 9:40 PM by InfinitiesLoop

Low tech... use a param array? Every two params is your name/value pair.

GetUrl(string url, params string[] query)

just assert the length of query is even :)

# re: Using C# 3.0 Anonymous Types as Dictionaries

Tuesday, September 25, 2007 1:09 PM by Bertrand Le Roy

On second thought, isn't the use of reflection going to be a big problem? I don't see what you can cache efficiently as you'll pretty much get a different type for each call. I'm beginning to like the low-tech params array better...

# re: Using C# 3.0 Anonymous Types as Dictionaries

Wednesday, September 26, 2007 1:21 AM by Rick Strahl

I'm also in the low tech camp. When it comes down to it, that's the easiest way to use it if not the most elegant way.

But Eilon hits on a sore note about there not really being a user friend dictionary type that's easy to construct. I run into this same situation occasionally and keep revisiting the docs for each of these collection types and walk away building something custom to make it work.

# ROR flavor ASP.NET

Tuesday, October 02, 2007 7:43 AM by Wiennat's Blog

ROR flavor ASP.NET

# re: Using C# 3.0 Anonymous Types as Dictionaries

Monday, October 08, 2007 2:42 PM by Jimmy Bogard

Wow that's funny...I saw this exact code at Scott Guthrie's ALT.NET presentation on the new MVC framework for ASP.NET.  Very interesting....I didn't see if IntelliSense worked in the ASPX page from the anonymous type passed into the view from the controller, so I might rather use the generic versions of the controller and view instead.  But very cool nonetheless.

# re: Using C# 3.0 Anonymous Types as Dictionaries

Monday, October 08, 2007 2:52 PM by Eilon

Jimmy, it's no coincidence! :)

When I said "During a design meeting for a new feature in ASP.NET" I was refering to our MVC design meetings!

- Eilon

# re: Using C# 3.0 Anonymous Types as Dictionaries

Tuesday, October 30, 2007 5:15 AM by Alun Harford

I think you've been doing too much javascript and it's warped your mind.

But I like it :-)

# re: Using C# 3.0 Anonymous Types as Dictionaries

Tuesday, October 30, 2007 1:23 PM by Vijay Santhanam

This is one of the coolest things about the MVC, I never have to hard code urls again.. the world will be a better place.

In the CTP, will the HtmlHelper.GetUrl and GetLink   type reflection be cached for performance?

How do .net developers usually make reflective methods like these faster?

What does the @ in @class do?

# re: Using C# 3.0 Anonymous Types as Dictionaries

Tuesday, October 30, 2007 5:02 PM by Mark Brackett

Wilco is right - the Dictionary<> supports collection initializers fine - which means you can go back to your initial design at the cost of a few more curly braces.

The "new" design is certainly more Ruby-esque, but I don't think that's a compliment in a strongly typed language such as C#. Just declaring the param as an object and using reflection to grab the properties and values is a little more dynamic than I want my core C# to be.

Personally, I'd prefer to see an HtmlAttribute class that takes name and values in the constructor. Then, just make GetHtmlLink(string text, params HtmlAttribute[] htmlAttributes). Calling code would be like:

GetHtmlLink("test", new HtmlAttribute("class", "extLink"), new HtmlAttribute("href", "http://www.google.com"));

If that's too wordy, an HtmlAttributes collection (inheriting from List<HtmlAttribute>) with a Add(string name, string value) could shorten it to (similar to Wilco's Dictionary example):

GetHtmlLink("test", new HtmlAttributes() {{"class", "extLink"}, {"href", "http://www.google.com"}});

But that's too many curly braces to keep track of IMO. So, to shorten it up, how about a conversion operator:

GetHtmlLink("test", (HtmlAttribute) "class=extLink", (HtmlAttribute) "href=http://www.google.com");

Or we could break the Guidelines (msdn2.microsoft.com/.../5b63aadf(VS.71).aspx) and implement an implicit operator (but it would have to throw or do something nonsensical if it wasn't in "name=value" format):

GetHtmlLink("test", "class=extLink", "href=http://www.google.com");

# links for 2007-10-31 | Lazycoder

Wednesday, October 31, 2007 6:26 AM by links for 2007-10-31 | Lazycoder

Pingback from  links for 2007-10-31 | Lazycoder

# re: Using C# 3.0 Anonymous Types as Dictionaries

Wednesday, October 31, 2007 8:08 AM by dpirs

I would also prefer to leave c# statically typed as it is. There are plenty of other dinamically typed langugaes if I will ever want to use them.

# re: Using C# 3.0 Anonymous Types as Dictionaries

Wednesday, October 31, 2007 8:28 AM by Steven Harman

Vijay, The "@" symbol is needed on the @class property because "class" is a reserved keyword in C#... so we need a way to distinguish between the keyword and just-another-property-name.

# 17 Links Today (2007-10-31)

Wednesday, October 31, 2007 11:19 AM by 17 Links Today (2007-10-31)

Pingback from  17 Links Today (2007-10-31)

# Response.Redirect into a new window (with Extension Methods)

Wednesday, October 31, 2007 4:07 PM by Infinities Loop

This question comes up from time to time , to time . If you understand how redirects work, then you also

# re: Using C# 3.0 Anonymous Types as Dictionaries

Saturday, November 03, 2007 12:58 AM by Jason Bunting

Not trying to bash or anything (honestly!), but anyone that has used any of the decent JavaScript libraries around these days and has passed anonymous types to functions as a way of specifying a 'dictionary' of name/value pairs and recognized that C#'s anonymous type syntax looks amazingly like JavaScript's literal object notation would have thought to try this.

I have been using the MochiKit JS library for the last 18 months and regularly pass anonymous objects to MochiKit's DOM element creation functions like so:

var inputElement = INPUT({type:"text", id:"foo", name:"foo"});

setStyle(inputElement, {"background-color": "red", opacity: 0.5});

Perhaps that is what inspired this idea? Personally, I think this is a great idea and will be looking for more ways to make my C# authoring experience feel more like my JavaScript authoring experience, which I absolutely enjoy.

# re: Using C# 3.0 Anonymous Types as Dictionaries

Thursday, November 08, 2007 7:15 PM by autofed

I have to agree with Mark Brackett and dpirs. I understand that dynamic languages are all the rage right now, but C# is NOT a dynamic language, and .NET is not a dynamic framework. I use C# in .NET specifically because I WANT a statically typed language; if I wanted to use a dynamically typed language, I would use one of the many that are available. Please don't try to force dynamic constructs where they don't belong. See more discussion at commongenius.com/.../Collection-Initializers-and-Duck-Typing.aspx.

# hostab &raquo; Blog Archive &raquo; Using C# 3.0 Anonymous Types as Dictionaries

Pingback from  hostab  &raquo; Blog Archive   &raquo; Using C# 3.0 Anonymous Types as Dictionaries

# re: Using C# 3.0 Anonymous Types as Dictionaries

Saturday, November 10, 2007 3:41 PM by Fredrik Normén

For over 15 years I have study other developers and read books about how to write readable code. Code that will be easier to understand, need less time to understand and make it more logical for others to understand. Still I’m not an expert in the area. But here are my thoughts.

GetHtmlLink("Click me", new { Key1 = "value1", Key2 = "value2", Key3 = "value3" });

The code above is much easier to read than the following:

GetHtmlLink("Click me", new Pairs { {"Key1", "someStyle"}, {"Key1", "http://www.example.org"} })

All the { } and " will not make the code so "visible" by the eye. We need to take a longer and deeper look at the code. We also need more thinking to figure what "Key1" and "someStyle" is, and how they are connected and to figure out by only looking at the code that the final result will be "Key1=someStyle". If we write Name = "Test" we easy know that the Name will have the value "Test". But { "Name", "Test" } is not so "logical" (are not logical conneted byt only looking at that part of the code).

The first code example will be more visible for the eye and also easier to read, and we need less work when we read the code to understand it. For me that is quality, and makes code easier to understand and read. But the Beauty's in the eye of the beholder ;)

# re: Using C# 3.0 Anonymous Types as Dictionaries

Monday, November 12, 2007 9:53 AM by autofed

By the way, since when do collections have to have an Add method with a single argument in order to use collection initializers? I haven't seen that requirement anywhere in any of the descriptions I have seen, including the Scott Guthrie link you included.

# ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 6:51 AM by BusinessRx Reading List

Two weeks ago I blogged about a new MVC (Model View Controller) framework for ASP.NET that we are going

# ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 7:00 AM by Elan Hasson's Favorite Blogs

Two weeks ago I blogged about a new MVC (Model View Controller) framework for ASP.NET that we are going

# ASP.NET MVC Framework (Part 1)

Tuesday, November 13, 2007 7:21 AM by Community Blogs

Two weeks ago I blogged about a new MVC (Model View Controller) framework for ASP.NET that we are going

# ASP.NET MVC Framework (Primera parte) &laquo; Thinking in .NET

Sunday, November 18, 2007 11:56 AM by ASP.NET MVC Framework (Primera parte) « Thinking in .NET

Pingback from  ASP.NET MVC Framework (Primera parte) &laquo; Thinking in .NET

# C# 3.0 New Feature of the Week #3: Anonymous Types

Friday, November 23, 2007 12:19 PM by Doron's .NET Space

This week&#39;s C# 3.0 New Features article will discuss a neat feature called anonymous types. You&#39;ll

# re: Using C# 3.0 Anonymous Types as Dictionaries

Tuesday, December 04, 2007 6:55 PM by WooBoo

It would be cool to be able constrain input parameters by the interface. Let's say our method declaration would look like this:

public static string GetHtmlLink(IHtmlLinkParams props);

and

interface IHtmlLinkParams{

string text {get;set;}

string href {get;set;}

}

and then we could use it like this:

HtmlHelpers.GetHtmlLink(new { text = "Some Text", href = "http://www.example.org", @class="someClass" })

I know the compiler in this version doesn't accept it but it might be a feature request for C# 4.0 or so and it would please those "C# is not a dynamic language" guys.

# re: Using C# 3.0 Anonymous Types as Dictionaries

Tuesday, December 04, 2007 7:03 PM by Eilon

Hi WooBoo,

I in fact proposed this to the C# guys and they've added it to their list of suggestions for a future version of the language. The suggested syntax is something like:

new : IHtmlLinkParams { text = "Some Text", customProp = "some value" }

This would create an anonymous type that implemented the IHtmlLinkParams that contained an additional "customProp" string property. We'll have to wait and see what they do! :)

- Eilon

# ASP.NET MVC Framework (2?? Parte): URL Routing &laquo; Thinking in .NET

Pingback from  ASP.NET MVC Framework (2?? Parte): URL Routing &laquo; Thinking in .NET

# ASP.NET MVC Design Philosophy

Monday, December 10, 2007 9:30 PM by Eilon Lipton's Blog

This week the first preview of the ASP.NET MVC framework was released to the web as part of the ASP.NET

# re: Using C# 3.0 Anonymous Types as Dictionaries

Wednesday, December 12, 2007 8:32 PM by Jonathan Holland

Hi Eilon,

Perhaps you can answer my question regarding the use of anonymous types instead of dictionaries and the implications that causes when generating things such as RouteTables during runtime instead of compile-time?

codeeleven.blogspot.com/.../yesterday-i-finally-installed-visual.html

Thanks.

# re: Using C# 3.0 Anonymous Types as Dictionaries

Wednesday, December 12, 2007 8:39 PM by Eilon

Hi Jonathan,

There are a couple of ways to do what you want but both are kinda ugly in their own ways.

1. The first is to use a custom build provider. In that implementation you'll be generating C# code (or VB, or whatever) so you can generate your own types and they'll get compiled.

2. Implement the ICustomTypeDescriptor interface on some new type of you're choosing. In the implementation of GetProperties() you can return a custom set of PropertyDescriptors that represent properties you cooked up out of the ether. Or instead of the ether, you could get them from your XML configuration :)

However, in the next preview of the MVC framework we'll just let you pass in dictionaries with your data instead of requiring you to use anonymous types. If you check out my newest blog post on the MVC framework I readily admit that we went "a bit too far" with the syntax :)

Thanks,

Eilon

# re: Using C# 3.0 Anonymous Types as Dictionaries

Thursday, December 13, 2007 11:14 PM by Jonathan Holland

Thanks for your help Eilon. I implemented a CustomTypeDescriptor and everything works great.

You can check it out at:

codeeleven.blogspot.com/.../aspnet-mvc-routebuilder-httpmodule.html

# Testing Routes In ASP.NET MVC

Monday, December 17, 2007 4:06 AM by you've been HAACKED

Testing Routes In ASP.NET MVC

# Testing Routes In ASP.NET MVC

Monday, December 17, 2007 4:19 AM by Community Blogs

The URL routing system within ASP.NET MVC plays a very important role. Routes map incoming requests for

# C# 3.0: Dictionary parameters (like in Ruby)

Wednesday, December 19, 2007 12:04 PM by Joe White's Blog

# ASP.NET MVC Helpers For Repopulating A Form

Friday, December 21, 2007 7:59 PM by Community Blogs

A common pattern when submitting a form in ASP.NET MVC is to post the form data to an action which performs

# Collection Initializers

Sunday, January 06, 2008 2:57 PM by you've been HAACKED

Collection Initializers

# The Weekly Source Code 12 - Back in Black Edition

Tuesday, January 08, 2008 2:43 PM by Scott Hanselman's Computer Zen

# The Weekly Source Code 12 - Back in Black Edition

Tuesday, January 08, 2008 3:10 PM by ASPInsiders

It's been a while since the last Weekly Source Code , but I have the holidays and the preponderance of

# re: Using C# 3.0 Anonymous Types as Dictionaries

Saturday, January 12, 2008 12:00 AM by Jeremy Gray

Since this post seems to be getting some fresh link love even after being posted a while back, I thought I might post a comment that I meant to post when this subject was first brought up ages ago.

The problem with these "anonymous types as dictionaries" approaches that have been popping up is that at the end of the day anonymous types are essentially useless "above" the method in which they are defined, short of breaking out all sorts of low-perf reflection on them or even higher-perf trickery that still needs string keys to make use of the results.

If the main issue here is with that of the syntax required to initialize dictionaries, it doesn't even take .net 3.5, let alone anonymous types to craft extremely tight syntax for creating dictionaries. Consider this piece of sample code of mine ("D" is just a utility function that gets things going):

IDictionary<string, string> d = D<string, string>()

["Key1", "value1"]

["Key2", "value2"]

["Key3", "value3"];

Yes, that's all it takes, and though I will admit that the use of indexers is, well, creative, it is within the guidelines in that it really is a getter and really doesn't change the state of the object on which it was called.

The resulting dictionary also has the benefit of actually being usable without breaking out a pile of reflection.

As for how this is implemented, stick the following words into the back of your head this weekend: "builder", "method chaining", "immutable stack", and "implicit cast". :)

Heck, if you think the implicit cast at the end is pushing it, you can even use an explicit one or an outright method call and the overall syntax doesn't suffer much.

Have at it!

# re: Using C# 3.0 Anonymous Types as Dictionaries

Wednesday, January 16, 2008 4:07 PM by Alex G

I think a lot of people are missing the point. MVC team was clearly inspired by RoR and in this case by Ruby. Creating clear cut easy for a HUMAN to read and write code is a good thing. Few would care that it makes machine's job harder.

In ruby:

get_html_link("Click me", :key1 => "value1", :key2 => "value2", :key3 => "value3")

with C# we can't get syntaxt as clear, but anonymous types let us get pretty close

GetHtmlLink("Click me", new { Key1 = "value1", Key2 = "value2", Key3 = "value3" });

It's pretty obvious that they convert it to a basic dictionary, so what? The framework is trying to make your, developers' jobs more comfortable. I don't see anything wrong with that, even at a slight cost of an overhead.

Web sites are very easily scaled horizontally. If having 22 boxes instead of 20 will keep your developer happier and allow you to have full suite of unit tests, who could argue with that?

# ASP.NET ed i Patterns: ASP.NET MVC (Model, View, Controller) Framework (Parte 2)

Wednesday, January 23, 2008 4:38 AM by Noticias externas

Nella prima parte del post ho introdotto il nuovo ASP.NET MVC Framework fino all&#39;implementazione

# re: Using C# 3.0 Anonymous Types as Dictionaries

Friday, January 25, 2008 4:44 PM by David

@Alex:

I think you are missing the point. C# is a statically typed language. I use C# because for the development that I am doing, I prefer static typing. Ruby is great when I want a dynamic language, but often I DON'T want a dynamic language. But when the major frameworks that are used by my chosen statically typed language start offering API's that only operate in a dynamically typed manner, I am forced to either use dynamic typing (or the C# equivalent), which negates the purpose of me choosing a statically typed language in the first place, or not use the framework, which negates a major reason why I chose .NET in the first place (the framework support).

People in charge of designing these major frameworks (including the MVC team as well as the C# language team) need to get OFF the bandwagon and realize that just because dynamic languages are all the rage right now does not mean that forcing dynamic features into a statically typed language is a good idea.

# re: Using C# 3.0 Anonymous Types as Dictionaries

Monday, February 11, 2008 4:24 AM by [ICR]

I always liked the idea of extending the var params style of C# to also use dictionaries, so the method signature would look like:

static void MyMethod(int argument1, params IDictionary<int> argument2)

And then you could call it like:

MyMethod(10, fish = 10, food = 20);

This comes very close, cheers.

# re: Using C# 3.0 Anonymous Types as Dictionaries

Monday, February 18, 2008 1:46 PM by anonymous

Why in the world would you use an array when you can have a strongly typed list of object?

# [转自scott]ASP.NET MVC框架 (第二部分): URL路径选择

Thursday, April 03, 2008 4:35 AM by 菩提树下的杨过

英文原文地址:weblogs.asp.net/.../asp-net-mvc-framework-part-2-url-routing.as...

# [转自Scott]ASP.NET MVC框架(第三部分): 把ViewData从控制器传到视图

Sunday, April 06, 2008 11:39 PM by 菩提树下的杨过

英文原文地址:weblogs.asp.net/.../asp-net-mvc-framework-part-3-passing-viewda...

# re: Using C# 3.0 Anonymous Types as Dictionaries

Tuesday, April 22, 2008 3:54 PM by aaron

For those of you complaining about not wanting any dynamically influenced language features in your code: don't use them. For everyone else, Rejoice!

# re: Using C# 3.0 Anonymous Types as Dictionaries

Sunday, May 25, 2008 2:53 PM by Stormy

All these arguments are moot really, about the value of anonymous types, etc.

You should NEVER build a web application that has its markup tags and attributes generated  via dependencies in backend code like this. The whole point of CSS/XHTML and the whole Web Standards movement is to get away from the whole concept of generating HTML in the backend and separation of business logic from the UI layer. This reminds me of the messy html used in ASP.NET 1.1. The HTML Helpers are also breaking this separation in that model.

What you should do is have a static web page with anchor tags and a full set of attributes with default values assigned. This allows UI designers control over the interface design. When it comes time to manipulate the attributes of these tags, the backend should pass in the control and change attributes as properties on that control like ASP.NET does now with HTML Server Controls, not dynamically generate these links in the backend.

What happens if the UI designer does NOT want that anchor displayed, or wants to customize it via JavaScript, or expects to pull in additional attributes or databinding to those attributes? This model would have to be retooled. I say, all of you need to go back to school and relearn basic HTML 101.

Leave a Comment

(required) 
(required) 
(optional)
(required)