1

I have an object model, based on TCP Connections, which belong to Connections, which belong to Managers. It seems like two TCP Connections are different, which I can see, but when I try to see the same for the Connections they belong to, I get error message CS0211: Cannot take the address of the given expression. Do anybody know why and how I can handle this?

Watch window content for both TCP Connections:

&connectionManager.Connection.TcpConnection  0x00007fe80035f670
&Connection_For_Message.TcpConnection        0x00007fe70042bf08

=> both TCPConnections are in another memory address, so they are clearly different (although all their values, properties and attributes are equal).

When asking the same for the Connections, this does not work:

&connectionManager.Connection  error CS0211: Cannot take the address of the given expression    
&Connection_For_Message        0x00007fe700375230

Why is that?

For your information: when I ask for connectionManager.Connection (not the address, just the data), everything is ok.

Thanks in advance

Dominique
  • 16,450
  • 15
  • 56
  • 112
  • Do you really want to know the memory addresses or do you just want to evaluate if the two are the same object or not? In the latter case, the answers here might be of help: https://stackoverflow.com/questions/4251450/uniquely-identifying-reference-types-in-the-debugger – Klaus Gütter Dec 22 '22 at 14:02
  • @KlausGütter: I would like to be sure they are equal and for that I thought comparing their memory addresses was a good idea (otherwise I might doubt about the quality of the equality operator). – Dominique Dec 22 '22 at 14:05
  • 3
    But `Object.ReferenceEquals(obj1, obj2)` would work – Klaus Gütter Dec 22 '22 at 14:20
  • @KlausGütter: sorry, but `Object.ReferenceEquals(obj1, obj2)` only works when both are available at the same time. I'm dealing with an object, and later on I'm again dealing with an object, which **should** be the same, but I'm quite sure it isn't. In C++ this is easy: just compare their memory address. How can this be done in C#? – Dominique Jan 19 '23 at 15:13
  • I had a look at that other post, but I don't get it: I create an object (one in a list), I click on "Make object ID", and at the creation of the next object, I put `1#` in the watch-window. I get the error message "error CS2043: 'id#' syntax is no longer supported. Use '$id' instead.", and when I put `$id` I get `error CS0103: The name '$id' does not exist in the current context`. Do you know what to do? – Dominique Jan 19 '23 at 15:21
  • in older versions of the debugger, the format was `id#`, where in this case, `id === 1`. in the newer debugger, the format is `$id`, or, `$1` – Claies Jan 19 '23 at 15:31
  • What is the type of `connectionManager`? Could `Connection` be a property that _returns_ an object, and not necessarily an object itself? – D Stanley Jan 19 '23 at 15:35
  • 1
    `ReferenceEquals` is the canocical way to determine if two references point to the same object. `Equals` is the canonical way to tell if two objects are "equal", which might mean they are the same object, or they have the same values (depending on the definition of `Equals`. IF you have a specific use case where `ReferenceEquals` does not work the way you want, then describe that in more detail, otherwise it just looks like you're trying to reinvent the wheel – D Stanley Jan 19 '23 at 15:37
  • 1
    If you can store the memory address to compare later, then you can store a reference (in an`object` variable) to compare later. Also I don't think you can assume that an object is in the same location in memory throughout it's life (but I may be wrong). – D Stanley Jan 19 '23 at 15:39
  • @DStanley: the `Connection` is defined in the `ConnectionManager` as follows: `public TConnection Connection { get; set; }` where `TConnection` is the class of `Connection`. I don't worry about chaning values of properties of a`TcpConnection` object: I'm closing the socket inside a `TcpConnection` and later on that socket seems not to be closed. I would like to be sure that I'm dealing with the same `TcpConnection` (if ever those are different, then it's obvious that one socket is open while the other is closed. However, if it's one and the same object then something else is happening. – Dominique Jan 19 '23 at 15:51
  • I believe I have a solution: I run my application and make a model ID on one object (this becomes `$1`). Later on I do the same on the other object (of which I want to verify if it's equal to that first one) and I also make a model ID (this becomes `$2`). In the immediate window, I type `? Object.ReferenceEquals($1, $2)`. If I get `true`, both are equal. If I get `false`, both are different. Can anybody confirm this is correct and in case yes, write this as an answer (preferably with a official reference)? I'll accept it and reward the bounty. – Dominique Jan 19 '23 at 15:58
  • @Dominique That's not usually required. If the second instance is actually the same object, it already is `$1` and the debugger shows that. The debugger will always show the ID next to the value. Or the other way round, if two objects are marked as `$1` and `$2`, they are certainly _not_ equal. – PMF Jan 21 '23 at 20:47

1 Answers1

2

Retrieving an object address in different parts of the code may be misleading because objects can be moved if GC runs in the middle. The simplest way to go is to check the object's Hash Code by calling GetHashCode() method. If you get different numbers, two objects are guaranteed to be different. But equal Hash Codes don't 100% mean that two references point to the same object. In that case, you can use a temporary hack and store the first object in public static variable, then, when the code reaches the second object, use Object.ReferenceEquals(obj1, obj2) as suggested by @KlausGütter in comments.

Artur
  • 4,595
  • 25
  • 38
  • "If you get different numbers, two objects are guaranteed to be different." Except when they're not. `GetHashCode()` is a virtual method that can be overridden to produce any number you feel like. I've seen at least one implementation that returns a different code every time. It's *supposed* to produce consistent values but there's no enforcement of this. – Corey Jan 22 '23 at 05:34