Không thể ToString ()


142

Tôi thấy mọi công trình như:

int? myVar = null;
string test = myVar.HasValue ? myVar.Value.ToString() : string.Empty;

Tại sao không sử dụng đơn giản:

string test = myVar.ToString();

Điều đó có giống hệt nhau không? Ít nhất Reflector nói rằng:

public override string ToString()
{
  if (!this.HasValue)
  {
    return "";
  }
  return this.value.ToString();
}

Vì vậy, đó là chính xác (phiên bản ngắn hơn) hoặc tôi đang thiếu một cái gì đó?


1
Tôi chưa thấy mã như thế này :)
tymtam

Câu trả lời:


112

Bạn khá đúng. Cũng trong câu hỏi này , giải pháp trước đây được đề xuất trong khi không ai thực sự thông báo ToString()đã đưa ra câu trả lời chính xác.

Có thể đối số cho giải pháp dài dòng hơn là khả năng đọc: Khi bạn gọi ToString()một thứ được chonull, bạn thường mong đợi một NullReferenceException, mặc dù ở đây nó không bị ném.


21
Trên thực tế, ít nhất hai người chú ý: Eric Lippert và Johannes Rössel.
Jon Skeet

7
Mặc dù tôi chắc chắn rằng đó không phải là ý bạn, nhưng tài liệu tham khảo thực sự không có ở đây. Nullable <T> là một loại giá trị. Đây là lý do tại sao gọi ToString()công trình mà không có bất kỳ NullReferenceExceptionbị ném.
Thorarin

2
Nếu đó là tâm lý, bạn sẽ .HasValuevẫn ném ngoại lệ đó.
Extragorey

Một lý do khác khiến mọi người sử dụng phiên bản dài dòng có thể là để tương đương với các biểu thức như myNullableDateTime.HasValue ? myNullableDateTime.Value.ToString("d") : nullnơi bạn cần đối tượng chưa được mở để truy cập ToStringphương thức mong muốn . Tất nhiên, cũng có một giải pháp ngắn gọn hơn cho điều đó:$"{myNullableDateTime:d}"
Extragorey

14

Tôi nghĩ rằng nhiều người có kiểm tra như vậy bởi vì đó không phải là hành vi tự nhiên của một đối tượng có thể giữ giá trị null.


@Andrew, đồng ý, vì mọi người (như tôi) lúc đầu nghĩ rằng nó sẽ ném ngoại lệ.
Nathan Koop

1
Tôi không biết đây là hành vi. Tôi chắc chắn đã nghĩ rằng bất kỳ cấu trúc nào trả về true cho (x == null) cũng sẽ ném NullReferenceException nếu bạn gọi x.ToString ().
Dan Bryant

5

Không, bạn đã đúng, phiên bản ngắn hơn giống như những gì người khác đã làm về vấn đề đó. Cấu trúc khác tôi có xu hướng sử dụng rất nhiều thay vì ternary với nullables là toán tử hợp nhất null ,. Điều này cũng bảo vệ bạn khỏi nulls. Đối với ToString () không cần thiết (như bạn đã chỉ ra) nhưng đối với các giá trị int mặc định (ví dụ), nó hoạt động độc đáo, ví dụ:

int page = currentPage ?? 1;

cho phép bạn thực hiện tất cả các thao tác số nguyên trên trang w / o trước tiên kiểm tra null và gọi giá trị trong currentPage (trong đó currentPage là một int? có lẽ được truyền dưới dạng param)


5

Tôi biết, rất lâu sau khi nó có liên quan, nhưng ... tôi nghi ngờ đó là vì các loại nullable như int? phương thức .ToString () không cho phép bạn sử dụng các chuỗi định dạng. Xem Làm cách nào tôi có thể định dạng một DateTime nullable với ToString ()? . Có lẽ trong mã gốc, có một chuỗi định dạng trong .ToString () hoặc có lẽ người viết mã đã quên rằng .ToString () không có chuỗi định dạng vẫn có sẵn trên các loại nullable.


3

có thể chỉ là để theo mô hình? hoặc họ không biết phụ trợ. bạn đúng mã là hoàn toàn giống nhau. bạn thậm chí có thể làm:

int? i = null;
i.ToString(); //No NullReferenceException

Bạn có thể cần đi theo con đường dài nếu ToString () cần phải có văn hóa bất biến, vì nullables không có nó trong menu của họ.
Ε é И

1

int?là cú pháp đường giúp đơn giản hóa việc khai báo biến nullable. Nó giống như Nullable<int>.

Vì vậy, nếu bạn xem việc triển khai ToString()phương thức cho Nullable<T> (xem bên dưới) , bạn có thể nhận thấy rằng nó trả về chuỗi rỗng trong trường hợp nếu nó không có giá trị.

public struct Nullable<T> where T : struct
{
    public override string ToString()
    {
      if (!this.hasValue)
        return "";
      return this.value.ToString();
    }
}

MSDN nói gì:

Phương pháp Nullable.ToString

Trả về đại diện văn bản của giá trị của đối tượng Nullable hiện tại nếu thuộc tính HasValue là true hoặc chuỗi rỗng ("") nếu thuộc tính HasValue là sai.

Vì vậy, đoạn mã sau sẽ in chuỗi rỗng vào bàn điều khiển thay vì ném ArgumentNullExceptionngoại lệ.

static void Main(string[] args)
{
    int? a = null;
    Console.WriteLine(a.ToString()); // Prints empty string to console.
}
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.