ใน. Net ทำไมเป็น String.Empty อ่านอย่างเดียวแทนที่จะเป็นค่าคงที่? ฉันแค่สงสัยว่าถ้าใครรู้ว่าเหตุผลอยู่เบื้องหลังการตัดสินใจ
ใน. Net ทำไมเป็น String.Empty อ่านอย่างเดียวแทนที่จะเป็นค่าคงที่? ฉันแค่สงสัยว่าถ้าใครรู้ว่าเหตุผลอยู่เบื้องหลังการตัดสินใจ
คำตอบ:
เหตุผลที่static readonly
ถูกนำมาใช้แทนconst
เป็นเพราะใช้กับรหัสที่ไม่มีการจัดการตามที่ระบุโดยไมโครซอฟท์ที่นี่ในแหล่งที่มาร่วมกันภาษาทั่วไปโครงสร้างพื้นฐาน 2.0 ที่วางจำหน่าย sscli20\clr\src\bcl\system\string.cs
แฟ้มดูที่เป็น
ค่าคงที่ว่างเปล่าเก็บค่าสตริงว่าง เราจำเป็นต้องเรียกใช้ตัวสร้างสตริงเพื่อให้คอมไพเลอร์ไม่ได้ทำเครื่องหมายสิ่งนี้ว่าเป็นตัวอักษร
การทำเครื่องหมายสิ่งนี้เป็นตัวอักษรหมายถึงว่ามันไม่ปรากฏเป็นเขตข้อมูลที่เราสามารถเข้าถึงได้จากเจ้าของภาษา
ผมพบว่าข้อมูลนี้จากบทความที่มีประโยชน์นี้ที่ CodeProject
String.Empty
อีกต่อไปด้วยเหตุผลเพียงอย่างเดียว
ฉันคิดว่ามีความสับสนและการตอบสนองที่ไม่ดีที่นี่
ก่อนอื่นconst
ฟิลด์คือstatic
สมาชิก ( ไม่ใช่สมาชิกอินสแตนซ์ )
ตรวจสอบส่วนที่ 10.4 ค่าคงที่ของข้อกำหนดภาษา C #
แม้ว่าค่าคงที่จะถูกพิจารณาว่าเป็นสมาชิกแบบสแตติกการประกาศอย่างต่อเนื่องไม่จำเป็นต้องมีหรือไม่อนุญาตให้ตัวดัดแปลงแบบคงที่
หากpublic const
สมาชิกเป็นสมาชิกคงไม่สามารถคิดได้ว่าค่าคงที่จะสร้างวัตถุใหม่
ให้นี้บรรทัดของรหัสต่อไปทำว่าสิ่งเดียวกันในส่วนที่เกี่ยวกับการสร้างวัตถุใหม่
public static readonly string Empty = "";
public const string Empty = "";
นี่คือบันทึกจาก Microsoft ที่อธิบายถึงความแตกต่างระหว่าง 2:
คำหลักแบบอ่านอย่างเดียวแตกต่างจากคำหลัก const ฟิลด์ const สามารถเริ่มต้นได้ที่การประกาศของฟิลด์เท่านั้น เขตข้อมูลแบบอ่านอย่างเดียวสามารถเริ่มต้นได้ทั้งที่การประกาศหรือในตัวสร้าง ดังนั้นเขตข้อมูลแบบอ่านอย่างเดียวสามารถมีค่าแตกต่างกันขึ้นอยู่กับตัวสร้างที่ใช้ นอกจากนี้ในขณะที่เขตข้อมูล const เป็นค่าคงที่เวลารวบรวม, เขตข้อมูลแบบอ่านอย่างเดียวสามารถใช้สำหรับค่าคงที่แบบรันไทม์, ...
ดังนั้นฉันจึงพบว่าคำตอบที่น่าเชื่อถือเพียงข้อเดียวคือเจฟฟ์เยตส์
const string
และstatic readonly string
ทำสิ่งเดียวกัน ค่า Const ถูกแทนที่ในโค้ดที่เชื่อมโยงในขณะที่ค่าคงที่อ่านอย่างเดียวจะถูกอ้างอิง หากคุณมีconst
ไลบรารีใน A ที่ใช้โดยไลบรารี B ไลบรารี B จะแทนที่การอ้างอิงทั้งหมดไปยังconst
ตัวแปรนั้นด้วยค่าตัวอักษร หากตัวแปรนั้นถูกstatic readonly
แทนที่มันจะถูกอ้างอิงและค่าของมันจะถูกกำหนดที่รันไทม์
String.Empty read only instead of a constant?
หากคุณทำให้ค่าคงที่สตริงใด ๆคอมไพเลอร์จะถูกแทนที่ด้วยสตริงจริงทุกที่ที่คุณเรียกใช้และคุณเติมโค้ดของคุณด้วยสตริงเดียวกันทั่วทุกครั้งและเมื่อโค้ดที่รันนั้นจำเป็นต้องอ่านอีกครั้งและอีกครั้ง ข้อมูล.
ถ้าคุณปล่อยให้สายของคุณอ่านได้ที่เดียวเพราะมันคือ String.Empty
โปรแกรมจะเก็บสายเดียวกันไว้ในที่เดียวแล้วอ่านมันหรืออ้างอิงมัน - เก็บข้อมูลไว้ในหน่วยความจำขั้นต่ำ
นอกจากนี้หากคุณรวบรวม dll ใด ๆ ที่ใช้ String.Empty เป็น const และด้วยเหตุผลใดก็ตามที่การเปลี่ยนแปลง String.Empty จากนั้น dll รวบรวมที่รวบรวมจะไม่ทำงานอีกต่อไปเหมือนกันเพราะ cost
ทำโค้ดภายในเพื่อเก็บสำเนาของสตริง ทุกการโทร
ดูรหัสนี้เช่น:
public class OneName
{
const string cConst = "constant string";
static string cStatic = "static string";
readonly string cReadOnly = "read only string";
protected void Fun()
{
string cAddThemAll ;
cAddThemAll = cConst;
cAddThemAll = cStatic ;
cAddThemAll = cReadOnly;
}
}
คอมไพเลอร์จะมาเป็น:
public class OneName
{
// note that the const exist also here !
private const string cConst = "constant string";
private readonly string cReadOnly;
private static string cStatic;
static OneName()
{
cStatic = "static string";
}
public OneName()
{
this.cReadOnly = "read only string";
}
protected void Fun()
{
string cAddThemAll ;
// look here, will replace the const string everywhere is finds it.
cAddThemAll = "constant string";
cAddThemAll = cStatic;
// but the read only will only get it from "one place".
cAddThemAll = this.cReadOnly;
}
}
และการเรียกชุมนุม
cAddThemAll = cConst;
0000003e mov eax,dword ptr ds:[09379C0Ch]
00000044 mov dword ptr [ebp-44h],eax
cAddThemAll = cStatic ;
00000047 mov eax,dword ptr ds:[094E8C44h]
0000004c mov dword ptr [ebp-44h],eax
cAddThemAll = cReadOnly;
0000004f mov eax,dword ptr [ebp-3Ch]
00000052 mov eax,dword ptr [eax+0000017Ch]
00000058 mov dword ptr [ebp-44h],eax
แก้ไข: พิมพ์ผิด
คำตอบนี้มีอยู่เพื่อวัตถุประสงค์ทางประวัติศาสตร์
แต่เดิม:
เพราะString
เป็นคลาสจึงไม่สามารถเป็นค่าคงที่ได้
ขยายการสนทนา:
กล่องโต้ตอบที่มีประโยชน์มากมายถูกตอกย้ำในการตอบคำถามนี้และแทนที่จะลบออกเนื้อหานี้จะถูกทำซ้ำโดยตรง:
ใน. NET สตริง (ซึ่งแตกต่างจากใน Java) และสตริงเหมือนกันทุกประการ และใช่คุณสามารถมีค่าคงที่ตัวอักษรสตริงใน. NET - DrJokepu 3 กุมภาพันธ์ 09 เวลา 16:57
คุณกำลังบอกว่าคลาสไม่สามารถมีค่าคงที่ได้หรือไม่? - StingyJack 3 ก.พ. 09 เวลา 16:58
ใช่วัตถุต้องใช้แบบอ่านอย่างเดียว structs เท่านั้นที่สามารถทำค่าคงที่ ฉันคิดว่าเมื่อคุณใช้
string
แทนString
คอมไพเลอร์เปลี่ยน const เป็นแบบอ่านอย่างเดียวสำหรับคุณ ทุกอย่างเกี่ยวกับการทำให้โปรแกรมเมอร์ C มีความสุข - Garry Shutler 3 ก.พ. 09 เวลา 16:59tvanfosson เพิ่งอธิบายมัน verbose เพิ่มเติมอีกนิด "X ไม่สามารถเป็นค่าคงที่ได้เนื่องจาก Y ที่บรรจุอยู่ในชั้นเรียน" เป็นเพียงบริบทน้อยเกินไป;) #: 38211 Leonidas
string.Empty เป็นคุณสมบัติสแตติกที่ส่งคืนอินสแตนซ์ของคลาส String กล่าวคือสตริงว่างไม่ใช่คลาสสตริงเอง - tvanfosson 3 กุมภาพันธ์ 2552 เวลา 17:01 น
Empty เป็นอินสแตนซ์แบบอ่านอย่างเดียว (ไม่ใช่คุณสมบัติ) ของคลาส String - senfo 3 ก.พ. 09 เวลา 17:02
ปวดหัว ฉันยังคิดว่าฉันพูดถูก แต่ตอนนี้ฉันไม่ค่อยแน่ใจ งานวิจัยที่ต้องการคืนนี้! - Garry Shutler 3 ก.พ. 09 เวลา 17:07 น
สตริงว่างเป็นตัวอย่างของคลาสสตริง Empty เป็นฟิลด์สแตติก (ไม่ใช่คุณสมบัติฉันยืนแก้ไข) ในคลาส String โดยทั่วไปความแตกต่างระหว่างตัวชี้และสิ่งที่ชี้ไป ถ้ามันไม่ได้อ่านอย่างเดียวเราสามารถเปลี่ยนอินสแตนซ์ที่ฟิลด์ว่างอ้างถึงได้ - tvanfosson 3 ก.พ. 09 เวลา 17:07
แกร์รีคุณไม่จำเป็นต้องทำการวิจัยใด ๆ ลองคิดดู String เป็นคลาส Empty เป็นตัวอย่างของ String - senfo 3 ก.พ. 09 เวลา 17:12
มีบางอย่างที่ฉันไม่ค่อยได้รับ: ตัวสร้างสแตติกของคลาส String สามารถสร้างอินสแตนซ์ของคลาส String ได้อย่างไรบนโลก นั่นไม่ใช่สถานการณ์แบบ "ไก่หรือไข่" ใช่ไหม - DrJokepu 3 ก.พ. 09 เวลา 17:12 5
คำตอบนี้จะถูกต้องสำหรับเกือบทุกชั้นอื่น ๆ แต่ System.String .NET ทำปลอกประสิทธิภาพเป็นพิเศษสำหรับสตริงจำนวนมากและหนึ่งในนั้นคือคุณสามารถมีค่าคงที่สตริงได้เพียงลองใช้ ในกรณีนี้ Jeff Yates มีคำตอบที่ถูกต้อง - Joel Mueller 3 ก.พ. 09 เวลา 19:25
ดังที่อธิบายไว้ใน§7.18นิพจน์คงที่คือนิพจน์ที่สามารถประเมินได้ทั้งหมดในเวลาคอมไพล์ เนื่องจากวิธีเดียวในการสร้างค่าที่ไม่เป็น null ของการอ้างอิงชนิดอื่นที่ไม่ใช่สตริงคือการใช้โอเปอเรเตอร์ใหม่และเนื่องจากไม่อนุญาตให้โอเปอเรเตอร์ใหม่ในนิพจน์คงที่จึงมีความเป็นไปได้สำหรับค่าคงที่ประเภทอ้างอิง นอกเหนือจากสตริงเป็นโมฆะ ความคิดเห็นสองรายการก่อนหน้าถูกนำมาโดยตรงจากข้อกำหนดภาษา C # และย้ำถึงสิ่งที่ Joel Mueller พูดถึง - senfo 4 ก.พ. 09 เวลา 15:05 5