2012-07-02 17 views
27

C# 4 introdujo una característica llamada named arguments lo cual es especialmente útil en escenarios comoargumentos con nombre en C#

int RegisterUser(string nameFirst, string nameLast, string nameMiddle, string email) 

¿Hay una manera de forzar el uso de argumentos con nombre? Tal vez algún atributo para aplicar a un método o un compilador del que no estoy enterado? Supongo que se puede hacer con las herramientas de inspector de código, pero solo quiero saber si hay otra forma.

p.s.

Para aquellos interesados ​​en por qué uno puede necesitarlo y por qué no simplemente usar una clase/estructura para utilizar object initializers hay escenarios cuando es imposible. Al igual que las llamadas a bibliotecas que no están bajo tu control o las convenciones de código extraño que tienes que obedecer.

+4

no veo mucho uso en argumentos nombrados a menos que sus argumentos son en su mayoría opcional. –

+1

@BobKaufman Supongo todo lo contrario. Cuando compila el código, "olvida" si se lo denominó parámetro posicional, nombre o valor predeterminado. –

+1

¿Por qué _usted_ necesita esto? ¿Se te está imponiendo una convención de código? – driis

Respuesta

24

No, no en el idioma C#. Siempre aceptará parámetros posicionales si se suministran todos los parámetros.

Se podría build a custom FxCop rule o un StyleCop rule para hacer cumplir este - como se ha señalado en los comentarios, es probable que un StyleCop regla que estaría interesado en (gracias a Kris).

+7

No se puede crear una regla FxCop personalizada, porque las reglas FxCop funcionan en binarios, no en origen, y los argumentos nombrados se "compilan lejos". Sin embargo, supongo que puedes hacer una regla CustomCop personalizada. –

+0

@KrisVandermotten, creo que tienes razón, sin embargo, FxCop puede extraer información del PDB, pero no sé si el uso de parámetros con nombre va al PDB. Si ese no es el caso, creo que en su lugar se necesita una regla de policía de estilo. – driis

+2

No, en cuanto a los parámetros con nombre es el PDB: "la computadora dice no!". –

15

Es posible obligar a las personas que llaman a utilizar siempre args con nombre. No lo haría en la mayoría de las circunstancias porque es bastante feo, pero depende de qué tan seguro sea el uso del método.

Aquí está la solución:

int RegisterUser(
#if DEBUG 
     int _ = 0, 
#endif 
     string nameFirst = null, 
     string nameLast = null, 
     string nameMiddle = null, 
     string email = null) { /*...*/ } 

El primer parámetro es un maniquí que no debe ser usado (y se compila de distancia en estreno de eficiencia). Sin embargo, asegura que todos los parámetros siguientes deben ser nombrados.

uso válido es cualquier combinación de los parámetros con nombre:

RegisterUser(); 
    RegisterUser(nameFirst: "Joe"); 
    RegisterUser(nameFirst: "Joe", nameLast: "Smith"); 
    RegisterUser(email: "[email protected]"); 

Cuando intenta utilizar los parámetros posicionales, el código no se compilará.

+2

Con su directiva de preprocesador de compilación, actúa como si 'int _ = 0' ni siquiera existe si el símbolo DEPURAR no está definido, por lo que no tiene ningún efecto en absoluto para una versión de lanzamiento ... No lo hago t pensar que esta respuesta hace lo que cree que hace ... – Zack

+2

El efecto es que el parámetro "_" no utilizado con valor predeterminado obliga al resto de los siguientes parámetros a tener valores predeterminados, y debe nombrarse al llamar. – user4698855

+5

Feo, pero listo. – joelsand

2

También he buscado una manera de forzar argumentos con nombre. Los parámetros opcionales pueden ser peligrosos, especialmente si tiene múltiples parámetros del mismo tipo. Las sobrecargas son casi siempre una solución más segura, pero hay veces en que tienes un método que puede tomar muchas combinaciones de argumentos, por lo que crear 20 sobrecargas para tener en cuenta la posibilidad de siempre es exagerado.

En situaciones extremas donde es de suma importancia que los argumentos sean nombrados en todo momento, crearé una clase de argumento sin un constructor definido. En su caso, usted puede hacer esto:

public class UserRegistrationArguments 
{ 
    public string nameFirst { get; set; } 
    public string nameLast { get; set; } 
    public string nameMiddle { get; set; } 
    public string email { get; set; } 
} 

llamada así:

RegisterUser(new UserRegistrationArguments { nameFirst = "Bob", nameLast = "Slob" }); 

También podría simplificar así:

public class UserRegistrationArguments 
{ 
    public string nameMiddle { get; set; } 
    public string email { get; set; } 
} 

int RegisterUser(string nameFirst, string nameLast, UserRegistrationArguments args = null) 

... y hacer esto:

RegisterUser("Bob", "Slob", new UserRegistrationArguments { nameMiddle = "Teh" }); 

De esta manera, sólo tiene un PARAMET opcional er y eso es para sus parámetros opcionales.

Editar: Tal vez no leí correctamente el OP. ¿No estás usando argumentos opcionales? Si no, entonces esta respuesta probablemente no te ayude.

0

Estoy usando otro método. En mi configuración, tengo 1 parámetro que siempre espero, luego vienen un montón de cadenas opcionales que realmente quiero asegurar que el usuario elija activamente. Así que mi primera cadena en esta lista es un valor de "trampa", que si se establece arroja un error. De esta manera:

public HtmlString Toolbar(DynamicEntity target = null, string dontRelyOnParameterOrder = Constants.RandomProtectionParameter, string actions = null, string contentType = null, object prefill = null) 
    { 
     if (!Enabled) return null; 
     protectAgainstMissingParameterNames(dontRelyOnParameterOrder); 

     var toolbar = new ItemToolbar(target, actions, contentType, prefill); 

     return new HtmlString(toolbar.Toolbar); 
    } 

    private void protectAgainstMissingParameterNames(string criticalParameter) 
    { 
     if(criticalParameter != Constants.RandomProtectionParameter) 
      throw new Exception("when using the toolbar command, please use named parameters - otherwise you are relying on the parameter order staying the same."); 

    } 

espero que les guste :)

Cuestiones relacionadas