2009-05-20 27 views
6

C# chấp nhận như sau:không thể chuyển đổi loại 'chuỗi' thành 'int?' thông qua một chuyển đổi tài liệu tham khảo, chuyển đổi quyền Anh, chuyển đổi unboxing, gói chuyển đổi hoặc chuyển đổi loại rỗng

object o = "hello"; 
int? i = o as int?; 

if (i == null) { 
    // o was not a boxed int 
} 
else { 
    // Can use i.Value to recover the original boxed value 
} 

Nhưng không

String o = "hello"; 
int? i = o as int?; 

if (i == null) { 
    // o was not a boxed int 
} 
else { 
    // Can use i.Value to recover the original boxed value 
} 

Tôi chỉ tự hỏi về hành vi của các từ khóa as trong C#.

Giống như trong Java này sẽ thất bại:

Object test1 = "hello"; 
Integer test2 = (Integer) test1; 
String test3 = "hello"; 
Integer test4 = (Integer) test3; //compilation error 

Trả lời

17

Trình biên dịch biết rằng một chuỗi không bao giờ có thể là int? để nó cho bạn biết điều đó. Điều đó không có nghĩa là int? không hữu ích. Trường hợp sử dụng đã cố gắng của bạn cách xa trường hợp bình thường. Điều bình thường là "Tôi muốn đại diện cho một số nguyên và khả năng giá trị bị thiếu/không rõ". Để làm được điều đó, int? hoạt động rất tốt.

Tại sao bạn mong đợi mã ban đầu của bạn hoạt động? Tại sao nó sẽ hữu ích?

Lưu ý rằng bạn có thể sử dụng as với các loại nullable, cho unboxing:

object o = "hello"; 
int? i = o as int?; 

if (i == null) 
{ 
    // o was not a boxed int 
} 
else 
{ 
    // Can use i.Value to recover the original boxed value 
} 

EDIT: Đã thấy bình luận của bạn, bạn không sử dụng as để phân tích mọi thứ. Bạn có thể muốn sử dụng int.TryParse:

string text = "123": 
int value; 
if (int.TryParse(text, out value)) 
{ 
    Console.WriteLine("Parsed successfully: {0}", value); 
} 
else 
{ 
    Console.WriteLine("Unable to parse text as an integer"); 
} 

Nếu bạn chắc chắn chuỗi được hiểu là một số nguyên (tức là nó là một lỗi khác) sau đó bạn chỉ có thể sử dụng int.Parse:

int value = int.Parse(text); 

Đó sẽ ném một ngoại lệ nếu phân tích cú pháp không thành công. Lưu ý rằng cả hai phương pháp này đều cho phép bạn chỉ định nhà cung cấp định dạng (thường là thông tin văn hóa) cho phép bạn thể hiện cách các số được biểu thị theo định dạng đó (ví dụ: hàng nghìn dấu phân cách).

EDIT: Trong câu trả lời cho câu hỏi mới của bạn, trình biên dịch ngăn chặn điều này bởi vì nó biết một chuỗi không thể có thể là một hộp đóng gói - chuyển đổi sẽ không bao giờ thành công.Khi nó chỉ biết rằng giá trị ban đầu là một đối tượng, nó có thể thành công.

Ví dụ: giả sử tôi đã nói với bạn, "Đây là hình dạng: có phải là hình vuông không?" Đó là một câu hỏi hợp lý. Nó là hợp lý để hỏi nó: bạn không thể nói mà không nhìn vào hình dạng.

Nếu, tuy nhiên, tôi đã nói: "Đây là hình tam giác: có phải là hình vuông không?" Sau đó, bạn sẽ được hợp lý có quyền cười trên khuôn mặt của tôi, như một hình tam giác không thể có thể là một hình vuông - câu hỏi không có ý nghĩa.

+0

vì bạn đang cố gắng gán một giá trị chuỗi đến một int. dấu hỏi chỉ cho phép int chứa một giá trị null, nó không thay đổi thực tế là nó là một int. – kscott

+0

Juan: Bạn không sử dụng dàn diễn viên hoặc "dưới dạng" để chuyển đổi giữa các chuỗi và các loại khác. Không có sẵn chuyển đổi ngầm hoặc rõ ràng - bạn phải sử dụng phương pháp phân tích cú pháp. Xem phần thứ hai của câu trả lời của tôi để biết chi tiết và một ví dụ. –

