C# ignore empty textboxes - c#

I have ha a WinForms app with some textboxes.
At the moment the app is simple and i only want to test how it will work.
It will get mutch more complex in the future.
What i tried to do create a rule to ignore empty textboxes or if empty use the value 0.
The code i have is this one:
decimal ata;
decimal a1;
decimal a2;
decimal a3;
decimal a4;
decimal a5;
decimal j = 0;
a1 = decimal.TryParse(textBox1.Text, out j);
a2 = decimal.Parse(textBox2.Text);
a3 = decimal.Parse(textBox4.Text);
a4 = decimal.Parse(textBox10.Text);
a5 = decimal.Parse(textBox24.Text);
ata = a1 + a2 + a3 + a4 + a5;
resposta.Text = ata.ToString();
i get an error "Cannot implicitly convert type 'bool' to 'decimal'
in the line:
a1 = decimal.TryParse(textBox1.Text, out j);
Can anyone help me with this problem.
Thanks in advance,

Use decimal.TryParse(textBox1.Text, out j); instead of a1 = decimal.TryParse(textBox1.Text, out j);. Your value is returned in j

You declared
decimal a1;
Then you tried:
a1 = decimal.TryParse(textBox1.Text, out j);
decimal.TryParse returns a bool not a decimal
j
Is taking the parsed value

The TryParse method returns a bool value to indicate whether conversion succeeded or not. The real value is returned in the second parameter (out parameter).
You could try:
if (Decimal.TryParse(textBox1.Text, out j))
a1 = j;
This only sets a1 if parsing was successful. Otherwise a1 keeps its previous value.

The way you want to use the TryParse() method is like so
decimal a1 = 0;
bool parsed = decimal.TryParse(textBox1.Text, out a1);
if(parsed)
{
//your arithmetic
}
else
{
//throw error
}

The error is because TryParse() returns a boolean, not a decimal. You need to write explicit if statements to test if the textboxes are empty. You should consider wrapping this in a method.

You are trying to assign a bool value to a decimal variable that's why getting this error.
Decimal.TryParse() will return bool value, Please take a look here you can use this value to check parsing is successful or not.
You will get result in your out parameter i.e j.

the return value TryParse is a bool. It indicates whether the conversion was successful or not. Usually you would use it like this:
decimal j;
if (decimal.TryParse(textBox1.Text, out j))
{
// here the conversion worked and it is save to use j
}
You check whether it was successful and in this case you can use the value of the converted variable, otherwise it will remain null.
Here is the documentation
In respect to the value that is passed via the out keyword the documentation says: (s is equivalent to textBox1.Text and result is equivalent to j)
When this method returns, result contains the Decimal number that is equivalent to the numeric value contained in s, if the conversion succeeded, or is zero if the conversion failed. The conversion fails if the s parameter is null or String.Empty, is not a number in a valid format, or represents a number less than MinValue or greater than MaxValue. This parameter is passed uninitialized; any value originally supplied in result will be overwritten.

One of the nice things of object oriented programming is reusability of code in similar situations.
You mentioned you are going to use some kind of "nullable decimal text boxes" a lot of times. Why not create a class for it? You'll only have to create the class once, and everyone who needs your nullable decimal text box (especially you with all your text boxes) can reuse this one code.
Bonus: if you ever need to change the behaviour of this kind of text boxes, for instance get a yellow background when empty, all your special text boxes instantaneously behave the same.
To make it possible to ignore empty text boxes you need a property IsEmpty
Property Value returns the Value of the text box as a decimal or 0M if IsEmpty
What do you want to return if not empty but text is not a decimal?
public class MyNullableTextBox : TextBox
{
public bool IsEmpty {get{return String.IsNullOrEmpty(base.Text);} }
public decimal Value
{
get
{
if (this.IsEmpty)
return 0M;
else
{
decimal parsedValue;
bool parsed = Decimal.TryParse(base.Text, out parsedValue);
if (!parsed)
// decide what you want in this case
else
return parsedValue;
}
}
}
}
The nice thing is, that once you've added this (as a reference) to your solution, it can be found in the Toolbox and used in your forms designer as if it was a regular text box

Related

Change this condition so that it does not always evaluate to 'true'

