Tim Coulter
Tim Coulter

Reputation: 8937

Different property values on two references to the same object (C#)

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

Answers (4)

driis
driis

Reputation: 164341

Two things that might be happening from the top of my mind:

  • Accessing Blocks or Blocks.Count might mutate state (it shouldn't, but it is possible).
  • The object might be changed on another thread between the two calls. Do you use multi-threading in the application ?

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().

Edit in response to your update

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

3Dave
3Dave

Reputation: 29071

Possibilities (some of which you have already discounted in the comments):

  1. Some external process, say something that is loading Blocks into FlowDocument, is altering the value between writes.

  2. 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.

  3. 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().

  4. 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.

  5. You have dead pixels on your screen that make the first "3" look like a "1".

  6. You live next to a nuclear reactor.

Some things to try:

  1. Run your .Assert code in a loop and see if the values stabilize.

  2. 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

Brian Rasmussen
Brian Rasmussen

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

CodeMonkey1313
CodeMonkey1313

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

Related Questions