4

I am importing a python list (of string) in C# using Python.NET and I can't find any example of conversion from Python.NET dynamic object to C# List (all examples out there seems to be in the opposite direction C# to Python).

I tried to cast the dynamic python.net object with (List<string>) and with Enumerable.ToList<string>() but both failed. The as operator returned null. The only thing that worked was to loop over it with foreach... but is this really the only way and the best solution ?

Here is the code:

using (Py.GIL())
{
   dynamic MyPythonClass = Py.Import("MyPythonClass")
   dynamic pyList = MyPythonClass.MyList;
   
   //List<string> mylist = (List<string>)pyList;               //failed
   //List<string> mylist = Enumerable.ToList<string>(pyList);  //failed
   //List<string> mylist = pyList as List<string>;             //returns null

   List<string> mylist = new List<string>();
   foreach(string item in pyList)
   {
         mylist.Add(item);                                     //Success !
   }
}

11
  • have you tried as operator Commented Aug 27, 2020 at 17:58
  • @Prasad Telkikar : just tried and it returned null (with no error), I'll update the post. Commented Aug 27, 2020 at 18:01
  • I'm not familiar with this interop or python, but this looks like MyPythonClass.List has a runtime type that isn't a List<string> or assignable to it. Stick the debugger on and see what the run time type of pyList really is Commented Aug 27, 2020 at 18:02
  • 1
    List has a ctor that takes an IEnumerable (which we know we have cos we can foreach it) so use that var myList = new List<string>((IEnumerable<string>)pyList) Commented Aug 27, 2020 at 18:06
  • 2
    mm actually looking at the source csharp.hotexamples.com/site/… it doesn't actually implement IEnumerable, it takes advantage of little c# oddity that foreach statements use duck typing - it doesn't care about an interface just the presence of GetEnumerator and that GetEnumerator has to return something with Current and MoveNext() - so your casting is likely to never work and what you are doing is probably best Commented Aug 27, 2020 at 18:25

1 Answer 1

9

Answer was (shamefully) very simple, thanks to @Dave:

string[] mylist = (string[])pyList;

//or

List<string> mylist = ((string[])pyList).ToList<string>();
Sign up to request clarification or add additional context in comments.

1 Comment

I would mention that the second form only works when you add using System.Linq; before. A method that works without Linq is using the List<string> constructor taking an array as an argument: List<string> mylist = new List<string>((string[])pyList);

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.