skip to Main Content

I’ve got the following code:

using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
                    
public class Program
{
    public static void Main()
    {
        var json = JsonConvert.DeserializeObject<dynamic>("["test1", "test2"]");
        var list = json.ToObject<IEnumerable<string>>().Concat(new[] { "test3" });
        Console.WriteLine(string.Join(", ", list));
    }
}

I would expect the result to be "test1, test2, test3" but instead this throws an exception:

[Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: ‘System.Collections.Generic.List’ does not contain a definition for ‘Concat’] at CallSite.Target(Closure , CallSite , Object , String[] )
at System.Dynamic.UpdateDelegates.UpdateAndExecute2[T0,T1,TRet](CallSite site, T0 arg0, T1 arg1)
at Program.Main() :line 10

As far as I can tell in testing, both sides of the Concat should be a version of IEnumerable<string>.

I’ve gotten a successful try doing this:

using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
                    
public class Program
{
    public static void Main()
    {
        var json = JsonConvert.DeserializeObject<dynamic>("["test1", "test2"]");
        var list = (json as IEnumerable<dynamic>).Select(item => (string)item).Concat(new[] { "test3" });
        Console.WriteLine(string.Join(", ", list));
    }
}

But that’s a bit clunky.

What am I doing wrong? Am I missing something?

2

Answers


  1. Borrowing the solution from here, I tried assigning the output of ToObject() method to a new variable with explicit type like so:

    using Newtonsoft.Json;
    
    public class Program
    {
        public static void Main()
        {
            var json = JsonConvert.DeserializeObject<dynamic>("["test1", "test2"]");
            IEnumerable<string> jsonAsEnumerable = json.ToObject<IEnumerable<string>>();
            var list = jsonAsEnumerable.Concat(new[] { "test3" });
            Console.WriteLine(string.Join(", ", list));
        }
    }
    

    It seems to do the trick.

    Login or Signup to reply.
  2. Your code was super simple to fix. Here it is:

    var json = JsonConvert.DeserializeObject<dynamic[]>("["test1", "test2"]");
    var list = json.Concat(new[] { "test3" });
    Console.WriteLine(string.Join(", ", list));
    

    You just needed to change dynamic to dynamic[].

    Remember that dynamic is just compiler trickery for object-that-doesn’t-throw-compiler-errors. But it isn’t something that is enumerable. However, dynamic[] is.

    But for that matter, object[], and even string[], works.

    string[] json = JsonConvert.DeserializeObject<string[]>("["test1", "test2"]");
    IEnumerable<string> list = json.Concat(new[] { "test3" });
    Console.WriteLine(string.Join(", ", list));
    

    My advice is avoid dynamic in almost all cases. Use strong-typing instead.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search