Weird C# syntax - c#

I've just found this syntax:
date1 = date2?.ToString("yyyy-MM-dd") ?? date3;
Of course, being the first time I saw such a syntax, I did not understand it. After debugging, I understood that it is equivalent to:
if(date2 != null)
date1 = date2.ToString("yyyy-MM-dd");
else
date1 = date3;
My question is: why was this syntax introduced, since it is not legible at all, and it just economizes 3 lines of text?
Edit: my question is about the ? operator, not ??

That statement doesn't just economize 3 lines, it more readable and also spares a code block, which is important to allow more complex LINQ queries.
What do you think of these two?
var x = collection.Select(x => new SomeClass(x?.Property ?? "default"));
Opposed to:
var x = collection.Select(x =>
{
string value = null;
if (x != null)
{
value = x.Property;
}
if (value == null)
{
value = "default";
}
return new SomeClass(value);
}
);
The first is much more expressive and powerful. And what if you have more than one property?

They introduced the ?. operator for the same reason that they introduced the ?? operator: to shorten the code. The same argument you made against ?. could be made against ?? (and to a lesser degree could be made against the ternary operator ? :). But in the end I consider it useful (in the same way that I consider it useful the ternary operator ? :). It is readable if you know what it means. If you don't know what it means any operator is unreadable.
It is useful because the code that you wrote is correct only if date2 is a field/local variable/parameter... If it is a property, there is a guarantee that the property isn't read twice (something that could be quite important, depending on how the parameter is calculated). The code is changed to something like:
DateTime? temp = date2;
string date1 = temp != null ? temp.GetValueOrDefault().ToString("yyyy-MM-dd") : date3;
so it can get a little more complex than you thought.

This type of syntax was newly added with C# 6.0.
?. is called null-conditional.
This microsoft article describes all newly added features of C# 6.0 and also lists this new null-conditional operator.

Related

C#, is this "if... else..." block equivalent to one line of code using null-coalescing operator

I'm curious if this block of code:
//value is an object, maybe null, maybe not
if (value == null)
item.PassageStimuliTitle = "";
else
item.PassageStimuliTitle = value.ToString().Trim();
is equivalent to this line:
item.PassageStimuliTitle = (string)(value ?? value.ToString().Trim());
I've used if... else... for a long time, but recently came across the null-coalescing operator in C#. I've used it to prevent null exception errors for params passed in method calls. I think using it in the example above is equivalent, and condenses the code from 4 lines to 1. Thanks for reading. Curious to hear feedback.
I'm expecting the two examples to be equivalent, but curious if there's something I'm missing.
No, the null-coalescing operator expression is not written correctly. a ?? b means "evaluate to b if a is null, otherwise evaluate to a". Therefore, your use of the null-coalescing operator will always produce a NullReferenceException if value is null - your code will try to evaluate value.ToString() when value is null.
Your use of ?? would translate to something like the following if statement, which I think you'd agree is quite non-sensical:
if (value == null) {
item.PassageStimuliTitle = (string)value.ToString().Trim();
} else {
item.PassageStimuliTitle = (string)value;
}
With certain assumptions, the if statement can be rewritten as:
item.PassageStimuliTitle = value?.ToString().Trim() ?? "";
This uses the null conditional operator ?.. If value is null, then the entire value?.ToString().Trim() expression is null, and hence the RHS of the ?? is evaluated. Otherwise, .ToString().Trim() is called on value.
item.PassageStimuliTitle = value != null ? value.ToString().Trim() : "";
From #Charles Mager comment:
item.PassageStimuliTitle = value?.ToString().Trim() ?? ""
Is a better and clearer one-liner.
You used ?? operator incorrectly.
In this example:
result = left_value ?? right_value;
?? operator returns left_value if it is NOT null.
If left_value is null, it returns right_value.
So, in your case, if variable value is of type object, it should be:
item.PassageStimuliTitle = (value ?? "").ToString().Trim();
Here is a successfully compiled code fiddle.

why would a ? appear in IEnumerable<int>?.ToList()? [duplicate]

This question already has answers here:
What does x?.y?.z mean?
(3 answers)
Closed 6 years ago.
I was reviewing some code and I came across the following line of code:
List authorIntList = authorIds?.ToList();
In the example above, authorIds is an IEnumerable. What is the purpose of the ? in the line of code above? I'm not sure I've ever seen this pattern before. What does it do and in which version of .NET was it implemented?
That's called the "null conditional operator" -- i.e. ? and . together -- new to C# 6.0. What it means is that, if authorIds is not null, then it will call/return ToList() on it. Otherwise, it will return null. It's basically syntactic sugar so you don't have to write lengthier code like List AuthorIntList = authorIds != null ? authorIds.ToList() : null;.
The "Null Conditional Operator" exists as a way to shorthand "If this isn't null, do the thing, otherwise return null". It's basically the same as
List authorIntList = authorIds ? authorIDs.ToList() : null; //null coalescing
or
List authorIntList = null;
if(authorIDs != null) { authorIntList = authorIDs.ToList(); } //traditional if
It is a null conditional operator that in many languages people call it Elvis operator. It has been added from c# 6.0 and checks your code with null.
So if you have something like:
var x= a?.b?.c?.d;
x will be null if any of a,b,c or d be null. and it will be the value in d if all of them are not null. before you had to put them in if conditions.
if(a!= null && a.b!= null && a.b.c!= null)
{
x= a?.b?.c?.d;
}
Correction Null Conditional operator
https://msdn.microsoft.com/en-us/library/dn986595.aspx
It's like saying if authorId's is not null then execute ToList() else returns null.

