命名参数何时有用?

在C#代码中是否存在位置参数不足的情况? 我真的没有看到命名参数的任何好处,相反我可以看到过度使用命名参数会使代码难以阅读? 所以我的问题是,为什么有人会使用它们,它们如何帮助编写更好的代码,因为我确信它们没有理由没有实现?

这看起来更干净:

private void Foo(1, true); 

然后:

 private void Foo(bar: 1, baz: true); 

命名参数旨在提高可读性。 例如,我刚刚使用了一个

 public void MarkAsDone(bool skipped) {} 

现在通过调用没有名称的方法,我们有一个歧义

 MarkAsDone(true); //does true mean that it is successfully done? 

可以通过使用名称澄清来解决

 MarkAsDone(skipped: true); 

我认为使用命名参数会使客户端代码变得不那么模糊。

它是一个部分,当有多个具有相同类型的可选参数时,它们可用于唯一地标识可选参数

 MarkAsDone(int first, int second=0, int third=0) {} /// MarkAsDone(1, third: 3); 

我使用命名参数使呼叫站点更清晰,当我有默认值的参数时。 已经在许多不同的答案中讨论了默认值的情况,所以我们来谈谈呼叫站点的清晰度。

使用metasyntactic变量进行分析并不会突出其有用性。 考虑一下,如果你愿意的话,这更像是“现实世界”。

我们来看一个呼叫网站:

 something.OpenFile(documentPath, true); 

这是怎么回事? 它将打开documentPath 。 还有别的吗? 还有什么? 我不记得了,即使我一周前写过OpenFile

以下是OpenFile三个不同的相对现实的示例。

 void OpenFile(string path, bool shouldOverwrite) void OpenFile(string path, bool preserveExisting) void OpenFile(string path, bool enableWriting) 

使用命名参数,我们可以使呼叫站点清晰:

 something.OpenFile(documentPath, shouldOverwrite: false); 

很明显,文件不会被覆盖。

 something.OpenFile(documentPath, preserveExisting: false); 

很明显,如果需要,文件被覆盖。

最后,我们有:

 something.OpenFile(documentPath, enableWriting: false) 

很明显,该文件只能打开阅读。

这个特定的例子可以用枚举等其他东西来解决吗? 是。 你能不能改变代码? 没有。其他人对bool参数有同样的持久仇恨吗? 编号:-)

你可以用命名参数来做吗? 是。 好的本地变量名有用吗? 极大。

当我们需要使用这样的方法时,我们发现了一个非常有趣的命名参数用法:

 private void ShowPopup(FrameworkElement content, string title = "My Application", bool isDialog = true, double? width = null, double? height = null, double? offsetX = null, double? offsetY = null, bool isTransparent = false, ... etc) 

几乎所有参数都是可选的。 在某些情况下,您需要将所有这些参数保留为默认值,除了一个或几个参数,例如:

PopupHelper.ShowPopup(_view, isTransparent: true);

或类似的东西。

当使用可选参数调用方法时,它们非常有用 – 实际上是隐式需要的 – 因为当您使用可选参数调用方法时,必须指定要传递的方法,否则您必须提供最后一个所需的整个列表。使用。

给出这样的方法:

 public void Do(Thing thing, bool doItTwice = false, bool logResults = false, string something = null, bool makeTeaAfterwards = false) 

然后,您必须使用命名参数,以避免必须指定整个列表:

 Do(thing, makeTeaAfterwards: true); 

而不是:

 Do(thing, false, false, null, true); 

后者的缺点是你必须复制默认值,这会引入错误的可能性。

我不确定,但我认为你误解了命名参数。

请参阅: http : //www.dotnetperls.com/named-parameters

基本上,当您需要将大量参数发送到方法时,它们非常有用。 使用命名参数,您可以确定要发送给方法的参数

 Method1(test1: 1, ..., test20: 10); 

你应该小心使用它,因为它有很大的性能缺点。

如果你有一个方法签名,如:

 private void Foo(int bar, bool baz); 

然后命名参数没有多大帮助,没有。

但想象一下方法签名如:

 private void Foo(bool bar, int baz=0, int qux=0); 

并且说你想传递baz的默认值但是qux的参数,那么命名参数有助于:

 Foo(true, qux:1); 

这些天C#支持可选参数,例如:

 public void Dance(string song = "makarena", string location = "your house", string performer = "Michael", DateTime? date = null, int milliseconds = 0, Action callback = null) { ///party code } 

现在你可以通过跳过一些参数(以任何顺序)来调用它:

 Dance(location : "my house", date : DateTime.Now, performer : "Christina"); 

我测试了代码。 可悲的是,我没有看到克里斯蒂娜的性感舞蹈,因为我忘了设置毫秒参数:P(不是我的蜕皮,但是那些做API的人,为什么每天可能毫秒可选?:P)。

我的观点是,它的真正价值在于COM Interop和类似的情况。 例如,Office COM对象有一些方法,其中包含许多没有这些参数的参数(例如Word.Documents.Open )。

回答了一个被删除的类似问题,所以我会在这里发布..我认为尚未包括Com Call参数:

使用命名参数有一两个很好的理由。

1)使用Com调用/可选参数时

想象一下:

 var excelApp = new Microsoft.Office.Interop.Excel.Application(); excelApp.Workbooks.Add(); excelApp.Visible = true; var myFormat = Microsoft.Office.Interop.Excel.XlRangeAutoFormat.xlRangeAutoFormatAccounting1; excelApp.get_Range("A1", "B4").AutoFormat(myFormat, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing); 

在C#3.0及更早版本中,您需要为每个参数提供参数。

但是,通过使用C#4.0中引入的命名参数和可选参数,可以大大简化对AutoFormat的调用。

 excelApp.Range["A1", "B4"].AutoFormat( Format: myFormat ); 

2)命名参数可以创建更好/更清晰的代码

 File.Copy("source.txt", "destination.txt", true); 

除非您是熟悉此方法的开发人员,否则您只能猜测最后一个布尔参数的用途。 使用C#4.0命名参数,可以像这样编写代码以更清楚地表达意图:

 File.Copy("source.txt", "destination.txt", overwrite: true); 

3)它是shoprtenes代码

而是使用

 Person person = new Person(); person.FirstName = "John"; person.LastName = "Smith"; person.DateOfBirth = new DateTime(1970, 1, 1); 

你可以使用(取决于可读性偏好)

 Person person = new Person() { FirstName = "John", LastName="Smith", DateOfBirth = new DateTime(1970, 1, 1)}; 

它们可以是一个很好的意图声明,并提高可读性,其中参数是相同类型或可以隐式转换。

例如

 int Duration(d1,d2) 

那是从d1到d2还是d2 – d1? Intellisense可能会告诉您参数是否具有良好的名称,或者文档是否正确且是最新的。 或者你可以查看代码……

使用多个可选参数它们甚至更有用,避免像所有可选参数一样的规则必须是最后一个,并且必须指定所有不想使用默认值的参数。 总噩梦如果由于某种原因你需要重新考虑参数列表。 你可能想要考虑简洁和简洁之间的区别。 简洁总是好的,很少简洁。

我觉得它牺牲了紧凑性以便于阅读。 假设您有一个清除一些不需要的元素的函数。 不需要的可能是:旧的,已弃用的,未使用的:

 // unnamed: collection.remove(true, true, false) // named: collection.remove(old:true, deprecated:true, unused:false); 

当然,还有许多其他方法可以实现这一点,从按位标志到智能感知。 但是,当用Python编程时,我使用命名的params非常分配。 当然,那里没有powershell打字,而且工具更差。