Цепная интерполяция строки stati c не работает должным образом - PullRequest
2 голосов
/ 17 января 2020

Я использовал код, подобный следующему:

public static class Program {
    public static void Main() {
        Console.WriteLine(hello);
    }

    internal static readonly string hello = $"hola {name} {num}";
    internal static readonly string name  = $"Juan {num}";
    public const int num = 4;
}

В этом случае, когда я получил значение hello, оно вернуло мне "hola 4", поэтому кажется, что при интерполяции возникает проблема другая строка, использующая интерполяцию. Мое ожидаемое поведение - «Привет, Хуан 4 4», или если язык не поддерживает этот вид цепной интерполяции, ошибка во время компиляции.

Кто-нибудь знает, почему C# получает такое поведение?

Ответы [ 2 ]

7 голосов
/ 17 января 2020
Поля

Stati c инициализируются в порядке их объявления. Итак, что происходит:

  1. Изначально hello и name оба null. num является константой.
  2. hello инициализирован. name по-прежнему null. Тем не менее, num является константой, поэтому она подставляется правильно. hello имеет значение "hola 4"
  3. name инициализировано.

Почему тот факт, что num является константой, имеет значение? Помните, что значение const подставляется непосредственно в места, которые он использует, компилятором во время компиляции. Поэтому, если вы посмотрите на то, что генерирует компилятор, вы увидите:

public static class Program
{
    internal static readonly string hello = string.Format("hola {0} {1}", name, 4);

    internal static readonly string name = string.Format("Juan {0}", 4);

    public const int num = 4;

    public static void Main()
    {
        Console.WriteLine(hello);
    }
}

(Предоставлено SharpLab )

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


Если у вас есть поля * stati c, которые зависят друг от друга, вы должны быть очень осторожны с порядком, в котором они объявлены, или это обычно более безопасно (и более читабельно!) просто использовать конструктор stati c:

public static class Program {
    static Program() {
        name = $"Juan {num}";
        hello = $"hola {name} {num}";
    }

    public static void Main() {
        Console.WriteLine(hello);
    }

    internal static readonly string hello;
    internal static readonly string name;
    public const int num = 4;
}
1 голос
/ 17 января 2020

Вы можете переключать позиции hello и name, например,

internal static readonly string name = $"Juan {num}";
internal static readonly string hello = $"hola {name} {num}";

Поскольку при назначении hello, name еще не назначено.

После изменения порядка name и hello он будет печататься так, как вы хотите

Prints => "hola Juan 4 4"

...