การใช้คำหลัก var ใน C #


406

หลังจากสนทนากับเพื่อนร่วมงานเกี่ยวกับการใช้คำหลัก 'var' ใน C # 3 ฉันสงสัยว่าความคิดเห็นของผู้คนเกี่ยวกับการใช้การอนุมานประเภทที่เหมาะสมผ่านทาง var คืออะไร

เช่นฉันค่อนข้างใช้ var อย่างเกียจคร้านในสถานการณ์ที่น่าสงสัยเช่น: -

foreach(var item in someList) { // ... } // Type of 'item' not clear.
var something = someObject.SomeProperty; // Type of 'something' not clear.
var something = someMethod(); // Type of 'something' not clear.

การใช้ var ที่ถูกต้องมากขึ้นมีดังนี้: -

var l = new List<string>(); // Obvious what l will be.
var s = new SomeClass(); // Obvious what s will be.

LINQ ที่น่าสนใจน่าจะเป็นพื้นที่สีเทาเล็กน้อยเช่น: -

var results = from r in dataContext.SomeTable
              select r; // Not *entirely clear* what results will be here.

เห็นได้ชัดว่าผลลัพธ์จะเป็นอย่างไรซึ่งจะเป็นประเภทที่ใช้ IEnumerable แต่ก็ไม่ชัดเจนโดยสิ้นเชิงเช่นเดียวกับที่ var ประกาศวัตถุใหม่

มันยิ่งแย่ลงเมื่อพูดถึง LINQ กับวัตถุเช่น: -

var results = from item in someList
              where item != 3
              select item;

สิ่งนี้ไม่ดีไปกว่า foreach ที่เท่าเทียมกัน (รายการ var ใน someList) {// ... } equivilent

มีข้อกังวลอย่างแท้จริงเกี่ยวกับความปลอดภัยของประเภทที่นี่ - ตัวอย่างเช่นถ้าเราวางผลลัพธ์ของข้อความค้นหานั้นลงในวิธีที่มากเกินไปที่ยอมรับ IEnumerable <int> และ IEnumerable <double> ผู้โทรอาจส่งผ่านผิดประเภท

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


68
การใช้ var ใช้งานได้ดี แต่"ฉันไม่ต้องคิดออก"ดูเหมือนจะเป็นเหตุผลที่แย่มากที่จะใช้มัน ... คุณควรจะรู้ว่าประเภทนั้นคืออะไร var เป็นเพียงทางลัดเพื่อหลีกเลี่ยงการพิมพ์
โทมัส Levesque

53
var i = 0;== ล้มเหลว! var c = new CrazyFrigginLongClassName();== ชนะ!
dotjoe

6
"Var ยังทำให้ฉันนึกถึงประเภทของตัวแปร VB / VBA อีกทั้งยังมีที่อยู่ฉันจำได้ว่า (จากเมื่อหลายปีก่อน) การใช้งานเป็นประเภทที่ไม่เป็นที่ต้องการและค่อนข้างหิวทรัพยากร" <- แสดงว่านี่เป็นคำถามแบบ baiting เนื่องจากประเภท 'var' ของ C # ไม่มีส่วนเกี่ยวข้องกับประเภทตัวแปร VB / VBA
user7116

20
var readabilityBeDamned = true;
spoulson

9
ปัญหาของตัวอย่างทั้งหมดที่ระบุไว้ที่นี่คือเรากำลังดูโค้ดหนึ่งบรรทัด เมื่อฉันเห็นบรรทัดต่อบรรทัดของการประกาศ "var" หนึ่งรายการถัดจากนั้นประกาศออกมาจากมือ ความสามารถในการอ่านเป็นเรื่องส่วนตัว แต่ฉันพบว่าวาร์ถูกทำร้ายมากกว่าที่ใช้อย่างน่านับถือ
jro

คำตอบ:


293

ฉันยังคิดว่าvarสามารถสร้างโค้ดให้อ่านง่ายขึ้นในบางกรณี ถ้าฉันมีคลาสลูกค้าที่มีคุณสมบัติคำสั่งซื้อและฉันต้องการกำหนดให้กับตัวแปรฉันจะทำสิ่งนี้:

var orders = cust.Orders;

ฉันไม่สนใจถ้า Customer.Orders คือIEnumerable<Order>, ObservableCollection<Order>หรือBindingList<Order>- ทั้งหมดที่ฉันต้องการคือการเก็บรายชื่อในหน่วยความจำที่ย้ำมากกว่านั้นหรือได้รับการนับหรืออะไรของมันในภายหลัง

เปรียบเทียบกับการประกาศข้างต้นด้วย:

ObservableCollection<Order> orders = cust.Orders;

สำหรับฉันชื่อประเภทเป็นเพียงเสียงรบกวน และถ้าฉันย้อนกลับไปและตัดสินใจที่จะเปลี่ยนประเภทของลูกค้าสั่งให้ติดตาม (พูดจากObservableCollection<Order>เป็นIList<Order>) ฉันก็ต้องเปลี่ยนคำประกาศนั้นด้วย - บางอย่างที่ฉันไม่ต้องทำถ้าฉันใช้ var ในครั้งแรก สถานที่.


48
ฉันชอบมีชนิดที่ชัดเจนต่อหน้าฉันเมื่อฉันอ่านรหัส ฉันจะรู้ได้อย่างไรว่า "cust.Orders" อยู่ที่นี่โดยไม่มีประเภท? ใช่ฉันสามารถเลื่อนเม้าส์ไปหา แต่ทำไมฉันต้องทำ? :)
Jon Tackabury

77
แต่ประเด็นก็คือโดยทั่วไปแล้วมันไม่สำคัญ ให้ cust.Orders เป็นสิ่งที่คุณสามารถระบุ (เช่นบอกล่วงหน้า) แล้วมันไม่สำคัญว่ามันจะเป็นอะไร รหัสพิเศษที่เพิ่งได้รับในทางของการอ่านเจตนา
Matt Hamilton

67
แต่ถ้าคุณเพียงแค่ต้องการให้ cust.Orders เป็น "สิ่งที่คุณสามารถแจกแจงได้" ก็ไม่ได้ประกาศว่ามันเป็น <Order> IEnumerable ที่ทำให้ความต้องการนั้นชัดเจนและชัดเจน? การประกาศเป็น var หมายความว่าคุณสูญเสียข้อกำหนดนั้นอย่างมีประสิทธิภาพ
GrahamS

5
@ จอนและวิธีการสั่งซื้อ IEnumerbal = cust.Orders foreach (var order in orders) สร้างความแตกต่างอย่างไร สิ่งเดียวที่ IEnumerable กล่าวคือคุณสามารถใส่ไว้ใน foreach ได้ แต่คุณรู้แล้วว่าจากบรรทัดด้านล่าง
Rune FS

18
"สิ่งเดียวที่ IEnumerable กล่าวคือคุณสามารถใส่ไว้ในหน้า" - มันเป็นการแสดงออกถึงความตั้งใจที่สิ่งเดียวที่คุณสามารถทำได้คือการแจกแจง การใช้ var ช่วยให้เข้าถึงและ intellisense สำหรับสมาชิกสาธารณะของประเภทคอลเลกชันที่เป็นรูปธรรม
Joe

167

ฉันใช้varอย่างกว้างขวาง มีการวิพากษ์วิจารณ์ว่าสิ่งนี้ลดทอนความสามารถในการอ่านรหัส แต่ไม่มีข้อโต้แย้งใด ๆ ที่จะสนับสนุนข้อเรียกร้องดังกล่าว

เป็นที่ยอมรับว่าอาจหมายถึงไม่ชัดเจนว่าเรากำลังเผชิญกับประเภทใด แล้วอะไรล่ะ นี่คือจุดประสงค์ของการออกแบบที่แยกกัน เมื่อจัดการกับอินเตอร์เฟสคุณจะไม่สนใจตัวแปรชนิดที่มีอยู่ varนี้จะใช้เวลามากไปจริง แต่ผมคิดว่าการโต้แย้งยังคงเหมือนเดิมจากจุดอ่านของมุมมอง: โปรแกรมเมอร์ควรไม่จริงมีความสนใจในประเภทของตัวแปร แต่ในสิ่งที่ตัวแปรไม่ นี่คือเหตุผลที่ Microsoft เรียกใช้การอนุมานประเภท "การพิมพ์เป็ด"

ดังนั้นตัวแปรจะทำอย่างไรเมื่อฉันประกาศว่าใช้var? ง่ายๆมันทำทุกสิ่งที่ IntelliSense บอกให้ทำ เหตุผลเกี่ยวกับ C # ที่ละเว้น IDE นั้นขาดความเป็นจริง ในทางปฏิบัติรหัส C # ทุกโปรแกรมใน IDE ที่สนับสนุน IntelliSense

ถ้าฉันใช้varตัวแปรที่ประกาศและสับสนว่าตัวแปรนั้นมีไว้มีอะไรผิดปกติกับรหัสของฉัน varไม่ใช่สาเหตุมันทำให้อาการมองเห็นได้เท่านั้น อย่าโทษผู้ส่งสาร

ตอนนี้ทีมงาน C # ได้ออกแนวทางการเข้ารหัสที่ระบุว่าvarควรเพียง แต่นำมาใช้ในการจับภาพผลของคำสั่งที่สร้าง LINQ ชนิดที่ไม่ระบุชื่อ (เพราะที่นี่เราไม่มีทางเลือกที่แท้จริงในการvar) สกรูที่ ตราบใดที่ทีม C # ไม่ได้ให้เหตุผลที่ดีกับฉันสำหรับแนวทางนี้ฉันจะเพิกเฉยต่อเรื่องนี้เพราะในความเห็นของฉันเป็นมืออาชีพและเป็นส่วนตัวมันเป็นเรื่องไร้เหตุผล (ขออภัย; ฉันไม่มีลิงก์ไปยังแนวทางปฏิบัติที่เป็นปัญหา)

จริงๆแล้วมีคำอธิบายที่ดี (เผิน) บางอย่างเกี่ยวกับสาเหตุที่คุณไม่ควรใช้varแต่ฉันก็ยังเชื่อว่าพวกเขาผิดไปมาก นำตัวอย่างของ“ searchabililty”: ผู้เขียนอ้างว่าvarทำให้ยากต่อการค้นหาสถานที่ที่MyTypeมีการใช้งาน ขวา. อินเทอร์เฟซทำ จริงๆแล้วทำไมฉันถึงอยากรู้ว่าใช้คลาสที่ไหน ฉันอาจสนใจที่จะหาอินสแตนซ์และยังสามารถค้นหาได้เพราะมีตัวเรียกใช้งานจากที่ใดที่หนึ่ง (แม้ว่าจะทำในทางอ้อมต้องพิมพ์ชื่อประเภทที่อื่น)


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

6
ฉันเกลียดที่จะรับช่วงของแหล่งที่มา 100k โดยไม่มีเอกสารประกอบและการใช้ var แบบเสรี โดยเฉพาะอย่างยิ่งถ้าคุณรวม var กับชื่อตัวแปรที่มีประโยชน์น้อยกว่า ฉันเห็นว่ามันมีประโยชน์เมื่อแสดงจุด (หรือการจัดการกับประเภทที่ไม่ระบุชื่อ) แต่ในรหัสการผลิตหรือไม่
Shea

7
Arnshea: ดีที่คุณได้ชี้ให้เห็นแล้วว่าปัญหาที่แท้จริงมี: ไร้ประโยชน์ชื่อตัวแปรและที่ขาดหายไปเอกสาร ฉันล้มเหลวจริงๆที่จะเห็นสิ่งที่varก่อให้เกิดความสับสน แน่นอนว่าอาจมีบางกรณีที่จำเป็นต้องเน้นประเภท / ขนาดของตัวแปร (เช่นการทำงานบิตระดับต่ำ) ไม่เป็นไรไม่เคยมีใครอ้างว่าvarควรใช้เป็นพิเศษ กฎนั้นง่าย: ถ้ามันทำให้เกิดความสับสนอย่าใช้มัน
Konrad Rudolph

17
ทุกตัวอย่างตรงข้ามกับ var ที่ฉันเคยเห็นสมมติว่าโปรแกรมเมอร์จะใช้ชื่อตัวแปรที่ไม่มีความหมาย แต่นี่อาจเป็นสาเหตุว่า var ดีกว่าการระบุประเภทอย่างชัดเจน: มันบังคับให้โปรแกรมเมอร์เขียนชื่อตัวแปรที่ดี
ไรอันลุน

16
Microsoft ยังเรียกการอนุมานประเภท“ การพิมพ์เป็ด” - พวกเขาจริงเหรอ? ฉันจะตกใจ ...
แอนตัน Tykhyy

118

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

จากมุมมองของฉันการใช้หลักการตั้งชื่อที่ดีสำหรับตัวแปรและวิธีการมีความสำคัญมากกว่าจากมุมมองที่สามารถอ่านได้มากกว่าข้อมูลประเภทที่ชัดเจน หากฉันต้องการข้อมูลประเภทฉันสามารถวางเคอร์เซอร์ไว้เหนือตัวแปร (เป็น VS) และรับมันได้ อย่างไรก็ตามโดยทั่วไปแล้วข้อมูลประเภทที่ชัดเจนไม่จำเป็นต้องใช้กับผู้อ่าน สำหรับนักพัฒนาใน VS คุณยังคงได้รับ Intellisense ไม่ว่าจะมีการประกาศตัวแปรอย่างไร ต้องบอกว่าทั้งหมดอาจยังมีบางกรณีที่เหมาะสมที่จะประกาศประเภท - บางทีคุณอาจมีวิธีที่ส่งกลับค่า a List<T>แต่คุณต้องการปฏิบัติต่อมันในฐานะIEnumerable<T>ในวิธีการของคุณ เพื่อให้แน่ใจว่าคุณกำลังใช้อินเตอร์เฟสการประกาศตัวแปรของชนิดอินเตอร์เฟสสามารถทำให้สิ่งนี้ชัดเจน หรือบางทีคุณต้องการประกาศตัวแปรที่ไม่มีค่าเริ่มต้นเพราะมันจะได้รับค่าตามเงื่อนไขบางอย่างทันที ในกรณีที่คุณต้องการประเภท หากข้อมูลประเภทมีประโยชน์หรือจำเป็นให้ไปข้างหน้าและใช้งาน แต่ฉันรู้สึกว่าโดยทั่วไปแล้วมันไม่จำเป็นและรหัสนั้นอ่านง่ายกว่าถ้าไม่มีในกรณีส่วนใหญ่


3
ฉันเห็นด้วยโดยรวม จุดสำคัญในความคิดของฉันคือเพื่อให้แน่ใจว่าเจตนาชัดเจน หากไม่ชัดเจนสำหรับนักพัฒนาส่วนใหญ่ในทีมแสดงว่าเป็นอันตรายไม่เป็นประโยชน์ ที่กล่าวว่าฉันเป็นแฟนตัวยงของเรื่องนี้ แต่ต้องกลับมามีส่วนร่วมเล็กน้อยเมื่อ devs อื่น ๆ ในทีมของฉันมีปัญหาในการระบุเจตนาของฉัน ไปคิด
Steve Brouillard

3
เอ๊ะฉันอ่านง่ายกว่าตอนที่อยู่ทางซ้าย เมื่อใช้ ReSharper ฉันไม่ต้องพิมพ์อีกครั้งทางด้านขวา แต่อย่างใดมันจึงไม่รบกวนฉัน
BlueRaja - Danny Pflughoeft

1
@ BlueLaja - ฉันพบว่าการใช้ชื่อตัวแปรที่ดีมักจะไม่จำเป็นต้องกังวลกับประเภทที่แท้จริงอยู่แล้วเพื่อความเข้าใจ Intellisense ยังคงมีอยู่ในตัวแปรที่กำหนด "var" ดังนั้นฉันไม่จำเป็นต้องรู้ประเภทในการเลือกวิธีการ / คุณสมบัติเมื่อทำการเข้ารหัส
tvanfosson

2
มันไม่ได้เกี่ยวกับตอนที่คุณเขียนโค้ดเหมือนตอนที่คุณต้องอ่านรหัส
BlueRaja - Danny Pflughoeft

1
ฉันจะต้องอยู่ด้านหนาแล้วฉันต้องวิธีการที่ดีและชื่อตัวแปรและความเข้าใจในประเภทการดำเนินการเพื่อให้สามารถเข้าใจรหัสที่ฉันอ่านได้อย่างถูกต้อง ฉันคิดว่าคุณพูดถูกแม้ว่ามันจะเป็นอาการของปัญหาที่ใหญ่กว่า หนึ่งในความไว้วางใจ เพื่อให้แน่ใจว่ารหัสกำลังทำสิ่งที่ดูเหมือนจะเป็นการทำคุณจะต้องแน่ใจว่าประเภทที่ใช้
AnthonyWJones

91

ไม่มีสิ่งใดที่เป็นจริงอย่างแน่นอน varสามารถมีทั้งผลบวกและลบที่มีต่อการอ่านได้ ในความเห็นของฉันvarควรใช้เมื่อสิ่งใดสิ่งหนึ่งต่อไปนี้เป็นจริง:

  1. ประเภทเป็นแบบไม่ระบุชื่อ (คุณไม่มีตัวเลือกใด ๆ ที่นี่เนื่องจากต้องเป็น var ในกรณีนี้)
  2. ประเภทจะชัดเจนตามนิพจน์ที่กำหนด (เช่นvar foo = new TypeWithAReallyLongNameTheresNoSenseRepeating())

varไม่มีผลกระทบต่อประสิทธิภาพเนื่องจากน้ำตาลทรายเป็นประโยค คอมไพเลอร์ infers ประเภทและกำหนดเมื่อมันรวบรวมเป็น IL; ไม่มีอะไรเปลี่ยนแปลงได้จริงเกี่ยวกับเรื่องนี้


1
เห็นด้วยกับทั้งสอง แต่ผมมีข้อ จำกัด นานกว่ากรณีที่สองถ้าเป็นชนิดที่เป็นมานานแล้วว่ามันมักจะเป็นประเภททั่วไปที่มีจำนวนมากของการขัดแย้งทั่วไปที่ซ้อนกันในกรณีที่พิมพ์ขอ "ShortType เทียบเท่ากับ TypeWithAReallyLongNameTheresNoSenseRepeating" ทำให้รู้สึกมากขึ้น
ไอออน Todirel

12
ฉันไม่มีความปรารถนาที่จะเริ่มสงครามศาสนา แต่ฉันเองก็มักจะไม่เห็นด้วยกับไอออน ฉันต้องการชื่อประเภทที่ยาวมาก แต่แม่นยำมาก (ala Uncle Bob Martin) มากกว่าชื่อที่สั้นและคลุมเครือ ฉันจะเพิ่มข้อแม้ที่ฉันไม่เห็นด้วยกับการเพิ่มความยาวของชื่อด้วย หากตัวละคร 5 ตัวสร้างชื่อรัดกุมที่แสดงเจตนาชัดเจนให้ใช้ 5 และไม่ใช่ 25
Steve Brouillard

2
@ Steve: ฉันต้องเห็นด้วยกับคุณ; การสร้าง "short type" (ซึ่งฉันถือว่าคุณหมายถึงการสืบทอดจากประเภทสามัญที่เฉพาะเจาะจงเพียงเพื่อจุดประสงค์ในการทำให้ชื่อสั้นลง) ไม่ใช่วิธีปฏิบัติที่ดี มันจะต้องให้คุณทำซ้ำและส่งผ่านตัวสร้างใด ๆ จากประเภททั่วไปเช่นเดียวกับการป้องกันไม่ให้คุณผ่านประเภทที่แตกต่างกันที่สืบทอดจากประเภททั่วไปไปยังฟังก์ชั่น คุณกำลังใช้มรดกเหมือนtypedefเมื่อไม่ได้
Adam Robinson

7
ใช้varเมื่อชนิดชัดเจนหรือไม่ บางที แต่กำไรที่แท้จริงคือเมื่อประเภทไม่สำคัญ หากคุณกำลังทำสิ่งต่าง ๆvar customers = whatever; var query = from c in customers select stuffมันไม่สำคัญว่า 'ลูกค้า' คือประเภทใด เห็นได้ชัดว่าคุณสามารถใช้มันอย่างไรและก็เพียงพอแล้ว และถ้าประเภทที่แท้จริงนั้นยุ่งยากก็คุ้มค่าที่จะปราบปรามมัน
Joren

2
@Kristoffer: ฉันสามารถเข้าใจความต้องการที่จะกำจัดความยุ่งเหยิงของแท็ก แต่การตัดพวกเขาลงในชั้นเรียนไม่ใช่ทางเลือกที่ยอมรับได้ (IMO) ในขณะที่คุณตัดความเป็นไปได้ของชั้นเด็กประเภทอื่น ๆ พารามิเตอร์ที่ถูกต้อง ฉันอยากจะใช้using ShortType = LongGenericType<A,B,C>คำสั่งที่ด้านบนของไฟล์เนื่องจากมันให้การอ่านที่เหมือนกันไม่ต้องการให้คุณสร้างนวกรรมิกขึ้นใหม่และไม่กำจัดคลาสเด็กออกจากการเป็นผู้สมัคร
อดัมโรบินสัน

68

จาก Eric Lippert วิศวกรออกแบบซอฟต์แวร์อาวุโสในทีม C #:

ทำไมvarคำหลักถูกนำมาใช้?

มีสองเหตุผลหนึ่งที่มีอยู่ในปัจจุบันซึ่งจะปลูกใน 3.0

เหตุผลแรกคือรหัสนี้น่าเกลียดอย่างไม่น่าเชื่อเพราะความซ้ำซ้อนทั้งหมด:

Dictionary<string, List<int>> mylists = new Dictionary<string, List<int>>();

และนั่นคือตัวอย่างง่ายๆ - ฉันเขียนแย่กว่านี้ ทุกครั้งที่คุณถูกบังคับให้พิมพ์สิ่งเดียวกันซ้ำสองครั้งนั่นคือความซ้ำซ้อนที่เราสามารถนำออกได้ ดีกว่าที่จะเขียน

var mylists = new Dictionary<string,List<int>>();

และให้คอมไพเลอร์เข้าใจว่าประเภทนั้นเป็นไปตามการกำหนด

ประการที่สอง C # 3.0 แนะนำประเภทที่ไม่ระบุชื่อ ตั้งแต่ประเภทที่ไม่ระบุชื่อโดยความหมายไม่มีชื่อคุณต้องการที่จะสามารถสรุปประเภทของตัวแปรจากการแสดงออกของการเริ่มต้นถ้าเป็นชนิดที่ไม่ระบุชื่อ

เน้นการขุด บทความทั้งหมดC # 3.0 ยังคงพิมพ์แบบคงที่ซื่อสัตย์! และซีรีย์ต่อมาก็ค่อนข้างดี

นี่คือสิ่งที่varมีไว้เพื่อ การใช้งานอื่น ๆ อาจไม่ทำงานได้ดีนัก การเปรียบเทียบใด ๆ กับ JScript, VBScript หรือการพิมพ์แบบไดนามิกคือสองชั้นรวม หมายเหตุอีกครั้งvarถูกต้องเพื่อให้มีคุณสมบัติอื่น ๆ บางอย่างในการทำงานใน .NET


ฉันพบข้อโต้แย้งของ Lippert ไม่มีใครพิมพ์ชื่อชั้นที่สองพวกเขาปล่อยให้ Intellisense เขียนมันสำหรับพวกเขา แต่แล้วเขาก็หันหลังกลับและอ้างว่า var นั้นดีกว่าเพราะคอมไพเลอร์ / Intellisense ทำงานได้ คุณมีทั้งสองวิธีไม่ได้!
เดฟ

5
ทีม C # ไม่ได้ควบคุมระบบภายในพวกเขาควบคุมคอมไพเลอร์ ไม่ว่าในกรณีใด ๆ ที่ไม่ใช่ปัญหาหลัก ฉันไม่คิดว่า var จะทำ 100 คะแนนในการบันทึกการพิมพ์เพียงอย่างเดียว
Dustman

@Dustman: var ไม่ได้บันทึกการพิมพ์เลย มันทำให้คุณเขียนมากขึ้น!
Piotr Perak

53

ฉันคิดว่าการใช้ var ควรควบคู่กับชื่อตัวแปรที่ถูกเลือกอย่างชาญฉลาด

ฉันไม่มีปัญหาในการใช้ var ในคำสั่ง foreach หากไม่เป็นเช่นนี้:

foreach (var c in list) { ... }

ถ้ามันเป็นแบบนี้:

foreach (var customer in list) { ... }

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

เช่นเดียวกับสถานการณ์อื่น ๆ นี่คือไร้ประโยชน์สวย:

var x = SaveFoo(foo);

... แต่นี่สมเหตุสมผล:

var saveSucceeded = SaveFoo(foo);

ฉันเดาว่าแต่ละคน ฉันพบว่าตัวเองกำลังทำสิ่งนี้ซึ่งบ้าไปแล้ว:

var f = (float)3;

ฉันต้องการโปรแกรม var 12 ขั้นตอนบางประเภท ฉันชื่อแมตต์และฉัน (ab) ใช้ var


6
ผิดพลาดเพียงอย่างเดียวกับ "var f = (float) 3;" ก็คือมันควรจะเป็น "var f = 3f" หรือ "var f = 3.0 (สาเหตุความแม่นยำเดียว sucks)"
MichaelGG

3
Heh yeah 3f หรือ 3.0 เป็นวิธีที่จะไป! Maniacs var เราต้องติดกัน!
Matt Hamilton

27
ปัญหาที่แท้จริงในตัวอย่างแรกนั้นคือ "list" ไม่ใช่ "c" "รายการ" ของสิ่งที่ ? "รายการ" ควรเปลี่ยนชื่อเป็น "ลูกค้า" หรือ "customersWhoOweMoney" หรือ "ลูกค้าปัจจุบัน" หรืออะไรที่สื่อความหมายได้มากกว่า และเมื่อคุณมีสิ่งนั้นแล้ว "c" ก็ยังคงอยู่เหมือนเดิมเพราะคุณรู้แล้วว่ามันจะมีอะไรบ้าง
Ryan Lundy

4
สวัสดี Matt! ชื่อของฉันคือ Kenny และฉันเป็น varaddict
kenny

var MattHamil = "Luke Skywalker"; // ถอดมันออกเป็นตัน
Binoj Antony

40

เราได้นำเอา "รหัสสำหรับคนไม่ใช่เครื่องจักร" มาใช้บนพื้นฐานของสมมติฐานที่ว่าคุณใช้เวลาในการบำรุงรักษานานกว่าการพัฒนาใหม่

สำหรับฉันนั่นเป็นข้อโต้แย้งว่าคอมไพเลอร์ "รู้" ว่าตัวแปรคืออะไร - แน่นอนคุณไม่สามารถเขียนรหัสที่ไม่ถูกต้องในครั้งแรกเพราะคอมไพเลอร์หยุดโค้ดของคุณจากการรวบรวม แต่เมื่อนักพัฒนาต่อไปกำลังอ่านรหัส ในเวลา 6 เดือนพวกเขาต้องสามารถสรุปสิ่งที่ตัวแปรทำอย่างถูกต้องหรือไม่ถูกต้องและระบุสาเหตุของปัญหาได้อย่างรวดเร็ว

ดังนั้น,

var something = SomeMethod();

นั้นผิดกฎหมายตามมาตรฐานการเข้ารหัสของเรา แต่ได้รับการสนับสนุนจากทีมงานของเราดังต่อไปนี้เพราะมันเพิ่มความสามารถในการอ่าน:

var list = new List<KeyValuePair<string, double>>();
FillList( list );
foreach( var item in list ) {
   DoWork( item ); 
}

4
ฉันพบว่า ("รหัสสำหรับผู้คนไม่ใช่เครื่อง") เป็นแนวทางที่ยอดเยี่ยม - การทำตามอาจทำให้โค้ดดีขึ้นและช่วยหลีกเลี่ยงการเพิ่มประสิทธิภาพก่อนวัยอันควร
Thanatos

3
ฉันไม่ได้รับรายการ var = new KeyValuePair <string, double>? สำหรับฉันรายการสามารถมีมากกว่าในสิ่ง
TTT

"รหัสสำหรับคนไม่ใช่เครื่อง" - สาธุ
user1068352

39

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

อีกกรณีที่น่ากังวลในการโทรต่อไปนี้คุณไม่สามารถบอกได้เพียงแค่ดูรหัสประเภทที่ส่งคืนโดยCallMe:

var variable = CallMe();

นั่นคือหลักของฉันบ่นกับ var

ผมใช้ var เมื่อฉันประกาศผู้ได้รับมอบหมายที่ไม่ระบุชื่อในวิธีการอย่างใด var Funcดูสะอาดกว่าถ้าฉันต้องการใช้ พิจารณารหัสนี้:

var callback = new Func<IntPtr, bool>(delegate(IntPtr hWnd) {
   ...
});

แก้ไข : อัปเดตตัวอย่างโค้ดล่าสุดตามการป้อนข้อมูลของ Julian


3
แต่คุณจำเป็นต้องรู้ประเภทที่นั่นตรงนั้นหรือไม่? คุณรู้ว่า CallMe คืนอะไรบางอย่าง ยังไม่พอที่จะรู้ว่ามีการสร้างตัวแปรท้องถิ่นที่ชื่อว่าvariable? ถ้าคุณไม่ขยายตัวอย่างของคุณนี่ไม่ใช่ข้อร้องเรียนที่มั่นคงมาก IMO
Randolpho

2
มันไม่เกี่ยวกับการไม่ได้ verbose มันเกี่ยวกับการไม่ให้คอมไพเลอร์ทำไวยากรณ์น้ำตาลให้คุณ พิจารณาสิ่งนี้: var getter ... ตอนนี้Func <object> getter ... ด้วยวินาทีที่คุณรู้ว่าคุณไม่จำเป็นต้องระบุพารามิเตอร์ใด ๆ คุณรู้ตั้งแต่เริ่มต้นว่า "ต้องทำอะไร" และสามารถตัดสินใจได้เร็วขึ้นเมื่อออกแบบบางอย่างหรือปรับโครงสร้างใหม่ การมีข้อมูลทั้งหมดในมือมีความสำคัญมากกว่าตัวละครอีกสองสามตัว สิ่งนี้สามารถชื่นชมได้เมื่อคุณทำงานกับโค้ดจำนวนมาก
Ion Todirel

2
เนื่องจากเราทุกคนกำลังพูดถึง visual studio อยู่แล้วเรื่องใหญ่อะไรเกี่ยวกับการวางตัวชี้เมาส์ไว้เหนือตัวแปรสำหรับวินาทีและแค่เห็นว่ามันคืออะไร? ดีกว่าวิ่งไปที่การประกาศต่อไป
บี้

3
ตัวแปรทั่วไปและชื่อฟังก์ชัน ( variable, CallMe) สร้างตัวอย่างที่ไม่ดี อย่างไรก็ตามหากCallMe()เป็นฟังก์ชั่นใน "แอปพลิเคชั่นโทรศัพท์" บางประเภทแล้วvar call = CallMe(); .... call.HangUp();จะทำให้รู้สึกมากกว่า
Danko Durbić

3
@ Randolpho: "เรื่องใหญ่เกี่ยวกับการวางตัวชี้เมาส์ไว้เหนือตัวแปรสำหรับวินาทีและเพิ่งเห็นมันเป็นประเภทอะไร?" มันเพิ่มเวลาในการบำรุงรักษา ... บวกหนึ่งวินาทีเป็นเพียงเวลาโฮเวอร์แทนที่จะนับแป้นพิมพ์เป็นสวิตช์บริบทของเมาส์ ฉันไม่รู้เกี่ยวกับคุณ แต่ฉันทำงานกับกำหนดเวลา ทุกครั้งที่ฉันต้องวางเมาส์เหนือตัวแปรเพื่อค้นหาว่ามันคือประเภทใดเวลาที่ฉันสามารถใช้แก้ไขปัญหาได้ดีขึ้น
Powerlord

36

Var ไม่เหมือนตัวแปรเลย ตัวแปรยังคงพิมพ์อยู่อย่างแรงเพียงคุณไม่ต้องกดปุ่มเพื่อให้มันเป็นเช่นนั้น คุณสามารถโฮเวอร์เหนือมันใน Visual Studio เพื่อดูประเภท หากคุณกำลังอ่านโค้ดที่พิมพ์เป็นไปได้ว่าคุณอาจจะต้องคิดให้ดีก่อนว่าประเภทนี้คืออะไร แต่มีเพียงบรรทัดเดียวที่ประกาศไว้และอีกหลายบรรทัดที่ใช้ดังนั้นการให้ชื่อที่เหมาะสมยังคงเป็นวิธีที่ดีที่สุดในการทำให้โค้ดของคุณง่ายต่อการติดตาม

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


6
1 เพียงคนที่จะทราบว่ามีอะไรจะทำอย่างไรกับvar Variant
user7116

27

เวลาที่น่าจะเป็นไปได้มากที่สุดสำหรับประเภทที่ไม่ระบุตัวตน (ซึ่งจำเป็นต้องใช้ 100%); แต่มันก็หลีกเลี่ยงการทำซ้ำสำหรับคดีเล็ก ๆ น้อย ๆ และ IMO จะทำให้เส้นชัดเจนขึ้น ฉันไม่ต้องการเห็นประเภทสองครั้งสำหรับการเริ่มต้นอย่างง่าย

ตัวอย่างเช่น:

Dictionary<string, List<SomeComplexType<int>>> data = new Dictionary<string, List<SomeComplexType<int>>>();

(โปรดอย่าแก้ไข hscroll ในข้างต้น - มันค่อนข้างพิสูจน์จุด !!!)

VS:

var data = new Dictionary<string, List<SomeComplexType<int>>>();

อย่างไรก็ตามมีบางครั้งที่สิ่งนี้ทำให้เข้าใจผิดและอาจทำให้เกิดข้อบกพร่อง ใช้ความระมัดระวังvarหากตัวแปรดั้งเดิมและชนิดเริ่มต้นไม่เหมือนกัน ตัวอย่างเช่น:

static void DoSomething(IFoo foo) {Console.WriteLine("working happily") }
static void DoSomething(Foo foo) {Console.WriteLine("formatting hard disk...");}

// this working code...
IFoo oldCode = new Foo();
DoSomething(oldCode);
// ...is **very** different to this code
var newCode = new Foo();
DoSomething(newCode);

1
(สำหรับข้อมูลที่คุณจะได้รับปัญหาที่คล้ายกันในสิ่งที่นี้เป็นแปลงชนิดนัย)
Marc Gravell

1
ไม่เห็นด้วยกับส่วนที่คุณไม่ต้องการเห็นสองครั้งในบรรทัดเดียวกัน เป็นไปได้ว่าในอนาคตคุณไม่ได้สร้างตัวแปรโดยตรงหลังจากประกาศ (ตัวอย่างเช่นถ้าด้านล่างคำจำกัดความ) กว่าที่อาจไม่ชัดเจนว่าประเภทคืออะไร นักพัฒนาส่วนใหญ่จะใช้เพื่อดูประเภทโดยตรงที่จุดเริ่มต้นของบรรทัดโดยเฉพาะอย่างยิ่งในรหัสที่ซับซ้อนที่คุณไม่ต้องการให้อ่านรหัสยาก
Gertjan

@TheVillageIdiot - ฉันย้อนกลับการแก้ไขของคุณเพราะในครั้งนี้ hscroll ที่เกี่ยวข้องกับ ;-P จุด
Marc Gravell

2
@Gertjan - สมองของฉันถูก จำกัด ถ้ามันซับซ้อนฉันไม่ต้องการเห็นมันสองครั้งและต้องเริ่มเปรียบเทียบ (interface / concrete / etc) ฉันดีใจที่ได้เห็นครั้งเดียวและคิดว่า "พิมพ์เป็นหนึ่งในนั้น"
Marc Gravell

17

กรณีเฉพาะหนึ่งกรณีที่ var ยาก: การตรวจสอบโค้ดออฟไลน์โดยเฉพาะกรณีที่ทำบนกระดาษ

คุณไม่สามารถพึ่งพาเม้าส์ได้


17
ทำไมรหัสคุณถึงได้มีการทบทวนบนกระดาษ? คิดว่าต้นไม้! ;)
Dustman

