I'm trying to compare two DataRows in a loop. However, the following if statement doesn't return true:
if (dt1.Rows[0]["Name"] == dt2.Rows[b]["Name"]) {
// This never executes
}
However, if I add .ToString() to the end of each DataRow, the if statement returns true:
if (dt1.Rows[0]["Name"].ToString() == dt2.Rows[b]["Name"].ToString()) {
// This now executes
}
The column "Name" is from the same table/column. So the question is quite simple... What am I doing wrong?
Thanks
Stephen
Those cells hold objects so you are doing an object comparison, which just does a reference comparison, which is different from a value comparison. It asks the question "Are these two objects really the same object?", essentially are they referring to the same object, hence "reference comparison". When you do the ToString() call, you are then doing string comparison. That is why it works.
Here's a link to MS's discussion of Operator== and comparison.
As itsmatt has said, your first snippet is doing a reference comparison. An alternative to calling ToString is to use Object.Equals:
if (Object.Equals(dt1.Rows[0]["Name"], dt2.Rows[b]["Name"])) {
// stuff
}
The reason for using the static method instead of the instance method is to avoid problems with null references.
The == operator, if not overloaded, is identical to ReferenceEquals() -- that is, it determines whether two given objects are the same instances.
The call to ToString() returns an object of string class, which has overloaded == operator, which does string comparison.
Related
I have code where I get a string as input, and I compare it with an integer.
I saw that integer variable also has an Equals function that accepts a string parameter.
I have used it directly thinking it will typecast it.
It did not give any compile time or runtime error, but it always gives a false result.
For example,
int sessionId = 1;
string requestId="1"
return sessionId.Equals(requestId);
sessionId.Equals(requestId) always gives false.
Why is the reason for such behavior? If there is a reason, why are they allowing it run without error?
Integers and strings are always different, and thus "1".Equals(1) returns false.
It compiles because object.Equals(object other) takes an object as the right side, and thus accepts any type.
The reason why this happens is that a string "0" is not the same as 0, so it returns false.
Why is such behavior supported? Because the Equals method allows you to pass an object as a parameter, and a string is in an object, so you are "allowed" to do it. As you have found, it's not very useful in this case.
To solve your problem either get a string representation of the integer, or parse your string to an integer, then compare.
E.g. Try
return (sessionId.ToString() == requestId);
or
return (sessionId == int.Parse(requestId));
If you choose the later you may need to consider if the Parse could fail and how you might handle that.
Yes, Equals takes any type on the right side because it is requires an object. But inside the function it requires the same type as the left side. IMHO there's no need to throw an exception for type mismatching because one only wants to know about equality of two types.
Decompiled Equals of int:
public override bool Equals(object obj)
{
return obj is int && this == (int)obj;
}
If someone shows you a car and a banana, and asks whether they are the same thing, would you throw a temper tantrum because a car is a vehicle and a banana is a fruit, or would you simply say "no, they are not the same thing"?
In many languages, trying to compare an integer and a string will yield a compiler error, because the compiler knows that the integer and the string cannot possibly be the same thing and thus any code that tried to compare them would almost certainly be erroneous. On the other hand, when you say sessionId.Equals(requestId), the compiler knows that you are asking that requestId be passed to the Int32 override of Equals. Since that override can accept a reference to any kind of heap object, it has no problem passing the string "1". That method in turn knows that it was given something which isn't the same as an Int32 with the value 1. It doesn't know that the calling code can't possibly supply anything that would match an Int32; all it knows is that the particular value isn't the same, and because the value isn't the same it perfectly happily returns false.
Shouldn’t we be using String.Compare for string comparison and forget about Equals?
I did have the same problem and I believe the function Equals should throw an exception. In my case, I have been comparing a string with a Boolean.
The discussion by now went wrong way. This is my view:
If a comparison between objects belonging to two different classes always returns false, then they do not need to be compared in the first place.
If there is a need to have a function that bypasses type checking, there should be one. However, having the function Equals positioned as a recommended method for string comparison and in the same time introducing the possibility of unneeded bugs (which may sit in your program for eternity) is a kind of irresponsible.
Moreover, it is extremely misleading that the function call String.Equals(string1, string2, StringComparison. xxx) also accepts non-string arguments. Thus not only string1.Equals(string2).
If that is by design, then it is a poor design.
Basically the title. I see a lot of the former in the code I'm working on and I was wondering why they didn't use the latter. Are there any differences between the two?
Thanks.
Straight from the documentation
Unlike the Equals method and the equality operator, the ReferenceEquals method cannot be overridden. Because of this, if you want to test two object references for equality and are unsure about the implementation of the Equals method, you can call the ReferenceEquals method. However, note that if objA and objB are value types, they are boxed before they are passed to the ReferenceEquals method.
Not really. One can overload operator ==, so you basically can get it return e.g. false always. The recommended usage for this operator is to signify value equality, so (for correcftly implemented operator) basically check against null may return true if the object is semantically null.
See this article for more details and some historical overview.
Another difference is that for value types ReferenceEquals doesn't make much sense: for example, any two "instances" of int 0 have to be considered the same in any sane circumstances. (For purists: I put quotes because, strictly speaking, we cannot talk about instances of a value type.)
The main benefit of ReferenceEquals() is that the intention is much clearer, you are trying to determine if two references are equal, not if the contents of the objects referred to are equal.
It does this by checking for operator == equality between the two references cast to object (since the params are both object), which eliminates any subclass operator == overloads that might confuse the issue (like string's).
So essentially, this:
if (ReferenceEquals(x, y))
Is the same as this:
if (((object)x) == ((object)y))
Though the former is easier to read.
There are definitely times where it comes in handy, especially avoiding infinite recursion when you are overloading operator == yourself:
public class Foo
{
public static bool operator ==(Foo first, Foo second)
{
// can't say if (first == second) here or infinite recursion...
if (ReferenceEquals(first, second))
{
// if same object, obviously same...
return true;
}
// etc.
}
}
Whats the difference between these two comparison statments?
var result = EqualityComparer<T>.Default.Equals(#this, null);
var result = #this == null;
Obviously the aim is to test whether the object '#this' isnull.
Well it depends on the type of #this. If it doesn't have an overload of ==, the second line will just perform a direct reference comparison, whereas the first line will call an overridden Equals method or an implementation of IEquatable.Equals.
Any sensible implementation will give the same result for both comparisons.
The first statement calls the Equals() method between objects to see if their values are equal, assuming it has been overriden and implemented in the class T. The second statement compares the references instead, unless the == operator has been overridden like in the String class.
operator == calls ReferenceEquals on comparing objects, so compare that objects are pointing to the same memory location.
Equals, instead, is a just virtual method, so can behave differently for different types, as it can be overriden.
For example, for CLR string Equals compares content of a string and not a reference, even if string is a reference type.
I'm used to seeing old code like
if (true)
{
...
}
where it's intuitively clear that someone was being either lazy or overly cautious when making a change. I ran across this snippet today, and I'm curious whether there's a functional difference between doing type comparison this way:
private static bool logField(Type t, string fieldname)
{
if (t.ToString() == typeof (Property).ToString())
{
...
}
return true;
}
and doing it this way:
private static bool logField(Type t, string fieldname)
{
if (t == typeof (Property))
{
...
}
return true;
}
I'd say that's generally laziness - but it may not be. For example, you could have two Property types, in the same effective file, but different copies. If typeof(Property) loads it from one file but t is loaded from a different one, your replacement would say they were different but the original code would compare say they were the same.
It's definitely an edge case, and one that you normally want to avoid in the first place... but it's just possible.
I can't think of any good reasons.
In fact, the former will throw if t is null.
The first one compares references of Strings, while the second one actually checks to see if t is of the Property type.
The first one will always be "correct" because the two strings refer to the same object, but the second one is the correct way to check if t is of the Property type.
An equivalent and more readable way to do a type check is
if (t is Property)
No, getting the type object of 2 instances of the same type will always return a reference to the same type object in memory. This means that performing a reference equality check (==) is sufficient.
Essentially, calling:
if (t.ToString() == typeof (Property).ToString())
will call ToString() twice on the same object, where t is the 'Property' type.
I'd say that the first approach was probably done by someone unfamiliar with C#, not necessary being lazy. The string comparison will work for a majority of the time, except:
If t is null it would throw a null reference exception.
It doesn't take namespaces into consideration.
I would recommend the second case, unless you fall into needing the #2 edge case.
Why use one over the other?
== is the identity test. It will return true if the two objects being tested are in fact the same object. Equals() performs an equality test, and will return true if the two objects consider themselves equal.
Identity testing is faster, so you can use it when there's no need for more expensive equality tests. For example, comparing against null or the empty string.
It's possible to overload either of these to provide different behavior -- like identity testing for Equals() --, but for the sake of anybody reading your code, please don't.
Pointed out below: some types like String or DateTime provide overloads for the == operator that give it equality semantics. So the exact behavior will depend on the types of the objects you are comparing.
See also:
http://blogs.msdn.com/csharpfaq/archive/2004/03/29/102224.aspx
#John Millikin:
Pointed out below: some value types like DateTime provide overloads for the == operator >that give it equality semantics. So the exact behavior will depend on the types of the >objects you are comparing.
To elaborate:
DateTime is implemented as a struct. All structs are children of System.ValueType.
Since System.ValueType's children live on the stack, there is no reference pointer to the heap, and thus no way to do a reference check, you must compare objects by value only.
System.ValueType overrides .Equals() and == to use a reflection based equality check, it uses reflection to compare each fields value.
Because reflection is somewhat slow, if you implement your own struct, it is important to override .Equals() and add your own value checking code, as this will be much faster. Don't just call base.Equals();
Everyone else pretty much has you covered, but I have one more word of advice. Every now and again, you will get someone who swears on his life (and those of his loved ones) that .Equals is more efficient/better/best-practice or some other dogmatic line. I can't speak to efficiency (well, OK, in certain circumstances I can), but I can speak to a big issue which will crop up: .Equals requires an object to exist. (Sounds stupid, but it throws people off.)
You can't do the following:
StringBuilder sb = null;
if (sb.Equals(null))
{
// whatever
}
It seems obvious to me, and perhaps most people, that you will get a NullReferenceException. However, proponents of .Equals forget about that little factoid. Some are even "thrown" off (sorry, couldn't resist) when they see the NullRefs start to pop up.
(And years before the DailyWTF posting, I did actually work with someone who mandated that all equality checks be .Equals instead of ==. Even proving his inaccuracy didn't help. We just made damn sure to break all his other rules so that no reference returned from a method nor property was ever null, and it worked out in the end.)
== is generally the "identity" equals meaning "object a is in fact the exact same object in memory as object b".
equals() means that the objects logically equal (say, from a business point of view). So if you are comparing instances of a user-defined class, you would generally need to use and define equals() if you want things like a Hashtable to work properly.
If you had the proverbial Person class with properties "Name" and "Address" and you wanted to use this Person as a key into a Hashtable containing more information about them, you would need to implement equals() (and hash) so that you could create an instance of a Person and use it as a key into the Hashtable to get the information.
Using == alone, your new instance would not be the same.
According to MSDN:
In C#, there are two different kinds of equality: reference equality (also known as identity) and value equality. Value equality is the generally understood meaning of equality: it means that two objects contain the same values. For example, two integers with the value of 2 have value equality. Reference equality means that there are not two objects to compare. Instead, there are two object references and both of them refer to the same object.
...
By default, the operator == tests for reference equality by determining whether two references indicate the same object.
Both Equals and == can be overloaded, so the exact results of calling one or the other will vary. Note that == is determined at compile time, so while the actual implementation could change, which == is used is fixed at compile time, unlike Equals which could use a different implementation based on the run time type of the left side.
For instance string performs an equality test for ==.
Also note that the semantics of both can be complex.
Best practice is to implement equality like this example. Note that you can simplify or exclude all of this depending on how you plan on using you class, and that structs get most of this already.
class ClassName
{
public bool Equals(ClassName other)
{
if (other == null)
{
return false;
}
else
{
//Do your equality test here.
}
}
public override bool Equals(object obj)
{
ClassName other = obj as null; //Null and non-ClassName objects will both become null
if (obj == null)
{
return false;
}
else
{
return Equals(other);
}
}
public bool operator ==(ClassName left, ClassName right)
{
if (left == null)
{
return right == null;
}
else
{
return left.Equals(right);
}
}
public bool operator !=(ClassName left, ClassName right)
{
if (left == null)
{
return right != null;
}
else
{
return !left.Equals(right);
}
}
public override int GetHashCode()
{
//Return something useful here, typically all members shifted or XORed together works
}
}
Another thing to take into consideration: the == operator may not be callable or may have different meaning if you access the object from another language. Usually, it's better to have an alternative that can be called by name.
The example is because the class DateTime implements the IEquatable interface, which implements a "type-specific method for determining equality of instances." according to MSDN.
use equals if you want to express the contents of the objects compared should be equal. use == for primitive values or if you want to check that the objects being compared is one and the same object. For objects == checks whether the address pointer of the objects is the same.
I have seen Object.ReferenceEquals() used in cases where one wants to know if two references refer to the same object
In most cases, they are the same, so you should use == for clarity. According to the Microsoft Framework Design Guidelines:
"DO ensure that Object.Equals and the equality operators have exactly the same semantics and similar performance characteristics."
https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/equality-operators
But sometimes, someone will override Object.Equals without providing equality operators. In that case, you should use Equals to test for value equality, and Object.ReferenceEquals to test for reference equality.
If you do disassemble (by dotPeek for example) of Object, so
public virtual bool Equals(Object obj)
described as:
// Returns a boolean indicating if the passed in object obj is
// Equal to this. Equality is defined as object equality for reference
// types and bitwise equality for value types using a loader trick to
// replace Equals with EqualsValue for value types).
//
So, is depend on type.
For example:
Object o1 = "vvv";
Object o2 = "vvv";
bool b = o1.Equals(o2);
o1 = 555;
o2 = 555;
b = o1.Equals(o2);
o1 = new List<int> { 1, 2, 3 };
o2 = new List<int> { 1, 2, 3 };
b = o1.Equals(o2);
First time b is true (equal performed on value types), second time b is true (equal performed on value types), third time b is false (equal performed on reference types).