Using VS2010 Express, C# and it's WinForms Application.
Here I have three text boxes(aTextBox, bTextBox, cTextBox) from which Inputs are strings and then using int.Parse(aTextBox.Text) converted to integers.
Then a Button (calcBtn) method which is going to calculate charges and then to display results after some maths to particular TextBoxes on Result groupBox which again contains text boxes for results...
The problem is causing by the way I am parsing or the order in which it's executing. If any of the textbox is filled then result should display and not to get in the format exceptions. Here I am getting stuck because inside the calcBtn I am parsing all text boxes and if one of them is empty then exception occurs. Compiler is I guess trying to parse empty strings from the empty text boxes, and I don't want it to be.
Any suggestions if you got what I mean? :)
Here's what GUI looks like
You can use the extended method...
1) method
public static class TE
{
public static int StringToInt(this string x)
{
int result;
return int.TryParse(x, out result) ? result : 0;
}
}
2) use
System.Windows.Forms.TextBox t = new System.Windows.Forms.TextBox();
int x = t.Text.StringToInt();
The Int32.Parse method does not accept malformed strings, and this includes empty strings. I have two suggestions.
You could check if the string is empty/whitespace first, and return 0 or some other default value:
private static int ParseInteger(string str)
{
if (str == null || str.Trim() == "")
return 0;
// On .NET 4 you could use this instead. Prior .NET versions do not
// have the IsNullOrWhiteSpace method.
//
// if (String.IsNullOrWhiteSpace(str))
// return 0;
return Int32.Parse(str);
}
Or you could simply ignore all parsing errors, treating them as 0. This will treat things like "", "123abc", and "foobar" as zero.
private static int ParseInteger(string str)
{
int value;
if (Int32.TryParse(str, out value))
return value;
return 0;
}
Which approach you take depends on the specific needs of your application.
You can simply do:
private static int ParseInteger(string str)
{
int value;
Int32.TryParse(str, out value);
return value;
}
without any if, since TryParse set value to 0 if it fails
Related
edit; Based on responses, I may have been unclear in my final goal. I've updated the last section.
Situation
I have a number of variables which I need to perform the same operation on. In this case, they are strings, and can at the point we reach this code have the value null, "", "Blank", or they could already have an assigned other value that I want to keep.
if (String.IsNullOrEmpty(MyVar1) || "Blank".Equals(MyVar1))
MyVar1 = null;
if(String.IsNullOrEmpty(MyVar2) || "Blank".Equals(MyVar2))
MyVar2 = null;
...
if(String.IsNullOrEmpty(MyVar10) || "Blank".Equals(MyVar10))
MyVar10 = null;
Being a programmer that wants to keep my code clean and this block drives me mad, I'm looking for a way to create a list of these variables, and perform this same if statement + null assignment on each.
For an example, here's what I'd like to do:
MyVar1 = "Blank";
DreamDataStructure varList = new DreamDataStructure() { MyVar1, MyVar2, ..., MyVar10 };
foreach(ref string MyVar in varList)
{
if(String.IsNullOrEmpty(MyVar) || "Blank".Equals(MyVar))
MyVar = null;
}
Console.WriteLine(MyVar1); //Should now be null
What Doesn't Work
1) Because my variables are strings, I can't do something like this.
var myListOfVariables = new[] { &MyVar1, &MyVar2, ..., &MyVar10 };
If I could, I'd be able to foreach over them as expected. Because string is a managed type though, it cannot be passed by reference like this.
2) Similarly, if I just made a List<string> of the variables, they would be passed by value and wouldn't help my case.
3) These variables can't be wrapped in an outer object type, as they need to be used as strings in a large number of places in a legacy application. Assume that it would be too large an effort to change how they're used in every location.
Question
Is there a way to iterate over string (or other managed type) variables in a pass-by-reference way that will allow me to put the entire operation inside of a loop and reduce the duplication of code that's happening here?
The goal here is that I can use the original variables later on in my code with the updated values. MyVar1, etc, are referenced later on already by legacy code which expects them to be null or have an actual value.
If I understand your question correctly, I don't think what you want to do is possible. Please see this question: Interesting "params of ref" feature, any workarounds?
The only thing I can suggest (which I know doesn't answer your question) is creating a method to avoid duplication of your conditional logic:
void Convert(ref string text)
{
if (string.IsNullOrEmpty(text) || "Blank".Equals(text))
{
text = null;
}
}
You could create a function instead of passing references, which would also be more readable.
string Validate(string inputString)
{
return string.IsNullOrEmpty(inputString) || "Blank".Equals(inputString) ? null : inputString;
}
<...>
MyVar1 = Validate(MyVar1);
Update:
Now I get what you're trying to do. You have a bunch of variables, and you want to perform some sort of bulk operation on them without changing anything else. Putting them in a class isn't an option.
In that case you're really stuck operating on them one at a time. There are ways to shorten it, but you're pretty much stuck with the repetition.
I'd
create a string SanitizeString(string input) function
type x = SanitizeString(x); once for each variable
copy and paste the variable names to replace x.
It's lame, but that's about all there is.
Perhaps this would be a better approach. It ensures that the values are always sanitized. Otherwise you can't easily tell whether the values have been sanitized or not:
public class MyValues
{
private string _value1;
private string _value2;
private string _value3;
public string Value1
{
get { return _value1; }
set { _value1 = Sanitize(value); }
}
// repeat for other values
private string Sanitize(string input) =>
string.IsNullOrEmpty(input) || string.Equals("Blank", input) ? null : input;
}
That's one option. Another is to sanitize the inputs earlier. But ideally we want to ensure that a given class is always in a valid state. We wouldn't want to have an instance of a class whether the values may or may not be valid. It's better to ensure that they are always valid.
ref doesn't really factor into it. We don't need to use it often, if ever. With a value type or string we can just return a new value from a function.
If we're passing a reference type and we want to make changes to it (like setting its properties, adding items to a list) then we're already passing a reference and we don't need to specify ref.
I'd try to write methods first without using ref and only use it if you need to. You probably never will because you'll succeed at whatever you're trying to do without using ref.
Your comment mentioned that this is a legacy app and it's preferable not to modify the existing class. That leaves one more option - reflection. Not my favorite, but when you say "legacy app" I feel your pain. In that case you could do this:
public static class StringSanitizer
{
private static Dictionary<Type, IEnumerable<PropertyInfo>> _stringProperties = new Dictionary<Type, IEnumerable<PropertyInfo>>();
public static void SanitizeStringProperties<T>(T input) where T : class
{
if (!_stringProperties.ContainsKey(typeof(T)))
{
_stringProperties.Add(typeof(T), GetStringProperties(typeof(T)));
}
foreach (var property in _stringProperties[typeof(T)])
{
property.SetValue(input, Sanitize((string)property.GetValue(input)));
}
}
private static string Sanitize(string input)
{
return string.IsNullOrEmpty(input) || string.Equals("Blank", input) ? null : input;
}
private static IEnumerable<PropertyInfo> GetStringProperties(Type type)
{
return type.GetProperties(BindingFlags.Instance | BindingFlags.Public)
.Where(property => property.PropertyType == typeof(string) && property.CanRead && property.CanWrite);
}
}
This will take an object, find its string properties, and sanitize them. It will store the string properties in a dictionary by type so that once it has discovered the string properties for a given type it won't have to do it again.
StringSanitizer.SanitizeStringProperties(someObject);
you can simply use a string[] and get the changes back to the caller method like this.
public Main()
{
var myVar1 = "Blank";
var myVar2 = "";
string myVar3 = null;
var myVar4 = "";
string[] dreamDataStructure = new string[] { myVar1, myVar2, myVar3, myVar4 };
}
private void ProcessStrings(string[] list)
{
for(int i = 0; i < list.Length; i++)
{
if (String.IsNullOrEmpty(list[i]) || "Blank".Equals(list[i]))
list[i] = null;
}
}
I'm trying to take objects out of an object list to an int list. If the object list's value contains a string than I want to convert it to an int. the error that I'm getting is "cannot convert from 'object' to 'System.ReadOnlySpan'. I've tried looking up examples and information about lists made of objects but couldn't find anything.
I'm also at a loss as to what to do with the 'else' part of the code.
public class ListFilterer
{
public static IEnumerable(int) GetIntegersFromList(List(object) listOfItems)
{
List<int> Integers = new List<int>();
foreach (var value in listOfItems)
{
int number = 0;
bool success = Int32.TryParse(value, out number);
if (success)
{
Integers.Add(number);
}
else
{
Integers.Add(number);
}
}
return Integers;
}
}
It'll probably work out if you TryParse value.ToString() instead, if you're looking for anything that might look like an int and can be converted to an int. If you only want things that actually are ints, something like if(value is int number) should work if your c# version is recent. If it's older you may have to if(value is int) and then cast the value inside the if
Your code can be simplified to:
foreach(...){
int.TryParse(value.ToString(), out var n);
integers.Add(n);
}
Or
foreach(...){
if(value is int)
integers.Add((int)value);
else
integers.Add(0);
}
You could simply use:
var ints = listOfItems
.Select(o => { int.TryParse(o.ToString(), out int num); return num;} )
.ToList();
This will work as you wish, as if conversion fails num is 0 by default.
If Try Parse fails number is automatically 0 so you can directly write this
Int32.TryParse(value, out int number)
Integers.Add(number);
Maybe you can find the better way
var intList = objs.ConvertAll(delegate (object obj) { return (int)obj; });
I have a web service function which has a decimal value i.e. BRGEW.
Client is supposed to send the decimal value but he's sending string from SOAP UI and it's failing in conversion.
I have done this to control it but doesn't work.
if (General.BRGEW == 0 || General.BRGEW.ToString() == "") {
General.BRGEW =0;
}
How can I control this?
I guess you need String.IsNullOrEmpty(String) method
Check here
You can try this if you want to check that user input is decimal or not
var check= double.IsNaN(variable); //It will return boolean value after that add your code logic
First you need to check if the value is null or empty, if it is not null or empty then convert it.
decimal number;
string value = "";
if(!String.IsNullOrEmpty(value))
{
if(Decimal.TryParse(value, out number))
{
Console.WriteLine("Converted '{0}' to {1}.", value, number);
}
else
{
Console.WriteLine("Unable to convert '{0}'.", value);
}
}
if (General.BRGEW == 0)
{
General.BRGEW = 0;
}
doesn't change things much :) If RRGEW is already 0, then setting it to zero will have little effect.
A. Make the client send the number
This would be the easiest solution.
B. Deal with it
If you cannot make the client send the number then the following could help:
Make General.BRGEW as string.
Create another property e.g. General.BRGEWAsInt
public class X {
public string BRGEW {get; set;}
public int BRGEWAsInt => Int32.TryParse(BRGEW, out var number)
? number
: 0;
}
You don't need to make a property, you could just parse when you need.
I have an int and a double, but as soon as I try to subtract the integer from the double, the following error is thrown:
Input string was not in a correct format.
Now lets look at the code:
double TotalNoRegis = values.Sum(); // This is a LIST and its = 1569
string otherFe ="600";
double totalafter;
if(otherFe != string.Empty || otherFe!= "") // This part works fine
{
totalafter = TotalNoRegis - Convert.ToInt32(otherFe); // Here the error is thrown
}
What am I doing wrong here? I looked at this Example, which is basically the same thing: int x = 1 and int y = 2 and then int this = x-y;
Please let me know if you know the issue here.
What am I doing wrong here?
Lots.
if(otherFe != string.Empty || otherFe!= "") // This part works fine
That's nonsensical code. string.Empty and "" are the same string.
Instead use
if (!string.IsNullOrEmpty(otherFe))
Moving on:
totalafter = TotalNoRegis - Convert.ToInt32(otherFe); // Here the error is thrown
You claim that the error is the subtraction, but it is not. The problem is in the ToInt32. You are passing some other string than the one you are showing.
The way I like to do this is by making an extension method:
static public class Extensions
{
public static int? ParseAsInteger(this string s) {
if (string.IsNullOrEmpty(s)) return null;
int i;
return int.TryParse(s, out i) ? (int?)i : (int?)null;
}
// Similarly write `ParseAsDouble` and so on.
}
Now you have an extension you can use:
double? totalAfter = TotalNoRegis - otherFe.ParseAsInteger();
(Or ParseAsDouble, or whatever.)
If otherFe was valid, then totalAfter has the total; if it was not, then it is null.
The lesson here is: move the type conversion logic into its own method which you can independently test. Then the logic at the call site of that method becomes simpler and easier to follow.
You should use an integer instead of a double, especially if you don't have a reason to use the double. So to rectify, you could simply do the following.
int total = values.Sum();
var other = "6000";
if(!string.IsNullOrEmpty(other))
if(int.TryParse(other, out int subtractor))
total -= subtractor;
If you require a double, then use but if you don't why bother? Also, you are subtracting fifteen hundred items from six thousand, your total after will always be negative or often be negative. Is that your desired intent?
Something to note, with the TryParse if it fails it'll skip the subtraction rather than fail like parse or convert would do. Also do you want the sum of the list or count?
I'm working with a DNN form-building module that allows for some server-side code to be run based on a condition. For my particular scenario, I need my block of code to run if the first 4 characters of a certain form text are numeric.
The space to type the condition, though, is only one line and I believe gets injected into an if statement somewhere behind the scenes so I don't have the ability to write a mult-line conditional.
If I have a form field called MyField, I might create a simple conditional like this:
[MyField] == "some value"
Then somewhere behind the scenes it gets translated to something like if("some value" == "some value") {
I know that int.TryParse() can be used to determine whether or not a string is numeric but every implementation I've seen requires two lines of code, the first to declare a variable to contain the converted integer and the second to run the actual function.
Is there a way to check to see if the first 4 characters of a string are numeric in just one line that can exist inside an if statement?
Wrap it in an extension method.
public static class StringExtensions
{
public static bool IsNumeric(this string input)
{
int number;
return int.TryParse(input, out number);
}
}
And use it like
if("1234".IsNumeric())
{
// Do stuff..
}
UPDATE since question changed:
public static class StringExtensions
{
public static bool FirstFourAreNumeric(this string input)
{
int number;
if(string.IsNullOrEmpty(input) || input.Length < 4)
{
throw new Exception("Not 4 chars long");
}
return int.TryParse(input.Substring(4), out number);
}
}
And use it like
if("1234abc".FirstFourAreNumeric())
{
// Do stuff..
}
In response to this:
Is there a way to check to see if the first 4 characters of a string are numeric in just one line that can exist inside an if statement?
You guys don't have to make it account for anything more complicated than a positive integer.
new Regex(#"^\d{4}").IsMatch("3466") // true
new Regex(#"^\d{4}").IsMatch("6") // false
new Regex(#"^\d{4}").IsMatch("68ab") // false
new Regex(#"^\d{4}").IsMatch("1111abcdefg") // true
// in an if:
if (new Regex(#"^\d{4}").IsMatch("3466"))
{
// Do something
}
Old answer:
If you can't use TryParse, you could probably get away with using LINQ:
"12345".All(char.IsDigit); // true
"abcde".All(char.IsDigit); // false
"abc123".All(char.IsDigit); // false
If you can, here's an IsNumeric extension method, with usage:
public static class NumberExtensions
{
// <= C#6
public static bool IsNumeric(this string str)
{
float f;
return float.TryParse(str, out f);
}
// C# 7+
public static bool IsNumeric(this string str) => float.TryParse(str, out var _);
}
// ... elsewhere
"123".IsNumeric(); // true
"abc".IsNumeric(); // false, etc
"-1.7e5".IsNumeric(); // true
How about some easy LinQ?
if (str.Take(4).All(char.IsDigit) { ... }