Trong C #, tôi muốn khởi tạo một giá trị chuỗi bằng một chuỗi rỗng.
Làm thế nào tôi nên làm điều này? Cách đúng, và tại sao?
string willi = string.Empty;
hoặc là
string willi = String.Empty;
hoặc là
string willi = "";
hay cái gì?
Trong C #, tôi muốn khởi tạo một giá trị chuỗi bằng một chuỗi rỗng.
Làm thế nào tôi nên làm điều này? Cách đúng, và tại sao?
string willi = string.Empty;
hoặc là
string willi = String.Empty;
hoặc là
string willi = "";
hay cái gì?
Câu trả lời:
Sử dụng bất cứ điều gì bạn và nhóm của bạn tìm thấy dễ đọc nhất.
Các câu trả lời khác đã gợi ý rằng một chuỗi mới được tạo ra mỗi khi bạn sử dụng ""
. Điều này không đúng - do thực hiện chuỗi, nó sẽ được tạo một lần cho mỗi lần lắp ráp hoặc một lần cho mỗi AppDomain (hoặc có thể một lần cho toàn bộ quá trình - không chắc chắn ở mặt trước đó). Sự khác biệt này là không đáng kể - ồ ạt, ồ ạt không đáng kể.
Mà bạn thấy dễ đọc hơn là một vấn đề khác, tuy nhiên. Đó là sự chủ quan và sẽ thay đổi từ người này sang người khác - vì vậy tôi khuyên bạn nên tìm hiểu xem hầu hết mọi người trong nhóm của bạn thích gì, và tất cả đều đi cùng với sự nhất quán. Cá nhân tôi thấy ""
dễ đọc hơn.
Cuộc tranh cãi ""
và " "
dễ bị nhầm lẫn với nhau không thực sự gột rửa với tôi. Trừ khi bạn đang sử dụng phông chữ tỷ lệ (và tôi chưa từng làm việc với bất kỳ nhà phát triển nào), thật dễ dàng để phân biệt.
string.Empty
không phải là một hằng số . Điều đó có nghĩa là trong một số trường hợp bắt buộc phải có hằng số thời gian biên dịch, string.Empty
thậm chí không hợp pháp. Điều này bao gồm case ""
các khối trong các switch
câu lệnh, giá trị mặc định của các tham số , tham số và thuộc tính tùy chọn trong việc áp dụng các thuộc tính và rất nhiều tình huống khác (để lại cho người đọc). Vì vậy, string.Empty
không được phép trong một số tình huống phổ biến, tốt hơn là sử dụng ""
quy ước -everywhere.
Thực sự không có sự khác biệt từ quan điểm về hiệu suất và mã được tạo. Trong thử nghiệm hiệu suất, họ đã đi qua lại giữa cái nào nhanh hơn cái kia và chỉ bằng mili giây.
Khi nhìn vào mã hậu trường, bạn thực sự cũng không thấy bất kỳ sự khác biệt nào. Sự khác biệt duy nhất là ở IL, string.Empty
sử dụng opcode ldsfld
và ""
sử dụng opcode ldstr
, nhưng đó chỉ string.Empty
là do tĩnh và cả hai hướng dẫn đều làm điều tương tự. Nếu bạn nhìn vào lắp ráp được sản xuất, nó là hoàn toàn giống nhau.
private void Test1()
{
string test1 = string.Empty;
string test11 = test1;
}
private void Test2()
{
string test2 = "";
string test22 = test2;
}
.method private hidebysig instance void
Test1() cil managed
{
// Code size 10 (0xa)
.maxstack 1
.locals init ([0] string test1,
[1] string test11)
IL_0000: nop
IL_0001: ldsfld string [mscorlib]System.String::Empty
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: stloc.1
IL_0009: ret
} // end of method Form1::Test1
.method private hidebysig instance void
Test2() cil managed
{
// Code size 10 (0xa)
.maxstack 1
.locals init ([0] string test2,
[1] string test22)
IL_0000: nop
IL_0001: ldstr ""
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: stloc.1
IL_0009: ret
} // end of method Form1::Test2
string test1 = string.Empty;
0000003a mov eax,dword ptr ds:[022A102Ch]
0000003f mov dword ptr [ebp-40h],eax
string test11 = test1;
00000042 mov eax,dword ptr [ebp-40h]
00000045 mov dword ptr [ebp-44h],eax
string test2 = "";
0000003a mov eax,dword ptr ds:[022A202Ch]
00000040 mov dword ptr [ebp-40h],eax
string test22 = test2;
00000043 mov eax,dword ptr [ebp-40h]
00000046 mov dword ptr [ebp-44h],eax
Mã tốt nhất là không có mã nào cả :
Bản chất cơ bản của mã hóa là nhiệm vụ của chúng tôi, với tư cách là lập trình viên, là nhận ra rằng mọi quyết định chúng tôi đưa ra là một sự đánh đổi. [ V ]] Bắt đầu với sự ngắn gọn. Tăng kích thước khác theo yêu cầu của thử nghiệm.
Do đó, ít mã là mã tốt hơn: thích ""
đến string.Empty
hay String.Empty
. Hai cái đó dài hơn sáu lần mà không có thêm lợi ích - chắc chắn không có thêm sự rõ ràng, vì chúng thể hiện cùng một thông tin.
i
là tốt hơn so với một tên biến dài. Thậm chí tổng quát hơn, các tên biến ngắn hơn truyền tải cùng một thông tin , trong cùng một độ rõ ràng, luôn luôn được ưa thích hơn. Chỉ là để thể hiện thông tin cần thiết, bạn cần một độ dài ký tự nhất định, và tôi không phủ nhận điều này (không có ai).
Một điểm khác biệt là nếu bạn sử dụng switch-case
cú pháp, bạn không thể viết case string.Empty:
vì đó không phải là hằng số. Bạn nhận được mộtCompilation error : A constant value is expected
Nhìn vào liên kết này để biết thêm thông tin: chuỗi-trống-so với trống-trích dẫn
switch
tuyên bố là một ví dụ rất tốt. Ngoài ra, nếu bạn tạo một tham số tùy chọn, như void MyMethod(string optional = "") { ... }
, nó cũng không thể sử dụng string.Empty
. Và dĩ nhiên, nếu bạn muốn xác định một const
trường hoặc biến cục bộ, const string myString = "";
thì lại ""
là tùy chọn duy nhất. Nếu chỉ string.Empty
là một trường không đổi, sẽ không có sự khác biệt. Nhưng nó không phải, vì vậy trong một số trường hợp bạn phải sử dụng ""
. Vậy tại sao không sử dụng ""
tất cả thời gian?
string.Empty
ngăn bạn đạt được sự thống nhất trong cơ sở mã của bạn: bạn phải sử dụng hai thực thể khác nhau để thể hiện cùng một điều. Và để thêm vào danh sách những điều bạn không thể làm: bạn không thể sử dụng string.Empty
với các thuộc tính .
Tôi muốn string
đến String
. lựa chọn string.Empty
hơn ""
là vấn đề chọn một và gắn bó với nó. Ưu điểm của việc sử dụng string.Empty
là nó rất rõ ràng với ý nghĩa của bạn và bạn không vô tình sao chép các ký tự không in được như "\x003"
trong của bạn ""
.
""
nguy hiểm khi sao chép / dán là void, tôi khẳng định, bởi vì bạn không bao giờ sao chép / dán chuỗi trống. Đối với các chuỗi khác, tất nhiên luôn luôn là một cái gì đó để tâm.
Tôi sẽ không kêu gọi, nhưng tôi thấy một số thông tin sai được đưa ra đây.
Tôi, cá nhân, thích string.Empty
. Đó là một sở thích cá nhân, và tôi tập trung vào ý chí của bất kỳ đội nào tôi làm việc trong từng trường hợp cụ thể.
Như một số người khác đã đề cập, không có sự khác biệt nào giữa string.Empty
và String.Empty
.
Ngoài ra, và đây là một thực tế ít được biết đến, sử dụng "" là hoàn toàn chấp nhận được. Mỗi phiên bản của "" sẽ, trong các môi trường khác, tạo một đối tượng. Tuy nhiên, .NET thực hiện các chuỗi của nó, vì vậy các phiên bản trong tương lai sẽ lấy cùng một chuỗi bất biến từ nhóm thực tập và bất kỳ lần nhấn hiệu suất nào cũng sẽ không đáng kể. Nguồn: Brad Abrams .
String.Empty
và string.Empty
là tương đương. String
là tên lớp BCL; string
là bí danh C # của nó (hoặc phím tắt, nếu bạn muốn). Tương tự như với Int32
và int
. Xem các tài liệu để biết thêm ví dụ.
Theo như ""
có liên quan, tôi không thực sự chắc chắn.
Cá nhân, tôi luôn luôn sử dụng string.Empty
.
Chỉ cần mọi nhà phát triển ngoài kia sẽ biết "" nghĩa là gì. Cá nhân tôi gặp String.Empty lần đầu tiên và đã phải dành chút thời gian tìm kiếm google để tìm hiểu xem họ có thực sự là điều tương tự chính xác.
string.Empty
gì? Bạn có biết ""
lần đầu tiên bạn nhìn thấy nó là gì không?
Chủ đề này khá cũ và dài, vì vậy xin lỗi nếu hành vi này đã được đề cập ở một nơi khác. (Và chỉ cho tôi câu trả lời bao gồm điều này)
Tôi đã tìm thấy một sự khác biệt trong hành vi của trình biên dịch nếu bạn sử dụng string.Empty
hoặc trích dẫn kép. Sự khác biệt thể hiện nếu bạn không sử dụng biến chuỗi được khởi tạo bằng chuỗi.Empty hoặc với dấu ngoặc kép.
Trong trường hợp khởi tạo với string.Empty
Cảnh báo Trình biên dịch
CS0219 - The variable 'x' is assigned but its value is never used
không bao giờ được phát ra trong khi trong trường hợp khởi tạo với dấu ngoặc kép bạn nhận được thông báo mong đợi.
Hành vi này được giải thích trong bài viết Kết nối tại liên kết này: https://connect.microsoft.com/VisualStudio/feedback/details/799810/c-warning-cs0219-not-reported-when-assign-non-constant-value
Về cơ bản, nếu tôi hiểu đúng, họ muốn cho phép lập trình viên đặt biến với giá trị trả về của hàm cho mục đích gỡ lỗi mà không làm phiền anh ta bằng thông báo cảnh báo và do đó họ chỉ giới hạn cảnh báo trong trường hợp gán và chuỗi tốn kém. Trống không phải là một hằng số mà là một lĩnh vực.
var unused = "literal";
có thể được tối ưu hóa hoàn toàn (loại bỏ) bởi trình biên dịch. Nó có thể không có tác dụng phụ. Mặt khác, var unused = MyClass.Member;
không thể được loại bỏ hoàn toàn. Đó là bởi vì đọc Member
có thể có tác dụng phụ. Nếu Member
là một thuộc tính tĩnh với một bộ truy cập get
, rõ ràng là phải giữ cuộc gọi đến getter. Nhưng ngay cả khi Member
là một trường tĩnh, có thể có tác dụng phụ mà hàm tạo tĩnh có thể chạy. Chắc chắn nó sẽ là phong cách mã hóa xấu để có nó theo cách đó. Nhưng bạn cần một hình nộm để đọc Member
.
Tôi đã thực hiện thử nghiệm rất đơn giản này bằng phương pháp sau trong một ứng dụng giao diện điều khiển:
private static void CompareStringConstants()
{
string str1 = "";
string str2 = string.Empty;
string str3 = String.Empty;
Console.WriteLine(object.ReferenceEquals(str1, str2)); //prints True
Console.WriteLine(object.ReferenceEquals(str2, str3)); //prints True
}
Điều này rõ ràng gợi ý rằng cả ba biến cụ thể str1
, str2
và str3
mặc dù được khởi tạo bằng các cú pháp khác nhau đều trỏ đến cùng một đối tượng chính xác (có độ dài bằng không) trong bộ nhớ. Tôi đã thực hiện thử nghiệm này trong ứng dụng giao diện điều khiển .NET 4.5. Vì vậy, bên trong họ không có sự khác biệt và tất cả đều nắm bắt được sự thuận tiện mà bạn muốn sử dụng như một lập trình viên. Hành vi này của lớp chuỗi được gọi là thực tập chuỗi trong .NET. Eric Lippert có một blog rất hay ở đây mô tả khái niệm này.
Tôi đặc biệt thích String.Empty, ngoài các lý do khác để đảm bảo bạn biết nó là gì và bạn không vô tình xóa nội dung, mà chủ yếu là để quốc tế hóa. Nếu tôi thấy một chuỗi trong dấu ngoặc kép thì tôi luôn phải tự hỏi liệu đó có phải là mã mới hay không và nó có nên được đưa vào bảng chuỗi không. Vì vậy, mỗi khi mã được thay đổi / đánh giá, bạn cần tìm "cái gì đó trong dấu ngoặc kép" và vâng, bạn có thể lọc ra các chuỗi trống nhưng tôi nói với mọi người rằng không nên đặt chuỗi trong dấu ngoặc kép trừ khi bạn biết nó sẽ không được bản địa hóa .
Không ai đề cập rằng trong VisualStudio String được mã hóa màu khác nhau sau đó là chuỗi. Điều này rất quan trọng đối với khả năng đọc. Ngoài ra, chữ thường thường được sử dụng cho vars và type, không phải là vấn đề lớn nhưng String.Empty là một hằng số và không phải là var hoặc type.
string
là từ đồng nghĩa với System.String
loại, Chúng giống hệt nhau.
Các giá trị cũng giống hệt nhau: string.Empty == String.Empty == ""
Tôi sẽ không sử dụng hằng ký tự "" trong mã, string.Empty
hay là String.Empty
- dễ dàng hơn để xem ý nghĩa của lập trình viên.
Giữa string
và String
tôi thích chữ thường string
hơn chỉ vì tôi đã từng làm việc với Delphi trong nhiều năm và kiểu Delphi là chữ thường string
.
Vì vậy, nếu tôi là sếp của bạn, bạn sẽ viết string.Empty
Tôi sẽ ủng hộ string.Empty
hơn String.Empty
bởi vì bạn có thể sử dụng nó mà không cần bao gồm một using System;
trong tập tin của bạn.
Đối với việc chọn ""
qua string.Empty
, đó là sở thích cá nhân và nên được quyết định bởi nhóm của bạn.
string.Empty
hằng mà không cần nhập using System
không gian tên - Từ khóa trong C # chỉ cần được chuyển đổi thành tên đủ điều kiện của họ, bao gồm cả không gian tên trước khi được viết là MSIL trong đầu ra *. tập tin exe. Vì vậy, có hiệu quả string.Empty
được viết như System.String.Empty
trong MSIL bởi trình biên dịch. Và như bạn đã biết rằng nếu bạn đề cập đến tên loại đủ điều kiện thì bạn có thể bỏ qua việc nhập không gian tên ở đầu tệp mã của bạn.
Tôi không làm cho một sự khác biệt. Cái cuối cùng là nhanh nhất để gõ :)
Điều đó không quan trọng - chúng hoàn toàn giống nhau. Tuy nhiên, điều chính là bạn phải nhất quán
ps Tôi luôn phải vật lộn với loại "điều đúng đắn" này.
Đây hoàn toàn là một ưu tiên kiểu mã, làm thế nào để .NET xử lý các chuỗi. Tuy nhiên, đây là ý kiến của tôi :)
Tôi luôn luôn sử dụng các tên BCL Loại khi truy cập vào các phương pháp tĩnh, tài sản và các lĩnh vực: String.Empty
hay Int32.TryParse(...)
hayDouble.Epsilon
Tôi luôn sử dụng các từ khóa C # khi khai báo các trường hợp mới: int i = 0;
hoặcstring foo = "bar";
Tôi hiếm khi sử dụng các chuỗi ký tự không được khai báo vì tôi muốn có thể quét mã để kết hợp chúng thành các hằng có tên có thể tái sử dụng. Trình biên dịch thay thế các hằng số bằng chữ dù sao vì vậy đây là cách để tránh các chuỗi / số ma thuật và mang lại một chút ý nghĩa cho chúng bằng một tên. Cộng với việc thay đổi các giá trị dễ dàng hơn.
Một trong hai người đầu tiên sẽ được tôi chấp nhận. Tôi sẽ tránh cái cuối cùng vì việc giới thiệu một lỗi tương đối dễ dàng bằng cách đặt một khoảng trắng giữa các trích dẫn. Lỗi đặc biệt này sẽ khó tìm thấy bằng quan sát. Giả sử không có lỗi chính tả, tất cả đều tương đương về mặt ngữ nghĩa.
[BIÊN TẬP]
Ngoài ra, bạn có thể muốn luôn luôn sử dụng string
hoặc String
để thống nhất, nhưng đó chỉ là tôi.
Cá nhân tôi đã chứng kiến "" dẫn đến các vấn đề (nhỏ) hai lần. Một lần là do lỗi của một nhà phát triển cơ sở mới đối với lập trình dựa trên nhóm và cái kia là một lỗi đánh máy đơn giản, nhưng thực tế là sử dụng chuỗi.Empty sẽ tránh được cả hai vấn đề.
Vâng, đây thực sự là một lời kêu gọi phán xét, nhưng khi một ngôn ngữ mang đến cho bạn nhiều cách để thực hiện, tôi có xu hướng nghiêng về một ngôn ngữ có khả năng giám sát trình biên dịch mạnh nhất và thực thi thời gian biên dịch mạnh nhất. Đó không phải là "". Đó là tất cả về việc thể hiện ý định cụ thể.
Nếu bạn gõ string.EMpty hoặc Strng.Empty, trình biên dịch sẽ cho bạn biết bạn đã làm sai. Ngay. Nó chỉ đơn giản là sẽ không biên dịch. Là một nhà phát triển, bạn đang trích dẫn ý định cụ thể mà trình biên dịch (hoặc nhà phát triển khác) không thể hiểu sai theo bất kỳ cách nào và khi bạn làm sai, bạn không thể tạo ra lỗi.
Nếu bạn gõ "" khi bạn có nghĩa là "" hoặc ngược lại, trình biên dịch sẽ vui vẻ làm những gì bạn bảo nó làm. Một nhà phát triển khác có thể hoặc không thể lượm lặt được ý định cụ thể của bạn. Lỗi tạo ra.
Rất lâu trước chuỗi.Empty là một điều tôi đã sử dụng một thư viện chuẩn xác định hằng số EMPTY_STRING. Chúng tôi vẫn sử dụng hằng số đó trong các câu lệnh tình huống trong đó string.Empty không được phép.
Bất cứ khi nào có thể, hãy đặt trình biên dịch để làm việc cho bạn và loại bỏ khả năng lỗi của con người, dù nhỏ đến đâu. IMO, điều này vượt qua "khả năng đọc" như những người khác đã trích dẫn.
Tính cụ thể và biên dịch thời gian thực thi. Đó là những gì cho bữa tối.
Trình biên dịch sẽ làm cho tất cả chúng giống nhau trong thời gian dài. Chọn một tiêu chuẩn để mã của bạn sẽ dễ đọc và gắn bó với nó.
Tôi chỉ nhìn vào một số mã và câu hỏi này xuất hiện trong đầu tôi mà tôi đã đọc một thời gian trước đây. Đây chắc chắn là một câu hỏi về khả năng đọc.
Hãy xem xét mã C # sau đây ...
(customer == null) ? "" : customer.Name
đấu với
(customer == null) ? string.empty : customer.Name
Cá nhân tôi thấy cái sau ít mơ hồ và dễ đọc hơn.
Như được chỉ ra bởi những người khác, sự khác biệt thực tế là không đáng kể.
Trong khi sự khác biệt là rất, RẤT ít, sự khác biệt vẫn tồn tại.
1) "" tạo đối tượng trong khi String.Empty thì không. Nhưng đối tượng này sẽ được tạo một lần và sẽ được tham chiếu từ nhóm chuỗi sau nếu bạn có "" khác trong mã.
2) Chuỗi và chuỗi giống nhau, nhưng tôi khuyên bạn nên sử dụng String.Empty (cũng như String.Format, String.Copy, v.v.) vì ký hiệu dấu chấm chỉ lớp, không phải toán tử và có lớp bắt đầu bằng chữ in hoa phù hợp với Tiêu chuẩn mã hóa C #.
Trên http://bloss.msdn.com/b/brada/archive/2003/04/22/49997.aspx :
Như David ngụ ý, có sự khác biệt giữa
String.Empty
và""
khá nhỏ, nhưng có một sự khác biệt.""
Tôi thực sự tạo ra một đối tượng, nó có thể sẽ bị kéo ra khỏi chuỗi intern, nhưng vẫn ... trong khiString.Empty
không tạo đối tượng nào ... vì vậy nếu bạn thực sự tìm kiếm hiệu quả bộ nhớ, tôi đề nghịString.Empty
. Tuy nhiên, bạn nên lưu ý sự khác biệt như vậy trival bạn sẽ thích không bao giờ nhìn thấy nó trong mã của bạn ...
Đối vớiSystem.String.Empty
hoặcstring.Empty
hoặcString.Empty
... Học chăm sóc của tôi là thấp ;-)
Chuỗi rỗng giống như tập rỗng chỉ là một tên mà mọi người sử dụng để gọi ""
. Ngoài ra, trong các ngôn ngữ chính thức, các chuỗi được tạo từ một bảng chữ cái có độ dài bằng 0 được gọi là chuỗi rỗng. Cả bộ và chuỗi có một biểu tượng đặc biệt cho nó. Chuỗi rỗng: và tập rỗng:. Nếu bạn muốn nói về chuỗi có độ dài bằng không này, bạn sẽ gọi nó là chuỗi rỗng để mọi người biết chính xác những gì bạn đang đề cập đến. Bây giờ trong trường hợp bạn đặt tên cho nó là chuỗi rỗng tại sao không sử dụng string.Empty
mã, nó cho thấy ý định rõ ràng. Nhược điểm là nó không phải là hằng số và do đó không có sẵn ở mọi nơi, như trong các thuộc tính. (Đây không phải là hằng số vì một số lý do kỹ thuật, xem nguồn tham khảo.)
Tôi thích ""
bởi vì nó ngắn hơn và String.Empty
giải quyết một vấn đề không tồn tại.