(Iron)Python - 定义特定类型的变量

时间:2011-12-06 09:06:29

标签: python types ironpython

是的,我知道,这似乎与之前成千上万次询问的问题相同。 但不,这不是真的 - 至少我是这么认为的。

我使用IronPython并想调用C#方法:

bool GetClassInstance<T>(out T myClassInstance)

通过python调用此函数看起来像:

myClassInstance = None
myInstance.GetClassInstance[ClassType](myClassInstance)

问题出现以下错误消息:

expected StrongBox[ClassType], got NoneType (ArgumentTypeException)

现在我有两个问题:

  • 是否可以让它运行?
  • 如何???

非常感谢!!

2 个答案:

答案 0 :(得分:8)

要调用具有out参数的方法,只需省略参数(因为您实际上没有传递值),并且其返回值将是具有函数结果的元组(如果它是非元的) void)和out值按照它们的定义顺序。

ref参数的情况下,传入参数,它仍然会在元组中返回。对象上的任何突变都将按预期工作。

如,

>>> from System import Int32
>>> Int32.TryParse('12345')
(True, 12345)
>>> Int32.TryParse('12345x')
(False, 0)

这是我做过的测试,因此您可以看到如何调用不同的变体。

namespace TestLibrary
{
    public class Test
    {
        public static void Test1(out int b)
        {
            b = 1;
        }

        public static bool Test2(out int b)
        {
            b = 2;
            return b == 2;
        }

        public static void Test3(int a, out int b, int c)
        {
            b = a + c;
        }

        public static bool Test4(int a, out int b, int c)
        {
            b = a + c;
            return b == 4;
        }

        public static void Test5(int a, out int b, int c, out int d)
        {
            b = a + c;
            d = a * c;
        }

        public static bool Test6(int a, out int b, int c, out int d)
        {
            b = a + c;
            d = a * c;
            return b == 6 || d == 6;
        }

        public static void Test7(int a, out int b, int c, out int d, ref int e)
        {
            b = a + c;
            d = a * c;
            int oldE = e++;
            Console.WriteLine("\"{0}\" -> \"{1}\"", oldE, e);
        }

        public static bool Test8(int a, out int b, int c, out int d, ref int e)
        {
            b = a + c;
            d = a * c;
            int oldE = e++;
            Console.WriteLine("\"{0}\" -> \"{1}\"", oldE, e);
            return b == 8 || d == 8 || oldE == 8;
        }

        public static bool Test9(int a, out int b, int c, out int d, ref int e, ref int[] f)
        {
            b = a + c;
            d = a * c;
            int oldE = e++;
            Console.WriteLine("\"{0}\" -> \"{1}\"", oldE, e);
            f = f ?? new int[0];
            for (int i = 0; i < f.Length; i++)
                f[i] = i;
            return b == 8 || d == 8 || oldE == 8;
        }
    }
}
>>> from TestLibrary import Test
>>> Test.Test1()
1
>>> Test.Test2()
(True, 2)
>>> Test.Test3(1, 3)
4
>>> Test.Test4(1, 3)
(True, 4)
>>> Test.Test5(1, 3)
(4, 3)
>>> Test.Test6(1, 3)
(False, 4, 3)
>>> Test.Test7(1, 3, 5)
"5" -> "6"
(4, 3, 6)
>>> Test.Test8(1, 3, 5)
"5" -> "6"
(False, 4, 3, 6)
>>> from System import Array
>>> array = Array.CreateInstance(int, 10)
>>> array
Array[int]((0, 0, 0, 0, 0, 0, 0, 0, 0, 0))
>>> Test.Test9(1, 3, 5, array)
"5" -> "6"
(False, 4, 3, 6, Array[int]((0, 1, 2, 3, 4, 5, 6, 7, 8, 9)))
>>> array
Array[int]((0, 1, 2, 3, 4, 5, 6, 7, 8, 9))

或者,如果您想使用C#样式调用,则需要传入clr.Reference[T]对象来代替out / ref参数来保存该值。您可以通过Value属性访问该值。

>>> outval = clr.Reference[int]()
>>> Test.Test1(outval)
>>> outval
<System.Int32 object at 0x000000000000002B [1]>
>>> outval.Value
1

答案 1 :(得分:2)

Jeff的答案很好 - 但是如果你真的想要ref / out语义,答案是异常,你可以使用StrongBox类型(可以通过clr.StrongBox获得,但这与LINQ使用的StrongBox相同):

import clr
myClassInstance = clr.StrongBox[ClassType]()
myInstance.GetClassInstance[ClassType](myClassInstance)
print myClassInstance.Value # value is now updated

这可以实现奇怪的场景,比如函数重载时只有ref / out参数不同,或者想要在GetClassInstance返回之前更新另一个线程上的值。