Key value pairs in C# Params

2019-03-22 15:07发布

I'm looking for a way to have a function such as:

myFunction({"Key", value}, {"Key2", value});

I'm sure there's something with anonymous types that would be pretty easy, but I'm not seeing it.

The only solution I can think of is to have a "params KeyValuePair[] pairs" parameter, but that ends up being something similar to:

myFunction(new KeyValuePair<String, object>("Key", value), new KeyValuePair<String, object>("Key2", value));

Which is, admittedly, much uglier.

EDIT:

To clarify, I'm writing a "Message" class to pass between 2 different systems. It contains a ushort specifying the the Message Type, and a dictionary of string to object for "Data" associated with the message. I'd like to be able to pass all this information in the constructor, so I am able to do this:

Agent.SendMessage(new Message(MessageTypes.SomethingHappened, "A", x, "B", y, "C", z)); or similar syntax.

11条回答
聊天终结者
2楼-- · 2019-03-22 15:44

You can do that:

TestNamedMethod(DateField => DateTime.Now, IdField => 3);

where DateField and IdField are supposed to be a 'string' identifiers.

The TestNameMethod:

public static string TestNameMethod(params Func<object, object>[] args)
{
    var name = (args[0].Method.GetParameters()[0]).Name;
    var val = args[0].Invoke(null);
    var name2 = (args[1].Method.GetParameters()[0]).Name;
    var val2 = args[1].Invoke(null);
    Console.WriteLine("{0} : {1}, {2} : {3}", name, val, name2, val2);
}

Performance is 5% faster than using Dictionary. Disadvantage: you can't use variable as a key.

查看更多
我命由我不由天
3楼-- · 2019-03-22 15:45

A bit of a hack, but you could have your Message class implement the IEnumerable interface and give it an Add method. You'll then be able to use collection initializer syntax:

Agent.SendMessage
(
    new Message(MessageTypes.SomethingHappened) {{ "foo", 42 }, { "bar", 123 }}
);

// ...

public class Message : IEnumerable
{
    private Dictionary<string, object> _map = new Dictionary<string, object>();

    public Message(MessageTypes mt)
    {
        // ...
    }

    public void Add(string key, object value)
    {
        _map.Add(key, value);
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return ((IEnumerable)_map).GetEnumerator();
        // or throw a NotImplementedException if you prefer
    }
}
查看更多
霸刀☆藐视天下
4楼-- · 2019-03-22 15:47

You could also reference the nugetpackage "valuetuple", which allows you to do the following:

public static void MyFunction(params ValueTuple<string, object>[] pairs)
{
    var pair = pairs[1];
    var stringValue = pair.item1;
    var objectValue = pair.item2;
}

You can then call the method like this:

MyFunction(("string",object),("string", object));
查看更多
混吃等死
5楼-- · 2019-03-22 15:48

You could use Tuples to achieve something similar to @Bryan Watts's Pairing.Of without the extra class:

public static void MyFunction(params Tuple<string, int>[] pairs)
{
}

MyFunction(Tuple.Create("foo", 1), Tuple.Create("bar", 2));
查看更多
对你真心纯属浪费
6楼-- · 2019-03-22 15:49

Here's more of the same:

static void Main(string[] args)
{
    // http://msdn.microsoft.com/en-us/library/bb531208.aspx
    MyMethod(new Dictionary<string,string>()
    {
        {"key1","value1"},
        {"key2","value2"}
    });
}

static void MyMethod(Dictionary<string, string> dictionary)
{
    foreach (string key in dictionary.Keys)
    {
        Console.WriteLine("{0} - {1}", key, dictionary[key]);
    }
}

Some details on initialising a dictionary can be found here.

查看更多
登录 后发表回答