Переопределение C # равнозначно использованию “as” и специализированного метода для корректности, гибкости и производительности
-
19-08-2019 - |
Вопрос
Я задавался вопросом о наилучшем способе реализации правильные, гибкие и быстрые аналоги в C #, которые могут быть использованы практически для любого класса и ситуации.Я полагал, что специализированное Equals (принимающее объект фактического класса в качестве параметра) необходимо для повышения производительности.Чтобы избежать дублирования кода, общие Equals должны вызывать специализированные Equals.Нулевые проверки должны выполняться только один раз, даже в унаследованных классах.
Наконец-то я придумал этот дизайн:
class MyClass
{
public Int32 SomeValue1 = 1;
public Int32 SomeValue2 = 25;
// Ignoring GetHashCode for simplicity.
public override bool Equals(object obj)
{
return Equals (obj as MyClass);
}
public bool Equals(MyClass obj)
{
if (obj == null) {
return false;
}
if (!SomeValue1.Equals (obj.SomeValue1)) {
return false;
}
if (!SomeValue2.Equals (obj.SomeValue2)) {
return false;
}
return true;
}
}
class MyDerivedClass : MyClass
{
public Int32 YetAnotherValue = 2;
public override bool Equals(object obj)
{
return Equals (obj as MyDerivedClass);
}
public bool Equals(MyDerivedClass obj)
{
if (!base.Equals (obj)) {
return false;
}
if (!YetAnotherValue.Equals (obj.YetAnotherValue)) {
return false;
}
return true;
}
}
Важные идеи:
- Использование оператора "as".Таким образом, нам не нужно проверять наличие нулей в общем Равенстве.Неправильные типы классов будут сведены к нулю и будут отсортированы в специализированных Equals .
- Проверка на нулевой уровень ровно в одной точке, даже для производных классов.
- Проверка атрибутов одного за другим обеспечивает четкую структуру.
Есть ли недостатки в этой концепции, или я пропустил какие-то условия?
Решение
Ваш метод Equals не является рефлексивным, когда задействованы разные типы:
MyDerivedClass mdc = new MyDerivedClass();
MyClass mc = new MyClass();
Object omdc = mdc;
Object omc = mc;
// mc.Equals(mdc) - true
// mdc.Equals(mc) - true by calling the right overload
// omc.Equals(omdc) - true
// omdc.Equals(omc) - false, the "as" in MyDerivedClass will result in null
Обычный способ обойти это - использовать:
if (GetType() != other.GetType())
{
return false;
}
Смотрите документы в Объект.Равен:"x.Equals(y) возвращает то же значение, что и y.Equals(x)". Использование перегрузки для получения разных результатов может привести к ужасно проблемы, которые было бы очень сложно отладить.