Null conditional operator to "nullify" array element existence - c#

The new C# 6.0 null-conditional operator is a handy vehicle for writing more concise and less convoluted code. Assuming one has an array of customers, then you could get null instead of a length if customers is null using this (examples from MSDN):
int? length = customers?.Length;
Similarly you could get null instead of a customer with this:
Customer first = customers?[0];
And for a more elaborate expression, this yields null if customers is null, the first customer is null, or the first customer's Orders object is null:
int? count = customers?[0]?.Orders?.Count();
But then there is the interesting case of the non-existent customer that the null-conditional operator does not seem to address. We saw above that a null customer is covered, i.e. if an entry in the customers array is null. But that is quite distinct from a non-existent customer, e.g. looking for customer 5 in a 3-element array or customer n in a 0-element list. (Note that the same discussion applies to Dictionary lookup as well.)
It seems to me that the null-conditional operator is focused exclusively on negating the effects of a NullReferenceException; IndexOutOfRangeException or KeyNotFoundException are alone, exposed, cowering in the corner, and needing to fend for themselves! I submit, that in the spirit of the null-conditional operator, it should be able to handle those cases as well... which leads to my question.
Did I miss it? Does the null-conditional provide any elegant way to truly cover this expression...
customers?[0]?.Orders?.Count();
...when there is no zeroth element?

No, because it is a null-conditional operator, not an indexoutofrange-conditional operator and is merely syntactic sugar to something like the following:
int? count = customers?[0]?.Orders?.Count();
if (customers != null && customers[0] != null && customers[0].Orders != null)
{
int count = customers[0].Orders.Count();
}
You can see that if there is no zeroth customer, you will get your regular IndexOutOfRangeException.
One way you could work around it is to have an extension method that checks for the index and returns null if it doesn't exist:
public static Customer? GetCustomer(this List<Customer> customers, int index)
{
return customers.ElementAtOrDefault(index); // using System.Linq
}
Then your check could be:
int? count = customers?.GetCustomer(0)?.Orders?.Count();

customers?.FirstOrDefault()?.Orders?.Count();
No zeroeth, no problem.

If you want to get the nth element without having NullReference or IndexOutOfRange exceptions, you can use:
customers?.Skip(n)?.FirstOrDefault()

It doesn't support indexing safety because, when you get down to it, an indexer really is just syntactic sugar for any other type of method.
For example:
public class MyBadArray
{
public Customer this[int a]
{
get
{
throw new OutOfMemoryException();
}
}
}
var customers = new MyBadArray();
int? count = customers?[5]?.Orders?.Count();
Should this be caught here? What if the exception was more sensible, similar to a KeyNotFoundException, but specific to the type of collection we're implementing? We'd have to continually update the ?. functionality to keep up.
Further, ?. does not catch exceptions. It prevents them.
var customer = customers?[5]; is actually compiled as:
Customer customer = null;
if (customers != null)
customer = customers[5];
Making it catch exceptions becomes exceptionally more difficult. For example:
void Main()
{
var thing = new MyBadThing();
thing.GetBoss()?.FireSomeone();
}
public class MyBadThing
{
public class Boss
{
public void FireSomeone()
{
throw new NullReferenceException();
}
}
public Boss GetBoss()
{
return new Boss();
}
}
If it were simply catching exceptions, it would be written as :
Boss boss = customer.GetBoss();
try
{
boss.FireSomeone();
} catch (NullReferenceException ex) {
}
Which would actually catch the exception within FireSomeone, rather than the null reference exception which would be thrown if boss were null.
The same bad-catching problem would be present if we were to catch index lookup exceptions, key not found exceptions, etc.

Related

Nullable record structs in C# [duplicate]

