Как определить именованные параметры C#

Это кажется простым вопросом, но по какой-то причине я не могу найти ответ нигде. В принципе, я хотел бы иметь возможность реализовать конструктор, который принимает NamedParameters.

по именованным параметрам я не имею в виду параметры со значениями по умолчанию (необязательные параметры), такие как:

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

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

хорошим примером того, чего я пытаюсь достичь, является атрибутом authorizeattribute С система.Сеть.В MVC сборка. Что вы можете используйте следующий способ:

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

}

подпись конструктора в intellisense выглядит как следующий пример, и я считаю (Пожалуйста, подтвердите), что эти NamedParameters сопоставляются со свойствами класса.

атрибутом authorizeattribute.Атрибутом authorizeattribute(NamedParameters...) Initiliaze новый экземпляр системы.Сеть.В MVC.AuthorizeAttribute class

именованные параметры:

  • заказать int
  • пользователи строку
  • роли строку

10 ответов


поведение, о котором вы говорите, специфично для атрибутов и не может быть повторно использовано в конструкторах "нормальных" классов.


обратите внимание:

синтаксис определения имени параметра при вызове метода не имеет ничего общего с дополнительными параметрами:

можно использовать Foo(bar1 : "customBar1"); даже если Foo объявляется следующим образом: void Foo(string bar1)


ответить на вопрос:
Я предполагаю, что это синтаксический сахар, похожий на инициализаторы объектов представил в Visual Studio 2010 и поэтому вы не можете использовать это для ваших собственных классов.


вам не нужно ничего "реализовывать".

параметры могут использоваться так, как вы описываете, просто существуя в качестве параметров в конструкторе.

вы do нужно использовать C# 3.5 или выше, когда они были введены.

ваш пример будет компилироваться и выполняться на C# 4.0 и Visual Studio 2010 и без изменений.

посмотреть именованные и необязательные Аргументы (руководство по программированию на C#) на В MSDN.


Что касается свойств объекта, которые не имеют соответствующих аргументов конструктора, точный синтаксис специфичен для атрибутов и не может быть реплицирован, хотя, с инициализаторы объектов вы можете сблизиться.


вы можете использовать шаблон builder/constructor info вместе с инициализаторами свойств.

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

Я сомневаюсь, что это возможно. Это нечто специфическое для атрибутов.

Я думаю, что ближайший вариант-использовать инициализатор объекта:

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

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

попробуйте использовать эту подпись

[AttributeUsage(AttributeTargets.Class)]

перед именем класса


пожалуйста, обратитесь к спецификации MSDN для полного описания:

https://msdn.microsoft.com/en-us/library/aa664614 (v=против 71).aspx

"каждое нестатическое публичное поле чтения-записи и свойство для класса атрибутов определяет именованный параметр для класса атрибутов".


именованные параметры не относятся к атрибутам. Это синтаксис языка, который можно использовать везде. Можно использовать свойства для инициализаторов, но вы не всегда хотите, чтобы внутренние были установлены как свойства set.

просто создайте экземпляр класса, используя:

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

что касается этой части вопроса:

" Я, однако, не понимаю, почему вы не просто используете именованные параметры и предоставляете null для указания необязательного параметры."

причина, по которой именованные параметры хороши, заключается в том, что вам не нужно предоставлять посторонние значения в скобках, только то, что вы хотите указать, потому что если это необязательно, вам даже не нужно ставить null. Кроме того, если указано значение null, переопределяется любое значение по умолчанию для этого параметра, что делает его необязательным. Необязательно означает, что значение по умолчанию значение не передается.

инициализация свойства во время экземпляра чисто там для удобства. Начиная с C появилась возможность инициализации значений во время построения по типам. Что удобно, если эти значения не могут быть указаны в конструкторе. Я лично чувствую, что удобство их испортило людей, и это становится слишком либеральным и делает все публичным. Как раз зависит от конструкции и обеспеченности свойств вам.


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

здесь вы можете видеть, что аргумент передается с нашим их порядком


что вы, вероятно, хотите сделать, это реализовать общественные свойства атрибутов:

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

    public AuditFilterAttribute() { }
}

Они могут быть доступны через именованные параметры, где вы примените его:

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

надеюсь, что это поможет...