How to best convert VB6 "Select Case 1067 To 2938..." to C#? - c#

I'm converting some VB6 logic to C# and have encountered the following SELECT/CASE statement.
Select Case ZipCode
Case 1067 To 19417, 35075 To 35085, 48455 To 48465, 55583 To 55596, 67480 To 67551, 75392, 85126, _
93047 To 93059, 21217 To 21739, 35091 To 35096, 48480, 55606 To 55779, 67655 To 67707, 76726 To 76835, _
85221 To 87679, 94315 To 94419, 22844 To 25799, 35102, 48488, 56154 To 56254, 67731 To 67759, 76855 To 76889, _
87719 To 88339, 94428 To 94437, 25868, 35112, 48499 To 48531, 56271, 67824 To 67829, 77761, 88353, 94522, _
25879, 35117, 48653, 56281 To 56299, 69427 To 69429, 77773 To 77776, 88361 To 88364, 94553, 26121 To 26160, _
35216 To 35282, 48720 To 48727, 56321 To 56337, 69437 To 69439, 78048 To 78126, 88368 To 88379, 94559, _
26180 To 26215, 35287 To 35469, 49124 To 49356, 56410 To 56479, 70173 To 71287, 78136 To 79117, 88410, 95028 To 95032, _
26316 To 26389, 35576 To 35768, 49406, 56575, 71332 To 71540, 80331 To 83313, 88481, 95111 To 95152, _
26419, 36110, 49419, 56626 To 56648, 71546 To 71711, 83324 To 83362, 88529, 95176 To 95185, _
26434 To 26441, 36304 To 36358, 49448, 56727 To 56745, 71720 To 72189, 83365 To 83379, 88633, 95188 To 95194, _
26452, 36367 To 36369, 49453, 56751 To 57339, 72250 To 72417, 83413, 88662 To 90491, 95197
The best conversion I can think of is a series of if/then/else statements which map each range, e.g.
if((ZipCode >= 1067 && ZipCode <=19417) ||
(ZipCode >= 35075 && ZipCode <=35085) ||
...
Or is there a better way, e.g. some way to put these range values in a hash/array/collection of some sort?

Assuming you are using 3.5 or above, and have access to extension methods:
If I had that many comparisons I would create a nice method for myself:
public static class IntUtils
{
public static bool InRange(this int value, int low, int high)
{
return value <= low && value <= high;
}
}
Then to use it:
if (zipCode.InRange(1067, 19417) ||
zipCode.InRange(35075, 35085) || ...
If you don't have 3.5 or you don't want to use extension methods:
public static class IntUtils
{
public static bool InRange(int value, int low, int high)
{
return value <= low && value <= high;
}
}
then to use it:
if (IntUtils.InRange(zipCode, 1067, 19417) ||
IntUtils.InRange(zipCode, 35075, 35085) || ...

Maybe you can create extension method on int like:
private static bool Between (this int i, int lower, int upper)
{
return i >= lower && i <= upper;
}
and use it in code like
if ZipCode.Between(1067, 19417) || ZipCode.Between(35075, 35085) || ...
additional thoughts
If you do processing based on this, maybe you can use something along those lines
Dictionary<int[], Action> actionMap = new Dictionary<int[], Action>
{
{new[]{1067,19417}, ProcessA},
{new[]{35075, 35085}, ProcessB}
};
public void ProcessA()
{
// do something;
}
public void ProcessB()
{
// do something else;
}
public void Process(int zipCode)
{
var action = actionMap.FirstOrDefault(a => zipCode >= a.Key[0] && zipCode <= a.Key[1]);
if (action.Value != null)
{
action.Value();
}
}
p.s. Not sure this is 100% working code, wrote it from top of my head
p.p.s. Triead and now I'm quite sure it's working

The method you describe is the literal transformation from VB to C#. However, this is so much data that it seems better off in a configuration file than in the code. If you do that, the easiest way is probably to simply loop through the list with zipcodes and compare them one by one.
A more efficient way would be to sort the zipcodes and do a binary search, or use a hash function or something like that, but I would be surprised if this turns out to be a performance bottleneck.

If you wanted to make some of the given approaches a little more abstract, you could go with an extension method like such:
public static class Utils
{
public static bool InRange<T>(this T value, T low, T high) where T : IComparable
{
return low.CompareTo(value) <= 0 && high.CompareTo(value) >= 0;
}
}

Related

how to find two short numbers in between another short numbers in C#

I am having two short numbers 20101, 20141 if i pass 20121 and 20131 then it should return it is available with in the range. if i pass 20081 and 20091 then it should return false, same for 20142 to 20154.
how to find in between for two short numbers.
bool TestRange (int numberToCheck, int bottom, int top)
{
return (numberToCheck >= bottom && numberToCheck <= top);
}
tried the above but it is working as expected. because in my case i want to check two short numbers in another two short numbers. how to do it
Change the signature to bool TestRange (int[] numbersToCheck, int bottom, int top) and iterate numbersToCheck and return as required
Since I needed to use something like that way too often and I'm lazy, I've written an extension method, to check if any integer is between two values.
public static class IntExtensions
{
public static bool Between(this int value, int lowerBound, int upperBound)
{
return value >= lowerBound && value <= upperBound;
}
}
That way you can easily use it with LinQ as
return Array.All(x => x.Between(integer, integer)); // All numbers must be in range.
return Array.Any(x => x.Between(integer, integer)); // At least one number must be in range.
Or just return the numbers that match the constraint as a new array:
return Array.Where(x => x.Between(integer, integer)).ToArray();
In general case with many (arbitrary number) items to test, I suggest signature modification and Linq:
// If you want to pass many items, pass IEnumerable<T>
bool TestRange(IEnumerable<int> numbersToCheck, int bottom, int top) {
if (null == numberToCheck)
throw new ArgumentNullException("numbersToCheck"); // or return true or false...
return numbersToCheck.All(item => item >= bottom && top <= item);
}
...
if (TestRange(new int[] {20121, 20131}, 20101, 20141)) {...}

Array sorting by two parameters

I'm having a little difficulty with the array.sort. I have a class and this class has two fields, one is a random string the other one is a random number. If i want to sort it with one parameter it just works fine. But i would like to sort it with two parameters. The first one is the SUM of the numbers(from low to high), and THEN if these numbers are equal by the random string that is give to them(from low to high).
Can you give some hint and tips how may i can "merge" these two kinds of sort?
Array.Sort(Phonebook, delegate(PBook user1, PBook user2)
{ return user1.Sum().CompareTo(user2.Sum()); });
Console.WriteLine("ORDER");
foreach (PBook user in Phonebook)
{
Console.WriteLine(user.name);
}
That's how i order it with one parameter.
i think this is what you are after:
sourcearray.OrderBy(a=> a.sum).ThenBy(a => a.random)
Here is the general algorithm that you'll use for comparing multiple fields in a CompareTo method:
public int compare(MyClass first, MyClass second)
{
int firstComparison = first.FirstValue.CompareTo(second.SecondValue);
if (firstComparison != 0)
{
return firstComparison;
}
else
{
return first.SecondValue.CompareTo(second.SecondValue);
}
}
However, LINQ does make the syntax for doing this much easier, allowing you to only write:
Phonebook = Phonebook.OrderBy(book=> book.Sum())
.ThenBy(book => book.OtherProperty)
.ToArray();
You can do this in-place by using a custom IComparer<PBook>. The following should order your array as per your original code, but if two sums are equal it should fall back on the random string (which I've called RandomString):
public class PBookComparer : IComparer<PBook>
{
public int Compare(PBook x, PBook y)
{
// Sort null items to the top; you can drop this
// if you don't care about null items.
if (x == null)
return y == null ? 0 : -1;
else if (y == null)
return 1;
// Comparison of sums.
var sumCompare = x.Sum().CompareTo(y.Sum());
if (sumCompare != 0)
return sumCompare;
// Sums are the same; return comparison of strings
return String.Compare(x.RandomString, y.RandomString);
}
}
You call this as
Array.Sort(Phonebook, new PBookComparer());
You could just do this inline but it gets a bit hard to follow:
Array.Sort(Phonebook, (x, y) => {
int sc = x.Sum().CompareTo(y.Sum());
return sc != 0 ? sc : string.Compare(x.RandomString, y.RandomString); });
... Actually, that isn't too bad, although I have dropped the null checks.

C# converting a decimal to an int safely

I am trying to convert a decimal to an integer safely.
Something like
public static bool Decimal.TryConvertToInt32(decimal val, out int val)
this will return false if it cannot convert to an integer, and true w/ successful output if it can.
This is to avoid catching the OverflowException in decimal.ToInt32 method. What is the easiest way to do this?
Here:
public static bool TryConvertToInt32(decimal val, out int intval)
{
if (val > int.MaxValue || val < int.MinValue)
{
intval = 0; // assignment required for out parameter
return false;
}
intval = Decimal.ToInt32(val);
return true;
}
I would write an extension method for class decimal like this:
public static class Extensions
{
public static bool TryConvertToInt32(this decimal decimalValue, out int intValue)
{
intValue = 0;
if ((decimalValue >= int.MinValue) && (decimalValue <= int.MaxValue))
{
intValue = Convert.ToInt32(decimalValue);
return true;
}
return false;
}
}
You can use it in that way:
if (decimalNumber.TryConvertToInt32(out intValue))
{
Debug.WriteLine(intValue.ToString());
}
Compare the decimal against int.MinValue and int.MaxValue prior to the conversion.
What's wrong with using Int32.TryParse(string) ?
Why are you trying to avoid catching the OverflowException? It is there for a reason and you should totally catch it where you call Decimal.ToInt32(). Exceptions are used widely throughout the framework and users should catch them. The Try methods can help you around them to make code tighter and cleaner, but where the framework doesn't have a suitable method (Decimal.TryConvertToInt32() in this case) catching OverflowException is the appropriate thing to do. It is actually more clear than making an extension class or writing your own separate static method (both of those involve writing your own code where the framework is already giving you this functionality).

Comparing approximate values in c# 4.0?

First of all, please excuse any typo, English is not my native language.
Here's my question. I'm creating a class that represents approximate values as such:
public sealed class ApproximateValue
{
public double MaxValue { get; private set; }
public double MinValue { get; private set; }
public double Uncertainty { get; private set; }
public double Value { get; private set; }
public ApproximateValue(double value, double uncertainty)
{
if (uncertainty < 0) { throw new ArgumentOutOfRangeException("uncertainty", "Value must be postivie or equal to 0."); }
this.Value = value;
this.Uncertainty = uncertainty;
this.MaxValue = this.Value + this.Uncertainty;
this.MinValue = this.Value - this.Uncertainty;
}
}
I want to use this class for uncertain measurments, like x = 8.31246 +/-0.0045 for example and perform calculations on these values.
I want to overload operators in this class. I don't know how to implement the >, >=, <= and < operators... The first thing I thought of is something like this:
public static bool? operator >(ApproximateValue a, ApproximateValue b)
{
if (a == null || b == null) { return null; }
if (a.MinValue > b.MaxValue) { return true; }
else if (a.MaxValue < b.MinValue) { return false; }
else { return null; }
}
However, in the last case, I'm not satisfied with this 'null' as the accurate result is not 'null'. It may be 'true' or it may be 'false'.
Is there any object in .Net 4 that would help implementing this feature I am not aware of, or am I doing the correct way? I was also thinking about using an object instead of a boolean that would define in what circumstances the value is superior or not to another one rather than implementing comparison operators but I feel it's a bit too complex for what I'm trying to achieve...
I'd probably do something like this. I'd implement IComparable<ApproximateValue> and then define <, >, <=, and >= according to the result of CompareTo():
public int CompareTo(ApproximateValue other)
{
// if other is null, we are greater by default in .NET, so return 1.
if (other == null)
{
return 1;
}
// this is > other
if (MinValue > other.MaxValue)
{
return 1;
}
// this is < other
if (MaxValue < other.MinValue)
{
return -1;
}
// "same"-ish
return 0;
}
public static bool operator <(ApproximateValue left, ApproximateValue right)
{
return (left == null) ? (right != null) : left.CompareTo(right) < 0;
}
public static bool operator >(ApproximateValue left, ApproximateValue right)
{
return (right == null) ? (left != null) : right.CompareTo(left) < 0;
}
public static bool operator <=(ApproximateValue left, ApproximateValue right)
{
return (left == null) || left.CompareTo(right) <= 0;
}
public static bool operator >=(ApproximateValue left, ApproximateValue right)
{
return (right == null) || right.CompareTo(left) <= 0;
}
public static bool operator ==(ApproximateValue left, ApproximateValue right)
{
return (left == null) ? (right == null) : left.CompareTo(right) == 0;
}
public static bool operator !=(ApproximateValue left, ApproximateValue right)
{
return (left == null) ? (right != null) : left.CompareTo(left) != 0;
}
This is one of the rare cases where it may make more sense to define a value type (struct), which then eliminates the null case concern. You can also modify MinValue and MaxValue to be computed properties (just implement a get method that computes the result) rather than storing them upon construction.
On a side note, comparison of approximate values is itself an approximate operation, so you need to consider the use cases for your data type; are you only intending to use comparison to determine when the ranges are non-overlapping? It really depends on the meaning of your type. Is this intended to represent a data point from a normally distributed data set, where the uncertainty is some number of standard deviations for the sampling? If so, it might make more sense for a comparison operation to return a numeric probability (which couldn't be called through the comparison operator, of course.)
It looks to me like you need to check if a.MaxValue == b.MinValue also, in your current implementation that would return null, which seems incorrect, it should either return true or false based on how you want the spec to actually work. I'm not sure of any built in .net functionality for this, so I believe you are going about it the correct way.
return a.Value - a.Uncertainty > b.Value + b.Uncertainty
I wouldn't really mess with the semantics of >: I think bool? is a dangerous return type here. That said, given the uncertainty, you could return true, if a is more likely to be > b.
It seems to me that you're trying to implement some form of Ternary Logic because you want the result of applying the operators to be either True, False or Indeterminate. The problem with doing that is that you really cannot combine the built-in boolean values with your indeterminate value. So whilst you could do some limited form of comparison of two ApproximateValues I think that it's inappropriate to use bool as the result of these comparisons because that implies that the result of the comparisons can be freely combined with other expressions that result in bool values, but the possibility of an indeterminate value undermines that. For example, it makes no sense to do the following when the result of operation on the left of the OR is indeterminate.
ApproximateValue approx1 = ...;
ApproximateValue approx2 = ...;
bool result = ...;
bool result = approx1 > approx2 || someBool;
So, in my opinion, I don't think that it's a good idea to implement the comparisons as operators at all if you want to retain the indeterminacy. The solutions offered here eliminate the indeterminacy, which is fine, but not what was originally specified.

How to force a number to be in a range in C#? [duplicate]

This question already has answers here:
Where can I find the "clamp" function in .NET?
(11 answers)
Closed 6 years ago.
In C#, I often have to limit an integer value to a range of values. For example, if an application expects a percentage, an integer from a user input must not be less than zero or more than one hundred. Another example: if there are five web pages which are accessed through Request.Params["p"], I expect a value from 1 to 5, not 0 or 256 or 99999.
I often end by writing a quite ugly code like:
page = Math.Max(0, Math.Min(2, page));
or even uglier:
percentage =
(inputPercentage < 0 || inputPercentage > 100) ?
0 :
inputPercentage;
Isn't there a smarter way to do such things within .NET Framework?
I know I can write a general method int LimitToRange(int value, int inclusiveMinimum, int inlusiveMaximum) and use it in every project, but maybe there is already a magic method in the framework?
If I need to do it manually, what would be the "best" (ie. less uglier and more fast) way to do what I'm doing in the first example? Something like this?
public int LimitToRange(int value, int inclusiveMinimum, int inlusiveMaximum)
{
if (value >= inclusiveMinimum)
{
if (value <= inlusiveMaximum)
{
return value;
}
return inlusiveMaximum;
}
return inclusiveMinimum;
}
This operation is called 'Clamp' and it's usually written like this:
public static int Clamp( int value, int min, int max )
{
return (value < min) ? min : (value > max) ? max : value;
}
A much cleaner method that will work with more than just integers (taken from my own library of shared code):
public static T Clamp<T>(T value, T min, T max) where T : IComparable<T>
{
if (value.CompareTo(min) < 0)
return min;
if (value.CompareTo(max) > 0)
return max;
return value;
}
I see Mark's answer and raise it by a this:
public static class InputExtensions
{
public static int LimitToRange(
this int value, int inclusiveMinimum, int inclusiveMaximum)
{
if (value < inclusiveMinimum) { return inclusiveMinimum; }
if (value > inclusiveMaximum) { return inclusiveMaximum; }
return value;
}
}
Usage:
int userInput = ...;
int result = userInput.LimitToRange(1, 5)
See: Extension Methods
I like Guffa's answer, but I am surprised that no one has yet posted a solution using Min/Max.
public int LimitInclusive(int value, int min, int max)
{
return Math.Min(max, Math.Max(value, min));
}
An alternative way to write your LimitToRange function is as follows.
public int LimitToRange(int value, int inclusiveMinimum, int inclusiveMaximum)
{
if (value < inclusiveMinimum) { return inclusiveMinimum; }
if (value > inclusiveMaximum) { return inclusiveMaximum; }
return value;
}
I think this is a little easier to understand while still being efficient.
No, there isn't any method for that built in the framework. I suppose that it was left out because you already have Min and Max, so you can accomplish it using them.
If you write your own method for it, it doesn't matter much how you write it. If you use if statements or the conditional operator ?, it will still compile to pretty much the same code anyway.
To clamp values without giving users any feedback that the value entered by them is wrong, in general, might not be a great idea (IMHO). This might lead to subtle bugs later, which are difficult to debug, especially when min/max values are determined at run time.
Think of this. You have $100 in your bank account, and you want to transfer $150 to your friend. Would you like your banking system to throw an InsufficientFundsException or get into a discussion with your friend that you transferred $150 but he received only $100 (assuming the bank clamped the transfer amount to 100 since your did not have sufficient funds)
That being said, you should also look at code contracts.
public void MyFunction (Type input)
{
Contract.Requires(input > SomeReferenceValue);
Contract.Requires (input < SomeOtherReferencValue);
}
This will force the user input to be within the range.
I like the Clamp name. I would suggest the following class
public class MathHelper
{
public static int Clamp (int value,int min,int max)
{
// todo - implementation
}
public static float Clamp (float value,float min,float max)
{
// todo - implementation
}
)
or if you want to use generics, then
public class MathHelper
{
public static T Clamp<T> (T value, T min, T max) where T : IComparable
{
// todo - implementation
T output = value;
if (value.CompareTo(max) > 0)
{
return max;
}
if (value.CompareTo(min) < 0)
{
return min;
}
return output;
}
}

Categories