2014-06-26 15 views
5

Khi đi qua mã nguồn dự án, tôi tình cờ gặp một phương pháp và tự hỏi về một điều. Hai phương pháp sau đây có giống hệt nhau từ quan điểm hiệu năng/bộ nhớ/trình biên dịch không?Biến trở về có được tự động tạo bởi trình biên dịch không?

public static string Foo(string inputVar) 
{ 
    string bar = DoSomething(inputVar); 
    return bar; 
} 

public static string Foo(string inputVar) 
{ 
    return DoSomething(inputVar); 
} 

Biến trở về có được tạo tự động bởi trình biên dịch không?

+1

Nếu * mà * là một nút cổ chai hiệu suất thực tế cho bạn, xin chúc mừng. Tuy nhiên, kinh nghiệm của tôi cho thấy nó không thể. Viết mã mà bạn thấy rõ ràng nhất, lo lắng về hiệu suất khi các vấn đề hiệu suất thực sự được chứng minh và bạn xác định nơi tốt nhất để đầu tư tài nguyên của mình. –

+2

@Damien_The_Unbeliever: Đây không phải là câu hỏi về hiệu suất. Chỉ cần một câu hỏi đơn giản về cách thức .Net/C# hoạt động. –

+0

@NikhilAgrawal - vì vậy đề cập đến hiệu suất trong câu hỏi và câu hỏi là * được gắn thẻ * hiệu suất nên được bỏ qua? –

Trả lời

8

Sử dụng Bộ tách IL (được bao gồm trong .NET SDK/VS), bạn có thể xem IL do trình biên dịch tạo ra. Mã được tạo ra bằng cách sử dụng VS2013 (không phải Roslyn).

Một đầu cung cấp cho các IL sau:

.method public hidebysig static string Foo(string inputVar) cil managed 
{ 
    // Code size  14 (0xe) 
    .maxstack 1 
    .locals init ([0] string bar, 
      [1] string CS$1$0000) 
    IL_0000: nop 
    IL_0001: ldarg.0 
    IL_0002: call  string TestIL.Program::DoSomething(string) 
    IL_0007: stloc.0 
    IL_0008: ldloc.0 
    IL_0009: stloc.1 
    IL_000a: br.s  IL_000c 
    IL_000c: ldloc.1 
    IL_000d: ret 
} // end of method Program::Foo 

Thứ hai:

.method public hidebysig static string Foo(string inputVar) cil managed 
{ 
    // Code size  12 (0xc) 
    .maxstack 1 
    .locals init ([0] string CS$1$0000) 
    IL_0000: nop 
    IL_0001: ldarg.0 
    IL_0002: call  string TestIL.Program::DoSomething(string) 
    IL_0007: stloc.0 
    IL_0008: br.s  IL_000a 
    IL_000a: ldloc.0 
    IL_000b: ret 
} // end of method Program::Foo 

Sự khác biệt dường như là người đầu tiên tạo ra một mục bổ sung trong bảng phương pháp dân địa phương. Nếu điều này được tối ưu hóa bởi trình biên dịch JIT mà tôi không biết.

Để trả lời câu hỏi: Không, trình biên dịch tự động tạo biến cục bộ trong trường hợp này, nhưng trong trường hợp nâng cao hơn có thể làm (như trả về x * (y + z)).

Edit: Nếu bạn bật "Tối ưu hóa mã" thậm chí rõ ràng hơn của nó:

.method public hidebysig static string Foo(string inputVar) cil managed 
{ 
    // Code size  9 (0x9) 
    .maxstack 1 
    .locals init ([0] string bar) 
    IL_0000: ldarg.0 
    IL_0001: call  string TestIL.Program::DoSomething(string) 
    IL_0006: stloc.0 
    IL_0007: ldloc.0 
    IL_0008: ret 
} // end of method Program::Foo 

.method public hidebysig static string Foo(string inputVar) cil managed 
{ 
    // Code size  7 (0x7) 
    .maxstack 8 
    IL_0000: ldarg.0 
    IL_0001: call  string TestIL.Program::DoSomething(string) 
    IL_0006: ret 
} // end of method Program::Foo 
+2

Cân nhắc bật tối ưu hóa trình biên dịch. Tôi hy vọng nó sẽ cắt giảm IL đến 3 hướng dẫn tương ứng 5 và sẽ làm cho sự khác biệt rõ ràng hơn. – sloth

+0

Điểm tốt và đó cũng là trường hợp. – svenslaggare

+0

Cặp còn lại 'stloc'/'ldloc' trông giống như trên bề mặt của nó, có thể tối ưu hóa một cách trivially. Bất kỳ manh mối nào về lý do tại sao người tối ưu không làm điều đó? Hoặc, hãy nghĩ về nó, hiệu ứng '.maxstack 8' có tác dụng gì? – ClickRick

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