web-dev-qa-db-fra.com

Notation littérale pour Dictionnaire en C #?

J'ai actuellement un WebSocket entre JavaScript et un serveur programmé en C #. En JavaScript, je peux facilement transmettre des données à l'aide d'un tableau associatif:

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

Pour représenter cet objet de données côté serveur, j'utilise un Dictionary<string, string>, mais cela coûte plus cher en dactylographie qu'en JavaScript:

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

Existe-t-il une sorte de notation littérale pour les tableaux associatifs/Dictionarys en C #?

163
pimvdb

Vous utilisez la syntaxe collection initializer , mais vous devez tout d’abord créer un objet new Dictionary<string, string>, Car la syntaxe du raccourci est traduite en un groupe d’appels Add() (comme votre code):

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

En C # 6, vous avez maintenant la possibilité d'utiliser une syntaxe plus intuitive avec Dictionary, ainsi que tout autre type prenant en charge indexeurs . La déclaration ci-dessus peut être réécrite comme suit:

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

Contrairement aux initialiseurs de collection, cela appelle l'indexeur sous le capot, plutôt qu'une méthode Add() appropriée.

267
BoltClock

Bien que la réponse de l’initialiseur de dictionnaire soit tout à fait correcte, il existe une autre approche que j’aimerais souligner (mais je ne le recommanderais peut-être pas). Si votre objectif est de fournir une utilisation limitée de l'API, vous pouvez utiliser des objets anonymes.

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

La variable "data" est alors de type anonyme "indéfinissable", vous ne pouvez donc la transmettre qu'en tant que System.Object. Vous pourriez alors écrire du code pouvant transformer un objet anonyme en dictionnaire. Un tel code reposerait sur une réflexion qui pourrait être lente. Cependant, vous pouvez utiliser System.Reflection.Emit, ou System.Linq.Expressions pour compiler et mettre en cache un délégué qui ferait les appels suivants beaucoup plus rapidement.

Les API Asp.net MVC utilisent cette technique dans un certain nombre d'endroits que j'ai vus. Un grand nombre d'aides HTML ont des surcharges acceptant un objet ou un dictionnaire. Je suppose que l'objectif de la conception de leurs API est identique à celui que vous recherchez. syntaxe concise lors de l'appel de la méthode.

12
MarkPflug

En utilisant DynamicObject, il n’est pas si difficile de créer un initialiseur de dictionnaire plus simple.

Imaginez que vous souhaitez appeler la méthode suivante

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

en utilisant une syntaxe littérale comme

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

Ceci peut être accompli en créant un objet dynamique comme celui-ci

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;
    }
}
6
Krumelur

Utiliser les littéraux de dictionnaire (proposition C # 9)

C # 9 introduit une syntaxe plus simple pour créer des objets initialisés Dictionary<TKey,TValue> Sans avoir à spécifier le nom du type de dictionnaire ou les paramètres de type. Les paramètres de type du dictionnaire sont déduits à l'aide des règles existantes utilisées pour l'inférence de type de tableau.

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

Cette synthax simplifie l'utilisation des dictionnaires en C # et supprime le code redondant.

Vous pouvez suivre le problème sur GitHub (et voici le jalon pour C # 9 ).

1
aloisdg