Is this a bug in Visual Studio 2010 compiler? - c#

DateTime? date = null;
string tmp = "a" + "(" + date ?? "blablabla" + ")";
Console.WriteLine(tmp);
This will print something close to: 'a ('.
Is this a bug with null-coalescing operator?
If I put date ?? "blablabla" in parenthesis, it is underlined as error.

Null-coalescing operator ?? has a lower precedence than the + operator, so your code is equal to
string tmp = ("a" + "(" + date) ?? ("blablabla" + ")");
Since everything in the + operation with a string produces a string (by calling .ToString() on all non-string operands), your code will always produce the "a(" string.

First, you should always assume it's your fault, not the compiler's fault; select isn't broken. Do you honestly think the Visual Studio 2010 implementation of the ?? operator hasn't been battle tested? When you encounter something that doesn't match your expectations, check your expectations. Get out the manual, and make sure that you understand exactly what is suppose to happen. In this case, open the language specification.
If you proceed to §1.4 of the specification, you'll see a table that groups operators into precedence groupings; you can also find it online. In particular, the null coalescing operator ?? is near the bottom, above only the lowly conditional ternary operator and assignments and =>. It is below the additive operator. Thus, your statement
string tmp = "a" + "(" + date ?? "blablabla" + ")";
is treated by the compiler as
string tmp = (("a" + "(" + date) ?? ("blablabla" + ")"));
I'm not going to be completely pedantic and also parenthesize the first additive expression1. Since the left-hand-side of the expression in that statement is never null, of course it always assigns "a(" (or "a(" + date.ToString() when date.HasValue is true) to tmp.
The main point is that you had an incorrect expectation as to what should be happening that you should have verified against the manual.
If I put date ?? "blablabla" in parenthesis, it is underlined as error.
Of course it is. Did you even read the error message? It probably tells you that you can't do ?? on a DateTime? and a string because there are no implicit conversions between DateTime? and string in either direction. This, too, is covered in the language specification; see §7.13. You have to read this message and respond to it. To get something semantically equivalent to what you're trying to express, you'll have to resort to the conditional ternary operator:
date.HasValue ? date.ToString() : "blablabla"
and then wrap that whole thing in parentheses because the conditional ternary operator has very low precedence.
Finally, I find a correctly parenthesized version of your code rather ugly, not fun to read, and probably not enjoyable to maintain. Just make it simple, please:
var tmp = String.Format("a({0})",
date.HasValue ? date.ToString() : "blablabla");
Now it is so clear what is going on and what is going to happen. I don't have to think to understand it. Save your thinking for the difficult problems you'll encounter.
1: Be careful. We would need to add in a method call to date.ToString (which has the highest precedence) before attempting to correctly figure out what is evaluated first.

Here just another version:
DateTime? date = null;
string tmp = string.Format("a({0})",
date.HasValue ? date.ToString() : "blablabla");
I really love string.Format instead of concatenation.

"blablabla" is not a date, so you can't use is to set a date?.
string tmp = "a" + "(" + date ?? "blablabla" + ")";
is equivalent to
string tmp = ("a" + "(" + date) ?? ("blablabla" + ")");
which is where your a( is coming from.
However
string tmp = "a" + "(" + (date ?? DateTime.Now) + ")";
or similar should work.

From C# Language Specification §1.4
The following table summarizes C#’s operators, listing the operator
categories in order of precedence from highest to lowest. Operators in
the same category have equal precedence.
It says Additive operators is higher precedence than null coalescing operator.
So, + has higher precedence than ?? and that's why "blablabla" + ")" expression works first.
And since date is null, the statement works like;
string tmp = "a" + "(" + null;
And normally result will be a(

This is most likely because date isn't a string and the ?? operator can't determine a common base type for date and "blablabla". Try (date.ToString() ?? "blablabla"). But this won't satisfy your need either because date.ToString() will never be null.
string tmp = "a" + "(" + (date ?? DateTime.Now) + ")";
should work.

It's not a bug with the null-coalescing operator.
It's operator precedence:
"a" + "(" + date ?? "blablabla" + ")"
is the same as:
("a" + "(" + date.ToString() ) ?? ( "blablabla" + ")" )
and ("a" + "(" + date.ToString() ) is not null.

Related

How to get number value with Decimal from DataReader

According to the SQL queries below, I need to get a number value 2083.10, but when try to use the code to get int value from dbreader, it will be only 2083. the demical were gone.
string SQLCash = #"SELECT sum(t2.Cash-Change) AS Cash
FROM dbFBHdr t1, dbFBCollection t2
WHERE t1.Branch = t2.Branch
AND t1.CashNo = t2.CashNo
AND t1.CashDate >= '" + PDC.DateFrom + "' " +
"AND t1.CashDate <= '" + PDC.DateTo + "' " +
"AND t1.Status = 'CLOSED'";
FbCommand cmdCASH = new FbCommand(SQLCash, FbCon);
cmdCASH.ExecuteNonQuery();
FbDataReader readerCASH = cmdCASH.ExecuteReader();
while (readerCASH.Read() == true)
{
if (readerCASH["Cash"].ToString() == "")
{
PDC.CASH = "0";
}
else
{
PDC.CASH += String.Format("{0:n}",readerCASH["Cash"]);
PDC.TOCASH = readerCASH.GetInt32(readerCASH.GetOrdinal("Cash"));
}
}
And This is the code which I use it to get Int value from SQL
PDC.TOCASH = readerCASH.GetInt32(readerCASH.GetOrdinal("Cash"));
Since you need to Gets the value as a Decimal object, You need to use SqlDataReader.GetDecimal(Int32) method instead:
readerCASH.GetDecimal(readerCASH.GetOrdinal("Cash"));
Because the GetInt32 method will get the value as a 32-bit signed integer. Also you need to change the TOCASH's type to decimal. Also you should always use parameterized queries to avoid SQL Injection. Something like this:
AND t1.CashDate >= #DateFrom
yourCommand.Parameters.AddWithValue("#DateFrom", PDC.DateFrom);
//And other parameters also
Although specify the type directly and use the Value property is better than AddWithValue. See this https://blogs.msmvps.com/jcoehoorn/blog/2014/05/12/can-we-stop-using-addwithvalue-already/
Don't use GetInt32 if you want to get value as decimal, use GetDecimal
PDC.TOCASH = readerCASH.GetDecimal(readerCASH.GetOrdinal("Cash"));
You are formatting it to be without commas so it will be return as it is integer
PDC.CASH += String.Format("{0:n2}",readerCASH["Cash"]);
n2 means 2 digits after comma also i suggest you to use {0:c2} if you are working with currency
If you not sure to which .Net type will be mapped initial RDBMS one (e.g. Number(16, 4) -> ? will it be Single, Double or Decimal?) you can try converting:
decimal result = Convert.ToDecimal(readerCASH["Cash"]);

Why does LastName not show in C# string concat operator below [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 5 years ago.
Improve this question
I've got code like the following where adding the ?? operator causes last to disappear.
Expected Result: was that if first was null then first would be replaced by "" and that "" would be concatinated with last giving just last as the result.
Actual Result: What happened was the result I got was just first.
var first = "Joe";
var last = "Smith"
var str1 = first + last; // gives "JoeSmith"
var str2 = first ?? "" + last // gives "Joe"
It's a matter of precedence. + binds more tightly than ??, so your code is effectively:
var str2 = first ?? ("" + last)
It sounds like you probably meant:
var str2 = (first ?? "") + last
But there's no point, given that string concatenation with null is equivalent to string concatenation with an empty string - so just use first + last as you already have with str1.
This is the expected behavior of the null coalescing operator ??. It will use the first value, unless it is null in which case it will fall to the second. Consider how this appears with the variables replaced:
var str2 = "Joe" ?? "" + "Smith";
Since "Joe" isn't null, it will set str2 to that and ignore the rest of the expression. If you wanted to only coalesce the first name, then you would need to group it with parentheses to replace any null instances of first with the empty string:
var str2 = (first ?? "") + last;
However, this really doesn't make any difference from your existing code, as your null will simply be an empty string and yield the same thing.
From MSDN:
The ?? operator is called the null-coalescing operator. It returns the left-hand operand if the operand is not null; otherwise it returns the right hand operand.
Since first is not null it returns "Joe"

C# weird string behaviour?

I have a string variable as below:
string testVar = "abc ";
Then I have a if statement as below:
if(this.testVar[this.testVar.Length-1].Equals(" "))
From the above I'm trying to find if the last character is space, if it is space then do something. But it is always false even if my testVar = "abc "?
testVar[…] returns a char, not a string. That’s why an Equals test with a string always returns false. You can fix this easily by comparing to a char. you also don’t need Equals:
if (testVar[testVar.Length - 1] == ' ')
It is worth nothing that, if you had used == initially instead of Equals, you would have gotten a compile time error explaining the problem. This illustrates nicely why it’s good to use early binding rather than late binding (Equals takes an object and hence doesn’t offer compile-time type checking).
Why do you not just use:
if (testVar.EndsWith (" "))
It is always false because a char is never equal to a string.
This would work:
if (this.testVar[this.testVar.Length-1].Equals(' '))
or this
if (this.testVar[this.testVar.Length-1] == ' ')
check this dude
var result = str.Substring(str.LastIndexOf(' ') + 1);

String concatenation with null-coalescing operator

I was trying to build a string like the following and I noticed that it gets cut off after using the ?? operator, regardless of whether the previous value is null.
"Some Text" + System.Environment.NewLine +
varOne.ToString() ?? string.Empty + System.Environment.NewLine +
varTwo.ToString()...
All that the string contains (regardless of the values) is up to varOne (Some Text + newline + varOne) unless I remove the ?? operator. After looking around a bit I see that this is not the preferred way of doing this and that I should probably use a stringbuilder instead but I was just curious as to why this happens?
Have a look at ?? Operator (C# Reference)
The ?? operator is called the null-coalescing operator and is used to
define a default value for nullable value types or reference types. It
returns the left-hand operand if the operand is not null; otherwise it
returns the right operand.
This implies, stuff after ?? is only assigned, if stuff before it is null.
So
string sNull = null;
string s = sNull ?? "TADA";
s would be TADA
and
string sNull = null;
string s = sNull ?? "TADA";
string sNormal = s ?? "NOT TADA";
sNormal would also be TADA
Try :
"Some Text" + System.Environment.NewLine +
(varOne == null ? string.Empty : varOne.ToString()) + System.Environment.NewLine +
varTwo.ToString()...
varOne.ToString() is never null. And suppose we have a ?? b + c + d ?? n, if a != null the whole thing eveluates to a and not a + (d ?? n) (because of operators precedence)
The ?? operator means "if the thing before this operator is not null, use it, otherwise use the thing after this operator".
What you might be getting confused by is what constitutes "the thing before this operator". In your case, it's the whole of this:
"Some Text" + System.Environment.NewLine + varOne.ToString()
That's never going to be null. Even if varOne.ToString() returned null (which would be a bug in varOne's class, since ToString() should never return null), the result of concatenating a string with null is the original string. There's absolutely no situation in which the above could result in null.
Now, varOne could be null, and in that case you'd get an exception. It's possible that this is what you think you're guarding against, but it isn't the case. If that's really what you want, you'd need something like this:
"Some Text" + System.Environment.NewLine +
(varOne != null ? varOne.ToString() : string.Empty) + System.Environment.NewLine +
varTwo.ToString()...
This checks that varOne is not null, uses varOne.ToString if it isn't, and falls back to string.Empty if it is.
Note that I've avoided the whole issue of this coding style versus the use of StringBuilder, since that isn't actually part of the question.
Nowadays the answer has changed. You could:
"Some Text" + System.Environment.NewLine +
// no need to coalesce because concatenating nulls are ignored
varOne?.ToString()
System.Environment.NewLine + varTwo.ToString()
or even
$"Some Text{System.Environment.NewLine}{varOne}{System.Environment.NewLine}{varTwo}"
// If you're not writing to a system-dependent file, \r\n will also work fine:
$"Some Text\r\n{varOne}\r\n{varTwo}"

Automatic casting to string in C# and VB.NET

I could do this in C#..
int number = 2;
string str = "Hello " + number + " world";
..and str ends up as "Hello 2 world".
In VB.NET i could do this..
Dim number As Integer = 2
Dim str As String = "Hello " + number + " world"
..but I get an InvalidCastException "Conversion from string "Hello " to type 'Double' is not valid."
I am aware that I should use .ToString() in both cases, but whats going on here with the code as it is?
In VB I believe the string concatenation operator is & rather than + so try this:
Dim number As Integer = 2
Dim str As String = "Hello " & number & " world"
Basically when VB sees + I suspect it tries do numeric addition or use the addition operator defined in a type (or no doubt other more complicated things, based on options...) Note that System.String doesn't define an addition operator - it's all hidden in the compiler by calls to String.Concat. (This allows much more efficient concatenation of multiple strings.)
Visual Basic makes a distinction between the + and & operators. The & will make the conversion to a string if an expression is not a string.
&Operator (Visual Basic)
The + operator uses more complex evaluation logic to determine what to make the final cast into (for example it's affected by things like Option Strict configuration)
+Operator (Visual Basic)
I'd suggest to stay away from raw string concatenation, if possible.
Good alternatives are using string.format:
str = String.Format("Hello {0} workd", Number)
Or using the System.Text.StringBuilder class, which is also more efficient on larger string concatenations.
Both automatically cast their parameters to string.
The VB plus (+) operator is ambiguous.
If you don't have Option Explicit on, if my memory serves me right, it is possible to do this:
Dim str = 1 + "2"
and gets str as integer = 3.
If you explicitly want a string concatenation, use the ampersand operator
Dim str = "Hello " & number & " world"
And it'll happily convert number to string for you.
I think this behavior is left in for backward compatibility.
When you program in VB, always use an ampersand to concatenate strings.

Categories