8
คุณสามารถมีปัญหาเดียวกันโดยไม่ต้องใช้ var ปัญหาไม่ได้หลากหลาย ปัญหาคือชื่อตัวแปรที่ไม่ดี หากชื่อตัวแปรได้รับการคัดสรรมาเป็นอย่างดีการใช้ var นั้นไม่สำคัญ
Ryan Lundy

ฉันมีผู้ชายในทีมของฉันที่ตรวจสอบรหัสของตัวเองและค้นหาข้อบกพร่องด้วยการพิมพ์รหัสของเขา กำแพงของเขาเต็มไปด้วยรหัส ฉันเคยเข้ามาและเขามีกระดานไวท์บอร์ดขนาดใหญ่ปกคลุมไปด้วยแบบฝึกหัดการแก้จุดบกพร่อง น่าจะเป็น ~ 10,000 LOC
ปี๊บปี๊บ

ชื่อตัวแปรเพียงอย่างเดียวไม่สามารถแก้ปัญหาได้เว้นแต่คุณจะกลับไปที่รูปแบบฮังการีซึ่งประเภทนั้นเป็นส่วนหนึ่งของชื่อ
Kevin Gale

17

ฉันไม่เห็นสิ่งที่เป็นเรื่องใหญ่ ..

var something = someMethod(); // Type of 'something' not clear <-- not to the compiler!

