I have a .Find statement like so:
MyObject obj = existingObjs.Find(x => x.listA == currentObj.listA &&
x.listB == currentObj.listB);
Unfortunately "obj" is always null because my "currentObj" has a listB = null but "x.listB" is always an empty list. I want to treat null and empty list as the same thing, how would I put that into my .Find statement?
I tried something like so but, it is returning a bool instead of an obj so it won't compile.
MyObject obj = existingObjs.Find(x => x.listA == currentObj.listA &&
(x.listB == null ? null : currentObj.listB));
Some points to note:
you should rather not use == for comparing complicated objects like lists, since == tests for reference equality, not the structure (e.g. whether elements on the list are the same). For comparing lists you could use Enumerable.SequenceEqual
mixing null and empty list in the same variable is a bad practice that will hit you in many places just like here, but for handling null vs empty there is nullish coalescing operator x.listB ?? Enumerable.Empty() that will always return enumerable object that you can use for comparisons
all of this should be put into bool Equals(MyObject other) method
for example
using System;
using System.Linq;
class MyObject<T> : IEquatable<MyObject<T>> {
public bool Equals(MyObject<T> other) {
if (other == null)
return false;
return ListsEqual(listA, other.listA) &&
ListsEqual(listB, other.listB);
}
bool ListsEqual(IList<T> l1, IList<T> l2) {
return Enumerable.SequenceEqual(ListOrEmpty(l1), ListOrEmpty(l2));
}
IEnumerable<T> ListOrEmpty(IList<T> li) {
return li ?? Enumerable.Empty<T>();
}
IList<T> listA;
IList<T> listB;
}
You could use the conditional operator:
currentObj.listB == null ?
!Any(x.listB) :
Enumerable.SequenceEqual(currentObj.listB, x.listB)
You could use null-coalescing operator to make sure array in currentObject will be empty arrays when they are null and then compare them:
currentObject.listA ??= Array.Empty<ListAType>();
currentObject.listB ??= Array.Empty<ListBType>();
MyObject obj = existingObjs.Find(x => Enumerable.SequenceEqual(x.listA, currentObj.listA) &&
Enumerable.SequenceEqual(x.listB, currentObj.listB));
object bread(food foo)
{
return foo.ingredient ?? "cheese";
}
If foo exits, but ingredient is null, I get "cheese".
My question, including an assumption:
If foo itself is null will "chesse" be returned or will it throw an ArgutmentNullException?
My GUESS is that the NullCoalescingOperator is implemented more or less like this:
object nco(object lhs, object rhs)
{
if(lhs != null)
return lhs;
else
return rhs;
}
Therefore passing foo.ingredient already causes the exception(since you cannot check a field in an object that you don't have) and thus it is thrown.
Would make sense.
Is this idea correct / how is the nco implemented and why?
You will get a NullReferenceException if foo is null.
So you've got to treat this case, with a ternary (if else) rather than a coalesce.
return (foo == null || foo.ingredient == null)
? "cheese"
: foo.ingredient;
Yes, you idea is absolutely correct because:
foo.ingredient ?? "cheese";
Equals to:
foo.ingredient != null ? foo.ingredient : "cheese";
What you might like, in VS2014 CTP they already have new operator ?., which will do what you need:
foo?.ingredient ?? "cheese";
Of course it'll throw an exception. You cannot access a property of the object, that's not there. If you want secure yourself from an error, you could write:
return (foo == null) ? "cheese" : (foo.ingredient ?? "cheese");
This is my code..
object o = DBExecuteScalar(myQuery);
if ((int.parse(o.ToString())) <= 2 || (o is null))
{
// my task....
}
In this code, 'o is null' part is giving error. Any help how to deal with these both conditions in single if statement.. What I want is that the value of o should be (null,0,1,2).
Any help ??
In C#, the is operator checks for type equality. You need to check for null as o == null:
object o = DBExecuteScalar(myQuery);
if ((o == null) || (int.parse(o.ToString())) <= 2)
{
// my task....
}
You also need to check for null before you try to perform any actions on it
when you reverse the conditions in the if, then it should work.
In your case the ToString is called first on object o. But because o is null this will result in an exception.
When you reverse the order of your conditions, then the nullcheck will be first. The second part of the or (||) is only evaluated when the first part is false. This will prevent the exception from occurring
With || operator first condition is evaluated first - you want to check if is null first.
Also the int.Parse is not necessary. As RGraham mentioned is null is not a proper way how to check for null.
if (o == null || o == DBNull.Value || (int)o <= 2)
As I understand and read you can use short circuiting in if statement (&& or ||) in order for second condition not to fire. and if you want both condition to fire you would use single operands (& or |).
So say if I have inline if statement as below :
var test = (MyObject != null || string.IsNullOrEmpty(MyObject.Property)) ? string.Empty : MyObject.Property;
This will throw object reference error if MyObject is null, which in my opinion should not as I am using short circuiting. Can someone please explain this.
You're using the wrong condition. This part:
MyObject != null || string.IsNullOrEmpty(MyObject.Property)
should be:
MyObject == null || string.IsNullOrEmpty(MyObject.Property)
The RHS of an || only executes if the left hand is false. You want it to only execute if MyObject is not null.
EDIT: If you really want the MyObject != null part, you could change the whole thing to:
var test = MyObject != null && !string.IsNullOrEmpty(MyObject.Property)
? MyObject.Property : "";
Note the reversal of the 2nd and 3rd operands of the conditional operator too though.
You should have an == not an !=
var test = (MyObject == null || string.IsNullOrEmpty(MyObject.Property) ? string.Empty : MyObject.Property
Try this:
var test = (MyObject == null || string.IsNullOrEmpty(MyObject.Property)
? string.Empty : MyObject.Property
MyObject != null || string.IsNullOrEmpty(MyObject.Property)
Here you say.
If my object is not null.
or
string.IsNullOrEmpty(MyObject.Property)
Which means that if MyObject is null he will try to execute the second part.
MyObject == null || string.IsNullOrEmpty(MyObject.Property)
This won't throw null exception
That happens because MyObject is null and therefore the first condition is false so the second part must be evaluated to know the whole of the condition. Change the line to this:
MyObject != null && string.IsNullOrEmpty(MyObject.Property)
You should prefer readability instead of line-count, e.g.:
string prop = string.Empty;
if(MyObject != null && MyObject.Property != null)
prop = MyObject.Property;
(the reason for your exception was already explained in other answers)
C#6 Update
In C#6 ?. is now a language feature:
// C#1-5
propertyValue1 = myObject != null ? myObject.StringProperty : null;
// C#6
propertyValue1 = myObject?.StringProperty;
The question below still applies to older versions, but if developing a new application using the new ?. operator is far better practice.
Original Question:
I regularly want to access properties on possibly null objects:
string propertyValue1 = null;
if( myObject1 != null )
propertyValue1 = myObject1.StringProperty;
int propertyValue2 = 0;
if( myObject2 != null )
propertyValue2 = myObject2.IntProperty;
And so on...
I use this so often that I have a snippet for it.
You can shorten this to some extent with an inline if:
propertyValue1 = myObject != null ? myObject.StringProperty : null;
However this is a little clunky, especially if setting lots of properties or if more than one level can be null, for instance:
propertyValue1 = myObject != null ?
(myObject.ObjectProp != null ? myObject.ObjectProp.StringProperty) : null : null;
What I really want is ?? style syntax, which works great for directly null types:
int? i = SomeFunctionWhichMightReturnNull();
propertyValue2 = i ?? 0;
So I came up with the following:
public static TResult IfNotNull<T, TResult>( this T input, Func<T, TResult> action, TResult valueIfNull )
where T : class
{
if ( input != null ) return action( input );
else return valueIfNull;
}
//lets us have a null default if the type is nullable
public static TResult IfNotNull<T, TResult>( this T input, Func<T, TResult> action )
where T : class
where TResult : class
{ return input.IfNotNull( action, null ); }
This lets me us this syntax:
propertyValue1 = myObject1.IfNotNull( x => x.StringProperty );
propertyValue2 = myObject2.IfNotNull( x => x.IntProperty, 0);
//or one with multiple levels
propertyValue1 = myObject.IfNotNull(
o => o.ObjectProp.IfNotNull( p => p.StringProperty ) );
This simplifies these calls, but I'm not sure about checking this sort of extension method in - it does make the code a little easier to read, but at the cost of extending object. This would appear on everything, although I could put it in a specifically referenced namespace.
This example is a rather simple one, a slightly more complex one would be comparing two nullable object properties:
if( ( obj1 == null && obj2 == null ) ||
( obj1 != null && obj2 != null && obj1.Property == obj2.Property ) )
...
//becomes
if( obj1.NullCompare( obj2, (x,y) => x.Property == y.Property )
...
What are the pitfalls of using extensions in this way? Are other coders likely to be confused? Is this just abuse of extensions?
I guess what I really want here is a compiler/language extension:
propertyValue1 = myObject != null ? myObject.StringProperty : null;
//becomes
propertyValue1 = myObject?StringProperty;
This would make the complex case far easier:
propertyValue1 = myObject != null ?
(myObject.ObjectProp != null ? myObject.ObjectProp.StringProperty) : null
//becomes
propertyValue1 = myObject?ObjectProp?StringProperty;
This would only work for value types, but you could return nullable equivalents:
int? propertyValue2 = myObject?ObjectProp?IntProperty;
//or
int propertyValue3 = myObject?ObjectProp?IntProperty ?? 0;
We independently came up with the exact same extension method name and implementation: Null-propagating extension method. So we don't think it's confusing or an abuse of extension methods.
I would write your "multiple levels" example with chaining as follows:
propertyValue1 = myObject.IfNotNull(o => o.ObjectProp).IfNotNull(p => p.StringProperty);
There's a now-closed bug on Microsoft Connect that proposed "?." as a new C# operator that would perform this null propagation. Mads Torgersen (from the C# language team) briefly explained why they won't implement it.
Here's another solution, for chained members, including extension methods:
public static U PropagateNulls<T,U> ( this T obj
,Expression<Func<T,U>> expr)
{ if (obj==null) return default(U);
//uses a stack to reverse Member1(Member2(obj)) to obj.Member1.Member2
var members = new Stack<MemberInfo>();
bool searchingForMembers = true;
Expression currentExpression = expr.Body;
while (searchingForMembers) switch (currentExpression.NodeType)
{ case ExpressionType.Parameter: searchingForMembers = false; break;
case ExpressionType.MemberAccess:
{ var ma= (MemberExpression) currentExpression;
members.Push(ma.Member);
currentExpression = ma.Expression;
} break;
case ExpressionType.Call:
{ var mc = (MethodCallExpression) currentExpression;
members.Push(mc.Method);
//only supports 1-arg static methods and 0-arg instance methods
if ( (mc.Method.IsStatic && mc.Arguments.Count == 1)
|| (mc.Arguments.Count == 0))
{ currentExpression = mc.Method.IsStatic ? mc.Arguments[0]
: mc.Object;
break;
}
throw new NotSupportedException(mc.Method+" is not supported");
}
default: throw new NotSupportedException
(currentExpression.GetType()+" not supported");
}
object currValue = obj;
while(members.Count > 0)
{ var m = members.Pop();
switch(m.MemberType)
{ case MemberTypes.Field:
currValue = ((FieldInfo) m).GetValue(currValue);
break;
case MemberTypes.Method:
var method = (MethodBase) m;
currValue = method.IsStatic
? method.Invoke(null,new[]{currValue})
: method.Invoke(currValue,null);
break;
case MemberTypes.Property:
var method = ((PropertyInfo) m).GetGetMethod(true);
currValue = method.Invoke(currValue,null);
break;
}
if (currValue==null) return default(U);
}
return (U) currValue;
}
Then you can do this where any can be null, or none:
foo.PropagateNulls(x => x.ExtensionMethod().Property.Field.Method());
If you find yourself having to check very often if a reference to an object is null, may be you should be using the Null Object Pattern. In this pattern, instead of using null to deal with the case where you don't have an object, you implement a new class with the same interface but with methods and properties that return adequate default values.
How is
propertyValue1 = myObject.IfNotNull(o => o.ObjectProp.IfNotNull( p => p.StringProperty ) );
easier to read and write than
if(myObject != null && myObject.ObjectProp != null)
propertyValue1 = myObject.ObjectProp.StringProperty;
Jafar Husain posted a sample of using Expression Trees to check for null in a chain, Runtime macros in C# 3.
This obviously has performance implications though. Now if only we had a way to do this at compile time.
I just have to say that I love this hack!
I hadn't realized that extension methods don't imply a null check, but it totally makes sense. As James pointed out, The extension method call itself is not any more expensive than a normal method, however if you are doing a ton of this, then it does make sense to follow the Null Object Pattern, that ljorquera suggested. Or to use a null object and ?? together.
class Class1
{
public static readonly Class1 Empty = new Class1();
.
.
x = (obj1 ?? Class1.Empty).X;
it does make the code a little easier to read, but at the cost of extending object. This would appear on everything,
Note that you are not actually extending anything (except theoretically).
propertyValue2 = myObject2.IfNotNull( x => x.IntProperty, 0);
will generate IL code exactly as if it were written:
ExtentionClass::IfNotNull(myObject2, x => x.IntProperty, 0);
There is no "overhead" added to the objects to support this.
To reader not in the know it looks like you're calling a method on a null reference. If you want this, I'd suggest putting it in a utility class rather than using an extension method:
propertyValue1 = Util.IfNotNull(myObject1, x => x.StringProperty );
propertyValue2 = Util.IfNotNull(myObject2, x => x.IntProperty, 0);
The "Util." grates, but is IMO the lesser syntactic evil.
Also, if you developing this as part of a team, then gently ask what others think and do. Consistency across a codebase for frequently used patterns is important.
While extension methods generally cause misunderstandings when called from null instances, I think the intent is pretty straightforward in this case.
string x = null;
int len = x.IfNotNull(y => y.Length, 0);
I would want to be sure this static method works on Value Types that can be null, such as int?
Edit: compiler says that neither of these are valid:
public void Test()
{
int? x = null;
int a = x.IfNotNull(z => z.Value + 1, 3);
int b = x.IfNotNull(z => z.Value + 1);
}
Other than that, go for it.
Not an answer to the exact question asked, but there is Null-Conditional Operator in C# 6.0. I can argue it will be a poor choice to use the option in OP since C# 6.0 :)
So your expression is simpler,
string propertyValue = myObject?.StringProperty;
In case myObject is null it returns null. In case the property is a value type you have to use equivalent nullable type, like,
int? propertyValue = myObject?.IntProperty;
Or otherwise you can coalesce with null coalescing operator to give a default value in case of null. For eg,
int propertyValue = myObject?.IntProperty ?? 0;
?. is not the only syntax available. For indexed properties you can use ?[..]. For eg,
string propertyValue = myObject?[index]; //returns null in case myObject is null
One surprising behaviour of the ?. operator is that it can intelligently bypass subsequent .Member calls if object happens to be null. One such example is given in the link:
var result = value?.Substring(0, Math.Min(value.Length, length)).PadRight(length);
In this case result is null if value is null and value.Length expression wouldn't result in NullReferenceException.
Personally, even after all your explanation, I can't remember how the heck this works:
if( obj1.NullCompare( obj2, (x,y) => x.Property == y.Property )
This could be because I have no C# experience; however, I could read and understand everything else in your code. I prefer to keep code language agnostic (esp. for trivial things) so that tomorrow, another developer could change it to a whole new language without too much information about the existing language.
Here is another solution using myObject.NullSafe(x=>x.SomeProperty.NullSafe(x=>x.SomeMethod)), explained at
http://www.epitka.blogspot.com/