Каков наилучший способ преобразования объекта Address в строку? - PullRequest
1 голос
/ 02 марта 2009

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

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

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

"Адрес Line1 Адрес AddressLine2 ZipCode в пригороде".

Теперь, оригинальный способ, которым я это сделал, был простым 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....

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

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

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

Ответы [ 7 ]

3 голосов
/ 02 марта 2009

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

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, но вы не упоминаете свою языковую версию, поэтому я предполагаю, что все в порядке).

1 голос
/ 02 марта 2009

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

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

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

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

Приветствие
Ash

1 голос
/ 02 марта 2009

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

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

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

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

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

0 голосов
/ 12 марта 2019

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

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();
}
0 голосов
/ 02 марта 2009

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

И +1 за предложение использовать строитель строк, а не конкатенацию строк.

0 голосов
/ 02 марта 2009

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

0 голосов
/ 02 марта 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...