felangel / equatable

A Dart package that helps to implement value based equality without needing to explicitly override == and hashCode.

Home Page:https://pub.dev/packages/equatable

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Strange behavior when comparing objects with lists

samuellow opened this issue · comments

class AccountSelectionState extends LoginState {
  final List<String> accounts;

  final List<bool> selected;

  AccountSelectionState(this.accounts, this.selected);

  @override
  List<Object> get props => List.from(accounts)..addAll(selected);
}

The equality check always returns true for the above state with two list attributes, even when provided with different list values.

The workaround was to capture a snapshot of the attributes.

class AccountSelectionState extends LoginState {
  final List<String> accounts;

  final List<bool> selected;

  final List<Object> values;

  AccountSelectionState(this.accounts, this.selected) :
    values = List.from(accounts)..addAll(selected);    

  @override
  List<Object> get props => values;
}

Is this the expected behavior?

I'm actually curious as well.
I landed here because I was looking for the (best) way to List/Map fields to the props. I didn't even think about just putting all elements in there.

class AccountSelectionState extends LoginState {
  final List<String> accounts;

  final List<bool> selected;

  AccountSelectionState(this.accounts, this.selected);

  @override
  List<Object> get props => List.from(accounts)..addAll(selected);
}

The equality check always returns true for the above state with two list attributes, even when provided with different list values.

The workaround was to capture a snapshot of the attributes.

class AccountSelectionState extends LoginState {
  final List<String> accounts;

  final List<bool> selected;

  final List<Object> values;

  AccountSelectionState(this.accounts, this.selected) :
    values = List.from(accounts)..addAll(selected);    

  @override
  List<Object> get props => values;
}

Would using the spread operator work as well?

@override
List<Object> get props =>List.of([...accounts,...selected]);

Just ran into this again.
Using:

@override
List<Object> get props => List.of([...accounts,...selected]);

cannot be trusted because the order changes the outcome.

I've solved this by using the following on each List-property that I want to be considered equal, even when the items are in a different order:

list.sortedBy<num>((element) => element.hashCode).toList();

So in this example it would be:

@override
List<Object> get props =>List.of([
  ...accounts.sortedBy<num>((element) => element.hashCode).toList(),
  ...selected.sortedBy<num>((element) => element.hashCode).toList(),
]);

Am I missing something?
I would assume the right way to implement props for this class would be

class AccountSelectionState extends LoginState {
  final List<String> accounts;

  final List<bool> selected;

  AccountSelectionState(this.accounts, this.selected);

  @override
  List<Object> get props => [ accounts, selected ];
}

Am I missing something?
I would assume the right way to implement props for this class would be

class AccountSelectionState extends LoginState {
  final List<String> accounts;

  final List<bool> selected;

  AccountSelectionState(this.accounts, this.selected);

  @override
  List<Object> get props => [ accounts, selected ];
}

I think you are correct. I personally got sidetracked because I wanted the lists to be equal even if the items were in different orders.

I simply solved that by using a Set instead of a List.

Set also doesn't work for me @SEGVeenstra

This still seems to be an open question and not addressed in the instructions how to handle it, could we reopen the this issue?