Cómo definir los parámetros nombrados C #

Esto parece una pregunta simple, pero por alguna razón no puedo encontrar la respuesta en ninguna parte. Básicamente, me gustaría poder implementar un constructor que tome NamedParameters .

Por parámetros nombrados, no me refiero a parámetros con valores predeterminados (parámetros opcionales) como:

public SomeMethod(){ string newBar = Foo(bar2 : "customBar2"); } public string Foo(string bar1 = "bar1", bar2 = "bar2" ){ //... } 

Un buen ejemplo de lo que estoy tratando de lograr es el AuthorizeAttribute del ensamblado System.Web.Mvc . Que se puede utilizar de la siguiente manera:

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

La firma del constructor en intellisense se parece al siguiente ejemplo y creo (por favor, confirme) que esos NamedParameters se asignan a las propiedades de la clase.

AuthorizeAttribute.AuthorizeAttribute ( NamedParameters … ) Inicia la nueva instancia de la clase System.Web.Mvc.AuthorizeAttribute

Parámetros nombrados:

  • Orden int
  • Cadena de usuarios
  • Cadena de roles

El comportamiento del que habla es específico para los atributos y no se puede reutilizar en constructores de clases “normales”.

Tenga en cuenta:

La syntax de definir el nombre del parámetro al llamar a un método no tiene nada que ver con los parámetros opcionales:

Puedes usar Foo(bar1 : "customBar1"); incluso si Foo se declara así: void Foo(string bar1)


Para responder a la pregunta:
Supongo que este es un azúcar sintáctico similar a los inicializadores de objetos introducidos en Visual Studio 2010 y, por lo tanto, no puede usar esto para sus propias clases.

No necesitas “implementar” nada.

Los parámetros se pueden usar de la manera que describe simplemente existiendo como parámetros en el constructor.

Debe utilizar C # 3.5 o superior, cuando se introdujeron.

Su ejemplo se comstackrá y ejecutará en C # 4.0 / Visual Studio 2010 sin modificaciones.

Consulte Argumentos con nombre y opcionales (Guía de progtwigción de C #) en MSDN.


En lo que respecta a las propiedades en el objeto, que no tienen los argumentos de constructor correspondientes, la syntax exacta es específica de los atributos y no se puede replicar, sin embargo, con los inicializadores de objetos puede acercarse.

Puede usar el patrón de información constructor / constructor junto con los inicializadores de propiedades.

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

Sin embargo, no entiendo, por qué no solo utiliza parámetros con nombre y proporciona un valor nulo para indicar parámetros opcionales.

 class Person { public Person(string name = null, int? age = null, Color? favoriteColor = null) { /* ... */ } } var p = new Person(name: "Peter", age: 15); 

Dudo que sea posible. Esto es algo específico para los atributos.

Creo que la opción más cercana es usar un inicializador de objetos:

 class Foo { public string Name {get;set;} public int Data {get;set;} } var foo = new Foo {Name = "MyName", Data = 12}; 

intenta usar esta firma

 [AttributeUsage(AttributeTargets.Class)] 

antes del nombre de tu clase

Consulte la especificación de MSDN para una descripción completa:

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

Cada propiedad y campo público no estático de lectura y escritura para una clase de atributo define un parámetro con nombre para la clase de atributo “.

Los parámetros nombrados NO son específicos de los atributos. Es una syntax de lenguaje que se puede utilizar en todas partes. Está bien usar propiedades para los inicializadores, pero no siempre desea que los elementos internos se configuren como propiedades establecidas.

Solo instancia tu clase usando:

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

Con respecto a esta parte de la pregunta:

“Sin embargo, no entiendo, por qué no solo utiliza parámetros con nombre y proporciona un valor nulo para indicar parámetros opcionales”.

La razón por la que los parámetros nombrados son agradables es que no es necesario que proporcione valores extraños entre paréntesis, solo lo que desea especificar, porque si es opcional, no debería tener que poner un valor nulo. Además, si especifica nulo, está anulando cualquier valor predeterminado para ese parámetro que lo hace opcional. Ser opcional implica que hay un valor predeterminado que significa que no se pasa nada.

La inicialización de la propiedad en el momento de la instancia está puramente allí por conveniencia. Desde C, se ha podido inicializar valores en el momento de la construcción en tipos. Lo que es útil si esos valores no se pueden especificar en el constructor. Personalmente, siento que la conveniencia de ellos ha arruinado a la gente y se vuelve demasiado liberal y hace que todo sea público y se ponga en marcha. Solo depende del diseño y seguridad de las propiedades que necesite.

Visual C # 2010 introduce argumentos nombrados y opcionales. El argumento con nombre le permite especificar un argumento para un parámetro particular asociando el argumento con el nombre del parámetro en lugar de con la posición del parámetro en la lista de parámetros. Los argumentos con nombre le exigen la necesidad de recordar o buscar el orden de los parámetros en el Listas de parámetros de los métodos llamados.

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

Aquí se puede ver que los argumentos se pasan con nuestra orden de ellos.

Lo que probablemente quieras hacer es implementar propiedades públicas en tu atributo:

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

Se puede acceder a ellos a través de Parámetros con nombre donde lo apliques:

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

Espero que ayude…