0

I have a function, that reads the Text from a TextBox and then tries to parse it to a number. If that is possible, it will store the parsed data. If it is not possible, the data is not touched, instead the TextBox.Text will be set to the String-Representation of the variable. As I need it for various TextBoxes and underlying Variables my function looks like this:

public bool ValidateAndParseTextBox(TextBox textBox, ref double storage)
    {
        try
        {
            storage = double.Parse(textBox.Text);
            return true;
        }
        catch (FormatException)
        {
            textBox.Text = storage.ToString();
            return false;
        }
    }

And the same for int

Now I moved the underlying data to a seperate object, and therefore I wanted to use properties instead of just having the variables public. With those however I can't use the ref statement.

If I didn't need the boolean returnvalue, I could just do it like this

public double ValidateAndParseTextBox(TextBox textBox, double Value)
    {
        double ret;
        if (!double.TryParse(textBox.Text, ret))
            return Value;
        return ret;
    }

But I somehow fail to see a solution with the bool value. Any Ideas? What would be nice, if I somehow could send the property setter as delegate to a function, or something like that.

thanks, -m-

2 Answers2

1

To me it looks like this function is trying to do too much. Have a pure function that accepts only the textbox, validates it and returns a bool.

public bool IsTextboxValid(TextBox textBox)
{
    double dummy;
    return double.TryParse(textbox.Text, out dummy);
}

Depending on the result of this function, the caller can decide whether or not to set the property.


Another way to do it would be to return a nullable double, which indicates whether the parse succeeded, as well as what (if anything), the double value is.

public double? ParseTextbox(TextBox textBox)
{
    double ret;
    if(double.TryParse(textbox.Text, out ret))
        return ret;
    else
        return null;
}

From the point of view of the caller, it can check if the return value .HasValue, in which case it can update the storage, otherwise it update the textbox with the storage value.


The literal answer to your question is, yes, you can pass a delegate that sets the property as a parameter:

public bool ValidateTextbox(TextBox textBox, Action<double> setValue)
{
    bool parseSucceeds;
    double d;
    if (parseSucceeds = double.TryParse(textBox.Text, out d))
        setValue(d);
    return parseSucceeds;
}

You can call it with d => whatever.Path.To.The.Property = d as an argument. I wouldn't recommend this though.

Asad Saeeduddin
  • 46,193
  • 6
  • 90
  • 139
  • This means two times parsing the same double whereas the information necessary can be retrieved with a single parsing operation. – Georg Oct 29 '15 at 07:46
  • @Georg Yeah, but I don't think parsing twice instead of once is a huge problem. – Asad Saeeduddin Oct 29 '15 at 07:50
  • That depends on how often you are going to call it. However, if this code is related to validating user input on a Desktop as it seems to be, you are of course absolutely right. – Georg Oct 29 '15 at 07:51
  • @Georg It's unlikely a textbox value is getting validated frequently enough for `double.TryParse` to become a bottleneck. – Asad Saeeduddin Oct 29 '15 at 07:57
  • Ok, I think the second part is the think I was looking for. As you are not recommending it, I remain riddled why. I wanted this, to avoid code duplication, so I though it would be good to extract everything that is done repeatedly in different places of my code into this one method. If I don't, it would be probably easier and cleaner to just inline the code from the first method you are propsing from the start, wouldn't it be? – derM - not here for BOT dreams Oct 29 '15 at 08:03
  • 1
    @derM Are you referring to the snippet with the nullable number? It's good to keep in mind that any subjective recommendations I'm making are without any knowledge of your overall codebase. If passing an action immensely cleans up your codebase, go for it, but be aware of the costs; it becomes harder to trace how a value is changing in your codebase if you start passing closures around. Also, if a function accepts a value and returns a value, it's nice to be able to assume it's not making any other changes in state silently. – Asad Saeeduddin Oct 29 '15 at 08:07
  • 1
    @derM Regarding just removing this function and inlining the code wherever you're calling it from; yes, it would be ideal to have the logic for doing the parsing and conditionally changing the values in the same place. If you're following an MVVM structure, this place would be a method in the view, where you can consult the textbox state as well as the viewmodel state. – Asad Saeeduddin Oct 29 '15 at 08:10
0

If you want a method to have multiple return values, you basically have two options:

  1. Use a struct that describes both values
  2. Use a ref or out parameter

In your case, you could simply return a nullable and be fine. Using a struct is generally a bit cleaner design since you do not rely that the calling language (if it is something different than C#) knows about ref and out parameters, whereas the latter option is a very luittle bit faster.

//edit: Oh, you would probably want to know the double value independently of whether the parsing succeeds or not. So it would probably be better to define your own struct.

Georg
  • 5,626
  • 1
  • 23
  • 44