A method with tryparse using min and max limits - c#

I'm trying to make a method such as this
public static bool GetInteger(string stringToConvert, out int intOutValue, int minLimit, int maxLimit)
I want it to check if the value is within the min and max range that I specify with the in-values. The parsing is just
int.TryParse(stringToConvert, out intOutValue)
but how do I now check if the value of "intOutValue" is within range? It keeps telling me that it is a bool-value...
Any help on how to do this would be greatly appriciated! (I'm pretty new to programming, and especially in c#)

If you're trying to do comparisons based on the result of the call to TryParse then therein lies your problem; that returns a boolean to indicate success or not (hence the Try). So you need to compare the inOutValue as that's what has been populated.
public static bool GetInteger(string input, out int result, int min, int max) {
return int.TryParse(input, out result) && (result >= min && result <= max);
}
There is no need for an out param here, and I'd even say the method naming is bad, unless you actually want the value to be accessible after the fact.

It looks like you want to check if it is also in the given range, as well as a valid int. In which case you could do:
public static bool GetInteger(string stringToConvert, out int intOutValue, int minLimit, int maxLimit)
{
bool parsed = int.TryParse(stringToConvert, out intOutValue);
return parsed && intOutValue >= minLimit && intOutValue <= maxLimit;
}

Related

Lambda Sort on Long Types

I'm trying to run a sort as below but am running into an issue with the Start properties being of type Long in the Lambda expression. When they were of type int this was working correctly but I need this to work over larger values. I've tried casting the a.Start - b.Start to int but this seems to provide an incorrect sort result.
Is there a different method by which I should be sorting or should I change datatypes?
ranges.Sort((a, b) => a.Start - b.Start);
private readonly List<Range> ranges = new List<Range>();
public class Range
{
public Range(long startEnd) : this(startEnd, startEnd)
{
}
public Range(long start, long end)
{
if (end >= start)
{
Start = start;
End = end;
}
else
{
Start = end;
End = start;
}
}
public long Start { get; private set; }
public long End { get; private set; }
public void Update(long newStart, long newEnd)
{
Start = newStart;
End = newEnd;
}
public static implicit operator Range(long i)
{
return new Range(i);
}
}
Function you pass to Sort should:
return anything negative if a < b (can be always -1 for example)
zero if a == b
anything positive if a > b (can be always 1 for example)
Your current function satisfies this criteria (but not safe to use because of potential overflow), but returns long. There are many other functions that satisfy this criteria though. One is already existing comparer for longs:
ranges.Sort((a, b) => a.Start.CompareTo(b.Start));
You can do the same yourself if you'd like (though no reason to):
ranges.Sort((a, b) => a.Start > b.Start ? 1 : a.Start < b.Start ? -1 : 0);
The delegate you pass to the Sort method is a Comparison<T> which must always return an int, whatever the type T it is comparing.
The int returned from this delegate should be:
A signed integer that indicates the relative values of x and y, as
shown in the following table.
Value Meaning
Less than 0 x is less than y.
0 x equals y.
Greater than 0 x is greater than y.
Therefore the fact that it worked when your Start was an int is actually purely coincidental.
You can fix your case by having your delegate return
a.Start.CompareTo(b.Start)
A comparison is supposed to return an int so you need to convert your long to an int somehow. You can either Convert.ToInt32 or, if that might be out of range, simply return -1 for any negative value and 1 for any positive value.
Another, probably better alternative, would be to use the CompareTo method of one of the values for both int and long, which would be functionally equivalent to the second option.
Casting a.Start - b.Start to int seems to work here, however by doing that you expose yourself to overflow errors (what if a.Start is 0 and b.Start is long.MaxValue, for example?). Since Sort only checks if your lambda is returning a positive value, a negative value or zero, you can do just this:
ranges.Sort((a, b) => a.Start > b.Start ? 1 : a.Start < b.Start ? -1 : 0);
Alternatively, LINQ's OrderBy works just fine (and is not limited to Lists), but be aware that it returns a new object rather than modifying the original one, which may or may not be ok for you:
ranges = ranges.OrderBy(r => r.Start).ToList()

Multiple comparison operators

What is the standard way in C# to check if a number is within a range of numbers?
Typically, I would do some variation of this with int i:
return (i >= start && i <= end);
Is there no syntax for something like this:
// does not work
return (start <= i <= end);
The most close to what you expect is
return start <= i && i <= end;
There are no mathematical notations in C#. Operators are functions that return a result. Usually operators are either unary or binary only (i.e. you cannot pass 3 arguments).
One trick you can do is to introduce an extension method:
public static class IntExtensions
{
public static bool WithinRange(this int value, int low, int high)
=> value >= low && value <= high;
}
So the usage would be:
return i.WithinRange(start, end);
This is more verbose, but more obscure at the same time; does it mean to include lower bound? does it mean to include higher bound?
The suggestion is to stick to the syntax that any software developer knows.

How do bool values and variables get sent between classes/forms?

I am having trouble getting a method working and I am not sure I am doing it the correct way. What I want to do is to send a string from a form by a button_click into a class and process it there for errors(tryparse method) and the send a boolvalue back to then either report and error to the user or to print input in an listbox.
This is the form code I have that is supposed to send the string into the class.
private void btnOK_Click(object sender, EventArgs e)
{
Errorcheck.GetDouble(numChoice);
}
and then the Errorcheck class:
public static bool GetDouble(string numChoice, out double value, double minLimit, double maxLimit)
{
while (!double.TryParse(numChoice, out value))
{
if ((value >= minLimit) && (value <= maxLimit))
{
return true;
}
}
return false;
}
How do I retrieve the bool value from the Errorcheck class? if it was ok or not. Am I doing the right way or is there a quicker way to go about it?
private void btnOK_Click(object sender, EventArgs e)
{
double foo;
var myresult = Errorcheck.GetDouble(numChoice, out foo, 1, 2);
//When myresult == true, foo contains the parsed value
}
myresult will contain the result returned by GetDouble either true (value could be parsed and is within limits) or false (value could be parsed but was out of limits or failed to parse in the first place). Also, foo will contain 0 if parsing failed, otherwise the parsed value (which, may or may not!) be within the limits.
I do, however, have some problems with your code. First; why is your class named Errorcheck while, in fact, it doesn't do error-checking (what is that anyway?) but parse a value.
Second, why use the while() construct?
public static bool GetDouble(string numChoice, out double value, double minLimit, double maxLimit)
{
return double.TryParse(numChoice, out value)
&& ((value >= minLimit) && (value <= maxLimit));
}
Third; GetDouble() doesn't actually "get" a "double". It checks if a value is parseable as a double and, if so, is within bounds. It returns a bool for Pete's sake.
EDIT Scratch that; I missed the out on the method signature. It returns a bool and also the value.
...and then some more but I might be nitpicking :P
And, last but not least, I don't see what this has to do with "how bool values and variables get sent between classes/forms"?
Take my, well intended, advice and get a good C# or general book on programming and brush up your basic skills a little. You will only benefit and soon you'll see why your code is, no flame intended, "bad" in many ways.
I would do it like that:
private void btnOK_Click(object sender, EventArgs e)
{
double parsedValue;
if (Errorcheck.IsDoubleBetween(numChoice, out parsedValue, maxValue, minValue))
{
//Your code here
}
}
Errorcheck code:
public static bool IsDoubleBetween(string numChoice, out double value, double minLimit, double maxLimit)
{
bool result = double.TryParse(numChoice, out value) && (value >= minLimit) && (value <= maxLimit);
return result;
}
As you can see, there are a few changes:
The name IsDoubleBetween explains the method logic.
There is a call to IsDoubleBetween with the right parameters.
There is a use of IsDoubleBetween return value.
IsDoubleBetween code is more readable.
In this case i would try to separate the two operations of IsDoubleBetween to two methods so there will be single responsibility to each - parsing and checking between value

Is there a class in C# to handle a couple of INT (range of 2 INT- 1-10)

I am quite new to C# and I was wondering if there is a Class or a data structure or the best way to handle the following requirement...
I need to handle a COUPLE of int that represent a range of data (eg. 1 - 10 or 5-245) and I need a method to verify if an Int value is contained in the range...
I believe that in C# there is a class built in the framework to handle my requirement...
what I need to do is to verify if an INT (eg. 5) is contained in the range of values Eg (1-10) ...
in the case that I should discover that there is not a class to handle it, I was thinking to go with a Struct that contain the 2 numbers and make my own Contain method to test if 5 is contained in the range 1-10)
in the case that I should discover that there is not a class to handle
it, I was thinking to go with a Struct that contain the 2 numbers and
make my own Contain method to test if 5 is contained in the range
1-10)
That's actually a great idea as there's no built-in class for your scenario in the BCL.
You're looking for a range type; the .Net framework does not include one.
You should make an immutable (!) Int32Range struct, as you suggested.
You may want to implement IEnumerable<int> to allow users to easily loop through the numbers in the range.
You need to decide whether each bound should be inclusive or exclusive.
[Start, End) is probably the most obvious choice.
Whatever you choose, you should document it clearly in the XML comments.
Nothing exists that meets your requirements exactly.
Assuming I understood you correctly, the class is pretty simple to write.
class Range
{
public int Low {get; set;}
public int High {get; set;}
public bool InRange(int val) { return val >= Low && val <= High; }
}
A Tuple<int,int> would get you part of the way but you'd have to add an extension method to get the extra behavior. The downside is that the lower- and upper-bounds are implicitly Item1 and Item2 which could be confusing.
// written off-the-cuff, may not compile
public static class TupleExtension
{
public static bool InRange(Tuple<int, int> this, int queryFor)
{
return this.Item1 >= queryFor && this.Item2 <= queryFor;
}
}
You could create an extension if you want to avoid making a new type:
public static class Extensions
{
public static bool IsInRange(this int value, int min, int max)
{
return value >= min && value <= max;
}
}
Then you could do something like:
if(!value.IsInRange(5, 545))
throw new Exception("Value is out of range.");
i think you can do that with an array.
some nice examples and explanation can be found here:
http://www.dotnetperls.com/int-array
Nothing built in AFAIK, but (depending on the size of the range) an Enumerable.Range would work (but be less than optimal, as you're really storing every value in the range, not just the endpoints). It does allow you to use the LINQ methods (including Enumerable.Contains), though - which may come in handy.
const int START = 5;
const int END = 245;
var r = Enumerable.Range(START, (END - START)); // 2nd param is # of integers
return r.Contains(100);
Personally, I'd probably go ahead and write the class, since it's fairly simple (and you can always expose an IEnumerable<int> iterator via Enumerable.Range if you want to do LINQ over it)

Casting using a decimal in C#

private int FindNumber(string sPar)
{
// Get the last number
int len = sPar.Length;
string s = sPar.Substring(len-1);
return new (int)Decimal(s);
}
In this I am getting the error ; required . Can any ine help me on this.
Thank You!
Change your code to this:
private int FindNumber(string sPar)
{
int len = sPar.Length;
string s = sPar.Substring(len - 1);
return Convert.ToInt32(s);
}
Or, even shorter:
private int FindNumber(string sPar)
{
return Convert.ToInt32(sPar.Substring(sPar.Length - 1));
}
I'm not 100% what you are trying to do here, but if you want to get 4 as the result from the string "17894" i guess you want to write it like this with minimum number of changes:
private int FindNumber(string sPar) {
// Get the last number
int len = sPar.Length;
string s = sPar.Substring(len-1);
return int.Parse(s);
}
No reason to include a decimal and parse it to an int if you are only taking one char of the string anyway.
Note that this will give an exception if the last char of the string for any reason is not a number.
what is Decimal(s)? If you mean "parse as a decimal, then cast to int":
return (int)decimal.Parse(s);
If it is known to be an integer, just:
return int.Parse(s);
Actually, since you are only interested in the last digit, you could cheat:
private static int FindNumber(string sPar)
{
char c = sPar[sPar.Length - 1];
if (c >= '0' && c <= '9') return (int)(c - '0');
throw new FormatException();
}
Decimal(s) is not a valid call since Decimal is a type. Try Decimal.Parse(s) instead if you are certain that s is a valid decimal, stored as a string. If not, use Decimal.TryParse instead.
Please take into account different Culture related problems also, check out the overload that takes an IFormatProvider (I think, not sure about the exact name)
Do you just want to parse the digit from the last position in the string?
private int FindNumber(string sPar)
{
return int.Parse(sPar.Substring(sPar.Length - 1));
}
Note that this will fail if (a) the string is null, (b) the string is empty, or (c) the last character of the string isn't a digit. You should add some checking to your method if these situations are likely to be a problem.
The last line is completely wrong.
Your code takes the last char of a string(that i presume is always a number) and cast it to an int.
Do the following
try{
return Int32.Parse(s);
}
catch(Exception e)
{
// manage conversion exception here
}
I suppose you want to convert string to decimal as your code is not very clear.
you can use
Decimal d1;
if(Decimal.TryParse(sPar,out d1))
{
return d1
}
else
{
return 0;
}

Categories

Resources