Tại sao giá trị mặc định của loại chuỗi null thay vì chuỗi rỗng?


218

Thật khó chịu khi kiểm tra tất cả các chuỗi của tôi nulltrước khi tôi có thể áp dụng các phương thức như ToUpper(), StartWith()v.v ... một cách an toàn , v.v ...

Nếu giá trị mặc định stringlà chuỗi rỗng, tôi sẽ không phải kiểm tra và tôi sẽ cảm thấy nó phù hợp hơn với các loại giá trị khác như inthoặc doubleví dụ. Ngoài ra Nullable<String>sẽ có ý nghĩa.

Vậy tại sao các nhà thiết kế của C # lại chọn sử dụng nulllàm giá trị mặc định của chuỗi?

Lưu ý: Điều này liên quan đến câu hỏi này , nhưng tập trung hơn vào lý do tại sao thay vì phải làm gì với nó.


53
Bạn có coi đây là một vấn đề cho các loại tài liệu tham khảo khác?
Jon Skeet

17
@JonSkeet Không, nhưng chỉ vì ban đầu, tôi đã nghĩ sai rằng các chuỗi là các loại giá trị.
Marcel

21
@Marcel: Đó là một lý do khá tốt để tự hỏi về nó.
TJ Crowder

7
@JonSkeet Có. Ồ vâng. (Nhưng bạn không lạ gì với cuộc thảo luận loại tham chiếu không thể bỏ qua)
Konrad Rudolph

7
Tôi tin rằng bạn sẽ có thời gian tốt hơn nhiều nếu bạn sử dụng các xác nhận trên chuỗi của mình ở những nơi bạn mong đợi chúng KHÔNG null(và tôi cũng khuyên bạn nên coi các khái niệm nullvà các chuỗi trống là những thứ khác nhau). Một giá trị null có thể là kết quả của một lỗi ở đâu đó, trong khi một chuỗi rỗng sẽ truyền đạt một ý nghĩa khác.
diegoreymendez

Câu trả lời:


312

Tại sao giá trị mặc định của loại chuỗi null thay vì chuỗi rỗng?

Bởi vì stringlà một loại tham chiếu và giá trị mặc định cho tất cả các loại tham chiếu là null.

Thật khó chịu khi kiểm tra tất cả các chuỗi của tôi thành null trước khi tôi có thể áp dụng các phương thức như ToUpper (), StartWith (), v.v ...

Điều đó phù hợp với hành vi của các loại tham chiếu. Trước khi gọi các thành viên cá thể của họ, người ta nên đặt một kiểm tra tại chỗ cho một tham chiếu null.

Nếu giá trị mặc định của chuỗi là chuỗi rỗng, tôi sẽ không phải kiểm tra và tôi sẽ cảm thấy nó phù hợp hơn với các loại giá trị khác như int hoặc double chẳng hạn.

Việc gán giá trị mặc định cho một loại tham chiếu cụ thể khác với nullviệc làm cho nó không nhất quán .

Ngoài ra Nullable<String>sẽ có ý nghĩa.

Nullable<T>làm việc với các loại giá trị. Đáng chú ý là thực tế Nullablekhông được giới thiệu trên nền tảng .NET ban đầu nên sẽ có rất nhiều mã bị hỏng nếu họ thay đổi quy tắc đó. ( Courtesy @jcolebrand )


10
@HenkHolterman Người ta có thể thực hiện cả tấn thứ, nhưng tại sao lại đưa ra một sự mâu thuẫn chói lóa như vậy?

4
@delnan - "tại sao" là câu hỏi ở đây.
Henk Holterman

8
@HenkHolterman Và "Tính nhất quán" là phản bác lại quan điểm của bạn "chuỗi có thể được đối xử không giống như các loại tham chiếu khác".

6
@delnan: Đang làm việc với một ngôn ngữ coi chuỗi là loại giá trị và hoạt động hơn 2 năm trên dotnet, tôi đồng ý với Henk. Tôi thấy nó là một FLAW chính trên dotnet.
Fabricio Araujo

