My value may not equal my value
- November 2nd, 2010
- Av Fredrik Mörk
- Kommentera
I saw a question at StackOverflow that, amongst other things, asked if it could ever be that a.ReferenceEquals(b) is true, while at the same time a.SomeProperty != b.SomeProperty. The spontaneous answer to that is probably “no, if they refer to the same instance, they also refer to the same data” and, I would argue, in most practical cases that answer would (and should) also be true. But there are situations when this could happen.
Imagine that we have a type with a property that has value that changes over time, and where it also takes a small amount of time to produce the value:
class Foo
{
public long SomeValue
{
get
{
// simulate that it takes a short while
// to get the info
Thread.Sleep(10);
return DateTime.Now.Ticks;
}
}
}
Then consider the following program:
class Program
{
static void Main()
{
Foo a = new Foo();
Foo b = a;
Console.WriteLine("object.ReferenceEquals(a, b) => {0}",
object.ReferenceEquals(a, b));
Console.WriteLine("a.SomeValue == b.SomeValue => {0}",
a.SomeValue == b.SomeValue);
}
}
What do you think it prints?
The answer is:
object.ReferenceEquals(a, b) => True a.SomeValue == b.SomeValue => False
The reason is obviously that the property getter is called twice on the same instance, but returns a different value each time. So, when a property returns a value that is produced in the getter, there is a possiblity to create scenarios where two variables may reference the same instance, but where comparing the values from the same property may still return
false.
This is not very strange really, but many programmers (myself included) might find such behavior confusing, and I would use that as an argument that property access should always be extremely cheap,
preferably just reading the value from a field. If there is work required to produce the value, and especially if the value may differ between calls, it should be a method instead.