So I've got a collection of structs (it's actually a WCF datacontract but I'm presuming this has no bearing here).
List<OptionalExtra> OptionalExtras;
OptionalExtra is a struct.
public partial struct OptionalExtra
Now I'm running the below statement:
OptionalExtra multiOptExtra = OptionalExtras.Where(w => w.Code == optExtra.Code).FirstOrDefault();
if (multiOptExtra != null)
{
}
Now this won't compile:
the operator != cannot be applied to opperands of type OptionalExtra
and '<null>'
After a little googling I realised it's because OptionalExtra is a struct. Which I believe is not nullable unless defined as a nullable type?
So my question is, if my where statement returns no results what will be the outcome of the FirstOrDefault call? Will it thrown an exception?
Incidently this should never happen but better safe than sorry.
If your collection is empty, FirstOrDefault will return default(OptionalExtras). The default value of a struct is the struct with all its values in turn default initialized (i.e. zero, null, etc.).
If you assume that there will be an element and your code doesn't work with an empty collection, Use First() instead, since that will throw an exception when your collection is empty. It's generally better to fail fast than to return wrong data.
If you cannot assume that there will be an element, but also cannot deal with struct default initialization, you might make the structs in the collection a nullable value type, for example as follows:
OptionalExtras
.Where(w => w.Code == optExtra.Code)
.Cast<OptionalExtra?>()
.FirstOrDefault();
This way you can get a null return even for a struct. The key idea here is to extend the set of possible values to include something other than an OptionalExtra to allow detection of an empty list. If you don't like nullables, you could instead use a Maybe<> implementation (not a .NET builtin), or use an empty-or-singleton list (e.g. .Take(1).ToArray(). However, a nullable struct is likely your best bet.
TL;DR;
.FirstOrDefault<T>() returns default(T) if the sequence is empty
Use .First() instead if you assume the list is non-empty.
Cast to nullable and then use .FirstOrDefault<T>() when you cannot assume the list is non-empty.
As others have said, the result of your code when no elements match will be:
default( OptionalExtra )
If you want a null returned, you can cast your list to OptionalExtra?
OptionalExtra? multiOptExtra = OptionalExtras.Cast<OptionalExtra?>().Where( ...
You can then test for null
If default(OptionExtra) is still a valid value, it's better to change your code to this
var results = OptionalExtras.Where(w => w.Code == optExtra.Code).Take(1).ToList();
if (results.Any()) {
multiOptExtra = results[0]
}
The result will be the default value of your struct, e.g. default(OptionalExtras).
Whereas for a reference type the default value is null.
its provide you defualt value for your structure like as below
int[] numbers = { };
int first = numbers.FirstOrDefault();
Console.WriteLine(first);//this print 0 as output
other option to handle is make use of default value like as below
List<int> months = new List<int> { };
// Setting the default value to 1 by using DefaultIfEmpty() in the query.
int firstMonth2 = months.DefaultIfEmpty(1).First();
Console.WriteLine("The value of the firstMonth2 variable is {0}", firstMonth2);
If you want to check for null, use System.Nullable collection:
var OptionalExtras = new List<OptionalExtra?>();
/* Add some values */
var extras = OptionalExtras.FirstOrDefault(oe => oe.Value.Code == "code");
if (extras != null)
{
Console.WriteLine(extras.Value.Code);
}
Note that you have to use Value to access the element.
Assuming Code is a string for the purposes of my answer, you should be able just to test that value for its default.
OptionalExtra multiOptExtra = OptionalExtras.Where(w => w.Code == optExtra.Code).FirstOrDefault();
if (multiOptExtra.Code != null)
{
}

How to read such construction?

I've jumped into such a thing in my code and I don't really know how to read this. Would be nice if somebody could help me with this :)
return Company?.Call?.SingleOrDefault(cf => cf.Name == Client?.CallID)
?? Company?.Call?.SingleOrDefault(cf => cf.IsDefault)
?? new CallData();
The ?. operator is called a Null-conditional operator and is a new feature from C# 6, and was announced in October 2014. https://msdn.microsoft.com/en-us/library/dn986595.aspx
The first part: Company?.Call?.SingleOrDefault can be seen as similar to this:
if (Company == null)
{
return null;
}
else if (Company.Call == null)
{
return null;
}
else
{
return Company.Call.SingleOrDefault(....
}
But then the original coder uses the ?? Null-coalesce operator, which has been a part of C# since at least 2007. It means that if whatever is left of the ?? is null, evaluate what is right of the ?? and return that instead.
So the code basically means:
If Company is null, return new CallData()
If Company.Call is null, return new CallData()
If the first call to Company.Call.SingleOrDefault returns a CallData instance (having a certain value for the Name property) , return that instance
If the first call returns null, but the second call returns a CallData instance (being the default one) , return that instance
If both calls to SingleOrDefault return null, return new CallData()
This piece of code has some issues.
First of all, it is unreadable and should be refactored into something that is easier to understand. New language features are nice, but only when used responsibly.
Second: If there are more than one CallData instances with the same Name, the SingleOrDefault will throw an exception, but there might be a unique index in the database the prevents this. The same goes for IsDefault property - if there are more than one records with IsDefault = true, the SingleOrDefault call will throw an exception.
Split it to 3 expressions first, separated by the ??:
Company?.Call?.SingleOrDefault(cf => cf.Name == Client?.CallID)
??
Company?.Call?.SingleOrDefault(cf=>cf.IsDefault)
??
new CallData();
The returned value of the entire expression would be the first expression that is returning a non-null value.
Within each segment, once any of the properties accessed using ?. is null, the entire expression will be evaluated to null.
See Null-conditional Operators

'?' in middle of LINQ statement

I cam across this line while going through some not that old code and don't understand why anyone would ever do it:
return dbStudents.MethodToReturnAllStudents()?.Select(x => new dtoStudent(x));
MethodToReturnAllStudents returns an IEnumerable<SQLDomain.Student> (dtoStudent) is in a different namespace -- all the SQLDomain.Student has been mapped from an IDataRecord.
Why would there be a ? in the middle of this statement. Will the LINQ Select try to do anything if MethodToReturnAllStudents returns null?
Is this just terrible code all around?
Side note: Either way, I am refactoring it to follow some alternative standards and to be much more readable.
This is not "old code", since this is a C#6 feature, the Null Conditional Operator. When used, it checks if the immediately preceding value is null before allowing property/method usage on that instance. If it is null, it returns null.
In this scenario, you can translate this code to:
var students = dbStudents.MethodToReturnAllStudents();
if (students == null) return null;
return students.Select(x => new dtoStudent(x));
However, there is actually a larger potential issue with this code than the unfamiliar operator.
The general consensus is that IEnumerable<T> should never return null and, as such, should never need to be null checked. It should always return a sequence that is either hydrated or empty.
That said, if this were in fact List<T> (or a null IEnumerable, although less common), this could be a real scenario (although I would still advocate for never returning null but rather an empty list).
You will have to decide as a development team if the Null Conditional Operator is more succinct and readable. Personally, I'm a fan of it, just not in this context since it is indicative of a larger design smell.
It's not "terrible" code, but it's non-intuitive if you're not familiar with the syntax. I personally enjoy the less-verbose options. LINQ will stop if MethodToReturnAllStudents() returns null and just return that null. It's basically saying
var retVal = dbstudents.MethodToReturnAllStudents();
if(retVal == null) {
return retVal;
} else {
return retVal.Select(x => new dtoStudent(x));
}
Now as users have pointed out, it shouldn't return null as the caller is expecting an IEnumerable.
var retVal = dbstudents.MethodToReturnAllStudents();
if(retVal == null) {
return new List<student>();
} else {
return retVal.Select(x => new dtoStudent(x));
}
Using a null coalescing operator makes the code even more concise and still properly handles return types so it doesn't return null:
return dbStudents.MethodToReturnAllStudents()?.Select(x => new dtoStudent(x)) ?? new List<student>();
It is the Null Conditional Operator
MSDN Documentation
If dbStudents.MethodToReturnAllStudents() is null, it will return null instead of executing .Select(x => new dtoStudent(x)) which would result in a NullReferenceException.

Check null result before accessing property or calling method

I would like to know if there is a better way or general rule to check null result before accessing property or calling method in C# Linq or lambda expressions. Thanks in advance.
At my understanding, to avoid exception like "Object reference not set to an instance of an object" or "Check null from Lambda result before accessing CSharp property or calling method", I should use "if" statement, or "try/catch" block like:
var product1 = _myProductRepository.FindOne(p => p.Id == -20301);
//1. use "if" statement to let code flow continue
if(product1 != null) // to prevent exception "Object reference not set to an instance of an object."
{
int id1 = sh1.Id; // note: accessing property "Id" is safe here
Console.WriteLine("Product Id: {0}", id1);
}
//2. use "try/catch" block to let code flow continue
var product2 = _myProductRepository.FindOne(123);
var possibleItems = product2.Orders.Where(x => x.Id == -1);
List<Order> myOrderList = null;
try
{
myOrderList = possibleItems.ToList(); // note: ToList() method call is safe here
}
catch
{
myOrderList = new List<Order>();
}
I should use "if" statement, or "try/catch" block like:
In general, I would prefer an explicit null check if the null return is something that is expected as part of the normal operation of your application.
In your case, this is likely true, as finding a product seems like an operation that very well could fail, as a product may not exist.
That being said, if the ID is a known element and really should always be in the DB, then null would not be an expected result. In this case, the FindOne method really shouldn't return a null instance, and that is truly an exceptional case, then exception handling may be preferred.

Checking for null in an object hierarchy

I have a large C# (3.0) object structure originating from a deserialized XML document. I need to know whether a variable deep in the hierarchy is null. The way I do this now is to check every parent object on the way down for null, but this leads to a long repetition of if statements.
I am trying to avoid expensive try-catch blocks.
Is there a smarter way to do this?
edit:
For example after a deserialization of an XML application form into an object hierarchy structure there could potentially be a salary value under
applicationForm.employeeInfo.workingConditions.salary
but to find out safely I have to write something like
if (applicationForm.employeeInfo != null)
if (applicationForm.employeeInfo.workingConditions != null)
if (applicationForm.employeeInfo.workingConditions.salary != null)
because simply using the latter if-statement will of course fail if one of the parent objects is null.
So I am looking for any smarter way to handle this situation.
You've run into the classic situation where each step in A.B.C.D may yield null. Though this is a common scenario, surprisingly there's no common pattern for solving it, other then using a large if-statement with lots of or's (||).
If each step can return a different class, then there's a rarely used pattern that you can apply: Use a generalized generic extension method with method chaining.
A generalized extension method is not a fixed term but I use it here for emphasizing that the ext. method is applicable to almost all types of objects, hence generalized. According to Bill Wagner in Effective C#, this is bad design. But in some remote cases, like yours, you can use it as long as you know what you're doing and why.
The trick is simple: define a generic extension method and generalize it for all classes that have a default constructor. If the test fails (object is null), the method returns a new object of the same type. Otherwise, it will return the unchanged object itself.
Why is this a good approach for your scenario? Because you don't need to change any existing classes, because it's understandable and promotes readable code, because it keeps type safety (compile time errors instead of runtime errors) and it's simply more concise compared to other approaches.
// extension method:
public static class SomeExtentionMethods
{
public static T SelfOrDefault<T>(this T elem)
where T : class, new() /* must be class, must have ctor */
{
return elem ?? new T(); /* return self or new instance of T if null */
}
}
// your code now becomes very easily readable:
Obj someObj = getYourObjectFromDeserializing();
// this is it applied to your code:
var mySalary = applicationForm.SelfOrDefault().
employeeInfo.SelfOrDefault().
workingConditions.SelfOrDefault().
salary;
// now test with one if-statement:
if(mySalary.IsEmpty())
// something in the chain was empty
else
// all's well that ends well :)
The beauty of this approach is that it works with all types of classes (provided they have a ctor), including collections and arrays. If any step is an index step, it will still work (depending on the collection, an invalid index can return null, default or raise an exception):
var x =
someObj.SelfOrDefault()
.Collection.SelfOrDefault()
.Items[1].SelfOrDefault()
.Mother.SelfOrDefault()
.Father.SelfOrDefault();
Update: expanded a bit and added a more elaborate example
Update: renamed NotNull, which implies boolean, to SelfOrDefault, which follows LINQ's naming convention (FirstOrDefault etc) and implies what it does.
Update: rewritten and reorganized, made code more applicable, hoping to make it more understandable overall :)
Firstly, if you're repeating the logic in more than one place, encapsulate it in a method.
Secondly, you don't need lots of if statements, you just need one with a lot of OR conditions:
if(parent==null ||
parent.Child == null ||
parent.Child.GrandChild == null ...
Thirdly, "avoiding expensive try/catch blocks" may be a premature optimization, depending on your scenario. Have you actually tried this and profiled it, and is it really causing a large overhead?
You can nest ternary operators. Still a pain, but not as bad as nested ifs.
string salary = (applicationForm.employeeInfo == null) ? null :
(applicationForm.employeeInfo.workingConditions == null) ? null :
applicationForm.employeeInfo.workingConditions.salary;
If you just want to know whether or not it is null:
bool hasSalary = (applicationForm.employeeInfo == null) ? false :
(applicationForm.employeeInfo.workingConditions == null) ? false :
(applicationForm.employeeInfo.workingConditions.salary != null);
Here's my simple solution:
if (applicationForm?.employeeInfo?.workingConditions?.salary != null)
Here any of these objects (applicationForm, employeeInfo, workingConditions, salary) can be null and it will resolve without error.
can't you iterate?
for (SomeObject obj = someInstance; obj != null; obj = obj.Parent) {
//do something
}
Use reflection.
Create a helper method that takes a parent object and a hierarchical dot notated string for your property names. Then use PropertyInfo and use recursion to go down one property at a time each time checking for null and returning null if so, else continuing down the hierarchy.
Since you didn't provide all too many details I had to fill in alot of the blanks. Here is a psuo-codeish example of how you might accomplish this via recursion
public bool doesHierarchyContainANull(MyObject ParentObject)
{
if (ParentObject.getMemberToCheckForNull() == null)
return true;
else if (ParentObject.isLastInHierarchy())
return false;
return doesHierarchyContainANull(ParentObject.getNextInHierarchy());
}
I liked the answer by Pontus Bremdahl, but added some more detail for my uses.
Code:
/// <summary>
/// Get a member in an object hierarchy that might contain null references.
/// </summary>
/// <typeparam name="TSource"></typeparam>
/// <typeparam name="TResult"></typeparam>
/// <param name="source">Base object to get member from.</param>
/// <param name="getResult">Member path.</param>
/// <param name="defaultResult">Returned object if object hierarchy is null.</param>
/// <returns>Default of requested member type.</returns>
public TResult SafeGet<TSource, TResult>(TSource source, Func<TSource, TResult> getResult, TResult defaultResult)
{
// Use EqualityComparer because TSource could by a primitive type.
if (EqualityComparer<TSource>.Default.Equals(source, default(TSource)))
return defaultResult;
try
{
return getResult(source);
}
catch
{
return defaultResult;
}
}
/// <summary>
/// Get a member in an object hierarchy that might contain null references.
/// </summary>
/// <typeparam name="TSource"></typeparam>
/// <typeparam name="TResult"></typeparam>
/// <param name="source">Base object to get member from.</param>
/// <param name="getResult">Member path.</param>
/// <returns>Default of requested member type.</returns>
public TResult SafeGet<TSource, TResult>(TSource source, Func<TSource, TResult> getResult)
{
// Use EqualityComparer because TSource could by a primitive type.
if (EqualityComparer<TSource>.Default.Equals(source, default(TSource)))
return default(TResult);
try
{
return getResult(source);
}
catch
{
return default(TResult);
}
}
Usage:
// Only authenticated users can run this code
if (!HttpContext.Current.SafeGet(s => s.User.Identity.IsAuthenticated))
return;
// Get count limit from app.config
var countLimit = int.Parse(ConfigurationManager.AppSettings.SafeGet(
s => s.Get("countLimit"),
"100" // Default 100 if no value is present
));
// Is int 6 a class? Always no, but just to show primitive type usage.
var is6AClass = 6.SafeGet(i => i.GetType().IsClass);
Update
CSharp version 6 now has this built into it.
https://github.com/dotnet/roslyn/wiki/New-Language-Features-in-C%23-6#null-conditional-operators
Null-conditional operators
Sometimes code tends to drown a bit in null-checking. The null-conditional operator lets you access members and elements only when the receiver is not-null, providing a null result otherwise:
int? length = customers?.Length; // null if customers is null
Customer first = customers?[0]; // null if customers is null
The null-conditional operator is conveniently used together with the null coalescing operator ??:
int length = customers?.Length ?? 0; // 0 if customers is null
The null-conditional operator exhibits short-circuiting behavior, where an immediately following chain of member accesses, element accesses and invocations will only be executed if the original receiver was not null:
int? first = customers?[0].Orders.Count();
This example is essentially equivalent to:
int? first = (customers != null) ? customers[0].Orders.Count() : null;
Except that customers is only evaluated once. None of the member accesses, element accesses and invocations immediately following the ? are executed unless customers has a non-null value.
Of course null-conditional operators can themselves be chained, in case there is a need to check for null more than once in a chain:
int? first = customers?[0].Orders?.Count();
Note that an invocation (a parenthesized argument list) cannot immediately follow the ? operator – that would lead to too many syntactic ambiguities. Thus, the straightforward way of calling a delegate only if it’s there does not work. However, you can do it via the Invoke method on the delegate:
if (predicate?.Invoke(e) ?? false) { … }
We expect that a very common use of this pattern will be for triggering events:
PropertyChanged?.Invoke(this, args);
This is an easy and thread-safe way to check for null before you trigger an event. The reason it’s thread-safe is that the feature evaluates the left-hand side only once, and keeps it in a temporary variable.
CheckForNull(MyType element)
{
if(element.ChildElement != null)
{
CheckForNull(element.ChildElement);
}
else
{
Console.WriteLine("Null Found");
}
}
You need a recursive function to iterate through the structure and check each node and its children for null. I was working on a sample but IE crashed (typical!!). Will post one later.
Sample
You could do something as simple (assuming you only ever want to just check if the structure is valid) as this:
public void ValidateStructure()
{
Node root = // get the root node
try
{
ValidateChildren(root);
Console.WriteLine("All nodes are valid");
}
catch (NullReferenceException)
{
Console.WriteLine("Structure contained a null node.");
}
}
public void ValidateChildren(Node parent)
{
// an NullReferenceException would be raised here since parent would be null
foreach (var child in parent.Children)
{
ValidateChildren(child);
}
}
My solution would be something like:
public static TResult SafeGet<TSource, TResult>(this TSource source, Func<TSource, TResult> getResult) {
if (source == null)
return default(TResult);
try {
return getResult(source);
}
catch {
return default(TResult);
}
}
Usage:
Test myTestObject = null;
var myStringOrNull = myTestObject.SafeGet(x => x.test.test.test.mySring);
Use the Null monad. It can be in the same file or a different file so long as you using it.
public static class NullMonad {
public static TResult SelectMany<TIn, TOut, TResult>(this TIn #in, Func<TIn, TOut> remainder, Func<TIn, TOut, TResult> resultSelector)
where TIn : class
where TOut : class
where TResult : class {
var #out = #in != null ? remainder(#in) : null;
return #out != null ? resultSelector(#in, #out) : null;
}
}
Then you can use LINQ:
var salary = from form in applicationForm
from info in form.employeeInfo
from cond in info.workingConditions
select cond.salary
This will return the salary if it exists, or null if any of the prior statements result to null, without throwing an exception.
Is it that much better? No, just saves you the slightest bit of repetition, but it looks cool. It also avoids the overhead of creating all the unused "OrDefault" objects in the accepted answer.

Categories

Resources