Question

J'ai un objet Address qui a les propriétés AddressLine1, AddressLine2, Suburb, State, ZipCode. (il y en a plus mais cela suffit pour l'exemple). De plus, chacune de ces propriétés est une chaîne. Et j'utilise C # 3.0.

Je veux le représenter sous forme de chaîne, mais je constate que je crée une méthode avec une complexité cyclomatique élevée en raison de toutes les déclarations if ...

En supposant que la chaîne affectée à chaque propriété est identique au nom de la propriété (par exemple, AddressLine1 = "quotLe AddressLine1") ... Je veux que l'adresse soit représentée comme suit:

"AddressLine1 AddressLine2 Code postal d'état de banlieue".

Maintenant, la méthode originale que j'ai utilisée était un simple String.Format ()

String.Format("{0} {1} {2} {3} {4}", address.AddressLine1, 
address.AddressLine2, address.Suburb, address.State, address.ZipCode);

C’est très bien jusqu’à ce que j’ai constaté que certains de ces champs peuvent être vides ... en particulier AddressLine2. Il en résulte des espaces inutiles ... qui sont particulièrement gênants lorsque vous en avez plusieurs à la suite.

Pour contourner ce problème et la seule solution à laquelle je puisse penser, il a fallu que je construise la chaîne manuellement et que je n’ajoute les propriétés de l’adresse à la chaîne que si elles ne sont ni vides ni vides.

c'est-à-dire

string addressAsString = String.Empty;

if (!String.IsNullOrEmpty(address.AddressLine1))
{
    addressAsString += String.Format("{0}", address.AddressLine1);
}

if(!String.IsNullOrEmpty(address.AddressLine2))
{
    addressAsString += String.Format(" {0}", address.AddressLine2);
}

etc....

Existe-t-il un moyen plus élégant et / ou plus concis d’atteindre cet objectif auquel je ne pense pas? Ma solution est simplement perçue en désordre et gonflée ... mais je ne vois pas de meilleure façon de le faire ...

Pour autant que je sache, c’est ma seule option compte tenu de ce que je veux faire ... mais j’avais juste pensé que jetterais ça ici pour voir si une personne plus expérimentée que moi connaissait une meilleure solution. S'il n'y a pas de meilleure option, mais bon ... mais s'il y en a une, je vais apprendre quelque chose que je ne savais pas auparavant.

Merci d'avance!

Était-ce utile?

La solution

Ce n'est peut-être pas le moyen le plus efficace, mais c'est concis. Vous pouvez placer les éléments de votre choix dans un tableau et filtrer ceux qui ne contiennent pas de valeur significative, puis les joindre.

var items = new[] { line1, line2, suburb, state, ... };
var values = items.Where(s => !string.IsNullOrEmpty(s));
var addr = string.Join(" ", values.ToArray());

Probablement plus efficace, mais un peu plus difficile à lire, consisterait à agréger les valeurs dans un StringBuilder , par exemple

.
var items = new[] { line1, line2, suburb, state, ... };
var values = items.Where(s => !string.IsNullOrEmpty(s));
var builder = new StringBuilder(128);
values.Aggregate(builder, (b, s) => b.Append(s).Append(" "));
var addr = builder.ToString(0, builder.Length - 1);

Je m'approcherais probablement de quelque chose comme la première mise en œuvre car il s'agit d'un code beaucoup plus simple et plus facile à maintenir, puis si la performance pose problème, envisagez quelque chose de plus semblable à la deuxième (si cela s'avère plus rapide ... ).

(Notez que cela nécessite C # 3.0, mais vous ne mentionnez pas votre version linguistique, donc je suppose que c'est OK).

Autres conseils

Lorsque vous assemblez des chaînes, je vous recommande d'utiliser la classe StringBuilder. La raison en est qu'un System.String est immuable, donc chaque modification apportée à une chaîne renvoie simplement une nouvelle chaîne.

Si vous souhaitez représenter un objet dans du texte, il peut être judicieux de remplacer la méthode ToString () et de mettre votre implémentation ici.

Dernier point, mais non le moindre, avec Linq en C # 3.5, vous pouvez les associer comme Greg Beech l’a fait ici, mais au lieu d’utiliser string.Join (), utilisez:

StringBuilder sb = new StringBuilder();
foreach (var item in values) {
  sb.Append(item);
  sb.Append(" ");
}

J'espère que cela vous aidera.

Je recommanderais de remplacer la méthode ToString et de prendre une implémentation IFormatProvider qui définit vos types personnalisés.

Voir MSDN à l'adresse http://msdn.microsoft.com/. en-us / library / system.iformatprovider.aspx pour plus d'informations sur la mise en œuvre d'IFormatProvider.

Vous pouvez alors coder comme ceci:
address.ToString ("s"); // adresse courte
address.ToString ("quel que soit"); // quel que soit le format personnalisé que vous définissez.

Ce n'est certainement pas la façon la plus simple de le faire, mais le plus propre IMHO. La classe DateTime est un exemple de cette implémentation.

A bientôt
Cendres

Premièrement, une adresse nécessite certaines informations. Vous ne devez donc pas autoriser une adresse qui n'a pas, par exemple, de code postal. Vous pouvez également vous assurer qu'ils ne sont jamais nuls en initialisant chaque propriété par une chaîne vide ou en exigeant que chaque propriété soit un argument du constructeur. De cette façon, vous savez que vous traitez déjà avec des données valides, vous pouvez donc simplement sortir une chaîne formatée sans avoir besoin des contrôles IsNullOrEmpty.

J'ai eu un problème similaire lors de la création d'un résumé de contact sur plusieurs lignes pouvant potentiellement contenir plusieurs champs vides. J'ai à peu près fait la même chose que vous, sauf que j'ai utilisé un constructeur de chaînes pour ne pas continuer à concaténer une chaîne encore et encore.

Si vos données ne sont pas complètement fiables, vous aurez besoin de cette logique quelque part. Je vous suggérerais de créer une autre propriété en lecture seule (appelez-la sous la forme FormattedAddress) qui effectue cette logique pour vous. De cette façon, vous ne devez modifier aucun code, vous nettoyez ou changez les règles.

Et +1 pour la suggestion d'utiliser un constructeur de chaînes, par opposition à la concaténation de chaînes.

Je sais que c’est vraiment vieux, mais j’ai senti une solution générale et mis en œuvre la mienne de cette façon:

private static string GetFormattedAddress(
    string address1,
    string address2,
    string city,
    string state,
    string zip)
{
    var addressItems =
        new []
        {
            new[] { address1, "\n" },
            new[] { address2, "\n" },
            new[] { city, ", " },
            new[] { state, " " },
            new[] { zip, null }
        };

    string suffix = null;
    var sb = new StringBuilder(128);

    foreach (var item in addressItems)
    {
        if (!string.IsNullOrWhiteSpace(item[0]))
        {
            // Append the last item's suffix
            sb.Append(suffix);

            // Append the address component
            sb.Append(item[0]);

            // Cache the suffix
            suffix = item[1];
        }
    }

    return sb.ToString();
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top