Tôi đã trả lời một câu hỏi về khả năng đóng cửa (một cách hợp pháp) kéo dài tuổi thọ đối tượng khi tôi gặp một số mã gen cực kỳ tò mò trên một phần của trình biên dịch C # (4.0 nếu vấn đề đó).
Đoạn repro ngắn nhất tôi có thể tìm thấy như sau:
- Tạo một lambda bắt một cục bộ trong khi gọi một phương thức tĩnh của kiểu chứa.
- Chỉ định tham chiếu đại biểu được tạo cho trường đối tượng chứa.
Kết quả: Trình biên dịch tạo một đối tượng bao đóng tham chiếu đến đối tượng đã tạo lambda, khi nó không có lý do gì - mục tiêu 'bên trong' của đại biểu là một phương thức tĩnh và các thành viên thể hiện của đối tượng tạo lambda không cần được (và không) chạm vào khi đại biểu được thực thi. Thực tế, trình biên dịch đang hoạt động giống như lập trình viên đã nắm bắt this
mà không có lý do.
class Foo
{
private Action _field;
public void InstanceMethod()
{
var capturedVariable = Math.Pow(42, 1);
_field = () => StaticMethod(capturedVariable);
}
private static void StaticMethod(double arg) { }
}
Mã được tạo từ bản dựng phát hành (được dịch ngược thành 'C # đơn giản hơn) trông như thế này:
public void InstanceMethod()
{
<>c__DisplayClass1 CS$<>8__locals2 = new <>c__DisplayClass1();
CS$<>8__locals2.<>4__this = this; // What's this doing here?
CS$<>8__locals2.capturedVariable = Math.Pow(42.0, 1.0);
this._field = new Action(CS$<>8__locals2.<InstanceMethod>b__0);
}
[CompilerGenerated]
private sealed class <>c__DisplayClass1
{
// Fields
public Foo <>4__this; // Never read, only written to.
public double capturedVariable;
// Methods
public void <InstanceMethod>b__0()
{
Foo.StaticMethod(this.capturedVariable);
}
}
Quan sát <>4__this
trường của đối tượng đóng được điền với tham chiếu đối tượng nhưng không bao giờ được đọc từ đó (không có lý do).
Vậy chuyện gì đang xảy ra ở đây? Liệu đặc tả ngôn ngữ cho phép nó? Đây có phải là một lỗi / kỳ lạ của trình biên dịch hay có một lý do chính đáng (mà tôi rõ ràng là thiếu) cho việc đóng cửa để tham chiếu đối tượng? Điều này khiến tôi lo lắng vì đây giống như một công thức cho các lập trình viên đóng cửa hạnh phúc (như tôi) vô tình đưa ra những rò rỉ bộ nhớ lạ (hãy tưởng tượng nếu đại biểu được sử dụng như một người xử lý sự kiện) vào các chương trình.
this
.