+0

Không - Tôi sẽ không bao giờ mong đợi một nhà điều hành chuyển đổi cố gắng phân tích cú pháp. Rất tiếc - có vẻ như tôi đã hiểu sai câu hỏi đã chỉnh sửa của bạn, tôi nghĩ điều đó cho biết bạn * đã cố gắng tìm cách để thực hiện chuyển đổi.Tôi sẽ để lại thông tin bổ sung cho người đọc trong tương lai. –

2

int? có nghĩa là một loại số nguyên nullable, không phải là một int có thể chứa bất kỳ loại biến nào khác.

Nếu bạn muốn loại biến có thể chứa int hoặc chuỗi, bạn phải sử dụng một đối tượng hoặc chuỗi mà tôi giả sử và sau đó sống một cuộc sống đầy loại truyền. Tôi không biết tại sao bạn lại muốn làm điều đó.

int? cho phép bạn lưu trữ bất kỳ giá trị số nguyên nào hoặc giá trị null. Điều này hữu ích khi nói câu trả lời cho câu hỏi "Có bao nhiêu đơn đặt hàng mà người này đặt" là hợp pháp "Tôi không biết" thay vì một số đơn đặt hàng hoặc số không sẽ là "Tôi biết thực tế người này chưa bao giờ đặt hàng ".

0

nhưng bạn có thể kiểm tra giá trị của giá trị rỗng và đặt thành giá trị rỗng.

int? blah; 
if (blah == null) 
{} 
0

int? là một số nguyên nullable, nó không có gì để làm với đúc và các từ khóa như. "String" là một đối tượng kiểu chuỗi, mà không thể chuyển đổi thành một int (nullable hoặc không nullable).

Các như từ khóa là hầu như giống như đúc sử dụng dấu ngoặc ngoại trừ nó sẽ không trở lại một lỗi, nó sẽ thiết lập các đối tượng để null:

int i = 1; 

object o = i; //boxing 

int j = (int)o; //unboxing 

ví dụ đầu tiên này làm việc như các đối tượng giao cho o là một int.

Bây giờ xem xét:

string i = "MyString"; 

object o = MyString; 

int j = (int)o //unboxing raises exception 

int j = o as int; //raises compilation Error as int is not nullable 
int? j = o as int?; /// o == null 

Tôi hy vọng rằng điều đó giúp giải thích sự khác biệt giữa hai khái niệm này.

Richard

+0

"int j = o as int" không làm tăng ngoại lệ - nó ngăn cản việc biên dịch, bởi vì không có giá trị cho j để nhận trong trường hợp o không phải là một hộp int. –

+0

Xin lỗi, cảm ơn vì đã chỉnh sửa Jon ... Tôi đã cập nhật câu trả lời tương ứng ... (hy vọng đúng) – Richbits

1

Tôi muốn thêm một số thông tin khác.

Một trường hợp khác, tại sao các diễn viên là không hợp lệ và trình biên dịch ném một lỗi trên biên soạn là, System.String được đánh dấu là kín. Vì vậy, trình biên dịch biết từ loại nào System.String kế thừa và loại bạn có thể truyền chuỗi bằng cách sử dụng làm -operator.

Do từ khóa kín, trình biên dịch cũng knows that bạn không thể kế thừa từ System.String để thêm chức năng hoặc implement một số giao diện bổ sung.

Đoạn code dưới đây là một ví dụ và trình biên dịch sẽ ném các lỗi sau về việc lập

Không thể chuyển đổi loại 'SealedClass' để 'ICastToInterface' thông qua một chuyển đổi tài liệu tham khảo , chuyển đổi boxing, chuyển đổi unboxing, gói chuyển đổi, hoặc chuyển đổi loại hình rỗng

public class UnsealedClass { 
    // some code 
} 

public sealed class SealedClass { 
    // some code 
} 

public interface ICastToInterface { 
    // some code 
} 

public class Test { 

    public Test() { 
    UnsealedClass unsealedClass = new UnsealedClass(); 

    SealedClass sealedClass = new SealedClass(); 

    ICastToInterface unsealedCast = unsealedClass as ICastToInterface; // This works fine 

    ICastToInterface sealedCast = sealedClass as ICastToInterface; // This won´t compile, cause SealedClass is sealed 
    } 
} 
Các vấn đề liên quan