Is c# 6.0 nameof() result interned?
Asked Answered
U

2

5

From what I can read the compiler just emits a string and nothing else really happens?

Is there any reason that the results of this call couldn't be interned? For a nameof(MyClass), if it happens a lot, it could, theoretically be worth it?

Unable answered 13/8, 2015 at 15:59 Comment(0)
M
7

Yes, it will be interned just as any other string literal.

This can be demonstrated with this TryRoslyn example where this:

public void M() 
{
    Console.WriteLine(nameof(M));
}

Is complied into this IL:

.method public hidebysig 
    instance void M () cil managed 
{
    // Method begins at RVA 0x2050
    // Code size 11 (0xb)
    .maxstack 8

    IL_0000: ldstr "M"
    IL_0005: call void [mscorlib]System.Console::WriteLine(string)
    IL_000a: ret
} // end of method C::M

You can see that "M" is being loaded using ldstr which means it is interned:

"The Common Language Infrastructure (CLI) guarantees that the result of two ldstr instructions referring to two metadata tokens that have the same sequence of characters return precisely the same string object (a process known as "string interning")."

From OpCodes.Ldstr Field

This can also be verified by running this example, which prints true:

Console.WriteLine(ReferenceEquals(nameof(Main), nameof(Main)));
Merryman answered 13/8, 2015 at 16:13 Comment(4)
So then nameof(MyClass) as object == nameof(MyClass) as object? Meaning memory saved?Unable
@Unable yes. "...the result of two ldstr instructions referring to two metadata tokens that have the same sequence of characters return precisely the same string object (a process known as "string interning")."Merryman
ah. I had always thought that every string was immutable and each literal was also new instance. This is a brilliant clarification.Unable
@Unable the thing to remember is that strings are reference types. So 2 string literals can point to the same memory in the intern pool.Urias
U
2

If the compiled output is a string literal, it will be interned. String literals are interned in .NET runtime.

Urias answered 13/8, 2015 at 16:6 Comment(2)
But if each call to nameof() generates a new string literal won't each instance be interned independently? i.e. nameof(MyClass) as object != nameof(MyClass) as object.Unable
@Unable no, both will be in the intern pool and the same reference object. Try string.IsInterned(nameof(MyClass))Urias

© 2022 - 2024 — McMap. All rights reserved.