为什么params关键字不是上下文相关的?

6

我问的原因是,它只在方法参数声明中有效,对吧?我试图在函数体内创建一个名为“params”的变量,但这当然不是什么大问题,只是想知道微软为什么选择将其作为全局关键字而不是上下文关键字。


3
不确定为什么要这样做,但如果你真的想在C#中使用它作为变量名,需要在变量名前面加上@符号:int @params = 1; - Derrick
4个回答

9
同样的问题也可以问到其他任何关键字。例如,“class”为什么不是上下文相关的,因为它只用于类声明中?
对我来说,关键字就是关键字。我想这大大简化了编译的词法分析部分,不需要那么上下文感知。
另外,您可以使用“@”符号来允许您声明一个名为“params”(或任何其他保留关键字)的变量:
var @params = new int[] { 1, 2 };

谢谢,但如果类是上下文相关的,那么如何分离嵌套类的使用呢?但是对于参数来说,没有其他地方可以使用它,似乎很容易区分它们,但我不像Eric Lippert那样是编译器大师。 - Joan Venge
我认为你可以尝试通过查找典型的类声明语法来使“class”具有上下文意义:[可访问性修饰符] class [类名] {}。但是,我对编译器规范不够了解,无法确定这是否可行。 - Adam Lear
1
假设“class”是有上下文的。 假设您有“class class {} class get {} class C {public class D {get” - 此时您不知道D是否是一个嵌套类声明,其字段(或方法)类型为“get”,名称缺失,还是D是类型为“class”的属性,其getter体缺失。 这些情况显然是人为制造的,但如果我们支持该功能,则必须针对所有可能的这种情况提供合理的错误。 这需要大量的分析、大量的规范编写和大量的测试,而这个功能几乎没有什么好处。 - Eric Lippert
1
顺便提一下,当我在VBScript 5中添加类时,我们确实将“Class”作为VBScript中的新保留字,而不是使其成为上下文相关的。 VBScript的语法和语义使得很难确定“Class Foo”是类的引入,还是带有参数“Foo”的过程“Class”的调用。不得不添加一个新的保留字令人烦恼,但其他选择被认为更糟糕。 - Eric Lippert
谢谢Eric,你的想法正是我所思考的,“class”关键字是有上下文语境的。 - Joan Venge

5

tvanoffson的回答认为使“params”具有上下文意义很难。实际上,并不是那么难。考虑以下内容:

void M(params x)

假设在这种情况下,我们需要首先尝试查找类型'params'。如果我们可以找到一个,那太好了,我们完成了。如果不能找到,则有一点问题。例如,假设x的位置被替换掉了。

void M(params Int32)

显然这是一个错误,但是是什么错误?我们应该假设Int32是参数名称并给出错误“您缺少类型”吗?我们应该假设Int32是类型并给出错误,指出类型必须是数组类型,并且您缺少标识符吗?我们应该给出一个错误,指出没有名为“params”的类型吗?在这里该怎么做才是正确的?显然,我们可以想出一些东西,但并不明显。
对于上下文关键字来说,棘手的是错误情况;使成功案例工作实际上非常简单。
但是实际上,使其成为上下文关键字并不是一件很大的胜利。使“set”和“value”成为上下文关键字是一个巨大的胜利,因为我们假设所有人都想使用名称为“set”和“value”的局部变量。 “params”甚至不是一个英语单词,因此似乎不太可能有人想要使用它。没有使它成为上下文关键字的重大好处,因此该功能的成本无法证明。

谢谢Eric。我真的很希望能读到你的想法。对我来说,似乎有效的情况有1.是否有params类型可用?2.如果没有,则必须有一个形式为Type[]的类型,后跟一个标识符。像你这样的专家,你认为这是否涵盖了所有情况?另外,你是对的,这不是一个英语单词,只是想在某些代码中有用,而不是写参数/(s)。 - Joan Venge

4
Eric Lippert有一篇博客文章,涵盖了上下文关键字和保留关键字(contextual and reserved keywords)及其历史。尽管它没有明确解释为什么params在保留列表中(自1.0以来就是这样),但它表明它属于难以使上下文相关的保留词之一。

谢谢,这就是保留字的作用吗?我以为它意味着将来保留给新的潜在用途? - Joan Venge
2
@Joan - 有些可能是,但大多数都是“保留”的,即“仅用于此目的保留”。 - tvanfosson

2

看起来,params关键字只在方法参数声明中有用,但我同意微软的观点,不应该让关键字用于实例名称。也许他们保留了在C#8.0中使用类似功能的能力:

params Customers = DB.GetCustomerList();

或者在本地作用域中也允许params.


但那会有什么作用呢?对我来说,像你展示的在本地范围内使用它并没有太多意义,不是吗?我不确定。顺便问一下,C# 8.0什么时候发布啊?:O - Joan Venge
1
我认为如果我的水晶球准确的话,应该是在2017年左右。 - Anonymous Type
1
Joan - 很好的问题。我不知道那会做什么。事实上,我认为由于语法错误,那行代码甚至无法在C# 8.0中编译。 - Flipster

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接