2016-09-12 21 views
11

Tại sao nội suy chuỗi trong C# không hoạt động với các chuỗi const? Ví dụ:Tại sao nội suy chuỗi không hoạt động với các chuỗi const

private const string WEB_API_ROOT = "/private/WebApi/"; 
private const string WEB_API_PROJECT = $"{WEB_API_ROOT}project.json"; 

Từ quan điểm của tôi, mọi thứ được biết đến lúc biên dịch. Hoặc là một tính năng sẽ được thêm vào sau này? nhắn

Compiler:

The expression being assigned to 'DynamicWebApiBuilder.WEB_API_PROJECT' must be constant.

Cảm ơn rất nhiều!

+8

Chuỗi nội suy chỉ được chuyển thành lệnh gọi 'string.Format'. – juharr

+3

Để giải quyết sự cố, thay thế 'const' bằng' readonly' –

+4

@juharr: điều này không thực sự giải thích tại sao trình biên dịch không thể kiểm tra xem tham số bạn vượt qua có phải là hằng số có thể được sử dụng để khởi tạo hằng số này hay không. Nó được cho phép với các chuỗi ký tự xâu chuỗi. Vậy tại sao nó không được phép với các chuỗi ký tự kết hợp, trình biên dịch có thể sử dụng cùng một kỹ thuật. –

Trả lời

22

Chuỗi nội suy được chuyển đổi đơn giản thành các cuộc gọi đến string.Format. Vì vậy, dòng trên của bạn thực sự đọc

private const string WEB_API_PROJECT = string.Format("{0}project.json", WEB_API_ROOT); 

Và đây không phải là hằng số thời gian biên dịch khi gọi phương thức được bao gồm.


Mặt khác, chuỗi nối (đơn giản, literals chuỗi liên tục) có thể được thực hiện bởi trình biên dịch, vì vậy đây sẽ làm việc:

private const string WEB_API_ROOT = "/private/WebApi/"; 
private const string WEB_API_PROJECT = WEB_API_ROOT + "project.json"; 

hoặc chuyển const-static readonly:

private static readonly string WEB_API_PROJECT = $"{WEB_API_ROOT}project.json"; 

để chuỗi được khởi tạo (và string.Format gọi) tại lần truy cập đầu tiên vào bất kỳ tôi mber của loại khai báo.

+0

Điều đó có ý nghĩa. Cảm ơn rất nhiều :) – BendEg

+1

Đó là sự hòa hợp đơn giản là rõ ràng, chỉ nghĩ rằng tôi cũng có thể sử dụng tính năng C# 6 mới ở đây. – BendEg

+0

@Rene, Ngay cả khi sử dụng [chuỗi đọc riêng tư tĩnh], trình biên dịch đưa ra lỗi "Tên 'WEB_API_ROOT' không tồn tại trong ngữ cảnh hiện tại". Biến 'WEB_API_ROOT' phải được định nghĩa trong cùng một ngữ cảnh. –

9

Giải thích bổ sung tại sao biểu thức nội suy chuỗi không được coi là hằng số là chúng không phải là hằng số, ngay cả khi tất cả đầu vào của chúng là hằng số. Cụ thể, chúng thay đổi dựa trên văn hóa hiện tại. Hãy thử thực hiện các đoạn mã sau:

CultureInfo.CurrentCulture = CultureInfo.InvariantCulture; 

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

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

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

đầu ra của nó là:

3.14 
3,14 

Lưu ý rằng đầu ra là khác nhau, mặc dù khái niệm chuỗi suy là như nhau trong cả hai trường hợp. Vì vậy, với const string pi = $"{3.14}", nó sẽ không được rõ ràng những gì trình biên dịch nên tạo ra.

4

Có một cuộc thảo luận trong dự án Roslyn tại roslyn rằng hoàn thiện kết luận sau:

Đọc đoạn trích:

It's not a bug, it was explicitly designed to function like this. You not liking it doesn't make it a bug. String.Format isn't needed for concatenating strings, but that's not what you're doing. You're interpolating them, and String.Format is needed for that based on the spec and implementation of how interpolation works in C#.

If you want to concatenate strings, go right ahead and use the same syntax that has worked since C# 1.0. Changing the implementation to behave differently based on usage would produce unexpected results:

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 

Ngay cả những tuyên bố:

private static readonly string WEB_API_PROJECT = $"{WEB_API_ROOT}project.json"; 

Trình biên dịch nêu ra lỗi:

"The name 'WEB_API_ROOT' does not exist in the current context". 

Biến 'WEB_API_ROOT' nên được định nghĩa trong bối cảnh tương tự

Vì vậy, đối với những câu hỏi của OP: Tại sao chuỗi suy không hoạt động với chuỗi const? Trả lời: Đó là thông số kỹ thuật của C# 6. để biết thêm chi tiết, hãy đọc .NET Compiler Platform ("Roslyn") -String Interpolation for C#

+0

Lưu ý rằng takeaway ở đây dường như ít nhiều: Có thể xác định (và thiết lập) một nền văn bản mặc định giả định sửa đổi tất cả các chuỗi định dạng, điều này sẽ thay đổi giá trị trả về của các lệnh 'string.Format()' chỉ 'const'' string's, ** khi chạy **. Vì việc kiểm tra văn hóa có thể xảy ra, tốt nhất, trong bộ khởi tạo tĩnh, nhưng giá trị chuỗi 'const' chỉ xảy ra ở thời gian trình biên dịch, một chuỗi nội suy' const' có thể trở thành không bằng giá trị của chuỗi nội suy trong thời gian chạy, nếu văn hóa tại thời gian biên dịch không phải là văn hóa trong thời gian chạy. – jrh

Các vấn đề liên quan