Why are semicolons necessary at the end of each line in C#?
Why can't the complier just know where each line is ended?
The line terminator character will make you be able to break a statement across multiple lines.
On the other hand, languages like VB have a line continuation character (and may raise compile error for semicolon). I personally think it's much cleaner to terminate statements with a semicolon rather than continue using undersscore.
Finally, languages like JavaScript (JS) and Swift have optional semicolon(s), but at least JS has a convention to always put semicolons (even if not required, which prevents accidents).
No, the compiler doesn't know that a line break is for statement termination, nor should it. It allows you to carry a statement to multilines if you like.
See:
string sql = #"SELECT foo
FROM bar
WHERE baz=42";
Or how about large method overloads:
CallMyMethod(thisIsSomethingForArgument1,
thisIsSomethingForArgument2,
thisIsSomethingForArgument2,
thisIsSomethingForArgument3,
thisIsSomethingForArgument4,
thisIsSomethingForArgument5,
thisIsSomethingForArgument6);
And the reverse, the semi-colon also allows multi-statement lines:
string s = ""; int i = 0;
How many statements is this?
for (int i = 0; i < 100; i++) // <--- should there be a semi-colon here?
Console.WriteLine("foo")
Semicolons are needed to eliminate ambiguity.
So that whitespace isn't significant except inside identifiers and keywords and such.
I personally agree with having a distinct character as a line terminator. It makes it much easier for the compiler to figure out what you are trying to do.
And contrary to popular belief it is not possible 100% of the time to for the compiler to figure out where one statement end and another begins without assistance! There are edge cases where it is ambiguous whether it is a single statement or multiple statements spanning several lines.
Read this article from Paul Vick, the technical lead of Visual Basic to see why its not as easy as it sounds.
Strictly speaking, this is true: if a human could figure out where a statement ends, so can the compiler. This hasn't really caught on yet, and few languages implement anything of that kind. The next version of VB will probably be the first language to implement a proper handling of statements that require neither explicit termination nor line continuation [source]. This would allow code like this:
Dim a = OneVeryLongExpression +
AnotherLongExpression
Dim b = 2 * a
Let's keep our fingers crossed.
On the other hand, this does make parsing much harder and can potentially result in poor error messages (see Haskell).
That said, the reason for C# to use a C-like syntax was probably due to marketing reasons more than anything else: people are already familiar with languages like C, C++ and Java. No need to introduce yet another syntax. This makes sense for a variety of reasons but it obviously inherits a lot of weaknesses from these languages.
It can be done. What you refer to is called "semicolon insertion". JavaScript does it with much success, the reason why it is not applied in C# is up to its designers. Maybe they did not know about it, or feared it might cause confusion among programmers.
For more details in semicolon insertion in JavaScript, please refer to the ECMA-script standard 262 where JavaScript is specified.
I quote from page 22 (in the PDF, page 34):
When, as the program is parsed from left
to right, the end of the input
stream of tokens is encountered and
the parser is unable to parse the
input token stream as a single complete
ECMA Script Program,
then a semicolon isa utomatically inserted at
the end of the input stream.
When, as
the program is parsed from left to right,
a token is encountered that is
allowed by some production of
the grammar, but
the production is a restricted production and the token would be the
first token for a terminal or
nonterminal immediately following the
annotation “[no LineTerminator
here]” with in the restricted production (and there fore such a token is
called a restricted token), and the
restricted token is separated fromt he
previous token by at least one
LineTerminator, then a
semicolon is automatically inserted before the restricted token.
However, there is an additional
overriding condition on the preceding
rules: a semicolon is never
inserted automatically if
the semicolon would then be parsed as an empty statement
or if that semicolon
would become one of the two semicolons in the header of a for statement
(section 12.6.3).
[...]
The specification document even contains examples!
Another good reason for semicolons is to isolate syntax errors. When syntax errors occur the semicolons allow the compiler to get back on track so that something like
a = b + c = d
can be disambiguated between
a = b + c; = d
with the error in the second statement or
a = b + ; c = d
with the error in the first statement. Without the semicolons, it can be impossible to say where a statement ends in the presence of a syntax error. A missing parenthesis might mean that the entire latter half of your program may be considered one giant syntax error rather than being syntax checked line by line.
It also helps the other way - if you meant to write
a = b; c = d;
but typoed and left out the "c" then without semis it would look like
a = b = d
which is valid and you'd have a running program with a bad and difficult to locate bug so semicolons can often help catch errors that otherwise would look like valid syntax. Also, I agree with everybody on readability. I don't like working in languages without some sort of statement terminator for that reason.
I've been mulling this question a bit and if I may take a guess at the motivations of the language designers:
C# obviously has semicolons because of its heritage from C. I've been rereading the K&R book lately and it's pretty obvious that Dennis Ritchie really didn't want to force programmers to code the way he thought was best. The book is rife with comments like, "Although we are not dogmatic about the matter, it does seem that goto statements should be used rarely, if at all" and in the section on functions they mention that they chose one of many format styles, it doesn't matter which one you pick, just be consistent.
So the use of an explicit statement terminator allows the programmer to format their code however they like. For better or worse, it seems consistent with how C was originally designed: do it your way.
I would say that the biggest reason that semicolons are necessary after each statement is familiarity for programmers already familiar with C, C++, and/or Java. C# inherits many syntactical choices from those languages and is not simply named similarly to them. Semicolon-terminated statements is just one of the many syntax choices borrowed from those languages.
Semi-colons are a remnant from the C language, when programmers often wanted to save space by combining statements on one line. i.e.
int i; for( i = 0; i < 10; i++ ) printf("hello world.\n"); printf("%d instance.\n", i);
It also helped the compiler, which was not smart enough to simply infer the end of a statement. In almost all cases, combining statements on one line is not looked favorably upon by most c# developers for readability reasons. The above is typically written like so:
int i;
for( i = 0; i < 10; i++ )
{
printf("hello world.\n);
printf("%d instance.\n", i);
}
Very verbose! For modern languages, compilers can easily be developed to infer end of statements. C# could be altered into another language which uses no unnecessary delimiters other than a space and indenting tab, i.e.
int i
for i=0 i<10 i++
printf "hello world.\n"
printf "%d instance.\n" i
That would certainly save some typing and it looks neater. If indents are used rather than spaces, the code becomes much more readable. We can do one better if we allow types to be inferred and make a special case of for, to read, (for [value]=[initial value] to [final value:
for i=1 to 10 // i is inferred to be an integer
printf "hello world.\n"
printf "%d instance.\n" i
Now, its beginning to look like f# and f#, in some ways, is almost like c# without the unnecessary punctuation. However f# lacks so many extras (like special .NET language constructs, code completion and good intellisense). So, in the end f# can be more work than c# or VB.NET to implement, sadly.
Personally, my work required VB.NET and I have been happier not having to deal with semi-colons. C# is a dated language. Linq has allowed me to cut down on the number of lines of code I have to write. Still, if I had the time, I would write a version of c# which had many of the features of f#.
You could accurately argue that requiring a semicolon to terminate a statement is superfluous. It is technically possible to remove the semicolon from the C# language and still have it work. The problem is that it leaves room for misinterpretation by humans. I would argue that the necessity of semicolons is the disambiguation for the sake of humans, not the compiler. Without some form of statement delimitation, it is much harder for humans to interpret consise staements such as this:
int i = someFlag ? 12 : 5 int j = i + 3
The compiler should be able to handle this just fine, but to a human the below looks much better
int i = someFlag ? 12 : 5; int j = i + 3;
Related
I am fairly new to c# and trying to learn best practices. I've been faced with many situations over the last week in which I need to make a choice between longer+simpler code, or shorter code that combines several actions into a single statement. What are some standards you veteran coders use when trying to write clear, concise code? Here is an example of code I'm writing with two options. Which is preferable?
A)
if (ncPointType.StartsWith("A"))//analog points
{
string[] precisionString = Regex.Split(unitsParam.Last(), ", ");
precision = int.Parse(precisionString[1]);
}
else
precision = null;
B)
if (ncPointType.StartsWith("A"))//analog points
precision = int.Parse(Regex.Split(unitsParam.Last(), ", ")[1]);
else
precision = null;
There is no right or wrong. This is opinion based really.
However, remember that whether you add braces, add comments, add whitespace or whatever, it doesn't affect the performance or the size of the final assembly because the compiler optimizes it very well. So, why not go with the more verbose so that other programmers can follow it easier?
This is basically subject to the coding standard you choose. There is no right or wrong, just personal preference.
Agree as a team what you prefer.
But even better is:
precision = ncPointType.StartsWith("A")?
int.Parse(Regex.Split(unitsParam.Last(), ", ")):
null;
This expresses the function beiong executed (set the precision),
and the conditions that control how it is set, in even less code,
- without creating unnecessary temporary variables to hold a temporary result that is not used anywhere else.
If you ask me both A and B are bad practice. You should always use braces regardless of whether or not it is one line or multiple lines. This helps to prevent bugs in the future when people add additional lines of code to your if or else blocks and don't notice that the braces are missing.
Sometimes having "more" code, like using temporary variables, etc., will make your code easier to debug as you can hover over symbols. It's all about balance, and this comes with experience. Remember that you may not be the only one working on your code, so clarity above all.
Ultimately it comes down to your choice because it has nothing to do with performance, but I would also note that you cannot instantiate or define variables if you omit the curly braces:
int a = 0;
if (a == 0)
int b = 3;
Is not valid, whereas:
int a = 0;
if (a == 0)
{
int b = 3;
}
Is valid.
It's easier to debug option A, but option B is more concise while still being readable. You could make it even more concise with a ternary operator:
precision = ncPointType.StartsWith("A") ? int.Parse(Regex.Split(unitsParam.Last(), ", ")[1]) : null;
Although it's far more readable this way (and still works the same way!):
precision = ncPointType.StartsWith("A") ?
int.Parse(Regex.Split(unitsParam.Last(), ", ")[1]) :
null;
It's best to stick with the standards used in your project. Readability is far more important for maintainability than having less lines of code. In both options, the efficiency is the same, so you don't need to worry about speed in this case.
As everyone else here points out, there are no hard and fast "rules" per se, but there should probably be braces around both block of code; both A and B have characteristics similar to the Apple goto bug because the introduce potential ambiguity.
Consider:
void Main()
{
int x=1;
if (x==1)
Console.WriteLine("1");
else if (x==2)
Console.WriteLine("NOT 1");
Console.WriteLine("OK");
}
will produce
1
OK
To someone scanning the code, especially if it's surrounded by other, innocuous looking code, this could easily be misread as "only print "OK" if x==2). Obviously some people will spot it, some won't, but why introduce the danger for the want of a brace of braces :)
For all you compiler gurus, I wanna write a recursive descent parser and I wanna do it with just code. No generating lexers and parsers from some other grammar and don't tell me to read the dragon book, i'll come around to that eventually.
I wanna get into the gritty details about implementing a lexer and parser for a reasonable simple language, say CSS. And I wanna do this right.
This will probably end up being a series of questions but right now I'm starting with a lexer. Tokenization rules for CSS can be found here.
I find my self writing code like this (hopefully you can infer the rest from this snippet):
public CssToken ReadNext()
{
int val;
while ((val = _reader.Read()) != -1)
{
var c = (char)val;
switch (_stack.Top)
{
case ParserState.Init:
if (c == ' ')
{
continue; // ignore
}
else if (c == '.')
{
_stack.Transition(ParserState.SubIdent, ParserState.Init);
}
break;
case ParserState.SubIdent:
if (c == '-')
{
_token.Append(c);
}
_stack.Transition(ParserState.SubNMBegin);
break;
What is this called? and how far off am I from something reasonable well understood? I'm trying to balance something which is fair in terms of efficiency and easy to work with, using a stack to implement some kind of state machine is working quite well, but I'm unsure how to continue like this.
What I have is an input stream, from which I can read 1 character at a time. I don't do any look a head right now, I just read the character then depending on the current state try to do something with that.
I'd really like to get into the mind set of writing reusable snippets of code. This Transition method is currently means to do that, it will pop the current state of the stack and then push the arguments in reverse order. That way, when I write Transition(ParserState.SubIdent, ParserState.Init) it will "call" a sub routine SubIdent which will, when complete, return to the Init state.
The parser will be implemented in much the same way, currently, having everything in a single big method like this allows me to easily return a token when I found one, but it also forces me to keep everything in one single big method. Is there a nice way to split these tokenization rules into separate methods?
What you're writing is called a pushdown automaton. This is usually more power than you need to write a lexer, it's certainly excessive if you're writing a lexer for a modern language like CSS. A recursive descent parser is close in power to a pushdown automaton, but recursive descent parsers are much easier to write and to understand. Most parser generators generate pushdown automatons.
Lexers are almost always written as finite state machines, i.e., like your code except get rid of the "stack" object. Finite state machines are closely related to regular expressions (actually, they're provably equivalent to one another). When designing such a parser, one usually starts with the regular expressions and uses them to create a deterministic finite automaton, with some extra code in the transitions to record the beginning and end of each token.
There are tools to do this. The lex tool and its descendants are well known and have been translated into many languages. The ANTLR toolchain also has a lexer component. My preferred tool is ragel on platforms that support it. There is little benefit to writing a lexer by hand most of the time, and the code generated by these tools will probably be faster and more reliable.
If you do want to write your own lexer by hand, good ones often look something like this:
function readToken() // note: returns only one token each time
while !eof
c = peekChar()
if c in A-Za-z
return readIdentifier()
else if c in 0-9
return readInteger()
else if c in ' \n\r\t\v\f'
nextChar()
...
return EOF
function readIdentifier()
ident = ""
while !eof
c = nextChar()
if c in A-Za-z0-9
ident.append(c)
else
return Token(Identifier, ident)
// or maybe...
return Identifier(ident)
Then you can write your parser as a recursive descent parser. Don't try to combine lexer / parser stages into one, it leads to a total mess of code. (According to the Parsec author, it's slower, too).
You need to write your own Recursive Descent Parser from your BNF/EBNF. I had to write my own recently and this page was a lot of help. I'm not sure what you mean by "with just code". Do you mean you want to know how to write your own recursive parser?
If you want to do that, you need to have your grammar in place first. Once you have your EBNF/BNF in place, the parser can be written quite easily from it.
The first thing I did when I wrote my parser, was to read everything in and then tokenize the text. So I essentially ended up with an array of tokens that I treated as a stack. To reduce the verbosity/overhead of pulling a value off a stack and then pushing it back on if you don't require it, you can have a peek method that simply returns the top value on the stack without popping it.
UPDATE
Based on your comment, I had to write a recursive-descent parser in Javascript from scratch. You can take a look at the parser here. Just search for the constraints function. I wrote my own tokenize function to tokenize the input as well. I also wrote another convenience function (peek, that I mentioned before). The parser parses according to the EBNF here.
This took me a little while to figure out because it's been years since I wrote a parser (last time I wrote it was in school!), but trust me, once you get it, you get it. I hope my example gets your further along on your way.
ANOTHER UPDATE
I also realized that my example may not be what you want because you might be going towards using a shift-reduce parser. You mentioned that right now you are trying to write a tokenizer. In my case, I did write my own tokenizer in Javascript. It's probably not robust, but it was sufficient for my needs.
function tokenize(options) {
var str = options.str;
var delimiters = options.delimiters.split("");
var returnDelimiters = options.returnDelimiters || false;
var returnEmptyTokens = options.returnEmptyTokens || false;
var tokens = new Array();
var lastTokenIndex = 0;
for(var i = 0; i < str.length; i++) {
if(exists(delimiters, str[i])) {
var token = str.substring(lastTokenIndex, i);
if(token.length == 0) {
if(returnEmptyTokens) {
tokens.push(token);
}
}
else {
tokens.push(token);
}
if(returnDelimiters) {
tokens.push(str[i]);
}
lastTokenIndex = i + 1;
}
}
if(lastTokenIndex < str.length) {
var token = str.substring(lastTokenIndex, str.length);
token = token.replace(/^\s+/, "").replace(/\s+$/, "");
if(token.length == 0) {
if(returnEmptyTokens) {
tokens.push(token);
}
}
else {
tokens.push(token);
}
}
return tokens;
}
Based on your code, it looks like you are reading, tokenizing, and parsing at the same time - I'm assuming that's what a shift-reduce parser does? The flow for what I have is tokenize first to build the stack of tokens, and then send the tokens through the recursive-descent parser.
If you are going to hand code everything from scratch I would definately consider going with a recursive decent parser. In your post you are not really saying what you will be doing with the token stream once you have parsed the source.
Some things I would recommend getting a handle on
1. Good design for your scanner/lexer, this is what will be tokenizing your source code for your parser.
2. The next thing is the parser, if you have a good ebnf for the source language the parser can usually translate quite nicely into a recursive decent parser.
3. Another data structure you will really need to get your head around is the symbol table. This can be as simple as a hashtable or as complex as a tree structure that can represent complex record structures etc. I think for CSS you might be somewhere between the two.
4. And finally you want to deal with code generation. You have many options here. For an interpreter, you might simply interpret on the fly as you parse the code. A better approach might be to generate a for of i-code that you can then write an iterpreter for, and later even a compiler. Of course for the .NET platform you could directly generate IL (probably not applicable for CSS :))
For references, I gather you are not heavy into the deep theory and I do not blame you. A really good starting point for getting the basics without complex, code if you do not mind the Pascal that is, is Jack Crenshaw's 'Let's build a compiler'
http://compilers.iecc.com/crenshaw/
Good luck I am sure you are going to enjoy this project.
It looks like you want to implement a "shift-reduce" parser, where you explicitly build a token stack. The usual alternative is a "recursive descent" parser, in which depth of procedure calls build the same token stack with their own local variables, on the actual hardware stack.
In shift-reduce, the term "reduce" refers to the operation performed on the explicitly-maintained token stack. For example, if the top of the stack has become Term, Operator, Term then a reduction rule can be applied resulting in Expression as a replacement for the pattern. The reduction rules are explicitly encoded in a data structure used by the shift-reduce parser; as a result, all reduction rules can be found in the same spot of the source code.
The shift-reduce approach brings a few benefits compared to recursive-descent. On a subjective level, my opinion is that shift-reduce is easier to read and maintain than recursive-descent. More objectively, shift-reduce allows for more informative error messages from the parser when an unexpected token occurs.
Specifically, because the shift-reduce parser has an explicit encoding of rules for making "reductions," the parser is easily extended to articulate what sorts of tokens could legally have followed. (e.g., "; expected"). A recursive descent implementation cannot easily be extended to do the same thing.
A great book on both kinds of parser, and the trade-offs in implementing different kinds of shift-reduce is "Introduction to Compiler Construction", by Thomas W. Parsons.
Shift-reduce is sometimes called "bottom-up" parsing and recursive-descent is sometimes called "top-down" parsing. In the analogy used, nodes composed with highest precedence (e.g., "factors" in multiplication expression) are considered to be "at the bottom" of the parsing. This is in accord with the same analogy used in "descent" of "recursive descent".
If you want to use the parser to also handle not-well-formed expressions, you really want a recursive descent parser. Much easier to get the error handling and reporting usable.
For literature, I'd recommend some of the old work of Niklaus Wirth. He knows how to write. Algorithms + Data Structures = Programs is what I used, but you can find his Compiler Construction online.
I was looking at some code length metrics other than Lines of Code. Something that Source Monitor reports is statements. This seemed like a valuable thing to know, but the way Source Monitor counted some things seemed unintuitive. For example, a for statement is one statement, even though it contains a variable definition, a condition, and an increment statement. And if a method call is nested in an argument list to another method, the whole thing is considered one statement.
Is there a standard way that statements are counted and are their rules governing such a thing?
The first rule of metrics is "be careful what you measure". You ask for a count of statements, that's what you're going to get. As you note, that figure is perhaps not actually relevant.
If you're interested in other measures, like how "complex" code is, consider looking into other code metrics, like cyclometric complexity.
http://en.wikipedia.org/wiki/Cyclomatic_complexity
UPDATE: Re: your comment
I agree that "doing too much" is an interesting metric. My rule of thumb is that one statement should have one side effect (usually a "local" side effect like mutating a local variable, but sometimes a visible side effect, like writing to a file) and therefore "number of statements" should be roughly correlated with how much the method is "doing" in terms of its number of side effects.
In practice, of course no one's code, my own included, actually meets that bar all the time. You might consider a metric for "how much the method is doing" to count not just statements but also, say, method calls.
To actually answer your question: I'm not aware of any industry standard that regulates what "number of statements" is. The C# specification certainly defines what a "statement" is lexically, but then of course you have to do some interpretation to do a count. For example:
void M()
{
try
{
if (blah)
{
Frob();
Blob();
}
}
catch(Exception ex)
{ /* eat it */ }
finally
{
Grob();
}
}
How many statements are there in M? Well, the body of M consists of one statement, a try-catch-finally. So is the answer one? The body of the try contains one statement, an "if" statement. The consequence of the "if" contains one statement -- remember, a block is a statement. The block contains two statements. The finally contains one statement. The catch block contains no statements -- a catch block is not a statement, lexically -- but it certainly is highly relevant to the operation of the method!
So how many statements is that altogether? One could make a reasonable case for any number from one to six, depending on whether you count blocks as "real" statements, whether you consider child statements as in addition to their parent statement or not, and so on. There is no standards body which regulates the answer to this question that I'm aware of.
The closest you might get to a formal definition of "what is a statement" would be the C# specification itself. Good luck working out whether a particular tool's measurement agrees with your reading of the specification.
Given that metrics are best used as a guide to better/worse code, and not a strict formula, does the exact definition used by the tool make much difference?
If I have three methods, with "statement lengths" of 2500, 1500 and 150, I know which method I'll be examining first; that another tool might report 2480, 1620 and 174 isn't too important.
One of the best tools I've seen for measuring metrics is NDepend, though again I'm not 100% sure what definitions it is using. According to the website, NDepend has 82 separate metrics, including Number of instructions and Cyclomatic Complexity.
The C# Metrics Tool defines the things being counted ("statements", "operands"), etc. by using a precise C# BNF language definition. (In fact, it precisely parses the code according a full C# grammar and then computes structural metrics by walking over the parse tree; SLOC count it gets by countline lines as you'd expect).
You might still argue that such a definition it unintuitive (grammars rarely are), but they are precise. I agree with other posters here, however, that the precise measure isn't as important as the relative value that one block of code has with respect to another. A value of "173.92" complexity just isn't very helpful by itself; compard to another complexity value of "81.02", we can say there's a good indication that the first one is more complex than the second, and that's enough to provide a focus of attention.
I think that metrics are also useful in trending; if last week, this code was "81.02" complex, ad this week it is "173.92", I should wonder why is all that happening inthis part of the code?
You might also consider a ratio of a structural metric (e.g., Cyclomatic) to SLOC as an indication of "doing too much", or at least an indication of writing code that is way too dense to understand
One simple metric is to just count the punctuation marks (;, ,, .) between tokens (so as to avoid those in strings, comments, or numbers). Thus, for (x = 0, y = 1; x < foo.Count; x++, y++) bar[y] = foo[x]; would count as 6.
Is there a C# library that provides the functionality of ">>" and "<<" for IO in C++? It was really convenient for console apps. Granted not a lot of console apps are in C#, but some of us use it for them.
I know about Console.Read[Line]|Write[Line] and Streams|FileStream|StreamReader|StreamWriter thats not part of the question.
I dont think im specific enough
int a,b;
cin >> a >> b;
IS AMAZING!!
string input = Console.ReadLine();
string[] data = input.split( ' ' );
a = Convert.ToInt32( data[0] );
b = Convert.ToInt32( data[1] );
... long winded enough? Plus there are other reasons why the C# solution is worse. I must get the entire line or make my own buffer for it. If the line im working on is IDK say the 1000 line of Bells Triangle, I waste so much time reading everything at one time.
EDIT:
GAR!!!
OK THE PROBLEM!!!
Using IntX to do HUGE number like the .net 4.0 BigInteger to produce the bell triangle. If you know the bell triangle it gets freaking huge very very quickly. The whole point of this question is that I need to deal with each number individually. If you read an entire line, you could easily hit Gigs of data. This is kinda the same as digits of Pi. For Example 42pow1048576 is 1.6 MB! I don't have time nor memory to read all the numbers as one string then pick the one I want
No, and I wouldn't. C# != C++
You should try your best to stick with the language convention of whatever language you are working in.
I think I get what you are after: simple, default formatted input. I think the reason there is no TextReader.ReadXXX() is that this is parsing, and parsing is hard: for example: should ReadFloat():
ignore leading whitespace
require decimal point
require trailing whitespace (123abc)
handle exponentials (12.3a3 parses differently to 12.4e5?)
Not to mention what the heck does ReadString() do? From C++, you would expect "read to the next whitespace", but the name doesn't say that.
Now all of these have good sensible answers, and I agree C# (or rather, the BCL) should provide them, but I can certainly understand why they would choose to not provide fragile, nearly impossible to use correctly, functions right there on a central class.
EDIT:
For the buffering problem, an ugly solution is:
static class TextReaderEx {
static public string ReadWord(this TextReader reader) {
int c;
// Skip leading whitespace
while (-1 != (c = reader.Peek()) && char.IsWhiteSpace((char)c)) reader.Read();
// Read to next whitespace
var result = new StringBuilder();
while (-1 != (c = reader.Peek()) && !char.IsWhiteSpace((char)c)) {
reader.Read();
result.Append((char)c);
}
return result.ToString();
}
}
...
int.Parse(Console.In.ReadWord())
Nope. You're stuck with Console.WriteLine. You could create a wrapper that offered this functionality, though.
You can Use Console.WriteLine , Console.ReadLine ..For the purpose.Both are in System NameSpace.
You have System.IO.Stream(Reader|Writer)
And for console: Console.Write, Console.Read
Not that I know of. If you are interested of the chaining outputs you can use System.Text.StringBuilder.
http://msdn.microsoft.com/en-us/library/system.text.stringbuilder(VS.71).aspx
StringBuilder builder = new StringBuilder();
builder.Append("hello").Append(" world!");
Console.WriteLine(builder.ToString());
Perhaps not as pretty as C++, but as another poster states, C# != C++.
This is not even possible in C#, no matter how hard you try:
The left hand side and right hand side of operators is always passed by value; this rules out the possibility of cin.
The right hand side of << and >> must be an integer; this rules out cout.
The first point is to make sure operator overloading is a little less messy than in C++ (debatable, but it surely makes things a lot simpler), and the second point was specifically chosen to rule out C++'s cin and cout way of dealing with IO, IIRC.
This is perfectly fine C# code and works fine provided correct URL. But the everything is just done at one line by reducing the readability of the code.
Here is the code :
return new StreamReader(WebRequest.Create(urlName).GetResponse().GetResponseStream()).ReadToEnd();
I am just wondering what are the opinions of fellow developers on this kind of short cut way of writing code
Push it into a well-named method, and perhaps break it up so that single statment stretches over a couple lines. I'd also probably use WebClient:
return new WebClient().DownloadString(urlName);
No, it's not really perfectly fine C# code. You should dispose the StreamReader, so at least have a using statement:
using (StreamReader reader = new StreamReader(WebRequest.Create(urlName).GetResponse().GetResponseStream()) {
return reader.ReadToEnd();
}
That code may gain a bit readability by dividing it into more lines, but not very much.
Generally I prefer readable code before compact code. Having one statement on each line makes the code easier to read and understand. For example:
if (i <= 4) i = 4 - i;
This becomes more readable with the if statement on one line and the code inside it on a separate line, with the if statement always having brackets:
if (i <= 4) {
i = 4 - i;
}
This code is of course rather readable even in the compact form, but the more complex the code is, the more it gains from putting each statement on a separate line.
...YUCK.
I will sometimes combine a few things into one line, usually when I am dumping stuff to a stream, but never this much.
Most compilers (c++ compilers at least) will often inline variable definitions if the definition is used only once, so if you make a one time use, throw away variable. Your C# compiler will probably just replace its name with its definition.
In addition to the readability problem, you should dispose any IDisposble object you are using.
One statement != one line , you can improve readability by improving formatting of your code. Of course you should not assume other people use high resolution monitors.