ทำไมฉันจึงสร้างคลาสชื่อ“ var” ได้


103

ไม่ใช่varคีย์เวิร์ดใน C #? แต่ทำไมฉันถึงทำได้:

public class var { }

public class main
{
    public static void main(string[] args)
    {
        var testVar = new var();
    }
}

varที่ใช้ในรหัสเป็นvarชั้นเรียนที่มีการประกาศก่อนที่mainระดับ และคอมไพเลอร์ไม่แม้แต่จะบ่น

ในขณะที่ฉันทำสิ่งนี้:

public class int { }

หรือสิ่งนี้:

public class true { }

คอมไพเลอร์บอกว่าintหรือtrueเป็นคีย์เวิร์ดและไม่สามารถใช้แบบนั้นได้ ทำไมถึงไม่เหมือนกันกับvar?


6
ทำไมคุณถึงต้องการ? สับสนและยากที่จะอ่าน
duffymo

6
อ่านสิ่งนี้: blogs.msdn.com/b/ericlippert/archive/2009/05/11/…
AakashM

31
เป็นคำถามที่ดีมาก!
Richard

50
คุณยังสามารถทำได้var var = "var";ในวิธีการ หลังจากนั้นก็เป็นวันศุกร์
Henk Holterman

11
ฉันเดาว่าพวกเขาทำแบบนี้เพื่อให้เข้ากันได้กับ code create ก่อนที่ "var" จะมีความหมายอะไรเป็นพิเศษ
vidstige

คำตอบ:


101

varไม่ใช่คำหลักตามรายการนี้

มันเป็นคีย์เวิร์ดตามบริบทดังนั้นจากบริบทคอมไพลเลอร์สามารถตัดสินใจได้ว่าคลาสใดเป็นคลาสของคุณและอันไหนเป็นคีย์เวิร์ดตามบริบทและไม่มีความสับสนเกิดขึ้น

คำหลักตามบริบทคือ:

ใช้เพื่อให้ความหมายเฉพาะในรหัส แต่ไม่ใช่คำสงวนใน C #

ดังนั้นเนื่องจากไม่ได้สงวนไว้คุณสามารถใช้งานได้

ตามที่ระบุไว้ในความคิดเห็นด้านบนมีการอภิปรายเกี่ยวกับความแตกต่างรวมถึงรายการคำหลักต่างๆและคำหลักตามบริบทที่เพิ่มใน c # แต่ละเวอร์ชันในบล็อก Eric Lipperts

เป็นเรื่องที่น่าสนใจที่จะทราบว่าเนื่องจากชุดคำหลักถูกตัดสินใน C # 1.0 จึงไม่มีการเพิ่มเติมใด ๆ เพื่อรักษาความเข้ากันได้แบบย้อนกลับ


1
อย่างไรก็ตามมันถูกจัดหมวดหมู่ภายใต้ "คำหลัก C #" ที่นี่msdn.microsoft.com/en-us/library/bb383973.aspx ... งง!
Richard

4
แต่มันคือContextual Keyword. "คำหลักตามบริบทใช้เพื่อให้ความหมายเฉพาะในรหัส แต่ไม่ใช่คำสงวนใน C #คำหลักตามบริบทบางคำเช่นบางส่วนและที่ไหนมีความหมายพิเศษในสองบริบทหรือมากกว่านั้น"
Tim Schmelter

5
@TimSchmelter จากนั้น "var" คือ "คำหลัก" แค่ไม่ใช่ "คำสงวน" ใช่ไหม?
luiscubal

2
ฉันคาดเดาว่าจะต้องรักษาความเข้ากันได้กับรหัสเก่า - ถ้ามีคนตั้งชื่อคลาสvarแล้วทุกอย่างไม่พังเมื่ออัปเกรด C #
Callum Rogers

1
@CallumRogers: ที่ว่าทำไมทีม C # ทำอย่างนี้ เช่นเดียวกับ "คำหลัก" อื่น ๆ ที่แนะนำในภายหลังเช่นจากเข้าร่วม ฯลฯ (ตามบริบททั้งหมด)
Abel

18

คอมไพเลอร์ฉลาดพอที่จะรู้ว่าบริบทที่คุณใช้varเป็นชื่อคลาสไม่เคยเป็นบริบทสำหรับคีย์เวิร์ดจึงอนุญาต (ซึ่งเป็นสาเหตุที่กำหนดให้เป็นคีย์เวิร์ดตามบริบท )


