2009-08-23 10 views
24

मैं इस तरह के रूप में एक समारोह के लिए एक तरह से तलाश कर रहा हूँ:सी # पैरामीटर में कुंजी मान युग्म

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

मैं वहाँ गुमनाम प्रकार के साथ कुछ है कि बहुत आसान हो जाएगा है यकीन है, लेकिन मैं नहीं कर रहा हूँ इसे देखकर

एकमात्र समाधान मैं के बारे में सोच सकते हैं एक "पैरामीटर KeyValuePair [] जोड़े" पैरामीटर के लिए है, लेकिन यह करने के लिए कुछ इसी तरह किया जा रहा समाप्त होता है:

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

कौन सा है, बेशक, बहुत भद्दा।

संपादित करें:

स्पष्ट करने के लिए, मैं एक "संदेश" वर्ग 2 अलग प्रणालियों के बीच पारित करने के लिए लिख रहा हूँ। इसमें संदेश प्रकार से निर्दिष्ट "डेटा" के लिए ऑब्जेक्ट करने के लिए संदेश प्रकार और स्ट्रिंग का एक शब्दकोश निर्दिष्ट करने वाला एक यूहॉर्ट शामिल है। मैं इस जानकारी को कन्स्ट्रक्टर में पास करने में सक्षम होना चाहता हूं, इसलिए मैं यह करने में सक्षम हूं:

एजेंट .ेंड मैसेज (नया संदेश (संदेश प्रकार। कुछ हो रहा है, "ए", एक्स, "बी", वाई , "सी", जेड)); या इसी तरह के वाक्यविन्यास।

+0

मैं अपने जवाब संपादित वाक्य रचना शब्दकोश का उपयोग करने के लिए एक उचित तरीका शामिल करने के लिए। इसे जांचना सुनिश्चित करें। –

उत्तर

52

जब वाक्यविन्यास अन्यथा सभ्य पैटर्न के लिए बुरा होता है, तो वाक्यविन्यास बदलें।कैसे के बारे में:

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); 
    } 
} 

उपयोग:

MyFunction(Pairing.Of("Key1", 5), Pairing.Of("Key2", someObject)); 
इससे भी अधिक दिलचस्प string के लिए एक विस्तार विधि जोड़ने का यह pairable बनाने के लिए किया जाएगा

:

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

उपयोग:

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

संपादित: तुम भी Dictionary<,> से पाने से सामान्य कोष्ठक के बिना वाक्य रचना शब्दकोश का उपयोग कर सकते हैं:

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

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

उपयोग:

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

हम्म, यह एक चालाक समाधान है, मुझे यह पसंद है। मुझे लगता है कि मैं यही उपयोग करूंगा। धन्यवाद। मैं यह देखने के लिए कि क्या कोई अन्य समाधान भी आ रहा है, मैं एक या दो घंटे के लिए अनुत्तरित प्रश्न छोड़ने जा रहा हूं। – Quantumplation

+0

या आप मुक्केबाजी मार्ग पर जा सकते हैं और 'माईफंक्शन (पैराम्स ऑब्जेक्ट [] तर्क) ' –

2

एक शब्दकोश का उपयोग करना:

myFunction(new Dictionary<string, object>(){ 
    {"Key", value}, 
    {"Key2", value}}); 

कौन सीधे आगे है, तो आप प्रत्येक तर्क के लिए नहीं, केवल एक new Dictionary<K, V> की जरूरत है। कुंजी और मूल्य प्राप्त करना मुश्किल है।

या एक गुमनाम प्रकार के साथ:

myFunction(new { 
    Key = value, 
    Key2 = value}); 

कौन सा बहुत समारोह के अंदर उपयोग करने के लिए अच्छा नहीं है, तो आप प्रतिबिंब की आवश्यकता होगी। यह कुछ इस तरह दिखेगा:

foreach (PropertyInfo property in arg.GetType().GetProperties()) 
{ 
    key = property.Name; 
    value = property.GetValue(arg, null); 
} 

(staight मेरे सिर, शायद कुछ त्रुटियाँ ... से)

+0

मैं दूसरे प्रकार के कुंजी/मूल्य जोड़े कैसे आकर्षित करूं? – Quantumplation

+0

आपको एएसपीनेट एमवीसी में एक्शनलिंक विधि में दूसरा स्थान मिलता है। क्या संपत्ति के नाम और मूल्यों को प्राप्त करने के लिए इसे प्रतिबिंब की आवश्यकता है? –

2

का प्रयोग करें एक 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"]; 
} 
+1

वैसे हां, लेकिन फ़ंक्शन का कॉलिंग पहले शब्दकोश को घोषित करने की आवश्यकता से जटिल है। इसके अलावा, डंप() के लिए क्या है? – Quantumplation

+0

