I have some textboxes in my C# windows form application. I want to do the following:
inRed = Convert.ToInt32(tbRed.Text.ToString().Length < 0 ? tbRed.Text = "0" : tbRed.Text);
inGreen = Convert.ToInt32(tbGreen.Text.ToString().Length < 0 ? tbGreen.Text = "0" : tbGreen.Text);
inBlue = Convert.ToInt32(tbBlue.Text.ToString().Length < 0 ? tbBlue.Text = "0" : tbBlue.Text);
inCyan = Convert.ToInt32(tbCyan.Text.ToString().Length < 0 ? tbCyan.Text = "0" : tbCyan.Text);
inMagenta = Convert.ToInt32(tbMagenta.Text.ToString().Length < 0 ? tbMagenta.Text = "0" : tbMagenta.Text);
If the textbox doesn't have a value, enter a 0 and convert to integer, otherwise convert the value of the textbox to integer.
I am getting the following error for inCyan, where the textbox is empty:
Input string was not in a correct format.
How can I achieve what I am looking for?
Instead of Convert.ToInt32, use Int32.TryParse. This gives you feedback regarding if it was a valid integer. e.g.
String textboxValue = "1";
Int32 i;
if (!String.IsNullOrWhitespace(textboxValue) && // Not empty
Int32.TryParse(textboxValue, out i)) { // Valid integer
// The textbox had a valid integer. i=1
} else {
// The texbox had a bogus value. i=default(Int32)=0
// You can also specify a different fallback value here.
}
As a follow-up, String.IsNullOrWhitespace makes it easy to decipher if a value is supplied, but (depending on your .NET version) is may not be available (and you may only have String.IsNullOrEmpty.
If need be, the polyfill is something long the lines of:
Boolean SringIsNullOrWhitespace(String input)
{
return !String.IsNullOrEmpty(input) && input.Trim().Length > 0;
}
Also, if you find yourself trying to perform this parsing frequently, you could refactor it into a helper class:
public static class ConvertUtil
{
public Int32 ToInt32(this String value)
{
return ToInt32(value, default(Int32));
}
public Int32 ToInt32(this String value, Int32 defaultValue)
{
#if NET4
if (!String.IsNullOrWhiteSpace(value))
#else
if (!String.IsNullOrEmpty(value) && value.Trim().Length > 0)
#endif
{
Int32 i;
if (Int32.TryParse(value, out i))
{
return i;
}
}
return defaultValue;
}
}
// explicit
inRed = ConvertUtil.ToInt32(tbRed.Text, 0/* defaultValue*/);
// As extension
inRed = tbRed.Text.ToInt32(0/* defaultValue*/);
You can do something like
// Initialise variable with 0
int value;
// Try parse it, if it's successful and able to parse then value is set to the int equivalent of your text input
int.TryParse(inputVariable, out value);
return value
This is a simple way of dealing with your problem - note, if the parse fails then it returns 0 to value.
How you would apply it to your particular problem.
int inMagenta;
int.TryParse(tbMagenta, out inMagenta);
etc.....
You can use tryparse.
int inRed; //default value will be 0 , if the string is not in a valid form
Int32.TryParse(tbRed.Text.ToString(), out inRed);
Related
I'm new to C# but not to programming in general.
I am trying to set add some error checking to my program. There are 3 textboxes and I am trying to make it so that if the text box is left blank, it assumes a value of 0. Here is my code so far:
private void btnCalculate_Click(object sender, EventArgs e)
{
if (String.IsNullOrEmpty(txtNumberOfClassATix.Text)) // Assumes 0 if no number entered for txtNumberOfClassATix.Text.
{
txtNumberOfClassATix.Text = "0";
}
if (String.IsNullOrEmpty(txtNumberOfClassBTix.Text)) // Assumes 0 if no number entered for txtNumberOfClassBTix.Text.
{
txtNumberOfClassBTix.Text = "0";
}
if (String.IsNullOrEmpty(txtNumberOfClassCTix.Text)) // Assumes 0 if no number entered for txtNumberOfClassCTix.Text.
{
txtNumberOfClassCTix.Text = "0";
}
int classANum = int.Parse(txtNumberOfClassATix.Text);
int classBNum = int.Parse(txtNumberOfClassBTix.Text);
int classCNum = int.Parse(txtNumberOfClassCTix.Text);
double classATotal = classANum * classAPrice;
double classBTotal = classBNum * classBPrice;
double classCTotal = classCNum * classCPrice;
lblCalculatedClassARevenue.Text = $"{classATotal:c}";
lblCalculatedClassBRevenue.Text = $"{classBTotal:c}";
lblCalculatedClassCRevenue.Text = $"{classCTotal:c}";
lblCalculatedTotalRevenue.Text = $"{(classATotal + classBTotal) + classCTotal:c}";
}
This code works but I'm sure I could replace those if statements with something simpler. I've seen how to set a variable to null if another is null using the null-conditional operator but I don't really grasp it enough to adapt it to my scenario.
So far maccettura's answer is the best, but can we do better? Sure we can. Let's make a general-purpose extension method:
internal static class Extensions
{
public static int? AsInt(this string s)
{
int result;
if (s == null)
return null;
else if (int.TryParse(s, out result))
return result;
else
return null;
}
}
And now:
int classANum = txtNumberOfClassATix.Text.AsInt() ?? 0;
If it's an int, you get the int. If it's not, you get zero. Easy peasy.
Or, you might want this extension method:
internal static class Extensions
{
public static int AsInt(this string s, int default = 0)
{
int result;
if (s == null)
return default;
else if (int.TryParse(s, out result))
return result;
else
return default;
}
}
And now you can say what you want the default to be without using ??.
This style of programming is called "fluent programming"; it can make code that is very easy to read and understand.
Notice that this solution does not update the UI with zeros; if you wanted to do that then I would recommend splitting that into two steps: one which causes the mutation, and then a separate step which computes the value. Operations which are useful for both their effects and their values can be confusing.
This is a perfect time to use a method so you arent repeating yourself:
private static int GetInputAsInt(TextBox textbox)
{
int outputValue = 0;
if(textbox?.Text != null && int.TryParse(textbox.Text, out outputValue))
{
return outputValue;
}
return 0;
}
Now you are checking if the textbox itself is not null, and that the value contained therein is a int, if anything fails it returns a 0;
Call it in your other method like this:
int classANum = GetInputAsInt(txtNumberOfClassATix);
Which means your button click event would be a bit simpler:
private void btnCalculate_Click(object sender, EventArgs e)
{
int classANum = GetInputAsInt(txtNumberOfClassATix);
int classBNum = GetInputAsInt(txtNumberOfClassBTix);
int classCNum = GetInputAsInt(txtNumberOfClassCTix);
double classATotal = classANum * classAPrice;
double classBTotal = classBNum * classBPrice;
double classCTotal = classCNum * classCPrice;
lblCalculatedClassARevenue.Text = $"{classATotal:c}";
lblCalculatedClassBRevenue.Text = $"{classBTotal:c}";
lblCalculatedClassCRevenue.Text = $"{classCTotal:c}";
lblCalculatedTotalRevenue.Text = $"{(classATotal + classBTotal) + classCTotal:c}";
}
To keep it simple, a good approach is to use the conditional operator. The full example is below (broken across two lines for readability):
txtNumberOfClassATix.Text =
String.IsNullOrEmpty(txtNumberOfClassATix.Text) ? "0" : txtNumberOfClassATix.Text;
This is a nice, readable, assignment for the first part:
myString = ...
The conditional operator breaks down by providing a boolean expression (true/ false) on the left side of the ?. So, for example:
myString = anotherString == "" ? ... // checking if another string is empty
The final part is the :. To the left is the assignment if the expression is true, and to the right goes the assignment if the expression is false. To finish the example:
myString = anotherString == "" ? "anotherString is empty" : "anotherString is not empty";
The above example can be written out in full to clear up any misunderstanding as:
if (anotherString == "")
{
myString = "anotherString is empty";
}
else
{
myString = "anotherString is not empty";
}
This can apply to all the statements. The documentation is found here.
The best way to reduce the line of code is use the function for your common operation(s). In your case, you can create function which checks whether or not the object is NULL or empty. Based on the return value of that function you can proceed ahead. On the other hand, you can handle it on front-end by using different validators such as RequiredFieldValidator, CustomValidator, etc.
Is it posible to create a method with a decimal argument, that only accepts values from 0 to 1?
Example:
public decimal GetSamplingError(decimal percent){
decimal result = 0;
result = 100*percent;
return result;
}
is it posible to control that the parameter percent is compres between 0 and 1?
Thanks and sorry for my bad english.
no there is no way to control parameter's range, what you can do, is control it inside the function itself, and add a comment to the function
public decimal GetSamplingError(decimal percent){
if(percent > 1)
percent = 1;
else if(percent <0)
percent = 0;
return 100*percent;
}
Or raise an ArgumentOutOfRangeException in case if the parameter is not in dsired range, but it depends on how you would like to manage a worklfow of your application.
I would create my own type of Percent with range checks as others have suggested and some additional stuff. That way, Percent is its own entity in your application and everyone knows when and how to use it. A plain decimal might work as well, I prefer the typed approach however.
internal class Percent
{
private readonly decimal _value;
public decimal Value
{
get { return _value; }
}
public Percent(decimal value)
{
_value = (100 * value);
if (value < 0m || value > 1m)
{
throw new ArgumentOutOfRangeException("value");
}
}
public override string ToString()
{
return String.Format("{0}%", _value);
}
public override int GetHashCode()
{
// HashCode implementation;
}
public override bool Equals(object obj)
{
// Equals implementation;
}
}
There is no way of compile-time checking this. The best solution would be to check the argument at run-time:
public decimal GetSamplingError(decimal percent)
{
if (percent < 0m || percent > 1m)
{
throw new ArgumentException("Percent should be between 0 and 1!", "percent");
}
decimal result = 0;
result = 100*percent;
return result;
}
Other than the approach of Tigran, this will throw an Exception when an invalid argument is passed. I prefer this method over just changing the percent-value, becasue it'll actually make you notice that you passed a wrong value.
When you use Code Contracts of Microsoft, then you could add a contract that ensures that the value is in a specific range. When static checking is enabled, you'll get an error message at compile-time.
Contract.Requires(percent > 0m && percent < 1m, "Percent must be between 0 and 1");
You would have to do:
public decimal GetSamplingError(decimal percent){
if (percent < 0m || percent > 1m)
throw new ArgumentOutOfRangeException("percent", "Must be between 0 and 1.");
// rest of method
}
Of course, it is also possible to make your own struct called DecimalBetweenZeroAndOne which is immutable and holds a decimal field which is readonly and where you write a check to guarantee that the value of the field is always in the required range.
It is possible to validate the input and throw exception if value is not what you expected:
decimal getPercentage(decimal val)
{
if (val < 0 || val > 1)
throw new ArgumentException();
return val * 100;
}
I have this code that it works only if all the textBox contains values.. But if a textbox is empty i get an error..
Int32 Total = Int32.Parse((txtChild1.Text))
+ Int32.Parse(txtChild2.Text)
+ Int32.Parse(txtChild3.Text)
+ Int32.Parse(txtWife1.Text)
+ Int32.Parse(txtWife2.Text)
+ Int32.Parse(txtWife3.Text);
I know that it must be a function like IsNull but for the integer values..
Does anyone know what it is ?
You're looking for Int32.TryParse:
Int32 val;
if (Int32.TryParse(txtChild1.Text, out val)){
// val is a valid integer.
}
Which you call on every .Text property, then add them together. You can also make an extension to make it easier (if you chose):
public static class NumericParsingExtender
{
public static Int32 ToInt32(this String input, Int32 defaultValue = 0)
{
if (String.IsNullOrEmpty(input)) return defaultValue;
Int32 val;
return Int32.TryParse(input, out val) ? val : defaultValue;
}
}
Then, in practice:
Int32 total = txtChild1.Text.ToInt32() + txtChild2.Text.ToInt32()
+ txtChild3.Text.ToInt32() + /* ... */;
And, of course, an example
You can use Int32.TryParse:
Int32 int1 = 0;
Int32.TryParse(txtChild1.Text, out int1);
//.... more int declarations
Int32 total = int1 + int2 + int3; //etc. etc.
TryParse will try to parse the text and if it fails, it will set the variable to 0.
You can also inline some of the logic (although this makes the code very long and messy):
Int32 Total = (txtChild1.Text.Length == 0 ? 0 : Int32.TryParse(txtChild1.Text)) + (txtChild2.Text.Length == 0 ? 0 : Int32.TryParse(txtChild2.Text)); //etc. etc.
Int32.TryParse reference: http://msdn.microsoft.com/en-us/library/f02979c7.aspx
Shorthand if reference: http://msdn.microsoft.com/en-gb/library/ty67wk28(v=vs.110).aspx
you should check if the TextBox is not empty before parsing it or you can use TryParse
http://msdn.microsoft.com/en-us/library/f02979c7.aspx
Int32 is a value type. It can't be null. Or course there is a nullable types but hey..
Try with Int32.Tryparse() method.
Converts the string representation of a number to its 32-bit signed
integer equivalent. A return value indicates whether the operation
succeeded.
Int32.TryParse(txtChild1.Text, out val)
returns boolean true if s was converted successfully; otherwise, false.
You can't parse an empty string "". Check if the box contains anything before parsing.
Textbox.text != ""
Other answers are quicker to use tryparse is the best in fact, as it does the same with less lines of code!
Well the question title may not be self explanatory, so let me go ahead and elaborate.
Consider, a TextBox that accepts only numeric value or is left empty. The value(text) entered is stored in an integer(int32) variable. The problem arises when the user enters the digit 0 or leaves the TextBox empty, as the conversion from string to int, converts an empty string to "0" as well.
So my question stands: How do I differentiate the 2 scenarios?
EDIT I figured a lot of questions may be answered by the code and exact problem(as I see it)
if (txtOtherId.Text == string.Empty)
{
otherId = Convert.ToInt32(null);
}
else
{
otherId = Convert.ToInt32(txtOtherId.Text);
}
How about an extension method?
public static class Extensions
{
public static bool TryGetInt(this TextBox tb, out int value)
{
int i;
bool parsed = int.TryParse(tb.Text, out i);
value = i;
return parsed;
}
}
Usage:
int i;
if (textBox1.TryGetInt(out i))
{
MessageBox.Show(i.ToString());
}
else
{
// no integer entered
}
What have you tried? Can we see your code?
Now, I tried the following:
int i;
i = Convert.ToInt32(""); // throws, doesn't give zero
i = int.Parse(""); // throws, doesn't give zero
bool couldParse = int.TryParse("", out i); // makes i=0 but signals that the parse failed
So I can't reproduce. However, if I use null instead of "", the Convert.ToInt32 does convert into zero (0). However, Parse and TryParse still fail with null.
UPDATE:
Now that I see your code. Consider changing the type of otherId from int to int? where the question mark makes it a nullable type. Then:
if (txtOtherId.Text == "")
{
otherId = null; // that's null of type int?
}
else
{
otherId = Convert.ToInt32(txtOtherId.Text); // will throw if Text is (empty again or) invalid
}
If you want to be sure no exceptions can happen, do this:
int tmp; // temporary variable
if (int.TryParse(txtOtherId.Text, out tmp))
otherId = tmp;
else
otherId = null; // that's null of type int?; happens for all invalid input
You could use a nullable int, and then have blank string be null.
int? myValue = String.IsNullOrEmpty(myTextbox.Text)
? (int?)null
: int.Parse(myTextbox.Text);
For clarity, the above is equivalent to
int? myValue = null;
if(!String.IsNullOrEmpty(myTextbox.Text))
{
myValue = int.Parse(myTextbox.Text);
}
Assuming that it is indeed a textbox...
string result = myTextBox.Text;
if (string.IsNullOrEmpty(result))
// This is an empty textbox
else
// It has a number in it.
int i = int.Parse(result);
There're 2 simple approaches how to do it:
string inputText="";
int? i=null;
if (!string.IsNullOrWhiteSpace(inputText))
i = int.Parse(inputText);
int i2;
bool ok = int.TryParse(inputText, out i2);
I am currently converting vb and vb.net to c# but have an issue. I would strongly like not to use the visualbasic dlls in the converted code and have been doing this fine so far.
But this code
Dim x as Double 'this was error saying it was integer
x = Val("1 23 45 x 6") ''#x is 12345
x = Val("1..23") ''#x is 1.23
x = Val("1 1,,,,,2,2..3") ''#x is 1122.3
Does not work the same as vb6 even with using "Val" from the visualbasic.conversion.dll Is there anyone that has solved this to work the same? A c# solution would be best.
None of the above seemed to satisfy my needs, so I wrote the following:
public static Double Val(string value)
{
String result = String.Empty;
foreach (char c in value)
{
if (Char.IsNumber(c) || (c.Equals('.') && result.Count(x => x.Equals('.')) == 0))
result += c;
else if (!c.Equals(' '))
return String.IsNullOrEmpty(result) ? 0 : Convert.ToDouble(result);
}
return String.IsNullOrEmpty(result) ? 0 : Convert.ToDouble(result);
}
Results of the test data:
"0 1 5.2123 123.123. 1 a" returns 15.21233123
" 1 5.2123 123a" returns 15.21233123
"a1 5.2123 123.123. 1 a" returns 0
"" returns 0
I know nothing of this VisualBasic.Conversion.dll (and neither does google), but the Microsoft.VisualBasic namespace (in Microsoft.VisualBasic.dll) is part of the core framework and perfectly fine and acceptable to use from C#. There are other nice gems in there as well (ie TextFieldParser), but this should have the exact Val() implementation you need.
If this is the library you've already tried and it doesn't seem right, then I'd go take another look at the unit tests on it.
Outside of this, the accepted ways in C# for converting strings to integers are int.Parse(), int.TryParse(), and Convert.ToInt32(). But, like it or not, the Val() function from the Microsoft.VisualBasic.dll library is the closest match you're going to find for your code's existing behavior.
Check out this site: http://www.dreamincode.net/forums/topic/36064-val-replacement/ where others give an example how to implement your own Val() function.
You could use the Convert static class. It's pretty close to Val() but you need to specify the convert to type. It's in the System namespace.
E.g.:
int x = Convert.ToInt32("23");
int y = Convert.ToDouble("23.342");
http://msdn.microsoft.com/en-us/library/system.convert(v=vs.71).aspx
There is no exact equivalent of vb6 val function in C#. But this function can be used by using Microsoft.VisualBasic namespace in C#.
To use val() function in C# add Microsoft.VisualBasic namespace and use following code:
Conversion.Val("09sdf");
From your examples it could look similar to this. But since I don't know the VB val specification it might not work on all strings correctly.
Decimal ParseNumerString(string s)
{
Decimal value=0;
Decimal multiplier=1;
bool decimalPart=false;
foreach(char c in s)
{
if(IsDigit(c))
{
int i=ParseDigit(c);
if(!decimalPart)
{
value=value*10+i;
}
else
{
muliplier/=10;
value=value+multiplier*i;
}
if(c=='.')
decimapPart=true;
}
return value;
}
This is pseudocode you need to implement parse digit and is digit yourself(trivial). I chose Decimal as internal representation because that way I don't get strange rounding errors in the fractional part.
Had the same issue, started with #ericosg 's answer, then realized I needed Negative Numbers and Scientific Notation
namespace VB6
{
public class Helper
{
public static double Val(object value)
{
double returnVal = 0;
string sToParse = value.ToString();
string result = string.Empty;
string num = string.Empty; //In the case of scientific notation e.g. 3e5 = 300000
foreach (char c in sToParse)
{
if (result.Length == 0 && c.Equals('-'))//negative numbers
result += c;
else if (Char.IsNumber(c) || (c.Equals('.') && result.Count(x => x.Equals('.')) == 0))
result += c;
else if ((c.Equals('e') || c.Equals('E')) && num.Length == 0 && result.Length != 0) //scientific notation
{
num = result;
result = string.Empty;
}
else if (!c.Equals(' '))
{
break;
}
}
if (num.Length > 0)
{
//scientific notation
double fSignificantFigures = string.IsNullOrEmpty(result) || result == "-" ? 1 : Math.Pow(10, Convert.ToDouble(result));
returnVal = num == "-" ? 0 : Convert.ToDouble(num) * fSignificantFigures;
}
else
{
returnVal = string.IsNullOrEmpty(result) || result == "-" ? 0 : Convert.ToDouble(result);
}
return returnVal;
}
}
}