¿Cuál es el propósito del nombre de?

Resuelto atikot asked hace 9 años • 17 respuestas

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 Ttipo en lugar del usado.

¿Alguna idea sobre el propósito?

atikot avatar Jul 29 '15 16:07 atikot
Aceptado

¿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 PropertyChangedevento? 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 SomePropertyprovocará 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 SomeOtherPropertyo 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é infoofno lo logró, mientras que nameofsí)

Patrick Hofman avatar Jul 29 '2015 09:07 Patrick Hofman

Es realmente útil para ArgumentExceptiony sus derivados:

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

Ahora, si alguien refactoriza el nombre del inputpará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 nameofes 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 INotifyPropertyChangedel 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....");
}
Keith avatar Jul 29 '2015 09:07 Keith

Otro caso de uso en el que nameofla 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 nameofsus 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});
Sateesh Pagolu avatar Nov 16 '2016 01:11 Sateesh Pagolu

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 nameofsiempre 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.

Jodrell avatar Jul 29 '2015 09:07 Jodrell