Как правильно заполнять нули с помощью строки.форматирование при использовании динамических форматов?


У меня есть иллюстративный код ниже. Мне нужно, чтобы выход для condition1 был правильно выровнен и дополнен нулями, такими как |1234500000| вместо |0000012345| вместо и с фиксированной шириной 10. Строка формата является условной, то есть может быть одна из многих возможных строк формата в зависимости от некоторых критериев, в то время как есть только одна строка для вывода. Поэтому такие функции, как PadRight и PadLeft, нельзя использовать со значением, если только нет способа использовать их, все еще имея то же самое выходная линия. (.NET 4.5)

Как я могу получить |1234500000|, удовлетворяя этим требованиям?

string format;

if (condition1)
format = "|{0:0000000000}|";
else
if (condition2)
format = "|{0}|";
//more conditions here
Int64 value = 12345;
string a = String.Format(format, value);
a.Dump();
2 2

2 ответа:

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

Func<Int64, String> formatter;
if (condition1) 
{
    formatter = (number) => number.ToString().PadRight(10, '0');
}
else if (condition2) 
{
    formatter = (number) => number.ToString();
}

Int64 sample = 12345;
string output = string.Format("|{0}|", formatter(sample));
output.Dump();

Другим вариантом было бы создание собственных поставщиков пользовательского формата строк путем реализации IFormatProvider и ICustomFormatter. Например, вот небрежный, который будет делать правильную прокладку:

public class RightPaddedStringFormatter : IFormatProvider, ICustomFormatter
{
    private int _width;

    public RightPaddedStringFormatter(int width) 
    {
        if (width < 0)
            throw new ArgumentOutOfRangeException("width");

        _width = width;
    }

    public string Format(string format, object arg, IFormatProvider formatProvider)
    {
        // format doubles to 3 decimal places
        return arg.ToString().PadRight(_width, '0');
    }

    public object GetFormat(Type formatType)
    {
        return (formatType == typeof(ICustomFormatter)) ? this : null;
    }
}

Затем вы можете использовать свои условия для выбора форматера, например:

IFormatProvider provider;
if (condition1)
{
    provider = new RightPaddedStringFormatter(10);
}
...

Int64 sample = 12345;
string output = string.Format(provider, "|{0}|", sample);
output.Dump();

Я скопировал из возможного дубликата выше, и это похоже на ответ Кори. Это позволяет вам нанизывать.Форматирование и накладка с обеих сторон с любым символом, будь то 0 или X, он остается для форматирования.

Написано с помощьюLinqPad .

void Main()
{
    var val = 12345;
    string.Format(new PaddedStringFormatInfo(), "{0:20:0}", val).Dump();
    string.Format(new PaddedStringFormatInfo(), "{0:-20:0}", val).Dump();
}

public sealed class PaddedStringFormatInfo : IFormatProvider, ICustomFormatter
{
    public object GetFormat(Type formatType)
    {
        if (typeof(ICustomFormatter).Equals(formatType)) return this;

        return null;
    }

    public string Format(string format, object arg, IFormatProvider formatProvider)
    {
        if (arg == null) throw new ArgumentNullException("Argument cannot be null");
        if (format == null) return arg.ToString();

        string[] args = format.Split(':');
        if (args.Length == 1) String.Format("{0, " + format + "}", arg);

        int padLength = 0;
        if (!int.TryParse(args[0], out padLength)) throw new ArgumentException("Padding length should be an integer");

        switch (args.Length)
        {
            case 2: // padded format
                if (padLength > 0)  return (arg.ToString()).PadLeft(padLength, args[1][0]);

                return (arg.ToString()).PadRight(padLength * -1, args[1][0]);

            default: // use default string.format
                return string.Format("{0," + format + "}", arg);
        }
    }
}

И выход будет:

00000000000000012345
12345000000000000000