如何定义命名参数C#

问题描述 投票:0回答:10

这似乎是一个简单的问题,但由于某种原因我无法在任何地方找到答案。基本上,我希望能够实现一个采用 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(){

}

智能感知中构造函数的签名类似于以下示例,我相信(请确认)这些 NamedParameters 映射到类属性。

AuthorizeAttribute.AuthorizeAttribute(命名参数...) 初始化 System.Web.Mvc.AuthorizeAttribute 类的新实例

命名参数:

  • 订购国际
  • 用户字符串
  • 角色字符串
c# .net custom-attributes named-parameters
10个回答
21
投票

请注意:

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

即使

Foo(bar1 : "customBar1");
声明如下,您也可以使用
Foo
void Foo(string bar1)


回答问题:
我的猜测是,这是类似于 Visual Studio 2010 中引入的对象初始值设定项的语法糖,因此您不能将其用于您自己的类。


17
投票

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


8
投票

您不需要“实施”任何东西。

参数可以按照您描述的方式使用,只需作为构造函数中的参数存在即可。

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

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

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


对于对象上没有相应构造函数参数的属性,确切的语法特定于属性并且无法复制,不过,使用 对象初始值设定项 您可以接近。


4
投票

您可以将构建器/构造函数信息模式与属性初始值设定项一起使用。

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);

3
投票

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

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

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

关于这部分问题:

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

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

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


2
投票

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

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

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

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

1
投票

尝试使用这个签名

[AttributeUsage(AttributeTargets.Class)]

班级名称之前


1
投票

请参阅 MSDN 规范以获取完整说明:

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

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


1
投票

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

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


1
投票

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

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

    public AuditFilterAttribute() { }
}

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

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

希望有帮助...

© www.soinside.com 2019 - 2024. All rights reserved.