@@ -24,12 +24,38 @@ public class IPAddress
2424 /// <summary>
2525 /// Provides an IP address that indicates that the server must listen for client activity on all network interfaces. This field is read-only.
2626 /// </summary>
27- public static readonly IPAddress Any = new ( 0x0000000000000000 ) ;
27+ /// <remarks>
28+ /// The <see cref="Socket.Bind"/> method uses the <see cref="Any"/> field to indicate that a <see cref="Socket"/> instance must listen for client activity on all network interfaces.
29+ ///
30+ /// The <see cref="Any"/> field is equivalent to 0.0.0.0 in dotted-quad notation.
31+ /// </remarks>
32+ public static readonly IPAddress Any = new ( new byte [ ] { 0 , 0 , 0 , 0 } ) ;
2833
2934 /// <summary>
3035 /// Provides the IP loopback address. This field is read-only.
3136 /// </summary>
32- public static readonly IPAddress Loopback = new ( 0x000000000100007F ) ;
37+ /// <remarks>
38+ /// The <see cref="Loopback"/> field is equivalent to 127.0.0.1 in dotted-quad notation.
39+ /// </remarks>
40+ public static readonly IPAddress Loopback = new ( new byte [ ] { 127 , 0 , 0 , 1 } ) ;
41+
42+ /// <summary>
43+ /// Provides the IP broadcast address. This field is read-only.
44+ /// </summary>
45+ /// <remarks>
46+ /// The <see cref="Broadcast"/> field is equivalent to 255.255.255.255 in dotted-quad notation.
47+ /// </remarks>
48+ public static readonly IPAddress Broadcast = new ( new byte [ ] { 255 , 255 , 255 , 255 } ) ;
49+
50+ /// <summary>
51+ /// Provides an IP address that indicates that no network interface should be used. This field is read-only.
52+ /// </summary>
53+ /// <remarks>
54+ /// The <see cref="Socket.Bind"/> uses the <see cref="None"/> field to indicate that a <see cref="Socket"/> must not listen for client activity.
55+ ///
56+ /// The <see cref="None"/> field is equivalent to 255.255.255.255 in dotted-quad notation.
57+ /// </remarks>
58+ public static readonly IPAddress None = Broadcast ;
3359
3460 internal readonly long Address ;
3561
@@ -136,6 +162,22 @@ public IPAddress(byte[] address)
136162 }
137163 }
138164
165+ /// <summary>
166+ /// Indicates whether two <see cref="IPAddress"/> objects are equal.
167+ /// </summary>
168+ /// <param name="a">The <see cref="IPAddress"/> to compare with <paramref name="b"/>.</param>
169+ /// <param name="b">The <see cref="IPAddress"/> to compare with <paramref name="a"/>.</param>
170+ /// <returns><see langword="true"/> if <paramref name="b"/> is equal to <paramref name="a"/>; otherwise, <see langword="false"/>.</returns>
171+ public static bool operator == ( IPAddress a , IPAddress b ) => a is not null && a . Equals ( b ) ;
172+
173+ /// <summary>
174+ /// Indicates whether two <see cref="IPAddress"/> objects are not equal.
175+ /// </summary>
176+ /// <param name="a">The <see cref="IPAddress"/> to compare with <paramref name="b"/>.</param>
177+ /// <param name="b">The <see cref="IPAddress"/> to compare with <paramref name="a"/>.</param>
178+ /// <returns><see langword="true"/> if <paramref name="b"/> is not equal to <paramref name="a"/>; otherwise, <see langword="false"/>.</returns>
179+ public static bool operator != ( IPAddress a , IPAddress b ) => ! ( a == b ) ;
180+
139181 /// <summary>
140182 /// Initializes a new instance of a IPV6 <see cref="IPAddress"/> class with the address specified as a Byte array.
141183 /// </summary>
@@ -173,45 +215,59 @@ private IPAddress(ushort[] address, uint scopeid)
173215 /// <summary>
174216 /// Compares two IP addresses.
175217 /// </summary>
176- /// <param name="obj ">An <see cref="IPAddress"/> instance to compare to the current instance.</param>
177- /// <returns></returns>
178- public override bool Equals ( object obj )
218+ /// <param name="other ">An <see cref="IPAddress"/> instance to compare to the current instance.</param>
219+ /// <returns><see langword="true"/> if the two addresses are equal; otherwise, <see langword="false"/>.< /returns>
220+ public override bool Equals ( object other )
179221 {
180- IPAddress addr = obj as IPAddress ;
222+ return other is IPAddress ipAddress && Equals ( ipAddress ) ;
223+ }
181224
182- if ( obj == null ) return false ;
225+ /// <summary>
226+ /// Compares two IP addresses.
227+ /// </summary>
228+ /// <param name="other">An <see cref="IPAddress"/> instance to compare to the current instance.</param>
229+ /// <returns><see langword="true"/> if the two addresses are equal; otherwise, <see langword="false"/>.</returns>
230+ public bool Equals ( IPAddress other )
231+ {
232+ if ( other is null )
233+ {
234+ return false ;
235+ }
236+
237+ // Compare families before address representations
238+ if ( AddressFamily != other . AddressFamily )
239+ {
240+ return false ;
241+ }
183242
184243 // Compare family before address
185- if ( _family != addr . AddressFamily )
244+ if ( _family != other . AddressFamily )
186245 {
187246 return false ;
188247 }
189248
190249 if ( _family == AddressFamily . InterNetworkV6 )
191250 {
192251 // For IPv6 addresses, compare the full 128bit address
193- for ( int i = 0 ; i < NumberOfLabels ; i ++ )
252+ for ( var i = 0 ; i < NumberOfLabels ; i ++ )
194253 {
195- if ( addr . _numbers [ i ] != this . _numbers [ i ] )
254+ if ( other . _numbers [ i ] != _numbers [ i ] )
196255 return false ;
197256 }
198257
199258 // Also scope must match
200- if ( addr . _scopeid == this . _scopeid )
201- return true ;
202-
203- return false ;
259+ return other . _scopeid == _scopeid ;
204260 }
205261 else
206262 {
207- return this . Address == addr . Address ;
263+ return Address == other . Address ;
208264 }
209265 }
210266
211267 /// <summary>
212- /// Provides a copy of the <see cref="IPAddress"/> as an array of bytes.
268+ /// Provides a copy of the <see cref="IPAddress"/> as an array of bytes in network order .
213269 /// </summary>
214- /// <returns>A Byte array.</returns>
270+ /// <returns>A <see langword="byte"/> array.</returns>
215271 public byte [ ] GetAddressBytes ( )
216272 {
217273 byte [ ] bytes ;
@@ -223,8 +279,8 @@ public byte[] GetAddressBytes()
223279 int j = 0 ;
224280 for ( int i = 0 ; i < NumberOfLabels ; i ++ )
225281 {
226- bytes [ j ++ ] = ( byte ) ( ( this . _numbers [ i ] >> 8 ) & 0xFF ) ;
227- bytes [ j ++ ] = ( byte ) ( ( this . _numbers [ i ] ) & 0xFF ) ;
282+ bytes [ j ++ ] = ( byte ) ( ( _numbers [ i ] >> 8 ) & 0xFF ) ;
283+ bytes [ j ++ ] = ( byte ) ( ( _numbers [ i ] ) & 0xFF ) ;
228284 }
229285 return bytes ;
230286 }
@@ -341,11 +397,9 @@ public override int GetHashCode()
341397 {
342398 return ToString ( ) . GetHashCode ( ) ;
343399 }
344- else
345- {
346- // For IPv4 addresses, we can simply use the integer representation.
347- return unchecked ( ( int ) Address ) ;
348- }
400+
401+ // For IPv4 addresses, we can simply use the integer representation.
402+ return unchecked ( ( int ) Address ) ;
349403 }
350404
351405 // For security, we need to be able to take an IPAddress and make a copy that's immutable and not derived.
@@ -410,7 +464,7 @@ public IPAddress MapToIPv6()
410464 return this ;
411465 }
412466
413- ushort [ ] labels = new ushort [ IPAddress . NumberOfLabels ] ;
467+ ushort [ ] labels = new ushort [ NumberOfLabels ] ;
414468 labels [ 5 ] = 0xFFFF ;
415469 labels [ 6 ] = ( ushort ) ( ( ( Address & 0x0000FF00 ) >> 8 ) | ( ( Address & 0x000000FF ) << 8 ) ) ;
416470 labels [ 7 ] = ( ushort ) ( ( ( Address & 0xFF000000 ) >> 24 ) | ( ( Address & 0x00FF0000 ) >> 8 ) ) ;
0 commit comments