Эквивалентность record-ов
От: VladD2 Российская Империя www.nemerle.org
Дата: 16.10.23 15:08
Оценка:
Что-то прямо сижу и тихо охрениваю.

В record нельзя добавить собственную реализацию эквивалентности (переопределит Equals) и при это они не умеют реализовывать эквивалентность для записей со списками.

record R(int X, ImmutableArray<int> Xs);

static class P
{
    static void Main()
    {
        var r1 = new R(1,ImmutableArray.Create(2));
        var r2 = new R(1,ImmutableArray.Create(2));

        Console.WriteLine(r1 == r2);
   }
}


Выводит False!

С массивами тоже самое. Т.е. любая ссылка в параметре и прощай эквивалентность. Причем и вручную это не ясно как исправить.

А как жить то с такими говнорекордами? Вот на фиг так делать?

Я что-то пропустил? Как обойти это безобразие?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: Эквивалентность record-ов
От: hi_octane Беларусь  
Дата: 16.10.23 15:36
Оценка: 131 (2)
VD>Я что-то пропустил? Как обойти это безобразие?
Там же ещё есть record struct, которые вообще ValueType. Поэтому переопределение в рекордах немножко своё. Нужно сделать Equals от IEquatable, но без override, компилятор поймёт:

public sealed record R(int x, int[] xs)
{
    public bool Equals(R? other)
        => other.x == x && other.xs.SequenceEqual(xs);
}


И тогда на == будет True
Re[2]: Эквивалентность record-ов
От: VladD2 Российская Империя www.nemerle.org
Дата: 16.10.23 16:07
Оценка:
Здравствуйте, hi_octane, Вы писали:

_>Там же ещё есть record struct, которые вообще ValueType.


Как-то раньше в структурах удавалось Equals переопределять ведь.

_>Поэтому переопределение в рекордах немножко своё. Нужно сделать Equals от IEquatable, но без override, компилятор поймёт:


_>
_>public sealed record R(int x, int[] xs)
_>{
_>    public bool Equals(R? other)
_>        => other.x == x && other.xs.SequenceEqual(xs);
_>}
_>


_>И тогда на == будет True


Что-то не очень понял. Правда вот так понял:
record R(int X, int[] Xs)
{
    public virtual bool Equals(R? other) => other != null && other.X == X && other.Xs.SequenceEqual(Xs);

    public override int GetHashCode()
    {
        return X;
    }
}


Но в любом случае все это выглядит странным. А что что не реализована эквивалентность для вложенных последовательностей — это вообще лажа какая-то.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: Эквивалентность record-ов
От: VladD2 Российская Империя www.nemerle.org
Дата: 16.10.23 16:16
Оценка:
Здравствуйте, hi_octane, Вы писали:

_>Там же ещё есть record struct, которые вообще ValueType.


Как-то раньше в структурах удавалось Equals переопределять ведь.

_>Поэтому переопределение в рекордах немножко своё. Нужно сделать Equals от IEquatable, но без override, компилятор поймёт:


_>
_>public sealed record R(int x, int[] xs)
_>{
_>    public bool Equals(R? other)
_>        => other.x == x && other.xs.SequenceEqual(xs);
_>}
_>


_>И тогда на == будет True


Что-то не очень понял. Правда вот так понял:
record R(int X, int[] Xs)
{
    public virtual bool Equals(R? other) => other != null && other.X == X && other.Xs.SequenceEqual(Xs);

    public override int GetHashCode()
    {
        return X;
    }
}


Но в любом случае все это выглядит странным. А что что не реализована эквивалентность для вложенных последовательностей — это вообще лажа какая-то.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: Эквивалентность record-ов
От: yenik  
Дата: 17.10.23 05:00
Оценка: +1 -1
VD>
VD>record R(int X, int[] Xs)
VD>{
VD>    public virtual bool Equals(R? other) => other != null && other.X == X && other.Xs.SequenceEqual(Xs);

VD>    public override int GetHashCode()
VD>    {
VD>        return X;
VD>    }
VD>}
VD>


VD>Но в любом случае все это выглядит странным. А что что не реализована эквивалентность для вложенных последовательностей — это вообще лажа какая-то.


Коллекции суть ссылочный типы, естественно, равенство для них — это ссылочное равенство. Странным было бы, если бы их равенство по дефолту делалось через SequenceEqual.
Re: Эквивалентность record-ов
От: _FRED_ Черногория
Дата: 17.10.23 15:08
Оценка: 199 (6)
Здравствуйте, VladD2, Вы писали:

