Change value of Enum - c#

I am reading about Enums and came across an example where the writer showed how we can typecast an enum to int and an int to an enum. However I didnt get how can we change the value of an enumeration by creating a reference of type TrickScore.
public enum TrickScore {
Sit = 7,
Beg = 25,
RollOver = 50,
Fetch = 10,
ComeHere = 5,
Speak = 30,
}
This code block changes the value of Fetch enumeration. I am unable to understand how score gets set to TrickScore.Fetch. When I call score.ToString(), it returns Fetch.
int value = (int)TrickScore.Fetch * 3;
MessageBox.Show(value.ToString());
TrickScore score = (TrickScore)value;
MessageBox.Show(score.ToString());

I'm afraid your understanding of enums is not quite right. This line of code:
int value = (int)TrickScore.Fetch * 3;
doesn't change value of TrickScore.Fetch. It takes the value of TrickScore.Fetch (10) multiplies it by 3 and assigns it to a variable value. In this case you are using TrickScore.Fetch almost as if it were a variable that keeps a number. When you have something like y = x * 5 you don't change a value of x. Only assigning the result to y.
Next line in your code that does something is this one:
TrickScore score = (TrickScore)value;
So you have your variable value (30) from previous operation. You cast the value to TrickScore enum type. The item with this number is Speak and it is assigned to the score variable.
One thing worth noting is that only because enum inherits from int doesn't mean it's a good practice to perform arithmetic operations on enums. I'd avoid casting them on ints and performing mathematical operations. After all does it really make sense to add up TrickScore.Beg and TrickScore.ComeHere and expect it to result in TrickScore.Speak?

Related

Using public integers in C#, make a formula for incremental numbers based on the dynamic ever increasing number

I'm trying to make a number that increases by a different amount every time (increment), but the value of that number is not random. It follows an equation which has only 1 dynamic integer, being the "everincreasing" one. But I've run into a snag as I'm trying to make my WFA do this in a public int. And it's giving me an error on my everincreasing in the formula.
This number is to be used as an incremental number to add on everytime it runs. And everytime it runs, it adds 1 to the everincreasing.
public partial class Form1 : Form
{
public int everincreasing = 1;
public int increment = Convert.ToInt32(Math.Floor(everincreasing + 300 * Math.Pow(2, everincreasing / 7)));
}
When I hover over everincreasing the error tooltip says: A field initializer cannot reference the non-static field, method, or property 'Form1.everincreasing'
I looked for this exception on the msdocs for c# and I was unable to find how to fix it, so I'm here asking the question I couldn't figure out how to fix in msdocs.
good explanation on that error from this SO answer -
This happens because - You cannot use an instance variable to
initialize another instance variable. Why? Because the compiler can
rearrange these - there is no guarantee that reminder will be
initialized before defaultReminder, so the above line might throw a
NullReferenceException.
In other words you can't use your everincreasing variable here:
public int increment = Convert.ToInt32(Math.Floor(everincreasing + 300 * Math.Pow(2, everincreasing / 7)));
because there is no guarantee that it will be initialized before your increment variable.
I would rather try use a method to achieve this if possible e.g.
public int Increment()
{
return Convert.ToInt32(Math.Floor(everincreasing + 300 * Math.Pow(2, everincreasing / 7)));
}
or increment your value in the form constructor:
public Form1()
{
increment = Convert.ToInt32(Math.Floor(everincreasing + 300 * Math.Pow(2, everincreasing / 7)));
}

.NET equivalent of Java's TreeSet.floor & TreeSet.ceiling

As an example, there's a Binary Search Tree which holds a range of values. Before adding a new value, I need to check if it already contains it's 'almost duplicate'. I have Java solution which simply performs floor and ceiling and further condition to do the job.
JAVA: Given a TreeSet, floor() returns the greatest element in this set less than or equal to the given element; ceiling() returns the least element in this set greater than or equal to the given element
TreeSet<Long> set = new TreeSet<>();
long l = (long)1; // anything
Long floor = set.floor(l);
Long ceil = set.ceiling(l);
C#: Closest data structure seems to be SortedSet<>. Could anyone advise the best way to get floor and ceil results for an input value?
SortedSet<long> set = new SortedSet<long>();
The above, as mentioned, is not the answer since this is a tree we expect logarithmic times. Java's floor and ceiling methods are logarithmic. GetViewBetween is logarigmic and so are Max and Min, so:
floor for SortedSet<long>:
sortedSet.GetViewBetween(long.MinValue, num).Max
ceiling for SortedSet<long>:
sortedSet.GetViewBetween(num, long.MaxValue).Min
You can use something like this. In Linq there is LastOrDefault method:
var floor = sortedSet.LastOrDefault(i => i < num);
// num is the number whose floor is to be calculated
if (! (floor < sortedSet.ElementAt(0)))
{
// we have a floor
}
else
// nothing is smaller in the set
{
}

