Key value pairs in C# Params

When the syntax is bad for an otherwise decent pattern, change the syntax. How about:

public void MyFunction(params KeyValuePair<string, object>[] pairs)
{
    // ...
}

public static class Pairing
{
    public static KeyValuePair<string, object> Of(string key, object value)
    {
        return new KeyValuePair<string, object>(key, value);
    }
}

Usage:

MyFunction(Pairing.Of("Key1", 5), Pairing.Of("Key2", someObject));

Even more interesting would be to add an extension method to string to make it pairable:

public static KeyValuePair<string, object> PairedWith(this string key, object value)
{
    return new KeyValuePair<string, object>(key, value);
}

Usage:

MyFunction("Key1".PairedWith(5), "Key2".PairedWith(someObject));

Edit: You can also use the dictionary syntax without the generic brackets by deriving from Dictionary<,>:

public void MyFunction(MessageArgs args)
{
    // ...
}

public class MessageArgs : Dictionary<string, object>
{}

Usage:

MyFunction(new MessageArgs { { "Key1", 5 }, { "Key2", someObject } });

Since C# 7.0, you can use value tuples. C# 7.0 not only introduces a new type but a simplified syntax for tuple types and for tuple values. A tuple type is simply written as a list of types surrounded by braces:

(string, int, double)

The corresponding elements are named Item1, Item2, Item2. You can also specify optional aliases. These aliases are only syntactic sugar (a trick of the C# compiler); the tuples are still based on the invariant (but generic) System.ValueTuple<T1, T2, ...> struct.

(string name, int count, double magnitude)

Tuple values have a similar syntax, except that you specify expressions instead of types

("test", 7, x + 5.91)

or with the aliases

(name: "test", count: 7, magnitude: x + 5.91)

Example with params array:

public static void MyFunction(params (string Key, object Value)[] pairs)
{
    foreach (var pair in pairs) {
        Console.WriteLine($"{pair.Key} = {pair.Value}");
    }
}

It is also possible to deconstruct a tuple like this

var (key, value) = pair;
Console.WriteLine($"{key} = {value}");

This extracts the items of the tuple in two separate variables key and value.

Now, you can call MyFunction with a varying number of arguments easily:

MyFunction(("a", 1), ("b", 2), ("c", 3));

It allows us to do things like

DrawLine((0, 0), (10, 0), (10, 10), (0, 10), (0, 0));

See: New Features in C# 7.0


Funny, I just created (minutes ago) a method that allows to do that, using anonymous types and reflection :

MyMethod(new { Key1 = "value1", Key2 = "value2" });


public void MyMethod(object keyValuePairs)
{
    var dic = DictionaryFromAnonymousObject(keyValuePairs);
    // Do something with the dictionary
}

public static IDictionary<string, string> DictionaryFromAnonymousObject(object o)
{
    IDictionary<string, string> dic = new Dictionary<string, string>();
    var properties = o.GetType().GetProperties();
    foreach (PropertyInfo prop in properties)
    {
        dic.Add(prop.Name, prop.GetValue(o, null) as string);
    }
    return dic;
}