为什么可选参数必须出现在声明的末尾

时间:2010-05-24 10:03:15

标签: c# java language-agnostic language-design optional-parameters

在支持可选参数的所有编程语言中,我都看到可选参数必须出现在声明的末尾。可选项目后可能不包含必需参数。 这是什么原因?我想它可能是编译器/解释器的要求。

6 个答案:

答案 0 :(得分:16)

嗯,如果他们在前面,你会怎么检测他们什么时候停止供应?唯一的方法是在可选参数后变量类型不同。这是一个奇怪的要求,所以你只需强制它们是最后一个是有道理的(省去​​了检测“最终”可选参数的复杂规则的麻烦)。

此外,在调用函数时,这是最自然的方式。

答案 1 :(得分:6)

这只是这些特定语言的设计者制定的任意规则。绝对没有技术上的理由说明为什么会出现这种限制。

它在Ruby中运行得很好:

def foo(m1, m2, o1='o1', o2='o2', *rest, m3, m4)
  return m1, m2, o1, o2, rest, m3, m4
end

foo(1, 2, 3, 4)
# => [1, 2, 'o1', 'o2', [], 3, 4]

foo(1, 2, 3, 4, 5)
# => [1, 2, 3, 'o2', [], 4, 5]

foo(1, 2, 3, 4, 5, 6)
# => [1, 2, 3, 4, [], 5, 6]

foo(1, 2, 3, 4, 5, 6, 7)
# => [1, 2, 3, 4, [5], 6, 7]

foo(1, 2, 3, 4, 5, 6, 7, 8)
# => [1, 2, 3, 4, [5, 6], 7, 8]

必须提供所有必须参数:

foo(1, 2, 3)
# => ArgumentError: wrong number of arguments (3 for 4)

如果没有rest参数,提供超过number_of_mandatory + number_of_optional参数是错误的:

def bar(m1, m2, o1='o1', o2='o2',  m3, m4)
  return m1, m2, o1, o2, m3, m4
end

bar(1, 2, 3, 4, 5, 6, 7)
# => ArgumentError: wrong number of arguments (7 for 6)

参数列表开头的必需参数从参数列表的开头从左到右绑定。参数列表末尾的必需参数从参数列表的末尾开始从右到左绑定。可选参数从剩余参数列表的开头从左到右绑定。剩下的所有论据都必然会有其他论点。

答案 2 :(得分:3)

考虑如下声明:

int foo(float a, int b=0, int c=0, float d);

(请注意我如何在列表中间定义defult参数),随后将其称为

foo(0.0,1,2.0)

电话是什么?特别是bc被省略了吗?

编译器设计人员可以使用命名参数来解决这个问题

foo(a=0,c=0,d=2.0)

例如python中可用的功能。

答案 3 :(得分:0)

只是在疯狂地猜测:它可能与调用约定有关(例如,参数从左到右被推到堆栈中,如果没有指定,则可以省略可选参数。)

答案 4 :(得分:0)

最后的可选参数允许您在某个时刻停止指定参数,例如

void Test(int a, optional int b = 0, optional int c = 0) { ... } 

Test(3);

如果您使c成为必需参数,则必须使用以下语法:

Test(3, , 2);
Test(a := 3, c := 2);

可选参数的优点是可以将其视为它不存在。如果可选参数位于参数列表的中间,则在没有“计算逗号”或使用过于冗长的语法的情况下,这是不可能的。

答案 5 :(得分:-1)

Java和C#没有命名参数,所以你不能这样做:

myfunction(param1='Meh', optionalParam=2)

你必须这样做:

myfunction('Meh', 2)

否则

myFunction(2, 'Meh')

含糊不清。编译器应该如何知道你的意思是2在可选参数集中?