-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
[System.Net] Introduce CIDR IPNetwork #82779
Conversation
Tagging subscribers to this area: @dotnet/ncl Issue Detailsnull
|
src/libraries/System.Net.Primitives/src/System/Net/IPNetwork.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Net.Primitives/src/System/Net/IPNetwork.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Net.Primitives/src/System/Net/IPNetwork.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Net.Primitives/src/System/Net/IPNetwork.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Net.Primitives/src/System/Net/IPNetwork.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Net.Primitives/src/System/Net/IPNetwork.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Net.Primitives/src/System/Net/IPNetwork.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Net.Primitives/src/System/Net/IPNetwork.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Net.Primitives/src/System/Net/IPNetwork.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Net.Primitives/src/System/Net/IPNetwork.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Net.Primitives/src/System/Net/IPNetwork.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Net.Primitives/src/System/Net/IPNetwork.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Net.Primitives/src/System/Net/IPNetwork.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Net.Primitives/src/System/Net/IPNetwork.cs
Outdated
Show resolved
Hide resolved
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.
Some comments regarding validation, more to come.
You also need to generate reference source: https://github.com/dotnet/runtime/blob/main/docs/coding-guidelines/updating-ref-source.md#for-most-assemblies-within-libraries
(I can do it for you if you want.)
src/libraries/System.Net.Primitives/src/System/Net/IPNetwork.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Net.Primitives/src/System/Net/IPNetwork.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Net.Primitives/src/System/Net/IPNetwork.cs
Outdated
Show resolved
Hide resolved
@antonfirsov I was actually having a problem with this one, even tests were not able to see IPNetwork😅 Thanks! |
/azp run runtime-extra-platforms |
Azure Pipelines successfully started running 1 pipeline(s). |
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.
@dotnet/ncl this is ready for review now. Since I changed most of the original implementation, it would need an approval from someone else.
Downlevel packaging will be implemented in a separate PR.
src/libraries/System.Net.Primitives/src/System/Net/IPNetwork.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Net.Primitives/src/System/Net/IPNetwork.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Net.Primitives/src/System/Net/IPNetwork.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Net.Primitives/src/System/Net/IPNetwork.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Net.Primitives/src/System/Net/IPNetwork.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Net.Primitives/src/System/Net/IPNetwork.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Net.Primitives/src/System/Net/IPNetwork.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Net.Primitives/src/System/Net/IPNetwork.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Net.Primitives/src/System/Net/IPNetwork.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Net.Primitives/src/System/Net/IPNetwork.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Net.Primitives/src/System/Net/IPNetwork.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Net.Primitives/src/System/Net/IPNetwork.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Net.Primitives/src/System/Net/IPNetwork.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Net.Primitives/src/System/Net/IPNetwork.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Net.Primitives/src/System/Net/IPNetwork.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Net.Primitives/src/System/Net/IPNetwork.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Net.Primitives/src/System/Net/IPNetwork.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Net.Primitives/src/System/Net/IPNetwork.cs
Outdated
Show resolved
Hide resolved
/// <returns>The <see cref="string"/> containing the <see cref="IPNetwork"/>'s CIDR notation.</returns> | ||
public override string ToString() | ||
{ | ||
return $"{BaseAddress}/{PrefixLength}"; |
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.
Is what this renders for default(IPNetwork).ToString()
desirable? Seems like here and below we should special-case BaseAddress == null to be the same as BaseAddress == IPAddress.Any.
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 big fan of making default(IPNetwork)
equivalent to another arbitrary state. Encountering such instances is a sign of a programming error in most of the cases. Would it be very unconventional if ToString()
returned something like <uninitialized>
instead?
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.
IPAddress.Any
Note that it could be also IPAddress.IPv6Any
.
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 big fan of making default(IPNetwork) equivalent to another arbitrary state.
I think we need to make default(IPNetwork)
valid. If you were forced to add a new IPNetwork()
constructor, what would its behavior be? What would an IPNetwork.Empty
do? Etc. Whatever that is, I think we should make default(IPNetwork)
behave equivalently. Having the default value of a struct randomly fail is an anti-pattern. We typically only do it on our structs not meant to be used directly, e.g. helper types used by a compiler or other tools.
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.
If you were forced to add a
new IPNetwork()
constructor, what would its behavior be? What would anIPNetwork.Empty
do?
One can argue that default(IPNetwork)
is an empty network that doesn't contain any IPAddress
, however note that it's not possible to define such an instance with an IP/prefix-length pair.
Having the default value of a struct randomly fail is an anti-pattern.
I have got rid of the exceptions, so the current PR behavior of default(IPNetwork)
is what I just described above ("empty network"). The methods don't fail anymore, we just don't pretend that there is a CIDR pair when none was defined.
Personally I find this to be a good compromise, but if you think it is not acceptable, and we should assign an IPAddress
to the BaseAddress == null
case, I don't think it would be a consistent behavior to special-case it only only in method implementations, we should rather do something like:
public readonly struct IPNetwork
{
private readonly IPAddress _address;
public IPAddress BaseAddress => _address ?? IPAddress.Any;
}
but I personally find this worse because IPAddress.Any
is an arbitrary choice.
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.
default(IPNetwork) is all zeros. Imagine IPAddress were a struct rather than a class. What would its all zero's value be? That's IPAddress.Any. Hence why I was suggesting it behave like IPAddress.Any + PrefixLength==0.
I do think you should make BaseAddress
return something if the address is null. Otherwise, the nullable annotations are wrong: it's advertising it will always return something non-nullable, but it might return null. Alternatively, you could make the property be public IPAddress? BaseAddress { get; }
.
And then Contains would also need to be tweaked, either making it return true rather than false if the address is null, or if we make it so that BaseAddress is never null (my preference), just using whatever it is and computing the answer based on that without any special-casing.
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.
That's IPAddress.Any
Or IPAddress.IPv6Any
, depends on the implementation. I don't think this case is similar to eg. default(Memory<T>)
. Using default(IPNetwork)
is a programming bug in 99% of the cases. As a user, I would expect a sw library to help detecting it and "fail fast" instead of hiding it with some arbitrary "correct" behavior. But based on your feedback, I assume this is not our preference with BCL structs. I wish we had design guidelines covering such details.
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.
I wish we had design guidelines covering such details.
We do. They say such values should work.
cc: @bartonjs
Co-authored-by: Miha Zupan <[email protected]> Co-authored-by: Stephen Toub <[email protected]>
/azp run runtime-extra-platforms |
Azure Pipelines successfully started running 1 pipeline(s). |
All feedback has been addressed, and all CI failures are unrelated. Will merge this if there are no further suggestions. |
PR for a type created based on #79946