ओह, डंप LINQPad से है, बस कंसोल सोचें। राइटलाइन। आप सब कुछ एक बयान में रखने के लिए खुद का विरोध क्यों करेंगे? आपको अपना इंटरफ़ेस सही बनाना चाहिए। कॉलिंग सम्मेलन के बारे में चिंता करना एक दूर दूसरा होना चाहिए। –

+2

यह एक संदेश वर्ग के निर्माता के लिए है, जो अक्सर भेजा जाता है, और बाद में एक अनावश्यक कॉलिंग सम्मेलन में जा रहा है। एक शब्दकोश घोषित करना, चाबियां जोड़ना, और इसे कई अलग-अलग उदाहरणों के लिए निर्माता को पास करना जहां संदेश भेजे जाते हैं, सहन करना मुश्किल हो जाता है, और पाठक/लेखक को जो हो रहा है उससे दूर ले जाता है, और इस प्रकार इसे बनाए रखना कठिन हो जाता है। – Quantumplation

2

यहाँ उसी के अधिक है:

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]); 
    } 
} 

शब्दकोश को शुरू करने के बारे में कुछ विवरण here मिल सकते हैं।

7

हैक के बारे में थोड़ी, लेकिन आप अपने Message वर्ग हो सकता था IEnumerable इंटरफ़ेस को कार्यान्वित करें और इसे Add विधि दें। (मिनट पहले)

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

ऐसा लगता है कि प्रतिबिंब विधि से बहुत कम ओवरहेड होता है, और वास्तव में शायद एक हैक नहीं है, क्योंकि मैं एक ऐड फ़ंक्शन चाहता हूं किसी भी मामले। – Quantumplation

+1

इस पर निर्भर करता है कि आप अपने 'संदेश' वर्ग को वास्तविक संग्रह की तरह व्यवहार करने के लिए कितना चाहते हैं, इसके बजाय आप 'inumerable' की तुलना में" बड़ा "इंटरफ़ेस लागू कर सकते हैं (उदाहरण के लिए, 'IDictionary ')। मैंने केवल 'आईनेमेरेबल' चुना है क्योंकि यह अतिरिक्त प्रारंभिक कार्य के साथ संग्रह प्रारंभकर्ता वाक्यविन्यास की अनुमति देता है! – LukeH

7

अजीब बात है, मैं अभी बनाया एक विधि है कि अज्ञात प्रकार और प्रतिबिंब का उपयोग कर, ऐसा करने की अनुमति देता है::

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; 
} 
+0

बिल्कुल सही! यह सिर्फ एक तरह का समाधान है जिसे मैं ढूंढ रहा था। प्रतिबिंब के कारण कितना उपर है? – Quantumplation

+0

कोई विचार नहीं ... वैसे भी, यह समाधान आसान है, लेकिन यदि आपके ऐप के लिए प्रदर्शन महत्वपूर्ण है तो उपयुक्त नहीं है –

1

आप इसके बाद आप संग्रह प्रारंभकर्ता सिंटैक्स का उपयोग करने में सक्षम हो जाएगा ऐसा कर सकते हैं:

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

जहां DateField और IdField अपेक्षा की जाती है एक 'स्ट्रिंग' identif होने के लिए IERS।

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); 
} 

प्रदर्शन 5% शब्दकोश का उपयोग कर की तुलना में तेजी है। नुकसान: आप एक कुंजी के रूप में चर का उपयोग नहीं कर सकते हैं।

2
सी # 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); 
    } 
} 

कॉल का उपयोग कर:

MyFunction(new {Key = "Key1", Value = "Value1"}, new {Key = "Key2", Value = "Value2"}); 
0

आप अतिरिक्त वर्ग के बिना @Bryan वाट के Pairing.Of को कुछ इसी तरह प्राप्त करने के लिए tuples इस्तेमाल कर सकते हैं:

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

MyFunction(Tuple.Create("foo", 1), Tuple.Create("bar", 2)); 
0

आप nugetpackage "वैल्यूएटप्ले" का भी संदर्भ दे सकते हैं, जो आपको अनुमति देता है

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

फिर आप इस तरह विधि कॉल कर सकते हैं: निम्न कार्य

MyFunction(("string",object),("string", object)); 
1

के बाद से सी # 7.0, आप मूल्य tuples उपयोग कर सकते हैं। सी # 7.0 न केवल एक नए प्रकार का परिचय देता है बल्कि टुपल्स के लिए एक नया सरलीकृत वाक्यविन्यास प्रस्तुत करता है।

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

यह भी इस

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

यह दो अलग-अलग चर में टपल का अर्क key और value की तरह एक टपल deconstruct करने के लिए संभव है।

अब आप तर्क का एक अलग संख्या के साथ इस तरह इस समारोह कॉल कर सकते हैं:

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

देखें: New Features in C# 7.0

संबंधित मुद्दे