คุณยังมีระบบ Intellisense เต็มรูปแบบสำหรับบางสิ่งและในกรณีที่คลุมเครือคุณต้องทำการทดสอบหน่วยใช่ไหม (คุณ?)

มันไม่ใช่ varchar มันไม่สลัวและแน่นอนว่าไม่ใช่การพิมพ์แบบไดนามิกหรือแบบอ่อนแอ มันหยุด maddnes เช่นนี้:

List<somethinglongtypename> v = new List<somethinglongtypename>();

และลดความคิดรวมทั้งหมดให้เป็น:

var v = new List<somethinglongtypename>();

นิสัยดีไม่ดีเท่า:

v = List<somethinglongtypename>();

แต่นั่นก็เป็นสิ่งที่Booใช้


ประเภทของ 'บางสิ่งบางอย่าง' มีความชัดเจนมากกับคอมไพเลอร์ภายใน "var" ได้รับการตั้งค่าเป็นประเภทส่งคืนของ 'someMethod' มันชัดเจนกับคอมไพเลอร์ แต่อาจไม่ชัดเจนสำหรับนักพัฒนาที่ทำงานในโครงการ และบูก็เติบโตขึ้นอย่างรวดเร็ว
stephenbayer

ไม่v = List<somethinglongtypename>();ไม่ได้ดีกว่า สิ่งสำคัญคือต้องแยกความแตกต่างระหว่างการแนะนำตัวแปรใหม่และการกำหนดให้กับตัวแปรที่มีอยู่
HighCommander4

ถ้าคุณได้กำหนดให้ 'v' มาก่อนในขอบเขตปัจจุบันการกำหนดให้กับที่มีอยู่ มิฉะนั้นจะเป็นการกำหนดให้ตัวแปรใหม่ 'v' ง่าย.
Frep D-Oronge

17

หากใครบางคนกำลังใช้varคำหลักเพราะพวกเขาไม่ต้องการที่จะ "คิดออกประเภท" นั่นคือเหตุผลที่ผิดแน่นอน varคำหลักไม่ได้สร้างตัวแปรที่มีประเภทแบบไดนามิกคอมไพเลอร์ยังคงมีการทราบชนิด เนื่องจากตัวแปรมีประเภทเฉพาะเสมอประเภทจึงควรปรากฏในรหัสหากเป็นไปได้

เหตุผลที่ดีในการใช้varคำหลักเป็นตัวอย่าง:

  • ในกรณีที่จำเป็นต้องใช้เช่นประกาศข้อมูลอ้างอิงสำหรับประเภทที่ไม่ระบุตัวตน
  • ที่ซึ่งทำให้โค้ดอ่านง่ายขึ้นเช่นลบการประกาศซ้ำ

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


11

เมื่อพิจารณาว่า Intellisense มีประสิทธิภาพมากแค่ไหนฉันไม่แน่ใจว่า var อ่านยากกว่าการมีตัวแปรสมาชิกในคลาสหรือตัวแปรโลคอลในวิธีที่กำหนดไว้นอกพื้นที่หน้าจอที่มองเห็นได้

