Cách chuyển đổi C # nullable int thành int


484

Làm thế nào để tôi chuyển đổi một nullable intthành một int? Giả sử tôi có 2 loại int như sau:

int? v1;  
int v2; 

Tôi muốn gán v1giá trị của nó cho v2. v2 = v1;sẽ gây ra lỗi. Làm thế nào để tôi chuyển đổi v1sang v2?


Hành vi mong muốn v1là khi nullnào?
Solomon Ucko

Câu trả lời:


637

Các câu trả lời khác cho đến nay đều đúng; Tôi chỉ muốn thêm một thứ nữa sạch hơn một chút:

v2 = v1 ?? default(int);

Bất kỳ Nullable<T>đều được chuyển đổi hoàn toàn thành của nó T, CUNG CẤP rằng toàn bộ biểu thức được đánh giá không bao giờ có thể dẫn đến việc gán null cho ValueType. Vì vậy, toán tử hợp nhất null ??chỉ là cú pháp đường cho toán tử ternary:

v2 = v1 == null ? default(int) : v1;

... đến lượt cú pháp đường cho một if / other:

if(v1==null)
   v2 = default(int);
else
   v2 = v1;

Ngoài ra, kể từ .NET 4.0, Nullable<T>có phương thức "GetValueOrDefault ()", đây là một công cụ nhận an toàn null, về cơ bản thực hiện quá trình kết hợp null được hiển thị ở trên, do đó, điều này cũng hoạt động:

v2 = v1.GetValueOrDefault();

4
default(int)thực sự cần thiết? Có gì sai với một đơn giản 0?
Cole Johnson

4
Nó sẽ hoạt động với ví dụ này, nhưng trong trường hợp chung, nên sử dụng defaultkhi thích hợp. Không luôn luôn có giá trị như một giá trị, ít hơn nhiều so với mặc định, vì vậy nếu bạn thay thế intbằng một chung chung, Tbạn sẽ thấy mã của tôi hoạt động trong khi không. Trong một số phiên bản khung trong tương lai, defaultcũng có thể trở nên quá tải; nếu và khi điều đó xảy ra, mã sử dụng mặc định sẽ dễ dàng có thể tận dụng lợi thế, trong khi các phép gán null hoặc zero rõ ràng sẽ phải được thay đổi.
KeithS

5
Điều này sẽ tăng lên hàng đầu: .NET 4.0, Nullable <T> có "GetValueOrDefault ()"
RandomHandle

Cảm ơn bạn đã quay lại để chỉnh sửa nó với GetValueOrDefault!
CindyH

Bạn có thể muốn cẩn thận với DateTime khi bạn sử dụng mặc định. Điều này có thể chèn ngày mặc định thay vì trống.
Ranch Camal


92

Bạn có thể sử dụng thuộc tính Giá trị để gán.

v2 = v1.Value;

8
Ngoài ra - nếu bạn không chắc chắn nếu v1 chứa null - bạn có thể sử dụng toán tử hợp nhất null để đặt giá trị dự phòng. Ví dụ: v2 = v1 ?? 0;
Arjen

12
Và hãy chắc chắn kiểm tra v1.HasValueđầu tiên.
Yuck

3
MSDN nói rằng điều này sẽ ném một ngoại lệ nếu v1null. Theo tôi, đây không phải là một câu trả lời đúng.
ventiseis

6
@ventiseis Tôi nghĩ rằng đó là hành vi mong muốn - Tôi ngạc nhiên vì rất nhiều câu trả lời khác đều ổn khi âm thầm chuyển đổi null thành 0. Nếu bạn chỉ định loại nullable thành loại không nullable, bạn nên chắc chắn rằng giá trị không thực sự là null. OP đã không nói "Tôi muốn gán v1 cho v2 hoặc 0 nếu v1 là null", nhưng đó là những gì mọi người dường như giả định
Michael Mrozek


49

Nếu bạn biết rằng v1có một giá trị, bạn có thể sử dụng thuộc Valuetính:

v2 = v1.Value;

Sử dụng GetValueOrDefaultphương thức sẽ gán giá trị nếu có, nếu không thì mặc định cho loại hoặc giá trị mặc định mà bạn chỉ định:

v2 = v1.GetValueOrDefault(); // assigns zero if v1 has no value

v2 = v1.GetValueOrDefault(-1); // assigns -1 if v1 has no value

Bạn có thể sử dụng thuộc HasValuetính để kiểm tra nếu v1có giá trị:

if (v1.HasValue) {
  v2 = v1.Value;
}

Ngoài ra còn có hỗ trợ ngôn ngữ cho GetValueOrDefault(T)phương pháp:

v2 = v1 ?? -1;

Bạn không nên sử dụng giá trị mà không kiểm tra trước để xem có giá trị không. Sử dụng ?? Toán tử thay thế.
Peter

45

Bạn không thể làm điều đó nếu v1 là null, nhưng bạn có thể kiểm tra với một nhà điều hành.

v2 = v1 ?? 0;

28

GetValueOrDefault()

lấy giá trị của đối tượng. Nếu nó là null, nó trả về giá trị mặc định của int, là 0.

Thí dụ:

v2= v1.GetValueOrDefault();


21

Nếu giá trị mặc định cho một loại nhất định là kết quả chấp nhận được:

if (v1.HasValue)
    v2 = v1.GetValueOrDefault();

Nếu bạn muốn một giá trị mặc định khác khi kết quả không được xác định:

v2 = v1.GetValueOrDefault(255);    // or any valid value for int in place of 255

Nếu bạn chỉ muốn giá trị được trả về (bất kể phương thức có thất bại hay không):

v2 = v1.GetValueOrDefault();


.NET 4.7.2.: Trả GetValueOrDefault()về giá trị trường mà không cần kiểm tra.


