Ternary operator; What is wrong with this syntax? - c#

I'm trying to create a MailMessage, and I'm getting the following error...
Cannot implicitly convert type 'string' to 'bool'
This is my init statement:
MailMessage msg = new MailMessage("DoNotReply#optoma.com",
myTbl.Rows[i]["Requester"].ToString().Trim(),
subject,
"Dear " + myTbl.Rows[i]["Ship_Attention"].ToString() + ",<br/><br/>" +
body + "<br/>Your ISO ID is " + myTbl.Rows[i]["ISO_ID"].ToString() +
(Convert.ToInt32(myTbl.Rows[i]["EmailType"]) == 1) ?
("<br/>Tracking Number: " + myTbl.Rows[i]["Tracking_No"].ToString()) :
("") + "<br/><br/>Please examine the loaned items for this transaction:<br/><br/>" +
sw.ToString());
I'm trying to add to the string at runtime based on a boolean expression. Why can't I do this? Am I not doing it right?
string + (true | false) ? "somestring" : "anotherstring" + string

the ? : operator has very low precedence. Put it in parenthesis and I think you'll resolve your issue.
((true|false)?"somestring":"anotherstring")

When you have string + (bool)?"somestring":"anotherstring" + string the + gets evaluated before the ?, so you need parentheses:
string + ((bool)?"somestring":"anotherstring") + string

just cleaning it up a wee bit.... and you won't run into operator precedence problems so much
void SendMessage(DataRow row, string subject, string body, string sw)
{
var to = row["Requester"].ToString().Trim();
var isoId = row["ISO_ID"].ToString();
var attention = row["Ship_Attention"].ToString();
var emailType = Convert.ToInt32(row["EmailType"]);
var message = (emailType == 1) ? ("<br/>Tracking Number: " + row["Tracking_No"]) : ("");
MailMessage msg = new MailMessage("DoNotReply#optoma.com",
to,
subject,
string.Format("Dear {0},<br/><br/>{1}<br/>Your ISO ID is {2}{3}<br/><br/>Please examine the loaned items for this transaction:<br/><br/>{4}",
attention, body, isoId, message, sw));
}

The precedence isn't what you expect -- + is being evaluated first. Your code should be in the form:
string + (true|false ? "somestring" : "anotherstring") + string
For your specific example:
MailMessage msg = new MailMessage("DoNotReply#optoma.com", myTbl.Rows[i]["Requester"].ToString().Trim(),
subject, "Dear " + myTbl.Rows[i]["Ship_Attention"].ToString() + ",<br/><br/>" +
body + "<br/>Your ISO ID is " + myTbl.Rows[i]["ISO_ID"].ToString() + (Convert.ToInt32(myTbl.Rows[i]["EmailType"]) == 1 ? ("<br/>Tracking Number: " + myTbl.Rows[i]["Tracking_No"].ToString()) : ("")) + "<br/><br/>Please examine the loaned items for this transaction:<br/><br/>" +
sw.ToString());
Note that this is a very long expression and should probably be broken down into several statements to make it more readable and maintainable.

The additive oprator (+) has higher priority than conditional (?:) as indicated here: http://msdn.microsoft.com/en-us/library/aa691323%28v=vs.71%29.aspx.
Therefore you need to put parenthesis around the whole condition:
string + ((true|false)?"somestring":"anotherstring") + string
I suggest you to divide your code into more lines, introduce some temporary variables and use string.format() to make it look clener. Finding errors in clean code is much easier.

Related

How to use SyntaxFactory for roslyn

I am trying to generate code using SyntaxFactory but stuck in converting one area Please see the code below I left comment where I am finding it difficult and used string manipulation.
The idea is there will be two variable removeExpression and getExpression which are of type ExpressionSyntax and finally both will be used to become the body of a anonymous function.
ExpressionSyntax removeExpression = SyntaxGenerator.MethodInvokeExpression(
valueExpression,
"RemoveAt",
BinaryExpression(
SyntaxKind.SubtractExpression,
SyntaxGenerator.PropertyAccessExpression(valueExpression, nameof(Enumerable.Count)),
atExpression
)
);
ExpressionSyntax getExpression = SyntaxGenerator.MethodInvokeExpression(valueExpression, nameof(Enumerable.First));
// Help me to convert the below line using SyntaxFactory.
IdentifierName("((Func<dynamic>)(() => { var res = " + getExpression.ToString() + ";" + removeExpression.ToString() + "; return res" + " ; }))(); ");

