简体   繁体   English

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

[英]Practical Reasons to use C# “named arguments”

I find this feature "named arguments" from C# to be really weird because I see two flaws from it. 我发现C#中的“命名实参”功能真的很奇怪,因为我发现它有两个缺陷。 The book says "named arguments give you the "ability to pass arguments in any order". 该书说“命名参数使您具有“以任何顺序传递参数的能力”。

Two flaws I think is a problem for this C# feature: 我认为此C#功能存在两个缺陷:

  1. It violates "information hiding" in computer science. 它违反了计算机科学中的“信息隐藏”。 (ie: the end user using the method needs to know the parameter name and data type to make use of the feature.) Coming from a Java background, this is weird. (即:使用该方法的最终用户需要知道参数名称和数据类型才能使用该功能。)来自Java背景,这很奇怪。 Why expose parameter names to the end of the user? 为什么将参数名称公开给用户?

  2. It is prone to ambiguity which can lead to bugs. 容易产生歧义,这可能导致错误。 (The programmer needs to do extra thinking and problems can creep up when the programmer wind up writing methods that use the same method name(aka overloading methods"). You will always get a "call is ambiguous when you have two methods with same name with the same parameters for each other even if the other method has a extra parameters with different data types. The only fix I can think of is to make the data type a "mandatory parameter" aka a parameter without a default value so the compiler does not get confused. But then this fix is only a bandage solution to leads to another worst case scenario (see below) (程序员需要做更多的思考,当程序员用相同的方法名称编写方法(又名重载方法)时,问题会逐渐蔓延。当您拥有两个名称相同的方法时,您总是会得到一个“歧义”即使另一种方法具有不同数据类型的额外参数,也可以使用彼此相同的参数。我能想到的唯一解决方法是使数据类型成为“强制参数”,也就是没有默认值的参数,因此编译器可以不会感到困惑。但是,此修复程序只是绷带解决方案,可导致另一种最坏的情况(请参见下文)

Do people in the industry even use this concept to this day? 迄今为止,行业内的人们是否还在使用这个概念? If so, why break the two rules to be given the "ability to pass arguments in any order when calling the method"? 如果是这样,为什么要打破这两个规则,即“在调用该方法时可以以任何顺序传递参数”?

TLDR: An Example to bring clarity to what I am talking about by introducing a possible worst case scenario(the compiler chose the wrong method call... despite resemblance of the two methods): 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");

        }


    }
}

Named arguments is yet another piece of technology that was added to make interoperability with COM (and similar technologies) easier. 命名参数是增加的另一项技术,可简化与COM(和类似技术)的互操作性。

Take the method to open a Word document using COM : 采用使用COM打开Word文档的方法

Document Open(
    [In] ref object FileName, 
    [In, Optional] ref object ConfirmConversions, 
    [In, Optional] ref object ReadOnly, 
    [In, Optional] ref object AddToRecentFiles, 
    [In, Optional] ref object PasswordDocument, 
    [In, Optional] ref object PasswordTemplate, 
    [In, Optional] ref object Revert, 
    [In, Optional] ref object WritePasswordDocument, 
    [In, Optional] ref object WritePasswordTemplate, 
    [In, Optional] ref object Format, 
    [In, Optional] ref object Encoding, 
    [In, Optional] ref object Visible, 
    [In, Optional] ref object OpenAndRepair, 
    [In, Optional] ref object DocumentDirection, 
    [In, Optional] ref object NoEncodingDialog, 
    [In, Optional] ref object XMLTransform
);

It has no less than 16 parameters, 15 of which are optional. 它具有不少于16个参数,其中15个是可选的。

What if you want to specify the XMLTransform parameter but don't care about the rest? 如果您想指定XMLTransform参数但不关心其余部分怎么办?

You would have to specify the rest with positional arguments. 您将必须使用位置参数指定其余部分。 With named arguments the call simply becomes: 使用命名参数,调用将简单地变为:

doc.Open("somefilename.doc", XMLTransform: xxx);

Along with dynamic and a few other things, it wasn't meant to be a good solution to a lot of problems but when you have an API that relies heavily on methods with lots and lots of parameters, most of which are optional, named arguments makes sense. 除了dynamic和其他一些功能外,它并不是解决许多问题的好方法,但是当您使用的API严重依赖具有很多参数的方法时,其中大多数是可选的,命名参数说得通。

