Pergunta

Eu tenho um objeto de endereço que possui propriedades de endereço1, linha de endereço2, subúrbio, estado, zipcode. (Há mais, mas isso é suficiente para o exemplo). Além disso, cada uma dessas propriedades são cordas. E estou usando C# 3.0.

Estou querendo representá-lo como uma corda, mas como estou fazendo, estou descobrindo que estou criando um método com uma alta complexidade ciclomática devido a todas as estradas IF ...

Supondo que a string atribuída a cada propriedade seja a mesma que o nome da propriedade (ou seja, endereço1 = "endereço1") ... quero que o endereço seja representado da seguinte forma:

"EndereçoLine1 EndereçoLine2 Suburb State ZipCode".

Agora, a maneira que eu fiz isso foi por uma string.Format () () () ()

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

Tudo isso é bom até que eu descobrisse que alguns desses campos podem estar vazios ... em particular o endereço2. O resultado são espaços desnecessários adicionais ... que são particularmente irritantes quando você recebe vários seguidos.

Para contornar esse problema, e a única solução em que consigo pensar, tive que construir a string manualmente e adicionar apenas as propriedades do endereço à string se elas não forem nulas ou vazias.

ou seja

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 uma maneira mais elegante e/ou concisa de conseguir isso em que não estou pensando? Minha solução apenas sentimentos bagunçado e inchado ... mas não consigo pensar em uma maneira melhor de fazê -lo ...

Pelo que sei, essa é a minha única opção, dado o que quero fazer ... mas pensei em jogar isso lá fora para ver se alguém com mais experiência do que eu conhece de uma maneira melhor. Se não houver opção melhor, então, bem ... mas, se houver, vou aprender algo que não conhecia antes.

Desde já, obrigado!

Foi útil?

Solução

Esta possivelmente não é a maneira mais eficiente, mas é concisa. Você pode colocar os itens que deseja em uma matriz e filtrar os sem um valor significativo e junte -se a eles.

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

Provavelmente mais eficiente, mas um pouco mais difícil de ler, seria agregar os valores em um StringBuilder, por exemplo

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

Eu provavelmente me inclinaria para algo como a primeira implementação, pois é um código muito mais simples e sustentável e, se o desempenho for um problema, considere algo mais parecido com o segundo (se for mais rápido ...).

(Observe que isso requer C# 3.0, mas você não menciona a versão do seu idioma, então estou assumindo que tudo bem).

Outras dicas

Ao montar strings, recomendo que você use a classe StringBuilder. A razão para isso é que um sistema.String é imutável; portanto, todas as alterações que você faz em uma string simplesmente retorna uma nova string.

Se você deseja representar um objeto no texto, pode ser uma boa idéia substituir o método ToString () e colocar sua implementação lá.

Por último, mas não menos importante, com o LINQ no C# 3.5, você pode unir aqueles como Greg Beech acabou de fazer aqui, mas em vez de usar String.Join () Use:

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

Espero que isto ajude.

Eu recomendaria substituir o método do toque e fazer uma implementação do IFORMATPROVER que define seus tipos personalizados.

Veja MSDN em http://msdn.microsoft.com/en-us/library/system.iformatProvider.aspx Para obter informações sobre a implementação do IFORMATPROVER.

Você pode então codificar como este:
endereço.toString ("S"); // Endereço curto
endereço.ToString ("qualquer coisa"); // Qualquer formato personalizado que você definir.

Definitivamente não é a maneira mais fácil de fazê -lo, mas o IMHO mais limpo. Um exemplo dessa implementação é a classe DateTime.

Felicidades
Cinza

Primeiro, um endereço requer certas informações; portanto, você não deve permitir um endereço que não tenha, digamos, um código postal. Você também pode garantir que eles nunca sejam nulos, inicializando cada propriedade em uma string vazia ou exigindo cada propriedade como argumentos ao construtor. Dessa forma, você sabe que já está lidando com dados válidos, para que você possa apenas emitir uma string formatada sem necessidade de verificações IsNullorEmpty.

Eu tive um problema semelhante na construção de um resumo de contato com várias linhas que poderia ter potencialmente vários campos vazios. Eu praticamente fiz a mesma coisa que você fez, exceto que usei um construtor de cordas para não continuar concatenando com uma corda repetidamente.

Se seus dados não forem completamente confiáveis, você precisará ter essa lógica em algum lugar - eu sugiro que você crie outra propriedade somente leitura (chame de algo como o formatteddress) que faz essa lógica para você. Dessa forma, você não precisa alterar nenhum código, em algum momento, você limpa ou altera as regras.

E +1 para a sugestão usar um StringBuilder, em oposição a sequências concatenadoras.

Eu sei que isso é muito antigo, mas senti uma solução geral e implementei a minha desta maneira:

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 em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top