¿Cuál es el propósito de nameof?

La versión 6.0 tiene una nueva característica de nameof , pero no puedo entender su propósito, ya que simplemente toma el nombre de la variable y lo cambia a una cadena en la comstackción.

Pensé que podría tener algún propósito al usar pero cuando trato de nameof(T) simplemente me imprime una T lugar del tipo usado.

¿Alguna idea sobre el propósito?

¿Qué pasa con los casos en los que desea reutilizar el nombre de una propiedad, por ejemplo, al lanzar una excepción basada en un nombre de propiedad o al manejar un evento PropertyChanged ? Hay numerosos casos en los que desearía tener el nombre de la propiedad.

Toma este ejemplo:

 switch (e.PropertyName) { case nameof(SomeProperty): { break; } // opposed to case "SomeOtherProperty": { break; } } 

En el primer caso, cambiar el nombre de SomeProperty también cambiará el nombre de la propiedad, o romperá la comstackción. El último caso no.

Esta es una forma muy útil de mantener su código comstackdo y libre de errores (tipo de).

(Un artículo muy bueno de Eric Lippert sobre por qué la infoof no lo hizo, mientras que el nameof hizo)

Es realmente útil para ArgumentException y sus derivados:

 public string DoSomething(string input) { if(input == null) { throw new ArgumentNullException(nameof(input)); } ... 

Ahora, si alguien refactoriza el nombre del parámetro de input , la excepción se mantendrá actualizada también.

También es útil en algunos lugares donde previamente se tenía que usar la reflexión para obtener los nombres de propiedades o parámetros.

En su nombre de ejemplo de nameof(T) obtiene el nombre del parámetro de tipo; esto también puede ser útil:

 throw new ArgumentException(nameof(T), $"Type {typeof(T)} does not support this method."); 

Otro uso de nameof es para enumeraciones: generalmente si quieres el nombre de la cadena de una enumeración, usas .ToString() :

 enum MyEnum { ... FooBar = 7 ... } Console.WriteLine(MyEnum.FooBar.ToString()); > "FooBar" 

Esto es realmente relativamente lento ya que .Net posee el valor enum (es decir, 7 ) y encuentra el nombre en tiempo de ejecución.

En su lugar use nameof :

 Console.WriteLine(nameof(MyEnum.FooBar)) > "FooBar" 

Ahora .Net reemplaza el nombre enum con una cadena en tiempo de comstackción.


Otro uso es para cosas como INotifyPropertyChanged y logging: en ambos casos, desea que el nombre del miembro al que está llamando se transfiera a otro método:

 // Property with notify of change public int Foo { get { return this.foo; } set { this.foo = value; PropertyChanged(this, new PropertyChangedEventArgs(nameof(this.Foo)); } } 

O…

 // Write a log, audit or trace for the method called void DoSomething(... params ...) { Log(nameof(DoSomething), "Message...."); } 

Tu pregunta ya expresa el propósito. Debe ver que esto podría ser útil para iniciar sesión o lanzar excepciones.

por ejemplo.

 public void DoStuff(object input) { if (input == null) { throw new ArgumentNullException(nameof(input)); } } 

esto es bueno, si cambio el nombre de la variable, el código se romperá o devolverá una excepción con un mensaje incorrecto .


Por supuesto, los usos no están limitados a esta simple situación. Puede usar el nameof cada vez que sea útil codificar el nombre de una variable o propiedad.

Los usos son múltiples cuando se consideran varias situaciones vinculantes y de reflexión. Es una excelente manera de llevar lo que fueron errores de tiempo de ejecución para comstackr el tiempo.

El caso de uso más común que se me ocurre es cuando se trabaja con la interfaz INotifyPropertyChanged . (Básicamente todo lo relacionado con WPF y enlaces utiliza esta interfaz)

Echale un vistazo a éste ejemplo:

 public class Model : INotifyPropertyChanged { // From the INotifyPropertyChanged interface public event PropertyChangedEventHandler PropertyChanged; private string foo; public String Foo { get { return this.foo; } set { this.foo = value; // Old code: PropertyChanged(this, new PropertyChangedEventArgs("Foo")); // New Code: PropertyChanged(this, new PropertyChangedEventArgs(nameof(Foo))); } } } 

Como puede ver a la antigua, tenemos que pasar una cadena para indicar qué propiedad ha cambiado. Con nameof podemos usar el nombre de la propiedad directamente. Esto puede no parecer un gran problema. Pero imagina lo que sucede cuando alguien cambia el nombre de la propiedad Foo . Al usar una cadena, el enlace dejará de funcionar, pero el comstackdor no lo advertirá. Al usar nameof, se obtiene un error de comstackción de que no hay propiedad / argumento con el nombre Foo .

Tenga en cuenta que algunos marcos usan alguna magia de reflexión para obtener el nombre de la propiedad, pero ahora que tenemos el nombre de esto ya no es necesario .

Otro caso de uso en el que el nameof característica de C # 6.0 es útil : considere una biblioteca como Dapper que hace que las recuperaciones de bases de datos sean mucho más sencillas. Aunque esta es una gran biblioteca, es necesario codificar los nombres de propiedad / campo dentro de la consulta. Lo que esto significa es que si decide renombrar su propiedad / campo, hay altas posibilidades de que olvide actualizar la consulta para usar nuevos nombres de campo. Con las funciones de interpolación de cadenas y nameof , el código se vuelve mucho más fácil de mantener y seguro.

Del ejemplo dado en el enlace

sin nombrede

var dog = connection.Query("select Age = @Age, Id = @Id", new { Age = (int?)null, Id = guid });

con nombrede

var dog = connection.Query($"select {nameof(Dog.Age)} = @Age, {nameof(Dog.Id)} = @Id", new { Age = (int?)null, Id = guid });

El uso más común estará en la validación de entrada, como

 //Currently void Foo(string par) { if (par == null) throw new ArgumentNullException("par"); } //C# 6 nameof void Foo(string par) { if (par == null) throw new ArgumentNullException(nameof(par)); } 

En el primer caso, si refactoriza el método cambiando el nombre del parámetro par , probablemente olvide cambiarlo en ArgumentNullException . Con nameof no tienes que preocuparte por eso.

Ver también: nameof (C # y Referencia de Visual Basic)

Como otros ya han señalado, el nameof operador inserta el nombre que el elemento recibió en el código fuente.

Me gustaría agregar que esta es una muy buena idea en términos de refactorización, ya que hace que esta cadena de refactorización sea segura. Previamente utilicé un método estático que utilizaba la reflexión para el mismo propósito, que sin embargo tiene un impacto en el rendimiento en el tiempo de ejecución. El nameof operador no tiene impacto en el tiempo de ejecución, hace su trabajo en tiempo de comstackción. Si echas un vistazo al código MSIL , encontrarás la cadena incrustada. Vea el siguiente método y su código desmontado.

 static void Main(string[] args) { Console.WriteLine(nameof(args)); Console.WriteLine("regular text"); } // striped nops from the listing IL_0001 ldstr args IL_0006 call System.Void System.Console::WriteLine(System.String) IL_000C ldstr regular text IL_0011 call System.Void System.Console::WriteLine(System.String) IL_0017 ret 

Sin embargo, eso puede ser un inconveniente si planea ofuscar su software. Después de la ofuscación, la cadena incrustada ya no puede coincidir con el nombre del elemento. Los mecanismos que dependen de este texto se romperán. Ejemplos de eso, incluidos, entre otros, los siguientes: Reflection, NotifyPropertyChanged …

La determinación del nombre durante el tiempo de ejecución cuesta algo de rendimiento, pero es seguro para la ofuscación. Si la ofuscación no es necesaria ni planeada, recomendaría elegir usar el nameof operador.

Considere que utiliza una variable en su código y necesita obtener el nombre de la variable y, por ejemplo, imprimirla, debe usar

 int myVar = 10; print("myVar" + " value is " + myVar.toString()); 

Y si luego alguien refactura el código y usa otro nombre para “myVar”, él / ella tendría que observar el valor de la cadena en su código y darle el valor correspondiente.

En cambio si tuvieras

 print(nameof(myVar) + " value is " + myVar.toString()); 

¡Ayudaría a refactorizar automáticamente!

El proyecto ASP.NET Core MVC utiliza nameof en AccountController.cs y ManageController.cs con el método RedirectToAction para hacer referencia a una acción en el controlador.

Ejemplo:

 return RedirectToAction(nameof(HomeController.Index), "Home"); 

Esto se traduce a:

 return RedirectToAction("Index", "Home"); 

y lleva al usuario a la acción ‘Índice’ en el controlador ‘Inicio’, es decir, /Home/Index .

El artículo de MSDN enumera el enrutamiento MVC (el ejemplo que realmente hizo clic en el concepto para mí) entre muchos otros. El párrafo de descripción (formateado) dice:

  • Al informar errores en el código,
  • conectando enlaces modelo-vista-controlador (MVC),
  • la propiedad de disparo cambió eventos, etc.,

a menudo quiere capturar el nombre de la cadena de un método . Usar nameof ayuda a mantener su código válido al cambiar el nombre de las definiciones.

Antes tenía que usar literales de cadena para referirse a las definiciones, lo cual es frágil al cambiar el nombre de los elementos de código porque las herramientas no saben cómo verificar estos literales de cadena.

Las respuestas aceptadas / mejor valoradas ya dan varios ejemplos concretos excelentes.

El propósito del operador nameof es proporcionar el nombre de origen de los artefactos.

Por lo general, el nombre de la fuente es el mismo nombre que el nombre de los metadatos:

 public void M(string p) { if (p == null) { throw new ArgumentNullException(nameof(p)); } ... } public int P { get { return p; } set { p = value; NotifyPropertyChanged(nameof(P)); } } 

Pero esto puede no ser siempre el caso:

 using i = System.Int32; ... Console.WriteLine(nameof(i)); // prints "i" 

O:

 public static string Extension(this T t) { return nameof(T); returns "T" } 

Un uso que le he estado dando es para nombrar recursos:

 [Display( ResourceType = typeof(Resources), Name = nameof(Resources.Title_Name), ShortName = nameof(Resources.Title_ShortName), Description = nameof(Resources.Title_Description), Prompt = nameof(Resources.Title_Prompt))] 

El hecho es que, en este caso, ni siquiera necesité las propiedades generadas para acceder a los recursos, pero ahora tengo un tiempo de comstackción para verificar que los recursos existen.

Uno de los usos de nameof keyword es para establecer Binding en wpf mediante progtwigción .

para establecer el Binding , debe establecer la Path con una cadena, y con el nameof palabra clave, es posible utilizar la opción Refactor.

Por ejemplo, si tiene la propiedad de dependencia IsEnable en su UserControl y desea vincularla a IsEnable de alguna CheckBox en su UserControl , puede usar estos dos códigos:

 CheckBox chk = new CheckBox(); Binding bnd = new Binding ("IsEnable") { Source = this }; chk.SetBinding(IsEnabledProperty, bnd); 

y

 CheckBox chk = new CheckBox(); Binding bnd = new Binding (nameof (IsEnable)) { Source = this }; chk.SetBinding(IsEnabledProperty, bnd); 

Es obvio que el primer código no puede refactorizarse, pero el que se cierra uno …

Anteriormente estábamos usando algo como eso:

 // Some form. SetFieldReadOnly( () => Entity.UserName ); ... // Base form. private void SetFieldReadOnly(Expression> property) { var propName = GetPropNameFromExpr(property); SetFieldsReadOnly(propName); } private void SetFieldReadOnly(string propertyName) { ... } 

Motivo: comstackr seguridad de tiempo. Nadie puede renombrar silenciosamente la propiedad y romper la lógica del código. Ahora podemos usar nameof ().

Tiene ventajas cuando usa ASP.Net MVC. Cuando utiliza HTML helper para construir algún control a la vista, usa los nombres de propiedad en el nombre attribure de la entrada html:

 @Html.TextBoxFor(m => m.CanBeRenamed) 

Hace algo así:

  

Entonces, si necesita validar su propiedad en el método Validate, puede hacer esto:

 public IEnumerable Validate(ValidationContext validationContext) { if (IsNotValid(CanBeRenamed)) { yield return new ValidationResult( $"Property {nameof(CanBeRenamed)} is not valid", new [] { $"{nameof(CanBeRenamed)}" }) } } 

En caso de que cambie el nombre de su propiedad utilizando herramientas de refactorización, su validación no se romperá.