2008-12-11 32 views
20

Khi sử dụng từ khóa 'as' trong C# để tạo một dàn diễn viên không thành công, null được trả lại. Điều gì đang xảy ra trong nền? Có phải nó đơn giản là loại bỏ một ngoại lệ vì vậy tôi không phải viết mã xử lý cho một sự thất bại?C# Các hiệu ứng đúc hiệu suất

Tôi quan tâm đến đặc điểm hiệu suất của nó so với một dàn diễn viên điển hình được bao bọc trong trò chơi thử.

Trả lời

49

Sử dụng hướng dẫn IL isinst để thực hiện diễn viên thay vì hướng dẫn castclass được sử dụng khi truyền. Đây là một hướng dẫn đặc biệt thực hiện các diễn viên nếu nó là hợp lệ, khác lá null trên ngăn xếp nếu nó không phải là. Vì vậy, không, nó không chỉ ngăn chặn một ngoại lệ, và là đơn đặt hàng của cường độ nhanh hơn làm như vậy.

Lưu ý rằng có một số khác biệt trong hành vi giữa isinst hướng dẫn và castclass - một trong những chính được rằng isinst không đưa vào khai thác dàn diễn viên tài khoản người dùng định nghĩa, nó chỉ xem xét phân cấp thừa kế trực tiếp, ví dụ nếu bạn xác định hai loại sau đây không có hệ thống phân cấp thừa kế nhưng một nhà điều hành chuyển kiểu tường minh:

class A 
{ 
    public int Foo; 
} 

class B 
{ 
    public int Foo; 

    public static explicit operator B(A a) 
    { 
     return new B { Foo = a.Foo }; 
    } 
} 

Sau đó, những điều sau đây sẽ thành công:

var a = new A { Foo = 3 }; 
var b = (B)a; 
Console.WriteLine(b.Foo); // prints 3 

Tuy nhiên, sau đây không biên dịch, với các lỗi 'Không thể chuyển đổi nhập 'A' vào 'B' qua chuyển đổi tham chiếu, chuyển đổi quyền anh, chuyển đổi hộp số, chuyển đổi gói hoặc chuyển đổi loại bỏ không '

var a = new A { Foo = 3 }; 
var b = a as B; 

Vì vậy, nếu bạn có y người dùng xác định phôi thiết lập (mà thường là một ý tưởng tồi trên các loại tài liệu tham khảo, vì lý do này và những người khác) thì bạn nên nhận thức được sự khác biệt này.

+0

Lý do tại sao nó sẽ không biên dịch? Tôi nghĩ 'as' chỉ được đánh giá khi thực thi mã? Điều đó có nghĩa là trình biên dịch cũng kiểm tra quá trình truyền trong thời gian biên dịch không? – faulty

+0

@faulty - Trình biên dịch sẽ xác minh tĩnh các phôi nếu có thể để đảm bảo bạn không viết mã không thể thành công (Tôi không thể nhớ đây có phải là cảnh báo hay lỗi khi tôi luôn cảnh báo khi bật các lỗi). –

7

Và để thêm vào bài xuất sắc của Greg ...

Lần đầu tiên một loại mới được tham chiếu trong thời gian chạy, tải CLR vào bộ nhớ một cấu trúc gọi là COREINFO_CLASS_STRUCT (hoặc một cái gì đó tương tự) có chứa, trong số những thứ khác, con trỏ đến đối tượng COREINFO_CLASS_STRUCT cho lớp cơ sở mà đối tượng này xuất phát từ ... Điều này có hiệu quả tạo danh sách liên kết gồm COREINFO_CLASS_STRUCT đối tượng cho chuỗi thừa kế cho Loại, kết thúc trong COREINFO_CLASS_STRUCT cho System.Object. Khi bạn thực hiện isinst, (hoặc phương pháp tương tự castclass), bạn chỉ cần tìm cấu trúc bộ nhớ COREINFO_CLASS_STRUCT cho loại bê tông của đối tượng bạn đang kiểm tra và duyệt danh sách được liên kết này để xem Loại bạn đang cố gắng truyền vào danh sách.

Nó cũng chứa một con trỏ đến một mảng riêng biệt chứa tất cả các giao diện được thực hiện bởi Loại, mà phải được tìm kiếm riêng biệt nếu bạn đang cố gắng truyền sang giao diện.