C# Null propagating operator / Conditional access expression & if blocks

The Null propagating operator / Conditional access expression coming in c#-6.0 looks like quite a handy feature. But I'm curious if it will help solve the problem of checking if a child member is not null and then calling a Boolean method on said child member inside an if block:
public class Container<int>{
IEnumerable<int> Objects {get;set;}
}
public Container BuildContainer()
{
var c = new Container();
if (/* Some Random Condition */)
c.Objects = new List<int>{1,2,4};
}
public void Test()
{
var c = BuildContainer();
//Old way
if ( null != c && null != c.Objects && c.Objects.Any())
Console.Write("Container has items!");
//C# 6 way?
if (c?.Object?.Any())
Console.Write("Container has items!");
}
Will c?.Object?.Any() compile? If the propagating operator short circuits (I assume that's the right term) to null then you have if (null), which isn't valid.
Will the C# team address this concern or am I missing the intended use case for the null propagating operator?
It won't work this way. You can just skip the explanation and see the code below :)
As you know ?. operator will return null if a child member is null. But what happens if we try to get a non-nullable member, like the Any() method, that returns bool? The answer is that the compiler will "wrap" a return value in Nullable<>. For example, Object?.Any() will give us bool? (which is Nullable<bool>), not bool.
The only thing that doesn't let us use this expression in the if statement is that it can't be implicitly casted to bool. But you can do comparison explicitly, I prefer comparing to true like this:
if (c?.Object?.Any() == true)
Console.Write("Container has items!");
Thanks to #DaveSexton there's another way:
if (c?.Object?.Any() ?? false)
Console.Write("Container has items!");
But as for me, comparison to true seems more natural :)
Null-conditional operator would return null or the value at the end of expression. For value types It will return result in Nullable<T>, so in your case it would be Nullabe<bool>. If we look at the example in the document for Upcoming Features in C# (specified here), it has an example:
int? first = customers?[0].Orders.Count();
In the above example, instead of int, Nullable<int> would be returned. For bool it will return Nullable<bool>.
If you try the following code in Visual Studio "14" CTP:
Nullable<bool> ifExist = c?.Objects?.Any();
The result of the above line would be a Nullable<bool>/bool?. Later you can do the comparison like:
Using null-coalescing operator ??
if (c?.Object?.Any() ?? false)
Using Nullable<T>.GetValueOrDefault Method
if ((c?.Objects?.Any()).GetValueOrDefault())
Using comparison against true
if (c?.Objects?.Any() == true)
var x = c?.Objects?.Any() is going to give you a nullable boolean, and as others have said, this means you can use an equality operator like this
x == true
or you can use null coalescing like this to have your result not be nullable
var x = c?.Objects?.Any() ?? false
But, personally, I think that 3-state (nullable) booleans are code smell. Even if this one is practically invisible, its existence should encourage you to think about what you are actually trying to do and determine if a nullable boolean is actually the way to go. In this case, I think that what you really want to do is something like this -
var objects = c?.Objects ?? Enumerable.Empty<Object>();
if (objects.Any())
{
...
}
Put that in an extension method and it will be even more succinct -
public static bool IsNullOrEmpty<T>(this IEnumerable<T> collection)
{
return !(collection ?? Enumerable.Empty<T>()).Any()
}

Is there a conditional operator for setting a variable in C# to the value of another variable if the latter isn't null?