หากคุณมีบรรทัดของรหัสเช่น

IDictionary<BigClassName, SomeOtherBigClassName> nameDictionary = new Dictionary<BigClassName, SomeOtherBigClassName>();

อ่านง่ายกว่าหรือยากกว่า:

var nameDictionary = new Dictionary<BigClassName, SomeOtherBigClassName>();

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

นั่นคือโดยทั่วไปเหตุผลเดียวที่พวกเขาดำเนินการมัน (นอกเหนือจากความสามารถในการประกาศประเภทที่ไม่ระบุชื่อ แต่พวกเขาจะได้ทำ "var" คำหลักที่พิเศษที่เป็นเพียงชนิดที่ไม่ระบุชื่อ.)
MQP

10

ฉันคิดว่าสิ่งสำคัญกับ VAR นั้นจะใช้เฉพาะเมื่อเหมาะสมเช่นเมื่อทำสิ่งต่าง ๆ ใน Linq ที่อำนวยความสะดวก (และอาจเป็นในกรณีอื่น ๆ )

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

การแบนผ้าห่มนั้นไม่ดีเท่ากับการใช้โครงสร้างในตอนแรก แต่ก็ไม่จำเป็นต้องมีมาตรฐานการเข้ารหัสที่สมเหตุสมผล

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