SQLCommand.Parameters.Add - How to give decimal value size?

How would you specify this:
Decimal(18,2)
In this:
SqlComm.Parameters.Add("#myValue", SqlDbType.Decimal, 0, "myValue");
Currently I have defined precision = 2 from the design side properties. I'm just curious as to how to accomplish this from the code. Thanks
There's not an overload of Add that lets you set the decimal precision inline, so you either need to create a SQlParameter object and add it to the collection:
SqlParameter param = new SqlParameter("#myValue", SqlDbType.Decimal);
param.SourceColumn = "myValue";
param.Precision = 18;
param.Scale = 2;
SqlComm.Parameters.Add(param);
or keep a reference to the parameter after adding it:
SqlParameter param = SqlComm.Parameters.Add("#myValue", SqlDbType.Decimal, 0, "myValue");
param.Precision = 18;
param.Scale = 2;
or using the parameter constructor:
SqlComm.Parameters.Add(new SqlParameter(
parameterName = "#myValue",
dbType = SqlDbType.Decimal,
precision = 18,
scale = 2,
sourceColumn = "myValue"));
var cmd = new SqlCommand()
SetDecimalParameter(cmd.Parameters.Add("#paramName", SqlDbType.Decimal), 18, 2).Value = 12.34;
SqlParameter SetDecimalParameter(SqlParameter parameter, byte precision, byte scale) {
parameter.Precision = precision;
parameter.Scale = scale;
return parameter;
}
My answer is not directly connected with the OP's question, but I've seen a lot of people asking "why set the precision since it is taken from the value".
It has to do with the way SQL Server works when comparing the decimal parameter with the text column. Imagine you have column named strNumberColumn witch is of nvarchar type. If you define a #var Decimal(1,0) = '1', comparison on the condition where strNumberColumn >= #var will work only as long, as the longest entry in that column is between "0" and "9". If any of the entries go beyond, for example "10" or "123" you will get an OverflowException while converting string to decimal. What is important, that conversion is made "behind the scenes".
Please, do not bring arguments like "if that column should contain numbers it should not be made nvarchar" - I totally agree, but that is beyond the scope of the problem (sometimes you work with a legacy system and you have no influence over the column datatype). The above example shows a real life scenario when defining precision is required in order for the query to run successfully despite having a smaller precision amount assigned to the variable (like #var Decimal(12,2) = '1.0').

C# getting first digit of int in custom class

I am trying to build a help function in my guess the number game, whereby the user gets the first digit of the number he/she has to guess. So if the generated number is 550, he will get the 5.
I have tried a lot of things, maybe one of you has an idea what is wrong?
public partial class Class3
{
public Class3()
{
double test = Convert.ToDouble(globalVariableNumber.number);
while (test > 10)
{
double firstDigit = test / 10;
test = Math.Round(test);
globalVariableNumber.helpMe = Convert.ToString(firstDigit);
}
}
}
Under the helpButton clicked I have:
private void helpButton_Click(object sender, EventArgs e)
{
label3.Text = globalVariableNumber.helpMe;
label3.AutoSize = true;
That is my latest try, I putted all of this in a custom class. In the main I putted the code to show what is in the helpMe string.
If you need more code please tell me
Why not ToString the number and use Substring to get the first character?
var number = 550;
var result = number.ToString().Substring(0, 1);
If for some reason you dont want to use string manipulation you could do this mathematically like this
var number = 550;
var result = Math.Floor(number / Math.Pow(10, Math.Floor(Math.Log10(number))));
What's wrong - you have an infinite while loop there. Math.Round(test) will leave the value of test unchanged after the first iteration.
You may have intended to use firstDigit as the variable controlling the loop.
Anyway, as suggested by others, you can set helpMe to the first digit by converting to a string and using the first character.
As an aside, you should consider supplying the number as a parameter and returning the helpMe string from the method. Your current approach is a little brittle.
The problem with your code is that you are doing the division and storing that in a separate variable, then you round the original value. That means that the original value only changes in the first iteration of the loop (and is only rounded, not divided), and unless that happens to make the loop condition false (i.e. for values between 10 and 10.5), the loop will never end.
Changes:
Use an int intead of a double, that gets you away from a whole bunch of potential precision problems.
Use the >= operator rather than >. If you get the value 10 then you want the loop to go on for another iteration to get a single digit.
You would use Math.Floor instead of Math.Round as you don't want the first digit to be rounded up, i.e. getting the first digit for 460 as 5. However, if you are using an integer then the division truncates the result, so there is no need to do any rounding at all.
Divide the value and store it back into the same variable.
Use the value after the loop, there is no point in updating it while you still have multiple digits in the variable.
Code:
int test = (int)globalVariableNumber.number;
while (test >= 10) {
test = test / 10;
}
globalVariableNumber.helpMe = test.ToString();
By using Math.Round(), in your example, you're rounding 5.5 to 6 (it's the even integer per the documentation). Use Math.Floor instead, this will drop the decimal point but give you the number you're expecting for this test.
i.e.
double test = Convert.ToDouble(globalVariableNumber.number);
while (test > 10)
{
test = Math.Floor(test / 10);
globalVariableNumber.helpMe = Convert.ToString(firstDigit);
}
Like #Sam Greenhalgh mentions, though, returning the first character of the number as a string will be cleaner, quicker and easier.
globalVariableNumber.helpMe = test >= 10
? test.ToString().SubString(0, 1)
: "Hint not possible, number is less than ten"
This assumes that helpMe is a string.
Per our discussion in the comments, you'd be better off doing it like this:
private void helpButton_Click(object sender, EventArgs e)
{
label3.Text = GetHelpText();
label3.AutoSize = true;
}
// Always good practice to name a method that returns something Get...
// Also good practice to give it a descriptive name.
private string GetHelpText()
{
return test >= 10 // The ?: operator just means if the first part is true...
? test.ToString().SubString(0, 1) // use this, otherwise...
: "Hint not possible, number is less than ten" // use this.
}

Average speed wpf

i'm trying to do a average speed of bugs killed per min. This is my code now but its throwing an error saying string input format is wrong. Any advice? I'm using C# for WPF.
//Score is the number of bugs hit
score.Text = (_killings * 1).ToString();
//Change it to integer
int x = Int32.Parse(score.Text);
int y = Int32.Parse(TBCountdown.Text); - this is where the error is showing
//Get the average speed by dividing number of bugs hit during the time
int average = (x / y);
//Displaying the average score by converting int to string
averagescore.Text = average.ToString();
For more information, i'm using a dispatcher timer and this is my code for the timer.
TBCountdown.Text = string.Format("00:0{0}:0{1}", time / 60, time % 60);
There are a couple of things that are wrong with your code, I am presuming that you are incrementing a variable and using it to create an elapsed time of some sort. The first thing to state is that Ed S. is correct and you should not be using your UI to store your value, create a backing variable and work with that. As far as your issues: the first one that comes to mind that I mentioned in my comments is that you are trying to convert a string that looks like a TimeSpan to an integer, the second is that your Format String will not convert to a DateTime Object it comes up with a Format Exception Error. I was able to get your code to work by changing your Timer's Tick eventhandler to this.
DateTime temp = DateTime.Parse(string.Format("00:{0}:{1}", time / 60, time % 60));
TBCountdown.Text = temp.ToString("00:mm:ss");
and you can use something like this to get your Y value (you did not respond to me about what information you were wanting for value)
int y = (int)TimeSpan.Parse(TBCountdown.Text).TotalSeconds;
There is a lot of conjecture here about what you want, if this isn't correct please let us know.
This is how you format the textbox:
TBCountdown.Text = string.Format("00:0{0}:0{1}", time / 60, time % 60);
And then you try to parse that as an int. Well, it's not an int. Parse it back as a DateTime or, better yet, just use the variable you already have (time). In general it is a poor idea to rely on your UI for storing your data. The UI is for display.
int y = time;
TBCountdown.Text = string.Format("00:0{0}:0{1}", (time / 60).ToString(), (time % 60).ToString());
remember this is a string function

Categories

Resources