Why do this:
// If parameter cannot be cast to Point return false.
TwoDPoint p = obj as TwoDPoint;
if ((System.Object)p == null)
{
return false;
}
Instead of this:
// If parameter cannot be cast to Point return false.
TwoDPoint p = obj as TwoDPoint;
if (p == null)
{
return false;
}
I don't understand why you'd ever write ((System.Object)p)?
Regards,
Dan
You cast to object when you don't know or can't be sure whether the original class has overridden operator ==:
using System;
class AlwaysEqual
{
public static bool operator ==(AlwaysEqual a, AlwaysEqual b)
{
return true;
}
public static bool operator !=(AlwaysEqual a, AlwaysEqual b)
{
return true;
}
}
class Program
{
static void Main()
{
object o = new AlwaysEqual();
AlwaysEqual ae = o as AlwaysEqual;
if (ae == null)
{
Console.WriteLine("ae is null");
}
if ((object)ae == null)
{
Console.WriteLine("(object)ae is null");
}
}
}
This code outputs only "ae is null", which is obviously not the case. The cast to object avoids the AlwaysEqual class's operator == and is therefore a true reference check against null.
Every object in .NET is derived from System.Object so there is no need for explicit cast.
And even more concise would be:
if (!(obj is TwoDPoint)) {
return false;
}
Plainly speaking, It's pointless. Null can always be assigned(except for non-nullables such as ints and structs) regardless of type so it can always be checked for. The cast is not necessary
If TwoDPoint is a non-nullable type such as a struct then indeed it may have a point. The (System.Object) cache would effectively box the struct into a nullable object. But if that was the case then obj as TwoDPoint would not be valid. You would need obj as TwoDPoint? to make it nullable. (can't use as with non-nullables)
It makes total sense if that code is inside Object.Equals override and you don't want to invoke the equality operator (which might, for example, erroneously call Equals). Casting to object allows to call standard equality operator, which compares references.
Normally, you would use Object.ReferenceEquals to compare an instance of an object to null inside Equals override.
For example, this would cause a stack overflow:
public class Point {
public override bool Equals (object other) {
var otherPoint = other as Point;
if (other == null)
return false;
//...
}
public static bool operator == (Point l, Point r) {
//...
//null checks
if (!l.Equals(r))
return false;
}
}
In the above example equality operator calls Equals and because otherPoint variable is of type Point, it would invoke the equality operator, causing infinite recursion.
Normally, when you override Equals and define the equality operator, you would put the comparison logic in the operator and invoke that from the Equals override. Bear in mind that it's recommended for the class to be immutable if both are overridden.
public class Point {
public override bool Equals (object other) {
var otherPoint = other as Point;
return this == otherPoint;
}
//must override GetHashCode() as well
public static bool operator == (Point l, Point r) {
if (Object.ReferenceEquals(l, null) && Object.ReferenceEquals(r, null))
return true;
if (Object.ReferenceEquals(l, null) || Object.ReferenceEquals(r, null))
return false;
//actual equality checks
}
public static bool operator != (Point l, Point r) {
return !(l==r);
}
}
Related
I found an interesting thing, take this as a C# program:
namespace ConsoleApplication1
{
using System;
public class Student
{
public int ID { get; set; }
public string Name { get; set; }
public override bool Equals(object comparedStudent)
{
Student stu = comparedStudent as Student;
if (stu == null)
{
return false;
}
return ID.Equals(stu.ID) && Name.Equals(stu.Name);
}
public override int GetHashCode()
{
return ID.GetHashCode() ^ Name.GetHashCode();
}
/// <summary>
/// Notice that this will cause NullPointException……Why?
/// If I use "return s1.ID==s2.ID && s1.Name==s2.Name", that'd be OK.
/// </summary>
public static bool operator ==(Student s1, Student s2)
{
return s1.Equals(s2);
}
public static bool operator !=(Student s1, Student s2)
{
return !s1.Equals(s2);
}
}
public class Program
{
static void Main(string[] args)
{
Student s1 = new Student();
s1.ID = 1;
s1.Name = "YourName";
Student s2 = new Student();
s2.ID = 1;
s2.Name = "YourName";
//Why there's an exception here (NullPoint exception)
bool isSame = (s1 == s2);
Console.WriteLine(isSame);
}
}
}
If you copy my codes and run, a NullPointer exception will be thrown out. Why?
PS:If I use "return s1.ID==s2.ID && s1.Name==s2.Name" in the overload operator +, that'd be OK.
Why? I'm using net4.0 VS2015.
And if you debug by dropping the debug point at "bool isSame = (s1 == s2);" You'll soon find it enters into the "==" overload function 3 times, and in the end, s1 and s2 are null!
Although Ians comment will fix the above issue it will not finally fix the problem in general.
The origin of the problem is in the overload of the comparison operators.
A programmer expects null == myobject as well as myobject == null to be a valid expression (as you did as well in implementation of .Equals). This does not work for the above class because of the invocation of the member function s1.Equals in operator ==.
So any reasonable overload of a comparison operator should be able to handle really any input without throwing an exception. In doubt simply return false.
This includes null values as well as class instances that do not yet have all properties assigned.
public static bool operator ==(Student s1, Student s2) =>
ReferenceEquals(s1, s2) || (!ReferenceEquals(s1, null) && s1.Equals(s2));
Rationale:
ReferenceEquals(s1, s2) handles null == null as well as x == x. The latter does not require to compare the content.
s1 != null handles null == x.
x == null is already handled by the .Equals implementation.
By the way: it is recommended to provide a strongly typed .Equals implementation when overloading equality operators by implementing IEquatable<Student>.
Furthermore you should not use .Equals to compare components, because this will sadly fail for a similar reason if Name has not been assigned so far.
public override bool Equals(object obj) =>
Equals(obj as Student);
public bool Equals(Student stu) =>
!ReferenceEquals(stu, null) && ID == stu.ID && Name == stu.Name;
See also the reply of Yuval Itzchakov to question Operator overloading ==, !=, Equals
I had to compare equality of two two-dimensional arrays. I tried to use StructuralComparisons.StructuralEqualityComparer.Equals(obj1, obj2) and it works.
So now I wrote this method (in Helpers utility class):
public static bool Equals<T>(T obj1, T obj2)
{
return StructuralComparisons.StructuralEqualityComparer.Equals(obj1, obj2);
}
And a question: Which method should I use when I don't know whether Type T is struct (i.e. array) or class? Object.Equals or this one?
The answer is yes.
In such situations we can use StructuralComparisons comparer because it checks whether first object implements IStructuralEquatable and if it really implements, then it uses IStructuredEquatable.Equals() method, otherwise it uses obj1.Equals(obj2).
The implementation of this method is listed below
public new bool Equals(Object x, Object y) {
if (x != null) {
IStructuralEquatable seObj = x as IStructuralEquatable;
if (seObj != null){
return seObj.Equals(y, this);
}
if (y != null) {
return x.Equals(y);
} else {
return false;
}
}
if (y != null) return false;
return true;
}
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How do I check for nulls in an ‘==’ operator overload without infinite recursion?
Say I have a type like this:
public class Effect
{
public static bool operator == ( Effect a, Effect b )
{
return a.Equals ( b );
}
public static bool operator != ( Effect a, Effect b )
{
return !a.Equals ( b );
}
public bool Equals ( Effect effect )
{
return this.TypeID.Equals ( effect.TypeID );
}
public override bool Equals ( object obj )
{
return this.TypeID.Equals ( ( ( Effect ) obj ).TypeID );
}
}
What's the most robust and cleanest way to handle null values?
I am not sure if I have to check for null for both the current instance (this) and the passed instance (effect/obj)? If I have null for the current instance (this), would the compiler still call effect.Equals or Object.Equals?
Also either way where should the null checks be done? I am assuming only inside the Equals methods, and not the equality operators (==, !=).
Firstly, this can never be null, at least not in code produced by the C# compiler.
Second, use the ReferenceEquals method to check for a null reference without possibly calling an overloaded version of == (or do ((object) sometypeinstance) == null).
Visual Studio has a snippet that provides a basic Equals() implementation for you. I'd follow that, unless you have a strong reason not to.
// override object.Equals
public override bool Equals(object obj)
{
//
// See the full list of guidelines at
// http://go.microsoft.com/fwlink/?LinkID=85237
// and also the guidance for operator== at
// http://go.microsoft.com/fwlink/?LinkId=85238
//
if (obj == null || GetType() != obj.GetType())
{
return false;
}
// TODO: write your implementation of Equals() here
throw new NotImplementedException();
return base.Equals(obj);
}
// override object.GetHashCode
public override int GetHashCode()
{
// TODO: write your implementation of GetHashCode() here
throw new NotImplementedException();
return base.GetHashCode();
}
How about
public static bool operator == ( Effect a, Effect b )
{
return object.Equals(a, b);
}
The default implementation of Object.Equals() does the null checking for you.
In case you're curious, here's how Object.Equals() does it (courtesy of .NET Reflector):
public static bool Equals(object objA, object objB)
{
return ((objA == objB) || (((objA != null) && (objB != null)) && objA.Equals(objB)));
}
It is necessary to check for nulls with every method that takes parameters making your class.
public class Effect
{
public static bool operator == ( Effect a, Effect b )
{
if (a == null) && (b == null) return true;
if (a == null) return false;
return a.Equals ( b );
}
public static bool operator != ( Effect a, Effect b )
{
return !(a == b);
}
public bool Equals ( Effect effect )
{
if (b == null) return false;
return this.TypeID.Equals ( effect.TypeID );
}
public override bool Equals ( object obj )
{
if (obj == null) return false;
return this.TypeID.Equals ( ( ( Effect ) obj ).TypeID );
}
}
Other things to look out for are GetHashCode which should be implemented if equality is being implemented and the fact that GetHashCode should only be implemented on immutable properties, if this object is going to be used in a dictionary or similar object that compares items using the hash code.
Yes, you should chech against null. Why are you afraid of that?
Remember that when you play around with equals, you probably also want to take a look at the hashcode method! Those two methods are intertwined.
Add this:
public static bool operator == ( Effect a, Effect b )
{
return a is Effect && b is Effect && a.TypeID.Equals (b.TypeID);
}
public static bool operator != ( Effect a, Effect b )
{
return !(a == b );
}
public bool Equals ( Effect effect )
{
return this == effect );
}
public override bool Equals ( object obj )
{
return obj is Effect && this == obj);
}
or instead of last put:
public override bool Equals ( object obj )
{
if (obj == null) throw new ArgumentNullException(
"obj", "obj is null");
if (!(obj is effect)) throw new ArgumentException(
"obj", "obj is not an effect");
return obj is Effect && this == obj);
}
I was looking through the "Domain Oriented N-Layered .NET 4.0 Sample App" project and ran across some code that I do not understand. In this project they often use syntax like the following to check arguments for null:
public GenericRepository(IQueryableContext context,ITraceManager traceManager)
{
if (context == (IQueryableContext)null)
throw new ArgumentNullException("context", Resources.Messages.exception_ContainerCannotBeNull);
Why would you cast null to the type of the object you are checking for null?
It's pointless in the example given.
While not applicable in this case, there is sometimes a need to cast null (or at least there was before default(T) was added. Consider the following:
void DoSomething(string x) {
...
}
void DoSomething(object x) {
...
}
DoSomething(null); // compiler can't infer the type
DoSomething((string)null); // string type is now explicit
DoSomething(default(string)); // same as previous
EDIT
Just thought of another case where you would have to do the cast when testing equality. If you had an object that had an overloaded == operator that allowed comparison with two reference types, comparing against null would be ambiguous. However because IQueryableContext is most likely an interface and interfaces cannot overload the == operator, I still don't see any valid reason to do it in the example you gave.
class CustomObject {
private string _id;
public CustomObject(string id) {
_id=id;
}
public static bool operator ==(CustomObject lhs, CustomObject rhs) {
if (ReferenceEquals(lhs, rhs)) { return true; }
if (ReferenceEquals(lhs, null)) { return false; }
if (ReferenceEquals(rhs, null)) { return false; }
return lhs._id == rhs._id;
}
public static bool operator !=(CustomObject lhs, CustomObject rhs) {
return !(lhs == rhs);
}
public static bool operator ==(CustomObject lhs, string rhs) {
if (ReferenceEquals(lhs, rhs)) { return true; }
if (ReferenceEquals(lhs, null)) { return false; }
if (ReferenceEquals(rhs, null)) { return false; }
return lhs._id == rhs;
}
public static bool operator !=(CustomObject lhs, string rhs) {
return !(lhs==rhs);
}
}
CustomObject o = null;
if (o == null) {
Console.WriteLine("I don't compile.");
}
I wouldn't do a cast. There's no reason for it in this case.
There is no reason to cast null in the given example. It might be for legibility... I don't know, I wouldn't do this =P
In some cases [which doesn't include the case covered in this topic] you have to cast to INullable before you can check to see if a variable is null. Otherwise, you have to use object==default(TypeOfObject)...
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());
}
}