Trước hết, câu trả lời của Jon, Michael và Jared về cơ bản là đúng nhưng tôi có một số điều nữa tôi muốn bổ sung cho họ.
Phương pháp "không tinh khiết" có nghĩa là gì?
Nó dễ dàng hơn để mô tả các phương pháp thuần túy. Phương pháp "thuần túy" có các đặc điểm sau:
- Đầu ra của nó hoàn toàn được xác định bởi đầu vào của nó; đầu ra của nó không phụ thuộc vào ngoại cảnh như thời gian trong ngày hoặc các bit trên đĩa cứng của bạn. Sản lượng của nó không phụ thuộc vào lịch sử của nó; gọi phương thức với một đối số cho trước hai lần sẽ cho cùng một kết quả.
- Một phương pháp thuần túy không tạo ra đột biến có thể quan sát được trong thế giới xung quanh nó. Một phương pháp thuần túy có thể chọn thay đổi trạng thái riêng tư vì lợi ích của hiệu quả, nhưng một phương pháp thuần túy thì không thay đổi một trường đối số của nó.
Ví dụ, Math.Cos
là một phương pháp thuần túy. Đầu ra của nó chỉ phụ thuộc vào đầu vào của nó và đầu vào không bị thay đổi bởi lệnh gọi.
Một phương pháp không tinh khiết là một phương pháp không tinh khiết.
Một số mối nguy hiểm khi chuyển cấu trúc chỉ đọc sang các phương thức không tinh khiết là gì?
Có hai điều mà tôi nghĩ đến. Đầu tiên là điều do Jon, Michael và Jared chỉ ra, và đây là điều mà Resharper đang cảnh báo bạn. Khi bạn gọi một phương thức trên một cấu trúc, chúng tôi luôn chuyển một tham chiếu đến biến đó là bộ nhận, trong trường hợp phương thức muốn thay đổi biến.
Vì vậy, điều gì sẽ xảy ra nếu bạn gọi một phương thức như vậy trên một giá trị, thay vì một biến? Trong trường hợp đó, chúng tôi tạo một biến tạm thời, sao chép giá trị vào đó và chuyển một tham chiếu đến biến.
Một biến chỉ đọc được coi là một giá trị, vì nó không thể bị đột biến bên ngoài hàm tạo. Vì vậy, chúng tôi đang sao chép biến sang một biến khác, và phương thức không tinh khiết có thể làm thay đổi bản sao, khi bạn định nó thay đổi biến.
Đó là sự nguy hiểm của việc chuyển một cấu trúc chỉ đọc như một bộ thu . Cũng có nguy cơ truyền một cấu trúc chứa trường chỉ đọc. Một cấu trúc có chứa một trường chỉ đọc là một thực tế phổ biến, nhưng về cơ bản nó là viết séc rằng hệ thống loại không có tiền để chuyển tiền mặt; "chỉ đọc" của một biến cụ thể được xác định bởi chủ sở hữu của bộ nhớ. Một thể hiện của kiểu tham chiếu "sở hữu" bộ nhớ riêng của nó, nhưng một thể hiện của kiểu giá trị thì không!
struct S
{
private readonly int x;
public S(int x) { this.x = x; }
public void Badness(ref S s)
{
Console.WriteLine(this.x);
s = new S(this.x + 1);
Console.WriteLine(this.x);
}
}
Một người cho rằng điều đó this.x
sẽ không thay đổi vì x là một trường chỉ đọc và Badness
không phải là một phương thức khởi tạo. Nhưng...
S s = new S(1);
s.Badness(ref s);
... chứng tỏ rõ ràng sự giả dối của điều đó. this
và s
tham chiếu đến cùng một biến, và biến đó không chỉ đọc!