VD>Что-то прямо сижу и тихо охрениваю.

VD>В record нельзя добавить собственную реализацию эквивалентности (переопределит Equals) и при это они не умеют реализовывать эквивалентность для записей со списками.

С событиями тоже здорово вышло, мало кто ожидал, что они станут и их сравнивать:
using System;

var r1 = new R("R");
var r2 = new R("R");
Console.WriteLine($"Compare {nameof(r1)} and {nameof(r2)} before subscription: {r1 == r2}");

r1.Event += delegate { };
Console.WriteLine($"Compare {nameof(r1)} and {nameof(r2)} after subscription: {r1 == r2}");

record R(string Name) {
  public event EventHandler? Event;
}


P.S. По-честному, если рекорд не `sealed`, хорощо б и `EqualityContract` сравнивать и учитывать в хеше:
record R(string Name) {
  public event EventHandler? Event;
    
  public virtual bool Equals(R? other) => other != null && other.EqualityContract == EqualityContract && other.Name == Name;
  public override int GetHashCode() => (EqualityContract, Name).GetHashCode();
}
Help will always be given at Hogwarts to those who ask for it.
Re[4]: Эквивалентность record-ов
От: _FRED_ Черногория
Дата: 17.10.23 15:27
Оценка: +1
Здравствуйте, yenik, Вы писали:

VD>>Но в любом случае все это выглядит странным. А что что не реализована эквивалентность для вложенных последовательностей — это вообще лажа какая-то.

Y>Коллекции суть ссылочный типы, естественно, равенство для них — это ссылочное равенство. Странным было бы, если бы их равенство по дефолту делалось через SequenceEqual.

Это не так. Компилятор использует `EqualityComparer<>.Default.Equals(, )` для сравнения членов, поэтому если коллекция будет иметь переопределённый `Equals`, то будет использван он, а не "ссылочное равенство".
Help will always be given at Hogwarts to those who ask for it.
Re[4]: Эквивалентность record-ов
От: Разраб  
Дата: 18.10.23 01:42
Оценка:
Здравствуйте, yenik, Вы писали:


VD>>Но в любом случае все это выглядит странным. А что что не реализована эквивалентность для вложенных последовательностей — это вообще лажа какая-то.


Y>Коллекции суть ссылочный типы, естественно, равенство для них — это ссылочное равенство. Странным было бы, если бы их равенство по дефолту делалось через SequenceEqual.

F# :
> let arr1 = [|1;2;3|];;
val arr1 : int [] = [|1; 2; 3|]

> let arr2 = [|1;2;3|];;
val arr2 : int [] = [|1; 2; 3|]

> arr1 = arr2;;
val it : bool = true

> type Cart = { Id : int; Items : array<int> };;
type Cart =
  {Id: int;
   Items: int array;}

> let c1 = { Id = 1; Items = arr1 };;
val c1 : Cart = {Id = 1;
                 Items = [|1; 2; 3|];}

> let c2 = { Id = 1; Items = arr2 };;
val c2 : Cart = {Id = 1;
                 Items = [|1; 2; 3|];}

> c1 = c2;;
val it : bool = true
☭ ✊ В мире нет ничего, кроме движущейся материи.
Re[5]: Эквивалентность record-ов
От: yenik  
Дата: 18.10.23 05:17
Оценка:
_FR>если коллекция будет иметь переопределённый `Equals`

И я о том: Странным было бы, если бы их равенство по дефолту делалось через SequenceEqual. А если переопределить Equals, тогда конечно любые фантазии.
Можно было бы ещё вспомнить string, но это особенный тип коллекции.
Re[5]: Эквивалентность record-ов
От: yenik  
Дата: 18.10.23 05:32
Оценка: -1
Р>F# :

Хорошее замечание. И хорошо, что этого нет в C#. Представляю себе два списка по миллиону элементов, и вдруг a == b их перебирает. Нет, если нужно SequenceEqual, то и вызывать нужно SequenceEqual в явном виде.
Re[6]: Эквивалентность record-ов
От: Разраб  
Дата: 18.10.23 06:35
Оценка: :)
Здравствуйте, yenik, Вы писали:

Р>>F# :


Y>Хорошее замечание. И хорошо, что этого нет в C#. Представляю себе два списка по миллиону элементов, и вдруг a == b их перебирает. Нет, если нужно SequenceEqual, то и вызывать нужно SequenceEqual в явном виде.

