是的,我知道,这似乎与之前成千上万次询问的问题相同。 但不,这不是真的 - 至少我是这么认为的。
我使用IronPython并想调用C#方法:
bool GetClassInstance<T>(out T myClassInstance)
通过python调用此函数看起来像:
myClassInstance = None
myInstance.GetClassInstance[ClassType](myClassInstance)
问题出现以下错误消息:
expected StrongBox[ClassType], got NoneType (ArgumentTypeException)
现在我有两个问题:
非常感谢!!
答案 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返回之前更新另一个线程上的值。