您认为在C#.Net 4.0中添加了什么值的命名和默认参数?
对于这些(在重载和覆盖时尚未实现)有什么用处?
答案 0 :(得分:4)
它可以使构造函数更简单,特别是对于不可变类型(对于线程很重要) - see here for a full discussion。不像应该那么好,但比有很多重载更好。你显然不能将对象初始化器与不可变对象一起使用,所以通常会这样:
new Foo {Id = 25, Name = "Fred"}
不可用;我会满足于:
new Foo (Id: 25, Name: "Fred")
这可以扩展到简化重载的一般想法,但在大多数情况下,我更喜欢过载宣传合法组合。构造函数有点不同,IMO,因为您只是(通常)定义初始状态。
事情的COM方面对很多人来说也很重要,但我根本就没有使用太多的COM互操作 - 所以这对我来说不是 。
编辑评论;为什么他们只使用属性使用的相同语法?简单 - 它可能与其他成员/变量不一致(这不是属性的问题);举个例子:
[XmlElement("foo", Namespace = "bar")]
使用一个常规参数(对ctor,“foo”)和一个命名赋值。因此,假设我们将此用于常规命名参数:
SomeMethod("foo", SecondArg = "bar");
(也可能是构造函数;为简单起见,我使用了一种方法)
现在......如果我们有一个名为SecondArg
的变量或属性怎么办?使用SecondArg
作为SomeMethod
的命名参数,将“bar”分配给SecondArg
,并将“bar”作为常规参数传递之间的含义不明确
为了说明这一点,这在C#3.0中是合法的:
static void SomeMethod(string x, string y) { }
static void Main()
{
string SecondArg;
SomeMethod("foo", SecondArg = "bar");
}
显然,SecondArg可以是属性,字段,变量等......
替代语法没有这种歧义。
<小时/> 编辑 - 280Z28的这一部分:很抱歉在这里添加这个,但它并不是一个独特的答案,它对于评论来说太长了,包括代码。你暗示了模棱两可,但你的例子没有强调决定性案例。我认为你给出的例子指出了可能令人困惑的事情,但是所需的
{}
对象初始化器可以防止潜在的语法模糊。我对以下代码的解释是作为多行块注释嵌入的。
[AttributeUsage(AttributeTargets.Class)]
public sealed class SomeAttribute : Attribute
{
public SomeAttribute() { }
public SomeAttribute(int SomeVariable)
{
this.SomeVariable = SomeVariable;
}
public int SomeVariable
{
get;
set;
}
}
/* Here's the true ambiguity: When you add an attribute, and only in this case
* there would be no way without a new syntax to use named arguments with attributes.
* This is a particular problem because attributes are a prime candidate for
* constructor simplification for immutable data types.
*/
// This calls the constructor with 1 arg
[Some(SomeVariable: 3)]
// This calls the constructor with 0 args, followed by setting a property
[Some(SomeVariable = 3)]
public class SomeClass
{
}
答案 1 :(得分:1)
这将有助于避免提供合适的API来使用Office应用程序的问题! :)
Office API的某些部分是可以的,但是有一些边缘情况明确设计为可以从具有可选/命名参数的语言中使用。所以这就是C#必须拥有它们的原因。
答案 2 :(得分:1)
可选参数还可以避免类提供许多方法的问题,这些方法只是接受的参数的变体。
考虑Exception类。它不是一个带有可选参数的构造函数,而是为'has message'和'具有内部异常'的每个组合提供了四个构造函数。那没关系,但是现在考虑一下如果你为一个带有innerException的构造函数提供一个空值会发生什么?它是否与没有innerException参数的构造函数完全相同,类似于没有innerException参数的构造函数,或者是否抛出空引用异常?
具有2个可选参数的单个构造函数会更明显地传递null innerException等同于根本不包含它。默认参数的理想位置。
另外不要忘记现在每个派生的Exception类也必须包含4个构造函数,这是一个毫无意义的麻烦。
答案 3 :(得分:0)
它将使COM互操作变得更加容易。
直到C#4 VB.Net是一个更好的互操作语言。如果没有默认值,您可以在C#中使用大量的伪引用参数列表。
答案 4 :(得分:0)
代码的简洁性是人们想到的明显的代码。为什么在定义一个函数时定义几个重载。但是,如果您有两个相同类型的参数,则无法始终构建您可能需要的完整重载集。
答案 5 :(得分:0)
这也不能编译:
[AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
sealed class MyAttribute : Attribute
{
public MyAttribute(object a = null)
{
}
}
class Test
{
[My] // [My(a: "asd")]
int prop1 { get; set; }
}
虽然这样做:
[AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
sealed class MyAttribute : Attribute
{
public MyAttribute()
{
}
public object a { get; set; }
}
class Test
{
[My] // [My(a=null)]
int prop1 { get; set; }
}