What is the difference between a == b and a.Equals(b)?
It depends on the types of a and b.
In particular, Equals is a virtual method, so that its behavior doesn't depend on the compile-time types of a and b.
In Java, == will always compare by reference, which is not necessarily what you want, especially for strings.
In C#, == can be overloaded, but is not virtual (it's a static method). Therefore, if a or b are declared as object, it will compare by reference, even if their actual type overloads operator ==.
Also, a.Equals(b) will throw a NullReferenceException (NullPointerException in Java) if a is null.