QueryString is taking first substring and discarding rest post space

I have a query string which passes 6 parameters in C# as shown below
string url = "Report.aspx?Desc=" + Desc.SelectedValue + "&PON=" + PNumber.Text + "&InsNme=" + ins.ToUpper().ToString() + "&BackTy=" + cb.SelectedValue + "&StartDate=" + txtDate.Text + "&EndDate=" + txtTodate.Text + "&Name=" + nme;
string s = "window.open('" + url + "', 'popup_window', 'width=1500,height=800,left=200,top=150,resizable=yes');";
ClientScript.RegisterStartupScript(this.GetType(), "script", s, true);
Now, in the above string InsNme contains a value of John Patrice Joanne. Instead of complete value of InsNme Report.aspx contains just John. How to handle this?
The spaces in the name are breaking the URL.
If you want to do it yourself, replace spaces with %20. Otherwise a simple, but not anywhere near "good" technique is:
url = "Report.aspx?";
// for each name value pair ...
url += dataLabel + "=" + System.Web.HttpUtility.UrlEncode( dataChunk ) +"&";
The utility is preferred as it will take care of other, similar issues such as literal '&' in a name.
Check this answer for better solutions.
How to build a query string for a URL in C#?

set string to a fixed space?

I have some vehicle information that I want to send in an email.
I have all code working but spacing out the information is a problem. Each vehicle has a checklist and that checklist then gets emailed. So I loop through the list and get the defect and the comment.
foreach (var item in chkList.CheckItems)
{
if (item.Defect == true)
{
defect += string.Format("{0,-40} {1}\n", item.ItemTitle, item.Comment);
}
}
if (hasDefect == true)
{
Utils.ChecklistSendMail("Checklist", ToAddresses.Split(';'),
"Vehicle Reg: " + reg + "\n" +
"Checklist No: " + chkList.CheckListNo + "\n"+
"Date: " + ChecklistDate.ToShortDateString() + "\n" +
"Defects: Comments: " + "\n" +
defect);
}
Email then looks like this:
Vehicle Reg: XLZ 8194
Checklist No: 0
Date: 22/03/2016
Defects: Comments:
Vehicle Secure comment1
Brakes comment2
I want the defects and the comments to be displayed like this:
Defects: Comments:
Vehicle Secure comment1
Brakes comment2
Since Vehicle Secure is longer than Brakes the comment is being pushed further out. But is there a way to fix the string at a certain position no matter how long first word is?
EDIT
code now looks like this:
string defect = "";
string comment = "";
string aheading = "Defects:";
string bheading = "Comments:";
foreach (var item in chkList.CheckItems)
{
if (item.Defect == true)
{
defect += item.ItemTitle;
comment += item.Comment;
}
}
string result = aheading.PadRight(20, ' ') + bheading.PadRight(20, ' ') + Environment.NewLine +
defect.PadRight(20, ' ') + comment.PadRight(20, ' ') + Environment.NewLine;
But the output looks like this:
Defects: Comments:
Vehicle SecureBrakestest1test2
If you really want to do this with spaces, you need to determine the label with the most characters and how much space you want after that. This creates a total number of characters. From this, you subtract the number of characters of the label to get the number of spaces necessary to line up the value.
However, you could just use a <table> or some other html.
A potential, quick and dirty solution would require you to generate the html as a part of your code. I seriously advise against some homegrown html generator logic. Invariably the data involved in the email becomes more complex. This leads to mixing code that is getting the data for the template and building the html, which is painful to debug. Also there are plenty of html templating solutions out there. You'd really be just reinventing the wheel to take on technical debt and the maintenance of more code.
A better solution would be use something like MvcMailer and build an html template. You then pass the template and a context object to the engine to render the resultant html.
Try and use String padding with ' ' as char
public string PadRight(
int totalWidth,
char paddingChar)
This method would complete the length of the string with the chosen char. by specifying the max length of the string and replacing the remaining length with " " (space). you can always have the strings aligned.
Read more about PadRight or PadLeft
string Defects ="Example"
Defects.PadRight(20," ");
Result: "Example "
Edit : Example Code .Please have a look at this code and check what you are doing wrong
string aheading = "Defects:";
string bheading ="Comments:";
string b = "Vehicle Secure";
string bComment = "My Comment value";
string c = "Brakes";
string cComment = "My Comment value";
string result= aheading.Trim().PadRight(20,' ')+bheading.Trim().PadRight(20,' ')+ Environment.NewLine +
b.Trim().PadRight(20, ' ') + bComment.Trim().PadRight(20, ' ') + Environment.NewLine +
c.Trim().PadRight(20,' ')+cComment.Trim().PadRight(20,' ')+Environment.NewLine ;
Console.WriteLine(result);
Edit:Answer based on the code you Posted
string aheading = "Defects:";
string bheading = "Comments:";
string result = aheading.PadRight(20, ' ') + bheading.PadRight(20, ' ') + Environment.NewLine ;
foreach (var item in chkList.CheckItems)
{
if (item.Defect == true)
{
string result += item.ItemTitle.Trim().PadRight(20,' ') + item.ItemTitle.Trim().PadRight(20,' ') + Environment.NewLine ;
}
}
Console.WriteLine(result);