1
@delnan: Người ta có thể tạo ra một loại giá trị hoạt động cơ bản giống như String, ngoại trừ (1) hành vi loại giá trị có giá trị mặc định có thể sử dụng được và (2) một lớp bổ sung quyền anh đáng tiếc bất cứ khi nào nó được sử dụng Object. Cho rằng đại diện của heap stringlà duy nhất, có sự đối xử đặc biệt để tránh quyền anh thêm sẽ không quá căng thẳng (thực ra, việc có thể chỉ định các hành vi đấm bốc không mặc định cũng sẽ là một điều tốt cho các loại khác).
supercat

40

Habib đúng - vì stringlà một loại tham khảo.

Nhưng quan trọng hơn, bạn không phải kiểm tra nullmỗi lần bạn sử dụng nó. Bạn có lẽ nên ném ArgumentNullExceptionnếu ai đó vượt qua chức năng của bạn một nulltham chiếu, mặc dù.

Đây là điều - khuôn khổ sẽ ném NullReferenceExceptioncho bạn dù thế nào nếu bạn cố gắng gọi .ToUpper()trên một chuỗi. Hãy nhớ rằng trường hợp này vẫn có thể xảy ra ngay cả khi bạn kiểm tra các đối số của mình nullvì bất kỳ thuộc tính hoặc phương thức nào trên các đối tượng được truyền cho hàm của bạn vì các tham số có thể ước tính null.

Điều đó đang được nói, kiểm tra các chuỗi rỗng hoặc null là một việc phổ biến để làm, vì vậy họ cung cấp String.IsNullOrEmpty()String.IsNullOrWhiteSpace()cho mục đích này.


30
Bạn không bao giờ nên tự ném NullReferenceExceptionmình ( msdn.microsoft.com/en-us/l Library / ms173163.aspx ); bạn ném ArgumentNullExceptionnếu phương thức của bạn không thể chấp nhận refs null. Ngoài ra, NullRef thường là một trong những trường hợp ngoại lệ khó chẩn đoán hơn khi bạn đang khắc phục sự cố, vì vậy tôi không nghĩ rằng đề xuất không kiểm tra null là một điều rất tốt.
Andy

3
@Andy "NullRef's thường là một trong những trường hợp ngoại lệ khó chẩn đoán nhất" Tôi hoàn toàn không đồng ý, nếu bạn đăng nhập công cụ thì rất dễ tìm và sửa (chỉ cần xử lý trường hợp null).
Louis Kottmann

6
Ném ArgumentNullExceptioncó lợi ích bổ sung là có thể cung cấp tên tham số. Trong quá trình gỡ lỗi, điều này giúp tiết kiệm ... err, giây. Nhưng giây quan trọng.
Kos

2
@DaveMarkle bạn có thể muốn bao gồm IsNullOrWhitespace quá msdn.microsoft.com/en-us/l
Nathan Koop

