it-swarm-ru.tech

Буквальная нотация для словаря в C #?

В настоящее время у меня есть WebSocket между JavaScript и сервером, запрограммированным на C #. В JavaScript я могу легко передавать данные, используя ассоциативный массив:

var data = {'test': 'val',
            'test2': 'val2'};

Чтобы представить этот объект данных на стороне сервера, я использую Dictionary<string, string>, но это более "дорого печатает", чем в JavaScript:

Dictionary<string, string> data = new Dictionary<string,string>();
data.Add("test", "val");
data.Add("test2", "val2");

Есть ли какая-нибудь буквальная запись для ассоциативных массивов/Dictionarys в C #?

158
pimvdb

Вы используете синтаксис инициализатор коллекции , но вам все равно нужно сначала создать объект new Dictionary<string, string>, так как синтаксис ярлыка преобразуется в набор вызовов Add() (например, ваш код):

var data = new Dictionary<string, string>
{
    { "test", "val" }, 
    { "test2", "val2" }
};

В C # 6 теперь у вас есть возможность использовать более интуитивный синтаксис со словарем, а также любой другой тип, который поддерживает indexers . Вышеприведенное утверждение можно переписать так:

var data = new Dictionary<string, string>
{
    ["test"] = "val",
    ["test2"] = "val2"
};

В отличие от инициализаторов коллекций, это вызывает установщик индексатора изнутри, а не соответствующий метод Add().

259
BoltClock

Хотя ответ инициализатора словаря является полностью правильным, есть другой подход, на который я хотел бы обратить внимание (но я бы не рекомендовал его). Если ваша цель - обеспечить краткое использование API, вы можете использовать анонимные объекты.

var data = new { test1 = "val", test2 = "val2"};

В этом случае переменная "data" имеет "невыразимый" анонимный тип, так что вы можете передать это только как System.Object. Затем вы можете написать код, который может преобразовать анонимный объект в словарь. Такой код будет опираться на рефлексию, которая потенциально будет медленной. Однако вы можете использовать System.Reflection.Emit или System.Linq.Expressions для компиляции и кэширования делегата, который сделает последующие вызовы намного быстрее.

API MVC Asp.net используют эту технику во многих местах, которые я видел. Многие помощники HTML имеют перегрузки, которые принимают либо объект, либо словарь. Я предполагаю, что цель их API-дизайна такая же, как и вы; краткий синтаксис при вызове метода.

12
MarkPflug

Используя DynamicObject, не так сложно создать простой инициализатор словаря.

Представьте, что вы хотите вызвать следующий метод

void PrintDict(IDictionary<string, object> dict) {
    foreach(var kv in dict) {
        Console.WriteLine ("  -> " + kv.Key + " = " + kv.Value);
    }
}

используя буквальный синтаксис, такой как

var dict = Dict (Hello: "World", IAm: "a dictionary");
PrintDict (dict);

Это может быть достигнуто путем создания такого динамического объекта

dynamic Dict {
    get {
        return new DynamicDictFactory ();
    }
}

private class DynamicDictFactory : DynamicObject
{
    public override bool TryInvoke (InvokeBinder binder, object[] args, out object result)
    {
        var res = new Dictionary<string, object> ();
        var names = binder.CallInfo.ArgumentNames;

        for (var i = 0; i < args.Length; i++) {
            var argName = names [i];
            if(string.IsNullOrEmpty(argName)) throw new ArgumentException();
            res [argName] = args [i];
        }
        result = res;
        return true;
    }
}
5
Krumelur

Используйте словарь литералов (предложение C # 9)

В C # 9 введен более простой синтаксис для создания инициализированных объектов Dictionary<TKey,TValue> без необходимости указывать имя типа словаря или параметры типа. Параметры типа для словаря выводятся с использованием существующих правил, используемых для вывода типа массива.

// C# 1..8    
var x = new Dictionary <string,int> () { { "foo", 4 }, { "bar", 5 }};   
// C# 9    
var x = ["foo":4, "bar": 5];  

Этот synthax упрощает работу со словарями в C # и убирает лишний код.

Вы можете следить за этой проблемой на GitHub (а вот веха для C # 9 ).

0
aloisdg