Something like the ternary operator (?:) or the null coalescing operator (??). It seems silly to me to take up two lines and be so wordy when the other operators exist.
EDIT:
Since it's requested, here's two possible examples of what I hope that I can find
var variable ?= mightBeNull;
or
var variable = mightBeNull != null ? mightBeNull
Really, it's either something that can be used to assign a value, if it's not null, to a variable or an If without an Else packaged nicely in an operator.
The ??= operator is coming to C# 8.
int? i = null; // i = null
i ??= 0; // i = 0
i ??= 1; // i = 0
// different ways of writing 'i ??= 0;':
i = i ?? 0;
if (i == null) i = 0;
So you want this?
if (other != null)
someVariable = other;
You could do the following, but I'd argue that the above is better due to clarity and possible side effects:
someVariable = other ?? someVariable;
The above might cause side effects if someVariable is a property and either the get or set can cause side effects; this shouldn't be important if your property follows the ordinary guidelines. Or, as Servy points out, even if it's a field, it could created different semantics in a multithreaded app. I should note that in the first example, you read other twice, which also has the potential for complexity to enter (though a smaller potential than the latter example).
I bet this is what you are looking for.
Let's say we have a function, myFunction that says whether the argument passed input is null or not. If input is null, it will return "Input is null!", else it will return "Input is not null".
This is the normal approach:
public String myFunction(string input) {
if (input == null)
return "Input is null!";
else
return "Input is not null";
}
And this is the other approach (What you are looking for):
public String myFunction(string input) {
return (input == null) ? "Input is null!" : "Input is not null";
}
It is called (?: conditional operator).
To assign a value to a variable only if it is not null, you would need to use an if. Neither the conditinal nor the null coalesce operators would do that.
if(somethingElse != null) something = somethingElse;
There is no specific operator in C# that does exactly this.
In Visual Studio 2015 C# there is a new operator called the Null-Conditional that does what you are asking. It is the ?. or ? operator.
int? length = customers?.Length; // null if customers is null
Customer first = customers?[0]; // null if customers is null
int? count = customers?[0]?.Orders?.Count(); // null if customers, the first customer, or Orders is null
Currently useable in previous versions of C# but not an operator but rather a one liner would be to use the ? : statement
?: operator
condition ? first_expression : second_expression;
AssingningTO = (someVar == null) ? null: someVar; // if null assign null ELSE assign someVar
AssingningTO = (someVar == null) ? String.Empth(): someVar; // if null assign empty string else someVar
Nullable types can represent all the values of an underlying type, and an additional null value.
http://msdn.microsoft.com/en-us/library/2cf62fcy.aspx

Shortest way to check for null and assign another value if not

I am pulling varchar values out of a DB and want to set the string I am assigning them to as "" if they are null. I'm currently doing it like this:
if (string.IsNullOrEmpty(planRec.approved_by) == true)
this.approved_by = "";
else
this.approved_by = planRec.approved_by.toString();
There seems like there should be a way to do this in a single line something like:
this.approved_by = "" || planRec.approved_by.toString();
However I can't find an optimal way to do this. Is there a better way or is what I have the best way to do it?
Try this:
this.approved_by = IsNullOrEmpty(planRec.approved_by) ? "" : planRec.approved_by.toString();
You can also use the null-coalescing operator as other have said - since no one has given an example that works with your code here is one:
this.approved_by = planRec.approved_by ?? planRec.approved_by.toString();
But this example only works since a possible value for this.approved_by is the same as one of the potential values that you wish to set it to. For all other cases you will need to use the conditional operator as I showed in my first example.
Starting with C# 8.0, you can use the ??= operator to replace the code of the form
if (variable is null)
{
variable = expression;
}
with the following code:
variable ??= expression;
More information is here
You are looking for the C# coalesce operator: ??. This operator takes a left and right argument. If the left hand side of the operator is null or a nullable with no value it will return the right argument. Otherwise it will return the left.
var x = somePossiblyNullValue ?? valueIfNull;
The coalesce operator (??) is what you want, I believe.
My guess is the best you can come up with is
this.approved_by = IsNullOrEmpty(planRec.approved_by) ? string.Empty
: planRec.approved_by.ToString();
Of course since you're hinting at the fact that approved_by is an object (which cannot equal ""), this would be rewritten as
this.approved_by = (planRec.approved_by ?? string.Empty).ToString();
With C#6 there is a slightly shorter way for the case where planRec.approved_by is not a string:
this.approved_by = planRec.approved_by?.ToString() ?? "";
Use the C# coalesce operator: ??
// if Value is not null, newValue = Value else if Value is null newValue is YournullValue
var newValue = Value ?? YourNullReplacement;
To extend #Dave's answer...if planRec.approved_by is already a string
this.approved_by = planRec.approved_by ?? "";
The accepted answer was correct in time, when it was given.
For people still finding this question:
Today you can use the ??= Operator.
e.g:
private string _test = null;
private void InitIfNull(){
_test ??= "Init";
}
To assign a non-empty variable without repeating the actual variable name (and without assigning anything if variable is null!), you can use a little helper method with a Action parameter:
public static void CallIfNonEmpty(string value, Action<string> action)
{
if (!string.IsNullOrEmpty(value))
action(value);
}
And then just use it:
CallIfNonEmpty(this.approved_by, (s) => planRec.approved_by = s);
You can also do it in your query, for instance in sql server, google ISNULL and CASE built-in functions.
I use extention method SelfChk
static class MyExt {
//Self Check
public static void SC(this string you,ref string me)
{
me = me ?? you;
}
}
Then use like
string a = null;
"A".SC(ref a);

Categories

Resources