2012-05-17 25 views
5

Tôi đã có cuộc thảo luận thú vị này hôm nay với một đồng nghiệp. Chúng tôi đã tranh luận hai đoạn mã trong C#.Bỏ trống vào một cái gì đó?

Code Snippet 1:

if(!reader.IsDBNull(2)) 
{ 
    long? variable1 = reader.GetInt64(2) 
} 

Code Snippet 2:

long variable1 = reader.IsDBNull(2) ? (long?) null : reader.GetInt64(2) 

Câu hỏi là: nó là một thực hành tốt để đúc rỗng vào một lâu nullable? Hoặc bạn muốn sử dụng câu lệnh if truyền thống để tránh truyền null thành giá trị dài.

+1

Vâng diễn viên dành cho toán tử điều kiện bạn sử dụng, nó cần kiểu trả về của các nhánh tương tự và snippet2 là lỗi trình biên dịch bạn cần nó là 'dài? variable1' – V4Vendetta

+0

Như V4Vendetta đã nói, trong đoạn thứ hai, các loại lh và rh của bạn khác nhau. –

+0

Trong đoạn 1, 'biến1' chỉ tồn tại bên trong phạm vi' if'. – comecme

Trả lời

15

Các biểu thức (type?)null, default(type?)new Nullable<type>() kết thúc được biên dịch vào các opcodes cùng:

 long? x = (long?)null; 
     long? y = default(long?); 
     long? z = new Nullable<long>(); 

được biến thành:

IL_0001: ldloca.s x 
    IL_0003: initobj valuetype [mscorlib]System.Nullable`1<int64> 
    IL_0009: ldloca.s y 
    IL_000b: initobj valuetype [mscorlib]System.Nullable`1<int64> 
    IL_0011: ldloca.s z 
    IL_0013: initobj valuetype [mscorlib]System.Nullable`1<int64> 

Nói cách khác, nếu bạn đang làm việc với các loại nullable, bạn có thể tự do sử dụng phiên bản nào bạn thích nhất. Lưu ý tuy nhiên, bạn nên cố gắng tránh các arithmetics với các kiểu nullable. Nếu bạn muốn trả về một giá trị nullable từ một biểu thức có điều kiện, cả hai kết quả có thể phải là nullable nếu một trong số chúng có thể là null. Bất kỳ cách nào khác có thể gây ra một ngoại lệ trong trường hợp đó.

+0

Vì lợi ích của sự hoàn chỉnh: Biểu thức 'null as type? 'cũng được biên dịch thành cùng mã IL đó. Trên thực tế,' null' không cần được đúc một cách rõ ràng nếu biểu thức xung quanh cung cấp một giá trị rỗng kiểu ngữ cảnh, ví dụ 'điều kiện? null: giá trị là kiểu?'. 'null' trong biểu thức đó cũng được biên dịch thành' new Nullable () 'IL mã. – Wormbo

1

Tôi không muốn đúc null giá trị (có vẻ lạ với tôi):

long? variable1 = reader.IsDBNull(2) ? null : (long?)reader.GetInt64(2); 

Một lựa chọn:

long? variable1 = reader.IsDBNull(2) ? default(long?) : reader.GetInt64(2); 
long? variable1 = reader.IsDBNull(2) ? (long?)null : reader.GetInt64(2); 
long? variable1 = reader.IsDBNull(2) ? new Nullable<long>() : reader.GetInt64(2); 
long? variable1 = reader.IsDBNull(2) ? new long?() : reader.GetInt64(2); 
long? variable1 = reader.IsDBNull(2) ? null : new long?(reader.GetInt64(2)); 

Nó chỉ là vấn đề của hương vị. Tôi nghĩ tùy chọn đầu tiên dễ đọc hơn những người khác.

UPDATE: Xem xét cũng viết một số phương pháp khuyến nông để làm cho mã của bạn rõ ràng hơn:

public static class DataReaderExtensions 
{ 
    public static long? GetNullableInt64(this IDataReader reader, int index) 
    { 
     if (reader.IsDBNull(index)) 
      return null; 

     return reader.GetInt64(index); 
    } 
} 

Trong trường hợp này bạn không sử dụng nhà điều hành ternary (không đúc để nullable), và đọc giá trị từ độc giả trông khá:

long? variable1 = reader.GetNullableInt64(2); 
+0

@lazyberezovsky Coz ​​bạn ** không thể chuyển đổi null thành dài?** – V4Vendetta

+0

@ V4Vendetta Tôi đã sửa lỗi đánh máy này trước nhận xét đầu tiên của bạn –

+0

@lazyberezovsky bạn vẫn có nó ở đó '...? null: (dài?) reader.GetInt64 (2) ':( – V4Vendetta

0

Snippet 2 là giá trị trong trường hợp của tôi, như trong trường hợp của null bạn đang gonna được 0, đó là một giá trị hoàn toàn hợp lệ cho long

3

Thay vì

(long?) null 

sử dụng

default(long?) 

tôi sẽ cấu trúc lại trên mã như

long? variable1 = reader.IsDBNull(2) ? default(long?) : reader.GetInt64(2) 
+0

Tại sao bạn sử dụng dấu ngoặc kép quanh 'long? '? –

+0

typo in cắt dán bản sao, thansk để chỉ ra – Tilak