15

Theo tôi là giải pháp tốt nhất là sử dụng GetValueOrDefault()phương pháp.

v2 = v1.GetValueOrDefault();

cái này hữu ích nhất cho tôi
Liakat

11

Int nullable để chuyển đổi int có thể được thực hiện như vậy:

v2=(int)v1;

9
Nếu v1 là null, điều này sẽ gây ra một UnlimitedOperationException.
MungeWrath

10

nó có thể với v2 = Convert.ToInt32(v1);


Điều này sẽ hoạt động về mặt kỹ thuật, nhưng các kỹ thuật khác như HasValue / Value hoặc GetValueOrDefault chạy hiệu quả hơn nhiều.
Brandon Barkley


9

Một chuyển đổi đơn giản giữa v1v2không thể thực hiện được vì v1có miền giá trị lớn hơn v2. Đó là tất cả mọi thứ v1có thể giữ cộng với nullnhà nước. Để chuyển đổi, bạn cần nêu rõ giá trị nào intsẽ được sử dụng để ánh xạ nulltrạng thái. Cách đơn giản nhất để làm điều này là ??toán tử

v2 = v1 ?? 0;  // maps null of v1 to 0

Điều này cũng có thể được thực hiện ở dạng dài

int v2;
if (v1.HasValue) {
  v2 = v1.Value;
} else {
  v2 = 0;
}

9

Tùy thuộc vào ngữ cảnh sử dụng của bạn, bạn có thể sử dụng tính năng khớp mẫu của C # 7:

int? v1 = 100;
if (v1 is int v2)
{
    Console.WriteLine($"I'm not nullable anymore: {v2}");
}

BIÊN TẬP:

Vì một số người đang bỏ phiếu mà không để lại lời giải thích, tôi muốn thêm một số chi tiết để giải thích lý do đưa vào đây là một giải pháp khả thi.

  • Kết hợp mẫu của C # 7 bây giờ cho phép chúng tôi kiểm tra loại giá trị và bỏ mặc nó. Trong đoạn mã trên, điều kiện if sẽ chỉ vượt qua khi giá trị được lưu trong v1tương thích với loại cho v2, trong trường hợp này là int. Theo sau khi giá trị v1null, điều kiện if sẽ thất bại vì null không thể được gán cho một int. Đúng hơn, nullkhông phải là một int.

  • Tôi muốn nhấn mạnh rằng giải pháp này có thể không phải luôn luôn là lựa chọn tối ưu. Như tôi đề xuất, tôi tin rằng điều này sẽ phụ thuộc vào bối cảnh sử dụng chính xác của nhà phát triển. Nếu bạn đã có int?và muốn vận hành có điều kiện theo giá trị của nó nếu và chỉ - nếu giá trị được gán không phải là null (đây là lần duy nhất an toàn để chuyển đổi một giá trị null thành int thông thường mà không mất thông tin), thì khớp mẫu có lẽ là một trong những cách ngắn gọn nhất để làm điều này.


Sự cần thiết phải giới thiệu một tên biến mới là không may, nhưng đây là giải pháp tốt nhất (an toàn nhất) nếu không có giá trị mặc định, vì không có nguy cơ vô tình tái cấu trúc HasValueséc của bạn .
minexew

Tôi chỉ không thấy bất kỳ lợi thế nào cho phương thức này so với v1.HasValue là kiểm tra và sau đó là v1. Giá trị để truy cập giá trị cơ bản. Tôi sẽ không đánh giá thấp nó, nhưng tôi nghĩ vấn đề này đã được giải quyết và một kỹ thuật mới không làm tăng thêm sự rõ ràng cho vấn đề. Tôi cũng đánh giá nó chậm hơn 8-9%.
Brandon Barkley

Cảm ơn đã cho điểm chuẩn đó, đó là điều tốt để biết! Dù bạn nhìn nó như thế nào, sự khác biệt là tốt nhất (trừ khi bạn làm điều này trong một số thời điểm quan trọng mà tôi cho là). Tôi nhìn vào điều này là "súc tích" hơn hoặc có thể là "thành ngữ" vì nó dựa vào các loại đường cú pháp được đưa vào ngôn ngữ thay vì API. Đó là một chút chủ quan, nhưng có lẽ nó "dễ bảo trì hơn". Mặc dù thực sự, tôi thích cách tiếp cận này hơn là dựa vào một giá trị mặc định như rất nhiều câu trả lời khác gợi ý.
Nicholas Miller

3

Nó sẽ gán giá trị v1cho v2nếu nó không null, nếu không nó sẽ lấy giá trị mặc định là 0.

v2=v1??0

Hoặc dưới đây là cách khác để viết nó.

v2 = v1.HasValue?v1:0


-1
 int v2= Int32.Parse(v1.ToString());

5
Mặc dù mã này có thể trả lời câu hỏi, cung cấp ngữ cảnh bổ sung về lý do và / hoặc cách mã này trả lời câu hỏi cải thiện giá trị lâu dài của nó.
xiawi

1
Tốt hơn là sử dụng cách "thực hành tốt nhất" cho các tùy chọn mở khóa, thay vì sử dụng các thủ thuật ngầm. Xem docs.microsoft.com/en-us/dotnet/csharp/lingu-reference/iêu để tham khảo
lorg

Khi trả lời một câu hỏi tám năm tuổi với mười lăm câu trả lời hiện có, điều quan trọng là phải giải thích khía cạnh mới của câu hỏi mà câu trả lời của bạn đang giải quyết, và lưu ý nếu thời gian trôi qua đã thay đổi câu trả lời. Mã câu trả lời hầu như luôn luôn có thể được cải thiện bằng cách thêm một số giải thích.
Jason Aller
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.