i have a project in which i have assigned some functions to single characters(e.g. Keyboard Key "H" will do high pass filtering).
Now To get "H" as an output i have created a down event which hopefully pick up the keys are down and calls the function with an integer value. However I get an error when i try to compare the input value with an integer value in the function. The following is my code...
public static event DownEventHandler Down;
public static delegate void DownEventHandler(string Key);
Down(FunctionChar((Keys)lParam.Code)); // lParam.code is an integer value.
private string FunctionChar(Keys e)
{
if(e >=65 && e<=90){
if (Control.IsKeyLocked(Keys.CapsLock) || ((Control.ModifierKeys !=0) && (Keys.Shift) != 0))
{
return e.ToString;
}
else
{
return e.ToString.ToLower;
}
}
I assume that this function will give me the output a string either "G" or "g". as mentioned before i want to use it in further functionality.
However it gives me error as following.
Operator '>=' cannot be applied to operands of type 'System.Windows.Forms.Keys' and 'int'
I know one of the solution is to use SWITCH statement but i want to use if statement and not switch.
Can some one tell me - what is the problem? What values does "e" posses and how can i convert it to (Int) so i can use it in the IF statement.
You can't compare System.Windows.Forms.Key with and Integer so you have to convert the key has been converted to an integer before you compare them. here is an example for you:
Keys e = Keys.A;
int keyVal= (int)e;// return 65
So you can do like this:
if((int)e >=65 && (int)e<=90)
{
// your code goes here
}
Another way for doing this is:
if(e >= Keys.A&& e<= Keys.Z)
{
// your code goes here
}
Update :
You can return the corresponding character using : return ((char)e).ToString();
Hence the whole function signature will be like the following:
private string FunctionChar(Keys e)
{
if ((int)e >= 65 && (int)e <= 90)
{
if (Control.IsKeyLocked(Keys.CapsLock) || ((Control.ModifierKeys != 0) && (Keys.Shift) != 0))
{
return ((char)e).ToString();
}
else
{
return ((char)e).ToString().ToLower();
}
}
return "";
}
When working with an enum, such as Keys, it's better design to express any conditions in terms of the enum's values, rather than casting back to ints.
So I'd recommend replacing:
if(e >=65 && e<=90)
with
if (e >= Keys.A && e <= Keys.Z).
This should compile fine - and your intention is clearer to anyone reading your code!
I'd rather not use magic numbers but actual chacraters, and I'd write an extension method(s) for this:
public static class KeysExtensions
{
public static Boolean IsLetter(this Keys value)
{
return value >= Keys.A && value <= Keys.Z;
}
}
So when handling events you can put readable code:
private void Something_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode.IsLetter())
{
// Do your operations here...
}
}
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.
At the top of my form I have:
public static int hoursInt;
public static int minutesInt;
public static int secondsInt;
public static int CompletedIn24;
Then further down I have the following to reset the numericUpDown boxes to zero when selecting a new runner:
private void lstRunners_SelectedIndexChanged(object sender, EventArgs e)
{
Runner selectedRunner = (Runner)lstRunners.SelectedItem;
numericUpDown1.Value = 0;
numericUpDown2.Value = 0;
numericUpDown3.Value = 0;
}
Then in the Finish button click event I have:
hoursInt = Convert.ToInt32(numericUpDown1.Value);
minutesInt = Convert.ToInt32(numericUpDown2.Value);
secondsInt = Convert.ToInt32(numericUpDown3.Value);
if (lstRunners.SelectedIndex > -1 && hoursInt + minutesInt + secondsInt != 0)
{
// Obtain selected climber
Runner selectedRunner = (Runner)lstRunners.SelectedItem;
selectedRunner.Hours = hoursInt;
selectedRunner.Minutes = minutesInt;
selectedRunner.Seconds = secondsInt;
var expertRunner = selectedRunner as Expert;
if (expertRunner != null)
{
expertRunner.UponFinish();
}
Here is my overriden method in Expert : Runner:
public override void UponFinish()
{
base.UponFinish();
// The integer must increment by one if the time is 24:00:00 or less i.e. 23:59:59 would increment the integer as well
if (Hours < 24 || (Hours == 24 && Minutes == 0 && Seconds == 0))
{
CompletedIn24++;
}
}
At present the UponFinish() method in Runner doesn't have anything inside the braces as I'm not sure if anything is required?
I tried to output the CompletedIn24 integer to a string to see if it would work when the button is clicked but the value stayed at zero even if an expert runner was selected and the time was 24:00:00 or less. The integer is not incrementing and I'm not sure what is causing the problem?
Any help would be appreciated.
Simply use the as keyword like this:
var runner = selectedRunner as Expert;
if(runner != null) runner.UponFinish();
If your class Runner already defines some method called UponFinish, you should define this method as virtual and override that method in the derived classes, like this:
public class Runner {
public virtual void UponFinish(){
//...
}
}
public class Expert : Runner {
public override void UponFinish(){
//You talked about the time, I asked for clarification on this
//but it's still very unclear. I suppose when you mean the time is 24:00:00
//that means the hours is 24, the minutes is 0 and the seconds is 0
if(Hours < 24 || (Minutes == 0 && Seconds == 0)) Completedin24++;
}
}
Then of course you don't need any cast, just call UponFinish and the overridden code (if any) will be called correctly:
selectedRunner.UponFinish();
You can check type like this:
if (selectedRunner.GetType() == typeof(Expert))
{
Expert expert = (Expert)selectedRunner;
}
You can do
if(selectedRunner is Expert)
{
UponFinish((Expert)selectedRunner);
//or ((Expert)selectedRunner).UponFinish(); if that was the intention
}
or alternatively
Expert selectedExpert = selectedRunner as Expert;
if(selectedExpert != null)
UponFinish(selectedExpert);
edit:
If your UponFinish function is already part of both Runner and Expert (that is, overridden in Expert), you don't need to cast selectedRunner before calling it.
There are several ways to do this, exists the operator is for example:
Operator IS
You can check if your Runner is an ExpertRunner by using the is keyword:
if(selectedRunner is ExpertRunner)
However, in terms of OOP you should never have to do this, you may want to check your hierarchy or logic why you need to handle this case seperately and not in overridden behaviour (function or properties).
Try this :
if(lstRunners.SelectedItem is Expert)
{
Expert selectedRunner = lstRunners.SelectedItem as Expert;
selectedRunner.UponFinish();
}
if (lstRunners.SelectedItem is Expert)
{
((Expert)lstRunners.SelectedItem).UponFinish();
}
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.
In our application we work with DataTables a lot. This is dictated by the interface to a another system. Often a column in one of these DataTable's is in fact an enumeration, which is then of a Int16 datatype. Currently we use magic constants all over the place, but that isn't pretty. A real enum would be much better, but how can you write an elegant comparison? Especially considering that a DBNull is also sometimes a valid value.
Ideally we would write this:
if ( tbl.Rows[0]["EnumColumn"] == MyEnum.SomeValue )
// Do stuff
But, naturally, that will not work. The closest to what I can come is:
if ( tbl.Rows[0]["EnumColumn"] != DBNull.Value && Convert.ToInt32(tbl.Rows[0]["EnumColumn") == (int)MyEnum.SomeValue )
// DO stuff
Which looks plain ugly. Any ideas on how to make this prettier and easier to write?
It should be something like this:
tbl.Rows[0]["EnumColumn"] != DbNull.Value && Convert.ToInt32(tbl.Rows[0]["EnumColumn"]) == MyEnum.SomeValue
I would make a static method for it:
public enum TestEnum
{
A = 1,
B = 2
}
public static bool EqualsTestEnum(object value, TestEnum enumValue)
{
if (value == null || value == DBNull.Value)
{
return false;
}
int i;
if (int.TryParse(value.ToString(), out i))
{
return i == (int) enumValue;
}
return false;
}
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;
}
}