2010-01-14 29 views
5

Tôi tự hỏi tại sao khi bạn đặt thuộc tính System.Diagnostics.Conditional ("DEBUG") vào một phương thức ảo trong lớp cơ sở mà bạn không nhận được lỗi trình biên dịch trên các lớp dẫn xuất ghi đè cùng một phương thức ảo nhưng không có thuộc tính có điều kiện khi điều kiện không được đáp ứng. Ví dụ:Thuộc tính có điều kiện trên hàm ảo

public class MyBaseClass 
{ 
    [System.Diagnostics.Conditional("DEBUG")] 
    public virtual void Test() 
    { 
     //Do something 
    } 
} 

public class MyDerivedClass : MyBaseClass 
{ 
    public override void Test() 
    { 
     //Do something different 
    } 
} 

Dường như khi DEBUG không được xác định, điều kiện về cơ bản sẽ tạo ra kích thước mà không thể tồn tại vì không có hàm ảo trong đầu ra IL thực tế. Tuy nhiên, trong thử nghiệm của tôi, trình biên dịch dường như tạo ra các mã chỉ tốt một trong hai cách. Có điều kiện chỉ cần ném ra IL cho cơ thể chức năng nhưng không thực hiện bất kỳ thay đổi thực sự cho chữ ký lớp?

+0

tiếp tuyến: di chuyển thuộc tính có điều kiện từ lớp ảo của lớp cơ sở sang kết quả ghi đè của lớp dẫn xuất trong một lỗi trình biên dịch. Điều này có ý nghĩa khi xem xét hành vi được nêu chi tiết trong câu trả lời. – devgeezer

Trả lời

5

Tôi nghĩ rằng điều này là do thuộc tính chỉ cho biết phương thức không thể gọi được bằng cách bỏ qua các cuộc gọi đến phương thức đó, nhưng phương pháp này không tồn tại.

Chỉnh sửa: Tôi đã tiếp tục và thử nghiệm một chút với điều này và nếu bạn kiểm tra việc xây dựng bản phát hành của mã sau trong Reflector, bạn sẽ nhận thấy cuộc gọi đến phương thức Kiểm tra không có.

public class TestClass 
    { 
     [ConditionalAttribute("DEBUG")] 
     public static void Test() 
     { 
      Console.WriteLine("Blierpie"); 
     } 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      Console.WriteLine("Starting test"); 
      TestClass.Test(); 
      Console.WriteLine("Finished test"); 
      Console.ReadKey(); 
     } 
    } 
+0

Vâng, đúng vậy - MSDN nói "Chỉ ra các trình biên dịch mà một cuộc gọi phương thức hoặc thuộc tính sẽ bị bỏ qua trừ khi một biểu tượng biên dịch có điều kiện được xác định được xác định." – Matthias

1

Anton là đúng. Chức năng ở đó nhưng một cuộc gọi trực tiếp đến nó bị bỏ qua. Nhưng bạn vẫn có thể gọi nó bằng cách sử dụng sự phản chiếu.

 MyDerivedClass myDerivedClass = new MyDerivedClass(); 
     //Following will not work in Release configuration 
     myDerivedClass.Test(); 
     //But it exist and you can still call it using reflection 
     myDerivedClass.GetType().GetMethod("Test").Invoke(myDerivedClass, null); 
     //It name will still appear. 
     foreach (MethodInfo method in myDerivedClass.GetType().GetMethods()) 
      Console.WriteLine(method.Name); 
1

Các trường hợp thú vị hơn là một trong những điều này:

class Program { 
    static void Main(string[] args) { 
     new Derived().Test(); 
    } 
} 
public class Base { 
    [System.Diagnostics.Conditional("DEBUG")] 
    public virtual void Test() { Console.WriteLine("base"); } 
} 

public class Derived : Base { 
    public override void Test() { 
     base.Test(); 
    } 
} 

}

Nếu bạn chạy Ildasm.exe về điều này, bạn sẽ thấy rằng nó thực sự phát ra các Base.Test() nhưng bỏ qua lệnh gọi base.Test(). Nói cách khác, [Conditional] không bỏ qua các phương thức, nó bỏ qua các cuộc gọi phương thức.

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