简体   繁体   中英

EqualityComparer<Uri>.Default.Equals() returning wrong result or what?

Is there an explanation for this other than being a bug in the .NET Framework? The EqualityComparer<Uri>.Default.Equals() method is saying that the following URLs are equal!

http://books.google.com/books?id=B84KAQAAIAAJ&pg=PA29&lpg=PA29&dq=fletcher+sandford+tilton&source=bl&ots=ou8eF5REOG&sig=74fzA11Z8AENBtyCUcXEsXV06jQ&hl=en&ei=2rHTS9LaN4249gTOh_GrDw&sa=X&oi=book_result&ct=result&resnum=3&ved=0CA0Q6AEwAg#v=onepage&q=fletcher s

and

http://books.google.com/books?id=B84KAQAAIAAJ&pg=PA29&lpg=PA29&dq=fletcher+sandford+tilton&source=bl&ots=ou8eF5REOG&sig=74fzA11Z8AENBtyCUcXEsXV06jQ&hl=en&ei=2rHTS9LaN4249gTOh_GrDw&sa=X&oi=book_result&ct=result&resnum=3&ved=0CA0Q6AEwAg#v=onepage&q=fletcher

Notice the space followed by 's' at the end of the first one.

Well, the concern (whether right or wrong) isn't in EqualityComparer<Uri>.Default . It calls into Uri.Equals() as it should.

Now, Uri.Equals() ignores differences on fragment alone. In a great many cases that is appropriate. In a great many it's not. Personally I wouldn't have had it as the default, but then since I'm not someone who coded it perhaps I don't know of some compelling reasons to have things as they are.

Note that this is documented.

Other decisions are also debatable (that it ignores case-difference on host components matches many practical concerns about URIs, but not how URI equality is defined in some specifications).

If you need a stricter equality than that, I suggest you define your own comparator:

public class UriStictEqualityComparer : IEqualityComparer<Uri>
{
  public bool Equals(Uri x, Uri y)
  {
    return ReferenceEquals(x, y)
      ||
      (
        x != null
        &&
        y != null
        &&
        x.IsAbsoluteUri == y.IsAbsoluteUri
        &&
        x.ToString() == y.ToString()
      );
  }
  public int GetHashCode(Uri obj)
  {
    return obj == null ? 0 : obj.ToString().GetHashCode();
  }
}

Still, you may find that you want some cases the above considers unequal, to be equal too. Eg you need to consider whether punycode and non-punycode versions are the same, whether escaped non-special characters should be unescaped, and so on. Uri's Compare method can be a benefit in such cases.

The behavior you are seeing is by-design. Uri fragments are ignored in its Equals implementation because they are not technically part of the URI itself. The Fragment part of your Uri is "#v=onepage&q=fletcher" (the # symbol and everything following it).

You can use a Uri 's Compare method and specify which UriComponents to include in the comparison.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM