ทำไม C # ให้รหัสที่บล็อกโดยไม่ต้องมีคำสั่งก่อนหน้านี้ (เช่นif
, else
, for
, while
)?
void Main()
{
{ // any sense in this?
Console.Write("foo");
}
}
ทำไม C # ให้รหัสที่บล็อกโดยไม่ต้องมีคำสั่งก่อนหน้านี้ (เช่นif
, else
, for
, while
)?
void Main()
{
{ // any sense in this?
Console.Write("foo");
}
}
คำตอบ:
ในบริบทที่คุณให้นั้นไม่มีความสำคัญ การเขียนสตริงคงที่ไปยังคอนโซลจะทำงานในลักษณะเดียวกันกับที่ใดก็ได้ในผังงานโปรแกรม 1
โดยทั่วไปคุณจะใช้เพื่อ จำกัด ขอบเขตของตัวแปรท้องถิ่นบางตัว นี้จะชี้แจงเพิ่มเติมที่นี่และที่นี่ ดูคำตอบของJoão AngeloและคำตอบของChris Wallisสำหรับตัวอย่างสั้น ๆ ฉันเชื่อว่าเช่นเดียวกันกับภาษาอื่น ๆ ที่มีไวยากรณ์สไตล์ C เช่นกันไม่ใช่ว่าจะเกี่ยวข้องกับคำถามนี้
1 เว้นแต่ว่าคุณตัดสินใจที่จะพยายามทำตัวตลกและสร้างConsole
ชั้นเรียนของคุณเองด้วยWrite()
วิธีการที่ทำสิ่งที่คาดไม่ถึงอย่างสิ้นเชิง
out
พารามิเตอร์ไปยังการใช้งานอินเทอร์เฟซที่เขียนขึ้น ในภาษาอื่นและการนำไปใช้งานนั้นอ่านตัวแปรก่อนที่จะเขียน
{ ... }
มีอย่างน้อยผลข้างเคียงของการแนะนำขอบเขตใหม่สำหรับตัวแปรท้องถิ่น
ฉันมักจะใช้มันในswitch
คำสั่งเพื่อให้ขอบเขตที่แตกต่างกันสำหรับแต่ละกรณีและด้วยวิธีนี้ทำให้ฉันสามารถกำหนดตัวแปรท้องถิ่นด้วยชื่อเดียวกันในตำแหน่งที่ใกล้เคียงที่สุดเท่าที่จะเป็นไปได้ของการใช้งานของพวกเขาและยังแสดงว่าพวกเขาใช้ได้เฉพาะในระดับเคสเท่านั้น
{}
การเก็บป้ายทองเหล่านั้นไว้ ... :)
มันเป็นไม่มากคุณลักษณะของ C # กว่าที่มันเป็นตรรกะผลข้างเคียงของหลายภาษา C ไวยากรณ์ที่ใช้จัดฟันเพื่อกำหนดขอบเขต
ในตัวอย่างของคุณวงเล็บปีกกาจะไม่มีผลเลย แต่ในโค้ดต่อไปนี้จะกำหนดขอบเขตและดังนั้นการมองเห็นของตัวแปร:
สิ่งนี้ได้รับอนุญาตเมื่อฉันอยู่นอกขอบเขตในบล็อกแรกและถูกกำหนดอีกครั้งในถัดไป
{
{
int i = 0;
}
{
int i = 0;
}
}
สิ่งนี้ไม่ได้รับอนุญาตเนื่องจากฉันอยู่นอกขอบเขตและไม่สามารถมองเห็นได้อีกต่อไปในขอบเขตภายนอก:
{
{
int i = 0;
}
i = 1;
}
และอื่น ๆ ไปเรื่อย ๆ
{}
เรียกว่าวงเล็บ
One of two marks of the form [ ] or ( ), and in mathematical use also {}, used for enclosing a word or number of words, a portion of a mathematical formula, or the like, so as to separate it from the context;
ในกรณีใดก็ตามพวกเขาไม่ใช่วงเล็บ แต่ 'วงเล็บปีกกา' ดูเหมือนจะใช้ได้
ฉันถือว่า{}
เป็นคำสั่งที่สามารถมีหลายข้อความ
พิจารณาคำสั่ง if ที่อยู่นอกนิพจน์บูลีนตามด้วยหนึ่งคำสั่ง สิ่งนี้จะได้ผล:
if (true) Console.Write("FooBar");
สิ่งนี้จะใช้ได้เช่นกัน:
if (true)
{
Console.Write("Foo");
Console.Write("Bar");
}
ถ้าผมจำไม่ผิดเรียกว่า block statement
เนื่องจาก{}
สามารถมีงบอื่น ๆ {}
ก็ยังสามารถมีอื่น ๆ ขอบเขตของตัวแปรถูกกำหนดโดยพาเรนต์{}
(คำสั่งบล็อก)
ประเด็นที่ฉันพยายามจะทำให้เป็น{}
เพียงคำสั่งดังนั้นจึงไม่ต้องใช้ if หรืออะไรก็ตาม ...
กฎทั่วไปในภาษา C-syntax คือ "สิ่งใด ๆ ระหว่าง{ }
ควรถือว่าเป็นคำสั่งเดียวและสามารถไปได้ทุกที่ที่คำสั่งเดียวทำได้":
if
.for
, หรือwhile
do
สำหรับความตั้งใจและวัตถุประสงค์ทั้งหมดเป็นไปตามที่ไวยากรณ์ของภาษารวมไว้:
<statement> :== <definition of valid statement> | "{" <statement-list> "}"
<statement-list> :== <statement> | <statement-list> <statement>
นั่นคือ "คำสั่งสามารถประกอบด้วย(สิ่งต่างๆ)หรือวงเล็บปีกกาเปิดตามด้วยรายการคำสั่ง (ซึ่งอาจรวมถึงหนึ่งคำสั่งหรือมากกว่า) ตามด้วยวงเล็บปีกกาปิด" IE " { }
บล็อกสามารถแทนที่คำสั่งใดก็ได้ทุกที่" รวมถึงตรงกลางของรหัส
การไม่อนุญาตให้{ }
บล็อกทุกที่ที่คำสั่งเดียวสามารถไปได้จะทำให้คำจำกัดความภาษาซับซ้อนขึ้น
เนื่องจาก C ++ (และ java) อนุญาตให้บล็อกโค้ดโดยไม่มีคำสั่งนำหน้า
C ++ อนุญาตเพราะ C ทำ
คุณสามารถพูดได้ว่าทั้งหมดมาจากข้อเท็จจริงที่ว่าการออกแบบภาษาโปรแกรมของสหรัฐอเมริกา (ตาม C) ได้รับรางวัลมากกว่าการออกแบบภาษาโปรแกรมยุโรป (ตามModula-2 )
(คำสั่งควบคุมทำหน้าที่ในคำสั่งเดียวคำสั่งสามารถเป็นกลุ่มเพื่อสร้างคำสั่งใหม่ได้)
// if (a == b)
// if (a != b)
{
// do something
}
1เพราะ ... มันคงไว้ซึ่งขอบเขตของคำสั่ง .. หรือฟังก์ชั่นนี้มีประโยชน์มากสำหรับแผงคอรหัสขนาดใหญ่ ..
{
{
// Here this 'i' is we can use for this scope only and out side of this scope we can't get this 'i' variable.
int i = 0;
}
{
int i = 0;
}
}
คุณถามว่า "ทำไม" C # อนุญาตให้บล็อกโค้ดโดยไม่ต้องมีข้อความนำหน้า คำถาม "ทำไม" ยังสามารถตีความได้ว่า "สิ่งที่เป็นไปได้ประโยชน์ของโครงสร้างนี้?"
โดยส่วนตัวแล้วฉันใช้บล็อกโค้ดแบบไม่มีคำสั่งใน C # ซึ่งความสามารถในการอ่านได้รับการปรับปรุงให้ดีขึ้นอย่างมากสำหรับนักพัฒนารายอื่นในขณะที่โปรดทราบว่าการบล็อกโค้ด จำกัด ขอบเขตของตัวแปรภายใน ตัวอย่างเช่นพิจารณาข้อมูลโค้ดต่อไปนี้ซึ่งอ่านได้ง่ายกว่ามากเนื่องจากบล็อกโค้ดเพิ่มเติม:
OrgUnit world = new OrgUnit() { Name = "World" };
{
OrgUnit europe = new OrgUnit() { Name = "Europe" };
world.SubUnits.Add(europe);
{
OrgUnit germany = new OrgUnit() { Name = "Germany" };
europe.SubUnits.Add(germany);
//...etc.
}
}
//...commit structure to DB here
ฉันทราบดีว่าสิ่งนี้สามารถแก้ไขได้อย่างหรูหรามากขึ้นโดยใช้วิธีการสำหรับโครงสร้างแต่ละระดับ แต่โปรดทราบอีกครั้งว่าสิ่งต่างๆเช่นตัวเพาะข้อมูลตัวอย่างมักจะต้องรวดเร็ว
ดังนั้นแม้ว่าโค้ดด้านบนจะดำเนินการแบบเชิงเส้น แต่โครงสร้างโค้ดจะแสดงถึงโครงสร้าง "โลกแห่งความจริง" ของอ็อบเจ็กต์ซึ่งทำให้นักพัฒนารายอื่นเข้าใจดูแลรักษาและขยายได้ง่ายขึ้น