Пользовательская проверка равенства для записей C# 9C#

Место общения программистов C#
Ответить
Anonymous
 Пользовательская проверка равенства для записей C# 9

Сообщение Anonymous »

Насколько я понимаю, записи на самом деле являются классами, которые реализуют собственную проверку на равенство таким образом, что ваш объект управляется значением, а не ссылкой.
Короче, для записи Foo, который реализуется следующим образом: var foo = new Foo { Value = "foo" и var bar = new Foo { Value = "foo" , the foo == bar Выражение приведет к True, хотя у них другая ссылка (

Код: Выделить всё

ReferenceEquals(foo, bar) // False
).
Теперь с записями, хотя в статье, размещенной в блоге .Net, написано:

Если вам не нравится поведение по умолчанию при сравнении полей
сгенерированного переопределения Equals, вместо этого вы можете написать свое собственное.

Когда я попытался разместить public override bool Равно или общедоступное переопределение int GetHashCode, или общедоступный статический логический оператор == и т. д. Я получал сообщение об ошибке Member с той же подписью, которая уже объявлена, поэтому я думаю, что это ограниченное поведение, чего нельзя сказать о объектах struct.
Неудачный пример:

Код: Выделить всё

public sealed record SimpleVo
: IEquatable
{
public bool Equals(SimpleVo other) =>
throw new System.NotImplementedException();

public override bool Equals(object obj) =>
obj is SimpleVo other && Equals(other);

public override int GetHashCode() =>
throw new System.NotImplementedException();

public static bool operator ==(SimpleVo left, SimpleVo right) =>
left.Equals(right);

public static bool operator !=(SimpleVo left, SimpleVo right) =>
!left.Equals(right);
}
Результат компиляции:

Код: Выделить всё

SimpleVo.cs(11,30): error CS0111: Type 'SimpleVo' already defines a member called 'Equals' with the same parameter types

SimpleVo.cs(17,37): error CS0111: Type 'SimpleVo' already defines a member called 'op_Equality' with the same parameter types

SimpleVo.cs(20,37): error CS0111: Type 'SimpleVo' already defines a member called 'op_Inequality' with the same parameter types
Мой главный вопрос: что, если мы захотим настроить способ работы средства проверки равенства? Я имею в виду, я понимаю, что это превосходит всю цель записей, но, с другой стороны, проверка на равенство — не единственная функция, которая делает записи интересными в использовании.
Один вариант использования, когда кто-то хотел бы переопределить равенство записей, потому что у вас может быть атрибут, который исключил бы свойство из проверки равенства. Возьмем, к примеру, эту реализацию ValueObject.
Затем, если вы расширите этот абстрактный класс ValueObject следующим образом:

Код: Выделить всё

public sealed class FullNameVo : ValueObject
{
public FullNameVo(string name, string surname)
{
Name    = name;
Surname = surname;
}

[IgnoreMember]
public string Name { get; }

public string Surname { get; }

[IgnoreMember]
public string FullName => $"{Name} {Surname}";
}
тогда вы получите следующие результаты:

Код: Выделить всё

var user1 = new FullNameVo("John", "Doe");
var user2 = new FullNameVo("John", "Doe");
var user3 = new FullNameVo("Jane", "Doe");

Console.WriteLine(user1 == user2); // True
Console.WriteLine(ReferenceEquals(user1, user2)); // False
Console.WriteLine(user1 == user3); // True
Console.WriteLine(user1.Equals(user3)); // True
На данный момент, чтобы каким-то образом реализовать описанный выше вариант использования, я реализовал абстрактный объект записи и использую его следующим образом:

Код: Выделить всё

public sealed record FullNameVo : ValueObject
{
[IgnoreMember]
public string Name;

public string Surname;

[IgnoreMember]
public string FullName => $"{Name} {Surname}";
}
и результаты выглядят так:

Код: Выделить всё

var user1 = new FullNameVo
{
Name    = "John",
Surname = "Doe"
};

var user2 = new FullNameVo
{
Name    = "John",
Surname = "Doe"
};

var user3 = user1 with { Name = "Jane" };

Console.WriteLine(user1 == user2); // True
Console.WriteLine(ReferenceEquals(user1, user2)); // False
Console.WriteLine(user1 == user3); // False
Console.WriteLine(user1.Equals(user3)); // False
Console.WriteLine(ValueObject.EqualityComparer.Equals(user1, user3)); // True
В заключение я немного озадачен: является ли ограничение переопределения методов равенства объектов записи ожидаемым поведением или это потому, что оно все еще находится на стадии предварительного просмотра? Если это задумано, вы бы реализовали описанное выше поведение другим (лучшим) способом или просто продолжили бы использовать классы?

Код: Выделить всё

dotnet --version
вывод: 5.0.100-rc.1.20452.10

Подробнее здесь: https://stackoverflow.com/questions/643 ... -9-records
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»