Why is SonarQube complaining about this part of the code?
I checked this code and not always this value is true.
public static void WriteJson(object value)
{
decimal decimalValue = ((decimal?)value).Value;
int intValue = (int)decimalValue;
if (decimalValue == intValue)
Console.WriteLine(intValue);
else
Console.WriteLine(decimalValue);
Console.ReadKey();
}
Why is SonarQube complaining about this?
The false positive is related to an imperfection in our dataflow analysis engine - it does not take into account the casts between floating point and integer numbers (yet) and cannot recognize when a floating point number has been truncated.
I will try to elaborate a bit: the dataflow analysis engine tracks the values of the local variables in the analyzed methods, and when a new value is being assigned to a variable, the engine creates a special object that represents the actual value. When you assign one variable to another variable, that object remains the same. For example:
var x = 5; // the symbol of x is associated with value_0
var y = x; // the symbol of y is associated with value_0
if (x == y) // value_0 is compared with value_0 --> always true
The values we assign do not contain type information (yet) and we cannot detect (yet) changes in cases like yours:
var x = 5.5; // the symbol of x is associated with value_0
var y = (int)x; // the symbol of y is associated with value_0 (wrong)
if (x == y) // false positive
and we generate false positives, but they are relatively rare, because most casts do not generate new values.
Thanks for the feedback, we will be looking into that in the near future.
Looks like SonarQube detects that you are assigning the same value to both variables, assume that value passed to method is equal to 2
1. decimal decimalValue = 2
2. int intValue = (int)decimalValue;
therefore decimalValue = 2 and intValue = 2
The C# compiler will obviously cast it to int so in case you pass 2.5 the if comparision will not evaluate always to true. But most probably SonarQube is just not aware about the casting. So it assumes always true.
I am not an expert at SonarQube, but I guess it is because SonarQube detects that you are setting intValue to the rounded form of decimalValue. And then again you are comparing decimalValue to the decimal form of intValue. So, in many cases, it will return 'true'.
To see how it will play out, suppose the decimalValue is "123.0". Then, the intValue will be exactly "123". Then, we compare "123.0"(The value of decimalValue) to "123.0"(The value of intValue after converting to decimal) with an "if" statement, which will return true. This will play out for all integers.

Novice enquiry on using TryParse() properly

I've just tried TryParse, and am new to C# and just trying to understand everything, and then hopefully best practices...
Syntactically this works:
double number = Double.Parse(C.ReadLine());
Does TryParse only return a boolean, true if parse succeeds?
When I do this:
double number;
bool b = Double.TryParse(C.ReadLine(), out number);
number is the parsed input, from C.ReadLine(), as expected, everything works. Is this how TryParse is normally used? Trying to be efficient, appreciate advice like this.
Any advice on approach welcome, plus info on online resources for Try(things).
You use TryParse when it may fail, and you don't want your code to throw an exception.
For example
if (!Double.TryParse(someinput, out number))
{
Console.WriteLine("Please input a valid number");
}
Parse will return the double value if it succeeds and throws an exception otherwise. TryParse will return a boolean value representing the success of the operation and if it does succeed, it fills in the parsed value in the out argument you pass to it. It will never throw an exception.
In general, you should use TryParse when you expect the input string to not be a valid number and you have the logic to handle it (and display an error message, for instance).
If you don't expect the input string to be anything except a valid double you should use Parse.
The only differnce is that TryParse won't thow an exception if it can't parse the double.
This is handy when you want to assign a default value or ignore the value in your code
Example:
double number;
if (Double.TryParse(C.ReadLine(), out number))
{
// this is a double so all good
}
else
{
// not a valid double.
}
Example:
double number;
progressBar.Value = Double.TryParse(C.ReadLine(), out number) ? number : 4.0;
// If number is a valid double, set progressbar, esle set default value of 4.0
You also asked aboy TyrParse on Enum, this can be done like this
DayOfWeek fav;
if (Enum.TryParse<DayOfWeek>(Console.ReadLine(), out fav))
{
// parsed
}

string in an Enum

Given an enum like:
enum Test
{
Hi=0x1,
Hello=0x2
}
From the database, I get either a 1 or 2.
I need to concatenate 0x (to display as hex value), when the query returns 1.
I concatenate 0x and when I assign, I get an invalid argument exception.
(Test)Enum.Parse(typeof(Test), reader.GetString(0));
How can this be done?
Test = (Test)int.Parse(reader.GetString(0));
That's bare minimum code, you need to do error checking and all that good stuff.
I am not sure what you are looking to do, but if you want to convert a string value in a database that is "0x0" or "0x1", then you can use something like the code below for t1 & t3:
Test t1 = (Test) Enum.Parse(typeof (Test), Convert.ToInt32("0x0", 16).ToString());
Test t2 = (Test) Enum.Parse(typeof(Test), "0");
Test t3 = (Test) Enum.Parse(typeof(Test), Convert.ToInt32("0x1", 16).ToString());
Test t4 = (Test) Enum.Parse(typeof(Test), "1");
Well, there's always Enum.TryParse. If you're not on .NET 4.0 yet, implementing a similar method for your own use only requires a few steps:
static bool TryParseEnum<TEnum>(string text, out TEnum value)
{
value = default(T);
int number;
if (int.TryParse(text, out number) && Enum.IsDefined(typeof(TEnum), number))
{
// This awkward double-cast is unfortunately necessary
// due to the lack of a where T : enum constraint --
// the compiler cannot guarantee that T is castable from int.
value = (TEnum)(object)number;
return true;
}
return false;
}
However, based on the answer you've accepted, it seems I may have misinterpreted your question! Nevertheless, I am leaving this answer here in case it's useful to anyone.
I think what you're trying to do is this:
Take a a string representation of a decimal number, and display that
number in hexidecimal form.
If so, try this:
String x = String.Format("{0:X2}", Int.Parse(myInteger));
Or perhaps I've misunderstood what your problem is.

