Reputation: 8937
I am trying to track down a very elusive bug in an application that manipulates a FlowDocument
. I have shown below three consecutive lines of debugging code, together with their output:
Debug.Assert(ReferenceEquals(document1, document2));
Debug.WriteLine(document1.Blocks.Count); // 1
Debug.WriteLine(document2.Blocks.Count); // 3
Can anyone help me to understand how two references to the same object can have different values for a given property? Or am I missing something about the way ReferenceEquals
works?
Thanks,
Tim
Edit:
If I change the assertion to an if
block, the debugging code never runs ...
if (ReferenceEquals(document1, document2))
{
Debug.WriteLine(document1.Blocks.Count);
Debug.WriteLine(document2.Blocks.Count);
}
... which makes me feel utterly stupid, because the ReferenceEquals
test is clearly working, but I don't understand why the assertion is not working.
Upvotes: 4
Views: 276
Reputation: 164341
Two things that might be happening from the top of my mind:
Also, if the references are of different types (ie. document2 is of an inherited type), the property might be overloaded to return something different. You could check to see whether document1.GetType() == document2.GetType()
.
Debug.Assert will only ever run, if the assembly is compiled in Debug mode. If you are running Release, it will not be run. This is because Debug.Assert is decorated with the [Conditional("DEBUG")]
attribute.
It seems that the issue is the fact that you indeed have 2 different objects.
Upvotes: 4
Reputation: 29071
Possibilities (some of which you have already discounted in the comments):
Some external process, say something that is loading Blocks into FlowDocument, is altering the value between writes.
Heisenberg: reading the Blocks property affects it. This happens sometimes when reading rows from a data source. I'm not familiar with FlowDocument
so I'm not sure how feasible this is.
If the instances were declared as different types, their references would still be equal, but the value of Blocks (or Blocks.Count) could be overridden, resulting in different return values since different code might be called - like Object.ToString() vs Int.ToString().
You're somehow calling this debug code in the middle of a loop. This could happen if you're running it in the command window or some attached debugger instead of within the application.
You have dead pixels on your screen that make the first "3" look like a "1".
You live next to a nuclear reactor.
Some things to try:
Run your .Assert code in a loop and see if the values stabilize.
Set a read/write breakpoint on the Blocks value. (I know you can do this in C, but haven't tried it in C#)
Update
Regarding your additional question about .Assert() not working as expected:
Just looked at this note on MSDN regarding Debug.Assert().
By default, the Debug.Assert method works only in debug builds. Use the Trace.Assert method if you want to do assertions in release builds. For more information, see Assertions in Managed Code.
Are you running a debug build or a release build?
Upvotes: 1
Reputation: 116481
If a property has side effects it can yield different results each time you call it. E.g. DateTime.Now does not always equal DateTime.Now.
Without knowing anything more about the code, that would be my guess.
EDIT: Using Reflector on FlowDocument shows that Blocks return a new instance each time it is called. Additionally, the Count property BlockCollection is rather elaborate, so I would take a closer look at that. Unfortunately I don't know the involved types very well, so I can't immediately tell you what is wrong.
Upvotes: 2
Reputation: 16031
Are you certain that the Blocks object reference points to the same object? Try a
Debug.Assert(ReferenceEquals(document1.Blocks, document2.Blocks));
and see if that succeeds.
Upvotes: 1