Нет, если нужно ReferenceEquals , то и вызывать нужно ReferenceEquals в явном виде.
obj.ReferenceEquals (arr1,arr2)// => false
☭ ✊ В мире нет ничего, кроме движущейся материи.
Re[4]: Эквивалентность record-ов
От: VladD2 Российская Империя www.nemerle.org
Дата: 18.10.23 16:45
Оценка:
Здравствуйте, yenik, Вы писали:

Y>Коллекции суть ссылочный типы, естественно, равенство для них — это ссылочное равенство.


Рекорды тоже ссылочный тип. Но эквивалентность для них сделана по значению. Следственно естественного тут ничего нет. Это твои стереотипы.

Тут на лицо непоследовательность. Для одних типов делаем, для других нет.

Взялись повторять функциональные языки, но на полпути забили на это дело. В Немерле есть встроенный список, который сам по себе является алгебраическим типом и для него эквивалентность работает как надо. Тут же ничего подобного не предусмотрели. Сам метод переопределения эквивалентности сделали мягко говоря странно.

Y>Странным было бы, если бы их равенство по дефолту делалось через SequenceEqual.


Что тут странного? Странно, что коллекции не поддерживают Equals и IEquatable из коробки.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: Эквивалентность record-ов
От: VladD2 Российская Империя www.nemerle.org
Дата: 18.10.23 16:46
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>P.S. По-честному, если рекорд не `sealed`, хорощо б и `EqualityContract` сравнивать и учитывать в хеше:


А кто-нибудь может в двух словах объяснить на фиг он вообще EqualityContract придумали?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[5]: Эквивалентность record-ов
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 18.10.23 18:29
Оценка: -1
Здравствуйте, VladD2, Вы писали:


Y>>Странным было бы, если бы их равенство по дефолту делалось через SequenceEqual.


VD>Что тут странного? Странно, что коллекции не поддерживают Equals и IEquatable из коробки.


Различная эквивалентность нужна. Например сравнивать через HashSet, сортированные списки по определенным полям, ReferenceEquals итд.
Кроме того надо разруливать циклические ссылки итд. Слишком много параметров сравнения. Проще для списков свою реализацию сделать.
и солнце б утром не вставало, когда бы не было меня
Re[3]: Эквивалентность record-ов
От: _FRED_ Черногория
Дата: 18.10.23 20:02
Оценка: 53 (1)
Здравствуйте, VladD2, Вы писали:

_FR>>P.S. По-честному, если рекорд не `sealed`, хорощо б и `EqualityContract` сравнивать и учитывать в хеше:

VD>А кто-нибудь может в двух словах объяснить на фиг он вообще EqualityContract придумали?

Чтобы экземпляр наследника вдруг не смог бы быть равен экземпляру базового типа.

The EqualityContract enables the equality methods to compare the runtime type of objects when they're checking for equality.

(отсюда)

Пример:
using System;

var r = new R("A");
var x = new X("A");
Console.WriteLine($"Compare {nameof(r)} and {nameof(x)}: {r == x}"); // False

var r1 = new R1("A");
var x1 = new X1("A");
Console.WriteLine($"Compare {nameof(r1)} and {nameof(x1)}: {r1 == x1}"); // True

record R(string Name) { }
record X(string Name) : R(Name) { }

record R1(string Name) {
  public virtual bool Equals(R1? other) => other is not null && other.Name == Name;
  public override int GetHashCode() => Name?.GetHashCode() ?? 0;
}

record X1(string Name) : R1(Name) { }
Help will always be given at Hogwarts to those who ask for it.
Re[5]: Эквивалентность record-ов
От: yenik  
Дата: 19.10.23 05:54
Оценка:
VD>Тут на лицо непоследовательность. Для одних типов делаем, для других нет.
VD>Что тут странного? Странно, что коллекции не поддерживают Equals и IEquatable из коробки.

https://learn.microsoft.com/ru-ru/dotnet/csharp/language-reference/builtin-types/record#value-equality

Для типов class два объекта равны, если они ссылаются на один и тот же объект в памяти.
Для типов struct два объекта равны, если хранят одинаковые значения и имеют один и тот же тип.
Для типов с модификатором record (record class, record struct и readonly record struct) два объекта равны, если они относятся к одному типу и хранят одинаковые значения.


