0

I'm trying to box values to an IEnumerable for a JsonConverter to be able to loop through dynamic data. However, I'm running into problems when trying to box a list of DateTime, or other structs.

        var datetime = DateTime.Now ;
        var boxed = datetime as object;  // Works: boxed is still a DateTime value

        var datetimeList = new List<DateTime> { DateTime.Now };
        var boxedEnumerable = datetimeList as IEnumerable<object>; // Does not work, boxedEnumerable is null

Casting to an IEnumerable seems to work well for all reference types, but not value types.

Note: The non-generic IEnumerable class can be used for these types of conversions instead of IEnumerable.

Devon Bessemer
  • 34,461
  • 9
  • 69
  • 95
  • I am curious why you need to box them in the first place? – kuskmen Apr 06 '20 at 16:05
  • We are using reflection on the class for a custom JsonConverter. So for any list types, we want to handle them differently.. – Devon Bessemer Apr 06 '20 at 16:06
  • 2
    Have you tried the linq method Cast? datetimeList.Cast() – ScottyD0nt Apr 06 '20 at 16:09
  • In our real example, we wouldn't know we'd have an IEnumerable to begin with, so Linq methods won't work. We only have an object type when we use Property.GetValue() from the reflection. – Devon Bessemer Apr 06 '20 at 16:12
  • .Cast is doing foreach within, casting each record in the enumerable to in your case object. Maybe you can try to do the same? Or simply create list of objects and add (object) DateTime.Now to it? – kuskmen Apr 06 '20 at 16:19
  • So, the property value is boxed already so we only have an object type, because we're using reflection. So we try to convert that object to an IEnumerable to see if it's a list type. So unfortunately, if we can't get it from an object to an IEnumerable, I don't see how we can iterate through it. – Devon Bessemer Apr 06 '20 at 16:21
  • https://stackoverflow.com/questions/9688268/why-cannot-ienumerablestruct-be-cast-as-ienumerableobject – Yuriy Rozhovetskiy Apr 06 '20 at 16:23
  • @YuriyRozhovetskiy, that seems to highlight the problem, unfortunately the solution of using cast doesn't work for our use case since we only have an object type to begin with when using GetValue() from reflection. – Devon Bessemer Apr 06 '20 at 16:26
  • 1
    Can you cast to non-generic System.Collections.IEnumerable? – Yuriy Rozhovetskiy Apr 06 '20 at 16:29
  • Thank you. I really should have thought of that. Non-generic IEnumerable works, then I can evaluate each item separately. – Devon Bessemer Apr 06 '20 at 16:40

1 Answers1

0

Variance applies only to reference types; if you specify a value type for a variant type parameter, that type parameter is invariant for the resulting constructed type

More details can be found here: https://learn.microsoft.com/en-us/dotnet/standard/generics/covariance-and-contravariance?redirectedfrom=MSDN#InterfaceCovariantTypeParameters