2009-08-23 14 views
24

Ben bir işlevi gibi olması bir yol arıyorum:Anahtar değer çiftleri

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

oldukça kolay olurdu anonim türleriyle şey var eminim ama değilim onu görmek Aklıma

tek çözüm bir "parametreler KeyValuePair [] çiftleri" parametresini sahip olmaktır, ama buna benzer bir şey olmak biter: Kuşkusuz, daha çirkin

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

.

DÜZENLEME:

Ben 2 farklı sistemler arasında geçirmek için "Mesaj" sınıf yazıyorum, netleştirmek için. İleti Türünü ve ileti ile ilişkili "Veriler" için nesne oluşturmak üzere bir dize sözlüğünü belirten bir ushort içerir. Kurucudaki tüm bu bilgileri iletmek istiyorum, bu yüzden bunu yapabilirim:

Agent.SendMessage (yeni ileti (MessageTypes.SomethingHappened, "A", x, "B", y "C", z)); veya benzer sözdizimi.

+0

. Bunu kontrol ettiğinizden emin olun. –

cevap

52

Sözdizimi düzgün olmayan bir desen için kötü olduğunda, sözdizimini değiştirin.Nasıl hakkında:

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

Kullanımı:

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

Daha da ilginç o pairable yapmak için string bir uzantı yöntemini eklemek olacaktır:

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

Kullanımı:

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

Düzenleme: Ayrıca Dictionary<,> türetmek jenerik parantez olmadan Sözlük sözdizimini kullanabilirsiniz:

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

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

Kullanımı:

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

Hmm, bu akıllıca bir çözüm, beğeniyorum. Sanırım kullanacağım şey bu. Teşekkür ederim. Başka bir çözüm bulunup bulunmadığını görmek için bir iki saatliğine cevapsız bırakacağım. – Quantumplation

+0

Ya da boks yoluna gidebilir ve 'MyFunction (params nesnesi [] args)' –

2

bir sözlük kullanma: yalındır

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

, değil her görüşün, yalnızca bir new Dictionary<K, V> gerekir. Anahtarları ve değerleri almak çok önemsiz.

Ya anonim bir tip

:

işlevi içinde kullanımı çok güzel değil
myFunction(new { 
    Key = value, 
    Key2 = value}); 

, yansıma gerekir. Bu şuna benzer olacaktır:

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

(staight kafamın, muhtemelen bazı hatalar ... itibaren)

+0

Anahtar/değer çiftlerini ikinci türden nasıl çıkarırım? – Quantumplation

+0

İkinci, asp.net MVC'deki ActionLink yönteminde bulunur. Bu özellik isimlerini ve değerlerini elde etmek için düşünmeye ihtiyaç var mı? –

2

kullanın 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

Evet, ancak işlevin çağrılması, önceden bir sözlük bildirme gereği ile burada karmaşıktır. Ayrıca, .Dump() ne için? – Quantumplation

+0

Oops, Dump LINQPad'den geliyor, sadece Console.Writeline'ı düşünün. Neden tek bir açıklamada herşeye sahip olmak için kendinize boyun eğdirdiniz? Arayüzünüzü düzeltmelisiniz. Arama kuralı endişesi uzak bir saniye olmalı. –

+2

Bir Message sınıfının kurucusu için, çok sık gönderilen bir şey ve daha sonra bir istenmeyen çağrı çağrısı geçecek. Bir sözlük beyan etmek, anahtarları eklemek ve mesajların gönderildiği birçok farklı örnek için kurucuya iletmek zorunda kalmak, bir okuyucu/yazarın neler olup bittiğinden uzaklaşmasını sağlamak ve böylece sürdürülmesi daha da zorlaşır. – Quantumplation

2

İşte aynı daha var: bir sözlük initialising üzerinde

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

Bazı ayrıntılar here bulunabilir.

7

A kesmek biraz, ama sen Message sınıf var olabilir IEnumerable arabirimini uygulayın ve bir Add yöntemini verin.

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

Yansıma yönteminden çok daha az yükü var gibi gözüküyor ve muhtemelen bir hack değil her durumda. – Quantumplation

+1

'Message' sınıfınızın gerçek bir koleksiyon gibi davranmasını istediğiniz yere bağlı olarak, 'IEnumerable' yerine" daha büyük "bir arabirim uygulayabilirsiniz (örneğin,' IDictionary '). Sadece IEnumerable'ı seçtim, çünkü toplama ekolayzır sözdizimini minimum miktarda ekstra çalışma ile sağlıyor! – LukeH

7

Komik, sadece yaratılan (önce dakika) anonim türleri ve yansıma kullanarak, bunu yapmak için izin veren bir yöntem:

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

Mükemmel! Bu sadece aradığım çözümdü. Yansıma yüzünden ne kadar yük var? – Quantumplation

+0

Fikrim yok ... Her neyse, bu çözüm kullanışlı, ancak uygulamanız için performans kritikse uygun değil –

1

You Ardından Koleksiyon başlatıcı sözdizimini kullanmak mümkün olacak yapabileceği: DateField ve IdField gerekiyordu

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

bir 'dize' künyesini olmak 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); 
} 

Performans Sözlük kullanarak% 5 daha hızlıdır. Dezavantaj: Değişken anahtar olarak kullanamazsınız. C# 4.0 dinamik türüyle

2

:

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

Çağrı kullanarak:

MyFunction(new {Key = "Key1", Value = "Value1"}, new {Key = "Key2", Value = "Value2"}); 
0
Ekstra sınıfta olmadan @Bryan Watts en Pairing.Of benzer bir şey elde etmek dizilerini kullanabilirsiniz

:

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

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

Ayrıca, nugetpackage "valuetuple" öğelerine de başvurabilirsiniz.

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

Sonra böyle bir yöntemini çağırabilirsiniz: aşağıdakileri yapın

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

7,0 C# olduğundan, değer dizilerini kullanabilirsiniz. C# 7.0 sadece yeni bir tip değil, aynı zamanda yeni bir basitleştirilmiş sözdizimi tanıtıyor.

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

Bu iki ayrı değişkenlerde başlığın öğeleri ayıklar key ve value gibi bir tuple yapısızlaştırmak da mümkündür.

Artık bağımsız değişkenlerin değişen sayıda fonksiyonu şu şekilde çağırabilirsiniz:

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

Bkz: New Features in C# 7.0 Ben Sözlük sözdizimi kullanmak için makul bir yol içerecek şekilde cevabım düzenlenmiş

İlgili konular