Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add a T to List<T> where List<T> masquerades as 'dynamic' and T as 'object'?

How would I get change this snippet to correctly add an instance of A to a List<A>, B to a List<B>, etc.?

// someChild's actual type is A
object someChild = GetObject();
// collection's actual type is List<A> though method below returns object
dynamic list = GetListFromSomewhere(...);
// code below throws a RuntimeBinderException
list.Add(somechild);

The exception is thrown because, while the Add() is found by the binder, it passes in dynamic which fails overload resolution. I prefer not to change the above to use reflection, or at least to minimize that. I do have access to the instance of System.Type for each of A and List<A>. The class or method containing the above code is itself not generic.

like image 504
Kit Avatar asked Jan 18 '12 14:01

Kit


2 Answers

All you need is to make the binding for the argument dynamic too - so you just need the type of someChild to be dynamic:

dynamic someChild = GetObject();
dynamic list = GetListFromSomewhere(...);
list.Add(somechild);

In your previous code, the compiler would have remembered that the compile-time type of someChild was object, and so used that compile-time type instead of the execution-time type. The execution-time binder is smart at only treating dynamic expressions dynamically for overload resolution.

like image 75
Jon Skeet Avatar answered Oct 15 '22 14:10

Jon Skeet


Jon's right so I accepted that, but there's also my own forgetfulness that List<T> implements IList (the non-generic version):

object someChild = GetObject();
var list = (IList)GetListFromSomewhere(...);
list.Add(somechild);
like image 1
Kit Avatar answered Oct 15 '22 13:10

Kit