19

这似乎是一个简单的问题,但由于某种原因,我无法在任何地方找到答案。基本上,我希望能够实现一个采用NamedParameters的构造函数。

通过命名参数,我并不是指具有默认值的参数(可选参数),例如:

public SomeMethod(){
    string newBar = Foo(bar2 : "customBar2");
}

public string Foo(string bar1 = "bar1", bar2 = "bar2" ){
     //...
}

我试图实现的一个很好的例子是来自System.Web.Mvc程序集的AuthorizeAttribute。您可以使用以下方式:

[Authorize(Roles = "Administrators", Users = "ThatCoolGuy")]
public ActionResult Admin(){

}

intellisense 中的构造函数签名类似于以下示例,我相信(请确认)那些 NamedParameters 正在映射到类属性。

AuthorizeAttribute.AuthorizeAttribute( NamedParameters... ) 初始化 System.Web.Mvc.AuthorizeAttribute 类的新实例

命名参数:

  • 订单整数
  • 用户字符串
  • 角色字符串
4

10 回答 10

18

请注意:

调用方法时定义参数名的语法与可选参数无关:

Foo(bar1 : "customBar1");即使这样声明,您也可以使用Foovoid Foo(string bar1)


回答这个问题:
我的猜测是,这是类似于 Visual Studio 2010 中引入的对象初始化程序的语法糖,因此您不能将它用于您自己的类。

于 2012-08-21T14:12:17.373 回答
15

您正在谈论的行为特定于属性,不能在“普通”类构造函数中重用。

于 2012-08-21T14:08:59.667 回答
7

你不需要“实现”任何东西。

参数可以以您描述的方式使用,仅作为构造函数上的参数存在。

引入它们时,您确实需要使用 C# 3.5 或更高版本。

您的示例无需修改即可在 C# 4.0 / Visual Studio 2010 上编译和运行。

请参阅MSDN 上的命名和可选参数(C# 编程指南)


关于对象的属性,没有相应的构造函数参数,确切的语法是特定于属性的,不能被复制,但是,使用对象初始化器可以接近。

于 2012-08-21T14:10:38.540 回答
3

您可以将构建器/构造器信息模式与属性初始化器一起使用。

class PersonInfo
{
    public string Name { get; set; }
    public int? Age { get; set; }
    public Color? FavoriteColor { get; set; }

    public Person BuildPerson()
    {
        return new Person(this);
    }
}

class Person
{
    public Person(PersonInfo info)
    {
        // use info and handle optional/nullable parameters to initialize person
    }

    ...
}

var p = new Person(new PersonInfo { Name = "Peter", Age = 15 });
// yet better
var p = new PersonInfo { Name = "Peter", Age = 15 }.BuildPerson();

但是我不明白,为什么您不只使用命名参数并提供 null 来指示可选参数。

class Person
{
    public Person(string name = null, int? age = null, Color? favoriteColor = null) { /* ... */ }
}

var p = new Person(name: "Peter", age: 15);
于 2012-08-21T14:06:34.653 回答
2

命名参数并不特定于属性。这是一种可以在任何地方使用的语言语法。对初始化程序使用属性很好,但您并不总是希望将内部设置为设置属性。

只需使用以下方法实例化您的类:

TheClass c = new Theclass(param3:firstValue, param1:secondValue, param2:secondValue);

关于这部分问题:

“但是我不明白,为什么你不只使用命名参数并提供 null 来指示可选参数。”

命名参数很好的原因是您不需要在括号中提供无关的值,只需指定您想要指定的值,因为如果它是可选的,您甚至不需要输入 null。此外,如果您指定 null,您将覆盖该参数的任何默认值,使其成为可选。可选意味着有一个默认值,意味着没有传入任何内容。

实例时的属性初始化纯粹是为了方便。自 C 以来,已经能够在类型的构造时初始化值。如果无法在构造函数中指定这些值,这很方便。我个人觉得他们的便利已经宠坏了人们,它变得有点太自由了,让一切都公开了。仅取决于您需要的属性的设计和安全性。

于 2014-04-07T01:52:47.443 回答
1

我怀疑这是可能的。这是特定于属性的东西。

我认为最接近的选择是使用对象初始化器:

class Foo {
    public string Name {get;set;}
    public int Data {get;set;}
}

var foo = new Foo {Name = "MyName", Data = 12};
于 2012-08-21T14:11:44.530 回答
0

尝试使用此签名

[AttributeUsage(AttributeTargets.Class)]

在您的班级名称之前

于 2013-10-02T15:08:11.197 回答
0

Visual C# 2010 引入了命名参数和可选参数。命名参数使您能够通过将参数与参数名称而不是参数在参数列表中的位置相关联来为特定参数指定参数。命名参数使您无需记住或查找参数在参数列表中的顺序被调用方法的参数列表。

static void Main(string[] args)
{
    mapingFunction(snum2: "www.stackoverflow.com", num1: 1);
}
public static void mapingFunction(int num1, string snum2)
{
   Console.WriteLine(num1 + " and " + snum2);
}

在这里你可以看到参数是按照我们的顺序传递的

于 2015-01-19T13:14:23.143 回答
0

完整说明请参考 MSDN 规范:

https://msdn.microsoft.com/en-us/library/aa664614(v=vs.71).aspx

属性类的每个非静态公共读写字段和属性都为属性类定义了一个命名参数”。

于 2016-07-12T13:45:23.853 回答
0

您可能想要做的是在您的属性中实现公共属性:

public class AuditFilterAttribute : ActionFilterAttribute
{
    public string Message { get; set; }

    public AuditFilterAttribute() { }
}

可以通过应用它的命名参数访问它们:

[AuditFilter(Message = "Deleting user")]
public ActionResult DeleteUser(int userId)

希望有帮助...

于 2017-11-29T14:32:20.407 回答