如何定义命名参数C#

时间:2012-08-21 14:04:29

标签: c# .net custom-attributes named-parameters

这似乎是一个简单的问题,但由于某种原因,我无法在任何地方找到答案。基本上,我希望能够实现一个带 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 ... )   Initiliaze System.Web.Mvc.AuthorizeAttribute类的新实例

     

命名参数:

     
      
  • Order int
  •   
  • 用户字符串
  •   
  • 角色字符串
  •   

10 个答案:

答案 0 :(得分:15)

请注意:

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

即使Foo(bar1 : "customBar1");声明为Foo,您也可以使用void Foo(string bar1):{{1}}


回答这个问题:
我的猜测是,这是与Visual Studio 2010中引入的object initializers类似的语法糖,因此您不能将它用于您自己的类。

答案 1 :(得分:14)

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

答案 2 :(得分:6)

您无需“实施”任何内容。

参数可以按照您在构造函数中作为参数的现有描述的方式使用。

需要使用C#3.5或更高版本。

您的示例将在C#4.0 / Visual Studio 2010上编译并运行,无需修改。

请参阅MSDN上的Named and Optional Arguments (C# Programming Guide)


关于对象的属性,没有相应的构造函数参数,确切的语法特定于属性,无法复制,但是object initializers可以接近。

答案 3 :(得分: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);

答案 4 :(得分:1)

我怀疑这是可能的。这是属性特有的。

我认为最接近的选择是使用对象初始值设定项:

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

var foo = new Foo {Name = "MyName", Data = 12};

答案 5 :(得分:0)

尝试使用此签名

[AttributeUsage(AttributeTargets.Class)]

在班级名称之前

答案 6 :(得分:0)

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

使用以下方法实例化您的课程:

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

关于这部分问题:

  

"但我不明白,为什么你不使用命名参数并提供null来表示可选参数。"

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

实例时的属性初始化纯粹是为了方便起见。由于C已经能够在构造时对类型进行初始化。如果不能在构造函数中指定这些值,那么这很方便。我个人认为他们的便利已经破坏了人们,它变得有点过于自由,让所有公共场所得到和设置。仅取决于您需要的属性的设计和安全性。

答案 7 :(得分: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);
}

在这里,您可以看到该参数与我们的订单一起传递

答案 8 :(得分:0)

有关完整说明,请参阅MSDN规范:

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

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

答案 9 :(得分:0)

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

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

    public AuditFilterAttribute() { }
}

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

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

希望有帮助...