Home > Mobile >  Check Map data types in generics
Check Map data types in generics

Time:01-11

I am making my own List and want to add logic to have different process based on the data type of E.
E = int is not a problem, but E = Map has an unwanted behavior.

For example, I want to treat all of E = Map<int, int>, E = Map<int, String> and E = Map as Map. However, == and is seem to consider these 3 are different. Could you help me with this issue?

my_list.dart

class MyList<E> extends ListBase<E> {
  final List<E> _list = <E>[];

  MyList() {
    print('E: $E');
    if (E == int) {
      print('int!!');
    } else if (E == HashMap || E is HashMap) {
      print('HashMap!!');
    } else if (E == LinkedHashMap || E is LinkedHashMap) {
      print('LinkedHashMap!!');
    } else if (E == SplayTreeMap || E is SplayTreeMap) {
      print('SplayTreeMap!!');
    } else if (E == Map || E is Map) {
      print('Map!!');
    }
  }

  // Other methods...
}

my_list_test.dart

void main() {
  test('Test MyList', () {
    final MyList<int> list = MyList<int>();
    final MyList<LinkedHashMap<int, String>> list1 =
        MyList<LinkedHashMap<int, String>>();
    final MyList<HashMap<int, String>> list2 = MyList<HashMap<int, String>>();
    final MyList<Map<int, int>> list3 = MyList<Map<int, int>>();
    final MyList<Map<int, String>> list4 = MyList<Map<int, String>>();
    final MyList<Map> list5 = MyList<Map>();
  });
}

Actual result

E: int
int!!
E: LinkedHashMap<int, String>
E: HashMap<int, String>
E: Map<int, int>
E: Map<int, String>
E: Map<dynamic, dynamic>
Map!!
✓ Test MyList

Expected Result

E: int
int!!
E: LinkedHashMap<int, String>
LinkedHashMap!! // This is not shown in the actual result
E: HashMap<int, String>
HashMap!! // This is not shown in the actual result
E: Map<int, int>
Map!! // This is not shown in the actual result
E: Map<int, String>
Map!! // This is not shown in the actual result
E: Map<dynamic, dynamic>
Map!!
✓ Test MyList

CodePudding user response:

The problem with E is Map is that the is operator is True if the object has the specified type, but the type of E is actually not E but rather type Type.

if (E is Type) {
  print('Type!!!');
}

The problem with E == Map is that Map is a raw type which is equivalent to Map<dynamic, dynamic>. If E is any other type of Map you will get false.

What you can do is check the type of an instance of E rather than E itself. For example, something like:

void add(E element) {
  if (element is Map) {
    print('Map!!');
  }
}

CodePudding user response:

This is how Flutter/Dart typing works. You can not explicitly check two types with generics (example on List): comparing of

List<int>

and

List

will always return false.

If you really need to compare two generic types then you can unpack them using generic helper to Type and try to compare them e.g. via string representations.

Helper:

Type _unpackedType<T>() => T;

Example usage:

void _check<T>() {
  print(_unpackedType<T>());
  print(_unpackedType<List>());
}


void main() {
  _check<List<int>>();
}

This will result into output as:

List<int>
List<dynamic>

Unfortunately these types can not be compared explicitly as the result will always be negative because of how Dart works with types, but as you can see the representation is comparable enough, so if you need such strict comparison you can simply normalise the output and remove the generic part from type string and compare type string representations. This will be relevant for any generic type and will work for you case.

  •  Tags:  
  • Related