Issue with string in c#?

I am creating a string in c#.
string jsVersion = #"function getContent() {
var content = " + "\"" + documentString + "\"" + #"
return content;
}";
The documentString variable contains a huge string which have line breaks also. Now in javascript when i load this string the content variable does not contains a valid string (because of line breaks).
Now how can i create a string which is valid even if there is line breaks ?
You can use HttpUtility.JavaScriptStringEncode
Can you use string.format instead of concatenation in this fashion?
An example:
string jsVersion = string.format("function getContent() {var content = '{0}'return content; }",documentString);
This will replace your line breaks with <br/>:-
stringToDecode.replace(/\n/, '<br />')
If you want to get rid of the line breaks just remove # from the sting.
# acts a verbatim for your string and therefor adds the line breaks you entered with your declaration.
string jsVersion = "function getContent() {
var content = " + "\"" + documentString + "\"" + "
return content;
}";
should do the trick.

Why is the null coalescing operator breaking my string assignment in c#?

I'm creating a query string in a web form, and I'm dealing with values from the parameters that might be null. There are lots of ways to check and fix these, but the most elegant one I found is the following:
string pass;
pass = "BillabilityDetail.aspx?_startDate=" + _startDate.Text + "&_endDate=" + _endDate.Text +
"&_isContractor=" + _isContractor.SelectedValue + "&_busUnit=" + _busUnit.Text
+ "&_projectUnit=" + _projectUnit.SelectedValue + "&_leadCon=" + _leadCon.Value ?? -1
+ "&_acctExec=" + _acctExec.Value ?? -1 + "&_isBillable=" + _isBillable.SelectedValue +
"&_isActive=" + _isActive.SelectedValue + "&_include=" + _include.SelectedValue;
The only issue is... it doesn't work. When the code reaches this part,
"&_leadCon=" + _leadCon.Value ?? -1 + "&_acctExec=" + _acctExec.Value ?? -1
the string stops assigning values. So the string would end with &_leadCon=.
I know of ways to work around this, but I don't know why it stopped working in the first place. Any tips?
The + has higher precedence than ??, thus you need to surround your null-coalescing expressions in parenthesis.
"&_leadCon=" + (_leadCon.Value ?? -1) + "&_acctExec=" + (_acctExec.Value ?? -1 )
See the precedence chart here
Try using parentheses to tell the compiler exactly what you mean.
For example:
"&_leadCon=" + (_leadCon.Value ?? -1) + "&_acctExec=" + (_acctExec.Value ?? -1)
You need to add braces i.e.
"&_leadCon=" + (_leadCon.Value ?? -1) + "&_acctExec=" + (_acctExec.Value ?? -1)
If you look at the precedence of operators in C# (more up to date but slightly less helpful version here), then you can see + comes above ??.
This means you are actually asking for most of your statement after ?? to be treated as one block.
So,
string test = "hello" + value ?? "this is" + " a test"
actually means:
Add "hello", then add "this is" + " a test" if value is null, otherwise add value itself.
So you probably want brackets in there as other answers said. I just thought I'd try and explain it a bit more.
There are more issues than you think:
As you said, it does not work
There are about 20 string creations (srting is immutable, string + string creates a new string and copies the contents of strings into it, so it's lot of memory copying). Hovewer, C# compiler makes an optimization for you, so this time you are lucky.
It barely readable
Consider using String.Format method.
string urlTemplate = 'BillabilityDetail.aspx?_startDate={0}&_endDate={1}';
pass = String.Format(urlTemplatel, _startDate.Text, _endDate.Text);
Also, as others pointed out, there are operator preceence errors (+ has higher precedence than ??), but this approach is free of it, as those coalescing operators will reside in parameter construction.

Categories

Resources