2014-10-26 30 views
103

Trong C# 6, bạn có thể sử dụng toán tử nameof() để nhận một chuỗi chứa tên biến hoặc loại.Là nameof() được đánh giá tại thời gian biên dịch?

Điều này có được đánh giá vào thời gian biên dịch hay khi chạy qua một số API Roslyn không?

Bạn có thể đọc về nhà điều hành nameof() tại sốđược chỉ ra trong accepted answer hoặc dedicated post at my blog. On 2000things.com, bạn có thể tìm thấy mô tả và ví dụ về việc sử dụng nó.

+0

Roslyn là nền tảng trình biên dịch mới. Nó chỉ được sử dụng trong thời gian biên dịch. –

+2

@PauloMorgado không đúng, bạn có thể sử dụng Rosyln trong thời gian chạy để làm việc.Chẳng hạn như xây dựng trình soạn thảo mã trực tiếp hoặc sử dụng công cụ phân tích cú pháp của Rosyln để thực hiện mọi thứ với cây hoặc biểu thức hoặc một cái gì đó –

+0

@ChrisMarisic đó là ấn tượng của tôi, nhưng tôi đã không trả lời vì kiến ​​thức của tôi về chủ đề bị giới hạn (do đó câu hỏi của tôi). Tôi đã đi qua này: http://scriptcs.net/ đó là một ví dụ khá tốt về sức mạnh của Roslyn, và tôi tin rằng thời gian chạy công cụ, nhưng tôi có thể sai vì tôi không khá thông tin về nó. – Gigi

Trả lời

105

Có. nameof() được đánh giá tại thời điểm biên dịch. Nhìn vào phiên bản mới nhất của thông số kỹ thuật:

Biểu thức tên là một hằng số. Trong mọi trường hợp, nameof (...) là được đánh giá tại thời điểm biên dịch để tạo chuỗi. Đối số của nó không được đánh giá trong thời gian chạy và được coi là mã không thể truy cập (tuy nhiên, nó không phát ra cảnh báo "mã không truy cập được").

Từ nameof operator - v5

Bạn có thể thấy rằng với this TryRoslyn example nơi này:

public class Foo 
{ 
    public void Bar() 
    { 
     Console.WriteLine(nameof(Foo)); 
    } 
} 

Được biên soạn và dịch ngược vào này:

public class Foo 
{ 
    public void Bar() 
    { 
     Console.WriteLine("Foo"); 
    } 
} 

nó chạy thời gian tương đương là:

public class Foo 
{ 
    public void Bar() 
    { 
     Console.WriteLine(typeof(Foo).Name); 
    } 
} 

Như đã đề cập trong các ý kiến, đó có nghĩa là khi bạn sử dụng nameof trên các thông số gõ vào một kiểu generic, không mong đợi để có được tên của các loại động thực tế sử dụng như một tham số kiểu thay vì chỉ tên của thông số loại. Vì vậy, đây:

public class Foo 
{ 
    public void Bar<T>() 
    { 
     Console.WriteLine(nameof(T)); 
    } 
} 

Will become này:

public class Foo 
{ 
    public void Bar<T>() 
    { 
     Console.WriteLine("T"); 
    } 
} 
+0

"Thời gian biên dịch" ở đây là gì? Biên dịch thành MSIL hoặc biên dịch thành mã gốc? – Mehrdad

+6

@Mehrdad Trình biên dịch C# tạo IL. – i3arnon

+2

Câu hỏi nhanh, tôi có thể sử dụng nameof trong trường hợp chuyển đổi không? – Spell

55

tôi muốn làm phong phú thêm the answer provided by @I3arnon với một bằng chứng cho thấy nó được đánh giá ở thời gian biên dịch.

Giả sử tôi muốn in tên của một biến trong Console bằng cách sử dụng nameof điều hành:

var firstname = "Gigi"; 
var varname = nameof(firstname); 
Console.WriteLine(varname); // Prints "firstname" to the console 

Khi bạn xem phần MSIL được tạo ra bạn sẽ thấy rằng nó tương đương với một tuyên bố chuỗi vì một đối tượng tham chiếu đến một chuỗi được đẩy vào stack sử dụng ldstr điều hành:

IL_0001: ldstr "Gigi" 
IL_0006: stloc.0 
IL_0007: ldstr "firstname" 
IL_000c: stloc.1 
IL_000d: ldloc.1 
IL_000e: call void [mscorlib]System.Console::WriteLine(string) 

Bạn sẽ nhận thấy rằng tuyên bố chuỗi firstname và sử dụng gener nameof điều hành cùng một mã trong MSIL, có nghĩa là nameof là hiệu quả như tuyên bố một biến chuỗi.

+2

Nếu MSIL được dịch ngược mã nguồn, cách dễ dàng sẽ cho decompiler để nhận ra nó là toán tử 'nameof', không phải là một chuỗi cứng được mã hóa đơn giản? – ADTC

+10

Đó là một câu hỏi hay! bạn có thể đăng nó như một câu hỏi mới trên SO nếu bạn muốn nhận được một lời giải thích chi tiết :) .. tuy nhiên câu trả lời ngắn gọn là trình giải mã sẽ không thể tìm ra nó là toán tử nameof, nhưng sẽ sử dụng chuỗi ký tự thay thế . Tôi đã xác minh đó là trường hợp với ILSpy và Reflector. –

+2

@ADTC: Khi nameof được thay thế hoàn toàn bằng tải-a-string-up-the-stack, làm cách nào để trình biên dịch thậm chí có thể đoán được đó là tên của một tên chứ không phải là tham số hằng số đơn giản? – quetzalcoatl

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