Is there any special expression or some kind or syntactic sugar built in in C# that would allow one to change a variable's value or leave it alone depending on condition?
I mean something that would do following:
str = (condition) ? "modifiedString" : str;
or
if (condition) str = "modifiedString";
But with simplicity of null coalescing operator. Something like
str = (condition) ?? "modifiedString"
How about
if(condition)
str = "modified"
Isn't that exactly what you want?
Related
This question already has answers here:
How does the ternary operator work?
(12 answers)
Closed 2 years ago.
Is it possible to write following C# code in a line without if and else?
string res = "";
if (!string.IsNullOrEmpty(var1))
res = string.Format("{0}/{1}", var1, var2);
else
res = var2;
Try this,
string res = !string.IsNullOrEmpty(var1) ? string.Format("{0}/{1}", var1, var2) : var2;
Basically,
(if this statement is true (like if block's condition part)) ? (this section works) : ((else) this section works);
Hope this helps,
The conditional operator ?:, also known as the ternary conditional operator, evaluates a Boolean expression and returns the result of one of the two expressions, depending on whether the Boolean expression evaluates to true or false.
The syntax for the conditional operator is as follows:
condition ? consequent : alternative
So the code line you are requested is
string res = !string.IsNullOrEmpty(var1) ? string.Format("{0}/{1}", var1, var2) : var2;
Tecnically, you can hide if within ternary operator ?:
string res = $"{(!string.IsNullOrEmpty(var1) ? $"{var1}/" : "")}{var2}";
but what for?
Let's imagine myString is an empty string variable
When I try myString.PadLeft(4, '0') ;
Eventually , it will generate a null reference exception as I'm trying to call the padding on an empty object
But , is there a way in which if the string is empty just fill it with 4 zero in the padding option, other than this "classic way" : !string.IsNullOrEmpty(myString)?myString.PadLeft(4, '0'):"0000";
You can try this by using null-coalescing operator
(myString??"").PadLeft(4, '0')
You have to make sure myString is not null before padding. Cleanest way is to use Null-coalescing Operator like so:
(myString ?? "").PadLeft(4, '0');
You can use the null-conditional and the null-coalescing operators.
myString = myString?.PadLeft(4,'0') ?? "0000";
Background
In PHP there is a shorthand for the ternary operator:
$value = "";
echo $value ?: "value was empty"; // same as $value == "" ? "value was empty" : $value;
In JS there's also an equivalent:
var value = "";
var ret = value || "value was empty"; // same as var ret = value == "" ? "value was empty" : value;
But in C#, there's (as far as i know) only the "full" version works:
string Value = "";
string Result = Value == string.Empty ? "value was empty" : Value;
So my question is: Is there a shorthand for the ternary operator in C#, and if not, is there a workaround?
Research
I found the following questions, but they're referring to use the ternary operator as shorthand to if-else:
shorthand If Statements: C#
Benefits of using the conditional ?: (ternary) operator
And this one, but it's concerning Java:
Is there a PHP like short version of the ternary operator in Java?
What I have tried
Use the shorthand style of PHP (Failed due to syntax error)
string Value = "";
string Result = Value ?: "value was empty";
Use the shorthand style of JS (Failed because "The || operator is not applicable to string and string.")
string Value = "";
string Result = Value || "value was empty";
There is no shorthand for when the string is empty. There is a shorthand for when the string is null :
string Value = null;
string Result = Value ?? "value was null";
The coalesce ?? operator works only on null, but you could "customize" the behavior with an extension method:
public static class StringExtensions
{
public static string Coalesce(this string value, string #default)
{
return string.IsNullOrEmpty(value)
? value
: #default;
}
}
and you use it like this:
var s = stringValue.Coalesce("value was empty or null");
But I don't think it is much better than the ternary.
Note: the # allows you to use reserved words as variable names.
Trying to figure out how to get the null coalescing operator to work in a foreach loop.
I'm checking to see what a string ends with and based on that, route it to a certain method. Basically what I want to say is....
foreach (String s in strList)
{
if s.EndsWith("d") ?? Method1(s) ?? Method2(s) ?? "Unknown file type";
}
In attempting to do this, of course you get the "Operator ?? cannot be used on type bool and type string." I know there is other ways to do it, just want to see how it can be done with null coalescing.
Have a good weekend.
#Richard Ev: Oh yes of course. Switch, if else, etc. Was just curious how it
could be handled
#Jon Skeet: After reading your comments it hit me, this is just bad! I am
interested in two file extensions basically. If a file ends with "abc" for
instance, send to method 1, if the file ends with "xyz" send to method 2. But
what if a file ends with an extension of "hij"...boom, you're done.
Thanks to Brian and GenericTypeTea as well for the thoughful input
I'm content calling it closed.
It looks like you want to use the normal ternary operator, not null coalescing. Something like:
(s.EndsWith("d") ? Method1(s) : Method2(s)) ?? "Unknown file type";
This is equivalent to:
string result;
if (s.EndsWith("d"))
result = Method1(s);
else
result = Method2(s);
if (result == null)
result = "Unknown file type";
return result;
I think you want a combination of the conditional (ternary) operator and the null coalescing operator:
foreach (String s in strList)
{
string result = (s.EndsWith("d") ? Method1(s) : Method2(s))
?? "Unknown file type";
}
In simple english, this will do the following:
If s ends with d, then it will try Method1.
If s does not end with d then it will try Method2.
Then if the outcome is null, it will use "Unknown file type"
If the outcome is not null, it will use the result of either A or B
I think the compiler gave you the appropriate answer, you can't.
Null coalescing is essentially this if statement:
if(x == null)
DoY();
else
DoZ();
A boolean value cannot be null, so you can't coalesce it like that. I'm not sure what your other methods return, but it seems like you want a simple || operator here.
You should first use the ?? null coalescing operator to guard against a null s reference. Then use the ? ternary operator to choose between Method1 and Method2. Finally use the ?? null coalescing operator again to provide the default value.
foreach (string s in strList)
{
string computed = s;
computed = computed ?? String.Empty;
computed = computed.EndsWith("d") ? Method1(s) : Method2(s);
computed = computed ?? "Unknown file type";
}
Which coding style do you prefer:
object o = new object();
//string s1 = o ?? "Tom"; // Cannot implicitly convert type 'object' to 'string' CS0266
string s3 = Convert.ToString(o ?? "Tom");
string s2 = (o != null) ? o.ToString() : "Tom";
s2 or s3?
Is it possible to make it shorter? s1 does not obviously work.
In this case, I think my preference would be:
string s1 = (string)o ?? "Tom";
Or:
string s1 = (o as string) ?? "Tom";
Depending on whether or not o is really expected to be a string or not. Either way, I prefer these because they better express what's being done, and don't pass this through an unnecessary conversion if o is already a string.
As a general rule, I prefer whichever is clearer and/or actually works. When working with strings, I often need to write something like this instead:
string result = !string.IsNullOrEmpty(value) ? value : "Default";
...which can't really be done at all with the null-coalescing operator. On the other hand, if I'm trying to coalesce a large number of values, it's about 500 times better:
var result = firstTry ?? secondTry ?? thirdTry ?? fourthTry ?? fifthTry;
Try writing that with the ternary operator instead.
If the difference is not this dramatic, if it's just going to be a couple of characters on one line of code, it really doesn't matter, just use whatever you're comfortable with.
This will also work, though calling ToString on a string feels a bit strange:
string s4 = (o ?? "Tom").ToString();
For this case I'd prefer using the ternary operator since it expresses the intent more clearly and avoids a redundant call to Convert.ToString(). In general I would prefer the null coalescing operator if the conversion is to an object of the same type e.g.
string s1 = null;
string s2 = s1 ?? string.Empty;
IMO, I tend to use:
var s = obj ?? "tom";
when s is the same type as obj without using the Convert or any other type of casting.
Then, I use:
var s = obj != null
? obj.ToString()
: "tom";
when I need to cast or have some other kind of transformation on the right side before assigning to the left side...
Just my style of coding, I suppose.
I don't like either. Converting object to a specific type is fraught with trouble, it should never be hidden in an expression. I'd much prefer that, if it bombs, then it does so on a specific statement. And to make it absolutely obvious to a reader of the code that this conversion is being done. So, at the very minimum:
string s1 = o as string;
string s2 = s1 ?? "Tom";