Коллекции в .NET относятся к типу class и по определению не поддерживают переопределение Equals и IEquatable из коробки. Если бы к существующим коллекциям вдруг приделали переопределение Equals, то это было бы несовместимое изменение. Если бы новые коллекции стали делать с Equals на основе поэлементного сравнения, то это было бы непоследовательно.
Типы record — это новшество, у которого равенство отличается от традиционной трактовки равенства объектов в C# и других популярных языках программирования.
Re[6]: Эквивалентность record-ов
От: samius Япония http://sams-tricks.blogspot.com
Дата: 19.10.23 07:33
Оценка:
Здравствуйте, yenik, Вы писали:

VD>>Тут на лицо непоследовательность. Для одних типов делаем, для других нет.

VD>>Что тут странного? Странно, что коллекции не поддерживают Equals и IEquatable из коробки.

Y>https://learn.microsoft.com/ru-ru/dotnet/csharp/language-reference/builtin-types/record#value-equality

Y>

Y>Для типов class два объекта равны, если они ссылаются на один и тот же объект в памяти.
Y>Для типов struct два объекта равны, если хранят одинаковые значения и имеют один и тот же тип.
Y>Для типов с модификатором record (record class, record struct и readonly record struct) два объекта равны, если они относятся к одному типу и хранят одинаковые значения.


Y>Коллекции в .NET относятся к типу class и по определению не поддерживают переопределение Equals и IEquatable из коробки.

Это определение вводит очень странное отношение равеснства объектов, пользоваться которым не сильно удобно, т.к. оно не указывает на то, могут ли быть равны две строки с одинаковыми значениями, но в разных участках памяти. То есть, даже для того, что бы понять как ведут себя рекорды со строковыми полями, мы не можем это определение использовать.
Кроме того, оно определяет равенство объектов через ссылку на объект, но ссылка не является объектом в системе типов .NET.

Y>Если бы к существующим коллекциям вдруг приделали переопределение Equals, то это было бы несовместимое изменение. Если бы новые коллекции стали делать с Equals на основе поэлементного сравнения, то это было бы непоследовательно.

Y>Типы record — это новшество, у которого равенство отличается от традиционной трактовки равенства объектов в C# и других популярных языках программирования.
Традиционная трактовка через популярные языки — вообще что-то некодифицируемое. Мы в одном-то языке не можем разобраться.
Есть отношения эквивалентности и их реализации, которые могут быть хорошими или не очень. Пожалуй, это все, на что можно опираться. У рекордов — эквивалентность такая, какую сегодня дает компилятор, согласно спецификации рекордов (https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-9.0/records). Разумеется, всем не угодишь, поэтому, она такая, какая есть, а в хелпах сова на глобусе.
Re[4]: Эквивалентность record-ов
От: VladD2 Российская Империя www.nemerle.org
Дата: 19.10.23 09:20
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Чтобы экземпляр наследника вдруг не смог бы быть равен экземпляру базового типа.


А чем им для этого GetType() не подошел? Да и для структурной эквивалентности (что и должна обеспечиваться для записей) не нужно совпадение типов. Достаточно совпадения полей и их значений. Так что это должно быть как опция.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: Эквивалентность record-ов
От: VladD2 Российская Империя www.nemerle.org
Дата: 19.10.23 09:31
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>Различная эквивалентность нужна. Например сравнивать через HashSet, сортированные списки по определенным полям, ReferenceEquals итд. Кроме того надо разруливать циклические ссылки итд. Слишком много параметров сравнения.


Тут есть два нюанса.

1. Удобство. Заставлять делать людей рутинную работу — глупо. Несомненно, если нужны какие-то нюансы, надо позволить людям заменить стандартную реализацию. Но по умолчанию должен работать самый ожидаемый вариант. Тогда не придется тратить время на непроизводительный труд.

2. Под записями (рекордами) лежат математические модели алгебраических типов и структурной типизации. Они не из пальца высосаны. И раз так, то нужно выдерживать все каноны этих моделей.

S>Проще для списков свою реализацию сделать.


Проще не делать ничего без необходимости. Проще, как раз, было бы реализовать для списков сравнение. И уже у конкретных видов коллекций сделать тот или ной вид сравнения. Для списков — последовательное сравнение (совпадение всех элементов), для сетов — совпадение множеств.

Ну и логично было бы сделать нормальный однонаправленный связанный список на рекордах, чтобы он был алгебраическим типом (как в Немерле).
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Отредактировано 19.10.2023 10:09 VladD2 . Предыдущая версия .
Re[7]: Эквивалентность record-ов
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 19.10.23 09:43
Оценка:
Здравствуйте, VladD2, Вы писали:


S>>Проще для списков свою реализацию сделать.


