"Simplify conditional ternary expression" - c#

var foo = context.FOOTABLE.FirstOrDefault();
var bar = foo != null ? foo.SomeBool : false;
Resharper tells me to Simplify conditional ternary expression. But I feel like a null check is necessary here, since FirstOrDefault() can return null.
So, who's wrong, me or Resharper?

First, a full example:
class Foo
{
public bool SomeBool { get; set; }
}
class Program
{
static void Main(string[] args)
{
var foo = MaybeFoo();
var bar = foo != null && foo.SomeBool;
}
static Foo MaybeFoo()
{
return new Random().Next() < 10 ? null : new Foo();
}
}
Here MaybeFoo is a method that sometimes returns null and sometimes returns a Foo. I've used Random so that R# doesn't automatically work out that it's always null or not-null.
Now, as you say on this line:
var bar = foo != null ? foo.SomeBool : false;
R# offers the inspection Simplify conditional operator. What does it mean by this? Well, as usual, we can Alt+Enter and accept the suggestion and see what it wants to replace it with, which in this case is:
var bar = foo != null && foo.SomeBool;
Now, as to your concern:
But I feel like a null check is necessary here, since FirstOrDefault() can return null.
So, who's wrong, me or Resharper?
Well, to put it shortly, you are. There's still a null check taking place here, and the && operator is short-circuiting, so the second operand (foo.SomeBool) will only be evaluated if the first one is true. So there won't be a NullReferenceException in the case when foo is null; the first check will fail and bar will be assigned false.
So the two lines
var bar = foo != null ? foo.SomeBool : false;
and
var bar = foo != null && foo.SomeBool;
are semantically equivalent, and R# as usual prefers the more concise version (in particular, explicit trues and falses in conditionals are often a mark of redundant code). You may not, in which case you could turn off this inspection.

ReSharper is suggesting to change your code to:
var bar = foo != null && foo.SomeBool;
Which does exactly the same as ternary operation, but looks better. The logic of your code won't change.

Related

C# nullable check verify that property is not null

