(Железный) Python - определение переменной определенного типа - PullRequest
4 голосов
/ 06 декабря 2011

да, я знаю, это тот же вопрос, который задавали тысячи раз раньше. Но нет, это не совсем так - по крайней мере, я так думаю.

Я использую IronPython и хочу вызвать метод C #:

bool GetClassInstance<T>(out T myClassInstance)

Вызов этой функции через python будет выглядеть так:

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

Проблема заключается в следующем сообщении об ошибке:

expected StrongBox[ClassType], got NoneType (ArgumentTypeException)

Теперь у меня есть два вопроса:

  • Можно ли заставить это работать?
  • Как ???

Спасибо большое !!

Ответы [ 2 ]

8 голосов
/ 06 декабря 2011

Для вызова методов, которые имеют out параметры, просто опустите аргумент (так как вы на самом деле не передаете значение), и его возвращаемое значение будет кортежем с результатом функции (если он не был * 1002) *) и значения 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
3 голосов
/ 07 декабря 2011

Ответ Джеффа хорош - но если вы действительно хотите семантику ref / out, ответ - исключение, вы можете использовать тип StrongBox (доступный через clr.StrongBox, но это тот же StrongBox, который использует LINQ):

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

Это включает нечетные сценарии, например, когда функция перегружена и отличается только параметрами ref / out или когда вы хотите просмотреть значение в другом потоке, поскольку оно обновляется до возврата GetClassInstance.

...