通用参数的动态长度

时间:2013-06-07 10:29:52

标签: c# .net generics

我编写了一个获取对象数组的方法,将数组内容的类型作为泛型,并尝试将每种类型转换为传递的泛型:

    public static void GetMultipleObjectsFromParameters<T, U>(
        object parameterArray, out T parameter1, out U parameter2)
    {
        parameter1 = default(T);
        parameter2 = default(U);

        try
        {
            object[] arr = parameterArray as object[];

            if (arr == null)
            {
                Debug.WriteLine("array not valid");
                return;
            }
            if (arr.Length != 2)
            {
                Debug.WriteLine("arr.Length != 2");
                return;
            }

            parameter1 = (T)arr[0];
            parameter2 = (U)arr[1];
        }
        catch (Exception ex)
        {
            Debug.Write(ex);
        }
    }

我认为如果我使用BackgroundWorker并希望提供不同类型的多个参数(例如,第一个参数为字符串,第二个为整数......),这个方法可能非常有用。

现在我想知道是否有办法在不强制固定大小的参数的情况下编写此方法。这将阻止我为每个参数计数编写这样的方法。

我希望这个问题是可以理解的。有一个简单的方法吗?谢谢你的帮助。

2 个答案:

答案 0 :(得分:5)

编辑:这个答案解决了原始问题而不是背后的动机。在将工作传递给BackgroundWorker等方面,使用lambda表达式非常有意义。

  

现在我想知道是否有办法在不强制固定大小的参数的情况下编写此方法。

不,我不敢。您正在寻找的是更高阶的类型,我认为 1 - 但它们在.NET中不存在(这就是为什么有这么多“通用的arity重载“对于Func<>Tuple<>Action<>等。


1 说实话,我自己对这些事情了解不多。 Joe Duffy有一个blog post让我大吃一惊,但这可能很有用。

答案 1 :(得分:2)

  

如果有办法编写此方法而不强制使用固定大小的参数

您不需要使用可变大小的参数编写此方法。您需要Tuple

        var myParams = Tuple.Create(100, "Hello, world!");
        var worker = new BackgroundWorker();

        worker.DoWork += (sender, args) =>
        {
            var arg = (Tuple<int, string>)args.Argument;
            if (arg.Item2.Length > 5)
            {
                var foo = arg.Item1 + 200;
            }

            // etc ...
        };

        worker.RunWorkerAsync(myParams);
带有闭包的

lambdas

        var someIntParam = 100;
        var someStringParam = "Hello, world!";

        var worker = new BackgroundWorker();
        worker.DoWork += (sender, args) =>
        {
            if (someStringParam.Length > 5)
            {
                var foo = someIntParam + 200;
            }

            // etc ...
        };

        worker.RunWorkerAsync();

这取决于您如何在实际代码中使用BackgroundWorker