Как обрабатывать nameof(this) для сообщения имени класса

Я хотел бы использовать следующий код С# 6

var joe = new Self();
Console.WriteLine(joe);

... и получить следующий вывод:

Джо

Следующая попытка

class Self {
  public string Name { get; set; } = nameof(this);
  public override string ToString() {
    return Name;
  }
}

терпит неудачу, поскольку nameof не может быть применен к this. Есть ли обходной путь для этой проблемы?

ИЗМЕНИТЬ. Сценарий, с которым я работаю, гарантирует, что никакие две ссылки не указывают на один и тот же объект Self.


person nincsmail    schedule 08.01.2015    source источник
comment
Я так не думаю. Рассмотрим var joe = new Self(); var jack = joe;. Должен ли Name возвращать "joe", "jack" или оба?   -  person Frédéric Hamidi    schedule 08.01.2015
comment
Что не так с nameof(joe)   -  person i3arnon    schedule 08.01.2015
comment
Вы можете узнать о некоторых случаях использования nameof(..) из этого поста: spicelogic.com/Journal/C-sharp-6-most-exciting-features-9   -  person Emran Hussain    schedule 24.01.2015
comment
Уникальность разных экземпляров одного и того же класса достигается с помощью методов ReferenceEquals, Equals и GetHashCode, возможно, с пользовательской реализацией (например, Equals может проверять поле/свойство Id в двух проверяемых экземплярах). Ваша идея использовать nameof для достижения такой цели очень странная...   -  person Massimiliano Kraus    schedule 17.11.2016


Ответы (5)


Нет, nameof предназначен для ссылки на имя во время компиляции члена, на который вы ссылаетесь. Если вы хотите, чтобы объект имел свойство Name как часть своего состояния, это не зависит от того, как вы добираетесь до свойства Name — как говорит Фредерик Хамиди, может быть несколько переменных (или ни одной), ссылающихся на к тому же объекту. В основном вам нужно различать объект и переменную, которая ссылается на этот объект.

Однако, если у вас есть конструктор для указания имени, вы можете использовать пару приемов, чтобы упростить получение правильного имени:

class Self
{
    public string Name { get; }

    public Self([CallerMemberName] string name = null)
    {
        this.Name = name;
    }
}

Затем:

class Foo
{
    private Self me = new Self(); // Equivalent to new Self("me")

    public void SomeMethod()
    {
        // Can't use the default here, as it would be "SomeMethod".
        // But we can use nameof...
        var joe = new Self(nameof(joe));
    }
}
person Jon Skeet    schedule 08.01.2015

Вы можете просто использовать nameof для самой переменной:

Console.WriteLine(nameof(joe));

Here's a working example using the current Roslyn version

person i3arnon    schedule 08.01.2015

Возможно, вы можете использовать следующий метод:

    class Self
    {
       public override string ToString()
       {
            return this.GetType().Name;
       }
    }
person Ivan Zalutskiy    schedule 09.06.2018

Идея nameof состоит в том, чтобы сделать вещи безопасными для указания элементов программы во время выполнения, но с проверкой безопасности типов во время компиляции.

Нужно атомизировать то, что вы хотите отобразить. Например, в свои сообщения об ошибках я включаю соответствующую информацию об имени класса и методе как таковом и его проверке, поэтому, если я изменю любое из имен, они будут обнаружены как ошибка времени компиляции:

class Operation
{
  public void Execute()
  { 
    try { ... }
    catch (Exception ex)
    {
    Console.Writeline($"{nameof(Operation)}.{nameof(Execute)} has encountered exception:{Environment.NewLine}{Environment.NewLine}{ex.Message}" );
    }
   }
}

Вывод

Operation.Excecute has exception:
...

С учетом сказанного вы должны переопределить ToString() и сообщить имя класса как таковое.

public override string ToString() { return nameof(Self); } 
person ΩmegaMan    schedule 10.01.2016

Обычно я создаю для него внутреннюю константу при работе с длинными именами классов:

private const string SomeConst = nameof(Self);

Затем вы можете использовать это в своем коде:

Console.WriteLine(SomeConst);
person CodeSoul    schedule 15.03.2018