1
Tôi thực sự nghĩ rằng việc kiểm tra null ở khắp mọi nơi là một nguồn của sự phình to mã. nó xấu, và trông có vẻ khó hiểu và thật khó để duy trì sự nhất quán. Tôi nghĩ (ít nhất là trong các ngôn ngữ giống như C #) một quy tắc tốt là "cấm từ khóa null trong mã sản xuất, sử dụng nó như điên trong mã kiểm tra".
sara

24

Bạn có thể viết một phương thức mở rộng (cho những gì đáng giá):

public static string EmptyNull(this string str)
{
    return str ?? "";
}

Bây giờ điều này hoạt động an toàn:

string str = null;
string upper = str.EmptyNull().ToUpper();

100
Nhưng xin đừng. Điều cuối cùng mà một lập trình viên khác muốn thấy là hàng ngàn dòng mã được viết bằng .EmptyNull () ở khắp mọi nơi chỉ vì anh chàng đầu tiên "sợ" các ngoại lệ.
Dave Markle

15
@DaveMarkle: Nhưng rõ ràng đó chính xác là những gì OP đang tìm kiếm. "Thật khó chịu khi kiểm tra tất cả các chuỗi của tôi thành null trước khi tôi có thể áp dụng các phương thức như ToUpper (), StartWith (), v.v."
Tim Schmelter

19
Các bình luận là cho OP, không phải cho bạn. Mặc dù câu trả lời của bạn là chính xác rõ ràng, một lập trình viên hỏi một câu hỏi cơ bản như thế này nên được cảnh báo mạnh mẽ chống lại việc thực sự đưa giải pháp của bạn vào thực tiễn WIDE, vì thường thì họ sẽ không làm. Có một số sự đánh đổi mà bạn không thảo luận trong câu trả lời của mình, chẳng hạn như độ mờ đục, độ phức tạp tăng lên, khó tái cấu trúc, lạm dụng tiềm năng các phương pháp mở rộng và có, hiệu suất. Đôi khi (nhiều lần) một câu trả lời đúng không phải là con đường đúng và đây là lý do tại sao tôi nhận xét.
Dave Markle

5
@Andy: Giải pháp để không kiểm tra null đúng cách là kiểm tra null đúng cách, không đặt vấn đề hỗ trợ ban nhạc cho một vấn đề.
Dave Markle

7
Nếu bạn đang gặp rắc rối với việc viết .EmptyNull(), tại sao không sử dụng đơn giản (str ?? "")thay vì nơi cần thiết? Điều đó nói rằng, tôi đồng ý với tình cảm được thể hiện trong bình luận của @ DaveMarkle: có lẽ bạn không nên. nullString.Emptykhác nhau về mặt khái niệm và bạn không nhất thiết phải đối xử với nhau như nhau.
CVn

17

Bạn cũng có thể sử dụng như sau, kể từ C # 6.0

string myString = null;
string result = myString?.ToUpper();

Kết quả chuỗi sẽ là null.


1
Nói chính xác, vì c # 6.0, phiên bản IDE không liên quan gì đến nó vì đây là một tính năng ngôn ngữ.
Stijn Van Antwerppen

3
Một lựa chọn khác -public string Name { get; set; } = string.Empty;
Jaja Harris

Cái này gọi là gì? myString? .ToUpper ();
Thợ săn Nelson

1
Nó được gọi là toán tử có điều kiện Null. Bạn có thể đọc về nó ở đây msdn.microsoft.com/en-us/magazine/dn802602.aspx
russelrillema

14

Chuỗi rỗng và null về cơ bản là khác nhau. Null là sự vắng mặt của một giá trị và một chuỗi rỗng là một giá trị trống.

Ngôn ngữ lập trình đưa ra các giả định về "giá trị" của một biến, trong trường hợp này là một chuỗi rỗng, sẽ tốt như khởi tạo chuỗi với bất kỳ giá trị nào khác sẽ không gây ra vấn đề tham chiếu null.

Ngoài ra, nếu bạn chuyển tay cầm cho biến chuỗi đó sang các phần khác của ứng dụng, thì mã đó sẽ không có cách nào để xác thực cho dù bạn đã cố tình chuyển một giá trị trống hay bạn đã quên nhập giá trị của biến đó.

Một dịp khác, đây sẽ là một vấn đề là khi chuỗi là giá trị trả về từ một số hàm. Vì chuỗi là một loại tham chiếu và về mặt kỹ thuật có thể có giá trị là null và rỗng cả hai, do đó, về mặt kỹ thuật cũng có thể trả về null hoặc rỗng (không có gì ngăn chặn nó làm như vậy). Bây giờ, vì có 2 khái niệm "không có giá trị", tức là một chuỗi rỗng và null, tất cả các mã tiêu thụ hàm này sẽ phải thực hiện 2 kiểm tra. Một cho trống và một cho null.

Nói tóm lại, thật tốt khi chỉ có 1 đại diện cho một trạng thái duy nhất. Đối với một cuộc thảo luận rộng hơn về trống và null, xem các liên kết dưới đây.

/software/32578/sql-empty-opes-vs-null-value

NULL vs Empty khi giao dịch với đầu vào của người dùng


2
Và chính xác làm thế nào để bạn thấy sự khác biệt này, nói trong một hộp văn bản? Có phải người dùng đã quên nhập một giá trị vào trường hoặc họ cố tình để trống? Null trong một ngôn ngữ lập trình không có một ý nghĩa cụ thể; không được chỉ định. Chúng tôi biết nó không có giá trị, không giống như cơ sở dữ liệu null.
Andy

1
Không có nhiều khác biệt khi bạn sử dụng nó với một hộp văn bản. Dù bằng cách nào, có một ký hiệu để biểu thị sự vắng mặt của một giá trị trong chuỗi là điều tối quan trọng. Nếu tôi phải chọn một, tôi sẽ chọn null.
Giới thiệu

Trong Delphi, chuỗi là một loại giá trị và do đó không thể rỗng. Nó làm cho cuộc sống dễ dàng hơn rất nhiều về mặt này - tôi thực sự thấy rất khó chịu khi biến chuỗi thành một kiểu tham chiếu.
Fabricio Araujo

1
Trong COM (Mô hình đối tượng chung) có trước .net, một loại chuỗi sẽ giữ một con trỏ tới dữ liệu của chuỗi hoặc nullđể biểu thị chuỗi trống. Có một số cách .net có thể đã triển khai ngữ nghĩa tương tự, nếu họ chọn làm như vậy, đặc biệt là Stringcó một số đặc điểm khiến nó trở thành một kiểu duy nhất [ví dụ: và hai loại mảng là loại duy nhất có phân bổ kích thước không đổi].
supercat

7

Lý do / vấn đề cơ bản là các nhà thiết kế đặc tả CLS (xác định cách ngôn ngữ tương tác với .net) không xác định phương tiện mà các thành viên lớp có thể chỉ định rằng họ phải được gọi trực tiếp, thay vì thông qua callvirt, mà không có người gọi thực hiện kiểm tra tham chiếu null; nó cũng không cung cấp một ý nghĩa của việc xác định các cấu trúc sẽ không phải là môn quyền anh "bình thường".

Nếu đặc tả CLS đã xác định một phương tiện như vậy, thì có thể .net sẽ luôn tuân theo hướng dẫn được thiết lập bởi Mô hình đối tượng chung (COM), theo đó một tham chiếu chuỗi null được coi là tương đương về mặt ngữ nghĩa với một chuỗi rỗng và đối với chuỗi khác Các kiểu lớp bất biến do người dùng định nghĩa được cho là có ngữ nghĩa giá trị để xác định các giá trị mặc định tương tự. Về cơ bản, những gì sẽ xảy ra sẽ là cho mỗi thành viên String, ví dụ như Lengthđược viết như một cái gì đó như thế nào [InvokableOnNull()] int String Length { get { if (this==null) return 0; else return _Length;} }. Cách tiếp cận này sẽ cung cấp ngữ nghĩa rất hay cho những thứ nên hoạt động như các giá trị, nhưng vì các vấn đề triển khai cần phải được lưu trữ trên heap. Khó khăn lớn nhất với cách tiếp cận này là ngữ nghĩa của việc chuyển đổi giữa các loại như vậy và Objectcó thể có một chút âm u.

Một cách tiếp cận khác là cho phép định nghĩa các loại cấu trúc đặc biệt không kế thừa Objectmà thay vào đó có các thao tác đấm bốc và mở hộp tùy chỉnh (sẽ chuyển đổi sang / từ một số loại lớp khác). Theo cách tiếp cận như vậy, sẽ có một loại lớp NullableStringhoạt động như chuỗi hiện tại và một kiểu cấu trúc được đóng hộp tùy chỉnh String, sẽ chứa một trường riêng Valuecủa loại String. Cố gắng chuyển đổi Stringthành NullableStringhoặc Objectsẽ trả về Valuenếu không null hoặc String.Emptynếu null. Cố gắng truyền tới String, một tham chiếu không null đến một NullableStringthể hiện sẽ lưu trữ tham chiếu trong Value(có thể lưu trữ null nếu độ dài bằng 0); đúc bất kỳ tài liệu tham khảo khác sẽ ném một ngoại lệ.

Mặc dù các chuỗi phải được lưu trữ trên heap, về mặt khái niệm không có lý do nào khiến chúng không hoạt động giống như các loại giá trị có giá trị mặc định không null. Việc chúng được lưu trữ dưới dạng cấu trúc "bình thường" chứa tham chiếu sẽ có hiệu quả đối với mã sử dụng chúng dưới dạng "chuỗi", nhưng sẽ thêm một lớp bổ sung và không hiệu quả khi truyền vào "đối tượng". Mặc dù tôi không thấy trước .net khi thêm một trong các tính năng trên vào cuối ngày này, có lẽ các nhà thiết kế của các khung công tác trong tương lai có thể xem xét bao gồm cả chúng.


1
Nói như một người làm việc trong SQL rất nhiều và đã giải quyết vấn đề đau đầu của Oracle là không tạo ra sự khác biệt giữa NULL và zero-length, tôi rất vui vì .NET làm được điều đó . "Trống" là một giá trị, "null" thì không.

@Jonof ALLTrades: Tôi không đồng ý. Trên mã ứng dụng, ngoại trừ xử lý mã db, không có nghĩa là một chuỗi được coi là một lớp. Đó là một loại giá trị và một loại cơ bản. Supercat: +1 cho bạn
Fabricio Araujo

1
Mã cơ sở dữ liệu là một "ngoại trừ" lớn. Miễn là có một số miền vấn đề mà bạn cần phân biệt giữa "hiện tại / đã biết, một chuỗi trống" và "không hiện diện / không xác định / không thể áp dụng", chẳng hạn như cơ sở dữ liệu, thì ngôn ngữ cần hỗ trợ. Tất nhiên bây giờ .NET có Nullable<>, các chuỗi có thể được thực hiện lại dưới dạng các loại giá trị; Tôi không thể nói về chi phí và lợi ích của sự lựa chọn đó.

3
@Jonof ALLTrades: Mã liên quan đến các số phải có một phương tiện ngoài băng để phân biệt giá trị mặc định bằng 0 với "không xác định". Như vậy, mã xử lý nullable hoạt động với chuỗi và số phải sử dụng một phương thức cho chuỗi nullable và phương thức khác cho số nullable. Ngay cả khi một loại lớp nullable stringhiệu quả hơn mức Nullable<string>có thể, thì việc sử dụng phương thức "hiệu quả hơn" sẽ nặng nề hơn so với việc có thể sử dụng cùng một cách tiếp cận cho tất cả các giá trị cơ sở dữ liệu nullable.
supercat

5

Bởi vì một biến chuỗi là một tham chiếu , không phải là một thể hiện .

Việc khởi tạo nó thành rỗng theo mặc định là có thể nhưng nó sẽ đưa ra rất nhiều mâu thuẫn trên bảng.


3
Không có lý do cụ thể stringsẽ phải là một loại tham chiếu. Để chắc chắn, các ký tự thực sự tạo nên chuỗi chắc chắn phải được lưu trữ trên heap, nhưng với số lượng hỗ trợ chuyên dụng mà các chuỗi có trong CLR đã có, sẽ không phải là một System.Stringloại giá trị với lĩnh vực riêng lẻ Valuecủa loại HeapString. Trường đó sẽ là một kiểu tham chiếu và sẽ được mặc định null, nhưng một Stringcấu trúc có Valuetrường là null sẽ hoạt động như một chuỗi rỗng. Nhược điểm duy nhất của phương pháp này là ...
supercat

1
... mà đúc một Stringđến Objectsẽ, trong trường hợp không đặc biệt hợp cụ thể mã trong thời gian chạy, gây ra việc tạo ra một đóng hộp Stringdụ trên heap, chứ không phải chỉ đơn giản là sao chép một tham chiếu đến HeapString.
supercat

1
@supercat - không ai nói rằng chuỗi nên / có thể là một loại giá trị.
Henk Holterman

1
Không ai ngoại trừ tôi. Có chuỗi là loại giá trị "đặc biệt" (với trường loại tham chiếu riêng) sẽ cho phép hầu hết việc xử lý có hiệu quả như hiện tại, ngoại trừ kiểm tra null được thêm vào các phương thức / thuộc tính như .Lengthv.v. một tham chiếu null sẽ không cố gắng xóa bỏ nó mà thay vào đó hoạt động như là phù hợp cho một chuỗi rỗng. Cho dù Khung sẽ tốt hơn hay xấu hơn khi stringthực hiện theo cách đó, nếu một người muốn default(string)trở thành một chuỗi trống ...
supercat

1
... có stringmột trình bao bọc loại giá trị trên trường loại tham chiếu sẽ là cách tiếp cận yêu cầu ít thay đổi nhất đối với các phần khác của .net [thực sự, nếu một người sẵn sàng chấp nhận chuyển đổi từ Stringđể Objecttạo thêm một mục được đóng hộp, người ta có thể chỉ đơn giản Stringlà một cấu trúc bình thường với một trường loại Char[]mà nó không bao giờ tiếp xúc]. Tôi nghĩ rằng có một HeapStringloại có thể sẽ tốt hơn, nhưng trong một số cách, chuỗi loại giá trị giữ một Char[]sẽ đơn giản hơn.
supercat

5

Tại sao các nhà thiết kế của C # chọn sử dụng null làm giá trị mặc định của chuỗi?

Bởi vì chuỗi là loại tham chiếu , loại tham chiếu là giá trị mặc định là null. Các biến của kiểu tham chiếu lưu trữ các tham chiếu đến dữ liệu thực tế.

Hãy sử dụng defaulttừ khóa cho trường hợp này;

string str = default(string); 

strlà một string, vì vậy nó là một loại tham chiếu , vì vậy giá trị mặc định là null.

int str = (default)(int);

strlà một int, vì vậy nó là một loại giá trị , vì vậy giá trị mặc định là zero.


4

Nếu giá trị mặc định stringlà chuỗi rỗng, tôi sẽ không phải kiểm tra

Sai lầm! Thay đổi giá trị mặc định không thay đổi thực tế rằng đó là loại tham chiếu và ai đó vẫn có thể đặt rõ ràng tham chiếu thành null.

Ngoài ra Nullable<String>sẽ có ý nghĩa.

Điểm đúng. Sẽ tốt hơn nếu không cho phép nullbất kỳ loại tham chiếu nào, thay vào đó yêu cầu Nullable<TheRefType>tính năng đó.

Vậy tại sao các nhà thiết kế của C # lại chọn sử dụng nulllàm giá trị mặc định của chuỗi?

Tính nhất quán với các loại tham chiếu khác. Bây giờ, tại sao cho phép nulltrong các loại tài liệu tham khảo? Có lẽ vì vậy mà nó cảm thấy như C, mặc dù đây là một quyết định thiết kế đáng ngờ trong một ngôn ngữ cũng cung cấp Nullable.


3
Có thể là do Nullable chỉ được giới thiệu trong .NET 2.0 Framework, vậy trước đó nó không có sẵn?
jcolebrand

3
Cảm ơn Dan Burton đã chỉ ra rằng ai đó CÓ THỂ đặt giá trị khởi tạo thành null trên các loại tham chiếu sau này. Suy nghĩ này thông qua cho tôi biết rằng ý định ban đầu của tôi trong câu hỏi dẫn đến không sử dụng.
Marcel

4

Có lẽ nếu bạn sử dụng ??toán tử khi gán biến chuỗi của mình, nó có thể giúp bạn.

string str = SomeMethodThatReturnsaString() ?? "";
// if SomeMethodThatReturnsaString() returns a null value, "" is assigned to str.

2

Chuỗi là một đối tượng không thay đổi, có nghĩa là khi được cung cấp một giá trị, giá trị cũ sẽ không bị xóa khỏi bộ nhớ, nhưng vẫn ở vị trí cũ và giá trị mới được đặt ở vị trí mới. Vì vậy, nếu giá trị mặc định String aString.Empty, nó sẽ lãng phíString.Empty khối trong bộ nhớ khi nó được đưa ra giá trị đầu tiên.

Mặc dù có vẻ rất nhỏ, nhưng nó có thể trở thành một vấn đề khi khởi tạo một chuỗi lớn các chuỗi với các giá trị mặc định là String.Empty. Tất nhiên, bạn luôn có thể sử dụng StringBuilderlớp có thể thay đổi nếu điều này sẽ là một vấn đề.


Cảm ơn đã đề cập đến điều "khởi tạo đầu tiên".
Marcel

3
Làm thế nào nó sẽ là một vấn đề khi khởi tạo một mảng lớn? Vì, như bạn đã nói, Chuỗi là bất biến, tất cả các phần tử của mảng sẽ chỉ là các con trỏ giống nhau String.Empty. Tôi có nhầm không?
Dan Burton

2
Giá trị mặc định cho bất kỳ loại nào sẽ có tất cả các bit được đặt thành không. Cách duy nhất để giá trị mặc định stringlà một chuỗi rỗng là cho phép tất cả các bit-0 dưới dạng biểu diễn của một chuỗi trống. Có một số cách có thể được thực hiện, nhưng tôi không nghĩ có bất kỳ cách nào liên quan đến việc khởi tạo tài liệu tham khảo String.Empty.
supercat

Các câu trả lời khác cũng thảo luận về điểm này. Tôi nghĩ mọi người đã kết luận rằng sẽ không có ý nghĩa gì khi coi lớp String là trường hợp đặc biệt và cung cấp một cái gì đó khác với all-bit-zero như là một khởi tạo, ngay cả khi nó là một cái gì đó giống như String.Emptyhoặc "".
djv

@DanV: Thay đổi hành vi khởi tạo của các stringvị trí lưu trữ cũng sẽ yêu cầu thay đổi hành vi khởi tạo của tất cả các cấu trúc hoặc các lớp có các trường loại string. Điều đó sẽ thể hiện một sự thay đổi khá lớn trong thiết kế của .net, hiện đang hy vọng sẽ không khởi tạo bất kỳ loại nào mà không cần phải suy nghĩ về nó là gì, chỉ tiết kiệm cho tổng kích thước của nó.
supercat

2

Vì chuỗi là loại tham chiếu và giá trị mặc định cho loại tham chiếu là null.


0

Có thể stringtừ khóa làm bạn bối rối, vì nó trông giống hệt như bất kỳ khai báo loại giá trị nào khác , nhưng nó thực sự là một bí danh System.Stringnhư được giải thích trong câu hỏi này .
Ngoài ra, màu xanh lam đậm trong Visual Studio và chữ cái đầu tiên viết thường có thể gây hiểu lầm rằng đó là một struct.


3
Không đúng với objecttừ khóa? Mặc dù thừa nhận, điều đó ít được sử dụng hơn string.

2
Như intlà một bí danh cho System.Int32. Ý bạn là sao? :)
Thorarin

