Question

J'ai un objet Person avec deux constructeurs - l'un prend un int (personId), l'autre une chaîne (logonName).Je voudrais un autre constructeur qui prend une chaîne (badgeNumber).Je sais que cela ne peut pas être fait, mais il semble que ce soit une situation courante.Existe-t-il une manière gracieuse de gérer cela ?Je suppose que cela s'appliquerait à n'importe quelle méthode surchargée.Code:

public class Person
{
    public Person() {}

    public Person(int personId)
    {
        this.Load(personId);
    }

    public Person(string logonName)
    {
        this.Load(logonName);
    }

    public Person(string badgeNumber)
    {
        //load logic here...
    }

...etc.

Était-ce utile?

La solution

Vous pourriez envisager d'utiliser des types personnalisés.

Par exemple, créez les classes LogonName et BadgeNumber.

Ensuite, vos déclarations de fonction ressemblent à...

public Person(LogonName ln)
{
    this.Load(ln.ToString());
}

public Person(BadgeNumber bn)
{
    //load logic here...
}

Une telle solution pourrait vous offrir un bon endroit pour conserver la logique métier qui régit le format et l’utilisation de ces chaînes.

Autres conseils

Vous pourriez peut-être utiliser des méthodes d'usine à la place ?

public static Person fromId(int id) {
    Person p = new Person();
    p.Load(id);
    return p;
}
public static Person fromLogonName(string logonName) {
    Person p = new Person();
    p.Load(logonName);
    return p;
}
public static Person fromBadgeNumber(string badgeNumber) {
    Person p = new Person();
    // load logic
    return p;
}
private Person() {}

Je peux penser à quatre options, dont trois ont déjà été nommées par d'autres :

  1. Suivez la voie de l'usine, comme suggéré par plusieurs autres ici.Un inconvénient est que vous ne pouvez pas avoir de dénomination cohérente via une surcharge (sinon vous auriez le même problème), donc c'est superficiellement moins propre.Un autre inconvénient, plus important, est qu’il exclut la possibilité d’allouer directement sur la pile.Tout sera alloué sur le tas si vous adoptez cette approche.

  2. Wrappers d’objets personnalisés.C'est une bonne approche, et celle que je recommanderais si vous partez de zéro.Si vous avez beaucoup de code utilisant, par exemple, des badges comme chaînes, la réécriture du code peut rendre cette option non viable.

  3. Ajoutez une énumération à la méthode, spécifiant comment traiter la chaîne.Cela fonctionne, mais nécessite que vous réécriviez tous les appels existants pour inclure la nouvelle énumération (bien que vous puissiez fournir une valeur par défaut si vous le souhaitez pour éviter une partie de cela).

  4. Ajoutez un paramètre factice qui n'est pas utilisé pour faire la distinction entre les deux surcharges.par exemple.Virer un bool sur la méthode.Cette approche est adoptée par la bibliothèque standard à quelques endroits, par ex. std::nothrow est un paramètre factice pour operator new.Les inconvénients de cette approche sont qu’elle est moche et qu’elle n’est pas évolutive.

Si vous disposez déjà d'une grande base de code existant, je vous recommande soit d'ajouter l'énumération (éventuellement avec une valeur par défaut), soit d'ajouter le paramètre factice.Ni l’un ni l’autre n’est beau, mais les deux sont assez simples à moderniser.

Si vous partez de zéro ou si vous n'avez qu'une petite quantité de code, je vous recommande les wrappers d'objets personnalisés.

Les méthodes d'usine seraient une option si vous avez du code qui utilise fortement le brut badge/logonName cordes, mais n'utilise pas beaucoup le Person classe.

Si vous utilisez C# 3.0, vous pouvez utiliser Initialiseurs d'objets:

public Person()
{
}

public string Logon { get; set; }
public string Badge { get; set; }

Vous appelleriez le constructeur comme ceci :

var p1 = new Person { Logon = "Steve" };
var p2 = new Person { Badge = "123" };

Non.

Vous pouvez envisager un champ d'indicateur (énumération pour plus de lisibilité), puis demander au constructeur d'utiliser htat pour déterminer ce que vous vouliez dire.

Cela ne marchera pas.Vous pourriez envisager de créer une classe appelée BadgeNumber qui encapsule une chaîne afin d'éviter cette ambiguïté.

Vous ne pouvez pas avoir deux constructeurs/méthodes différents avec la même signature, sinon, comment le compilateur peut-il déterminer quelle méthode exécuter.

Comme Zack a dit, j'envisagerais de créer une classe "options" dans laquelle vous pourriez réellement transmettre les paramètres contenus dans un type personnalisé.Cela signifie que vous pouvez transmettre autant de paramètres que vous le souhaitez et faire ce que vous voulez avec les options, mais faites attention à ne pas créer une méthode monolithique qui essaie de tout faire.

Soit ça, soit votez pour le modèle d'usine..

Vous pouvez utiliser une méthode de fabrique statique :

public static Person fromLogon(String logon) { return new Person(logon, null); }
public static Person fromBadge(String badge) { return new Person(null, badge); }

Comme cela a été suggéré, les types personnalisés sont la voie à suivre dans ce cas.

La seule chose à laquelle je peux penser pour gérer ce que vous voulez faire est d'avoir des paramètres, un qui décrit le type de paramètre (une énumération avec LogonName, BadgeNumer, etc.) et le second est la valeur du paramètre.

Vous pouvez passer à un modèle de style usine.

public class Person {

  private Person() {}

  public static PersonFromID(int personId)
  {
    Person p = new Person().
    person.Load(personID);

    return p;
    this.Load(personId);
  }

  public static PersonFromID(string name)
  {
    Person p = new Person().
    person.LoadFromName(name);

    return p;
  }

  ...
}

Ou, comme suggéré, utilisez des types personnalisés.Vous pouvez également pirater quelque chose en utilisant des génériques, mais je ne le recommanderais pas pour des raisons de lisibilité.

Que diriez-vous ...

public Person(int personId)
{
    this.Load(personId);
}

public Person(string logonName)
{
    this.Load(logonName);
}

public Person(Object badgeNumber)
{
    //load logic here...
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top