ฉันคิดว่าคำตอบนี้อย่างน้อยก็ทำให้เข้าใจผิด คอมไพเลอร์ไม่ว่า "พอสมาร์ท" เพื่อตรวจสอบว่ามีการใช้เป็นคำหลักในรหัสเช่นvar var testVar = new var();ใช่บริบทในแง่ที่ว่ามีการกำหนดประเภทที่กำหนดเองที่ตั้งชื่อvarไว้หรือไม่ แต่เป็นเพราะคอมไพเลอร์ไม่ฉลาดพอในกรณีเหล่านั้นที่จะรู้ว่าvar testVarอ้างถึงคลาสvarหรือคีย์เวิร์ดvarที่เป็นค่าเริ่มต้นของคลาส ในบริบทดังกล่าว เป็นvarคำหลักชื่อแตกต่างกันก็สามารถนำมาใช้ใน "บริบท" เดียวกันมาก
หรือผู้ทำแผนที่

ตรงกันข้ามกับคีย์เวิร์ดตามบริบทอื่น ๆ เช่นadd- ที่นี่คอมไพเลอร์รู้ทุกครั้งว่าคีย์เวิร์ดนั้นหมายถึงอะไร (การประกาศเหตุการณ์ตัวระบุจะไม่สมเหตุสมผลที่นั่น) หรือโค้ดนั้นอ้างถึงตัวระบุ (ประเภทหรือ ชื่อในการประกาศการใช้ตัวระบุภายในเนื้อความวิธีการคีย์เวิร์ดจะไม่สมเหตุสมผล)
หรือผู้ทำแผนที่

12

อีกวิธีหนึ่งในการดูสิ่งนี้: "var" เป็นคีย์เวิร์ดไม่ได้อยู่ใน C # เวอร์ชันแรก (ไม่เหมือนกับ "int" และ "true") ดังนั้นคุณอาจเขียนโค้ดบางส่วนแล้วซึ่งมีคลาสชื่อ "var" นี่เป็นสิ่งที่ดีและถูกกฎหมาย หลังจากนั้นเมื่อมีการเพิ่ม "var" ลงในภาษานักออกแบบก็ใจดีที่จะกำหนดให้เป็นคีย์เวิร์ดในบางบริบทเท่านั้นดังนั้นคลาส var ที่มีอยู่ของคุณจะยังคงใช้งานได้

นี่เป็นหนึ่งในความท้าทายที่แท้จริงของการออกแบบภาษา - วิธีเพิ่มคุณสมบัติใหม่โดยไม่ทำลายโค้ดที่มีอยู่และไม่ทำให้ฟีเจอร์ใหม่ยุ่งยากในการใช้งาน


8

ในเวอร์ชัน C # ก่อนเวอร์ชัน 3 ยังไม่รองรับตัวแปรโลคัลที่พิมพ์โดยปริยายดังนั้นจึงvarไม่มีความหมายพิเศษและสามารถกำหนดตัวแปรและคลาสที่ตั้งชื่อvarได้ โปรแกรมตัวอย่างของคุณเป็นกฎหมายเพราะทั้งสองเหตุการณ์varในเรียกว่าชั้นเรียนmainvar

C # 3 และเวอร์ชันที่ใหม่กว่าสามารถใช้งานร่วมกันได้ดังนั้นโค้ดที่เขียนใน C # ก่อนเวอร์ชัน 3 จะยังคงคอมไพเลอร์ด้วยคอมไพเลอร์ใหม่

intและtrueเป็นคำหลักตั้งแต่ C # 1


3

คำหลักสามารถสงวนตามบริบท เมื่อมีการแยกวิเคราะห์ซอร์สโค้ดบริบทนั้นจะถูกสร้างขึ้นเป็นส่วนหนึ่งของแผนผังการแยกวิเคราะห์ การประเมินคำหลักจะเกิดขึ้นภายในบริบทนั้น ดังนั้นในกรณีนี้ var ไม่ได้อยู่ในบริบทที่สงวนไว้และจะไม่มีความหมายเหมือนกับเวลาที่คุณใช้ในคำสั่งมอบหมาย ฉันเชื่อว่าเหตุผลหนึ่งสำหรับความยืดหยุ่นนี้คือ var ถูกนำมาใช้ใน C # 3 ดังนั้นการสงวนไว้ทุกที่อาจทำให้ความเข้ากันได้ย้อนหลังในบางโปรแกรมเสียไปในขณะที่การใช้เป็นประกาศประเภทตัวแปรจะไม่ได้รวบรวมในเวอร์ชันก่อนหน้าดังนั้นจึงไม่มี แตก

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.