@@ -17,7 +17,7 @@ namespace System
17
17
{
18
18
[ Serializable ]
19
19
[ System . Runtime . CompilerServices . TypeForwardedFrom ( "System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" ) ]
20
- public partial class Uri : ISpanFormattable , ISerializable
20
+ public partial class Uri : ISpanFormattable , IEquatable < Uri > , ISerializable
21
21
{
22
22
public static readonly string UriSchemeFile = UriParser . FileUri . SchemeName ;
23
23
public static readonly string UriSchemeFtp = UriParser . FtpUri . SchemeName ;
@@ -1674,20 +1674,6 @@ string IFormattable.ToString(string? format, IFormatProvider? formatProvider) =>
1674
1674
return ! uri1 . Equals ( uri2 ) ;
1675
1675
}
1676
1676
1677
- //
1678
- // Equals
1679
- //
1680
- // Overrides default function (in Object class)
1681
- //
1682
- // Assumes:
1683
- // <comparand> is an object of class Uri or String
1684
- //
1685
- // Returns:
1686
- // true if objects have the same value, else false
1687
- //
1688
- // Throws:
1689
- // Nothing
1690
- //
1691
1677
public override bool Equals ( [ NotNullWhen ( true ) ] object ? comparand )
1692
1678
{
1693
1679
if ( comparand is null )
@@ -1700,12 +1686,12 @@ public override bool Equals([NotNullWhen(true)] object? comparand)
1700
1686
return true ;
1701
1687
}
1702
1688
1703
- Uri ? obj = comparand as Uri ;
1689
+ Uri ? other = comparand as Uri ;
1704
1690
1705
1691
// we allow comparisons of Uri and String objects only. If a string
1706
1692
// is passed, convert to Uri. This is inefficient, but allows us to
1707
1693
// canonicalize the comparand, making comparison possible
1708
- if ( obj is null )
1694
+ if ( other is null )
1709
1695
{
1710
1696
if ( DisablePathAndQueryCanonicalization )
1711
1697
return false ;
@@ -1716,28 +1702,48 @@ public override bool Equals([NotNullWhen(true)] object? comparand)
1716
1702
if ( ReferenceEquals ( s , OriginalString ) )
1717
1703
return true ;
1718
1704
1719
- if ( ! TryCreate ( s , UriKind . RelativeOrAbsolute , out obj ) )
1705
+ if ( ! TryCreate ( s , UriKind . RelativeOrAbsolute , out other ) )
1720
1706
return false ;
1721
1707
}
1722
1708
1723
- if ( DisablePathAndQueryCanonicalization != obj . DisablePathAndQueryCanonicalization )
1709
+ return Equals ( other ) ;
1710
+ }
1711
+
1712
+ /// <summary>
1713
+ /// Compares two <see cref="Uri"/> instances for equality.
1714
+ /// </summary>
1715
+ /// <param name="other">The <see cref="Uri"/> to compare to this instance.</param>
1716
+ /// <returns><see langword="true"/> if the two instances represent the same URI; otherwise, <see langword="false"/>.</returns>
1717
+ public bool Equals ( [ NotNullWhen ( true ) ] Uri ? other )
1718
+ {
1719
+ if ( other is null )
1720
+ {
1721
+ return false ;
1722
+ }
1723
+
1724
+ if ( ReferenceEquals ( this , other ) )
1725
+ {
1726
+ return true ;
1727
+ }
1728
+
1729
+ if ( DisablePathAndQueryCanonicalization != other . DisablePathAndQueryCanonicalization )
1724
1730
return false ;
1725
1731
1726
- if ( ReferenceEquals ( OriginalString , obj . OriginalString ) )
1732
+ if ( ReferenceEquals ( OriginalString , other . OriginalString ) )
1727
1733
{
1728
1734
return true ;
1729
1735
}
1730
1736
1731
- if ( IsAbsoluteUri != obj . IsAbsoluteUri )
1737
+ if ( IsAbsoluteUri != other . IsAbsoluteUri )
1732
1738
return false ;
1733
1739
1734
1740
if ( IsNotAbsoluteUri )
1735
- return OriginalString . Equals ( obj . OriginalString ) ;
1741
+ return OriginalString . Equals ( other . OriginalString ) ;
1736
1742
1737
- if ( NotAny ( Flags . AllUriInfoSet ) || obj . NotAny ( Flags . AllUriInfoSet ) )
1743
+ if ( NotAny ( Flags . AllUriInfoSet ) || other . NotAny ( Flags . AllUriInfoSet ) )
1738
1744
{
1739
1745
// Try raw compare for _strings as the last chance to keep the working set small
1740
- if ( string . Equals ( _string , obj . _string , IsUncOrDosPath ? StringComparison . OrdinalIgnoreCase : StringComparison . Ordinal ) )
1746
+ if ( string . Equals ( _string , other . _string , IsUncOrDosPath ? StringComparison . OrdinalIgnoreCase : StringComparison . Ordinal ) )
1741
1747
{
1742
1748
return true ;
1743
1749
}
@@ -1746,20 +1752,20 @@ public override bool Equals([NotNullWhen(true)] object? comparand)
1746
1752
// Note that equality test will bring the working set of both
1747
1753
// objects up to creation of _info.MoreInfo member
1748
1754
EnsureUriInfo ( ) ;
1749
- obj . EnsureUriInfo ( ) ;
1755
+ other . EnsureUriInfo ( ) ;
1750
1756
1751
- if ( ! UserDrivenParsing && ! obj . UserDrivenParsing && Syntax ! . IsSimple && obj . Syntax . IsSimple )
1757
+ if ( ! UserDrivenParsing && ! other . UserDrivenParsing && Syntax ! . IsSimple && other . Syntax . IsSimple )
1752
1758
{
1753
1759
// Optimization of canonical DNS names by avoiding host string creation.
1754
1760
// Note there could be explicit ports specified that would invalidate path offsets
1755
- if ( InFact ( Flags . CanonicalDnsHost ) && obj . InFact ( Flags . CanonicalDnsHost ) )
1761
+ if ( InFact ( Flags . CanonicalDnsHost ) && other . InFact ( Flags . CanonicalDnsHost ) )
1756
1762
{
1757
1763
int i1 = _info . Offset . Host ;
1758
1764
int end1 = _info . Offset . Path ;
1759
1765
1760
- int i2 = obj . _info . Offset . Host ;
1761
- int end2 = obj . _info . Offset . Path ;
1762
- string str = obj . _string ;
1766
+ int i2 = other . _info . Offset . Host ;
1767
+ int end2 = other . _info . Offset . Path ;
1768
+ string str = other . _string ;
1763
1769
//Taking the shortest part
1764
1770
if ( end1 - i1 > end2 - i2 )
1765
1771
{
@@ -1794,14 +1800,14 @@ public override bool Equals([NotNullWhen(true)] object? comparand)
1794
1800
else
1795
1801
{
1796
1802
EnsureHostString ( false ) ;
1797
- obj . EnsureHostString ( false ) ;
1798
- if ( ! _info . Host ! . Equals ( obj . _info . Host ) )
1803
+ other . EnsureHostString ( false ) ;
1804
+ if ( ! _info . Host ! . Equals ( other . _info . Host ) )
1799
1805
{
1800
1806
return false ;
1801
1807
}
1802
1808
}
1803
1809
1804
- if ( Port != obj . Port )
1810
+ if ( Port != other . Port )
1805
1811
{
1806
1812
return false ;
1807
1813
}
@@ -1811,21 +1817,21 @@ public override bool Equals([NotNullWhen(true)] object? comparand)
1811
1817
// We should consider reducing the overall working set by not caching some other properties mentioned in MoreInfo
1812
1818
1813
1819
MoreInfo selfInfo = _info . MoreInfo ;
1814
- MoreInfo otherInfo = obj . _info . MoreInfo ;
1820
+ MoreInfo otherInfo = other . _info . MoreInfo ;
1815
1821
1816
1822
// Fragment AND UserInfo (for non-mailto URIs) are ignored
1817
1823
UriComponents components = UriComponents . HttpRequestUrl ;
1818
1824
1819
1825
if ( _syntax . InFact ( UriSyntaxFlags . MailToLikeUri ) )
1820
1826
{
1821
- if ( ! obj . _syntax . InFact ( UriSyntaxFlags . MailToLikeUri ) )
1827
+ if ( ! other . _syntax . InFact ( UriSyntaxFlags . MailToLikeUri ) )
1822
1828
return false ;
1823
1829
1824
1830
components |= UriComponents . UserInfo ;
1825
1831
}
1826
1832
1827
1833
string selfUrl = selfInfo . RemoteUrl ??= GetParts ( components , UriFormat . SafeUnescaped ) ;
1828
- string otherUrl = otherInfo . RemoteUrl ??= obj . GetParts ( components , UriFormat . SafeUnescaped ) ;
1834
+ string otherUrl = otherInfo . RemoteUrl ??= other . GetParts ( components , UriFormat . SafeUnescaped ) ;
1829
1835
1830
1836
// if IsUncOrDosPath is true then we ignore case in the path comparison
1831
1837
return string . Equals ( selfUrl , otherUrl , IsUncOrDosPath ? StringComparison . OrdinalIgnoreCase : StringComparison . Ordinal ) ;
0 commit comments