2012-04-08 9 views
25

Ngoài sự khác biệt nhàm chán thường xuyên giữa CastAsC# truyền sang loại có thể vô hiệu hóa?

  • nếu tôi biết rằng táo là một Fruit vì vậy tôi có thể sử dụng (Fruit)apple - và nó ném một ngoại lệ nếu nó không phải là
  • as value có thể được kiểm tra so với null để xem có thành công [không ném ngoại lệ ...]

Tuy nhiên Ive được đọc @EricLippert article về vấn đề này và đã có một mẫu tốt đẹp về Nullable Value loại:

short? s = (short?)123; 
int? i = s as int?; 

này sẽ không biên dịch ...

Không thể chuyển đổi loại 'ngắn? ' để 'int?' thông qua chuyển đổi tham chiếu, chuyển đổi quyền anh, chuyển đổi unboxing, chuyển đổi gói hoặc chuyển đổi loại null

Phạt tiền.

vậy tại sao điều này:

short? s = (short?)123; 
    int? i = (int?)s; 

Liệu Compile? (! chống lại mọi kỳ vọng tôi BIẾT rằng s không phải là int? - và nó sẽ đi BANG nhưng nó không phải là ...)

Cast kiểm tra ở đây nên được nhiều hơn nữa nguy hiểm hơn so với ví dụ trước đây (mà đi Bàng)

Tôi cảm thấy xấu khi hỏi về chủ đề được nói nhiều.

Cảm ơn trước.

+1

bạn mô tả chính xác những gì Eric Lippert đã viết - dàn diễn viên sẽ biên dịch trong khi toán tử 'as' sẽ không cho các trường hợp liên quan đến các loại nullable. – Yahia

+0

@Yahia nhưng chúng tôi có đồng ý rằng ngắn không phải là INT không? –

+0

ngắn không phải là NHƯNG có thể được đúc/chuyển đổi sang int - và đó là những gì bạn đang nói với trình biên dịch: làm cho ngắn này một int. – Yahia

Trả lời

23

Trong ví dụ đầu tiên của bạn, toán tử as cố gắng sử dụng đối tượng s làm int?. Kể từ int? không phải là bất kỳ nơi nào trong chuỗi kế thừa của short?, thao tác này không thành công.

Trong ví dụ thứ hai của bạn, bạn đang thực sự tạo một int? i mới với giá trị từ short? s. Đây là một hoạt động rộng rãi hơn, bởi vì nó không phải bảo tồn đối tượng s gốc ở phía bên tay trái.

Điểm quan trọng ở đây là as không được phép thực hiện bất kỳ thứ gì không giữ được danh tính của đối tượng của bạn. Một diễn viên rõ ràng có thể.

Dưới đây là những gì # tiêu chuẩn C nói về cách thức hình thức (int?) hoạt động:

6.1.4 chuyển đổi nullable Implicit

chuyển đổi tiềm ẩn Predefined hoạt động trên giá trị không nullable loại cũng có thể được sử dụng với các dạng nullable của các kiểu đó. Đối với mỗi những được xác định trước danh tính tiềm ẩn và chuyển đổi số chuyển đổi từ một tổ chức phi nullable kiểu giá trị S để một tổ chức phi nullable kiểu giá trị T, chuyển đổi nullable ngầm sau tồn tại:

· Một chuyển đổi ngầm từ S? đến T ?.

· Chuyển đổi ẩn từ S thành T ?.

đánh giá của một chuyển đổi nullable ngầm dựa trên một chuyển đổi cơ bản từ S để thu T như sau:

· Nếu việc chuyển đổi nullable là từ S? đến T ?:

o Nếu giá trị nguồn là rỗng (giá trị HasValue là sai), kết quả là giá trị null của loại T ?.

o Nếu không, chuyển đổi được đánh giá là một phần mở rộng của S? đến S, tiếp theo là chuyển đổi cơ bản từ S sang T, theo sau là một gói (§4.1.10) từ T đến T ?.

· Nếu chuyển đổi null từ S đến T ?, chuyển đổi được đánh giá là chuyển đổi cơ bản từ S sang T, sau đó là gói từ T đến T ?.

+0

ngoài giải thích này vẫn còn dòng này '(int?) S' mà DO liên quan đến thời đại thừa kế/boxing .... nhưng nó hoạt động và đó là điều mà tôi không understant. –

+0

@RoyiNamir, tôi thực sự không hiểu. Một chuyển đổi tồn tại từ 'short' thành' int' (đúng trong C, Java, và khá nhiều ở mọi nơi khác), và C# spec mô tả cách thực hiện chuyển đổi đó và làm cho nó hoạt động trên các kiểu nullable. (Tôi đã thêm đoạn trích có liên quan ở trên.) – sblom

+1

@sblom Tôi nghĩ bạn nên 'bôi đậm' đoạn trên nói rằng 'Điểm quan trọng ở đây là không được phép làm bất cứ điều gì không bảo vệ danh tính của đối tượng của bạn. Một diễn viên rõ ràng có thể.' - Tôi nghĩ đó là cốt lõi cho điều này. Và như cho phép đúc, tôi đồng ý, điều đó rõ ràng đối với tôi ('là' không thực sự), và như Eric nói không có arithmetics trên short-s (không thực sự quan trọng với điều này nhưng nó dễ hiểu hơn, để tôi ít nhất, chuyển đổi), nó chuyển thành int. – NSGaga

3

Ví dụ:

int? i = (int?)s; 

Liệu trình biên dịch vì một dàn diễn viên là bạn nói với trình biên dịch mà bạn biết điều gì đó mà nó không thể suy ra, có nghĩa là, rằng s có thể được chuyển đổi sang một int?.

Bạn sẽ chỉ nhận được ngoại lệ khi chạy nếu dàn diễn viên không thành công.

+2

không có ngoại lệ khi chạy ..... –

+0

@RoyiNamir - Rất tiếc, bạn nên thêm rằng chỉ trong trường hợp dàn diễn viên không hoạt động. – Oded

0

Tôi nghĩ nguyên nhân trong trường hợp as không thành công, bạn sẽ nhận được kết quả "hợp lệ" null, vì vậy dương tính giả. Trong trường hợp thứ hai, cast được cho phép gây ra trong trường hợp thất bại nó sẽ làm tăng một ngoại lệ.

0

Lý do là int? chỉ là viết tắt của System.Nullable<int> (System.Nullable<T> là loại). Loại ngắn này định nghĩa một diễn viên rõ ràng cho một int, tuy nhiên System.Nullable<T> không có bất kỳ diễn viên rõ ràng như vậy, bởi vì T có thể là bất kỳ loại giá trị khác.