On C# I'm having this issue as presented it the image. Does anyone knows why the Equals implementation is not giving me the expected behaviour? Wasn't supposed to return true because the value is the same?
Since FormattableString doesn't override .Equals and neither does ConcreteFormattableString which inherits from FormattableString, it reverts to Object.Equals which compares references for equality, that is why your current code returns false.
A quick fix would be to call .ToString() on both objects and use the string.Equals override as it compares the value of each string.
So you could switch your last line to this and it should produce true:
Console.WriteLine(string.Equals(x.ToString(), u.ToString()));
Documentation:
string.Equals(): https://learn.microsoft.com/en-us/dotnet/api/system.string.equals?view=netframework-4.7.2
FormattableString: https://learn.microsoft.com/en-us/dotnet/api/system.formattablestring?view=netframework-4.7.2
ConcreteFormattableString: https://weblogs.asp.net/dixin/csharp-6-0-string-interpolation-formattablestring-and-code-analysis-ca1305-specify-iformatprovider
The type of your variables are ConcreteFormattableString because of this assignment:
IFormattable x = $"string1"; // ConcreteFormattableString
var x = $"string1"; // this is regular string
And ConcreteFormattableString doesn't override Equals method, so object.Equals method is called which compares references. Since the two string have different references, you get false.
As mentioned in the comments if you want to compare contents of the strings, you can call ToString, then perform the comparison.
Related
I've made a simple test :
object t = 3;
object aa = 3;
#1 Console.WriteLine(t.Equals(aa));
#2 Console.WriteLine(t.Equals(3));
#3 Console.WriteLine(3.Equals(aa));
All of them are true.(that's my problem actually).
looking at object , this is the used function:
public virtual bool Equals(object obj);
The equals is virtual. so it can be overridden.
But I don't see any polymorphic behavior. this is just a pure boxed value.
Regarding line #1 t.Equals(aa)
The reference type is the static type - Object.
so I thought it should call Object.Equals : which means that the reference are different , meaning the first answer should be False.(and I probably wrong here). why is that?
Regarding line #2 t.Equals(3)
Again, t's static type is object. so Object.Equals is running. how come it is true ?
Regarding line #3 3.Equals(aa)
I believe it is the public override bool Equals(object obj); is running because the static type is int. and the param type is object. but why does it true ? does it un-box the value ?
it seems that something , somehow unboxes the object without my notice :-(
Objects Equals method is polymorphic, so it can be overriden by subtypes like int. Int32.Equals overrides this method to do a value comparison between the current object and its argument, and since the arguments are equal once unboxed, it returns true.
There are two overload of Int32.Equals - bool Equals(object) and bool Equals(int). The bool Equals(object) overload is the one overriden from object. Since t and aa are object references, this is the method which will be called in examples 1 and 2.
In example 3, it is still this overload which is called since aa is an object and this is therefore the only valid overload.
The == operator is static and is resolved statically based on the types of its arguments, which are both object in your example. The == operator for object compares references, and in this case will return false for two separate boxed ints.
The virtual method Object.Equals is being called, but because of the way virtual methods work, it calls the Int32.Equals method instead, which compares the int values, not the references.
Virtual methods are bound at runtime. That is, they choose the appropriate method at runtime, not at compile time. In this case, Object.Equals is what is in the compiled code, but since you're comparing ints, it chooses Int32.Equals at runtime. This is accomplished using something called v-tables (in case you wanted to read more on this).
Keep in mind that Equals is supposed to act like this, and if you really want reference equality, you can use ReferenceEquals.
Note that this doesn't have anything to do with boxing. You'll get the same behaviour with, for example, a string, or a custom class.
As you wrote in your question the following Asserts will all pass
[Test]
public void EqualityOnInts()
{
object a = 1;
object b = 1;
Assert.AreEqual(a, b);
Assert.IsTrue(1.Equals(a));
Assert.IsTrue(b.Equals(1));
}
If you instantiate a you create a new integer object with value 1. Calling the Equals method on a will result in calling the Equals method on Int32. Also, if you do a.GetType() it will returnInt32`.
Since the Equals implementation of Int32 will check if the value is equal, and does not care about a different object reference, the result will be "true".
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 am trying to compare two Lists using
CollectionAssert.AreEqual(ListExpected, ListActual);
But I am getting an exception
Expected and actual are both <System.Collections.Generic.List`1[API.Program.Relation]> with 11 elements
Values differ at index [0]
Expected: <API.Program.Relation>
But was: <API.Program.Relation>
But when I compared the zero element using Assert.AreEqual on field by field everything was fine.
Any idea why I cannot compare using CollectionAssert
An object is "declared" equal to another object in .NET is if its Equals(object other) method returns true. You need to implement that method for your API.Program.Relation class, otherwise .NET considers your objects different unless they are reference-equal. The fact that all fields are the same does not matter to .NET: if you need field-by-field equality semantics, you need to provide an implementation of Equals that supports it.
When you override Equals, don't forget to override GetHashCode as well - these must be overriden together.
If you do not want to or cannot override Equals for some reason, you could use an overload of CollectionAssert.AreEqual that takes an instance of IComparer to assist in comparing collection elements.
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.
List<tinyClass> ids = new List<tinyClass();
ids.Add(new tinyClass(1, 2));
bool b = ids.IndexOf(new tinyClass(1, 2)) >= 0; //true or false?
If it compares by value, it should return true; if by reference, it will return false.
If it compares by reference, and I make tinyClass a struct - will that make a difference?
From MSDN:
This method determines equality using the default equality comparer EqualityComparer<T>.Default for T, the type of values in the list.
The Default property checks whether type T implements the System.IEquatable<T> generic interface and if so returns an EqualityComparer<T> that uses that implementation. Otherwise it returns an EqualityComparer<T> that uses the overrides of Object.Equals and Object.GetHashCode provided by T.
It seems like it uses the Equals method, unless the stored class implements the IEquatable<T> interface.
For a class, with the default implementation of Equals - it will compare by reference.
If you change it to a tinyStruct, it will compare it by value.
It depends on the object's implementation of .Equals(..). By default for an object, the references are compared. If you did change it to a struct, then I believe it would evaluate to true based on the equality of the private members, but it would still be more programmically sound to implement IEquatable.
Be sure to implement .Equals(..) for your struct, as the default implementation may use reflection to compare each field, which is very expensive.
Read more at: http://blogs.microsoft.co.il/blogs/sasha/archive/2007/08.aspx
It also may be related to which of the class or struct instance is kept in the list, because of structs' equal implementation is based on values' equality.