¿Cuál es el propósito del nombre de?
La versión 6.0 tiene una nueva característica nameof
, pero no puedo entender su propósito, ya que simplemente toma el nombre de la variable y lo cambia a una cadena durante la compilación.
Pensé que podría tener algún propósito al usarlo <T>
, pero cuando lo intento, nameof(T)
simplemente me imprime un T
tipo en lugar del usado.
¿Alguna idea sobre el propósito?
¿Qué pasa con los casos en los que desea reutilizar el nombre de una propiedad, por ejemplo, cuando se lanza una excepción basada en el nombre de una propiedad o se maneja un PropertyChanged
evento? Hay numerosos casos en los que desearía tener el nombre de la propiedad.
Tome este ejemplo:
switch (e.PropertyName)
{
case nameof(SomeProperty):
{ break; }
// opposed to
case "SomeOtherProperty":
{ break; }
}
En el primer caso, cambiar el nombre SomeProperty
provocará un error de compilación si no cambia tanto la definición de propiedad como la nameof(SomeProperty)
expresión. En el segundo caso, cambiar el nombre SomeOtherProperty
o alterar la "SomeOtherProperty"
cadena dará como resultado un comportamiento de ejecución silenciosamente interrumpido, sin errores ni advertencias en el momento de la compilación.
Esta es una forma muy útil de mantener el código compilado y libre de errores (más o menos).
(Un artículo muy bueno de Eric Lippert por qué infoof
no lo logró, mientras que nameof
sí)
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 input
parámetro, la excepción también se mantendrá actualizada.
También es útil en algunos lugares donde anteriormente se tenía que utilizar la reflexión para obtener los nombres de propiedades o parámetros.
En su ejemplo, nameof(T)
se 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 desea el nombre de cadena de una enumeración, usa .ToString()
:
enum MyEnum { ... FooBar = 7 ... }
Console.WriteLine(MyEnum.FooBar.ToString());
> "FooBar"
En realidad, esto es relativamente lento ya que .Net mantiene el valor de enumeración (es decir, 7
) y encuentra el nombre en tiempo de ejecución.
En su lugar utilice nameof
:
Console.WriteLine(nameof(MyEnum.FooBar))
> "FooBar"
Ahora .Net reemplaza el nombre de la enumeración con una cadena en el momento de la compilación.
Otro uso más es para cosas como INotifyPropertyChanged
el registro; en ambos casos desea que el nombre del miembro al que está llamando se pase 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....");
}
Otro caso de uso en el que nameof
la característica de C# 6.0 resulta útil : considere una biblioteca como Dapper que facilita mucho la recuperación de bases de datos. Aunque esta es una gran biblioteca, es necesario codificar los nombres de propiedades/campos dentro de la consulta. Lo que esto significa es que si decide cambiar el nombre de su propiedad/campo, hay muchas posibilidades de que olvide actualizar la consulta para usar nuevos nombres de campo. Con la interpolación de cadenas y nameof
sus funciones, el código se vuelve mucho más fácil de mantener y seguro.
Del ejemplo dado en el enlace.
sin nombre de
var dog = connection.Query<Dog>(
"select Age = @Age, Id = @Id",
new {Age = (int?) null, Id = guid});
con nombre de
var dog = connection.Query<Dog>(
$"select {nameof(Dog.Age)} = @Age, {nameof(Dog.Id)} = @Id",
new {Age = (int?) null, Id = guid});
Tu pregunta ya expresa el propósito. Debes ver que esto podría ser útil para registrar o generar 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á en lugar de devolver una excepción con un mensaje incorrecto .
Por supuesto, los usos no se limitan a esta sencilla situación. Puede usarlo nameof
siempre que sea útil para codificar el nombre de una variable o propiedad.
Los usos son múltiples si se consideran diversas situaciones de unión y reflexión. Es una excelente manera de llevar lo que fueron errores de tiempo de ejecución al tiempo de compilación.