在 C# 中是否有与 Python 中等效的解包操作
Is there an equivalent unpacking operation in C# as in Python
在下面的 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);
你不能这样做的根本原因是,正如评论中提到的,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[]
否则转换将抛出。同样,这是一个玩具示例来说明什么是可能的。你绝对不想在生产代码中做这样的事情。
您可以使用扩展方法解决问题。这些方法将采用单个值或数组并添加额外的项目,如 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)
在下面的 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);
你不能这样做的根本原因是,正如评论中提到的,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[]
否则转换将抛出。同样,这是一个玩具示例来说明什么是可能的。你绝对不想在生产代码中做这样的事情。
您可以使用扩展方法解决问题。这些方法将采用单个值或数组并添加额外的项目,如 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)