C# 使用C“命名参数”的实际原因

C# 使用C“命名参数”的实际原因,c#,methods,parameters,arguments,optional-parameters,C#,Methods,Parameters,Arguments,Optional Parameters,我发现这个名为arguments from C的特性非常奇怪,因为我从中看到了两个缺陷。这本书说,命名参数使您能够以任何顺序传递参数 我认为此C功能存在两个缺陷: 它违反了计算机科学中的信息隐藏。 i、 e:使用该方法的最终用户需要知道参数名称和数据类型才能使用该功能。来自Java背景,这很奇怪。为什么要将参数名称公开给用户 它容易产生歧义,从而导致错误。 程序员需要做额外的思考,当程序员编写使用相同方法名的方法时,问题可能会慢慢出现。如果有两个名称相同、参数相同的方法,即使另一个方法有一个具有

我发现这个名为arguments from C的特性非常奇怪,因为我从中看到了两个缺陷。这本书说,命名参数使您能够以任何顺序传递参数

我认为此C功能存在两个缺陷:

它违反了计算机科学中的信息隐藏。 i、 e:使用该方法的最终用户需要知道参数名称和数据类型才能使用该功能。来自Java背景,这很奇怪。为什么要将参数名称公开给用户

它容易产生歧义,从而导致错误。 程序员需要做额外的思考,当程序员编写使用相同方法名的方法时,问题可能会慢慢出现。如果有两个名称相同、参数相同的方法,即使另一个方法有一个具有不同数据类型的额外参数,但调用总是不明确的。我能想到的唯一修复方法是将数据类型设置为强制参数,即没有默认值的参数,这样编译器就不会感到困惑。但是,这种修复方法只是一种绷带解决方案,会导致另一种最坏的情况,见下文

直到今天,业内人士都在使用这个概念吗?如果是这样,为什么要打破这两条规则,以便在调用方法时能够以任意顺序传递参数

TLDR:一个例子,通过介绍可能出现的最坏情况,使我所说的更加清晰。编译器选择了错误的方法调用。。。尽管两种方法相似:

namespace ConsoleApplication1
{
    class Venusaur
    {
        static void Main(string[] args)
        {

            new Venusaur().optMethod(fourth: "s");
        }

        public void optMethod(  string third , string fourth =  "hello", int fifth = 23, string two = "w")
        {
            // what if I wanted this method to run instead of the method below me
            Console.WriteLine("did not execute");
        }


        public void optMethod(string third = "Byte", string fourth = "hello",  int fifth = 4)
        {
            // But this method ran instead
            Console.WriteLine("run");

        }


    }
}

我觉得你的第一个论点完全似是而非。不管喜欢与否,参数的名称都是每个方法语义的一部分,特别是对于将在子类中重写的抽象类和方法。参数的名称是向方法用户发出的关于该方法语义以及该语义中每个参数角色的关键信号。此外,为了理解整个类层次结构的语义,参数名称必须保持一致,并且不受每个级别的单个程序员的突发奇想的影响

我觉得你的第二个论点完全无法理解。如果你在这里有一个正确的观点,我建议你重写它,以达到更清晰的目的


也就是说,我很少在方法调用中使用命名参数;接受两个以上相同类型的连续参数的方法除外。在这种情况下,我喜欢给它们命名,这样,作为代码的未来读者,我实际上可以破译该方法的用法,而不必不断地悬停以查看智能感知。

命名参数是另一项技术,它的加入使得与COM和类似技术的互操作更加容易

以:

它有不少于16个参数,其中15个是可选的

如果您想指定XMLTransform参数,但不关心其他参数,该怎么办

您必须使用位置参数指定其余部分。使用命名参数时,调用将变为:

doc.Open("somefilename.doc", XMLTransform: xxx);
除了动态和其他一些东西之外,它并不是解决很多问题的好方法,但是当你有一个API,它严重依赖于有很多很多参数的方法,其中大多数是可选的,命名参数是有意义的


是的,您可以无序指定参数。这并不意味着这是一个好主意,也不意味着它解决了某人真正遇到的问题。

1我不明白信息隐藏在哪里;方法签名是您要求最终用户提供给您的。他显然需要知道数据类型和名称,以消除为什么参数指的是什么。而且他仍然不知道你将如何处理那些你要求的参数,也许什么都不知道,所以需要对他隐藏的东西仍然是隐藏的

2这里的问题是,对于两个只因参数数量不同而不同的重载,选择不当,再加上省略可选参数提供的某些参数的功能,使您失去了区分它们的优势,除非您给出了所有参数


命名参数部分引入了互操作场景的动态参数;例如,对于Office Automation,在C3中,您需要添加一组类型.缺少的参数,然后在C4中,您可以只提供您想要/需要的参数。

关于COM交互的一点是最重要的

就我个人而言,如果我想要使用的方法签名中有一个布尔参数,但没有明显的变量可以使用,我倾向于使用它。 例如:

我觉得更有可读性

var isSuccessful = myObject.Method(isRecursive: true)
然后

最终,您可以使用更详细的语法

var isRecursive = true;
var isSuccessful = myObject.Method(isRecursive);
避免使用命名参数


这样调用方法的明显缺点是,如果由于某种原因方法的签名发生了更改,代码将不再生成

如果要运行optMethod的第一个声明,则需要显式指定第三个变量:new Venusaur.optMethodthirdStr,fo
urth:s;我不确定这个问题是否会在这个主题上得到考虑。然而,为了回答你的问题:使用命名参数是非常不寻常的,尽管在C中是允许的。我能回忆起的唯一真实世界的例子是XNA和MonoGame,老实说,它看起来既丑陋又怪异,我认为他们本可以做得更好。@jsve显式指定第三个变量不起作用,因为两个方法的参数名相同,所以编译器会感到困惑。它将产生歧义方法调用错误。我已经尝试过这个代码:new Venusaur.optMethodthird:thirdStr,fourth:s;不太清楚您是如何突出显示响应和回复的代码的。参数名称不是方法签名的一部分。根据C规范3.6:方法的签名包括方法的名称、类型参数的数量以及每个形式参数的类型和种类值、引用或输出,按从左到右的顺序考虑。虽然重载解析将使用参数名来查找符合条件的方法。@Theodoroschatziganakis:我已将签名更改为语义,因为这符合您提出的技术要点,并更清楚地说明了我的论点的意图。然而,正如Lasse Karlsen所指出的,参数名也没有完全排除在编译器对代码的解释之外。@PieterGeerkens说得很对。我要么重新思考我说的第二部分,要么接受C语言的怪癖。只是Java没有命名参数这一特性,使用它仍然是外来的。
var isSuccessful = myObject.Method(true);
var isRecursive = true;
var isSuccessful = myObject.Method(isRecursive);