Решил подробно изучить то, что именно сравнивают Equals, ReferenceEquals и == при сравнении разных объектов одинаковых и разных типов. Полазил тут и почитал моменты, которые меня интересовали, вроде, никакие лазейки не упустил:
https://docs.microsoft.com/ru-ru/dotnet/csharp/lan...
https://docs.microsoft.com/ru-ru/dotnet/api/system...
https://docs.microsoft.com/ru-ru/dotnet/api/system...
https://docs.microsoft.com/ru-ru/dotnet/api/system...
А вот сам эксперимент с выводами:
using System;
using System.Collections.Generic;
using System.Text;
using static System.Console;
namespace Workspace
{
class Program
{
static void Main()
{
//Классы:
A a = new A("Den");
A a2 = new A("Den");
WriteLine(a.Equals(a2)); //False
WriteLine(ReferenceEquals(a, a2)); //False
WriteLine(a == a2); //False
WriteLine();
A a3 = new A("Den");
A a4 = new A("Yan");
WriteLine(a3.Equals(a4)); //False
WriteLine(ReferenceEquals(a3, a4)); //False
WriteLine(a3 == a4); //False
WriteLine();
A a5 = new A("Den");
object a6 = new A("Den");
WriteLine(a5.Equals(a6)); //False
WriteLine(ReferenceEquals(a5, a6)); //False
WriteLine(a5 == a6); //False
WriteLine();
A a7 = new A("Den");
object a8 = new A("Yan");
WriteLine(a7.Equals(a8)); //False
WriteLine(ReferenceEquals(a7, a8)); //False
WriteLine(a7 == a8); //False
WriteLine();
////////////////////////////////////////
WriteLine();
WriteLine();
WriteLine();
A b = new B("Den", 19);
A b2 = new B("Den", 19);
WriteLine(b.Equals(b2)); //False
WriteLine(ReferenceEquals(b, b2)); //False
WriteLine(b == b2); //False
WriteLine();
A b3 = new B("Den", 19);
A b4 = new B("Yan", 19);
WriteLine(b3.Equals(b4)); //False
WriteLine(ReferenceEquals(b3, b4)); //False
WriteLine(b3 == b4); //False
WriteLine();
A b5 = new B("Den", 19);
object b6 = new B("Den", 19);
WriteLine(b5.Equals(b6)); //False
WriteLine(ReferenceEquals(b5, b6)); //False
WriteLine(b5 == b6); //False
WriteLine();
A b7 = new B("Den", 19);
object b8 = new B("Yan", 19);
WriteLine(b7.Equals(b8)); //False
WriteLine(ReferenceEquals(b7, b8)); //False
WriteLine(b7 == b8); //False
WriteLine();
WriteLine();
WriteLine();
WriteLine();
WriteLine();
WriteLine();
WriteLine();
//Структуры:
A2 a222 = new A2(2, 1, 3);
A2 a22 = new A2(2, 1, 3);
WriteLine(a222.Equals(a22)); //True
WriteLine(ReferenceEquals(a222, a22)); //False
//WriteLine(a222 == a22); оператор == невозможно применить к структуре
WriteLine();
A2 a23 = new A2(2, 1, 3);
A2 a24 = new A2(2, 4, 3);
WriteLine(a23.Equals(a24)); //False
WriteLine(ReferenceEquals(a23, a24)); //False
WriteLine();
A2 a25 = new A2(2, 1, 3);
object a26 = new A2(2, 1, 3);
WriteLine(a25.Equals(a26)); //True
WriteLine(ReferenceEquals(a25, a26)); //False
WriteLine();
A2 a27 = new A2(2, 1, 3);
object a28 = new A2(2, 4, 3);
WriteLine(a27.Equals(a28)); //False
WriteLine(ReferenceEquals(a27, a28)); //False
WriteLine();
////////////////////////////////////////
WriteLine();
WriteLine();
WriteLine();
A2 a22222 = new A2(2, 1, 3);
B2 a2222 = new B2(2, 1, 3);
WriteLine(a22222.Equals(a2222)); //False
WriteLine(ReferenceEquals(a22222, a2222)); //False
WriteLine();
A2 a223 = new A2(2, 1, 3);
B2 a224 = new B2(2, 4, 3);
WriteLine(a223.Equals(a224)); //False
WriteLine(ReferenceEquals(a223, a224)); //False
WriteLine();
A2 a225 = new A2(2, 1, 3);
object a226 = new B2(2, 1, 3);
WriteLine(a225.Equals(a226)); //False
WriteLine(ReferenceEquals(a225, a226)); //False
WriteLine();
A2 a227 = new A2(2, 1, 3);
object a228 = new B2(2, 4, 3);
WriteLine(a227.Equals(a228)); //False
WriteLine(ReferenceEquals(a227, a228)); //False
WriteLine();
object a229 = new A2(2, 1, 3);
object a220 = new B2(2, 1, 3);
WriteLine(a229.Equals(a220)); //False
WriteLine(ReferenceEquals(a229, a220)); //False
WriteLine();
WriteLine();
WriteLine();
WriteLine();
WriteLine();
WriteLine();
WriteLine();
//Массивы:
int[] c = new int[5];
int[] c2 = new int[5];
WriteLine(c.Equals(c2)); //False
WriteLine(ReferenceEquals(c, c2)); //False
WriteLine(c == c2); //False
WriteLine();
long[] c3 = new long[5];
int[] c4 = new int[5];
WriteLine(c3.Equals(c4)); //False
WriteLine(ReferenceEquals(c3, c4)); //False
/*WriteLine(c3 == c4);*/ //Из-за разности типов (long[] и int[]) - невозможно применить
WriteLine();
for (int i = 0; i < c.Length; i++)
{
c[i] = i;
c2[i] = i;
c3[i] = i;
c4[i] = i;
}
WriteLine(c.Equals(c2)); //False
WriteLine(ReferenceEquals(c, c2)); //False
WriteLine(c == c2); //False
WriteLine();
WriteLine(c3.Equals(c4)); //False
WriteLine(ReferenceEquals(c3, c4)); //False
WriteLine();
c2[2] = 45;
c4[2] = 55;
WriteLine(c.Equals(c2)); //False
WriteLine(ReferenceEquals(c, c2)); //False
WriteLine(c == c2); //False
WriteLine();
WriteLine(c3.Equals(c4)); //False
WriteLine(ReferenceEquals(c3, c4)); //False
WriteLine();
WriteLine();
WriteLine();
WriteLine();
WriteLine();
WriteLine();
WriteLine();
//String:
string d = "8";
string d2 = "8";
WriteLine(d.Equals(d2)); //True
WriteLine(ReferenceEquals(d, d2)); //True
WriteLine(d == d2); //True
WriteLine();
string d3 = "8";
object d4 = "8";
WriteLine(d3.Equals(d4)); //True
WriteLine(ReferenceEquals(d3, d4)); //True
WriteLine(d3 == d4); //True
WriteLine();
string d5 = new string("8");
string d6 = new string("8");
WriteLine(d5.Equals(d6)); //True
WriteLine(ReferenceEquals(d5, d6)); //False
WriteLine(d5 == d6); //True
WriteLine();
string d7 = new string("8");
object d8 = new string("8");
WriteLine(d7.Equals(d8)); //True
WriteLine(ReferenceEquals(d7, d8)); //False
WriteLine(d7 == d8); //False
WriteLine();
object d9 = new string("8");
object d0 = new string("8");
WriteLine(d9.Equals(d0)); //True
WriteLine(ReferenceEquals(d9, d0)); //False
WriteLine(d9 == d0); //False
WriteLine();
////////////////////////////////////////
WriteLine();
WriteLine();
WriteLine();
string d01 = "8";
string d02 = "9";
WriteLine(d01.Equals(d02)); //False
WriteLine(ReferenceEquals(d01, d02)); //False
WriteLine(d01 == d02); //False
WriteLine();
string d03 = "8";
object d04 = "9";
WriteLine(d03.Equals(d04)); //False
WriteLine(ReferenceEquals(d03, d04)); //False
WriteLine(d03 == d04); //False
WriteLine();
string d05 = new string("8");
string d06 = new string("9");
WriteLine(d05.Equals(d06)); //False
WriteLine(ReferenceEquals(d05, d06)); //False
WriteLine(d05 == d06); //False
WriteLine();
string d07 = new string("8");
object d08 = new string("9");
WriteLine(d07.Equals(d08)); //False
WriteLine(ReferenceEquals(d07, d08)); //False
WriteLine(d07 == d08); //False
WriteLine();
object h = "8";
object hh = "8";
WriteLine(h.Equals(hh)); //True
WriteLine(ReferenceEquals(h, hh)); //True
WriteLine(h == hh); //True
WriteLine();
//Другие примитивные типы:
int g = 5;
int g2 = 5;
WriteLine(g.Equals(g2)); //True
WriteLine(ReferenceEquals(g, g2)); //False
WriteLine(g == g2); //True
WriteLine();
int g3 = 5;
long g4 = 5;
WriteLine(g3.Equals(g4)); //False
WriteLine(ReferenceEquals(g3, g4)); //False
WriteLine(g3 == g4); //True
WriteLine();
int g5 = 5;
object g6 = 5;
WriteLine(g5.Equals(g6)); //True
WriteLine(ReferenceEquals(g5, g6)); //False
//WriteLine(g5 == g6); //Из-за разности типов (int и object) - невозможно применить
WriteLine();
object g7 = 5;
object g8 = 5;
WriteLine(g7.Equals(g8)); //True
WriteLine(ReferenceEquals(g7, g8)); //False
WriteLine(g7 == g8); //False
WriteLine();
//ReferenceEquals --- нельзя переопределить!
//Вывод:
//Если не переопределять:
//Классы:
//Equals: проверяет равенство ссылок
//ReferenceEquals: проверяет равенство ссылок
//==: проверяет равенство ссылок
//Структуры:
//Equals: сравнивает названия(типы) структур и значения соответственных полей\свойств
//ReferenceEquals: проверяет равенство ссылок
//==: не применяется(возможно, можно переопределить, но не проверял это)
//Массивы:
//Equals: проверяет равенство ссылок, несмотря на значения ячеек и возможное равенство соответственных ячеек
//ReferenceEquals: проверяет равенство ссылок
//==: проверяет равенство ссылок, но если разные типы массивов, то применить нельзя