Nullable Long switch statement not producing expected output in VS2015 - c#

I'm seeing some strange behavior when using a nullable long switch statement in VS2015 Update 1 that I'm not seeing in other Visual Studio releases where it runs as expected.
class Program
{
static void Main(string[] args)
{
NullableTest(-1);
NullableTest(0);
NullableTest(1);
NullableTest(2);
NullableTest(null);
}
public static void NullableTest(long? input)
{
string switch1;
switch (input)
{
case 0:
switch1 = "0";
break;
case 1:
switch1 = "1";
break;
default:
switch1 = "d";
break;
}
string switch2;
switch (input)
{
case -1:
switch2 = "-1";
break;
case 0:
switch2 = "0";
break;
case 1:
switch2 = "1";
break;
default:
switch2 = "d";
break;
}
string ifElse;
if (input == 0)
{
ifElse = "0";
}
else if (input == 1)
{
ifElse = "1";
}
else
{
ifElse = "d";
}
Console.WriteLine("Input = {0}, Switch 1 output = {1}, Switch 2 output = {2}, If Else = {3}", input, switch1, switch2, ifElse);
}
This sample code produces the following output (Aligned for readability):
Input = -1, Switch 1 output = d, Switch 2 output = d, If Else = d
Input = 0, Switch 1 output = 0, Switch 2 output = d, If Else = 0
Input = 1, Switch 1 output = d, Switch 2 output = d, If Else = 1
Input = 2, Switch 1 output = d, Switch 2 output = d, If Else = d
Input = , Switch 1 output = d, Switch 2 output = d, If Else = d
I'm only observing this behavior with Nullable types. Non-nullable types work as expected.
Note that this is not the same behavior that's in this question, and is not caused by this compiler bug that's been fixed in VS2015 Update 1. I've verified that both of those examples run correctly.

It looks like this is caused by this bug, and was fixed with this pull request.
I've tried a recent build of Roslyn and the sample code in the question works as expected now.
Here is the updated version of MSBuild Tools 2015 that has corrected the issue.

This is a bug. I believe it must be a left over of the same bug. You better replace your code with an If to avoid any unexpected behavior.

Related

How can this switch statement be changed to a switch expression?

public class ChineseZodiac
{
public static void Main(String[] args)
{
Console.Write("Enter a year: ");
var year = Convert.ToInt64(Console.ReadLine());
switch (year % 12)
{
case 0:
Console.WriteLine("monkey");
break;
case 1:
Console.WriteLine("rooster");
break;
case 2:
Console.WriteLine("dog");
break;
case 3:
Console.WriteLine("pig");
break;
case 4:
Console.WriteLine("rat");
break;
case 5:
Console.WriteLine("ox");
break;
case 6:
Console.WriteLine("tiger");
break;
case 7:
Console.WriteLine("rabbit");
break;
case 8:
Console.WriteLine("dragon");
break;
case 9:
Console.WriteLine("snake");
break;
case 10:
Console.WriteLine("horse");
break;
case 11:
Console.WriteLine("sheep");
break;
}
}
}
I'm trying to get the formula in the switch statement block to output a zodiac sign based on the user's input. I'm also supposed to have the switch statement converted to a switch expression with the same results. I was able to run it without any errors in VS Code as a switch statement but I'm confused about the difference between a switch statement and a switch expression.
Switch expressions return a value, so you couldn't do exactly what you're doing now (since the action is happening within the switch), but you could use it to return the string and then display it:
var yearMod12 = year % 12;
var yearOf = yearMod12 switch
{
0 => "monkey",
1 => "rooster",
...
};
Console.WriteLine(yearOf);
An enum or Dictionary<int, string> would be a good choice for this type of mapping as well.
I suggest extracting model (animals) into a collection; try keeping data and actions separatedly:
public class ChineseZodiac {
// Model (data): Zodiac animals
private static readonly IReadOnly<string> s_Animals = new string[] {
"monkey", "rooster", "dog",
"pig", "rat", "ox",
"tiger", "rabbit", "dragon",
"snake", "horse", "sheep",
};
// An action which is based on the model
public static void Main(String[] args) {
Console.Write("Enter a year: ");
Console.WriteLine(s_Animals[int.Parse(Console.ReadLine()) % s_Animals.Count]);
}
}

Calculator shows an error: 'Input string was not in a correct format.'

I'm trying to make a calculator, and I'm kinda stuck at the mod and exp operations, whenever I try to use them I get below error:
System.FormatException: 'Input string was not in a correct format.'
This is the event in which the error happens :
private void Equal_Click(object sender, EventArgs e)
{
switch (operationPerf)
{
case "+":
TB.Text = (result + Double.Parse(TB.Text)).ToString();
CO.Text = "";
break;
case "-":
TB.Text = (result - Double.Parse(TB.Text)).ToString();
CO.Text = "";
break;
case "*":
TB.Text = (result * Double.Parse(TB.Text)).ToString();
CO.Text = "";
break;
case "/":
TB.Text = (result / Double.Parse(TB.Text)).ToString();
CO.Text = "";
break;
case "Mod":
TB.Text = (result % Double.Parse(TB.Text)).ToString();
CO.Text = "";
break;
case "Exp":
TB.Text = Math.Exp(Double.Parse(TB.Text) * Math.Log((result) * 4)).ToString();
CO.Text = "";
break;
default:
break;
}
result = Double.Parse(TB.Text); // Here is where the error happens
CO.Text = "";
}
Probably operationPerf is none of the expected operators, so the default case is executed and the textbox still contains the original expression (e.g. "23Exp3"), which, of course, cannot be converted to a double.
You should really separate the calculator logic from input and output. Create a Calculator class in a separate code file (Calculator.cs)
public class Calculator
{
public double Result { get; set; }
public void Calculate(string operation, double operand)
{
switch (operation)
{
case "+":
Result = Result + operand;
break;
case "-":
Result = Result - operand;
break;
case "*":
Result = Result * operand;
break;
case "/":
Result = Result / operand;
break;
case "Mod":
Result = Result % operand;
break;
case "Exp":
Result = Math.Exp(operand * Math.Log(Result * 4));
// Did you want this instead?
// Result = Math.Pow(Result, operand);
break;
default:
break;
}
}
}
It is easier to understand, as it does only contain pure math and does not require any parsing or formatting.
In a form field (at the top of the form class) you can then declare
public partial class Form1 : Form
{
private Calculator _calculator = new Calculator();
...
}
The event handler is the easier too
private void Equal_Click(object sender, EventArgs e)
{
if (Double.TryParse(TB.Text, out double operand)) {
_calculator.Calculate(operationPerf, operand);
TB.Text = _calculator.Result.ToString();
CO.Text = "";
} else {
MsgBox.Show("The TextBox does not contain a number");
}
}
If the textbox still contains "23Exp3", you will not be able to convert it to a double. Either use different textboxes to enter the operation, the operator (a number) and the result, or separate the string into its three parts (the 2 numbers and the operation).
I really don't understand the logic behind Math.Exp(operand * Math.Log(Result * 4)). Since I do not know the expected behavior, I cannot give you any advice. Did you want to use Math.Pow instead?
public static double Pow(double x, double y)
Returns a specified number raised to the specified power.
See: Math.Pow Method (Double, Double)
You are asking the user to enter something like this: 10Exp3. And you expect your program to raise 10 to the power of 3 and then show the result. So you expect 1000 in this case. But you are simply doing this:
case "Exp":
TB.Text = Math.Exp(Double.Parse(TB.Text) * Math.Log((result) * 4)).ToString();
First issue with your code is, you are using Exp because this is the documentation for Exp:
Returns e raised to the specified power.
Do you want e raised to the specified power? No you do not. So you cannot use that method. But even if you could and wanted to (and maybe you do want e), the computer cannot convert 10Exp3 to a number--you have to tell it what to do.
Here is how (Read my comments inline for more clarity):
var input = "10Exp3";
// Let's split the numbers using <Exp>
var splits = input.Split(new[] { "Exp" }, StringSplitOptions.None);
// Let's try and convert the first part into a double and see if it works
double numberBase = 0;
if (!double.TryParse(splits[0], out numberBase))
{
// The part before the word Exp is
// not a number, perhaps show an error to the user in a message box
}
// Now let's try and convert the second part
double exponent = 0;
if (!double.TryParse(splits[1], out exponent))
{
// The part after the word Exp is
// not a number, perhaps show an error to the user in a message box
}
// Now we will call the Pow method or use Math.Exp if you want e
double result = Math.Pow(numberBase, exponent);

Regex Error in Switch Statements

I want to create a program that takes in a string and output just the numbers, hopefully using regex to save effort, here is the following code i have
public void main{
string str = "abc-123.44def";
string output = "";
bool setA = false;
StringBuilder stb = new StringBuilder();
for(int i=0; i<str.Length; i++){
switch(str[i]){
case 'b':
setA = foo();
break;
case 'c':
foo2();
break;
case '\d':
case '-':
case '.':
if(setA){
stb.Append(str[i]);
}
break;
default:
break;
}
}
output = stb.toString();
}
public void foo(){
return true;
}
Problem is, the editor gives me a error saying
Unrecognized Escape Sequence
on the '\d' part. Ive seen online sample codes where such usage is allowed so im not sure why my editor is not accepting this. Can someone explain to me what the problem is and how to solve it?
EDIT: It seems like my sample was alittle misleading. I cannot just take out the numbers from the strings by itself since other characters in the string calls different functions and the number characters i want to take out depends on some of them. I updated the code to correct the misinformation.
You can use the Char.IsDigit() to check if a char is a digit (as I mentioned in my first comment):
string str = "abc-123.44def";
string output = "";
bool setA = false;
StringBuilder stb = new StringBuilder();
for(int i=0; i<str.Length; i++){
switch(str[i]){
case 'b':
setA = foo();
break;
case 'c':
foo2();
break;
// case '\d': REMOVE IT
case '-':
case '.':
if(setA){
stb.Append(str[i]);
}
break;
default:
if (Char.IsDigit(str[i])) stb.Append(str[i]); // Add this
break;
}
}
output = stb.ToString();
}
Result:
Is this what you are looking for ?
Regex r = new Regex(#"\d+");
string s = "abc-123.44def";
var matches = r.Matches(s);
List<string> numbersOnly = new List<string>();
foreach (Match match in matches)
numbersOnly.Add(match.Value);
foreach (var number in numbersOnly)
Console.WriteLine(number);
//output:
//123
//44

C#, how to make list<int> and functional if statements [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I am a novice C# user, and I am experimenting with lists in Csharp's console application. This list contains 10 numbers, and the order of these numbers are randomized. What I want to do is to make specific text for a specific number which if statements will handle.
For example: If number == 0, the text "Hello" will show up. Or if the number == 3, the text "Goodbye" will show up.
I tried a few things but I got problems like repeated text: http://i.imgur.com/8sCbeLn.jpg?1
Random r = new Random();
int tempValue;
List<int> number = new List<int>();
number.Add(0);
number.Add(1);
number.Add(2);
number.Add(3);
number.Add(4);
number.Add(5);
number.Add(6);
number.Add(7);
number.Add(8);
number.Add(9);
for (int i = 0; i < 10; i++)
{
tempValue = r.Next(0, number.Count);
Console.WriteLine(number[tempValue]);
number.RemoveAt(tempValue);
Console.ReadLine();
}
Please help me getting on the right track.
You can for example use a switch to select strings from a value.
If you get repeated values, I suspect that you used tempValue to select the string, you have to use number[tempValue]:
string text = null;
switch (number[tempValue]) {
case 0: text = "Hello"; break;
case 1: text = "How do you do"; break;
case 2: text = "Howdie"; break;
case 3: text = "Goodbye"; break;
case 4: text = "Bye"; break;
case 5: text = "Hello again"; break;
case 6: text = "Good day"; break;
case 7: text = "Have fun"; break;
case 8: text = "Greatings"; break;
case 9: text = "Goodbye again"; break;
}
Why not add 10 random numbers to a list and then loop through the list, and print using you if statements
Random r = new Random();
List<int> nums= new List<int>();
int numForList = r.Next(0,10);
bool numInList = true;
//add 10 random numbers to a list
for(int i=0;i<10;i++)
{
do
{
if(!nums.Contains(numForList))
{
numInList = false;
nums.Add(numForList);
}
else
{
numForList = r.Next(0,10);
}
} while (numInList == true);
numInList = true;
}
foreach(var num in nums)
{
switch (num)
{
case 0: Console.WriteLine("Hello"); break;
case 1: Console.WriteLine("How do you do"); break;
... //Add more cases here for each possible random number
}
}

not recognizing a declared variables in c#.net

The last but 3rd line of code is not recognizing variables that I have declared and filled with strings.
static void Main(string[] args)
{
string inputNumber = "1979";
string input1 = inputNumber.Substring(0, 1);
string input2 = inputNumber.Substring(1, 1);
string input3 = inputNumber.Substring(2, 1);
string input4 = inputNumber.Substring(3, 1);
int intInput1;
int intInput2;
int intInput3;
int intInput4;
intInput1 = Convert.ToInt32(input1);
intInput2 = Convert.ToInt32(input2);
intInput3 = Convert.ToInt32(input3);
intInput4 = Convert.ToInt32(input4);
string stringOutput1;
string stringOutput2;
string stringOutput3;
string stringOutput4;
// 1000 Input.
switch (intInput1)
{
case 1:
stringOutput1 = "M";
break;
default:
break;
}
//100 Input
switch (intInput2)
{
case 9:
stringOutput2 = "CM";
break;
default:
break;
}
//10 Input
switch (intInput3)
{
case 7:
stringOutput3 = "LXX";
break;
default:
break;
}
//1 Input
switch (intInput4)
{
case 9:
stringOutput4 = "IX";
break;
default:
break;
}
//Use of unassigned local variable error is showing for 'stringOutput1', 'stringOutput2', 'stringOutput3' and 'stringOutput4'
Console.WriteLine("{0} is {1}{2}{3}{4} in Roman Numerals",inputNumber, stringOutput1, stringOutput2, stringOutput3, stringOutput4);
Console.CursorVisible = false;
Console.ReadKey();
}
P.S. I know that the variables are being filled by commenting out
Console.WriteLine("{0} is {1}{2}{3}{4} in Roman Numerals",inputNumber, stringOutput1, stringOutput2, stringOutput3, stringOutput4);
and using break point and stepping over the code.
This is because your variables might not have been assigned anything yet. Variables must be guaranteed to have been assigned something before they can be used. As a simple fix, you can use declarations like this:
string stringOutput1 = "";
Try assigning nulls to the declarations
string stringOutput1 = null;
string stringOutput2 = null;
string stringOutput3 = null;
string stringOutput4 = null;
You have to initialize your variables, do it like this.
string stringOutput1 , stringOutput1, stringOutput3, stringOutput4 = string.Empty;
and you can also assign default values per variable.
string stringOutput1 = "foo1", stringOutput1 = "foo2"
, stringOutput3= "foo3", stringOutput4 = "foo4";

Categories

Resources