ฉันสงสัยว่าอันนี้กำลังจะวิ่งและวิ่ง (-:

Murph


10

แน่นอนว่า intง่าย แต่เมื่อชนิดของตัวแปรเป็นIEnumerable<MyStupidLongNamedGenericClass<int, string>> var จะทำให้สิ่งต่าง ๆ ง่ายขึ้นมาก


2
+1 สำหรับสิ่งนี้ intเมื่อเทียบกับvarสิ่งที่จะทะเลาะกัน แต่ประเภททั่วไปหลายซ้อนกันทำให้varสวรรค์ นี่คือที่ใช้ชื่อประเภทซ้ำแล้วซ้ำอีกจริงๆทำลายความสามารถในการอ่านของรหัส
Chris Farmer

นี่เป็นเหตุผลที่ผิดอย่างยิ่งสำหรับการใช้งาน หากรหัสของคุณใช้ประเภทสามัญที่ซ้อนกันคุณควรได้รับคลาสที่มีชื่อเฉพาะ ตัวอย่างเช่น: class IntStringEnumerator : IEnumerable<MyStupidLongNamedGenericClass<int, string>>จากนั้นใช้ชื่อใหม่ เป็นการทำความสะอาดโค้ดและอธิบายชนิดที่ดีกว่า
xxbbcc

เอาล่ะ แต่ตัวอย่างของฉันเป็นแค่อติพจน์ IntStringEnumerator i = new IntStringEnumerator()ยังพิมพ์มากเกินไป
Blorgbeard ออก

9

ถูกขโมยจากการโพสต์ในปัญหานี้ที่ CodingHorror :


น่าเสียดายที่คุณและคนอื่น ๆ เข้าใจผิด ในขณะที่ฉันเห็นด้วยกับคุณว่าการซ้ำซ้อนไม่ใช่สิ่งที่ดีวิธีที่ดีกว่าในการแก้ปัญหานี้คือการทำสิ่งต่อไปนี้:

MyObject m = new ();

หรือถ้าคุณผ่านพารามิเตอร์:

คน p = new ("FirstName", "LastName);

โดยที่ในการสร้างวัตถุใหม่คอมไพเลอร์จะแทรกซึมประเภทจากด้านซ้ายมือไม่ใช่ที่เหมาะสม นี่มีข้อดีอื่น ๆ มากกว่า "var" ซึ่งสามารถใช้ในการประกาศฟิลด์ได้เช่นกัน (นอกจากนี้ยังมีพื้นที่อื่น ๆ ที่อาจเป็นประโยชน์เช่นกัน แต่ฉันจะไม่เข้าไปที่นี่)

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

Nicholas Paldino. NET / C # MVP เมื่อวันที่ 20 มิถุนายน 2551 เวลา 08:00 น


ฉันเดาว่าข้อกังวลหลักของคุณคือต้องพิมพ์ให้น้อยลง - ไม่มีข้อโต้แย้งใด ๆ ที่จะทำให้คุณไม่สามารถใช้งานได้

หากคุณกำลังเพียงจะเคยเป็นคนที่มีลักษณะที่รหัสของคุณแล้วที่ใส่ใจ? มิฉะนั้นในกรณีเช่นนี้:

var people = Managers.People

ไม่เป็นไร แต่ในกรณีเช่นนี้:

var fc = Factory.Run();

มันลัดวงจรการลดประเภทใด ๆ ในทันทีที่สมองของฉันสามารถเริ่มสร้างจาก 'ภาษาอังกฤษ' ของรหัส

มิฉะนั้นเพียงใช้วิจารณญาณที่ดีที่สุดและเขียนโปรแกรม 'มารยาท' ต่อผู้อื่นที่อาจต้องทำงานในโครงการของคุณ


4
ตัวอย่างของคุณด้านบนไม่ใช่ข้อโต้แย้งสำหรับการไม่ใช้ var; พวกเขาเป็นอาร์กิวเมนต์สำหรับการใช้ชื่อตัวแปรอธิบายที่ดี หากแทนที่จะ [var fc = Factory.Run ();] คุณมี [bool fc = Factory.Run ();] รหัสจะไม่กลายเป็นชัดเจนขึ้น
ไรอันลุน

9

การใช้varแทนประเภทที่ชัดเจนทำให้การปรับโครงสร้างทำได้ง่ายขึ้นมาก (ดังนั้นฉันต้องโต้แย้งผู้โพสต์ก่อนหน้านี้ซึ่งหมายความว่ามันไม่ได้สร้างความแตกต่างหรือเป็น

คุณสามารถเปลี่ยนประเภทการคืนสินค้าของวิธีการของคุณโดยไม่ต้องเปลี่ยนทุกไฟล์ที่เรียกวิธีนี้ จินตนาการ

...
List<MyClass> SomeMethod() { ... }
...

ซึ่งใช้เหมือน

...
IList<MyClass> list = obj.SomeMethod();
foreach (MyClass c in list)
  System.Console.WriteLine(c.ToString());
...

หากคุณต้องการ refactor SomeMethod()เพื่อส่งคืนIEnumerable<MySecondClass>คุณจะต้องเปลี่ยนการประกาศตัวแปร (เช่นภายในforeach ) ในทุกสถานที่ที่คุณใช้วิธีการ

ถ้าคุณเขียน

...
var list = obj.SomeMethod();
foreach (var element in list)
  System.Console.WriteLine(element.ToString());
...

คุณไม่จำเป็นต้องเปลี่ยนแทน


เห็นด้วย - สงสัยว่าทำไมผลข้างเคียงที่ดีนี้ไม่ได้ถูกขนานนามให้มากไปกว่าผู้เชี่ยวชาญด้านอื่น ๆ
fieldingmellish

มันเกิดขึ้นกับฉันวันนี้ ฉันมีคลาสโรงงานที่ส่งคืน istance ของคลาส MainMenu วันนี้ฉันสร้าง MainMenu2 ด้วยอินเตอร์เฟสเดียวกันของ MainMenu ฉันมีรหัสแอพทั้งหมดของฉันแตะต้องหลังจากการเปลี่ยนแปลง!
Marco Staffoli

8

@aku: ตัวอย่างหนึ่งคือความคิดเห็นรหัส อีกตัวอย่างหนึ่งคือการจำลองสถานการณ์จำลองอีกครั้ง

โดยทั่วไปฉันไม่ต้องการออกไปล่าสัตว์ด้วยเมาส์ มันอาจไม่สามารถใช้ได้


2
เป็นเรื่องที่น่าสนใจที่คุณพูดว่าเพราะ var สามารถทำให้การปรับโครงสร้างทำได้ง่ายขึ้น หากคุณเคยใช้ var คุณไม่จำเป็นต้องทำ ตอนนี้คุณสามารถพึ่งพาเครื่องมือ refactoring IDE ที่ แต่คุณรู้ว่าคุณสามารถพึ่งพา IDE สำหรับประเภทเช่นกัน :)
เฟร็ด

8

มันเป็นเรื่องของรสนิยม ความยุ่งเหยิงทั้งหมดนี้เกี่ยวกับประเภทของตัวแปรจะหายไปเมื่อคุณคุ้นเคยกับภาษาที่พิมพ์แบบไดนามิก นั่นคือถ้าคุณเริ่มที่จะชอบพวกเขา (ฉันไม่แน่ใจว่าทุกคนสามารถทำได้ แต่ฉันทำ)

C # varค่อนข้างเจ๋งที่ดูเหมือนว่าการพิมพ์แบบไดนามิก แต่จริงๆแล้วการพิมพ์แบบคงที่ - คอมไพเลอร์บังคับใช้การใช้งานที่ถูกต้อง

ประเภทของตัวแปรของคุณนั้นไม่สำคัญมากนัก มันควรจะค่อนข้างชัดเจนจากบริบท (การโต้ตอบกับตัวแปรและวิธีการอื่น ๆ ) และชื่อ - อย่าคาดหวังว่าcustomerListจะมีint...

ฉันยังคงรอดูว่าเจ้านายของฉันคิดอย่างไรกับเรื่องนี้ - ฉันได้ผ้าห่ม "ไปข้างหน้า" เพื่อใช้สิ่งก่อสร้างใหม่ใน 3.5 แต่เราจะทำอะไรเกี่ยวกับการบำรุงรักษา


7

ในการเปรียบเทียบของคุณระหว่างIEnumerable<int>และIEnumerable<double>คุณไม่จำเป็นต้องกังวล - ถ้าคุณผ่านประเภทผิดรหัสของคุณจะไม่รวบรวม

มีความกังวลเกี่ยวกับประเภทความปลอดภัยไม่ได้เป็นvarคือไม่ได้แบบไดนามิก มันเป็นเพียงแค่คอมไพเลอร์เวทย์มนตร์และการโทรที่ไม่ปลอดภัยประเภทใดก็ตามที่คุณทำจะถูกจับได้

Var จำเป็นอย่างยิ่งสำหรับ Linq:

var anonEnumeration =
    from post in AllPosts()
    where post.Date > oldDate
    let author = GetAuthor( post.AuthorId )
    select new { 
        PostName = post.Name, 
        post.Date, 
        AuthorName = author.Name
    };

ตอนนี้ดูที่anonEnumerationใน Intellisense และมันจะปรากฏเป็นอย่างนั้นIEnumerable<'a>

foreach( var item in anonEnumeration ) 
{
    //VS knows the type
    item.PostName; //you'll get intellisense here

    //you still have type safety
    item.ItemId;   //will throw a compiler exception
}

คอมไพเลอร์ C # นั้นค่อนข้างฉลาด - ประเภทอานนท์ที่สร้างแยกกันจะมีประเภทที่สร้างขึ้นเหมือนกันถ้าคุณสมบัติตรงกัน

นอกเหนือจากนั้นตราบใดที่คุณมีความเป็น Intellisense คุณสามารถใช้งานvarได้ทุกที่บริบทนั้นชัดเจน

//less typing, this is good
var myList = new List<UnreasonablyLongClassName>();

//also good - I can't be mistaken on type
var anotherList = GetAllOfSomeItem();

//but not here - probably best to leave single value types declared
var decimalNum = 123.456m;

โปรดลบออกIQueriable<T>ก่อนที่จะวนซ้ำ: anonEnumeration.ToList();
David Diez

@DavidDiez คุณสามารถเรียบเรียงใหม่ได้หรือไม่? ข้อความของคุณไม่สมเหตุสมผล ไม่มีข้อมูลโค้ดของฉันอ้างอิงIQueryableหรือ.ToList()
Keith

var anonEnumeration = from post in AllPosts() where post.Date > oldDate let author = GetAuthor( post.AuthorId ) select new { PostName = post.Name, post.Date, AuthorName = author.Name };ไม่ส่งคืนIQueriable<T>หรือไม่
David Diez

1
@DavidDiez มันขึ้นอยู่กับว่าAllPosts()ผลตอบแทน - ผู้List<T>ถามหมายถึงดังนั้นฉันคิดว่า ในกรณีที่ว่าผลที่ได้คือว่าจะเป็นประเภทanonEnumeration IEnumerable<'a>ตอนนี้ถ้าAllPosts()ผลตอบแทนIQueryable<T>แทนแล้วanonEnumerationจะกลายเป็นIQueryable<'a>(หมายเหตุไม่มีiใน queryable) - แต่ในกรณีที่รหัสของฉันยังคงทำงานเพราะการดำเนินการIQueryable<T> IEnumerable<T>มีคำถามและคำตอบที่ดีกว่ามากมายเกี่ยวกับความแตกต่างระหว่างพวกเขา - ในกรณีของฉัน'aคือไม่ระบุชื่อและvarอนุญาตให้คุณกำหนดให้กับตัวแปรที่พิมพ์แบบคงที่
Keith

โอ้ฉันเข้าใจแล้วขอบคุณที่อธิบายมัน :) ความคิดเห็นของฉันเป็นเพราะการทำซ้ำIQueryable<T>ไม่ใช่วิธีปฏิบัติที่ดีเพราะในการทำซ้ำแต่ละครั้งคุณกำลังอ่านข้อความในฐานข้อมูล ต้องแน่ใจว่า*.ToList() IQueryable<T>ได้ทำซ้ำก่อน
เดวิดดีซ

7

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

ท้ายที่สุดถ้างบชอบ

var index = 5; // this is supposed to be bad

var firstEligibleObject = FetchSomething(); // oh no what type is it
                                            // i am going to die if i don't know

เป็นจริงที่เป็นไปไม่ได้ที่จะจัดการกับไม่มีใครจะใช้ภาษาที่พิมพ์แบบไดนามิก


สันนิษฐานว่าใน. Net 4 ที่ประเภทไดนามิกเป็นสถานที่ทั่วไปสิ่งนี้จะมีความสำคัญมากกว่าหรือไม่
Colin Desmond

2
ในทางตรงกันข้ามหากคุณสับสนด้วย "var" ตอนนี้ฉันคาดว่าคุณจะสับสนด้วย "ไดนามิก" พระเจ้าห้ามใครก็ตามที่เคยประกาศว่ามีพลวัตแล้วทำการอ้างอิงกับมันโดยใช้ "var" :)
mqp