Yes, you can specify arguments out of order. 是的,您可以指定乱序的参数。 It doesn't mean it's a good idea or that it solves a problem someone really had. 这并不意味着它是一个好主意,也不意味着它可以解决某人确实遇到的问题。

I find your first argument completely specious. 我发现你的第一个论点完全是似是而非。 Like it or not the names of parameters are part of each method's semantics, particularly for abstract classes and methods that will be overridden in subclasses. 不管是否喜欢,参数名称都是每种方法语义的一部分,尤其是对于抽象类和将在子类中覆盖的方法。 The names of the parameters are a key signalling to users of a method on the semantics of that method, and of each parameters role in that semantics. 参数的名称是向用户告知该方法的语义的关键信号,并且每个参数在该语义中的作用。 Further it is essential for understanding of the semantics throughout the class hierarchy that parameter names be consistent, and not subject to the whims of individual programmers at each level. 此外,对于理解整个类层次结构的语义而言,至关重要的是,参数名称必须一致,并且不受每个级别的各个程序员的异想天开。

Your second argument I find completely unintelligible. 我发现您的第二个论点完全难以理解。 If you actually have a valid point here I suggest you rewrite this to achieve greater clarity. 如果您在这里确实有一个有效的观点,我建议您重写此观点以提高清晰度。

That said, I rarely use named parameters in my method calls; 也就是说,我很少在方法调用中使用命名参数。 the exception being for methods that accept more than two consecutive parameters of the same type. 接受两个以上相同类型连续参数的方法除外。 In this case I like to name them so that I, as the future reader of the code, can in fact decipher the method's use without having to constantly hover to see the intelli-sense. 在这种情况下,我想为它们命名,以便作为代码的未来读者,我实际上可以解密该方法的用法,而不必不断地悬停以查看智能感知。

1) I don't understand where "information hiding" lies there ; 1)我不知道“信息隐藏”在哪里; a method signature is what you ask the end user to give you. 方法签名是您要求最终用户给您的。 He obviously needs to know the data type and name to disambiguate why argument refers to what. 他显然需要知道数据类型和名称,以消除参数为何指代什么的歧义。 Also he still doesn't know what you gonna do with those parameters you asked for (maybe nothing) so what needs to be hidden from him is still hidden. 而且,他仍然不知道您要使用那些您要的参数做什么(也许什么也没有),因此需要隐藏的内容仍然隐藏。

2) the problem here is in a bad choice for two overloads which differ only by number of arguments, that combined with the ability to omit certain arguments (provided by optional arguments) makes you lose the "benefit" to distinguish them (unless you give all the arguments) 2)对于两个仅因参数数量不同而导致的重载,这里的问题是一个不好的选择,再加上省略某些参数(由可选参数提供)的能力,会使您失去区分它们的“好处”(除非您给出所有参数)

Named parameters were (partly) introduced with dynamic for interop scenario ; 为interop场景引入了(部分)动态命名的参数; for example with Office Automation where in C#3 you needed to add a bunch of Type.Missing arguments and then in C#4 you can just provide those you want/need. 例如,在Office Automation中,在C#3中您需要添加一堆Type.Missing参数,然后在C#4中,您只需提供所需/需要的参数即可。

The point about COM inter-op is most important. 关于COM互操作的要点是最重要的。

Personally I tend to use it if I have a boolean parameter in the method signature that I want to use but there is no obvious variable that I can use. 如果我在方法签名中有一个布尔参数想要使用,但是我没有明显的变量可以使用,我个人倾向于使用它。 Example: 例:

I find more readable 我觉得更具可读性

var isSuccessful = myObject.Method(isRecursive: true)

then 然后

var isSuccessful = myObject.Method(true);

eventually you could more verbose syntax 最终您可以使用更详细的语法

var isRecursive = true;
var isSuccessful = myObject.Method(isRecursive);

to avoid named parameter. 避免命名参数。

Obvious disadvantage of calling methods like that is if for some reason signature of the method changes, you code will no longer build. 这样调用方法的明显缺点是,如果由于某种原因方法的签名发生更改,您的代码将不再生成。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM