I am converting some VB.NET code to C#, as I am more comfortable with it and it helps me in resolving issues faster. However, I came across this code which is NOT an error in VB.NET — but converting it to C# is generating a compiler error.
VB.NET Code
Select Case name
Case "FSTF"
.....
Case "FSTF"
.....
End Select
C# Converted Code
switch(name) {
case "FSTF":
....;
break;
case "FSTF":
....;
break;
}
And the error is:
The Label 'case "FSTF":' already occurs in this switch statement.
What is the solution here — does it mean that in the VB.NET code, the second case statement was just a dummy — or was the first case a dummy?
From the documentation for Select...Case:
If testexpression matches an expressionlist clause in more than one Case clause, only the statements following the first match run.
So here the second case is effectively redundant. Personally I prefer the C# approach of highlighting what was almost certainly an unnoticed programming error rather than the deliberate introduction of a duplicate case...
I assume it was done this way to make VB.NET compatible with the Visual Basic 6.0 and older versions because that is the way they behaved. Had VB.NET reported a compilation error like C# then it would have been more difficult to port older Visual Basic code to VB.NET.
The odd thing about this is that VB.NET does not seem smart enough to eliminate the redundant case in the generated CIL code. This leads to another peculiar difference between C# and VB.NET. That is, VB.NET does not change its strategy from a sequential lookup to a Dictionary lookup when targeting string types like C#. This means VB.NET's Select constructs using string types can be slower to execute than C#'s switch counterpart. The reason for this (credit given to MarkJ) is because C# case statements can only contain constants whereas Visual Basic case statements can contain expressions.
Related
This is ok in C#:
private int total;
public int Total {
get {
return total;
}
}
So the backing field total is spelled the same as the Property Total with the only thing telling them apart being the case of the T.
With VB.NET VS complains if I try to do the following. In fact it won't even let me write Return total with a lower case t and auto-corrects to an upper case T
But if I spell the backing field differently then it seems to be ok:
Private fTotal As Integer
Public ReadOnly Property Total() As Integer
Get
Return fTotal
End Get
End Property
I realize they are different languages but is there a logical reason behind this difference? (EDIT originally said "apparent inconsistency" rather than "difference")
Also - I assume even though Visual Studio auto-corrects the case of my VB.NET but in reality this language is not case-sensitive?
I realize they are different languages but is there a logical reason behind this apparent inconsistency?
The original reason is simply historical: VB is based on BASIC which, like other languages at the time (FORTRAN) was case insensitive (but was usually written in all-uppercase).
Furthermore, I don’t see any inconsistency: inside VB, the casing is entirely consistent. In particular, it’s not “sort of case-sensitive” as your title asks.
There is a logical reason to be case insensitive, even today: it makes it harder to introduce bugs due to name clashes; consider the following C# code:
private int total;
public int Total {
get { return total; }
set { Total = value; }
}
Did you spot the error immediately? If so, not bad (the syntax highlight here helps). In VB, this class of errors cannot happen. But in practice I think this class of bugs isn’t all that problematic because once identified they are easily eliminated. So while this is a reason for case insensitivity, it’s not a very strong one.
Finally, notice that Windows and OS X file systems use the same convention as VB here: the file system is case insensitive (filename case doesn’t matter) but case aware – meaning the file system preserves the original casing of a filename and displays it correctly but when comparing, it doesn’t consider case.
VB.NET is not case-sensitive, it was designed to be easy to learn for Visual Basic programmers, and shares this trait with Visual Basic.
C# is case-sensitive, it's a different language than VB.NET. Even if they are both used for .NET development, they don't have to be consistent. You can use many languages for .NET development, and the differences between these languages are many and not limited to case-sensitivity.
There are several points to address:
The language Visual Basic is always case-insensitive. The compiler doesn't care if you declare a variable one way and use it another.
The IDE (Visual Studio) will helpfully fix the case of variable usages to match the actual declaration. You may be able to turn this off in the settings, but I've never tried so I don't know if it's actually possible.
Now back to your code:
Private total As Integer
Public ReadOnly Property Total() As Integer
Get
Return Total
End Get
End Property
There are actually two bugs here:
You have two members with the same name, a field called total and a property called Total. They're the same name because they're compared case-insensitively (the compiler shows you an error for this - the blue squiggly line in your screenshot).
The IDE auto-corrects 'total' to 'Total' inside the property, because you're actually referring to the property, not the field. The compiler won't show you an error because of this, but if you were to remove the field (so that your program compiles), you will run into a stack overflow at runtime because the property would call itself. Note that even if you did manage to turn of the IDE's auto-correct, you'd still be referring to the property, since it's looked up case-insensitively.
The VB.Net compiler is case insensitive in so far that for all intent and purposes it forbids the use of fields with the same name and the only difference of a upper case or lower case letter.
The underlying CLI (common language interface) and CLR (common language runtime) do support case differences. However the c# example given is not CLS valid.
Actually, the problem here is nothing to do with the different case field named 'total'. You'll see the same problem if you remove that field.
The problem is that VB allows you to optionally set the value to be returned by a property or a function via a hidden local variable named the same as the property or function and then to return that hidden variable.
e.g., this will work:
Public ReadOnly Property Total() As Integer
Get
Total = 3 'setting the hidden VB variable
Return Total 'returning the hidden VB variable
End Get
End Property
VB even allows omitting the return statement in this case:
Public ReadOnly Property Total() As Integer
Get
Total = 3 'setting the hidden VB variable
End Get 'since the hidden VB variable was set, it is returned implicitly
End Property
These sort of VB-isms can make it very frustrating to interpret what is really happening in VB code.
Usually, if I use switch for enums in C#, I have to write something like that:
switch (e)
{
case E.Value1:
//...
break;
case E.Value2:
//...
break;
//...
default:
throw new NotImplementedException("...");
}
In C++ (for VS) I could enable warnings C4061 and C4062 for this switch, make them errors and have a compile-time check. In C# I have to move this check to runtime...
Does anyone know how in C# I can have this checked in compile time? Maybe there is a warning, disabled by default, which I missed, or some other way?
No, there isn't be a compile-time check - it's legitimate to have a switch/case which only handles some of the named values. It would have been possible to include it, but there are some issues.
Firstly, it's entirely valid (unfortunately) for an enum value not to have any of the "named" values:
enum Foo
{
Bar = 0,
Baz = 1
}
...
Foo nastyValue = (Foo) 50;
Given that any value is feasible within the switch/case, the compiler can't know that you didn't mean to try to handle an unnamed value.
Secondly, it wouldn't work well with Flags enums - the compiler doesn't really know which values are meant to be convenient combinations. It could infer that, but it would be a bit icky.
Thirdly, it's not always what you want - sometimes you really do only want to respond to a few cases. I wouldn't want to have to suppress warnings on a reasonably regular basis.
You can use Enum.IsDefined to check for this up front, but that's relatively inefficient.
I agree that all of this is a bit of a pain - enums are a bit of a nasty area when it comes to .NET :(
I understand that this is necroposting, but nothing really changed in this area inside of the compiler. So, I made Roslyn analyzer for switch statements.
You can download SwitchAnalyzer package.
This is Roslyn analyzer and it supports
Enums with operations | and & for them. So, you can check flags as well
(but not like single int value)
Interface implementations (pattern matching) in the current data context.
Pattern matching for classes is not implemented in version 0.4 yet (but I hope to implement it soon).
To use it, just add this package to your project, you will get warnings for all uncovered cases if you don't have default branch or if it throws exception. And of course, you can enable "Treat warnings as errors" option for your project for all or specific warnings. Feel free to contact me in case if you will find any bugs.
I did some reading on this, and from questions similar to mine, it looks like what I am about to ask might not be (easily) possible... But I wanted to verify anyway. Maybe all those questions were from an older version of C#/.NET, and the thing has been implemented recently.
Anyway. I have a switch-case statement in one of my classes, whose purpose is essentially to take an int (typeID) and string (value) and check whether the value can be parsed as the data type indicated by typeID. For example, here is part of what I have now:
case 1:
char charret;
return char.TryParse(value, out charret);
case 2:
Regex re = new Regex(Constants.REGEX_ALPHANUMERIC);
return re.IsMatch(value);
case 3:
bool boolret;
return bool.TryParse(value, out boolret);
//And so on...
What I would like to do is to be able to avoid the char/bool instantiation you see in cases 1 & 3. Ideally, I would like to just have the return statement. It's not a big deal (obviously), but it would be nice if I could make this more (even more) compact.
That's inherently impossible.
Variables passed as out parameters must exactly match the parameter type.
There's no way to avoid declaring a variable when you are calling a function with an out parameter.
This post might be helpful as it does a generic TryParse (if it is available):
http://toadcode.blogspot.com/2010/10/generic-object-tryparse.html
I was wondering why C# requires me to use break in a switch statement although a fall-through semantics is by definition not allowed. hence, the compiler could generate the break at the end of each case-block and save me the hassle.
However, there is one scenario (which has already been discussed on this site) which I could come up with that might be the reason for the explicit usage of break:
switch (foo) {
case 0:
case 1:
bar();
break;
default:
break;
}
Here, the method bar() is called if foo has either the value 0 or 1.
This option would break in the truest sense of the word if the compiler would generate break statements by itself. Is this it, is this the reason why the break is compulsory or are there any other good reasons?
The question presupposes a falsehood and therefore cannot be answered. The language does NOT require a break at the end of a switch section. The language requires that the statement list of a switch section must have an unreachable end point. "break" is just the most commonly used statement that has this property. It is perfectly legal to end a switch section with "return;", "goto case 2;", "throw new Exception();" or "while (true) {}" (or in some cases, continue, though that's usually a bad idea.)
The reason we require a statement list with an unreachable endpoint is to enforce the "no fall through" rule.
If your question is better stated as "why doesn't the compiler automatically fix my error when I fail to produce a switch section with a statement list with an unreachable end point, by inserting a break statement on my behalf?", then the answer is that C# is not a "make a guess about what the developer probably meant and muddle on through" sort of language. Some languages are -- JScript, for example -- but C# is not.
We believe that C# programmers who make mistakes want to be told about those mistakes so that they can intentionally and deliberately correct them, and that this is a good thing. Our customers tell us that they do not want the compiler to make a guess about what they meant and hope for the best. That's why C# also does not make a guess about where you meant to put that missing semicolon, as JScript does, or silently fail when you attempt to modify a read-only variable, as JScript does, and so on.
I suspect that the reason C# requires the developer to place a break or terminal statement at the end of each case is for clarity.
It avoids newcomers to the language from assuming that switch( ) in C# behaves like switch in C or C++ where fall through behavior occurs. Only in the cases of adjacent empty cases does fall through occur in C# - which is relatively obvious.
EDIT: Actually, in C# fallthrough is always illegal. What is legal, however, is having a single case associated with two or more labels. Eric Lippert writes at length about this behavior and how it differs from C/C++ switch statements.
You may be interested in reading this article on Eric Lipperts blog.
By making break optional, you open yourself up to bugs like this:
switch (thing_result)
{
case GOOD_THING:
IssueReward();
// UH-OH, missing break!
case BAD_THING:
IssuePunishment();
break;
}
The C# language designers have tried to help programmers avoid pitfalls in the languages that came before it, generally by forcing the programmer to be more explicit (e.g. explicit use of the 'override' or 'new' keyword for implementing or shadowing virtual members).
My understanding of the matter is that it was included to match C++ syntax.
If you wouldn't need to append a break, there is a problem
switch (number)
{
case 0:
case 1:
DoSomething();
}
What happens if number == 0? Is this an empty case which does not do anything or will DoSomething() be executed?
http://msdn.microsoft.com/en-us/library/x810d419.aspx
From what we can see on MSDN, it says to be careful about which expressions we put as they change from language to language. My question is: what are the supported languages for writing those expressions? If various languages can do it, how does it detect which language is being used?
I've made my class in CLI, and coded the expression in c#, being that it works. I've tried in c++/CLI, but that way it doesn't.
Here is my code:
[DebuggerDisplay("z = {ToString()} Norm = {System.Math.Round(Norm,2)} Angle = {System.Math.Round(Angle, 2)}")]
Now, trying it the c++/CLI way:
[DebuggerDisplay("z = {ToString()} Norm = {System::Math::Round(Norm,2)} Angle = {System::Math::Round(Angle, 2)}")]
My assumption is that it will always read the expression as c# code. Is this true?
I found this link
There is a down-side to this power
though - because evaluation of the
DebuggerDisplayAttribute format string
is compiler-specific, the first
example will work fine most other
debuggers such as VB, but the second
one will not evaluate due to its use
of the C#-specific ternary operator.
Depending on the debugger this will
cause it to display either the default
value of the class name, or an error
indicating which part of the syntax
could not be evaluated; this may be
important if you work in a
multi-language environment, or if you
ship your classes as a library to
customers.
My interpretation is that it will always interpret it in a format that happens to look a lot like C#, yes. So . for members-access, etc (the same as data-binding uses . for member-access, regardless of the caller's language). It is also a lot like the string.Format pattern, if you see the relationship ("{0} - {1}" etc).
Of course, if the expression gets too complex you could consider a debugger type proxy.