patterncsharpMinor
TextBoxes for various number types
Viewed 0 times
textboxesnumberfortypesvarious
Problem
Is there a way I could somehow have all this classes condensed into one, while keeping the code as clean as possible?
They are all doing essentially the same thing, just for the different number type. I don't know how to "generalize"
Base class:
Int variant:
UInt variant:
```
public class TextBoxUInt : TextBoxNum
{
public override void Update(object sender, EventArgs e)
{
uint newValue;
if (uint.TryParse(Text, out newValue))
{
if (newValue max)
{
newValue = Clamp(newValue);
}
value.Set(newValue);
Text = value.Get().ToString();
}
else
{
Text = value.Get().ToString();
Focus();
}
}
public TextBoxUInt(Value value
They are all doing essentially the same thing, just for the different number type. I don't know how to "generalize"
TryParse() without using switch or if tree which doesn't seem very clean to me.Base class:
public class TextBoxNum : TextBox where T : IComparable
{
protected T min;
protected T max;
protected Value value;
public virtual void Update(object sender, EventArgs e)
{
}
protected T Clamp(T input)
{
if (input.CompareTo(max) > 0)
{
return max;
}
if (input.CompareTo(max) value, T min, T max)
{
this.value = value;
this.min = min;
this.max = max;
LostFocus += new EventHandler(Update);
}
}Int variant:
public class TextBoxInt : TextBoxNum
{
public override void Update(object sender, EventArgs e)
{
int newValue;
if (int.TryParse(Text, out newValue))
{
if (newValue max)
{
newValue = Clamp(newValue);
}
value.Set(newValue);
Text = value.Get().ToString();
}
else
{
Text = value.Get().ToString();
Focus();
}
}
public TextBoxInt(Value value, int min, int max) : base(value, min, max)
{
}
}UInt variant:
```
public class TextBoxUInt : TextBoxNum
{
public override void Update(object sender, EventArgs e)
{
uint newValue;
if (uint.TryParse(Text, out newValue))
{
if (newValue max)
{
newValue = Clamp(newValue);
}
value.Set(newValue);
Text = value.Get().ToString();
}
else
{
Text = value.Get().ToString();
Focus();
}
}
public TextBoxUInt(Value value
Solution
class TextBoxNum- Abbreviation should be avoided when naming a class:
Num->Numeric
- The descriptive adjective should also be in front of the noun. It is a numerical textbox, and not a textbox number:
NumericTextBoxBase
TextBoxNumandUpdateshould be marked asabstract, unless a generic way of updating the value is provided inTextBoxNum. And by changing it to a abstract class, we should appendBaseto the end of the class name :NumericTextBoxBase, and its concrete classes can be named asFloatTextBox,DoubleTextBox...
class ValueWithout the definition of this class, I can only make some guess about it. We can observe that the value is assigned by a parameter from the constructor. The class itself seems to serve no other purpose than holding the value via
void Value.Set(T) and T Value.Get(). I would suggest you to replace them by T or T?, depending on whether or not if you want to enforce valid value is required.Misc
- Avoid
try-catchas control-structure much as possible, unless that is your last resort.
- Your
Clampmethod is comparing the value against the same upper boundary,max, twice.
Code:
public class NumericTextBox : TextBox where T : IComparable
{
protected T min;
protected T max;
protected T value;
public NumericTextBox(T value, T min, T max)
{
this.min = min;
this.max = max;
// ensure the value is with in valid range
this.value = Clamp(value);
// actually you should implement a full property for value and update the Text property in the setter
this.Text = value.ToString();
LostFocus += new EventHandler(Update);
}
protected virtual void Update(object sender, EventArgs e)
{
var type = typeof(T);
var tryParse = type.GetMethod("TryParse", new[]
{
typeof(string), type.MakeByRefType()
});
var args = new object[] { Text, null };
var result = (bool)tryParse.Invoke(null, args);
if (result)
{
value = Clamp((T)args[1]);
Text = value.ToString();
}
else
{
Text = value.ToString();
Focus();
}
}
protected T Clamp(T input)
{
if (input.CompareTo(max) > 0)
{
return max;
}
if (input.CompareTo(min) < 0)
{
return min;
}
return input;
}
}Code Snippets
public class NumericTextBox<T> : TextBox where T : IComparable<T>
{
protected T min;
protected T max;
protected T value;
public NumericTextBox(T value, T min, T max)
{
this.min = min;
this.max = max;
// ensure the value is with in valid range
this.value = Clamp(value);
// actually you should implement a full property for value and update the Text property in the setter
this.Text = value.ToString();
LostFocus += new EventHandler(Update);
}
protected virtual void Update(object sender, EventArgs e)
{
var type = typeof(T);
var tryParse = type.GetMethod("TryParse", new[]
{
typeof(string), type.MakeByRefType()
});
var args = new object[] { Text, null };
var result = (bool)tryParse.Invoke(null, args);
if (result)
{
value = Clamp((T)args[1]);
Text = value.ToString();
}
else
{
Text = value.ToString();
Focus();
}
}
protected T Clamp(T input)
{
if (input.CompareTo(max) > 0)
{
return max;
}
if (input.CompareTo(min) < 0)
{
return min;
}
return input;
}
}Context
StackExchange Code Review Q#141455, answer score: 3
Revisions (0)
No revisions yet.