我如何在C#中使用params`out`?

12 .net c#

我发现自己处于需要这种情况的状态

public static void Fill(this SomeClass c, params out object[] p)
Run Code Online (Sandbox Code Playgroud)

并称之为

c.Fill(out i, out i2, out sz, out i3, out sz2);
Run Code Online (Sandbox Code Playgroud)

但是我得到了错误 error CS1611: The params parameter cannot be declared as ref or out

我如何传递可变长度参数并使它们可写?所有这些都是整数和字符串的混合

Mar*_*ell 19

您无法将参数视为out(或ref)并同时使用该params功能.它根本不起作用.您可以做的最好的事情是创建一个数组参数,生成数组 out,声明一个数组变量并调用传递数组的方法,然后通过索引手动检查每个元素.

Foo(out object[] data) {...}
object[] result;
Foo(out result);
// look at result[0], result[1], result[2] etc
Run Code Online (Sandbox Code Playgroud)

所以:你不能做你想做的事.即使你可以,ref/ out 从不工作,除非数据类型之间存在完全匹配,所以它仍然必须是:

object o1, o2, o3, o4;
Foo(out o1, out o2, out o3, out o4);
// cast o1, o2, o3, o4
Run Code Online (Sandbox Code Playgroud)

哪个仍然不是你想要的.


dtb*_*dtb 7

这里没有技术需求out.这有效:

void Fill(object[] p)
{
    p[0] = 1;
    p[1] = 42;
    p[2] = "Hello";
    p[3] = -1;
    p[4] = "World";
}

object[] p = new object[5];
foo.Fill(p);
i = (int)p[0];
i2 = (int)p[1];
sz = (string)p[2];
i3 = (int)p[3];
sz2 = (string)p[4];
Run Code Online (Sandbox Code Playgroud)

您可以将您的值作为元组返回:(
如果您不使用.NET4.0,则定义您自己的元组类)

static Tuple<int, string> Fill()
{
    return new Tuple(42, "Hello World");
}
Run Code Online (Sandbox Code Playgroud)

然后定义解压缩元组的扩展方法:

public static class TupleExtensions
{
    public static void Unpack<T1, T2>(
        this Tuple<T1, T2> tuple,
        out T1 item1,
        out T2 item2)
    {
        item1 = tuple.Item1;
        item2 = tuple.Item2;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后你可以这样写:

int i;
string sz;

foo.Fill().Unpack(out i, out sz);
Run Code Online (Sandbox Code Playgroud)


why*_*why 0

我想我也许可以回答你的问题;考虑以下代码片段,其中主要的“InvokeMemberMethod”函数完成您要求的工作。我遇到了和你一样的问题并提出了这个解决方案:

注意:“isOutXX”参数指定前面的参数是否是“out”参数。

static object InvokeMemberMethod(object currentObject, string methodName, int argCount, 
        ref object arg1, bool isOut1,
        ref object arg2, bool isOut2,
        ref object arg3, bool isOut3,
        ref object arg4, bool isOut4,
        ref object arg5, bool isOut5,
        ref object arg6, bool isOut6)
    {
        if (string.IsNullOrEmpty(methodName))
        {
            throw new ArgumentNullException("methodName");
        }

        if (currentObject == null)
        {
            throw new ArgumentNullException("currentObject");
        }

        Type[] argTypes = null;
        object[] args = null;
        if (argCount > 0)
        {
            argTypes = new Type[argCount];
            args = new object[argCount];

            argTypes[0] = arg1.GetType();
            if (isOut1)
            {
                argTypes[0] = arg1.GetType().MakeByRefType();
            }
            args[0] = arg1;

            if (argCount == 2)
            {
                argTypes[1] = arg2.GetType();
                if (isOut2)
                {
                    argTypes[1] = arg2.GetType().MakeByRefType();
                }
                args[1] = arg2;
            }

            if (argCount == 3)
            {
                argTypes[2] = arg3.GetType();
                if (isOut3)
                {
                    argTypes[2] = arg3.GetType().MakeByRefType();
                }
                args[2] = arg3;
            }

            if (argCount == 4)
            {
                argTypes[3] = arg4.GetType();
                if (isOut4)
                {
                    argTypes[3] = arg4.GetType().MakeByRefType();
                }
                args[3] = arg4;
            }

            if (argCount == 5)
            {
                argTypes[4] = arg5.GetType();
                if (isOut5)
                {
                    argTypes[4] = arg5.GetType().MakeByRefType();
                }
                args[4] = arg5;
            }

            if (argCount == 6)
            {
                argTypes[5] = arg6.GetType();
                if (isOut6)
                {
                    argTypes[5] = arg6.GetType().MakeByRefType();
                }
                args[5] = arg6;
            }
        }

        MethodInfo methodInfo = currentObject.GetType().GetMethod(methodName, argTypes);
        int retryCount = 0;
        object ret = null;
        bool success = false;
        do
        {
            try
            {
                //if (methodInfo is MethodInfo)
                {
                    Type targetType = currentObject.GetType();
                    ParameterInfo[] info = methodInfo.GetParameters();
                    ParameterModifier[] modifier = new ParameterModifier[] { new ParameterModifier(info.Length) };
                    int i = 0;
                    foreach (ParameterInfo paramInfo in info)
                    {
                        if (paramInfo.IsOut)
                        {
                            modifier[0][i] = true;
                        }
                        i++;
                    }
                    ret = targetType.InvokeMember(methodName, BindingFlags.InvokeMethod, null, currentObject, args,
                        modifier, null, null);
                    //ret = ((MethodInfo)methodInfo).Invoke(currentObject, args,);
                    success = true;
                }
                //else
                {
                    // log error
                }
            }
            catch (TimeoutException ex)
            {

            }
            catch (TargetInvocationException ex)
            {
                throw;
            }
            retryCount++;
        } while (!success && retryCount <= 1);

        if (argCount > 0)
        {
            if (isOut1)
            {
                arg1 = args[0];
            }

            if (argCount == 2)
            {
                if (isOut2)
                {
                    arg2 = args[1];
                }
            }

            if (argCount == 3)
            {
                if (isOut3)
                {
                    arg3 = args[2];
                }
            }

            if (argCount == 4)
            {
                if (isOut4)
                {
                    arg4 = args[3];
                }
            }

            if (argCount == 5)
            {
                if (isOut5)
                {
                    arg5 = args[4];
                }
            }

            if (argCount == 6)
            {
                if (isOut6)
                {
                    arg6 = args[5];
                }
            }
        }

        return ret;

    }




    public int OutTest(int x, int y)
    {
        return x + y;
    }

    public int OutTest(int x, out int y)
    {
        y = x + 1;
        return x+2;
    }

    static void Main(string[] args)
    {
        object x = 1, y = 0, z = 0;
        Program p =  new Program();
        InvokeMemberMethod(p, "OutTest", 2, 
            ref x, false, 
            ref y, true, 
            ref z, false,
            ref z, false,
            ref z, false,
            ref z, false);
    }
Run Code Online (Sandbox Code Playgroud)