ฉันหมายถึงบางสิ่งเช่นไดนามิก d = 52; var x = d; ซึ่งควรจะดี
mqp

7

ฉันใช้ var ก็ต่อเมื่อมันชัดเจนเพื่อดูประเภทที่ใช้

ตัวอย่างเช่นฉันจะใช้ var ในกรณีนี้เพราะคุณสามารถเห็นได้ทันทีว่า x จะเป็นประเภท "MyClass":

var x = new MyClass();

ฉันจะไม่ใช้ var ในกรณีเช่นนี้เพราะคุณต้องลากเมาส์ไปวางบนรหัสและดูที่คำแนะนำเครื่องมือเพื่อดูว่า MyFunction ประเภทใดที่ส่งกลับ:

var x = MyClass.MyFunction();

โดยเฉพาะอย่างยิ่งฉันไม่เคยใช้ var ในกรณีที่ด้านขวาไม่ได้เป็นวิธี แต่เพียงค่า:

var x = 5;

(เพราะคอมไพเลอร์ไม่สามารถรู้ว่าฉันต้องการ byte, short, int หรืออะไรก็ตาม)


ถ้าด้านขวามือจะไม่ชัดเจนพอที่จะปรับใช้varแล้วvarไม่ได้เป็นปัญหา: ด้านขวามือเป็นปัญหา มันไม่ได้สื่อความหมายมากพอ Customer c = GetContext()คือยังคงvarไม่มีความชัดเจนและไม่มีดีกว่าการใช้
JulianR

