2
\$\begingroup\$

The objective is to implement the reversed version of StringToDoubleConverter but without writing too many redundancies. I love DRY (Don't Repeat Yourself) design principle.

public class StringToDoubleConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return double.TryParse(value as string, out var x) ? x : double.NaN;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value is double x ? x.ToString("f3") : string.Empty;
    }
}

Here are my approaches. Any suggestions or comments are welcome.

Version A: Inheritance

public class DoubleToStringConverter : StringToDoubleConverter, IValueConverter
{
    public new object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return base.ConvertBack(value, targetType, parameter, culture);
    }
    public new object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return base.Convert(value, targetType, parameter, culture);
    }
}

Version B: Composition

public class DoubleToStringConverter : IValueConverter
{
    private static readonly StringToDoubleConverter std = new();

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return std.ConvertBack(value, targetType, parameter, culture);
    }
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return std.Convert(value, targetType, parameter, culture);
    }
}
\$\endgroup\$
5
  • \$\begingroup\$ I just realized. I should choose the version B and make all classes sealed. \$\endgroup\$
    – D G
    Commented Nov 19, 2022 at 22:44
  • \$\begingroup\$ what is the IValueConverter definition? \$\endgroup\$
    – radarbob
    Commented Nov 20, 2022 at 0:07
  • \$\begingroup\$ Are you using this IValueConverter interface: learn.microsoft.com/en-us/dotnet/api/… ? \$\endgroup\$ Commented Nov 20, 2022 at 6:34
  • 1
    \$\begingroup\$ Btw why do you need two classes? Isn't your first class enough? \$\endgroup\$ Commented Nov 20, 2022 at 6:36
  • \$\begingroup\$ @PeterCsala IValueConverter is in your link. Two classes are needed for two different usages. \$\endgroup\$
    – D G
    Commented Nov 20, 2022 at 6:41

1 Answer 1

1
\$\begingroup\$

Why don't you define an abstract class with the following two methods:

  • One which can convert an object to string
  • Another which can convert an object to double
public abstract class FromObjectConverter
{
    protected double ToDouble(object value)
        => double.TryParse(value as string, out var x) ? x : double.NaN;

    protected string ToString(object value)
        => value is double x ? x.ToString("f3") : string.Empty;
}

With this class in our hand the two concrete converter classes are just simple wrappers

public sealed class StringToDoubleConverter : FromObjectConverter, IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        => ToDouble(value);

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        => ToString(value);
}

public sealed class DoubleToStringConverter : FromObjectConverter, IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        => ToString(value);

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        => ToDouble(value);
}

Or if you want to avoid inheritance then define the FromObjectConverter class and its methods as static.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.