This seems like a simple question, but for some reason I can't find the answer anywhere. Basically, I'd like to be able to implement a constructor that takes NamedParameters.
By named parameters, I do not mean parameters with default values (optional parameters) such as:
public SomeMethod(){
string newBar = Foo(bar2 : "customBar2");
}
public string Foo(string bar1 = "bar1", bar2 = "bar2" ){
//...
}
A good example of what I'm trying to achieve is the AuthorizeAttribute from the System.Web.Mvc assembly. Which you can use the following way:
[Authorize(Roles = "Administrators", Users = "ThatCoolGuy")]
public ActionResult Admin(){
}
The constructor's signature in intellisense looks like the following example and I believe (please confirm) that those NamedParameters are mapping to class properties.
AuthorizeAttribute.AuthorizeAttribute(NamedParameters...) Initiliaze new instance of the System.Web.Mvc.AuthorizeAttribute class
Named parameters:
- Order int
- Users string
- Roles string
The behaviour you are talking about is specific for attributes and cannot be reused in "normal" classes constructors.
Please note:
The syntax of defining the parameter name when calling a method has nothing to do with optional parameters:
You can use Foo(bar1 : "customBar1");
even if Foo
is declared like this: void Foo(string bar1)
To answer the question:
My guess is that this is syntactic sugar similar to the object initializers introduced in Visual Studio 2010 and therefore you can't use this for your own classes.
You don't need to "implement" anything.
The parameters can be used in the manner you describe just by existing as parameters on the constructor.
You do need to be using C# 3.5 or above, when they were introduced.
Your example will compile and run on C# 4.0 / Visual Studio 2010 without modification.
See Named and Optional Arguments (C# Programming Guide) on MSDN.
In regards to properties on the object, that do not have a corresponding constructor arguments, the exact syntax is specific to attributes and can't be replicated, though, with object initializers you can get close.
You can use the builder/constructor info pattern together with property initializers.
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();
I however don't understand, why you don't just use named parameters and provide null for indicating optional parameters.
class Person
{
public Person(string name = null, int? age = null, Color? favoriteColor = null) { /* ... */ }
}
var p = new Person(name: "Peter", age: 15);
I doubt that's possible. This is something specific for attributes.
I think the closest option is to use an object initializer:
class Foo {
public string Name {get;set;}
public int Data {get;set;}
}
var foo = new Foo {Name = "MyName", Data = 12};
try to use this signature
[AttributeUsage(AttributeTargets.Class)]
before the name of your class
Please refer to MSDN specification for full description:
https://msdn.microsoft.com/en-us/library/aa664614(v=vs.71).aspx
"Each non-static public read-write field and property for an attribute class defines a named parameter for the attribute class".
Named parameters are NOT specific to attributes. It's a language syntax that can be used everywhere. It's fine to use properties for initialisers but you don't always want to have internals set as set properties.
Just instantiate you class using:
TheClass c = new Theclass(param3:firstValue, param1:secondValue, param2:secondValue);
With regards to this part of the question:
"I however don't understand, why you don't just use named parameters and provide null for indicating optional parameters."
The reason named parameters are nice is you don't need to provide extraneous values in parentheses, just what you want to specify, because if it's optional you shouldn't even need to put null. Furthermore, if you specify null, you are overriding any default value for that parameter which makes it optional. Being optional implies there's a default value meaning nothing passed in.
Property initialisation at instance time is purely there for convenience. Since C there has been the ability to initialise values at construction time on types. Which is handy if those values can't be specified in the constructor. I personally feel that the convenience of them has spoiled people and it get a little too liberal and make everything public get AND set. Just depends on the design and security of properties you need.
Visual C# 2010 introduces named and optional arguments. Named argument able you to specify an argument for a particular parameter by associating the argument with the parameter's name rather than with the parameter's position in the parameter list.Named arguments free you from the need to remember or to look up the order of parameters in the parameter lists of called methods.
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);
}
here you can see that argument are passed with our their order
What you probably want to do is implement public properties in your attribute:
public class AuditFilterAttribute : ActionFilterAttribute
{
public string Message { get; set; }
public AuditFilterAttribute() { }
}
They can be accessed through Named Parameters where you apply it:
[AuditFilter(Message = "Deleting user")]
public ActionResult DeleteUser(int userId)
Hope that helps...
来源:https://stackoverflow.com/questions/12056639/how-to-define-named-parameters-c-sharp