I have a complex object I want to check is valid. I have a method to check it, but C# nullability checks don't know about them:
#nullable enable
...
bool IsValid(Thing? thing)
{
return thing?.foo != null && thing?.bar != null;
}
...
if(IsValid(thing))
{
thing.foo.subProperty; // CS8602 warning: foo is possibly null here
Is there any way to apply something like TypeScript's type-gates here? If IsValid is true then we know that thing.foo is not null, but the C# analyser can't see inside the function. If I inline the check it can, but then I'm copy-pasting code and this is a simple example.
Is there any annotation or pattern where I can have the nullability analysis with the more complex checks?
You can use the null-forgiving operator like this:
if (IsValid(thing))
{
thing.foo!.subProperty;
}
As #JeroenMostert points out, while it won't help you with foo, an alternative is the NotNullWhen attribute.
The compiler knows thing is not null here, but foo might still be null.
bool IsValid([NotNullWhen(true)] Thing? thing)
{
return thing?.foo != null && thing?.bar != null;
}
if (IsValid(thing))
{
thing.foo;
}

what does the questionmark do when typing object?.field? [duplicate]

With C# 6.0 in the VS2015 preview we have a new operator, ?., which can be used like this:
public class A {
string PropertyOfA { get; set; }
}
...
var a = new A();
var foo = "bar";
if(a?.PropertyOfA != foo) {
//somecode
}
What exactly does it do?
It's the null conditional operator. It basically means:
"Evaluate the first operand; if that's null, stop, with a result of null. Otherwise, evaluate the second operand (as a member access of the first operand)."
In your example, the point is that if a is null, then a?.PropertyOfA will evaluate to null rather than throwing an exception - it will then compare that null reference with foo (using string's == overload), find they're not equal and execution will go into the body of the if statement.
In other words, it's like this:
string bar = (a == null ? null : a.PropertyOfA);
if (bar != foo)
{
...
}
... except that a is only evaluated once.
Note that this can change the type of the expression, too. For example, consider FileInfo.Length. That's a property of type long, but if you use it with the null conditional operator, you end up with an expression of type long?:
FileInfo fi = ...; // fi could be null
long? length = fi?.Length; // If fi is null, length will be null
It can be very useful when flattening a hierarchy and/or mapping objects. Instead of:
if (Model.Model2 == null
|| Model.Model2.Model3 == null
|| Model.Model2.Model3.Model4 == null
|| Model.Model2.Model3.Model4.Name == null)
{
mapped.Name = "N/A"
}
else
{
mapped.Name = Model.Model2.Model3.Model4.Name;
}
It can be written like (same logic as above)
mapped.Name = Model.Model2?.Model3?.Model4?.Name ?? "N/A";
DotNetFiddle.Net Working Example.
(the ?? or null-coalescing operator is different than the ? or null conditional operator).
It can also be used out side of assignment operators with Action. Instead of
Action<TValue> myAction = null;
if (myAction != null)
{
myAction(TValue);
}
It can be simplified to:
myAction?.Invoke(TValue);
DotNetFiddle Example:
using System;
public class Program
{
public static void Main()
{
Action<string> consoleWrite = null;
consoleWrite?.Invoke("Test 1");
consoleWrite = (s) => Console.WriteLine(s);
consoleWrite?.Invoke("Test 2");
}
}
Result:
Test 2
Basically, I have applied ?. operator after Model as well. I am trying to know that whether it can be applied directly to the model or does it only work with the navigation properties?
The ? or null conditional operator operators on the left value, regardless of the type of value. And the compiler doesn't care what the value is on the right. It's simple compiler magic (meaning it does something you can already do, just in a simplified why).
For example
var a = model?.Value;
is the same as saying
var a = model == null ? null : model.Value;
In the second case the evaluation of checking for null has no associate with the value returned. The null conditional operator basically just always return null if the left value is null.
The type of member (Method, Field, Property, Constructor) .Value is irrelevant.
The reason your DotNetFiddle example doesn't work is because the compiler being use for the .Net 4.7.2 isn't compatible with the c# version that support the null conditional operator. Changing it to .Net 5, works:
https://dotnetfiddle.net/7EWoO5
This is relatively new to C# which makes it easy for us to call the functions with respect to the null or non-null values in method chaining.
old way to achieve the same thing was:
var functionCaller = this.member;
if (functionCaller!= null)
functionCaller.someFunction(var someParam);
and now it has been made much easier with just:
member?.someFunction(var someParam);
I strongly recommend this doc page.

What does question mark and dot operator ?. mean in C# 6.0?

With C# 6.0 in the VS2015 preview we have a new operator, ?., which can be used like this:
public class A {
string PropertyOfA { get; set; }
}
...
var a = new A();
var foo = "bar";
if(a?.PropertyOfA != foo) {
//somecode
}
What exactly does it do?
It's the null conditional operator. It basically means:
"Evaluate the first operand; if that's null, stop, with a result of null. Otherwise, evaluate the second operand (as a member access of the first operand)."
In your example, the point is that if a is null, then a?.PropertyOfA will evaluate to null rather than throwing an exception - it will then compare that null reference with foo (using string's == overload), find they're not equal and execution will go into the body of the if statement.
In other words, it's like this:
string bar = (a == null ? null : a.PropertyOfA);
if (bar != foo)
{
...
}
... except that a is only evaluated once.
Note that this can change the type of the expression, too. For example, consider FileInfo.Length. That's a property of type long, but if you use it with the null conditional operator, you end up with an expression of type long?:
FileInfo fi = ...; // fi could be null
long? length = fi?.Length; // If fi is null, length will be null
It can be very useful when flattening a hierarchy and/or mapping objects. Instead of:
if (Model.Model2 == null
|| Model.Model2.Model3 == null
|| Model.Model2.Model3.Model4 == null
|| Model.Model2.Model3.Model4.Name == null)
{
mapped.Name = "N/A"
}
else
{
mapped.Name = Model.Model2.Model3.Model4.Name;
}
It can be written like (same logic as above)
mapped.Name = Model.Model2?.Model3?.Model4?.Name ?? "N/A";
DotNetFiddle.Net Working Example.
(the ?? or null-coalescing operator is different than the ? or null conditional operator).
It can also be used out side of assignment operators with Action. Instead of
Action<TValue> myAction = null;
if (myAction != null)
{
myAction(TValue);
}
It can be simplified to:
myAction?.Invoke(TValue);
DotNetFiddle Example:
using System;
public class Program
{
public static void Main()
{
Action<string> consoleWrite = null;
consoleWrite?.Invoke("Test 1");
consoleWrite = (s) => Console.WriteLine(s);
consoleWrite?.Invoke("Test 2");
}
}
Result:
Test 2
Basically, I have applied ?. operator after Model as well. I am trying to know that whether it can be applied directly to the model or does it only work with the navigation properties?
The ? or null conditional operator operators on the left value, regardless of the type of value. And the compiler doesn't care what the value is on the right. It's simple compiler magic (meaning it does something you can already do, just in a simplified why).
For example
var a = model?.Value;
is the same as saying
var a = model == null ? null : model.Value;
In the second case the evaluation of checking for null has no associate with the value returned. The null conditional operator basically just always return null if the left value is null.
The type of member (Method, Field, Property, Constructor) .Value is irrelevant.
The reason your DotNetFiddle example doesn't work is because the compiler being use for the .Net 4.7.2 isn't compatible with the c# version that support the null conditional operator. Changing it to .Net 5, works:
https://dotnetfiddle.net/7EWoO5
This is relatively new to C# which makes it easy for us to call the functions with respect to the null or non-null values in method chaining.
old way to achieve the same thing was:
var functionCaller = this.member;
if (functionCaller!= null)
functionCaller.someFunction(var someParam);
and now it has been made much easier with just:
member?.someFunction(var someParam);
I strongly recommend this doc page.

Assign a variable and check value?

Is it possible somethings like this:
var userAggregazione;
if (userAggregazione = YouTube.Actions.IsAccessTokenValid() != null)
{
}
IsAccessTokenValid() returns a userAggregazione instance or null. So, inside the if, I'd like to setup var userAggregazione, and check if it is null or not.
Is it possible?
not sure if I understand but let me attempt:
var userAggregazione = YouTube.Actions.IsAccessTokenValid();
if (userAggregazione == null)
{
// userAggregazione is null - do something
}
else
{
// it is not null - do something
}
It will work if there's an extra parentheses around the assignment, so that it will get evaluated before the != comparison.
MyClass userAggregazione;
if ((userAggregazione = YouTube.Actions.IsAccessTokenValid()) != null)
{}
edit2:
I assume the example is simplified, because normally you should do like this for clarity:
//my style preference is also to not use 'var' anyway
//when getting value from a function
//because it's not clear what the type is.
MyClass userAggregazione = YouTube.Actions.IsAccessTokenValid();
if (userAggregazione != null)
{}
Yes it is, you need to add some braces:
if ((userAggregazione = YouTube.Actions.IsAccessTokenValid()) != null)
Just ensure that IsAccessTokeValid does not throw any exceptions

C# coalesce operator Throws

I have a class with a string property. I use the coalesce operator when reading from it as it might be null, but it still throws me an NullRefrenceExeption.
string name = user.Section.ParentSection.Name ?? string.Empty;
To be more specific, its the ".ParentSection" that's null so is it because it don't even have ".name" ? If that's the case should i test ".ParentSection" first with an if block?
I assume there are something about the Coalesce operator i dont understand, hope someone can shed some light on whats going wrong here.
To be more specific, its the ".ParentSection" that's null so is it
because it don't even have ".name" ?
Yes.
If that's the case should i test ".ParentSection" first with an if
block?
Yes.
You'll need to check if Section and ParentSection are null. You could use an if-statement for this or write an extension method like this:
public static class MaybeMonad
{
public static TOut With<TIn, TOut>(this TIn input, Func<TIn, TOut> evaluator)
where TIn : class
where TOut : class
{
if (input == null)
{
return null;
}
else
{
return evaluator(input);
}
}
}
You would use this method like so:
string name = user.With(u => u.Section)
.With(s => s.ParentSection)
.With(p => p.Name) ?? string.Empty;
I think it's a lot cleaner than an if-statement with a lot of &&.
Some further reading: http://www.codeproject.com/Articles/109026/Chained-null-checks-and-the-Maybe-monad
You need to check if user, user.Section, or user.Section.ParentSection are null before you can use the null coalescing operator on a property of user.Section.ParentSection.
Nested property access is not safe if any of the objects accessed are null this will throw a NullReferenceException. You will have to explicitly test for the outer objects to be not null.
E.g.:
string name = string.Empty;
if(user!=null && user.Section!=null && user.Section.ParentSection !=null)
name = user.Section.ParentSection.Name ?? string.Empty;
In general I would try to avoid nested access to properties, you are violating the Law of Demeter. Some refactoring might make this unnecessary in the first place.
The ?? operator checks if the left side is null and if so returns the right one, if not the left one.
In your case the left-side is the "Name" property in the object user.Section.ParentSection and this is null.
In those cases either think on what might be null or do something like this:
string name = user == null
|| user.Section == null
|| user.ParentSection == null
|| user.Section.ParentSection.Name == null
? string.Empty
: user.Section.ParentSection.Name;
(yeah it's ugly I know)
Chances are user or user.Section or user.Section.ParentSection is a null value.
The ?? operator doesn't prevent checks like:
if (user != null && user.Section != null && user.Section.ParentSection != null){
Make sure that everything up to the string property is valid and exists, then you can use ??. You can't call (null).Name, no matter how many times you try.
Yes you need to check if Section or ParentSection are null before you check Name
It is probably best to do something like this:
if(user!=null && user.Section!=null && user.Section.ParentSection!=null)
{
string name = user.Section.ParentSection.Name ?? string.Empty;
}
The null coalescing operator takes a statement like:
a = b ?? c;
What this says is "evaluate b; if it has a non-null value then assign that to a. Otherwise assign the value of c to a".
However within your b you're using a user object which may be null that has a section object that may be null that has a parent section property that may be null that had a name property that may be null. If you wanted to check all of these (and typically you should) then you can do something like:
string name = string.Empty;
if (user != null &&
user.Section != null &&
user.Section.ParentSection != null)
{
name = user.Section.ParentSection.Name ?? string.Empty;
}
As soon as the IF check fails it will not check further and therefore you don't get a NullReferenceException when you assume an object is present and then try to access one of its properties.

Categories