Key value pairs in C# Params

前端 未结 8 2417
后悔当初
后悔当初 2021-02-11 14:55

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

相关标签:
8条回答
  • 2021-02-11 15:31

    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.

    0 讨论(0)
  • 2021-02-11 15:34

    With dynamic type in C# 4.0:

    public class MyClass
    {
        // Could use another generic type if preferred
        private readonly Dictionary<string, dynamic> _dictionary = new Dictionary<string, dynamic>();
    
        public void MyFunction(params dynamic[] kvps)
        {
            foreach (dynamic kvp in kvps)
                _dictionary.Add(kvp.Key, kvp.Value);
        }
    }
    

    Call using:

    MyFunction(new {Key = "Key1", Value = "Value1"}, new {Key = "Key2", Value = "Value2"});
    
    0 讨论(0)
  • 2021-02-11 15:34

    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

    0 讨论(0)
  • 2021-02-11 15:35

    Use a Dictionary ...

    void Main()
    {
        var dic = new Dictionary<string, object>();
        dic.Add( "Key1", 1 );
        dic.Add( "Key2", 2 );   
    
        MyFunction( dic ).Dump();
    }
    
    public static object MyFunction( IDictionary dic )
    {
       return dic["Key1"];
    }
    
    0 讨论(0)
  • 2021-02-11 15:37

    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
        }
    }
    
    0 讨论(0)
  • 2021-02-11 15:41

    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 } });
    
    0 讨论(0)
提交回复
热议问题