วิธีการนับทรัพย์สินเทียบกับจำนวน ()?


85

การทำงานกับคอลเลกชันฉันมีสองวิธีในการนับวัตถุ Count(คุณสมบัติ) และCount()(วิธีการ) ไม่มีใครรู้ว่าความแตกต่างที่สำคัญคืออะไร?

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

แก้ไข: ด้วยความอยากรู้อยากเห็นจะทำให้Count()เกิดข้อยกเว้นหากคอลเล็กชันเป็นโมฆะ? เพราะฉันค่อนข้างมั่นใจว่าCountคุณสมบัติจะคืนค่าเป็น 0


7
ทั้งคู่จะทำให้เกิดข้อยกเว้นสำหรับคอลเลกชัน null เนื่องจากทั้งคู่พยายามใช้ตัว.ดำเนินการกับสิ่งที่เป็นโมฆะ
AaronLS

คำตอบ:


110

การแยกแหล่งที่มาสำหรับCount()วิธีการขยายเผยให้เห็นว่ามันทดสอบว่าวัตถุนั้นเป็นICollection(ทั่วไปหรืออย่างอื่น) และถ้าเป็นเช่นนั้นเพียงแค่ส่งคืนพื้นฐานCountคุณสมบัติ :

ดังนั้นหากรหัสของคุณเข้าถึงCountแทนการโทรCount()คุณสามารถข้ามการตรวจสอบประเภท - ประโยชน์ด้านประสิทธิภาพตามทฤษฎี แต่ฉันสงสัยว่ามันจะเป็นสิ่งที่เห็นได้ชัดเจน!

// System.Linq.Enumerable
public static int Count<TSource>(this IEnumerable<TSource> source)
{
    checked
    {
        if (source == null)
        {
            throw Error.ArgumentNull("source");
        }
        ICollection<TSource> collection = source as ICollection<TSource>;
        if (collection != null)
        {
            return collection.Count;
        }
        ICollection collection2 = source as ICollection;
        if (collection2 != null)
        {
            return collection2.Count;
        }
        int num = 0;
        using (IEnumerator<TSource> enumerator = source.GetEnumerator())
        {
            while (enumerator.MoveNext())
            {
                num++;
            }
        }
        return num;
    }
}

10
+1 สำหรับการริเริ่มในการทำวิศวกรรมย้อนกลับสิ่งนี้มีประโยชน์มาก
พหุนาม

7
อย่างไรก็ตามโปรดทราบว่าใน 3.5 Count()ไม่ได้ตรวจสอบอินICollectionเทอร์เฟซที่ไม่ใช่ทั่วไป สิ่งนี้ถูกเพิ่มใน. NET 4 เท่านั้นทั้ง 3.5 และ 4 ตรวจสอบอินICollection<T>เทอร์เฟซทั่วไป
thecoop

2
จำนวนการโทรในลำดับที่ไม่มีองค์ประกอบจะทำให้เกิดข้อยกเว้น แต่ Count () จะทำงานได้ดี
amesh

33

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

ฉันไม่ได้บอกว่า.Count()ดีกว่าฉันแค่บอกว่ามีข้อควรพิจารณาอื่น ๆ ที่เกี่ยวข้องกับการใช้ซ้ำของโค้ดที่คุณกำลังเขียนมากกว่า


2
+1 นอกจากนี้ที่มีคุณค่าในการสนทนา รหัสบางอย่างที่ฉันดูแลอยู่นั้นพังเพราะคุณสมบัติ. Count ไม่รอดจากการอัพเกรดเวอร์ชันของ HtmlAgilityPack
Dan Solovay

1
นั่นอาจเป็นดาบสองคม จะเกิดอะไรขึ้นถ้าวันหนึ่งมีคนพยายามแก้ไข IEnumerable ให้เป็นเครื่องกำเนิดไฟฟ้าที่แท้จริง เมื่อมองไปที่ codebase ฉันเห็นสถานที่มากมายที่ .Count () สันนิษฐานว่าสามารถแจงนับได้หลายครั้ง
bashrc

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

20

