Take a look at this code:
System.Web.SessionState.HttpSessionState ss = HttpContext.Current.Session["pdfDocument"] ?? false;
if ((Boolean)ss)
{
Label1.Text = (String)Session["docName"];
}
Basically I want to check if HttpContext.Current.Session["pdfDocument"] is not null, and if it isn't to cast to Boolean, then check if its true or false.
I'm trying to avoid nested if statements and figured there would be a more elegant way to do it. I'm therefore only interested in answers that contain the conditional ? operator.
Any tips?
Why do you use ss variable?
What about this:
if (HttpContext.Current.Session["pdfDocument"] != null)
{
Label1.Text = (String)Session["docName"];
}
object ss = HttpContext.Current.Session["pdfDocument"] ?? false;
if ((Boolean)ss)
{
Label1.Text = (String)Session["docName"];
}
Not sure exactly what you're asking for, how about:
System.Web.SessionState.HttpSessionState ss;
Label1.Text = (Boolean)((ss = HttpContext.Current.Session["pdfDocument"]) ?? false) ? (String)Session["docName"] : Label1.Text;
Should leave ss with either a valid session or null, avoids the problem of trying to store false to ss and completely skips the subsequent 'if'. Though there's a repetition of Label1.Text.
Note: this has been edited to take account of the comment by Dave below.
The problem is that you can't do this:
SessionState.HttpSessionState ss = false;
Try putting your nested ifs into an extension method then call that instead.
HttpContext.Current.Session is an System.Web.SessionState.HttpSessionState object, which is a hash or dictionary, as some may call it, of different objects, so unless you're storing an HttpSessionState object as the "pdfDocument" location the first line is incorrect.
If you're actually storing a bool in the "pdfDocument" location which may or may not already be in this slot, you could cast that directly to a bool and null coalesce it: var ss = (bool)(HttpContext.Current.Session["pdfDocument"] ?? false);.
If you're possibly storing some other kind of object in the "pdfDocument" location you could just see if it's currently at that location by checking for null: var ss = HttpContext.Current.Session["pdfDocument"] != null;.
You can try this, though I don't know if it fits your aesthetics:
bool isPdfDocumentSet =
bool.TryParse((HttpContext.Current.Session["pdfDocument"] as string,
out isPdfDocumentSet)
? isPdfDocumentSet
: false;
EDIT: There is actually an even more concise way of doing it:
bool isPdfDocumentSet =
bool.TryParse(HttpContext.Current.Session["pdfDocument"] as string,
out isPdfDocumentSet) && isPdfDocumentSet;
I think the closest you will get to the solution taking that path is following:
System.Web.SessionState.HttpSessionState ss = HttpContext.Current.Session["pdfDocument"];
if (ss != null)
{
Label1.Text = (String)Session["docName"];
}
Related
In the below code, I am repeating the same code twice except one change. If there is a way to write the same in single line then it would be great.
The only changes I made is Obsc and zp based on the if..else statement.
var zp = __Services.GetValue("Z", Order.Code);
var St="";
if(sp.Label != null)
{
var Obsc = _Services.GetValue("Z", sp.Label);
St= string.Format(Obsc, .......,userProfile.DisplayName());
}
else
{
St = string.Format(zp, ......., userProfile.DisplayName());
}
Are you happy with something like this?
var code = sp.Label is null
? Order.Code
: sp.Label;
var zpOrObsc = service.GetValue("Z", code); // please use a valid variable name
var st = string.Format(zpOrObsc, ......, userProfile.DisplayName());
St = string.Format(_Services.GetValue("Z", sp.Label ?? Order.Code), ......., userProfile.DisplayName());
Make a variable to determine which parameter value you want to call GetValue with. You only need to call GetValue once and string.Format once.
var whateverTheSecondParamForGetValueIs = Order.Code;
if (sp.Label != null) {
whateverTheSecondParamForGetValueIs = sp.Label;
}
var zp = _Services.GetValue("Z", Order.Code);
var St = string.Format(zp, ......., userProfile.DisplayName());
No, this isn't a "single line", but I don't see the appeal in that. To me, this is much more readable than any ternary operator.
I'm also going to say that these variable names need quite an improvement. They don't convey any meaning.
The ternary (*) operator, also known as the "conditional operator" is basically a short-hand for "if then else " and is written like so:
result = condition ? trueValue : falseValue;
It is not comparable to an actual if ... else ... statement as it is an expression and must provide a value.
See its documentation in the C# language reference for full details: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/conditional-operator.
*) So called because it is the only operator that takes 3 arguments. Compare with "binary operator" and "unary operator".
Please forgive me the noob question, but C# is not my native language. In code I took over, I stumbled upon
var success = true;
success = Upload.Status == FileStatus.Ok;
In there, FileStatus is of type enum, somewhere custom defined. I guess, success is essentially non-nullable Boolean. I think that the 2nd line sets success to false if (and only if) Upload.Status == FileStatus.Ok, which would also induce that the latter two variables should be of same type.
Could you please let me know, whether my hypotheses are correct? Also: How is such a construct called? What is it short for?
success is going to be a bool.
It is initialized with true, but that should be unessesary.
var success = true;
And will then be set to the result of (Upload.Status == FileStatus.Ok) which is a bool.
success = Upload.Status == FileStatus.Ok;
Think of it as success = (Upload.Status == FileStatus.Ok); if that helps.
And yes, it took me a moment to parse it too. I have a profound dislike for people trying to save lines at the cost of readability. I would use this:
if(Upload.Status == FileStatus.Ok)
success = true;
else
success = false;
Maybe use the shorter if syntax.
Upload.Status == FileStatus.Ok evaluates to a bool, either true or false. success will be assigned the result of that evaluation.
It's no more mystical than var sum = 4 + 5; resulting in sum being assigned a value of 9.
It's assigning the result of an expression to a variable, same as var x = 1 + 2; just that in this case the expression is of type bool.
Needlessly verbose, this would be the same:
bool success;
if (Upload.Status == FileStatus.Ok)
{
success = true;
}
else
{
success = false;
}
I declare the variable setPassword outside of the loop and then give it a value within the loop. Then in the next do-while loop I try to use the value assigned but it says "Use of unassigned local variable".
profile[I] is an array of objects that are created prior to the loops. Is the value being assigned in the loop not saving or is the value of profile[I].Password null because the object hasn't been created yet?
bool good = false;
string username;
do
{
bool broke = false;
Console.WriteLine("Please create a username");
username = Console.ReadLine();
for (int i = 0; i < profile.Count; i++)
{
if (username == profile[i].Username)
{
Console.WriteLine("The username already exists");
broke = true;
break;
}
}
if (broke == false)
{
good = true;
}
} while (good == false);
Console.WriteLine("Please create a password");
string password = Console.ReadLine();
profile.Add(new Users(username, password, 0));
string setPassword;
bool validUser = false;
do
{
Console.Clear();
Console.WriteLine("Enter your username");
string tryUsername = Console.ReadLine();
for (int i = 0; i < profile.Count; i++)
{
if (profile[i].Username == tryUsername)
{
setPassword = profile[i].Password;
validUser = true;
}
}
if (validUser == false)
{
Console.WriteLine("Invalid username. Usernames are case sensitive");
Thread.Sleep(2500);
}
} while (validUser == false);
bool validPass = false;
do
{
Console.WriteLine("Enter your password");
string tryPass = Console.ReadLine();
if (tryPass == setPassword) //this is the error
{
validPass = true;
}
else
{
Console.WriteLine("Invalid password. Passwords are case sensitive");
}
} while (validPass == false);
The compiler can't know it will actually get assigned (and it doesn't if not all if statements you have evaluate to true).
Assign a default value and you will be fine:
string setPassword = null;
I initiate the variable setPassword outside of the loop and then give it a value within the loop.
This is the problem. The system cannot guarantee that a value is assigned before it is used.
It is possible that the loop iterates 0 times.
It is also possible that condition of the surrounding if statement evaluates to false.
Both of these situations lead to setPassword never getting a value.
So the compiler gives you an error, it is possible that you are using setPassword before it has a value.
The solution is to set it to a default value outside the loop, and outside the if.
This is because the compiler canĀ“t know that your for-loop is executed at least once and in particular that the if-statement within the loop also passes at least for one iteration of that loop. Thus - at least from the perspective of the compiler - it is possible that setPassword is never assigned a value and thus you get that error.
Assign null at the start:
string setPassword = null;
Basically the problem is this :
You are using them in mostly the if statements, the if statements uses a variable. But you only declared but never defined the variable globally/locally, which automatically gives an error, despite the variable will be taking a user's input locally, the if statement is unfortunately too stupid to detect that for you, plus it also takes the possibility that the user skips the step of giving an input too. Hence, you need to set a default value.
Like what they stated, you can use :
string setPassword = null; or string setPassword = "";
[Don't need to mind nullables , strings can be null by default]
To solve your problem, you should assign setPassword to string.Empty, null, or some other value, based on your use case
If you are curious about -
Why does the compiler complain that the variable is unassigned even though you assigned a value to it in while loop?
This is called the Definite Assignment behavior of the C# language. A variable is considered to be definitely assigned if
The variable was initialized at the time of declare - either with a default value or an explicitly value
Otherwise, if the compiler can prove, by static flow analysis (in simple words, compile time checks), that all possible execution paths leading up to the first use of variable will assign a value to the variable. Note, the static flow analysis is the key here, the compiler does not evaluate or take for granted that any run-time possibilities (conditions in if, while, for etc. control statements) will eventually assign the variable a value.
See Definite assignment at MSDN for more info. It is an archived document but should still be good a reference.
Also DotNetPerls Page describes it in simple language.
Disclaimer: I have no association with DotNetPerls.
I am tempted to use an if ... else ... but I am wondering if there's an easier way? I need to display the true or false result in a message box.
The bool.ToString method already does what you want.
This method returns the constants "True" or "False".
However in practice it is not that often that you need to explicitly call ToString directly from your code. If you are already writing a string then the easiest way is to use concatenation:
string message = "The result is " + b;
This compiles to a call to string.Concat and this calls the ToString method for you.
In some situations it can be useful to use String.Format, and again the ToString method is called for you:
string message = string.Format("The result is {0}. Try again?", b);
bool b = true;
Console.WriteLine(b.ToString());
I'm just going to throw:
val ? "true" : "false"
into the mix, as having a lowercase result is often necessary (a lot of machine-readable formats, such as a lot of XML formats, use lower case "true" and "false" for boolean values) and the above is faster and also IMO cleaner than val.ToString().ToLowerInvariant().
Of course, extension to val ? "yes" : "no" and so on is trivial. To be localisable is another matter, and not always trivial (quite a few cases would have quite different sentences if translated well, so the logic of messageStart + (val ? "yes" : "no") + messageEnd doesn't always work well.
What is wrong with .ToString(), which is available on every object?
bool myBool = false;
string myString = myBool.ToString();
bool v = true;
string s = v.ToString();
This is a one-liner. All c# types derive from Object and so inherit the methods of that class.
I'll point you here: http://msdn.microsoft.com/en-us/library/system.object.aspx and let you find it.
bool myBool = true;
MessageBox.show(myBool.toString());
It is always recommended to use static functions under Convert class. In your case
bool boolValue = true;
System.Convert.ToString(boolValue);
If you want to make it fully localizable, you can add a resource file called UiStrings to the project and add an entry for each of the boolean values. Visual Studio will generate a wrapper (using either PublicResXFileCodeGenerator or ResXFileCodeGenerator) for the resource manager, which you can then access using static properties.
Then, you can use it like this:
var booleanValue = true;
var booleanText = booleanValue ? UiStrings.TrueValueText : UiStrings.FalseValueText;
var messageText = UiString.ResultMessageText;
var messageString = String.Format("{0}:{1}", messageText, booleanText);
The verbose code is intentional so that you can identify the different parts.
I know you didn't ask this, but for the heck of adding my own narcissistic voice to the mix, this is how to you get an int from a bool (0, 1)
using System;
class Program
{
static void Main()
{
// Example bool is true
bool t = true;
// A
// Convert bool to int
int i = t ? 1 : 0;
Console.WriteLine(i); // 1
// Example bool is false
bool f = false;
// B
// Convert bool to int
int y = Convert.ToInt32(f);
Console.WriteLine(y); // 0
}
}
Output:
1
0
My Goal: Extracting one value from an Excel Range, and verify for these cells' value to be the same within this range;
When a cell's value is not the same as the other, I need to return null.
Here's a piece of code:
internal object GetValueFromCells(string start, string end, Formats format) {
// Verifying for empty or null parameters here and throwing accordingly...
try {
Range cells = Excel.get_Range(start, end) as Range;
object value = null;
bool sameValue = false;
foreach(Range cell in cells) {
// This condition block shall execute only once, since 'value' shall not be null afterwards.
if (value == null || value == DBNull.Value)
if (Formats.Formated == format) {
value = cell.Text;
// The following results to be false !?...
sameValue = value == cell.Text; // Shall this not be true?
} else {
value = cell.Value2;
// The following results to be false !?...
sameValue = value == cell.Value2; // Shall this not be true?
}
// This results being always false!?...
// Shall this not be true, I wonder?
sameValue = Formats.Formated == format ? value == cell.Text : value == cell.Value2;
if(!sameValue)
return null;
}
return value;
} catch (Exception ex) {
// Exception handling...
}
}
Reading this code, I would humbly expect a value to be returned when all of the cells in the range have the same value (for instance 334).
However, this methods always returns null (Nothing in Visual Basic)!
Anyone might explain what I'm missing here while this:
value == cell.Value2
always returns false?
Perhaps is it my algorithm that isn't quite right?
EDIT #1
This has solved the problem:
sameValue = Formats.Formatted == format ? cell.Text.Equals(value) : cell.Value2.Equals(value);
I accepted #Jerod Houghtelling's answer as his answer suggests both the ToString() and the Equals() methods to solve the problem.
In addition to it, I dislike having to call the ToString() method, since the value can be numbers, and comparing numbers under a string looks odd to me. So I prefer the Equals() way which I adopted within my solution.
I would like to thank #Sir Gallahad and #Jerod Houghtelling for their good answers. This was the first time I had to face such a situation, and they both helped me better understand what was going on under the hood, plus the others who contributed too through comments.
And thanks to those who upvoted my question. This serves a purpose to demonstrate that I was not so dumb asking! =P Hehehe...
I'm guessing that cell.Value2 is returning a new instance of an object each time you call it. Therefore I would deduce the == is checking to see if both sides of the equation are the same instance of the object. To actually compare the value stored on both side you will have to use the .Equals or convert the values to something that can be compared, for example a string.
sameValue = value.Equals( cell.Value2 );
/* or */
sameValue = value.ToString() == cell.Value2.ToString();
Also I don't see value being set in your example.
Probably the value == cell.Value2 are comparing objects that are from different instances.
Try value.ToString() == cell.Value2.ToString()