24

I'd like to use the following C#6 code

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

... and get the following output:

joe

The following attempt

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

fails as nameof cannot be applied to this. Is it there a workaround for this problem?

EDIT. The scenario I'm working with assures that no two references point to the same Self object.

ΩmegaMan
  • 29,542
  • 12
  • 100
  • 122
nincsmail
  • 241
  • 1
  • 2
  • 4
  • 4
    I don't think so. Consider `var joe = new Self(); var jack = joe;`. Should `Name` return `"joe"`, `"jack"`, or both? – Frédéric Hamidi Jan 08 '15 at 10:29
  • 2
    What's wrong with `nameof(joe)` – i3arnon Jan 08 '15 at 10:32
  • You can learn some usages of nameof(..) from this post : http://www.spicelogic.com/Journal/C-sharp-6-most-exciting-features-9 – Emran Hussain Jan 24 '15 at 18:34
  • 1
    Unicity of different instances of the same class is achieved through `ReferenceEquals`, `Equals` and `GetHashCode` methods, maybe with a custom implementation (for example `Equals` can check an `Id` field/property on the two inspected instances). Your idea of using `nameof` to achieve such a goal is very strange... – Massimiliano Kraus Nov 16 '16 at 22:42
  • Why can't we use `this.GetType().Name`? – Flimtix Mar 30 '22 at 10:39

5 Answers5

21

No, nameof is designed to refer to the compile-time name of the member you're referring to. If you want an object to have a Name property as part of its state, that is independent of how you get to the Name property - as Frédéric Hamidi says, there could be multiple variables (or none) referring to the same object. Basically you need to differentiate between an object and a variable which happens to refer to that object.

However, if you have a constructor to specify the name, you could then use a couple of tricks to make it easier to get the right name:

class Self
{
    public string Name { get; }

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

Then:

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));
    }
}
James Wilkins
  • 6,836
  • 3
  • 48
  • 73
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
11

Maybe you can use the following method:

    class Self
    {
       public override string ToString()
       {
            return this.GetType().Name;
       }
    }
mehrandvd
  • 8,806
  • 12
  • 64
  • 111
Ivan Zalutskii
  • 109
  • 1
  • 5
6

You can simply use nameof on the variable itself:

Console.WriteLine(nameof(joe));

Here's a working example using the current Roslyn version

i3arnon
  • 113,022
  • 33
  • 324
  • 344
1

The idea for nameof is to make things type safe for specifying program elements during runtime but with compile time type safety checking.

One should atomize what one wants to display. For example in my error messages I include the pertinent information of the class name and the method as such and its checked, so if I change any of the names they are caught as a compile time error:

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

Output

Operation.Excecute has exception:
...

With that said you should override ToString() and report the class name as such

public override string ToString() { return nameof(Self); } 
ΩmegaMan
  • 29,542
  • 12
  • 100
  • 122
0

I usually create an internal constant for it when dealing with long class names:

private const string SomeConst = nameof(Self);

Then you can use that in your code:

Console.WriteLine(SomeConst);
CodeSoul
  • 1
  • 1