Pregunta

Tengo un objeto de dirección que tiene las propiedades AddressLine1, AddressLine2, Suburb, State, ZipCode. (hay más pero esto es suficiente para el ejemplo). Además, cada una de estas propiedades son cadenas. Y estoy usando C # 3.0.

Quiero representarlo como una cadena, pero al hacerlo estoy descubriendo que estoy creando un método con una alta complejidad ciclomática debido a todas las declaraciones if ...

Suponiendo que la cadena asignada a cada propiedad es el mismo que el nombre de la propiedad (es decir, AddressLine1 = " AddressLine1 ") ... Quiero que la dirección se represente de la siguiente manera:

" AddressLine1 AddressLine2 Suburb State ZipCode " ;.

Ahora, la forma original en que lo hice fue mediante un simple String.Format ()

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

Todo esto está muy bien hasta que he encontrado que algunos de estos campos pueden estar vacíos ... en particular AddressLine2. El resultado son espacios adicionales innecesarios ... que son particularmente molestos cuando obtienes varios seguidos.

Para solucionar este problema, y ??la única solución que se me ocurre, tuve que crear la cadena manualmente y solo agregar las propiedades de la dirección a la cadena si no son nulas o están vacías.

es decir

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

¿Hay una manera más elegante y / o concisa de lograr esto en la que no estoy pensando? Mi solución simplemente se siente sucia e hinchada ... pero no puedo pensar en una mejor manera de hacerlo ...

Por lo que sé, esta es mi única opción, dado lo que quiero hacer ... pero pensé que lo tiraría por ahí para ver si alguien con más experiencia que yo sabe de una mejor manera. Si no hay una mejor opción, entonces bueno ... pero si la hay, aprenderé algo que no sabía antes.

Gracias de antemano!

¿Fue útil?

Solución

Posiblemente esta no sea la forma más eficiente, pero es concisa. Puede colocar los elementos que desea en una matriz y filtrar los que no tienen un valor significativo, luego unirse a ellos.

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

Probablemente, más eficiente, pero algo más difícil de leer, sería agregar los valores en un StringBuilder , por ejemplo

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

Probablemente me inclino por algo como la primera implementación, ya que es un código mucho más simple y más fácil de mantener, y luego, si el rendimiento es un problema, considere algo más parecido a la segunda (si resulta que es más rápido ... ).

(Ten en cuenta que esto requiere C # 3.0, pero no mencionas la versión de tu idioma, así que supongo que está bien).

Otros consejos

Al poner cadenas juntas, te recomiendo que uses la clase StringBuilder. La razón de esto es que un System.String es inmutable, por lo que cada cambio que realice en una cadena simplemente devuelve una nueva cadena.

Si desea representar un objeto en un texto, puede ser una buena idea anular el método ToString () y colocar su implementación allí.

Por último, pero no menos importante, con Linq en C # 3.5 puede unirlos como Greg Beech acaba de hacer aquí, pero en lugar de usar string.Join () use:

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

Espero que esto ayude.

Recomendaría anular el método ToString y tomar una implementación IFormatProvider que defina sus tipos personalizados.

Consulte MSDN en http://msdn.microsoft.com/ en-us / library / system.iformatprovider.aspx para obtener información sobre la implementación de IFormatProvider.

Entonces podrías codificar como este:
address.ToString (" s "); // dirección corta
address.ToString (" lo que sea "); // cualquier formato personalizado que defina.

Definitivamente no es la forma más fácil de hacerlo, sino la IMHO más limpia. Un ejemplo de dicha implementación es la clase DateTime.

Saludos
Ceniza

Primero, una dirección requiere cierta información, por lo que no debe permitir una dirección que no tenga, por ejemplo, un código postal. También puede asegurarse de que nunca sean nulos inicializando cada propiedad a una cadena vacía, o solicitando cada propiedad como argumentos al constructor. De esta manera, usted sabe que ya está tratando con datos válidos, por lo que solo puede generar una cadena formateada sin necesidad de las verificaciones de IsNullOrEmpty.

Tuve un problema similar al crear un resumen de contacto de varias líneas que podría haber tenido varios campos vacíos. Prácticamente hice lo mismo que tú, excepto que usé un generador de cadenas para no concatenar una cadena una y otra vez.

Si sus datos no son completamente confiables, tendrá que tener esa lógica en algún lugar. Le sugiero que cree otra propiedad de solo lectura (llámela como FormattedAddress) que haga esa lógica por usted. De esa manera, no tiene que cambiar ninguno de los códigos, en algún momento, usted limpia o cambia las reglas.

Y +1 para la sugerencia de usar un constructor de cadenas, en lugar de concatenar cadenas.

Sé que esto es realmente viejo, pero sentí una solución general y la implementé de esta manera:

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();
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top