Is VB really case insensitive?
I'm not trying to start an argument here, but for whatever reason, it's typically stated that Visual Basic is case insensitive and C languages aren't (and somehow that is a good thing).
But here's my question: Where exactly is Visual Basic case insensitive? When I type...
Dim ss As String
Dim SS As String
...into the Visual Studio 2008 or Visual Studio 2010 IDE, the second one has a warning of "Local variable SS
is already declared in the current block". In the VBA VBE, it doesn't immediately kick an error, but rather just auto-corrects the case.
Am I missing something here with this argument that Visual Basic is not case sensitive? (Also, if you know or care to answer, why would that be a bad thing?)
Why am I even 开发者_StackOverflowasking this question?
I've used Visual Basic in many of its dialects for years now, sometimes as a hobbyist, sometimes for small business-related programs in a workgroup. As of the last six months, I've been working on a big project, much bigger than I anticipated. Much of the sample source code out there is in C#. I don't have any burning desire to learn C#, but if there are things I'm missing out on that C# offers that Visual Basic doesn't (an opposite would be VB.NET offers XML Literals), then I'd like to know more about that feature. So in this case, it's often argued that C languages are case sensitive and that's good and Visual Basic is case insensitive and that is bad. I'd like to know...
- How exactly is Visual Basic case insensitive since every single example in the code editor becomes case sensitive (meaning the case gets corrected) whether I want it or not.
- Is this compelling enough for me to consider moving to C# if VB.NET case is somehow limiting what I could do with code?
The difference between VBA and VB.NET is just because VB.NET compiles continuously in the background. You'll get an error when you compile the VBA.
Like Jonathan says, when programming you can think of VB.NET as case-insensitive apart from string-comparisons, XML, and a few other situations...
I think you're interested in what's under the hood. Well, the .NET Common Language Runtime is case-sensitive, and VB.NET code relies on the runtime, so you can see it must be case-sensitive at runtime, e.g. when it's looking up variables and methods.
The VB.NET compiler and editor let you ignore that - because they correct the case in your code.
If you play around with dynamic features or late-binding (Option Strict Off) you can prove that the underlying run-time is case-sensitive. Another way to see that is to realise that case-sensitive languages like C# use the same runtime, so the runtime obviously supports case-sensitivity.
EDIT If you want to take the IDE out of the equation, you can always compile from the command-line. Edit your code in Notepad so it has ss
and SS
and see what the compiler does.
EDIT Quote from Jeffrey Richter in the .NET Framework Design Guidelines page 45.
To be clear, the CLR is actually case-sensitive. Some programming languages, like Visual Basic, are case insensitive. When the Visual Basic compiler is trying to resolve a method call to a type defined in a case-sensitive language like C#, the compiler (not the CLR) figures out the actual case of the method's name and embeds it in metadata. The CLR knows nothing about this. Now if you are using reflection to bind to a method, the reflection APIs do offer the ability to do case-insensitive lookups. This is the extent to which the CLR offers case-insensitivity.
Part of the problem here is you need to divide the language from the IDE experience.
As a language, VB.NET is certainly a case insensitive with respect to identifiers. Calling DateTime.Parse
and datetime.parse
will bind to the exact same code. And unlike languages like C#, it is not possible to define methods or types which differ only by case.
As an IDE, VB.NET attempts to preserve the case of existing identifiers when it pretty lists a block of code. Pretty lists occur whenever you move off of the current logical line of code. In this case you move off of the second declaration of SS
, the pretty lister notices there is an existing identifier with that name and corrects it to have matching case.
This behavior, though, is purely done as a user value add. It is not a part of the core language.
VB is mostly case insensitive, but there are exceptions. For example, XML literals and comprehension is case sensitive. String comparisons are usually case sensitive, unlike say T-SQL, but there are compiler switch to make string comparisons case insensitive. And of course there are the edge cases when dealing with inheritance, COM, and Dynamic Language Runtime.
Yes, the VB.NET compiler treats identifiers in a case insensitive way. And yes, that can cause problems when it consumes assemblies that were written in another language or uses COM components. The former case is covered by the Common Language Specification. The relevant rule is:
For two identifiers to be considered distinct, they must differ by more than just their case.
The COM case is rather crudely taken care of by the type library builder, it forces the casing of identifiers with the same name to be identical. Even when those identifiers have different roles. In other words, a method parameter with the name "index" will force a method name "Index" to be recased to "index". That has produced rather a lot of head scratching, as you might imagine :)
VB is case preserving (in the IDE) but case insensitive. It's like Windows file system in a way. Hello.txt and hello.txt are considered to be the same file name.
The IDE assumes that the declaration a variable is the "correct" case for that variable, and adjusts every instance of that variable match the declaration. It does this for eye-candy and consistency reasons, but not for functionality.
I've seen several instances where the case was not automatically changed to match the declaration, and the statement works just the same. You can also use any text editor to write code that will compile just fine in different cases.
A side-note:
Most PEOPLE think in a case-insensitive manner. When we see the word "dog" the word is translated into meaning in our minds. The meaning of the word is not based upon case (i.e. regardless of if spell it "DOG", "DoG", or "dOG" still barks.) COMPUTERS see words as discrete bags of bits. Uppercase and lowercase are different bit patterns, and are thus different.
Since most programmers are human, case insensitivity seems more adapted to the way people think and case sensitivity is more about humans adapting how they think to the constraints of a machine.
This is part of the editor you are using, they may behave differently but the fact is that Visual Basic really is case-insensitive language. So, ss
and SS
are same.
Please have a look at VB.NET Basics tutorial for more information :)
I'm not sure I understand you? VB is case insensitive, so ss and SS is the same variable, so the compiler correctly complains that you re-declared the variable.
I think that Variables are not case sensitive, but function names are.
Yes, VB is case insensitive. It sometimes throws those not used to it for a bit of a loop.
One doesn't have to try all that hard in VB.NET to create code with different uppercase/lowercase "spellings" of an identifier. Changing the casing of an identifier in the file where it's declared without using the "Rename" function will not cause the name to be updated in other files, though editing any line which contains the name will cause it to conform to the present definition.
In this way, one can determine that VB.NET is mostly case insensitive, but it does make the case of identifiers available to the CLR which may use that information in case-sensitive ways.
I'll try to answer your second question.
"is this compelling enough for me to consider moving to C# if VB.NET case is somehow limiting what I could do with code?"
Create a WCF WebService using C#. Create a DataContract (1 Class). One with "string email" property. Another with "string Email" as another property. Your choice to understand as personal email or office email. Or it could be in two different DataContracts.
For C# this is fine. The web service is created fine. A C# program can easily create a WSDL and everything is fine.
Now try to create a WSDL with VB (any version). It will say "email" is already declared and WSDL generation fails.
Like everyone I assumed this is a drawback in VB language. But!!!
Use FxCOP and analyze the original C# code. FxCOP says using email/Email is an issue. Recommends to use different name supporting case insensitivity. Also note as of date .NET framework has 106 programming languages and there are many languages having case sensitivity ON. We are all moving towards cloud and want our services to be accessible by all programming platform/languages.
So being case sensitive is your choice within your program and if you are C guy you would like it. If the program is going to be used/accessed by other non C programs you need to support case insensitivity but your language is your choice.
http://en.wikipedia.org/wiki/Comparison_of_C_Sharp_and_Visual_Basic_.NET http://www.vbrad.com/article.aspx?id=65
Hiding of symbols (eg. local hides field) is also case insensitive.
Here is an example:
Public Class C
Public Name As String
Public Function M(name As String) As Boolean
Return String.Equals(name, Name) ' case differs
End Function
End Class
The VB.NET compiler's output is decompiled to (and therefore equivalent to) the following C#:
public class C
{
public string Name;
public bool M(string name)
{
return string.Equals(name, name); // both lowercase
}
}
string.Equals
is passed the field twice. The local is hidden, irrespective of case. The language is case insensitive.
To explicitly reference the a member, such as this field, you must dereference the member via Me
:
Return String.Equals(name, Me.Name) ' differentiate field from local
I can only offer this, which as I recall from my programming text books back in the early 80s, is that case senstive languages were, (at that time) strictly intended to reduce compile time errors. That is to say, the "strictness" was intended to develop a coding discipline of greater accuracy. As it has turned out the addition of proper labeling of variables, classes, methods, functions, and whatever else you wish to throw in there, evolved as well.
I recall almost all of those books included a recommended pattern for leading capitalization, lower case, etc. As we all know, much of that has been thrown out or should I say, ignored in practice, save for the high end production houses, and CASE solutions, or for those that have reached a higher skill level. I think everyone experiences this learning curve.
Given the advancement of these langauges and IDE's, the better question becomes, which language improves my dev time? Of course if you are not familiar with each of the various langs, your options are limited.
I've not seen anyone comment on your explicit 2nd question at the end: "2: is this compelling enough for me to consider moving to C# if VB.NET case is somehow limiting what I could do with code?"
i prefer the more option approach that C# lets the programmer choose whether than limiting the programmer's options. i highly prefer C#, but for case sensitivity alone, i would not even think it close to learning a language just because it is case sensitive. all the features are what matter, and when i look at advantages of both, C# and VB.NET, i highly prefer C#. but i will give you a true balanced perspective, biased yes, because i have a preference, but i will be honest about the disadvantages of C# too.
first off, both languages have advantages and disadvantages. the differences that you can do in one language that cannot be done in the other is dwindling as, thankfully, Microsoft is improving both languages, and they seem to not be showing unfair partiality toward either language.
when C# first came out, VB did not have its XML comments that you could put before methods, which i loved in C#. i hated that in VB.NET. but i've seen over the years, that many features that are not in one language get added to the other. (the same team of MS developers develop both C# and VB, so it makes sense that the features should become quite similar.)
but you asked for what C# has that VB doesn't. here's some i can think of immediately:
1: C# is more concise and takes less typing.. in MANY ways! i've even seen stupidity speaking when the opposite claim is made, that VB saves typing. but please listen to the people who tell you they use both languages, and neither is rarely used by them. i use both C# and VB, C# at home because i like it (and when i work with C# at work), and my more recent job requests that i use VB and not C#. so i'm getting more frequent use of VB now (for about 10 months now), but in my personal testimony, i much prefer C#, and in terms of actual typing, VB is considerably more typing. the one example i've read where someone actually tried to say VB was more concise, was giving a 'with ...' example with a long variable in the with, so in VB, you could just use '.property'. this is stupidity in claiming that VB needs less typing. there are a few things (and not just this example) where VB is shorter, but many more times when C# is more concise, in real practice.
but the biggest reason i believe C# is more concise, is VB's verbose "IF/THEN" statements. if statements are common. in C# there is no 'then' word to type! :) also all the 'end ...' statements take typing which in c#, is usually just one closing brace '}'. i've read that some people claim this more verboseness in VB.NET is an advantage to VB since several closing block statements/symbols can be nested and end immediately next to one another, but i quite disagree. a person can almost always write a program better in either C# or VB than another programmer because the next code revision could be designed better. this applies to the 'confusing numerous closing braces in C#' plus if the nested blocks are all the same type like several nested IF's then VB suffers the same problem as it has in C#. this is no advantage in VB. this situation is precisely why i like to comment what my closing symbol or closing statement goes with in both languages. yes, this is more verbose to do, but in either language, you have the option to be clear, which is important in judgement based, situational specific cases. i think code clarity is quite important.
2: VB does not have multi-line comments. when i worked with VB i didn't mind. then i went to a few C-style languages. now i'm back mostly using VB.NET at work, and i miss them. it's just something you find convenient, and then have to lose. :(
3: VB's 'andalso' and 'orelse' is rather annoying to type all that when in C# it is simply '&&' and '||'. again, less typing. this is not rare in my code in both VB and C#. if anything, for functionality, 'OR' vs 'OrElse' usually does not matter except 'OrElse' is faster for the computer, so if a programmer just uses 'Or' and 'And' in VB, then it produces less optimal code for someone who likes clarity of code. 'Or' is far easier to skim than 'OrElse'.
4: more flexibility in code placement in C#. when a line is long and you want to wrap it on the next line, i hate VB.NET's 'controling' readjusting of my code. C# does it a little, but i find it more useful in C#, where in VB, it is much more controling. but this is more of the VB.NET IDE vs C# IDE rather than the language itself. but i don't know whether you want both or purely the language features without IDE differences.
5: one i really miss is just creating a new block of code in C#, i might have a lot happening in a method and i want to declare a variable in a very small block of code but not have that variable declared outside that block in the entire method. in C#, we can just create a new block with '{' and end it with '}'. VB has no such feature, but it's closest match is an unconditional 'If True Then' and 'End If' block. (note the 2 character C# vs 18 character VB.NET equivalent again... more typing in VB.)
6: self increment and decrement operators: ++ and -- as in myVariable++
or ++myVariable
or the equivalent decrement versions. this comes in very handy... sometimes. here is an example of actual code when i missed C# greatly:
// C#:
while (txt.Length > x)
{
thisChar = txt[x];
if (charsAllowedWithoutLimit.Contains(thisChar)) { ++x; }
else if (allowLettersWithoutLimit && char.IsLetter(thisChar)) { ++x; }
else if ((x2 = charsAllowedWithLimit.IndexOf(thisChar)) >= 0)
{
++x; if (++usedCountA[x2] > charAllowedLimit[x2]) { break; }
}
else { break; }
}
' VB.NET:
While (txt.Length > x)
thisChar = txt(x)
If (charsAllowedWithoutLimit.Contains(thisChar)) Then
x += 1
ElseIf (allowLettersWithoutLimit AndAlso Char.IsLetter(thisChar)) Then
x += 1
Else
x2 = charsAllowedWithLimit.IndexOf(thisChar)
If (x2 >= 0) Then
x += 1
usedCountA(x2) += 1S
If usedCountA(x2) > charAllowedLimit(x2) Then Exit While
Else
Exit While
End If
End If
End While
And just to give a VERY good example where C# rules, this is more code that i personally wrote recently:
// C#
public static bool IsNotWithin(this Byte v, Byte v1, Byte v2) { return (v1 > v && v < v2) || (v2 < v && v > v1); }
public static bool IsNotWithin(this SByte v, SByte v1, SByte v2) { return (v1 > v && v < v2) || (v2 < v && v > v1); }
public static bool IsNotWithin(this Int16 v, Int16 v1, Int16 v2) { return (v1 > v && v < v2) || (v2 < v && v > v1); }
public static bool IsNotWithin(this Int32 v, Int32 v1, Int32 v2) { return (v1 > v && v < v2) || (v2 < v && v > v1); }
public static bool IsNotWithin(this Int64 v, Int64 v1, Int64 v2) { return (v1 > v && v < v2) || (v2 < v && v > v1); }
public static bool IsNotWithin(this UInt16 v, UInt16 v1, UInt16 v2) { return (v1 > v && v < v2) || (v2 < v && v > v1); }
public static bool IsNotWithin(this UInt32 v, UInt32 v1, UInt32 v2) { return (v1 > v && v < v2) || (v2 < v && v > v1); }
public static bool IsNotWithin(this UInt64 v, UInt64 v1, UInt64 v2) { return (v1 > v && v < v2) || (v2 < v && v > v1); }
public static bool IsNotWithin(this Decimal v, Decimal v1, Decimal v2) { return (v1 > v && v < v2) || (v2 < v && v > v1); }
public static bool IsWithin(this Byte v, Byte v1, Byte v2) { return (v1 <= v && v <= v2) || (v2 <= v && v <= v1); }
public static bool IsWithin(this SByte v, SByte v1, SByte v2) { return (v1 <= v && v <= v2) || (v2 <= v && v <= v1); }
public static bool IsWithin(this Int16 v, Int16 v1, Int16 v2) { return (v1 <= v && v <= v2) || (v2 <= v && v <= v1); }
public static bool IsWithin(this Int32 v, Int32 v1, Int32 v2) { return (v1 <= v && v <= v2) || (v2 <= v && v <= v1); }
public static bool IsWithin(this Int64 v, Int64 v1, Int64 v2) { return (v1 <= v && v <= v2) || (v2 <= v && v <= v1); }
public static bool IsWithin(this UInt16 v, UInt16 v1, UInt16 v2) { return (v1 <= v && v <= v2) || (v2 <= v && v <= v1); }
public static bool IsWithin(this UInt32 v, UInt32 v1, UInt32 v2) { return (v1 <= v && v <= v2) || (v2 <= v && v <= v1); }
public static bool IsWithin(this UInt64 v, UInt64 v1, UInt64 v2) { return (v1 <= v && v <= v2) || (v2 <= v && v <= v1); }
public static bool IsWithin(this Decimal v, Decimal v1, Decimal v2) { return (v1 <= v && v <= v2) || (v2 <= v && v <= v1); }
' And the VB equivalent is a mess! Here goes:
<Extension()>
Public Function IsNotWithin(v As Byte, value1 As Byte, value2 As Byte) As Boolean
Return (value1 > v AndAlso v < value2) OrElse (value2 < v AndAlso v > value1)
End Function
<Extension()>
Public Function IsNotWithin(v As SByte, value1 As SByte, value2 As SByte) As Boolean
Return (value1 > v AndAlso v < value2) OrElse (value2 < v AndAlso v > value1)
End Function
<Extension()>
Public Function IsNotWithin(v As Int16, value1 As Int16, value2 As Int16) As Boolean
Return (value1 > v AndAlso v < value2) OrElse (value2 < v AndAlso v > value1)
End Function
' the % suffix means 'As Integer' in VB.
<Extension()>
Public Function IsNotWithin(v%, value1%, value2%) As Boolean
Return (value1 > v AndAlso v < value2) OrElse (value2 < v AndAlso v > value1)
End Function
' the & suffix means 'As Long' in VB.
<Extension()>
Public Function IsNotWithin(v&, value1&, value2&) As Boolean
Return (value1 > v AndAlso v < value2) OrElse (value2 < v AndAlso v > value1)
End Function
<Extension()>
Public Function IsNotWithin(v As UInt16, value1 As UInt16, value2 As UInt16) As Boolean
Return (value1 > v AndAlso v < value2) OrElse (value2 < v AndAlso v > value1)
End Function
<Extension()>
Public Function IsNotWithin(v As UInt32, value1 As UInt32, value2 As UInt32) As Boolean
Return (value1 > v AndAlso v < value2) OrElse (value2 < v AndAlso v > value1)
End Function
<Extension()>
Public Function IsNotWithin(v As UInt64, value1 As UInt64, value2 As UInt64) As Boolean
Return (value1 > v AndAlso v < value2) OrElse (value2 < v AndAlso v > value1)
End Function
' the @ suffix means 'As Decimal' in VB.
<Extension()>
Public Function IsNotWithin(v@, value1@, value2@) As Boolean
Return (value1 > v AndAlso v < value2) OrElse (value2 < v AndAlso v > value1)
End Function
<Extension()>
Public Function IsWithin(v As Byte, value1 As Byte, value2 As Byte) As Boolean
Return (value1 <= v AndAlso v <= value2) OrElse (value2 <= v AndAlso v <= value1)
End Function
<Extension()>
Public Function IsWithin(v As SByte, value1 As SByte, value2 As SByte) As Boolean
Return (value1 <= v AndAlso v <= value2) OrElse (value2 <= v AndAlso v <= value1)
End Function
<Extension()>
Public Function IsWithin(v As Int16, value1 As Int16, value2 As Int16) As Boolean
Return (value1 <= v AndAlso v <= value2) OrElse (value2 <= v AndAlso v <= value1)
End Function
' the % suffix means 'As Integer' in VB.
<Extension()>
Public Function IsWithin(v%, value1%, value2%) As Boolean
Return (value1 <= v AndAlso v <= value2) OrElse (value2 <= v AndAlso v <= value1)
End Function
' the & suffix means 'As Long' in VB.
<Extension()>
Public Function IsWithin(v&, value1&, value2&) As Boolean
Return (value1 <= v AndAlso v <= value2) OrElse (value2 <= v AndAlso v <= value1)
End Function
<Extension()>
Public Function IsWithin(v As UInt16, value1 As UInt16, value2 As UInt16) As Boolean
Return (value1 <= v AndAlso v <= value2) OrElse (value2 <= v AndAlso v <= value1)
End Function
<Extension()>
Public Function IsWithin(v As UInt32, value1 As UInt32, value2 As UInt32) As Boolean
Return (value1 <= v AndAlso v <= value2) OrElse (value2 <= v AndAlso v <= value1)
End Function
<Extension()>
Public Function IsWithin(v As UInt64, value1 As UInt64, value2 As UInt64) As Boolean
Return (value1 <= v AndAlso v <= value2) OrElse (value2 <= v AndAlso v <= value1)
End Function
' the @ suffix means 'As Decimal' in VB.
<Extension()>
Public Function IsWithin(v@, value1@, value2@) As Boolean
Return (value1 <= v AndAlso v <= value2) OrElse (value2 <= v AndAlso v <= value1)
End Function
Perhaps this is enuf evidence that C# is more concise. But not all programmers like conciseness. Some prefer to read "if a < b then ... " because it is more natural to their human language. And that's just fine. Preferences are fine. For me, hand effort is a factor i value, and i think anyone can get used to thinking in any symbols they prefer, for "if" and "then" are symbols of an alphabet, and C#'s "if (condition) statement;" syntax are symbols too. one is just closer to non-programmer's syntax than the other. i prefer the concise one.
I also think needing to use 'c' after character literals in VB to make it a character literal rather than a string is annoying. I like C#'s conciseness with that much more. when a method requires a character literal, you need to provide a character not a string with one character length, so sometimes you are forced to use ":"c
in VB while in C# it is ':'
. i think this is nit-picking tho.
To be fair, i will say there are advantages i like to VB like not having to put empty parentheses after method calls, like Dim nameUpper$ = name.ToUpperInvariant
where C# requires the empty parentheses: string nameUpper = name.ToUpperInvariant()
. or double that like trimming it too: Dim nameUpper$ = name.Trim.ToUpperInvariant
vs string nameUpper = name.Trim().ToUpperInvariant()
. I like VB's concise use of how i just used $
above to dim it ' As String' where C# does not have those shortcuts. VB has those shortcuts for String, Integer, Long, Decimal, Single, and Double types, but the disadvantage is it is less clear, so i use it with caution. but nevertheless, i prefer concise code.
Well, that's just some thots from this seasoned programmer, and as i consider, this is my programming 'testimony' of C# vs VB. both are nice languages tho, in my opinion. but yes, i still much prefer C#.
p.s. Since i plan to program for most of my life, i even re-learned to type using the most efficient keyboard: the Dvorak keyboard, which takes about 1/3 the effort to type English than on a Qwerty keyboard. look it up. maybe you might want to switch too. ;) it made my typing 67% easier! :) I encourage anyone to think outside the box and evaluate better efficiency in your work. The Dvorak Simplified Keyboard Layout and C# has done this for me. :)
P.S.S. i would compare the Dvorak and C# to metric as opposed to the Qwerty keyboard layout and VB to the Empirial measurements. Dvorak, metric, and C# are just 'clean'. BUT VB is not really far behind. But it does suffer from needing to be backward compatible to old VB6 code and pre .NET code, like the 'Or' vs 'OrElse', and 'IIF()'.
I finish with a caution. Please be more prudent that listening to people who do not really know what they are talking about. Half of all the cons against both VB and C# are not any issue anymore, and people still post about them being ignorant about what disadvantages really still do exist in the language. The best example i can think of is XML comments for methods using triple apostrophe in VB or triple slash comment symbols in C#. But please discern for yourself whether a person is speaking from ignorance, or from experience. Personal testimony means they know from their real experience. And after someone has lots of experience in it, then perk up your ears. I have more than 10 years experience in both C# and VB. And it boils down to this: both are (very) good languages. And most the differences, you can see immediately within 5 minutes of reading code. But yes, other features it may take years to find a handicap. And one handicap that i'm aware of (in C#), I can't even think of a real life situation where it would be useful. So perhaps it isn't a handicap after all.
Happy coding!
VB.NET is case-INsensitive.
Examples:
1.
Dim a As Integer
Dim A as Integer
2.
Sub b()
'Some statement(s) here
End Sub
Sub B()
'Some statement(s) here
End Sub
3.
Function c() As Integer
'Some statement(s) here
End Function
Function C() As Integer
'Some statement(s) here
End Function
These all code will throw a COMPILE-TIME ERROR.
For the 1st example, error will be shown, saying "Local variable 'A' is already declared in the current block.".
While for the 2nd and 3rd example, error will be shown saying "'Public Sub b()' has multiple definitions with identical signatures." and "'Public Function c() As Integer' has multiple definitions with identical signatures.", respectively.
From these errors, note that the errors are thrown at different positions for variables and procedures/functions. For variables, error is thrown at 2nd declaration while for procedures/functions it is thrown at 1st declaration/definition of identical code.
As said by a user in a comment somewhere above, the VB.NET code is continuously checked and/or corrected in background; you can see this error in "Error List" window in VS IDE. And as this is AN ERROR and NOT A WARNING, the code will not compile until error is resolved.
精彩评论