2009-09-09 20 views
11

Bất cứ ai cũng có ý tưởng tại sao một phương pháp chung hạn chế T đến lớp sẽ có hướng dẫn đấm bốc trong mã MSIL tạo ra?Tại sao phương pháp chung với kết quả T: lớp học trong boxing?

Tôi khá ngạc nhiên bởi điều này vì chắc chắn kể từ khi T bị ràng buộc với một loại tham chiếu mã được tạo ra không cần phải thực hiện bất kỳ quyền anh nào.

Đây là C# code:

protected void SetRefProperty<T>(ref T propertyBackingField, T newValue) where T : class 
{ 
    bool isDifferent = false; 

    // for reference types, we use a simple reference equality check to determine 
    // whether the values are 'equal'. We do not use an equality comparer as these are often 
    // unreliable indicators of equality, AND because value equivalence does NOT indicate 
    // that we should share a reference type since it may be a mutable. 

    if (propertyBackingField != newValue) 
    { 
     isDifferent = true; 
    } 
} 

Đây là IL tạo:

.method family hidebysig instance void SetRefProperty<class T>(!!T& propertyBackingField, !!T newValue) cil managed 
{ 
    .maxstack 2 
    .locals init (
     [0] bool isDifferent, 
     [1] bool CS$4$0000) 
    L_0000: nop 
    L_0001: ldc.i4.0 
    L_0002: stloc.0 
    L_0003: ldarg.1 
    L_0004: ldobj !!T 
    L_0009: box !!T 
    L_000e: ldarg.2 
    L_000f: box !!T 
    L_0014: ceq 
    L_0016: stloc.1 
    L_0017: ldloc.1 
    L_0018: brtrue.s L_001e 
    L_001a: nop 
    L_001b: ldc.i4.1 
    L_001c: stloc.0 
    L_001d: nop 
    L_001e: ret 
} 

Thông báo các hộp !! T hướng dẫn.

Bất kỳ ai cũng biết tại sao điều này được tạo ra?

Bất kỳ ai có ý tưởng nào để tránh điều này?

Xin cảm ơn, Phil

+1

Jon ra ngoài tôi đoán :-) – Peter

+7

Tôi đã tìm thấy câu trả lời của bạn và đó là một bản sao! Câu hỏi tuyệt vời, nhân tiện :) Xin vui lòng xem http://stackoverflow.com/questions/646517/boxing-when-using-generics-in-c –

+3

Ý chính của câu trả lời tôi đã liên kết là một hướng dẫn đấm bốc trên một tham chiếu loại là hiệu quả một nop. Điều này cho phép trình biên dịch tự do phát ra các chỉ dẫn đấm bốc có thể được loại bỏ bởi JIT đối với các kiểu được xây dựng đã đóng được tạo ra với một kiểu tham chiếu làm đối số kiểu chung. Trong trường hợp của bạn (vì 'T' bị ràng buộc như một kiểu tham chiếu), cả hai lệnh boxing được phát ra sẽ không bao giờ được chạy. –

Trả lời

2

Bạn không phải lo lắng về bất kỳ sự xuống cấp hiệu suất nào từ hướng dẫn box vì nếu đối số của nó là loại tham chiếu, hướng dẫn box sẽ không làm gì cả. Mặc dù nó vẫn còn lạ rằng hướng dẫn box thậm chí đã được tạo ra (có thể lười biếng/thiết kế dễ dàng hơn khi tạo mã?).

0

Tôi tin rằng điều này là do thiết kế. Bạn không ràng buộc T với một lớp cụ thể, vì vậy rất có thể nó sẽ truyền nó thành đối tượng. Do đó tại sao bạn thấy IL bao gồm quyền anh.

Tôi sẽ thử mã này với vị trí T: ActualClass

+3

Nếu bạn làm T: ActualClass, tại sao bận tâm với Generics? –

+0

Bởi vì bạn có thể hạn chế T đến các cấp cao hơn ... như iSomeInterface ... –

+1

Chris, nếu T là một đối tượng, nó sẽ không được đóng trước khi đẩy vào ngăn xếp? Tại sao sau đó sẽ có bất kỳ hoạt động đấm bốc nào cần được thực hiện trên nó? Tôi mong đợi toán tử == kiểm tra tính bình đẳng tham chiếu nếu T là một đối tượng, do đó, điều này cũng sẽ không yêu cầu các hoạt động un/boxing. – Phil

1

Tôi không chắc chắn tại sao bất kỳ quyền anh nào đang làm mờ. Một cách có thể để tránh đấm bốc là không sử dụng nó. Chỉ cần biên dịch lại mà không cần đấm bốc. Ví dụ:

.assembly recomp_srp 
{ 
    .ver 1:0:0:0 
} 

.class public auto ansi FixedPBF 
{ 

.method public instance void .ctor() cil managed 
{ 

} 

.method hidebysig public instance void SetRefProperty<class T>(!!T& propertyBackingField, !!T newValue) cil managed 
{ 
    .maxstack 2  
     .locals init (bool isDifferent, bool CS$4$0000) 

     ldc.i4.0 
     stloc.0 
     ldarg.1 
     ldobj !!T 
     ldarg.2 
     ceq 
     stloc.1 
     ldloc.1 
     brtrue.s L_0001 
     ldc.i4.1 
     stloc.0 
     L_0001: ret 

} 

} 

... nếu bạn lưu vào một tập tin recomp_srp.msil bạn chỉ có thể biên dịch lại như vậy:

ildasm/dll recomp_srp.msil

Và nó chạy OK mà không có sự boxing trên kết thúc của tôi:

 FixedPBF TestFixedPBF = new FixedPBF(); 

     TestFixedPBF.SetRefProperty<string>(ref TestField, "test2"); 

... tất nhiên, tôi cần thay đổi lại thành công cộng, bạn cần thực hiện lại phần còn lại.

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