为什么字符串插值不适用于const字符串

Ben*_*dEg 25 .net c# string-interpolation c#-6.0

为什么c#中的字符串插值不适用于const字符串?例如:

private const string WEB_API_ROOT = "/private/WebApi/";
private const string WEB_API_PROJECT = $"{WEB_API_ROOT}project.json";
Run Code Online (Sandbox Code Playgroud)

从我的角度来看,一切都在编译时就已知.或者这是一个稍后会添加的功能?

编译器消息:

分配给"DynamicWebApiBuilder.WEB_API_PROJECT"的表达式必须是常量.

非常感谢!

Ren*_*ogt 40

插值字符串只是转换为调用string.Format.所以你的上一行实际上是读

private const string WEB_API_PROJECT = string.Format("{0}project.json", WEB_API_ROOT);
Run Code Online (Sandbox Code Playgroud)

这不是编译时常量,因为包含了方法调用.


另一方面,字符串连接(简单的,常量字符串文字)可以由编译器完成,因此这将起作用:

private const string WEB_API_ROOT = "/private/WebApi/";
private const string WEB_API_PROJECT = WEB_API_ROOT + "project.json";
Run Code Online (Sandbox Code Playgroud)

或切换conststatic readonly:

private static readonly string WEB_API_PROJECT = $"{WEB_API_ROOT}project.json";
Run Code Online (Sandbox Code Playgroud)

所以string.Format在第一次访问声明类型的任何成员时初始化(和调用)字符串.


svi*_*ick 17

字符串插值表达式不被认为是常量的另一个原因是它们不是常数,即使它们的所有输入都是常量.具体而言,它们根据当前的文化而有所不同.尝试执行以下代码:

CultureInfo.CurrentCulture = CultureInfo.InvariantCulture;

Console.WriteLine($"{3.14}");

CultureInfo.CurrentCulture = new CultureInfo("cs-CZ");

Console.WriteLine($"{3.14}");
Run Code Online (Sandbox Code Playgroud)

它的输出是:

3.14
3,14
Run Code Online (Sandbox Code Playgroud)

请注意,输出是不同的,即使字符串插值表达式在两种情况下都相同.因此,const string pi = $"{3.14}"编译器生成的代码不清楚.


M.H*_*san 5

有在罗斯林项目的讨论 罗斯林即完成了以下结论:

阅读摘录:

这不是一个错误,它明确地设计为像这样的功能.你不喜欢它不会成为一个错误.串联字符串不需要String.Format,但这不是你正在做的事情.你正在插入它们,并且需要String.Format,这是基于插值在C#中如何工作的规范和实现.

如果要连接字符串,请继续使用与C#1.0相同的语法.根据使用情况将实现更改为不同的行为会产生意外结果:

  const string FOO = "FOO";
  const string BAR = "BAR";
  string foobar = $"{FOO}{BAR}";
  const string FOOBAR = $"{FOO}{BAR}"; // illegal today

  Debug.Assert(foobar == FOOBAR); // might not always be true
Run Code Online (Sandbox Code Playgroud)

甚至声明:

  private static readonly string WEB_API_PROJECT = $"{WEB_API_ROOT}project.json";
Run Code Online (Sandbox Code Playgroud)

编译器引发错误:

 "The name 'WEB_API_ROOT' does not exist in the current context". 
Run Code Online (Sandbox Code Playgroud)

应在同一上下文中定义变量"WEB_API_ROOT"

因此,对于OP的问题:为什么字符串插值不适用于const字符串?答:这是C#6规格.有关更多详细信息,请阅读.NET编译器平台("Roslyn") - C#的字符串插值


Tob*_*s J 5

C# 10(在撰写本文时目前为预览版)将包括使用const内插字符串的能力,只要使用不涉及文化可能影响结果的场景(例如本示例)。

因此,如果插值只是将字符串连接在一起,它将在编译时工作。

const string Language = "C#";
const string Platform = ".NET";
const string Version = "10.0";
const string FullProductName = $"{Platform} - Language: {Language} Version: {Version}";
Run Code Online (Sandbox Code Playgroud)

如果preview选择了语言版本(<LanguageVersion>preview</LanguageVersion>在您的项目文件中设置),那么现在在 VS 2019 版本 16.9 中允许这样做。

https://github.com/dotnet/csharplang/issues/2951#issuecomment-736722760