How to check for valid value before converting Decimal

I assume this will blow up if total is null (I don't recall if decimals are initalized to null at the beginning or zero)
public int SomePropertyName
{
get { return Convert.ToInt32(Decimal.Round(total)); }
}
So should I check for null or > 0 ?
Decimal is a value type - there's no such value as "null" for a decimal.
However, it's perfectly possible for a decimal to be out of range for an int. You might want:
decimal rounded = decimal.Round(total);
if (rounded < int.MinValue || rounded > int.MaxValue)
{
// Do whatever you ought to here (it will depend on your application)
}
return (int) rounded;
I'm somewhat confused as to why you're using Convert.ToInt32 at all though, given that your property is declared to return a decimal. What's the bigger picture here? What are you trying to achieve?
Decimal is a value type and can not be null.
If you need to know if it had been initialized, you should probably use a nullable decimal:
Decimal? total = null;
public int SomePropertyName
{
get
{
if (total.HasValue) Convert.ToInt32(Decimal.Round(total.Value));
return 0; // or whatever
}
}
Decimals are value types, and so cannot be null.
So no need to check there..
As others have said, Decimal is a value type and cannot be null. However, if converting from a string then Decimal.TryParse is your friend...
System.Decimal is a value type, so it cannot be null. Second thing, the method's return value is decimal, so why would you want to convert to a Int32?

C# doubt, finding the datatype

I have the following variables:
string str1 = "1";
string str2 = "asd";
string str3 = "3.5";
string str4 = "a";
Now I need to find the data type of each string i.e. the data type to which it can be converted if quotes are removed. Here is what I would like each variable to convert to:
str1 - integer
str2 - string
str3 - double
str4 - char
Note: if the string has single character it should be char, though a string can have single letter, I'm limiting it.
FYI: these values are obtained from DataGrid where i manually entered values. So everything is becoming a string.
Is there any way to do this?
Of course, there's no definite way to do this, but if you create a list of data types you want to check ordered by priority, then something like this may do the trick.
object ParseString(string str)
{
int intValue;
double doubleValue;
char charValue;
bool boolValue;
// Place checks higher if if-else statement to give higher priority to type.
if (int.TryParse(str, out intValue))
return intValue;
else if (double.TryParse(str, out doubleValue))
return doubleValue;
else if (char.TryParse(str, out charValue))
return charValue;
else if (bool.TryParse(str, out boolValue))
return boolValue;
return null;
}
Just call this function on each string, and you should have the appropiate type of object returned. A simple type check can then tell you how the string was parsed.
Use meta-data, if you can
That you have to guess what the data types are, is not a good idea.
Two things
1 Where is the data coming from?
If it's a database, are you sure they're strings?
If it is a database, there should be some meta data returned that will tell you what the datatypes of the fields are.
If it's an Xml file, is there a schema defined that will give you the types?
2 If you have to continue to guess.
Be aware that you can have strings that happen to be numbers, but are perfectly valid strings e.g phone numbers, bank acount numbers, that are best expressed as strings.
Also these numbers can have many digits, if you convert them to doubles you may loose some digits to floating point inaccuracies (you should be OK up to 14 or 15 digits)
I'm sure by now - cause I've taken my time typing this - there are lots of answers telling you how to do this (i.e. tryparse int first, then double, then test length for char, if not then it's a string etc), but if I were you, I'd try to NOT do that, and see if there's any way you can get, or pass some meta-data that will tell you what type it IS and not just what type it might be
Use the TryParse method of each type.
There is no built in way to do this, you could attempt TryParse on number types with increasing precision, but it wouldn't guarantee it to be right.
Your best bet what be to process it like you would manually. i.e. Is there a decimal place? No - then its an integer. How big? Is it negative?
The datatype for each of these items is string. If you want to attempt to parse them into different types you can use Int32.TryParse, Double.TryParse, etc. Or you can use Regex:
bool isInt = new Regex(#"^\d+$").IsMatch(str);
bool isDouble = !(isInt) && new Regex(#"^\d+\.\d+$").IsMatch(str);
bool isChar = !(isInt || isDouble) && new Regex(#"^.$").IsMatch(str);
bool isString = !(isInt || isDouble || isChar);

Categories

Resources