Как преобразовать Rect ToString, ограничивая десятичные разряды?

Есть простой поставщик формата, который будет возвращать структуру Rect ToString и ограничить количество знаков после запятой?

System.Windows.Rect myRect;

Если я использую myRect.ToString(), это возвращает

myRect: 0.0139211136847734,0.109375,0.995359599590302,1

Я хочу это, ограничив число до двух десятичных знаков, но myRect.ToString("D2") не компилируется

 myRect: 0.01,0.10,0.99,1

Примечание: меня не волнует округление, округление или усечение - это нормально.

3 ответа

Решение

Вы можете создать метод расширения:

public static class RectExtensions
{
    public static string ToStringRounded(this System.Windows.Rect rect)
    {
        return string.Format("{0},{1},{2},{3}", 
            Math.Round(rect.X, 2), Math.Round(rect.Y, 2), 
            Math.Round(rect.Width, 2), Math.Round(rect.Height, 2));
    }
}

а затем позвоните myRect.ToStringRounded();

Не забудьте включить пространство имен метода расширения

Одним из возможных решений было бы внедрение собственного провайдера нестандартного формата, чтобы вы могли использовать стандартный ToString метод прямоугольного объекта. Для этого вам нужно определить собственный класс форматера, который реализует интерфейс IFormatProvider и интерфейс ICustomFormatter. Таким образом, вы могли бы реализовать свой собственный ToString("D2") решение. Пример решения пользовательского форматера для ваших нужд может выглядеть следующим образом:

public class CustomRectFormat : IFormatProvider, ICustomFormatter
{
    public object GetFormat(Type formatType)
    {
        if (formatType == typeof(ICustomFormatter))
        {
            return this;
        }
        else
        {
            return null;
        }
    }

    // the custom format
    public string Format(string fmt, object arg, IFormatProvider formatProvider) 
    {
        // the method processes every part of the Rect members
        var chunk = arg.ToString();
        // skip delimiters
        if (chunk != ";")
        {
            // round doubles if possible
            Double part = 0.0;
            if (Double.TryParse(chunk, out part))
            {
                return Math.Round(part, 2).ToString();
            }
        }
        return chunk;
    }
}

Использование со стандартом Rect.ToString метод:

var rect = new Rect();
rect.X = 0.5678;
rect.Width = 1.2345;
Console.WriteLine(rect.ToString(new CustomRectFormat()));

Вывод по желанию:

0,57;0;1,23;0 

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

public class CustomRect
{
    private Rect rect;

    public CustomRect() : this(new Size(0.0, 0.0))
    {
    }

    public CustomRect(Size size)
    {
        rect = new Rect(size);
    }

    public Double Width
    {
        get { return rect.Width; }
        set { rect.Width = value; }
    }

    public Double X
    {
        get { return rect.X; }
        set { rect.X = value; }
    }

    public Double Y
    {
        get { return rect.Y; }
        set { rect.Y = value; }
    }

    public Double Height
    {
        get { return rect.Height; }
        set { rect.Height = value; }
    }

    public String ToString()
    {
        return String.Format("{0};{1};{2};{3}", Math.Round(rect.X, 2), Math.Round(rect.Y, 2), Math.Round(rect.Width, 2), Math.Round(rect.Height));
    }
}

Использование класса:

var rect1 = new CustomRect();
var rect2 = new Rect();
rect1.X = 0.123;
rect1.Width = 3.2342342342342;
rect1.Height = 0.987234876234;
rect2.X = 0.123;
rect2.Width = 3.2342342342342;
rect2.Height = 0.987234876234;
Console.WriteLine(rect1.ToString());
Console.WriteLine(rect2.ToString());

И вывод:

0,12;0;3,23;1
0,123;0;3,2342342342342;0,987234876234

Это решение имеет проблему, заключающуюся в том, что вам нужно везде использовать пользовательский класс, а не предопределенный Rect учебный класс.


Другим хорошим подходом было бы создание (как предложено @Flat Eric) метода расширения, который делает это для всех объектов Rect учебный класс. Недостатком этого подхода является то, что вы не можете использовать ToString метод, когда это необходимо.

Вам нужно решить, какое решение вам больше подходит в этом случае.

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

$"rect={rect:F2}"

Конечно, чем старше String.Format подход будет делать то же самое.

String.Format("{0:F2}", rect);
Другие вопросы по тегам