@Thorari @delnan: Cả hai đều bí danh, nhưng System.Int32là một Structvì thế nó có giá trị mặc định trong khi System.Stringlà một Classviệc có một con trỏ với giá trị mặc định null. Chúng được trình bày trực quan trong cùng một phông chữ / màu sắc. Không có kiến ​​thức, người ta có thể nghĩ rằng họ hành động theo cùng một cách (= có giá trị mặc định). Câu trả lời của tôi được viết với một en.wikipedia.org/wiki/Cognitive_psychology ý tưởng tâm lý học nhận thức đằng sau nó :-)
Alessandro Da Rugna

Tôi khá chắc chắn rằng Anders Hejlsberg đã nói điều đó trong một cuộc phỏng vấn kênh 9. Tôi biết sự khác biệt giữa heap và stack nhưng ý tưởng với C # là lập trình viên thông thường không cần.
Thomas Koelle

0

Các loại Nullable không xuất hiện cho đến 2.0.

Nếu các loại nullable đã được tạo ra trong phần đầu của ngôn ngữ thì chuỗi sẽ không phải là nullable và chuỗi? sẽ là vô giá trị. Nhưng họ không thể làm điều này để tương thích ngược.

Rất nhiều người nói về loại ref hoặc không phải loại ref, nhưng chuỗi là một lớp ngoài lớp thông thường và các giải pháp sẽ được tìm thấy để làm cho nó có thể.

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.