.Count()วิธีการอาจจะฉลาดพอหรือรู้เกี่ยวกับประเภทในคำถามและถ้าเป็นเช่นนั้นก็อาจใช้อ้างอิง.Countสถานที่ให้บริการ

จากนั้นอีกครั้งมันอาจจะไม่

ฉันจะบอกว่ามันปลอดภัยที่จะสมมติว่าหากคอลเลกชันมี.Countคุณสมบัตินั้นจะเป็นทางออกที่ดีที่สุดของคุณเมื่อพูดถึงประสิทธิภาพ

หาก.Count()เมธอดไม่ทราบเกี่ยวกับคอลเลกชันก็จะแจกแจงมากกว่าซึ่งจะเป็นการดำเนินการ O (n)


3
การใช้Countคุณสมบัติอาจจะดีกว่า แต่Count()วิธีการใช้ICollection<T>.Countนั้นมีการบันทึกไว้ที่นี่: msdn.microsoft.com/en-us/library/bb338038(v=vs.110).aspx
nawfal

ฉันไม่รู้ว่าคุณรู้เกือบทุกเรื่องได้อย่างไร
snr

5

Count()method เป็นวิธีการขยายที่วนซ้ำแต่ละองค์ประกอบของ an IEnumerable<>และส่งกลับจำนวนองค์ประกอบที่มี หากอินสแตนซ์ของIEnumerableเป็น a จริงList<>ดังนั้นจึงได้รับการปรับให้ส่งคืนCountคุณสมบัติแทนที่จะทำซ้ำองค์ประกอบทั้งหมด


แม้ว่าฉันจะมี List <> ฉันก็ใช้วิธี Count () เพื่อให้รหัสของฉันมีความกว้างมากขึ้น มันดีเมื่อฉันปรับโครงสร้างคลาสของฉันใหม่เพื่อใช้ IEnumerable <> โดยที่ไม่จำเป็นต้องใช้คอลเลคชันเฉพาะ
AntonioR

3

Count()มีวิธีการขยายจาก LINQ หรือไม่ - CountคือคุณสมบัติบนLists วัตถุคอลเลกชัน. NET จริง

ด้วยเหตุนี้Count()จะช้าลงเกือบตลอดเวลาเนื่องจากจะระบุวัตถุคอลเลกชัน / แบบสอบถาม ในรายการคิว, สแต็ค ฯลฯ Countการใช้งาน หรือสำหรับอาร์เรย์ - Length.


3

เวอร์ชันสั้น: หากคุณมีทางเลือกระหว่างCountคุณสมบัติและไฟล์Count()วิธีการให้เลือกคุณสมบัติเสมอ

ความแตกต่างส่วนใหญ่อยู่ที่ประสิทธิภาพของการดำเนินการ คอลเลกชัน BCL ทั้งหมดที่เปิดเผยCountคุณสมบัติทำในลักษณะ O (1) Count()วิธี แต่สามารถและมักจะมีค่าใช้จ่าย O (N) มีการตรวจสอบบางอย่างที่ต้องลองและนำไปที่ O (1) สำหรับการใช้งานบางอย่าง แต่ก็ไม่มีการรับประกัน


ผมคิดว่าคำตอบนี้มีความเหมาะสมมากขึ้นในการใช้ทรัพย์สินนับ
AT

3

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


3

Count()วิธีเป็นวิธี LINQ IEnumerable<>ที่ทำงานใด ๆ คุณคาดหวังว่าไฟล์Count()วิธีการนี้จะวนซ้ำในคอลเลกชันทั้งหมดเพื่อค้นหาการนับ แต่ฉันเชื่อว่าโค้ด LINQ มีการปรับให้เหมาะสมเพื่อตรวจสอบว่ามีคุณสมบัติ Count อยู่หรือไม่และหากเป็นเช่นนั้นให้ใช้

ดังนั้นทั้งคู่ควรทำสิ่งที่เหมือนกันเกือบทั้งหมด คุณสมบัติ Count น่าจะดีกว่าเล็กน้อยเนื่องจากไม่จำเป็นต้องมีการเช็คอินประเภทนั้น

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