7
votes

Dans C #, est-il un moyen d'écrire des initialisateurs d'objets personnalisés pour de nouveaux types de données?

in c #, il y a la technique de l'initialiseur "standard" {property1 = "a", property2 = "B"}, et il y a quelques variantes spéciales pour collections (liste et dictionnaire). {Value1, Value2}, et {{"Key1", Value1}, {"Key2", Value2}}.

J'aimerais avoir un initialiseur d'objet récursif pour un type de données d'arbres, mais je ne sais pas s'il y a un moyen de personnaliser ce mécanisme. J'aimerais quelque chose qui ressemble à une expression de S. {item1 {item2 item3 item4} {item5 item6}}

Je fais cela via des constructeurs, mais je voudrais une syntaxe de erser.


0 commentaires

3 Réponses :


4
votes

Utilisation d'un Variagin Lambda local N code> qui appelle simplement votre constructeur, vous pouvez l'obtenir aussi court que:

var n = (params Node[] nodes) => new Node(nodes);


3 commentaires

Pourquoi ne pas simplement dire des params? Ceci est une question C #.


Réponse rapide! C'est une solution assez intéressante, mais il faudrait définir la Lambda chaque fois que je souhaite effectuer une initialisation. En outre, il exigerait que tous les paramètres variadiques soient des éléments ou des arbres d'éléments, pas à la fois mélangés (par exemple, élément1, n (item2, élément3), point4) ne serait pas possible.


Vous pouvez définir la Lambda une fois et créer une référence locale lorsque vous avez besoin de la syntaxe plus courte. Aide un peu. Si vos articles d'arbre ne sont pas des nœuds eux-mêmes, vous pouvez modifier la Lambda pour accepter un objet Général [] et faire de la magie dessus.



11
votes

Si vous implémentez l'interface Strike> Icollection Strike> Icollection et avez une méthode appelée Ajouter. Incidemment, tout cela est inclus dans l'interface de l'ICOLLECTION, c'est pourquoi je l'ai confondu.

Test test = new Test() {
    new Test2() {
        new Test3() {

        }
    },
    new Test() {
        new Test2() {
            { new Test(), new Test2() },
            { new Test(), new Test2() },
            { new Test(), new Test2() }
        }
    }
};

public class Test : IEnumerable
{
    public void Add(Test a){}
    public void Add(Test2 a){}
    public IEnumerator GetEnumerator(){}
}

public class Test2 : IEnumerable
{
    public void Add(Test a, Test2 b){}
    public void Add(Test3 a){}
    public IEnumerator GetEnumerator(){}
}

public class Test3 : IEnumerable
{
    public void Add(Test a) {}
    public void Add(Test2 a){}
    public IEnumerator GetEnumerator(){}
}


4 commentaires

Vous n'avez pas besoin de mettre en œuvre l'ICOLLECTION - Juste iEnumerable.


Ce n'est pas aussi vrai que ce que j'imaginais, mais il semble que c'est aussi proche que possible. Il semble que la réponse à cela est que vous ne pouvez pas vraiment personnaliser le mécanisme d'initialisation de l'objet, mais vous pouvez faire du piggyback sur le support d'initialisation iEnumérable intégré.


Trouvé un article de blog sur cette Resharper.blogspot.com/ 2007/09 / ...


Donc, cherchez plus près de votre message, j'ai remarqué que la méthode d'ajout est la clé. Accepté! (Bien que ce ne soit pas aussi de terres que j'espérais)



1
votes

Si les nœuds de votre arborescence sont faciles à construire, c'est-à-dire que vous pouvez être initialisé à partir de leur valeur, vous pouvez rendre les choses erser que la réponse de Chaospandion, en ajoutant une méthode supplémentaire:

new Tree { "item1", new Tree { "item2", "item3", "item4" }, new Tree { "item5", "item6" } };


0 commentaires