Как лучше всего преобразовать объект Address в строку?

StackOverflow https://stackoverflow.com/questions/600967

  •  03-07-2019
  •  | 
  •  

Вопрос

У меня есть объект Address со свойствами AddressLine1, AddressLine2, Suburb, State, ZipCode.(есть еще, но для примера достаточно).Кроме того, каждое из этих свойств является строкой.И я использую С# 3.0.

Я хочу представить это как строку, но при этом обнаруживаю, что создаю метод с высокой цикломатической сложностью из-за всех операторов if...

Предполагая, что строка, назначенная каждому свойству, совпадает с именем свойства (т.е. AddressLine1 = «AddressLine1»)... Я хочу, чтобы адрес был представлен следующим образом:

«Почтовый индекс пригородного штата AddressLine1 AddressLine2».

Первоначально я это сделал с помощью простого метода String.Format().

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

Все это было хорошо, пока я не обнаружил, что некоторые из этих полей могут быть пустыми... в частности, AddressLine2.В результате появляются дополнительные ненужные пробелы... которые особенно раздражают, когда их несколько подряд.

Чтобы обойти эту проблему и единственное решение, которое я могу придумать, мне пришлось создать строку вручную и добавлять в нее свойства адреса только в том случае, если они не равны нулю или пусты.

т.е.

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

Есть ли более элегантный и/или краткий способ добиться этого, о котором я не думаю?Мое решение просто чувствует беспорядочно и раздуто... но я не могу придумать лучшего способа сделать это...

Насколько я знаю, это мой единственный вариант, учитывая то, что я хочу сделать... но я просто подумал, что выложу это, чтобы посмотреть, знает ли кто-нибудь с большим опытом, чем я, лучший способ.Если нет лучшего варианта, то да ладно... но если есть, то я научусь чему-то, чего не знал раньше.

Заранее спасибо!

Это было полезно?

Решение

Возможно, это не самый эффективный способ, но он краток.Вы можете поместить нужные элементы в массив и отфильтровать те, которые не имеют существенного значения, а затем объединить их.

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

Вероятно, более эффективным, но несколько более трудным для чтения было бы объединение значений в StringBuilder, например

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

Я бы, вероятно, склонился к чему-то вроде первой реализации, поскольку это гораздо более простой и удобный в обслуживании код, а затем, если производительность является проблемой, рассмотрите что-то более похожее на вторую (если она окажется быстрее...).

(Обратите внимание, что для этого требуется C# 3.0, но вы не указываете свою языковую версию, поэтому я предполагаю, что это нормально).

Другие советы

При объединении строк я рекомендую использовать класс StringBuilder.Причина этого в том, что System.String является неизменяемым, поэтому каждое изменение, которое вы вносите в строку, просто возвращает новую строку.

Если вы хотите представить объект в виде текста, возможно, было бы неплохо переопределить метод ToString() и поместить туда свою реализацию.

И последнее, но не менее важное: с помощью Linq в C# 3.5 вы можете объединить их вместе, как это только что сделал Грег Бич, но вместо использования string.Join() используйте:

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

Надеюсь это поможет.

Я бы рекомендовал переопределить метод ToString и использовать реализацию IFormatProvider, которая определяет ваши пользовательские типы.

См. MSDN на http://msdn.microsoft.com/en-us/library/system.iformatprovider.aspx для получения информации о реализации IFormatProvider.

Затем вы можете написать такой код:
адрес.ToString("s");// короткий адрес
адрес.ToString("что угодно");// любой пользовательский формат, который вы определите.

Определенно не самый простой способ сделать это, но, ИМХО, самый чистый.Примером такой реализации является класс DateTime.

Ваше здоровье
Пепел

Во-первых, для адреса требуется определенная информация, поэтому не следует разрешать адрес, не имеющий, скажем, почтового индекса.Вы также можете убедиться, что они никогда не равны нулю, инициализируя каждое свойство пустой строкой или требуя каждое свойство в качестве аргументов конструктора.Таким образом, вы будете знать, что уже имеете дело с действительными данными, поэтому можете просто вывести отформатированную строку без необходимости проверок IsNullOrEmpty.

У меня возникла аналогичная проблема при создании многострочной сводки контактов, которая потенциально могла содержать несколько пустых полей.Я сделал почти то же самое, что и вы, за исключением того, что я использовал построитель строк, чтобы не объединять строки снова и снова.

Если ваши данные не совсем надежны, вам нужно будет где-то иметь эту логику - я бы предложил вам создать еще одно свойство, доступное только для чтения (назовите его как-то вроде FormattedAddress), которое выполняет эту логику за вас.Таким образом, вам не придется менять какой-либо код, если в какой-то момент вы его очистите или иным образом измените правила.

И +1 за предложение использовать построитель строк вместо объединения строк.

Я знаю, что это действительно устарело, но я почувствовал общее решение и реализовал свое следующим образом:

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();
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top