Domanda

Ho un oggetto Address con proprietà AddressLine1, AddressLine2, Suburb, State, ZipCode. (ce ne sono altri ma questo è sufficiente per l'esempio). Inoltre, ognuna di queste proprietà sono stringhe. E sto usando C # 3.0.

Voglio rappresentarlo come una stringa ma, mentre lo sto facendo, sto scoprendo che sto creando un metodo con un'elevata complessità ciclomatica a causa di tutte le dichiarazioni if ??...

Supponendo che la stringa assegnata a ciascuna proprietà corrisponda al nome della proprietà (ovvero AddressLine1 = " AddressLine1 ") ... Voglio che l'indirizzo sia rappresentato come segue:

" AddressLine1 AddressLine2 Codice postale stato sobborgo " ;.

Ora, il modo originale in cui l'avevo fatto era un semplice String.Format ()

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

Va ??tutto bene finché non ho scoperto che alcuni di questi campi possono essere vuoti ... in particolare AddressLine2. Il risultato sono ulteriori spazi non necessari ... che sono particolarmente fastidiosi quando ne ottieni diversi di fila.

Per aggirare questo problema e l'unica soluzione che mi viene in mente, ho dovuto costruire la stringa manualmente e aggiungere le proprietà dell'indirizzo alla stringa solo se non sono nulle o vuote.

es

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....

Esiste un modo più elegante e / o conciso per raggiungere questo obiettivo a cui non sto pensando? La mia soluzione sembra disordinata e gonfia ... ma non riesco a pensare a un modo migliore per farlo ...

Per quanto ne so, questa è la mia unica opzione dato quello che voglio fare ... ma ho pensato di buttarlo lì fuori per vedere se qualcuno con più esperienza di me sa di un modo migliore. Se non esiste un'opzione migliore, vabbè ... ma se c'è, imparerò qualcosa che non sapevo prima.

Grazie in anticipo!

È stato utile?

Soluzione

Questo forse non è il modo più efficiente, ma è conciso. È possibile inserire gli elementi desiderati in un array e filtrare quelli senza un valore significativo, quindi unirli.

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

Probabilmente più efficiente, ma un po 'più difficile da leggere, sarebbe aggregare i valori in un StringBuilder , ad es.

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);

Probabilmente mi spingerei verso qualcosa di simile alla prima implementazione in quanto è un codice molto più semplice e più gestibile, e quindi se le prestazioni sono un problema, considera qualcosa di più simile alla seconda (se si rivela essere più veloce ... ).

(Nota che questo richiede C # 3.0, ma non menzioni la versione della tua lingua, quindi presumo che sia OK).

Altri suggerimenti

Quando metti insieme le stringhe ti consiglio di usare la classe StringBuilder. Il motivo è che System.String è immutabile, quindi ogni modifica apportata a una stringa restituisce semplicemente una nuova stringa.

Se vuoi rappresentare un oggetto nel testo, potrebbe essere una buona idea sovrascrivere il metodo ToString () e inserire la tua implementazione.

Ultimo ma non meno importante, con Linq in C # 3.5 puoi unirti a quelli come ha fatto Greg Beech qui, ma invece di usare string.Join () usa:

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

Spero che questo aiuti.

Consiglio di sostituire il metodo ToString e di prendere un'implementazione di IFormatProvider che definisce i tipi personalizzati.

Vedi MSDN su http://msdn.microsoft.com/ en-us / library / system.iformatprovider.aspx per informazioni sull'implementazione di IFormatProvider.

È quindi possibile codificare in questo modo:
address.ToString (" s "); // indirizzo breve
address.ToString (" qualsiasi "); // qualunque formato personalizzato tu definisca.

Sicuramente non è il modo più semplice per farlo, ma l'IMHO più pulito. Un esempio di tale implementazione è la classe DateTime.

Saluti
Ash

Innanzitutto, un indirizzo richiede determinate informazioni, quindi non dovresti consentire un indirizzo che non abbia, per esempio, un codice postale. Puoi anche assicurarti che non siano mai nulli inizializzando ciascuna proprietà su una stringa vuota o richiedendo ogni proprietà come argomento per il costruttore. In questo modo sai che hai già a che fare con dati validi, quindi puoi semplicemente generare una stringa formattata senza la necessità dei controlli IsNullOrEmpty.

Ho avuto un problema simile durante la creazione di un riepilogo dei contatti multilinea che avrebbe potuto potenzialmente avere diversi campi vuoti. Ho praticamente fatto la stessa cosa che hai fatto tu, tranne per il fatto che ho usato un generatore di stringhe per non continuare a concatenare una stringa più e più volte.

Se i tuoi dati non sono completamente affidabili, dovrai avere quella logica da qualche parte - ti suggerirei di creare un'altra proprietà di sola lettura (chiamandola come FormattedAddress) che fa quella logica per te. In questo modo, non è necessario modificare alcun codice, ad un certo punto, ripulire o modificare in altro modo le regole.

E +1 per il suggerimento di usare un stringbuilder, invece di concatenare stringhe.

So che è davvero vecchio, ma ho percepito una soluzione generale e ho implementato la mia in questo modo:

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();
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top