VD>Проще не делать ничего без необходимости. Проще, как раз, было бы реализовать для списков сравнение. И уже у конкретных видов коллекций сделать тот или ной вид сравнения. Для списков — последовательное сравнение (совпадение всех элементов), для сетов — совпадение множеств.


VD>Ну и логично было бы сделать нормальный однонаправленный связанный список на рекордах, чтобы он был алгебраическим типом (как в Немерле).


Как раз в большинстве вариантов нужны свои сравнения. Опять же Хэш код вычислять нужно время. А нужно то всего на всего сравнить ссылки
Я вот не помню когда пользовался односвязными списками вообще, только для буферов (страниц)

А так тебе придется для строк свои реализации с IgnoreCase делать итд.
Для списка достаточно по дефолту ReferenceEquals
и солнце б утром не вставало, когда бы не было меня
Re[8]: Эквивалентность record-ов
От: VladD2 Российская Империя www.nemerle.org
Дата: 19.10.23 10:04
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>Как раз в большинстве вариантов нужны свои сравнения.


Зачем говорить очевидную чушь? На хрена в большинстве случае нужно что-то за пределами структурной эквивалентности? В большинстве случаев её за глаза хватает. А оставшиеся 5% можно и вручную реализовать.

Ну и повторенное утверждение не становится от этого вернее.

S>Опять же Хэш код вычислять нужно время. А нужно то всего на всего сравнить ссылки


Ну все, тогда для строк эквивалентность не надо было делать. Аргументация как у девочки.

S>Я вот не помню когда пользовался односвязными списками вообще, только для буферов (страниц)


Ну как бы это твои проблемы. А так-то ими можно всегда пользоваться. Они обеспечивают неизменяемость, версионность, сравнение паттернматчингом (в нормальных языках) и всего на несколько процентов менее эффективны в случае когда нужно последовательное хранение.

S> А так тебе придется для строк свои реализации с IgnoreCase делать итд.


Чего? Это то тут причем? Компараторы и перегрузки Equals никто не отменял.

S>Для списка достаточно по дефолту ReferenceEquals


Ну глупое решение принятое глупыми людьми. Зачем его поддерживать то?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Отредактировано 19.10.2023 10:12 VladD2 . Предыдущая версия .
Re[5]: Эквивалентность record-ов
От: _FRED_ Черногория
Дата: 19.10.23 10:10
Оценка:
Здравствуйте, VladD2, Вы писали:

_FR>>Чтобы экземпляр наследника вдруг не смог бы быть равен экземпляру базового типа.

VD>А чем им для этого GetType() не подошел?

Видимо тем, что `EqualityContract` можно объявить и/или override-нуть явно:

using System;

var r = new R("A");
var x = new X("A");
Console.WriteLine($"Compare {nameof(r)} and {nameof(x)}: {r == x}"); // True

record R(string Name) { }
record X(string Name) : R(Name) {
  protected override Type EqualityContract => typeof(R);
}


VD>Да и для структурной эквивалентности (что и должна обеспечиваться для записей) не нужно совпадение типов. Достаточно совпадения полей и их значений. Так что это должно быть как опция.


В случае, когда мы допускаем, что экземпляр `record A { }` может быть "эквивалентен" экземпляру `record B : A { }` или даже `record C { }`, мне кажется, всё сильно усложнится. Как минимум, как-то вручную придётся беспокоиться о том, что `a.Equals(b) == b.Equals(a)` и `a.GetHashCode() == b.GetHashCode()` где `a` и `b` экземпляры различных типов.

Когда же ты явно переопределил `EqualityContract`, то тем самым ты заявил, что принимаешь все эти риски. Автоматически же компилятору поддерживать подобное (особенно в случае различных иерархий типов) в согласованном состоянии будет сложно.
Help will always be given at Hogwarts to those who ask for it.
Re[5]: Эквивалентность record-ов
От: _FRED_ Черногория
Дата: 19.10.23 10:47
Оценка: +1
Здравствуйте, VladD2, Вы писали:

VD>…Да и для структурной эквивалентности (что и должна обеспечиваться для записей) не нужно совпадение типов. Достаточно совпадения полей и их значений. Так что это должно быть как опция.


Кажется, хороший пример нашёлся, объясняющий почему мне лично такое вот "структурной эквивалентности … не нужно совпадение типов" не нравится "по дефолту":
abstract record Expression { }
abstract record BinaryExpression(Expression Left, Expression Right) : Expression { }
sealed record BinaryPlusExpression(Expression Left, Expression Right) : BinaryExpression(Left, Right) { }
sealed record BinaryMinusExpression(Expression Left, Expression Right) : BinaryExpression(Left, Right) { }


