diff --git a/src/Microsoft.Net.Http.Headers/EntityTagHeaderValue.cs b/src/Microsoft.Net.Http.Headers/EntityTagHeaderValue.cs
index 7f89a3e1..7d09920c 100644
--- a/src/Microsoft.Net.Http.Headers/EntityTagHeaderValue.cs
+++ b/src/Microsoft.Net.Http.Headers/EntityTagHeaderValue.cs
@@ -93,6 +93,15 @@ public override string ToString()
return _tag;
}
+ ///
+ /// Check against another for equality.
+ /// This equality check should not be used to determine if two values match under the RFC specifications (https://tools.ietf.org/html/rfc7232#section-2.3.2).
+ ///
+ /// The other value to check against for equality.
+ ///
+ /// true if the strength and tag of the two values match,
+ /// false if the other value is null, is not an , or if there is a mismatch of strength or tag between the two values.
+ ///
public override bool Equals(object obj)
{
var other = obj as EntityTagHeaderValue;
@@ -103,7 +112,7 @@ public override bool Equals(object obj)
}
// Since the tag is a quoted-string we treat it case-sensitive.
- return ((_isWeak == other._isWeak) && (string.CompareOrdinal(_tag, other._tag) == 0));
+ return _isWeak == other._isWeak && string.Equals(_tag, other._tag, StringComparison.Ordinal);
}
public override int GetHashCode()
@@ -112,6 +121,32 @@ public override int GetHashCode()
return _tag.GetHashCode() ^ _isWeak.GetHashCode();
}
+ ///
+ /// Compares against another to see if they match under the RFC specifications (https://tools.ietf.org/html/rfc7232#section-2.3.2).
+ ///
+ /// The other to compare against.
+ /// true to use a strong comparison, false to use a weak comparison
+ ///
+ /// true if the match for the given comparison type,
+ /// false if the other value is null or the comparison failed.
+ ///
+ public bool Compare(EntityTagHeaderValue other, bool useStrongComparison)
+ {
+ if (other == null)
+ {
+ return false;
+ }
+
+ if (useStrongComparison)
+ {
+ return !IsWeak && !other.IsWeak && string.Equals(Tag, other.Tag, StringComparison.Ordinal);
+ }
+ else
+ {
+ return string.Equals(Tag, other.Tag, StringComparison.Ordinal);
+ }
+ }
+
public static EntityTagHeaderValue Parse(string input)
{
var index = 0;
diff --git a/test/Microsoft.Net.Http.Headers.Tests/EntityTagHeaderValueTest.cs b/test/Microsoft.Net.Http.Headers.Tests/EntityTagHeaderValueTest.cs
index c17c9baa..f633fec2 100644
--- a/test/Microsoft.Net.Http.Headers.Tests/EntityTagHeaderValueTest.cs
+++ b/test/Microsoft.Net.Http.Headers.Tests/EntityTagHeaderValueTest.cs
@@ -99,6 +99,97 @@ public void Equals_UseSameAndDifferentETags_EqualOrNotEqualNoExceptions()
Assert.True(etag1.Equals(etag5), "tag vs. tag..");
}
+ [Fact]
+ public void Compare_WithNull_ReturnsFalse()
+ {
+ Assert.False(EntityTagHeaderValue.Any.Compare(null, useStrongComparison: true));
+ Assert.False(EntityTagHeaderValue.Any.Compare(null, useStrongComparison: false));
+ }
+
+ public static TheoryData NotEquivalentUnderStrongComparison
+ {
+ get
+ {
+ return new TheoryData
+ {
+ { new EntityTagHeaderValue("\"tag\""), new EntityTagHeaderValue("\"TAG\"") },
+ { new EntityTagHeaderValue("\"tag\"", true), new EntityTagHeaderValue("\"tag\"", true) },
+ { new EntityTagHeaderValue("\"tag\""), new EntityTagHeaderValue("\"tag\"", true) },
+ { new EntityTagHeaderValue("\"tag\""), new EntityTagHeaderValue("\"tag1\"") },
+ { new EntityTagHeaderValue("\"tag\""), EntityTagHeaderValue.Any },
+ };
+ }
+ }
+
+ [Theory]
+ [MemberData(nameof(NotEquivalentUnderStrongComparison))]
+ public void CompareUsingStrongComparison_NonEquivalentPairs_ReturnFalse(EntityTagHeaderValue left, EntityTagHeaderValue right)
+ {
+ Assert.False(left.Compare(right, useStrongComparison: true));
+ Assert.False(right.Compare(left, useStrongComparison: true));
+ }
+
+ public static TheoryData EquivalentUnderStrongComparison
+ {
+ get
+ {
+ return new TheoryData
+ {
+ { new EntityTagHeaderValue("\"tag\""), new EntityTagHeaderValue("\"tag\"") },
+ };
+ }
+ }
+
+ [Theory]
+ [MemberData(nameof(EquivalentUnderStrongComparison))]
+ public void CompareUsingStrongComparison_EquivalentPairs_ReturnTrue(EntityTagHeaderValue left, EntityTagHeaderValue right)
+ {
+ Assert.True(left.Compare(right, useStrongComparison: true));
+ Assert.True(right.Compare(left, useStrongComparison: true));
+ }
+
+ public static TheoryData NotEquivalentUnderWeakComparison
+ {
+ get
+ {
+ return new TheoryData
+ {
+ { new EntityTagHeaderValue("\"tag\""), new EntityTagHeaderValue("\"TAG\"") },
+ { new EntityTagHeaderValue("\"tag\""), new EntityTagHeaderValue("\"tag1\"") },
+ { new EntityTagHeaderValue("\"tag\""), EntityTagHeaderValue.Any },
+ };
+ }
+ }
+
+ [Theory]
+ [MemberData(nameof(NotEquivalentUnderWeakComparison))]
+ public void CompareUsingWeakComparison_NonEquivalentPairs_ReturnFalse(EntityTagHeaderValue left, EntityTagHeaderValue right)
+ {
+ Assert.False(left.Compare(right, useStrongComparison: false));
+ Assert.False(right.Compare(left, useStrongComparison: false));
+ }
+
+ public static TheoryData EquivalentUnderWeakComparison
+ {
+ get
+ {
+ return new TheoryData
+ {
+ { new EntityTagHeaderValue("\"tag\""), new EntityTagHeaderValue("\"tag\"") },
+ { new EntityTagHeaderValue("\"tag\"", true), new EntityTagHeaderValue("\"tag\"", true) },
+ { new EntityTagHeaderValue("\"tag\""), new EntityTagHeaderValue("\"tag\"", true) },
+ };
+ }
+ }
+
+ [Theory]
+ [MemberData(nameof(EquivalentUnderWeakComparison))]
+ public void CompareUsingWeakComparison_EquivalentPairs_ReturnTrue(EntityTagHeaderValue left, EntityTagHeaderValue right)
+ {
+ Assert.True(left.Compare(right, useStrongComparison: false));
+ Assert.True(right.Compare(left, useStrongComparison: false));
+ }
+
[Fact]
public void Parse_SetOfValidValueStrings_ParsedCorrectly()
{