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

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

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

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

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

Хорошим примером того, чего я пытаюсь добиться, является AuthorizeAttribute из сборки System.Web.Mvc. Что вы можете использовать следующим образом:

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

}

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

AuthorizeAttribute.AuthorizeAttribute (NamedParameters ...). Инициализация нового экземпляра класса System.Web.Mvc.AuthorizeAttribute.

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

  • Заказать int
  • Строка пользователей
  • Строка ролей

person Pierluc SS    schedule 21.08.2012    source источник
comment
@Jodrell Если вы посмотрите на определение класса в метаданных или отражателе, есть только одно определение конструктора AuthorizeAttribute, которое не принимает параметров, но каким-то образом вы можете передать ему свойства класса (именованные параметры)   -  person Pierluc SS    schedule 21.08.2012


Ответы (10)


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

person mathieu    schedule 21.08.2012
comment
Параметры имен используются с .NET 4.0 - они предназначены не только для атрибутов. - person Oded; 21.08.2012
comment
OP хочет того же поведения, что и в атрибутах: использование свойств класса в качестве необязательных параметров - person mathieu; 21.08.2012
comment
@Oded: Обратите внимание на разницу между Name = "Value" и name: "Value". Эта крошечная разница и есть то, что хочет OP. Этот ответ не заслуживает отрицательных оценок. - person Daniel Hilgarth; 21.08.2012
comment
Как только какой-либо класс имеет класс Attribute в своем дереве наследования, если этот класс имеет свойство с общедоступным набором, он появится в определении intellisense и будет использоваться как NamedParameter - person Pierluc SS; 21.08.2012

Пожалуйста, обрати внимание:

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

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


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

person Daniel Hilgarth    schedule 21.08.2012
comment
Кажется, что именованные аргументы можно будет использовать в 2021 году для собственных классов: MyClass foo = new MyClass(id:1,qty:4) - person surfmuggle; 07.02.2021
comment
@surfmuggle: Совершенно верно. Но так было всегда, как вы можете видеть в этом ответе от 2012 года, который вы прокомментировали :) - person Daniel Hilgarth; 09.02.2021

Не нужно ничего «реализовывать».

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

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

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

См. Именованные и дополнительные аргументы (Руководство по программированию C #) в MSDN.


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

person Oded    schedule 21.08.2012
comment
Под именованными параметрами я не имею в виду параметры со значениями по умолчанию (необязательные параметры), такие как + Подпись конструктора в intellisense выглядит как в следующем примере, и я считаю (пожалуйста, подтвердите), что эти NamedParameters сопоставляются со свойствами класса. - person mathieu; 21.08.2012
comment
Это не совсем так. Именованные параметры возможны в приложении .NET 3.5, но вам потребуется VS2010. - person Jensen; 21.08.2012

Вы можете использовать шаблон информации о строителе / ​​конструкторе вместе с инициализаторами свойств.

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);
person Sebastian Graf    schedule 21.08.2012
comment
Хорошо ... new Person(name: "Peter", age: 15); для меня не выглядит хуже по сравнению с чем-то вроде new Person { Name = "Peter", Age = 15 }. Думаю, просто двоеточия в параметрах метода не видны ... - person Sebastian Graf; 21.08.2012

Сомневаюсь, что это возможно. Это что-то особенное для атрибутов.

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

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

var foo = new Foo {Name = "MyName", Data = 12};
person Jensen    schedule 21.08.2012

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

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

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

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

«Однако я не понимаю, почему вы просто не используете именованные параметры и не предоставляете null для указания необязательных параметров».

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

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

person Stephen York    schedule 07.04.2014
comment
Я думаю, это должен быть ответ. Я что-то упускаю? - person Kirby L. Wallace; 22.01.2021

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

[AttributeUsage(AttributeTargets.Class)]

перед названием вашего класса

person Diogo de Freitas nunes    schedule 02.10.2013

См. Полное описание в спецификации MSDN:

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

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

person rahnema1    schedule 12.07.2016

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

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

person Adiii    schedule 19.01.2015

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

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

    public AuditFilterAttribute() { }
}

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

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

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

person Fred Mauroy    schedule 29.11.2017