The following overloaded ==operator is part of the Calender class in QL.net
public static bool operator ==(Calendar c1, Calendar c2)
{
return (c1.empty() && c2.empty())
|| (!c1.empty() && !c2.empty() && c1.name() == c2.name());
}
public bool empty() { return (object)calendar == null; }
When I try to access the SouthAfricanCalender property, I receive a System.NullReferenceException : Object reference not set to an instance of an object. which prompted me to dig into the source.
public SouthAfrica SouthAfricanCalender
{
get
{
if (_calender == null)
{
_calender = new SouthAfrica();
}
return _calender;
}
set
{
if (_calender == null)
{
_calender = value;
}
}
}
SouthAfrica _calender;
I have ammended the overload as follows based on the answer here
public static bool operator ==(Calendar c1, Calendar c2)
{
if ( object.ReferenceEquals(c1,c2)) return true;
if ((object)c1 == null || (object)c2 == null) return false;
return (c1.empty() && c2.empty())
|| (!c1.empty() && !c2.empty() && c1.name() == c2.name());
}
My question, have I changed the intent of the original code with my amendment?
Edit: any suggestions on how this can be cleaned up further?
No. You ensure that both are objects, and respond accordingly in the places that they aren't (assuming that ReferenceEquals can handle double null). Then you simply execute the same check. The whole .empty() thing is totally unnecessary, by the way, you already know that it's not null, just return the name comparison.
No, you haven't.
It still checks for equality.
Related
I'v been playing around with some shorter hand ways of checking multiple nested objects to see if any are null before proceeding. I'm trying to replace the multiple nested if statements into a single statement if possible using Null-conditional Operators.
So far i have something like this:
if ((Object1?.Object2?.Object3?.Object4 != null) ? true : false)
{
...
}
Would the above be effective at identifying if either Object1 2 3 or 4 is null and return a false if so? I'm interested to hear if anyone has any better solutions?
TIA
You don't need to return false or true - boolean condition itself has boolean value:
if (Object1?.Object2?.Object3?.Object4 != null)
This part is a completely valid option for checking nested objects if any of them is null. You can find exactly same example in null-conditional operator documentation:
// null if customers, the first customer, or Orders is null
int? count = customers?[0]?.Orders?.Count();
And explanation:
The last example demonstrates that the null-condition operators are
short-circuiting. If one operation in a chain of conditional member
access and index operation returns null, then the rest of the chain’s
execution stops.
The code
public void Foo()
{
if ((Object1?.Object2?.Object3?.Object4 != null) ? true : false)
{
...
}
}
is logically equivalent to
public void Foo()
{
if ((NullCheck(Object1) != null) ? true : false)
{
...
}
}
private Object4Type NullCheck(Object1Type object1)
{
if(!Object.RefrenceEquals(object1, null)) //This is "Object1?."
{
var tmpObject2 = tmpObject1.Object2;
if(!Object.RefrenceEquals(tmpObject2, null)) //This is "Object2?."
{
var tmpObject3 = tmpObject2.Object3;
if(!Object.RefrenceEquals(tmpObject3, null)) //This is "Object3?."
{
return tmpObject3.Object4;
}
}
}
return default(Object4Type);
}
or if Object4Type is a struct
public void Foo()
{
if ((NullCheck(Object1) != null) ? true : false)
{
...
}
}
private Nullable<Object4Type> NullCheck(Object1Type object1)
{
if(!Object.RefrenceEquals(object1, null)) //This is "Object1?."
{
var tmpObject2 = tmpObject1.Object2;
if(!Object.RefrenceEquals(tmpObject2, null)) //This is "Object2?."
{
var tmpObject3 = tmpObject2.Object3;
if(!Object.RefrenceEquals(tmpObject3, null)) //This is "Object3?."
{
return tmpObject3.Object4;
}
}
}
return default(Nullable<Object4Type>);
}
So your ... will only be run if all objects are not null and if a lower level object is null, the later objects never get evaluated.
What you have is currently the best way to do exactly what you want. I wanted to answer in order to illustrate what's necessary if you don't have access to the latest C# 6 language features. This is the next most developer-friendly way to make the same check in .NET 3.5-4.0:
//boilerplate, off in your extension method library
public static TOut OrDefault<TIn, TOut>(this TIn input,
Func<TIn, TOut> possiblyNullFunc)
{
try { return possiblyNullFunc(input); }
catch (NullReferenceException) //for most reference types
{ return default(TOut); }
catch (InvalidOperationException) //for Nullable<T>
{ return default(TOut); }
}
...
//usage
if (Object1.OrDefault(o=>o.Object2.Object3.Object4) != null)
{
...
}
It functions pretty well, until you try to use InvalidOperationException in your own classes for situations other than null member access.
Still beats the pants off this, especially if you have to make this check a lot:
if(Object1 != null
&& Object1.Object2 != null
&& Object1.Object2.Object3 != null
&& Object1.Object2.Object3.Object4 != null)
{
...
}
I have the following code that should check if all the properties of class are null. I tried the code below but it didn't work. Why?
You could make a property IsInitialized, that does this internally:
public bool IsInitialized
{
get
{
return this.CellPhone == null && this.Email == null && ...;
}
}
Then just check the property IsInitialized:
if (myUser == null || myUser.IsInitialized)
{ ... }
Another option is the use of reflection to walk over and check all properties, but it seems overkill to me. Also, this gives you the freedom to deviate from the original design (when you choose all properties, except one should be null for example).
//NameSpace
using System.Reflection;
//Definition
bool IsAnyNullOrEmpty(object myObject)
{
foreach(PropertyInfo pi in myObject.GetType().GetProperties())
{
if(pi.PropertyType == typeof(string))
{
string value = (string)pi.GetValue(myObject);
if(string.IsNullOrEmpty(value))
{
return true;
}
}
}
return false;
}
//Call
bool flag = IsAnyNullOrEmpty(objCampaign.Account);
I am suffering a weird problem in C# 4.5.
I have this in my model:
private DataMatrix<T> _matrix;
public DataMatrix<T> Matrix
{
get { return _matrix; }
set { _matrix = value; }
}
And I have a property which uses this:
public object SingleElement
{
get
{
if (Matrix == null) return String.Empty;
if (Matrix.ColumnCount >= 1 && Matrix.RowCount >= 1)
{
return Matrix[0, 0];
}
return null;
}
}
When I run it, before calling SingleElement, the Matrix property is null. But it doesn't return String.Empty, it goes to the second if-statement.
That's my Immediate window says:
I'm a bit confused. What did I do wrong?
This is a most likely a broken equality operator (==), which can be reproduced with the following code:
class Foo
{
public static bool operator == (Foo x, Foo y)
{
return false; // probably more complex stuff here in the real code
}
public static bool operator != (Foo x, Foo y)
{
return !(x == y);
}
static void Main()
{
Foo obj = null;
System.Diagnostics.Debugger.Break();
}
// note there are two compiler warnings here about GetHashCode/Equals;
// I am ignoring those for brevity
}
now at the breakpoint in the immediate window:
?obj
null
?(obj==null)
false
Two fixes:
preferred would be to fix the operator, perhaps adding before anything else:
if(ReferenceEquals(x,y)) return true;
if((object)x == null || (object)y == null) return false;
// the rest of the code...
alternative, if you can't edit that type, is to avoid using the operator; consider using ReferenceEquals explicitly in your code, or performing object-based null checks; for example:
if(ReferenceEquals(Matrix, null)) ...
or
if((object)Matrix == null) ...
This question already has answers here:
How do I check for nulls in an '==' operator overload without infinite recursion?
(13 answers)
Closed 9 years ago.
I overloaded the == operator on my class as follows:
public static bool operator ==(Table pt1, Table pt2) {
return Compare(pt1, pt2) == 0 && pt1.TableName == pt2.TableName;
}
Compare will work just as the strcmp does in c++, returning an integer. Problem is that if I do an if (MY_CLASS == null), it will call my == operator, and thus my Compare function. What is the alternatiev? to put an check on pt1 and pt2 to see if they are null? Or just in pt2?
You should checkout Microsoft's guidelines for implementing the '==' operator and also for overriding 'Equals()'.
Adapting their example you'd want something like:
public static bool operator ==(Table a, Table b)
{
// If both are null, or both are same instance, return true.
if (System.Object.ReferenceEquals(a, b))
{
return true;
}
// If one is null, but not both, return false.
if (((object)a == null) || ((object)b == null))
{
return false;
}
// Return true if the fields match:
return Compare(a, b) == 0 && a.TableName == b.TableName;
}
You will need the null checks to get the correct behaviour. The clearest way to add this check in my opinion is to call object.ReferenceEquals(x, null), since it is a straight non-polymorphic method call and presumably fairly efficient.
Just add this line to your operator:
if ((object)pt1 == null || (object)pt2 == null) return false;
The (object) cast is there to prevent recursion (from calling object.== instead of MY_CLASS.==.
Although I'm not sure of the conditions that should arise when comparing null to null.
I asked a similar question here. Have a look at it.
public bool Equals(ClauseBE other)
{
if (this._id == other._id)
{
return true;
}
return false;
}
public override bool Equals(Object obj)
{
if (obj == null)
{
return base.Equals(obj);
}
if (!(obj is ClauseBE))
{
throw new InvalidCastException("The 'obj' argument is not a ClauseBE object.");
}
return Equals(obj as ClauseBE);
}
public override int GetHashCode()
{
return this._id.GetHashCode();
}
public static bool operator ==(ClauseBE a, ClauseBE b)
{
if (ReferenceEquals(a, null) && ReferenceEquals(b, null))
{
return true;
}
if (ReferenceEquals(a, null) || ReferenceEquals(b, null))
{
return false;
}
return a.Equals(b);
}
public static bool operator !=(ClauseBE a, ClauseBE b)
{
return !(a == b);
}
I've defined a C# class with a string member. For all intents an purposes, think of this class as being a subclass of string (except that's not allowed). I'm using it to represent a strongly typed string field that matches a specific format (I've simplified this significantly).
public class field
{
private readonly string m_field;
public field(string init_value)
{
//Check the syntax for errors
if (CheckSyntax(init_value))
{
m_field = init_value;
}
else
{
throw new ArgumentOutOfRangeException();
}
}
public override string ToString()
{
return m_field;
}
}
Now, I want to be able to compare this class directly to any other string (object or literal). Therefore, I implemented the following in the class:
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
return this.m_field == obj.ToString();
}
public override int GetHashCode()
{
return this.m_field.GetHashCode();
}
public static bool operator ==(field x, Object y)
{
if ((object)x == null && y == null)
{
return true;
}
else if ((object)x == null || y == null)
{
return false;
}
else
{
return (x.m_field == y.ToString());
}
}
public static bool operator !=(field x, Object y)
{
return !(x == y);
}
Now when I'm writing a unit test, depending on the order that I'm passing in the arguments to Assert.AreEqual, I get different results:
string valid = "Some String";
field target = new field(valid);
Assert.AreEqual(target, valid); // PASSES
Assert.AreEqual(valid, target); // FAILS
I'm assuming this is because in the first assert, it's calling field.Equals() and in the second it's calling String.Equals(). Obviously I'm approaching this from the wrong angle. Can anyone give me some insight?
One other thing. I can't use a struct here (value type) because in my actual case I'm defining all this in a base class and inheriting from it.
Basically you can't do what you want to - there's no way you can make string recognise your class for equality purposes. You'll never be able to make it reflexive - you'll never be able to make it obey the contract of object.Equals.
I would personally try to redesign it so that you didn't have the validation as part of the type itself - make it part of the relevant properties of the business entities (or whatever they are).
This is described in detail in Effective Java as Item 8: Obey the general contract when overriding equals.
The equals method implements an equivalence relation.
It is Reflexive, Symmetric, Transitive, Consistent, and for any non-null reference x, x.equals(null) must return false. The example cited to break symmetry is similar to yours.
field class is aware of string class, but the built-in string class is not aware of field. This a one-way interoperability, and should be removed.
I would discourage anyone using your field class implicitly as a String, and force this type of usage:
string valid = "Some String";
field target = new field(valid);
Assert.AreEqual(target.toString(), valid);
Assert.AreEqual(valid, target.toString());
Based on everyone's feedback, and my own needs, here's what I'm putting forward as a possible solution (I'm modifying the Equals method as follows):
public override bool Equals(Object obj)
{
if (obj == null)
{
return false;
}
field f = obj as field;
if (f != null)
{
return this == f;
}
else
{
return obj.Equals(this);
}
}
This seems to allow its correct use in dictionary and collection classes that rely on the Equals and GetHashCode methods for determining if the value already exists.
Also, now these both fail:
string valid = "Some String";
field target = new field(valid);
Assert.AreEqual(target, valid); // FAILS
Assert.AreEqual(valid, target); // FAILS
And these both pass:
string valid = "Some String";
field target = new field(valid);
Assert.AreEqual(target.ToString(), valid); // PASSES
Assert.AreEqual(valid, target.ToString()); // PASSES
And these both pass:
field f1 = new field("Some String");
field f2 = new field("Some String");
Assert.AreEqual(f1, f2); // PASSES
Assert.AreEqual(f2, f1); // PASSES
This is String#Equals
public override bool Equals(object obj)
{
string strB = obj as string;
if ((strB == null) && (this != null))
{
return false;
}
return EqualsHelper(this, strB);
}
Supplying an argument other than a String to String#Equals is going to return false. I'd suggest a 'rethink' to get around this.
I suggest using object.ReferenceEquals() if you are internally trying to validate whether x or y is null.
public static bool operator ==(field x, Object y)
{
if (object.ReferenceEquals(x, null) && object.ReferenceEquals(y, null))
{
return true;
}
else if (object.ReferenceEquals(x, null) || object.ReferenceEquals(y, null))
{
return false;
}
else
{
return (x.m_field == y.ToString());
}
}