public void SequenceDecoderTest() { var codec = SequenceDecoder.Instance; var items = new List <PyObject>() { new PyInt(1), new PyInt(2), new PyInt(3) }; //SequenceConverter can only convert to any ICollection using var pyList = new PyList(items.ToArray()); using var listType = pyList.GetPythonType(); //it can convert a PyList, since PyList satisfies the python sequence protocol Assert.IsFalse(codec.CanDecode(listType, typeof(bool))); Assert.IsFalse(codec.CanDecode(listType, typeof(IList <int>))); Assert.IsFalse(codec.CanDecode(listType, typeof(System.Collections.IEnumerable))); Assert.IsFalse(codec.CanDecode(listType, typeof(IEnumerable <int>))); Assert.IsTrue(codec.CanDecode(listType, typeof(ICollection <float>))); Assert.IsTrue(codec.CanDecode(listType, typeof(ICollection <string>))); Assert.IsTrue(codec.CanDecode(listType, typeof(ICollection <int>))); //convert to collection of int ICollection <int> intCollection = null; Assert.DoesNotThrow(() => { codec.TryDecode(pyList, out intCollection); }); CollectionAssert.AreEqual(intCollection, new List <object> { 1, 2, 3 }); //no python exception should have occurred during the above conversion and check Runtime.CheckExceptionOccurred(); //convert to collection of string. This will not work. //The SequenceWrapper class will throw a python exception when it tries to access any element. //TryDecode is a lossless conversion so there will be no exception at that point //interestingly, since the size of the python sequence can be queried without any conversion, //the IList will report a Count of 3. ICollection <string> stringCollection = null; Assert.DoesNotThrow(() => { codec.TryDecode(pyList, out stringCollection); }); Assert.AreEqual(3, stringCollection.Count()); Assert.Throws(typeof(InvalidCastException), () => { string[] array = new string[3]; stringCollection.CopyTo(array, 0); }); Runtime.CheckExceptionOccurred(); //can't convert python iterable to collection (this will require a copy which isn't lossless) //python iterables do not satisfy the python sequence protocol var foo = GetPythonIterable(); var fooType = foo.GetPythonType(); Assert.IsFalse(codec.CanDecode(fooType, typeof(ICollection <int>))); //python tuples do satisfy the python sequence protocol var pyTuple = new PyTuple(items.ToArray()); var pyTupleType = pyTuple.GetPythonType(); Assert.IsTrue(codec.CanDecode(pyTupleType, typeof(ICollection <float>))); Assert.IsTrue(codec.CanDecode(pyTupleType, typeof(ICollection <int>))); Assert.IsTrue(codec.CanDecode(pyTupleType, typeof(ICollection <string>))); //convert to collection of int ICollection <int> intCollection2 = null; Assert.DoesNotThrow(() => { codec.TryDecode(pyTuple, out intCollection2); }); CollectionAssert.AreEqual(intCollection2, new List <object> { 1, 2, 3 }); //no python exception should have occurred during the above conversion and check Runtime.CheckExceptionOccurred(); //convert to collection of string. This will not work. //The SequenceWrapper class will throw a python exception when it tries to access any element. //TryDecode is a lossless conversion so there will be no exception at that point //interestingly, since the size of the python sequence can be queried without any conversion, //the IList will report a Count of 3. ICollection <string> stringCollection2 = null; Assert.DoesNotThrow(() => { codec.TryDecode(pyTuple, out stringCollection2); }); Assert.AreEqual(3, stringCollection2.Count()); Assert.Throws(typeof(InvalidCastException), () => { string[] array = new string[3]; stringCollection2.CopyTo(array, 0); }); Runtime.CheckExceptionOccurred(); }