2 votes

Besoin de référence à l'objet pour la classe CTOR (avant que l'objet ne soit construit)

Voir le signe ? pour la question.

public class Person 
{
    public Int16 ID { get; private set; }
    public string Name { get; private set; }
    public List<Toy> Toys { get; private set; }
    public Person(Int16 id, string name, List<Toy> toys)
    { ID = id; Name = name; Toys = toys; } 
}
public class Toy
{
    public string Name { get; private set; }
    public Person Owner { get; private set; }
    public Toy(Person owner, string name)  
    { Owner = owner; Name = name; }
}

Le problème se situe au niveau du CTOR de la personne. Comment passer les jouets au cteur de la personne ? Le jouet a besoin d'un propriétaire dans le CTOR du jouet mais ce propriétaire n'a pas encore été construit.

Je comprends que je peux déplacer les jouets hors du CTOR de la personne et rendre le jeu public. Supposons que vous n'ayez que les jouets avec lesquels vous êtes né - le jeu privé a une utilité. Et je comprends que ce que je demande peut ne pas être possible.

Comme si quelqu'un s'en souciait vraiment, mais Toy n'a besoin de connaître que le nom de son propriétaire, je vais donc modifier Toys.

  public class Toy
  {
     private Person owner;
     private string ownerName;

     public string Name { get; private set; }
     public String OwnerName 
     { 
        get
        {
           if (!string.IsnullOrEmpty(ownerName)) return ownerName;
           elseif (owner != null) return owner.Name;
           else throw new exception("homelesstoy");
     }
     public Toy( string name, Person owner)  
     { 
         Name = name; Owner = owner;
         // new toy need to write it to DB 
     }
     public Toy( string name, string _ownerName)  
     { 
         Name = name; ownerName = _ownerName;
     }
  } 

D'une certaine manière, c'est mieux. Si mon jouet est dans ma voiture et qu'ils ont mes clés, je ne veux pas qu'ils connaissent mon adresse. Avec mon nom, la police peut me trouver si la voiture est retrouvée.

2voto

Jim Schubert Points 10234

Pourquoi le setter sur Owner privé ? Je peux comprendre votre point de vue sur le setter sur Toys en el Person classe.

Si vous supprimez cette contrainte, vous pouvez créer un backing store (propriété complète) et ensuite boucler la liste des jouets dans le fichier Person et faire item.Owner = this .

public class Toy
{
    private Person _owner = null;
    public string Name { get; private set; }
    public Person Owner { 
         get { return _owner; }; 
         set {
              if(_owner != null) throw new InvalidOperationException("No Stealing");
              _owner = value;
         }
    }
    public Toy(Person owner, string name)  
    { Owner = owner; Name = name; }
}

Cela vous permettrait de définir Owner seulement une fois et les appels ultérieurs au setter seraient exceptionnels. Vous n'auriez pas besoin de modifier le constructeur, car vous pourriez toujours le faire :

Toy batman = new Toy(null, "Bruce");

L'un des problèmes que je vois est que cette relation entre le jouet et le propriétaire ne correspond pas au monde réel. Les enfants sont naissent parfois avec une foule de jouets à leur disposition, mais les jouets ne sont presque jamais fabriqués avec un propriétaire immédiat. Même après avoir été créé et donné à quelqu'un, un jouet peut être donné à quelqu'un d'autre.

Je pense que les détails conceptuels vous font perdre votre logique.

éditer : j'ai oublié le constructeur...

public Person(Int16 id, string name, List<Toy> toys)
{ 
    id = ID; 
    Name = name; 

    foreach(Toy item in toys) {
        item.Owner = this;
    }

    Toys = toys; 
}

2voto

Timwi Points 30896

Il y a deux possibilités auxquelles je peux penser :

  • Si vous souhaitez conserver les classes telles qu'elles sont actuellement, vous pouvez créer une personne avec une liste vide de jouets et ajouter les jouets par la suite, par exemple :

    var newPerson = new Person(id, name, new List<Toy>());
    var newToy = new Toy(newPerson, toyName);
    newPerson.Toys.Add(newToy);
  • Si vous souhaitez que la liste soit immuable après sa création, vous devez la déclarer en tant qu'objet de type ReadOnlyCollection<Toy> à la place. Dans cette situation, je recommande d'avoir une méthode statique qui crée le tout en une seule opération :

    public class Person 
    {
        public Int16 ID { get; private set; }
        public string Name { get; private set; }
        public ReadOnlyCollection<Toy> Toys { get; private set; }
        public Person(Int16 id, string name, List<Toy> toys)
        { ID = id; Name = name; Toys = toys; } 
    
        public static Person CreateWithToys(Int16 id, string name,
            IEnumerable<string> toyNames) // or could use “params string[]”, too
        {
            var person = new Person(id, name, null);
            var toys = new ReadOnlyCollection<Toy>(
                toyNames.Select(toyName => new Toy(person, toyName)).ToList());
            person.Toys = toys;
        }
    }
    
    [...]
    
    var jimmy = Person.CreateWithToys(47, "Jimmy",
        new[] { "Rattle", "Batman costume", "Nuclear missile" });
    
    // or, if you used “params string[]” above,
    var jimmy = Person.CreateWithToys(47, "Jimmy",
        "Rattle", "Batman costume", "Nuclear missile");

    Dans des cas plus complexes, il se peut que vous deviez faire en sorte que certains des setters interne au lieu de privé afin qu'une telle méthode statique puisse accéder à ce à quoi elle doit accéder.

1voto

Welton v3.54 Points 999

Vous pourriez passer une instance de personne au constructeur de jouets et faire en sorte que le nouveau jouet s'ajoute à la collection de jouets de la personne, au lieu de passer la collection de jouets au constructeur de la personne.

1voto

daryal Points 8211

Essayez de créer un nouveau constructeur Toy et de changer le setter Person de Toy en public ;

public class Toy
{
    public Person Owner { get; set; }
    public Toy(string toyName);
}

public class Person
{
    Int16 id;
    string name;
    List<Toy> toys;
    public Person(Int16 id, string name, List<Toy> toys)
    { 
        this.id = id;
        this.name = name;
        this.toys = new List<Toy>();
        this.AddToys(toys);

    }

    private void AddToys(List<Toy> toys)
    {
        foreach (var toy in toys)
        {
            this.toys.Add(toy);
            toy.Owner = this;
        }
    }
}

0voto

SliverNinja Points 15924

Vous ne pouvez pas savoir Toy propriétaire si vous n'avez pas encore créé le propriétaire. Vous devez faire Owner un setter public et changer le Toy CTOR.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X