6

สำหรับฉันแล้วความเกลียดชังที่มีต่อvarแสดงให้เห็นว่าทำไมการใช้สองภาษาใน. NET จึงมีความสำคัญ สำหรับโปรแกรมเมอร์ C # ผู้ที่ได้ทำ VB .NET แล้วข้อดีของการvarใช้งานนั้นชัดเจนโดยสังหรณ์ใจ การประกาศ C # มาตรฐานของ:

List<string> whatever = new List<string>();

เทียบเท่าใน VB .NET ของการพิมพ์นี้:

Dim whatever As List(Of String) = New List(Of String)

ไม่มีใครทำอย่างนั้นใน VB .NET คงจะเป็นเรื่องที่โง่เง่ามากเพราะตั้งแต่รุ่นแรกของ. NET คุณสามารถทำสิ่งนี้ได้ ...

Dim whatever As New List(Of String)

... ซึ่งสร้างตัวแปรและเริ่มต้นมันทั้งหมดในหนึ่งบรรทัดที่มีขนาดกะทัดรัดพอสมควร Ah แต่ถ้าคุณต้องการIList<string>ไม่List<string>? ใน VB .NET นั่นหมายความว่าคุณต้องทำสิ่งนี้:

Dim whatever As IList(Of String) = New List(Of String)

เช่นเดียวกับที่คุณต้องทำใน C # และไม่สามารถใช้varสำหรับ:

IList<string> whatever = new List<string>();

หากคุณต้องการประเภทที่จะเป็นสิ่งที่แตกต่างก็สามารถ แต่หนึ่งในหลักการพื้นฐานของการเขียนโปรแกรมที่ดีคือการลดความซ้ำซ้อนและนั่นคือสิ่งที่ var ทำ


1
ตลกคุณพูดถึงสองภาษาเป็นสิ่งที่ส่งเสริมการใช้ var การเป็นปรปักษ์กันของฉันต่อคำหลัก var เกิดขึ้นโดยตรงจากความคล่องแคล่วของฉันใน javascript! :)
urig

varใน C # ไม่มีการเชื่อมต่อใด ๆ กับvarใน JavaScript varตัวแปร -declared ใน C # เป็นอย่างยิ่งพิมพ์
Ryan Lundy

6

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

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

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

ฉันไม่สนใจการพิมพ์แบบไดนามิกและฉันไม่รังเกียจการพิมพ์โดยนัยในภาษาที่ออกแบบมาสำหรับพวกเขา ฉันค่อนข้างชอบงูใหญ่ แต่ C # ได้รับการออกแบบเป็นภาษาที่พิมพ์แบบคงที่อย่างชัดเจนและเป็นวิธีที่ควรอยู่ การทำลายกฎสำหรับประเภทนิรนามนั้นไม่ดีพอ การให้ผู้คนใช้สิ่งนั้นต่อไปและทำลายสำนวนภาษามากยิ่งขึ้นเป็นสิ่งที่ฉันไม่พอใจ ตอนนี้จีนี่ไม่อยู่ในขวดมันจะไม่มีทางกลับเข้าไป C # จะกลายเป็น balkanised ในค่าย ไม่ดี.


7
ว้าว. การเพิกเฉยต่อข้อโต้แย้งทั้งหมดที่เกิดขึ้นในเธรดนี้และการตั้งค่าการอภิปรายทั้งหมดใหม่ถือเป็นความสำเร็จ
Konrad Rudolph

100% นี้อธิบายถึงความรู้สึกของฉันเกี่ยวกับ 'var' โดยเฉพาะอย่างยิ่งจากมุมมองของการรับรหัสของคนอื่น การใช้ var เปลี่ยนแปลงอย่างรุนแรงงานในมือถ้ามันเกลื่อนไปทั่ว +1
Simon

6

หลายครั้งในระหว่างการทดสอบฉันพบว่าตัวเองมีรหัสเช่นนี้:

var something = myObject.SomeProperty.SomeOtherThing.CallMethod();
Console.WriteLine(something);

ตอนนี้บางครั้งฉันต้องการดูว่าตัวเองมี SomeOtherThing บ้าง SomeOtherThing ไม่ใช่ CallMethod () ประเภทเดียวกัน เนื่องจากฉันใช้ var ฉันก็แค่เปลี่ยนสิ่งนี้:

var something = myObject.SomeProperty.SomeOtherThing.CallMethod();

สำหรับสิ่งนี้:

var something = myObject.SomeProperty.SomeOtherThing;

หากไม่มี var ฉันจะต้องเปลี่ยนประเภทที่ประกาศทางด้านซ้ายด้วยเช่นกัน ฉันรู้ว่ามันเล็ก ๆ น้อย ๆ แต่มันสะดวกมาก


6

สำหรับ afficionados ที่คิดว่าvarช่วยประหยัดเวลาใช้เวลาในการพิมพ์น้อยลง:

StringBuilder sb = new StringBuilder();

กว่า

var sb = new StringBuilder();

นับถ้าคุณไม่เชื่อฉัน ...

19 กับ 21

ฉันจะอธิบายถ้าฉันต้องทำ แต่ลองดูนะ ... (ขึ้นอยู่กับสถานะปัจจุบันของ intellisense ของคุณคุณอาจต้องพิมพ์อีกสองสามอย่างสำหรับแต่ละอัน)

และมันก็เป็นจริงสำหรับทุกประเภทที่คุณนึกถึง !!

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


ฉันค้นหาการซ้ำซ้อนของ stringBuilder sb = new StringBuilder () ยุ่งและอีกต่อไปที่จะรับรู้ได้อย่างชัดเจน มันมีเสียงรบกวนมาก ปัญหาคือการพิจารณาว่าอะไรและไม่ได้ประกอบไปด้วยความพยายามทางปัญญาเป็นพิเศษในการทำความเข้าใจโค้ดบางอย่างนั้นเป็นเรื่องส่วนตัว!
ljs

"var ไม่ควรใช้ยกเว้นในกรณีที่ไม่ทราบชนิด ... " - คุณสามารถรู้ชนิดได้เสมอเช่นเดียวกับคอมไพเลอร์ นี่ไม่ใช่การพิมพ์แบบไดนามิกมันแค่ให้คอมไพเลอร์กำหนดประเภทให้คุณ แต่ประเภทนี้ไม่เป็นที่รู้จัก
Gabriel Magana

5

ฉันได้แยกสถานที่ต่าง ๆ สถานที่ที่น่าสงสัยเพียงอย่างเดียวสำหรับฉันคือประเภทสั้น ๆ ภายในเช่นฉันชอบint i = 3;มากกว่าvar i = 3;


5

แน่นอนว่ามันสามารถทำให้สิ่งต่าง ๆ ง่ายขึ้นจากรหัสที่ฉันเขียนเมื่อวาน:

var content  = new Queue<Pair<Regex, Func<string, bool>>>();
...
foreach (var entry in content) { ... }

varนี้จะมีเป็นอย่างมากอย่างละเอียดโดยไม่ต้อง

ภาคผนวก: เวลาที่ใช้ไปกับภาษาที่มีการอนุมานแบบเรียลไทม์ (เช่น F #) จะแสดงให้เห็นว่าคอมไพเลอร์ดีแค่ไหนที่ทำให้ประเภทของการแสดงออกถูกต้อง แน่นอนว่ามันมีความหมายว่าฉันมักจะใช้varให้มากที่สุดเท่าที่จะทำได้และตอนนี้การใช้ประเภทที่ชัดเจนนั้นบ่งชี้ว่า


ใช่คอมไพเลอร์ฉลาดกว่าเรา
Benjol

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