-
Notifications
You must be signed in to change notification settings - Fork 4.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Equals/GetHashCode for UnixDomainSocketEndPoint #69722
Conversation
Tagging subscribers to this area: @dotnet/ncl |
src/libraries/System.Net.Sockets/src/System/Net/Sockets/UnixDomainSocketEndPoint.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Net.Sockets/src/System/Net/Sockets/UnixDomainSocketEndPoint.cs
Outdated
Show resolved
Hide resolved
I am not entirely sold on having Equals mutate internal state, but in this case seems harmless. Otherwise looks good, but I'd rather somebody else take a look as well, perhaps @antonfirsov? |
@rzikm agree, but the allocation is effectively reused. So, during the app lifecycle, the amount of allocated memory remains the same. |
@@ -10,13 +11,24 @@ namespace System.Net.Sockets | |||
/// <summary>Represents a Unix Domain Socket endpoint as a path.</summary> | |||
public sealed partial class UnixDomainSocketEndPoint : EndPoint | |||
{ | |||
// taken from System.IO.PathInternal |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While this may be copy this is only best guess. Aside from Windows, the case (in)sensitivity is property of the file system e.g. while apfs is case insensitive by default, you can have case sensitive version as well. Similarly on Linux, ext2fs is case sensitive but you can have different filesystems (like vfat) that are not.
// Otherwise, two endpoints may not be equal even if they pointing to the same file. | ||
// Lazily initialized field then can be reused by these methods to avoid further | ||
// allocations. | ||
private string? _fullPath; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is somewhat surprising that GetHash or equality would need new state.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not actually new, the value of this field is used for two purposes. One of them is Equals/GetHashCode, yes. Otherwise, two paths pointing to the same location in fs will give different hash codes for EndPoint.
However, we can assume that relative paths pointing to the same location give us different EndPoints. If so, I can change the behavior.
Imo The |
I'm worried about all the semantics being baked into equality here, attempting to say that the type's equality is based on the underlying OS behavior. Can we just give the instance basic value equality, e.g. |
I see no problem with such an approach. However, we can be still more accurate and try to normalize relative paths. However, without #2162 I can't do that. Another thing - path comparison must take into account case sensitivity, IMO. P.S.: Interesting observation, but |
I'm suggesting it not. I'm suggesting Equals/GetHashCode here be agnostic to OS path equivalence, which is entirely up to the operating system and can be significantly influenced by case-sensitivity per folder, by symlinks, etc. I'm suggesting Equals/GetHashCode be based entirely on the state passed in, i.e. a UnixDomainSocketEndPoint is equivalent to another if and only if its string path is Equal (ordinal case-sensitive), and nothing more. If someone wants more complicated semantics, they can use a custom comparer. If such semantics make Equals/GetHashCode overrides undesirable, then we shouldn't override them. |
src/libraries/System.Net.Sockets/src/System/Net/Sockets/UnixDomainSocketEndPoint.cs
Outdated
Show resolved
Hide resolved
There seem to be test failures ( If the functionality is not supported on Windows, you can simply annotate the tests with |
@rzikm , sure. I'm using Linux, didn't see that error. |
Assert.NotEqual(endPoint1, endPoint3); | ||
Assert.NotEqual(endPoint2, endPoint3); | ||
Assert.NotEqual(endPoint1.GetHashCode(), endPoint3.GetHashCode()); | ||
Assert.NotEqual(endPoint2.GetHashCode(), endPoint3.GetHashCode()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These hashcode NotEqual asserts could sporadically fail. It should be exceedingly rare, but better to remove them. We could instead assert that the endpoint hashcode equals the path hashcode, and leave the correctness of the path hashcode up to string's implementation.
Same for the test below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because of hash code collision.. hmm, makes sense. I would prefer just to remove NotEqual
assertions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks.
Thanks for having the patience with this. |
Fixed #69488