ใน. NET ความแตกต่างระหว่างString.Empty
และ""
และเป็นสิ่งที่สามารถแลกเปลี่ยนกันได้หรือมีการอ้างอิงพื้นฐานหรือปัญหาการโลคัลไลซ์เซชันเกี่ยวกับความเสมอภาคที่String.Empty
จะทำให้แน่ใจว่าไม่มีปัญหา
ใน. NET ความแตกต่างระหว่างString.Empty
และ""
และเป็นสิ่งที่สามารถแลกเปลี่ยนกันได้หรือมีการอ้างอิงพื้นฐานหรือปัญหาการโลคัลไลซ์เซชันเกี่ยวกับความเสมอภาคที่String.Empty
จะทำให้แน่ใจว่าไม่มีปัญหา
คำตอบ:
ใน. NET ก่อนหน้ารุ่น 2.0 ""
สร้างวัตถุในขณะที่string.Empty
สร้างไม่มีการอ้างอิงวัตถุซึ่งทำให้string.Empty
มีประสิทธิภาพมากขึ้น
ในรุ่น 2.0 และหลังจาก .NET, เหตุการณ์ที่เกิดขึ้นทั้งหมดของ""
ดูที่ตัวอักษรสายเดียวกันซึ่งหมายความว่า""
จะเทียบเท่ากับการแต่ยังคงไม่เป็นอย่างที่.Empty
.Length == 0
.Length == 0
เป็นตัวเลือกที่เร็วที่สุด แต่.Empty
สร้างรหัสที่ทำความสะอาดได้เล็กน้อย
ดูสเปค NET สำหรับข้อมูลเพิ่มเติม
string.IsNullOrEmpty( stringVar )
หรือคุณอาจจะใช้
ความแตกต่างระหว่าง String.Empty และ "" คืออะไรและสามารถใช้ร่วมกันได้
string.Empty
เป็นฟิลด์อ่านอย่างเดียวในขณะที่""
เป็นค่าคงที่เวลารวบรวม สถานที่ที่พวกเขาทำงานแตกต่างกันคือ:
ค่าพารามิเตอร์เริ่มต้นใน C # 4.0 หรือสูงกว่า
void SomeMethod(int ID, string value = string.Empty)
// Error: Default parameter value for 'value' must be a compile-time constant
{
//... implementation
}
การแสดงออกกรณีในงบสลับ
string str = "";
switch(str)
{
case string.Empty: // Error: A constant value is expected.
break;
case "":
break;
}
ข้อโต้แย้งคุณสมบัติ
[Example(String.Empty)]
// Error: An attribute argument must be a constant expression, typeof expression
// or array creation expression of an attribute parameter type
String.Empty
การโต้แย้งในกรณีส่วนใหญ่ คุณมีสิทธิ์ที่ตัวอย่างทั้งหมดแสดงให้เห็นว่าyou simply can't put a (run-time) "value" into (compile-time) metadata
และนั่นคือสิ่งที่ตัวอย่างมีวัตถุประสงค์เพื่อแสดง
คำตอบก่อนหน้านี้ถูกต้องสำหรับ. NET 1.1 (ดูวันที่โพสต์ที่ลิงก์: 2003) ตั้งแต่. NET 2.0 ขึ้นไปไม่มีความแตกต่าง JIT จะจบลงด้วยการอ้างอิงวัตถุเดียวกันบนกองใด ๆ
ตามข้อกำหนด C #, ส่วน 2.4.4.5: http://msdn.microsoft.com/en-us/library/aa691090(VS.71).aspx
แต่ละสตริงตัวอักษรไม่จำเป็นต้องส่งผลให้เกิดอินสแตนซ์ของสตริงใหม่ เมื่อตัวอักษรสตริงอย่างน้อยสองตัวที่เทียบเท่าตามตัวดำเนินการสตริงที่เท่ากัน (ส่วน 7.9.7) ปรากฏในแอสเซมบลีเดียวกันตัวอักษรสตริงเหล่านี้อ้างอิงถึงอินสแตนซ์ของสตริงเดียวกัน
บางคนถึงกับกล่าวถึงสิ่งนี้ในความคิดเห็นของโพสต์ของแบรดอะรัม
โดยสรุปผลการปฏิบัติของ "" กับ String.Empty คือศูนย์ JIT จะคิดในท้ายที่สุด
ฉันได้ค้นพบแล้วว่า JIT นั้นฉลาดกว่าฉันดังนั้นฉันจึงพยายามไม่ฉลาดเกินกว่าที่จะใช้การเพิ่มประสิทธิภาพไมโครคอมไพเลอร์แบบนั้น JIT จะเปิดสำหรับลูป () ลูป, ลบโค้ดที่ซ้ำซ้อน, วิธีการอินไลน์, ฯลฯ ดีกว่าและในเวลาที่เหมาะสมกว่า I หรือคอมไพเลอร์ C # ที่สามารถคาดการณ์ล่วงหน้าได้ ปล่อยให้ JIT ทำงาน :)
String.Empty
คืออ่านได้อย่างเดียวฟิลด์ในขณะที่""
เป็นconst หมายความว่าคุณไม่สามารถใช้String.Empty
คำสั่ง switch ได้เนื่องจากมันไม่คงที่
default
คำหลักที่เราสามารถส่งเสริมการอ่านได้โดยไม่ต้องป้องกันการแก้ไขโดยไม่ได้ตั้งใจและมีค่าคงที่เวลารวบรวมแม้ว่าจะซื่อสัตย์ฉันยังคงคิดว่า String.Empty สามารถอ่านได้มากกว่าค่าเริ่มต้น แต่พิมพ์ช้ากว่า
ความแตกต่างก็คือว่า String.Empty สร้างรหัส CIL ที่ใหญ่กว่า ในขณะที่โค้ดสำหรับการอ้างอิง "" และ String.Empty มีความยาวเท่ากันคอมไพเลอร์ไม่ปรับการเรียงสตริงให้เหมาะสม (ดูโพสต์บล็อกของ Eric Lippert ) สำหรับอาร์กิวเมนต์ String.Empty ฟังก์ชั่นเทียบเท่าต่อไปนี้
string foo()
{
return "foo" + "";
}
string bar()
{
return "bar" + string.Empty;
}
สร้าง IL นี้
.method private hidebysig instance string foo() cil managed
{
.maxstack 8
L_0000: ldstr "foo"
L_0005: ret
}
.method private hidebysig instance string bar() cil managed
{
.maxstack 8
L_0000: ldstr "bar"
L_0005: ldsfld string [mscorlib]System.String::Empty
L_000a: call string [mscorlib]System.String::Concat(string, string)
L_000f: ret
}
"bar " + (ok ? "" : "error")
คำตอบข้างต้นนั้นถูกต้องทางเทคนิค แต่สิ่งที่คุณอาจต้องการใช้เพื่อการอ่านโค้ดที่ดีที่สุดและโอกาสที่น้อยที่สุดของการยกเว้นคือString.IsNullOrEmpty (s)
--foo=$BAR
คุณอาจต้องการเห็นความแตกต่างระหว่างพวกเขาลืมที่จะตั้งค่า env var และพวกเขาไม่ผ่านการตั้งค่าสถานะเลย string.IsNullOrEmpty
มักเป็นรหัสกลิ่นที่คุณยังไม่ได้ตรวจสอบอินพุตของคุณอย่างถูกต้องหรือกำลังทำสิ่งแปลก ๆ โดยทั่วไปคุณไม่ควรยอมรับสตริงที่ว่างเปล่าเมื่อคุณต้องการใช้งานnull
จริงหรือสิ่งที่ต้องการประเภทตัวเลือกอาจ /
ฉันมักจะใช้String.Empty
แทน""
เหตุผลง่าย ๆ แต่ก็ไม่ชัดเจน:
""
และ""
ไม่เหมือนกันตัวแรกมีอักขระความกว้าง 16 ศูนย์จริง ๆ เห็นได้ชัดว่าไม่มีนักพัฒนาที่มีความสามารถจะใส่และอักขระความกว้างเป็นศูนย์ในรหัสของพวกเขา แต่ถ้าพวกเขาเข้าไปที่นั่นมันอาจเป็นฝันร้ายของการบำรุงรักษา
หมายเหตุ:
ฉันใช้U + FEFFในตัวอย่างนี้
ไม่แน่ใจว่า SO จะกินอักขระเหล่านั้นหรือไม่ แต่ลองด้วยตัวคุณเองด้วยหนึ่งในอักขระที่มีความกว้างเป็นศูนย์
ฉันเพิ่งมาขอบคุณนี้เพื่อhttps://codegolf.stackexchange.com/
ใช้มากกว่าString.Empty
""
นี่คือความเร็วมากกว่าการใช้หน่วยความจำ แต่เป็นเคล็ดลับที่มีประโยชน์
""
เป็นดังนั้นตัวอักษรจะทำหน้าที่เป็นตัวอักษร: ในการใช้งานครั้งแรกมันถูกสร้างขึ้นและต่อไปนี้ใช้อ้างอิงจะถูกส่งกลับ อินสแตนซ์เดียวเท่านั้นที่""
จะถูกเก็บไว้ในหน่วยความจำไม่ว่าจะใช้กี่ครั้งก็ตาม! ฉันไม่เห็นบทลงโทษของหน่วยความจำใด ๆ ที่นี่ ปัญหาคือว่าทุกครั้งที่""
มีการใช้การวนลูปการเปรียบเทียบจะดำเนินการเพื่อตรวจสอบว่า""
มีอยู่แล้วในสระว่ายน้ำฝึกงาน ในด้านอื่น ๆ ที่String.Empty
มีการอ้างอิงไปยัง""
ที่เก็บไว้ในโซนหน่วยความจำ .NET FrameworkString.Empty
กำลังชี้ไปยังที่อยู่หน่วยความจำเดียวกันสำหรับแอปพลิเคชัน VB.NET และ C # ดังนั้นค้นหาเหตุผลสำหรับการอ้างอิงในแต่ละครั้งที่คุณต้องการ""
เมื่อคุณมีที่อ้างอิงในString.Empty
?
อ้างอิง: String.Empty
vs""
อินสแตนซ์ทั้งหมดของ "" เหมือนกันคือสตริงตัวอักษรที่อยู่ภายใน (หรือควรจะเป็น) ดังนั้นคุณจะไม่ได้โยนวัตถุใหม่บนกองทุกครั้งที่คุณใช้ "" แต่เพียงแค่สร้างการอ้างอิงไปยังวัตถุที่อยู่ภายในแบบเดียวกัน ต้องบอกว่าฉันชอบสตริง ฉันคิดว่ามันทำให้โค้ดอ่านง่ายขึ้น
มันไม่สำคัญหรอก!
บางการสนทนาที่ผ่านมาของสิ่งนี้:
http://www.codinghorror.com/blog/archives/000185.html
string mystring = "";
ldstr ""
ldstr
ผลักดันการอ้างอิงวัตถุใหม่ไปยังตัวอักษรสตริงที่เก็บไว้ในเมตาดาต้า
string mystring = String.Empty;
ldsfld string [mscorlib]System.String::Empty
ldsfld
ผลักดันค่าของสนามคงที่ไปยังกองการประเมินผล
ฉันมักจะใช้String.Empty
แทน""
เพราะ IMHO มันชัดเจนขึ้นและน้อยกว่า VB-ish
Eric Lippert เขียน (17 มิถุนายน 2013):
"อัลกอริทึมแรกที่ฉันเคยทำงานในคอมไพเลอร์ C # เป็นเครื่องมือเพิ่มประสิทธิภาพที่จัดการกับการเรียงสตริงแต่น่าเสียดายที่ฉันไม่ได้จัดการพอร์ตเหล่านี้ไปยังฐานข้อมูล Roslyn ก่อนที่ฉันจะออกไป ไปที่! "
ต่อไปนี้เป็นผลลัพธ์ของRoslyn x64ณ เดือนมกราคม 2562 แม้จะมีข้อสังเกตที่เป็นเอกฉันท์เกี่ยวกับคำตอบอื่น ๆ ในหน้านี้ แต่ก็ไม่ปรากฏว่าฉันปัจจุบัน x64 JIT กำลังปฏิบัติต่อทุกกรณีเหมือนกันเมื่อทุกคนพูดและทำ
อย่างไรก็ตามโดยเฉพาะอย่างยิ่งโปรดทราบว่ามีเพียงหนึ่งในตัวอย่างเหล่านี้ที่จริงแล้วจบการโทรString.Concat
และฉันเดาว่านั่นเป็นเพราะเหตุผลความถูกต้องที่คลุมเครือ ความแตกต่างอื่น ๆ ดูเหมือนยากที่จะอธิบาย
default (String) + {default (String), "", String.Empty}
static String s00() => default(String) + default(String);
mov rax,[String::Empty]
mov rax,qword ptr [rax]
add rsp,28h
ret
static String s01() => default(String) + "";
mov rax,[String::Empty]
mov rax,qword ptr [rax]
add rsp,28h
ret
static String s02() => default(String) + String.Empty;
mov rax,[String::Empty]
mov rax,qword ptr [rax]
mov rdx,rax
test rdx,rdx
jne _L
mov rdx,rax
_L: mov rax,rdx
add rsp,28h
ret
"" + {ค่าเริ่มต้น (สตริง), "", String.Empty}
static String s03() => "" + default(String);
mov rax,[String::Empty]
mov rax,qword ptr [rax]
add rsp,28h
ret
static String s04() => "" + "";
mov rax,[String::Empty]
mov rax,qword ptr [rax]
add rsp,28h
ret
static String s05() => "" + String.Empty;
mov rax,[String::Empty]
mov rax,qword ptr [rax]
mov rdx,rax
test rdx,rdx
jne _L
mov rdx,rax
_L: mov rax,rdx
add rsp,28h
ret
String.Empty + {ค่าเริ่มต้น (String), "", String.Empty}
static String s06() => String.Empty + default(String);
mov rax,[String::Empty]
mov rax,qword ptr [rax]
mov rdx,rax
test rdx,rdx
jne _L
mov rdx,rax
_L: mov rax,rdx
add rsp,28h
ret
static String s07() => String.Empty + "";
mov rax,[String::Empty]
mov rax,qword ptr [rax]
mov rdx,rax
test rdx,rdx
jne _L
mov rdx,rax
_L: mov rax,rdx
add rsp,28h
ret
static String s08() => String.Empty + String.Empty;
mov rcx,[String::Empty]
mov rcx,qword ptr [rcx]
mov qword ptr [rsp+20h],rcx
mov rcx,qword ptr [rsp+20h]
mov rdx,qword ptr [rsp+20h]
call F330CF60 ; <-- String.Concat
nop
add rsp,28h
ret
Microsoft (R) Visual C# Compiler version 2.10.0.0 (b9fb1610)
AMD64 Release
[MethodImpl(MethodImplOptions.NoInlining)]
'SuppressJitOptimization' = false
มาจากจุดนี้ในมุมมองของเอนทิตี้ของเฟรมเวิร์ก: EF เวอร์ชัน 6.1.3 ดูเหมือนจะปฏิบัติกับ String.Empty และ "" แตกต่างกันเมื่อทำการตรวจสอบ
string.Empty ถือว่าเป็นค่า Null สำหรับวัตถุประสงค์ในการตรวจสอบความถูกต้องและจะโยนข้อผิดพลาดในการตรวจสอบความถูกต้องถ้ามันถูกใช้ในช่องที่จำเป็น (ประกอบ) โดยที่ "" จะผ่านการตรวจสอบความถูกต้องและไม่ผิดพลาด
ปัญหานี้อาจแก้ไขได้ใน EF 7+ การอ้างอิง: - https://github.com/aspnet/EntityFramework/issues/2610 )
แก้ไข: [จำเป็น (AllowEmptyStrings = true)] จะแก้ไขปัญหานี้ทำให้สตริงได้รับการตรวจสอบ
เนื่องจาก String.Empty ไม่ใช่ค่าคงที่เวลารวบรวมคุณจึงไม่สามารถใช้เป็นค่าเริ่มต้นในการกำหนดฟังก์ชันได้
public void test(int i=0,string s="")
{
// Function Body
}
public void test(int i=0, string s=string.Empty) {}
จะไม่รวบรวมและพูดว่า "ค่าพารามิเตอร์เริ่มต้นสำหรับ 's' จะต้องเป็นค่าคงที่เวลาคอมไพล์คำตอบของ OP ใช้งานได้
เมื่อคุณสแกนรหัสด้วยสายตา "" จะปรากฏเป็นสีเมื่อมีการเปลี่ยนสีสตริง string.Empty ดูเหมือนการเข้าถึงระดับสมาชิกปกติ ในระหว่างการมองอย่างรวดเร็วจะง่ายต่อการมองเห็นหรือแปลความหมาย
มองเห็นสตริง (การกำหนดสีโอเวอร์โฟลว์สแต็กไม่ได้ช่วย แต่ใน VS จะเห็นได้ชัดเจนกว่า):
var i = 30;
var f = Math.Pi;
var s = "";
var d = 22.2m;
var t = "I am some text";
var e = string.Empty;
\u00ad
นักพัฒนาอาจทำให้ตัวละครที่เป็นศูนย์ที่มีความกว้างระหว่างคำพูดแทนการใช้ลำดับหนีเหมาะสมเช่น
ทุกคนที่นี่ให้การอธิบายทางทฤษฎีที่ดี ฉันมีข้อสงสัยคล้ายกัน ดังนั้นฉันจึงลองเขียนโค้ดพื้นฐานกับมัน และฉันก็พบความแตกต่าง นี่คือความแตกต่าง
string str=null;
Console.WriteLine(str.Length); // Exception(NullRefernceException) for pointing to null reference.
string str = string.Empty;
Console.WriteLine(str.Length); // 0
ดังนั้นดูเหมือนว่า "Null" แปลว่าโมฆะ & "String.Empty" หมายถึงมีค่าบางอย่าง แต่ว่างเปล่า
""
string.Empty
เฉพาะเมื่อพยายามที่จะบอกว่าสตริงว่างเปล่าnull
ได้รับการกล่าวถึง
string.Empty
และสิ่งที่เป็นเหตุผลที่อยู่เบื้องหลังการประกาศเป็นแทนreadonly
const