2010-08-03 42 views
11

Tôi cơ bản tạo ra một lớp nhẹ, nó được truyền trong khoảng 10 tham số, nó không thay đổi các tham số này, nó chỉ lưu trữ cục bộ khi trong hàm tạo.Vượt qua giá trị vs Vượt qua hiệu năng tham chiếu C# .net

Một số loại tham chiếu (chuỗi, lớp) khác là loại giá trị (int, bool, enums).

Câu hỏi của tôi là tôi nên chuyển tất cả những điều này vào (trừ các lớp học của tôi) với từ khóa 'ref'?

Xem xét của tôi ở đây là hiệu suất.

+0

Tôi không thấy nó giúp như thế nào. Ngay cả khi 'ref' tiết kiệm thời gian sao chép một cấu trúc, bạn không thể giữ' ref' là thành viên của lớp, 'ref' chỉ hữu dụng trong một phương thức. – Kobi

+0

có thể trùng lặp với từ khóa [hiệu ứng C# 'ref], hiệu suất] (http://stackoverflow.com/questions/900903/c-sharp-ref-keyword-performance) – nawfal

Trả lời

16

Chỉ sử dụng ref nếu phương pháp này cần phải thay đổi các thông số, và những thay đổi cần phải được thông qua vào mã gọi. Bạn chỉ nên tối ưu hóa điều này nếu bạn đã chạy nó thông qua một profiler và xác định rằng nút cổ chai thực sự là CLR sao chép các tham số phương thức vào ngăn xếp.

Ghi nhớ CLR được tối ưu hóa rất nhiều cho các phương thức gọi với các tham số, vì vậy tôi không nghĩ đây là vấn đề.

3

Nếu lớp chỉ giữ tham số có thể bạn nên sử dụng cấu trúc?

Có thể điều này đáng quan tâm?

When to use struct?

6

Không. Đối với các loại tham chiếu, bạn đang chuyển một tham chiếu, không cần chuyển tham chiếu theo tham chiếu trừ khi bạn muốn thay đổi tham chiếu trỏ đến, ví dụ: gán cho nó một đối tượng mới. Đối với các loại giá trị, bạn có thể chuyển qua tham chiếu, nhưng trừ khi bạn có vấn đề về hiệu suất, tôi sẽ không làm điều này. Đặc biệt là nếu các loại trong câu hỏi là nhỏ (4 byte hoặc ít hơn), có rất ít hoặc không đạt được hiệu suất, thậm chí có thể là một hình phạt.

+1

Đó là sự hiểu biết của tôi rằng luôn luôn mất hiệu suất khi truyền các loại giá trị bằng cách tham chiếu, bởi vì các loại giá trị phải được đóng hộp. Theo như tôi hiểu (từ C# In Depth kỳ diệu, bởi cùng một tuyệt vời @JonSkeet) đi qua một kiểu giá trị như tham số tham chiếu sẽ không bao giờ làm tăng hiệu năng, trái lại nó sẽ luôn làm giảm hiệu năng. –

+0

@ BenH: _ "luôn luôn có hiệu suất mất khi chuyển các loại giá trị theo tham chiếu, bởi vì các loại giá trị phải được đóng hộp" _ - không. bạn dường như khó hiểu khi đi qua tham chiếu với tham chiếu _a_ đi qua. Chúng không giống nhau. Sử dụng 'ref' với một loại giá trị không có giá trị. Nó chuyển một tham chiếu (con trỏ) tới biến giữ giá trị. –

+0

@PeterDuniho: Trong phạm vi nội bộ của .NET, chuyển đối số bằng tham chiếu chuyển một "byref". Tôi đã không thấy thuật ngữ đó được sử dụng nhiều trong các cuộc thảo luận, nhưng tôi nghĩ sẽ ít nhầm lẫn hơn nếu nó được sử dụng thường xuyên hơn, vì nó nghe có vẻ ít hơn "tham chiếu đối tượng" so với cụm từ "truyền bằng tham chiếu". – supercat

3

Không. Việc truyền tham số theo tham chiếu sẽ bổ sung thêm chi phí, do đó, nó sẽ chỉ làm giảm hiệu suất.

+0

Im sử dụng để c + + vì vậy tôi có thể hoàn toàn sai, nhưng bạn có thể xây dựng này nhiều hơn? cho phép nói rằng tôi có một số đối tượng lớn, wouldnt: vượt qua bằng cách tham khảo chỉ vượt qua một địa chỉ của dữ liệu thay vì phải sao chép các đối tượng hoàn chỉnh? –

+0

@SvenvandenBoogaart bạn không đối phó với nó. Bạn đang tạo một con trỏ mới bên trong phương thức để giữ giá trị đối tượng. Nhưng việc thay đổi giá trị con trỏ sẽ không sửa đổi con trỏ bên ngoài được sử dụng để chuyển giá trị này cho cuộc gọi phương thức. –

2

Theo tôi hiểu bạn có một lớp chỉ có các trường và một hàm tạo gán các tham số cho các trường đó, đúng không?

Nếu đúng như vậy, tôi sẽ xem xét sử dụng ref trong thực tiễn không đúng của hàm tạo. Nếu bạn gán tham số cho một trường trong lớp đó, nó sẽ được lưu trữ theo giá trị trong mọi trường hợp. Vì vậy, nếu bạn không thay đổi giá trị trong hàm tạo thì không cần sử dụng nó theo tham chiếu.

+0

+1 - chính xác những gì tôi không thể nói rõ trong nhận xét của tôi. – Kobi

3

Tôi tìm thấy trên các cuộc gọi hàm số lượng lớn cho các loại giá trị lớn hơn mà chuyển qua ref nhanh hơn một chút. Nếu bạn có một lượng lớn các cuộc gọi hàm và cần tốc độ thì đây có thể là một sự cân nhắc. Tôi mở ra bằng chứng thay thế.

public static void PassValue(decimal value) 
{ 

} 

public static void PassRef(ref decimal value) 
{ 

}    

decimal passMe = 0.00010209230982047828903749827394729385792342352345m; 

for (int x = 0; x < 20; x++) 
{ 
    DateTime start = DateTime.UtcNow; 
    TimeSpan taken = new TimeSpan(); 

    for (int i = 0; i < 50000000; i++) 
    { 
     PassValue(passMe); 
    } 

    taken = (DateTime.UtcNow - start); 
    Console.WriteLine("Value : " + taken.TotalMilliseconds); 

    start = DateTime.UtcNow; 

    for (int i = 0; i < 50000000; i++) 
    { 
     PassRef(ref passMe); 
    } 

    taken = (DateTime.UtcNow - start); 
    Console.WriteLine("Ref : " + taken.TotalMilliseconds); 
} 

Kết quả:

Value : 150 
Ref : 140 
Value : 150 
Ref : 143 
Value : 151 
Ref : 143 
Value : 152 
Ref : 144 
Value : 152 
Ref : 143 
Value : 154 
Ref : 144 
Value : 152 
Ref : 143 
Value : 154 
Ref : 143 
Value : 157 
Ref : 143 
Value : 153 
Ref : 144 
Value : 154 
Ref : 147 
Value : 153 
Ref : 144 
Value : 153 
Ref : 144 
Value : 153 
Ref : 146 
Value : 152 
Ref : 144 
Value : 153 
Ref : 143 
Value : 153 
Ref : 143 
Value : 153 
Ref : 144 
Value : 153 
Ref : 144 
Value : 152 
Ref : 143 
0

Tôi không chắc chắn cho C#, tuy nhiên đối với C++/c nó phụ thuộc vào những gì bạn đang đi qua. Nếu bạn đang đi qua một loại cơ sở (int, float, double, char) .... sau đó đi qua giá trị nhanh hơn sau đó đi qua tham chiếu (bởi vì chức năng gọi được tối ưu hóa cho điều này) Nếu bạn đang đi một cái gì đó lớn hơn, một lớp lớn , một mảng, chuỗi dài ... sau đó đi qua tham chiếu là nhiều, nhanh hơn nhiều vì nếu bạn đang làm một int [100000] thì bộ vi xử lý sẽ phải phân bổ một đoạn 100000 x 32/64 (tùy thuộc vào kiến ​​trúc), và sau đó sao chép tất cả các giá trị trên, mất rất nhiều thời gian.Trong khi đó, bằng cách tham khảo, chỉ cần chuyển một con trỏ

C# tóm tắt phần lớn, vì vậy tôi không biết nó làm gì, nhưng tôi nghĩ rằng những gì áp dụng cho C++/c về hiệu quả thường có thể áp dụng cho C#.

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