C#.Net 4.0命名和默认参数

C#.Net 4.0命名和默认参数,c#,c#-4.0,C#,C# 4.0,您认为命名参数和默认参数将在C#.Net 4.0中添加什么值 对于这些(重载和重写尚未实现的)功能,有什么好的用途 这将使COM的互操作更加容易 在C#4之前,VB.Net是一种更好的互操作语言。如果没有默认设置,在C#中会有大量的伪ref参数列表。代码的简洁性是显而易见的。既然可以定义一个函数,为什么还要定义几个重载呢。另外,如果您有两个相同类型的参数,那么并不总是能够构造您可能需要的全部重载集。它可以使构造函数更简单,特别是对于不可变类型(对于线程来说很重要)-。也许没有它应该的那么好,但是

您认为命名参数和默认参数将在C#.Net 4.0中添加什么值


对于这些(重载和重写尚未实现的)功能,有什么好的用途

这将使COM的互操作更加容易


在C#4之前,VB.Net是一种更好的互操作语言。如果没有默认设置,在C#中会有大量的伪ref参数列表。

代码的简洁性是显而易见的。既然可以定义一个函数,为什么还要定义几个重载呢。另外,如果您有两个相同类型的参数,那么并不总是能够构造您可能需要的全部重载集。

它可以使构造函数更简单,特别是对于不可变类型(对于线程来说很重要)-。也许没有它应该的那么好,但是比有很多重载要好。显然,不能对不可变对象使用对象初始值设定项,因此通常:

new Foo {Id = 25, Name = "Fred"}
不可用;我会满足于:

new Foo (Id: 25, Name: "Fred")
这可以扩展到简化重载的一般思想,但在大多数情况下,我更喜欢宣传合法组合的重载。在我看来,构造函数有点不同,因为您只是(通常)定义初始状态

COM方面的东西对很多人来说也很重要,但我只是不使用太多的COM互操作,所以这对我来说并不重要


编辑重新评论;为什么它们不使用与属性相同的语法呢?简单-它可能与其他成员/变量不明确(这不是属性的问题);例如:

[XmlElement("foo", Namespace = "bar")]
它使用了一个常规参数(对于ctor,“foo”)和一个命名赋值。因此,假设我们将其用于常规命名参数:

SomeMethod("foo", SecondArg = "bar");
(也可以是构造函数;为了简单起见,我使用了一种方法)

现在。。。如果我们有一个名为
SecondArg
的变量或属性,该怎么办?使用
SecondArg
作为
SomeMethod
的命名参数,将“bar”指定给
SecondArg
,并将“bar”作为常规参数传递,这两者之间是不明确的

举例来说,这在C#3.0中是合法的:

显然,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
{
}


这将有助于避免为Office应用程序提供体面的API的问题:)


Office API的某些部分还可以,但也有一些边缘案例是为使用带有可选/命名参数的语言而设计的。这就是为什么C#必须有它们的原因。

可选参数也避免了类提供几十个方法的问题,这些方法只是接受的参数的变体

考虑异常类。它不是一个带有可选参数的构造函数,而是为“has message”和“has internal exception”的每个组合使用四个构造函数。没关系,但是现在考虑如果给一个内嵌异常的构造函数提供空值会发生什么?它的行为是否与没有innerException参数的构造函数完全相同,或者与没有innerException参数的构造函数完全相同,或者它是否抛出空引用异常

带有2个可选参数的单个构造函数会使传递null innerException相当于根本不包含它变得更加明显。默认参数的完美位置


另外,请不要忘记,现在每个派生异常类还必须包含4个构造函数,这是一个毫无意义的麻烦。

此外,这不会编译:

[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; }
}

是的-直到大微软咬紧牙关,生产出真正的托管操作系统(我看不到他们很快就能做到),一些应用程序将不得不处理非托管呼叫。哦,非常好。我原以为他们必须允许从初始值设定项块中分配ReadOnly,但这个想法很快就变得混乱起来。这要好得多。尽管如你所说,如果构造函数是魔术般出现的,那就太好了。我很好奇为什么他们没有借用属性使用的命名参数语法。@Marc:我在你答案的底部发布了我的回复。:)我是这么说的;)使用Office API时,VB.Net比C更容易使用#
[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; }
}