2016-10-17 1 views
2

Je cherche/tring pour implémenter une implémentation de type coffre-fort en C#.in C# pour l'implémentation de l'arborescence de type safe (node ​​typesafe)

Comment une arborescence de type sécurisée peut-elle être implémentée, sans utiliser d'interface (qui oblige à réimplémenter la fonctionnalité de l'arborescence un peu partout) et sans utiliser de conversions? J'ai l'idée d'utiliser l'arbre comme classe de base commune, mais alors la sécurité du type a disparu. Mon approche actuelle est l'utilisation de génériques. Mais il me manque une conversion vers le type de base.

Voici un exemple réduit/non fonctionnel. L'idée est que les nœuds renvoyés prennent en charge les fonctions de l'arborescence et, en même temps, prennent également en charge leur comportement des types de base. Je pourrais utiliser la classe below sans et hériter de Node, mais alors je perds la sécurité de type d'une part, et aussi des problèmes d'héritage, car les Nodes ont déjà des classes parentes. J'ai également joué avec des extensions de classe, mais je n'ai rien qui soit proche d'une solution possible.

Je pense que j'ai besoin d'un petit indice sur la façon de continuer. Merci d'avance.

public class Node<T> // . 
{ 
    public Node<T> parent; 
    public List<Node<T>> children; 

    protected Node() 
    { 
     children = new List<Node<T>>(); 
     parent = null; 
    } 
    protected Node(Node<T> parent) 
     : this() 
    { 

     this.parent = parent; 
     parent.addChildren(this); 
    } 


    protected void addChildren(Node<T> child) 
    { 
     children.Add(child); 
    } 
    public Node<T> getRoot() // returns root node 
    public List<Node<T>> flatten() // return 1d-list of all nodes. 

} 
+0

Le type de T peut-il varier pour chaque nœud de l'arborescence? Ou sera-t-il toujours le même dans tout l'arbre? – Soukai

+0

Non (seulement les sous-classes). Mais je voudrais utiliser la même implémentation d'arbre pour un autre T. – James

Répondre

0

Voici une mise en œuvre d'arbre de type sécurisé:

public class Tree<T> : List<Tree<T>> 
{ 
    public T Value { get; set; } 
} 

Oui, voilà. Simple.

Bien sûr, vous pouvez ajouter un ou deux constructeurs, et rendre la propriété Value en lecture seule afin de rendre le tout un peu plus favorable à la POO. Et vous pouvez facilement ajouter la propriété Parent.

+0

Les meilleures idées sont celles qui sont évidentes. :-) – James

0

J'ai l'idée d'utiliser l'arbre classe de base comme commune, mais le type de sécurité puis est parti. Mon approche actuelle est l'utilisation de génériques. Mais il me manque une conversion vers le type de base.

Ensuite, la contrainte du type générique à votre type de base:

public class Node<T> where T: BaseType { ... } 

Maintenant, vous pouvez créer un arbre du type Node<MyDerivedType> tant que MyDerivedType dérive de BaseType.

D'un côté non, j'envisager de modifier les éléments suivants dans votre implémentation:

  1. Children devrait être une propriété, ne pas exposer un champ à moins que son lecture seule. En outre, vous ne devez pas l'exposer comme List; cela permettrait à n'importe qui d'ajouter ou de supprimer directement des nœuds qui peuvent violer les invariants supposés dans votre implémentation. Retour un IEnumerable<T> à la place:

    private readonly List<T> children; 
    public IEnumerable<T> Children => children.Select(c => c); 
    

    Vous pouvez retourner children directement son convertible en IEnumerable<T> implicitement; le problème est que n'importe qui peut simplement le renvoyer à List<T> et le modifier. Projeter cela vous protège de cette conversion.

  2. La même chose se produit avec Flatten (le premier f doit être en majuscule btw). Envisagez de renvoyer un IEnumerable<T> aussi.