vendredi 23 juillet 2021

Given Array.Cast

TL;DR - I would expect these all to work the same, but (per comments) they do not:

var c1 = new[] { FileMode.Append }.Cast<int>();
var c2 = new[] { FileMode.Append }.Select(x => (int)x);
var c3 = new[] { FileMode.Append }.Select(x => x).Cast<int>();

foreach (var x in c1 as IEnumerable)
  Console.WriteLine(x); // Append (I would expect 6 here!)

foreach (var x in c2 as IEnumerable)
  Console.WriteLine(x); // 6

foreach (var x in c3 as IEnumerable)
  Console.WriteLine(x); // 6

This is a contrived example; I obviously wouldn't cast the collections to IEnumerable if I didn't have to, and in that case everything would work as expected. But I'm working on a library with several methods that take an object and return a serialized string representation. If it determines via reflection that the object implements IEnumerable, it will enumerate it and, in almost all cases, return the expected result...except for this strange case with Array.Cast<T>.

There's 2 things I could do here:

  1. Tell uses to materialize IEnumerables first, such as with ToList().
  2. Create an overload for each affected method that takes an IEnumerable<T>.

For different reasons, neither of those is ideal. Is it possible for a method that takes an object to somehow infer T when Array.Cast<T>() is passed?





Aucun commentaire:

Enregistrer un commentaire