C# 中是否有与 Python 中等效的解包操作

问题描述 投票:0回答:2

在下面的 python 示例中,我们有一个函数,它接受可变数量的非关键字参数和可能的函数调用:

def print_numbers(*list_of_numbers):
    for i in list_of_numbers:
        print(i)
        

print_numbers(1,2,3,4, *[5,6], *[7,8], 9)

在 C# 中,我们有 params 关键字,它允许可变数量的参数。现在我很好奇在 C# 中我们是否可以想出与 Python 类似的东西。以下示例显示了我与所需用法的接近程度。

void Foo(params int[] liste)
{
    foreach(var item in liste)
    {
        Console.WriteLine(item);
    }
}


var array = new int[] {1, 2, 3, 4};

// allowed
Foo(array);

// compiler error CS1503
// Foo(array, 5, 6);
python c# parameters arguments
2个回答
2
投票

可以通过扩展方法来解决问题。这些方法将采用单个值或数组,并添加附加项目,如

params
:

public static class MixedParamsExtensions
{
    public static T[] Pack<T>(this T item, params T[] args)
    {
        var ret = new T[args.Length + 1];
        ret[0] = item;
        Array.Copy(args, 0, ret, 1, args.Length);
        return ret;
    }

    public static T[] Pack<T>(this T[] array, params T[] args)
    {
        var ret = new T[array.Length + args.Length];
        Array.Copy(array, 0, ret, 0, array.Length);
        Array.Copy(args, 0, ret, array.Length, args.Length);
        return ret;
    }
}

给出这个方法:

public static void print_numbers(params int[] args)
{
    foreach (var item in args) {
        Console.WriteLine(item);
    }
}

您可以拨打电话:

print_numbers(1.Pack(2, 3, 4).Pack(new[] { 5, 6 }).Pack(new[] { 7, 8 }).Pack(9));

这是我能想到的最接近Python的等价物:

print_numbers(1,2,3,4, *[5,6], *[7,8], 9)

C# 12添加了集合表达式。您可以编写以下等效代码:

int[] a = [5, 6];
int[] b = [7, 8];
print_numbers([1, 2, 3, 4, .. a, .. b, 9]);

上面链接的文档说:您使用 spread 元素

..
在集合表达式中内联集合值。


0
投票

你不能这样做的根本原因是因为,正如评论中提到的,

int
int[]
不是同一类型。

您可以通过模仿您想要的行为的

object
dynamic
类型做一些非常古怪和可怕的事情来解决这个问题。我不会推荐这个,我只是添加一个答案来展示什么是可能的,而不是什么是更好的。

void Foo(params object[] liste)
{
    foreach(var item in liste)
    {
        if (item.GetType().IsArray)
        {
            foreach (var arrayItem in (int[])item )
            {
                 Console.WriteLine(arrayItem);   
            }
        }
        else
        {
            Console.WriteLine(item);
        }     
    }
}


var array = new int[] {1, 2, 3, 4};

// allowed
Foo(array, 5, 6);

这做出了一个关键的假设......你的数组必须是

int[]
,否则转换将会抛出。同样,这是一个玩具示例,旨在说明什么是可能的。你永远不会想在生产代码中做这样的事情。

© www.soinside.com 2019 - 2024. All rights reserved.