Мне было бы странно вдруг получить, что экземпляр `BinaryPlusExpression` "эквивалентен" экземпляру `BinaryMinusExpression`. Не смотря на то, что данные там и там одинаковые, поведение (результат выполнения виртуальных методов) может быть разным.

Возможно, это вопрос терминологии и для рекордов не стоит применять понятие такой вот "структурной эквивалентности".
Help will always be given at Hogwarts to those who ask for it.
Отредактировано 19.10.2023 11:19 _FRED_ . Предыдущая версия .
Re[6]: Эквивалентность record-ов
От: VladD2 Российская Империя www.nemerle.org
Дата: 19.10.23 13:29
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Мне было бы странно вдруг получить, что экземпляр `BinaryPlusExpression` "эквивалентен" экземпляру `BinaryMinusExpression`. Не смотря на то, что данные там и там одинаковые, поведение (результат выполнения виртуальных методов) может быть разным.


Так это не структурная типизация, а номинативная. В структурной все определяется значениями, а не типами. Введи поле с символом (+/-) и все встанет на свои места.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[7]: Эквивалентность record-ов
От: _FRED_ Черногория
Дата: 19.10.23 17:03
Оценка:
Здравствуйте, VladD2, Вы писали:

_FR>>Мне было бы странно вдруг получить, что экземпляр `BinaryPlusExpression` "эквивалентен" экземпляру `BinaryMinusExpression`. Не смотря на то, что данные там и там одинаковые, поведение (результат выполнения виртуальных методов) может быть разным.


VD>Так это не структурная типизация, а номинативная. В структурной все определяется значениями, а не типами. Введи поле с символом (+/-) и все встанет на свои места.


Да, я понимаю. Говорю о том, что у рекордов такая типизация смотрелась бы странно для меня. Как минимум потому, что рекорды (как и другие пользовательские типы) помимо собственно данных содержат и определённое пользователем поведение, которое имеет право быть разным в разных типах и считать такие объекты одинаковыми "из коробки" было бы неожиданным.

Например в туплах, которые пользователем не расширяются и содержат только данные, это было бы (и есть в дотнете и шарпе) норм.

Кажется, ни что не мешает выписать коллекции с нужным алгоритмом сравнения элементов и использовать в рекордах и туплах их и тогда будет "как нужно" вроде какой спец. поддержки от компилятора тут не требуется?
Help will always be given at Hogwarts to those who ask for it.
Re[8]: Эквивалентность record-ов
От: VladD2 Российская Империя www.nemerle.org
Дата: 19.10.23 20:41
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Кажется, ни что не мешает выписать коллекции с нужным алгоритмом сравнения элементов и использовать в рекордах и туплах их и тогда будет "как нужно" вроде какой спец. поддержки от компилятора тут не требуется?


В целом, да. Вот только в стандартных на это забили. Да и культура у дотнетных программистов явно не та, что показывает данная тема. Всем естественно противоестественное поведение.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[9]: Эквивалентность record-ов
От: _FRED_ Черногория
Дата: 20.10.23 06:54
Оценка: 78 (1) +1
Здравствуйте, VladD2, Вы писали:

_FR>>Кажется, ни что не мешает выписать коллекции с нужным алгоритмом сравнения элементов и использовать в рекордах и туплах их и тогда будет "как нужно" вроде какой спец. поддержки от компилятора тут не требуется?

VD>В целом, да. Вот только в стандартных на это забили. Да и культура у дотнетных программистов явно не та, что показывает данная тема. Всем естественно противоестественное поведение.

Да тут совсем не в "культуре" дело, а в именно в том, что "в стандартных на это забили" и теперь уже есть то, что есть. И ломать это проблематично и люди просто не ожидают иного.

Решить это в целом вполне возможно:
  1. Выписать `IEqualityComparer`-ы для коллекций (имеющихся) вместо новых коллекций.
  2. Найти удобный способ связать компаратор с полем/свойством рекорда. Атрибут или приватное свойство с именем `<PropertyName>EqualityComparer` или что-то ещё или даже всё вместе.
  3. Сделать Source Generator. который вместо дефолтового компаратора будет брать тот, что указан выше.

Возможно, найдя хорошее решение для второго пункта, можно предложить его разработчикам языка.
Help will always be given at Hogwarts to those who ask for it.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.