Thuộc tính Count so với phương thức Count ()?


85

Làm việc với một tập hợp, tôi có hai cách để lấy số lượng các đối tượng; Count(thuộc tính) và Count()(phương thức). Có ai biết sự khác biệt chính là gì không?

Tôi có thể sai, nhưng tôi luôn sử dụng thuộc Counttính trong bất kỳ câu lệnh điều kiện nào vì tôi giả sử Count()phương thức thực hiện một số loại truy vấn đối với bộ sưu tập, nơi mà như Counthẳn đã được chỉ định trước khi tôi 'nhận'. Nhưng đó là phỏng đoán - tôi không biết liệu hiệu suất có bị ảnh hưởng nếu tôi sai hay không.

EDIT: Vì tò mò sau đó, sẽ Count()ném một ngoại lệ nếu bộ sưu tập là null? Bởi vì tôi khá chắc chắn thuộc Counttính chỉ trả về 0.


7
Cả hai sẽ ném một ngoại lệ cho các bộ sưu tập null, vì cả hai đều đang cố gắng áp dụng .toán tử cho một cái gì đó là null.
AaronLS

Câu trả lời:


109

Việc biên dịch mã nguồn cho Count()phương thức mở rộng cho thấy rằng nó kiểm tra xem đối tượng có phải là một ICollection(chung chung hay không) và nếu vậy chỉ đơn giản là trả vềCount :

Vì vậy, nếu mã của bạn truy cập Countthay vì gọi Count(), bạn có thể bỏ qua kiểm tra kiểu - một lợi ích về hiệu suất lý thuyết nhưng tôi nghi ngờ nó sẽ là một điều đáng chú ý!

// 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 vì đã chủ động thiết kế ngược điều này, rất hữu ích.
Đa thức

7
Tuy nhiên, hãy nhớ rằng trong 3.5 Count()không kiểm tra ICollectiongiao diện không chung chung . Điều này chỉ được thêm vào .NET 4. Cả 3.5 và 4 đều kiểm tra ICollection<T>giao diện chung .
thecoop

2
gọi số đếm trên một chuỗi không có phần tử nào sẽ ném ra một ngoại lệ. Nhưng Count () sẽ hoạt động tốt.
amesh

33

Hiệu suất chỉ là một lý do để chọn cái này hay cái kia. Chọn .Count()có nghĩa là mã của bạn sẽ chung chung hơn. Tôi đã có những lần cấu trúc lại một số mã không còn tạo ra một bộ sưu tập nữa, mà thay vào đó là một thứ gì đó chung chung hơn như IEnumerable, nhưng kết quả là mã khác bị hỏng vì nó phụ thuộc vào .Countvà tôi phải thay đổi nó thành .Count(). Nếu tôi muốn sử dụng .Count()ở mọi nơi, mã sẽ có thể được tái sử dụng và bảo trì nhiều hơn. Thông thường chọn sử dụng các giao diện chung chung hơn nếu bạn có thể thoát khỏi nó là đặt cược tốt nhất của bạn. Nói chung chung hơn, ý tôi là giao diện đơn giản hơn được thực hiện bởi nhiều loại hơn và do đó mang lại cho bạn khả năng tương thích cao hơn giữa các mã.

Tôi không nói .Count()là tốt hơn, tôi chỉ nói rằng có những cân nhắc khác giải quyết nhiều hơn khả năng tái sử dụng của mã bạn đang viết.


2
+1 Bổ sung có giá trị cho cuộc thảo luận. Một số mã mà tôi đang duy trì vừa bị hỏng vì thuộc tính .Count không tồn tại khi nâng cấp phiên bản của HtmlAgilityPack.
Dan Solovay

1
Đó có thể là con dao hai lưỡi. Điều gì sẽ xảy ra nếu một ngày ai đó cố gắng sửa đổi IEnumerable để trở thành một trình tạo thực sự. Nhìn vào codebase tôi nhìn thấy rất nhiều những nơi Count () giả định rằng đếm được có thể được lặp nhiều lần
bashrc

@bashrc Đúng. Tôi nghĩ nếu chúng ta đang xem xét việc thay đổi mã của nhà phát triển so với việc thay đổi mã khung, thì nhiều khả năng mã của nhà phát triển sẽ thay đổi. Nếu loại thay đổi đó được thực hiện trong khuôn khổ, nó sẽ phá vỡ rất nhiều thứ. Theo truyền thống, họ giới thiệu các bộ sưu tập / giao diện mới trong những trường hợp này để nhà phát triển có thể di chuyển như mong muốn.
AaronLS

20

Các .Count()phương pháp có thể là đủ thông minh, hoặc biết về loại trong câu hỏi, và nếu như vậy, nó có thể sử dụng cơ bản.Count tài sản.

Sau đó, một lần nữa, nó có thể không.

Tôi sẽ nói rằng có thể an toàn khi giả định rằng nếu bộ sưu tập có .Counttài sản riêng, thì đó sẽ là lựa chọn tốt nhất của bạn khi nói đến hiệu suất.

Nếu .Count()phương thức không biết về tập hợp, nó sẽ liệt kê trên đó, đây sẽ là một phép toán O (n).


3
Sử dụng thuộc Counttính có thể tốt hơn, nhưng Count()phương pháp tạo bằng cách sử dụng gần như ICollection<T>.Countđược ghi lại ở đây: msdn.microsoft.com/en-us/library/bb338038(v=vs.110).aspx
nawfal

Tôi không biết làm thế nào bạn biết hầu hết mọi thứ.
snr

5

Count()method là một phương thức mở rộng lặp lại từng phần tử của an IEnumerable<>và trả về có bao nhiêu phần tử. Nếu trường hợp của IEnumerablethực sự là a List<>, thì nó được tối ưu hóa để trả về thuộc Counttính thay vì lặp lại tất cả các phần tử.


ngay cả khi tôi có Danh sách <>, tôi sử dụng phương thức Count () để giữ cho mã của mình chung chung hơn. Thật tốt khi tôi đang cấu trúc lại các lớp của mình để sử dụng IEnumerable <> nơi không cần triển khai bộ sưu tập cụ thể.
AntonioR

3

Count()là một phương thức mở rộng từ LINQ - Countlà một thuộc tính trên Listcác đối tượng thu thập .NET thực tế.

Như vậy, Count()hầu như sẽ luôn chậm hơn, vì nó sẽ liệt kê đối tượng thu thập / có thể truy vấn. Trên danh sách, hàng đợi, ngăn xếp, v.v., hãy sử dụng Count. Hoặc cho một mảng - Length.


3

Phiên bản ngắn: Nếu bạn có sự lựa chọn giữa thuộc Counttính vàCount() phương thức, hãy luôn chọn thuộc tính.

Sự khác biệt chủ yếu xoay quanh hiệu quả của hoạt động. Tất cả các bộ sưu tập BCL thể hiện một thuộc Counttính đều làm như vậy theo kiểu O (1). Các Count()phương pháp mặc dù có thể, và thường sẽ, chi phí O (N). Có một số kiểm tra để thử và đưa nó đến O (1) cho một số triển khai nhưng không có nghĩa là nó không được đảm bảo.


Tôi nghĩ câu trả lời này hợp lý hơn để sử dụng thuộc tính đếm
AT

3

Nếu có một Counthoặc thuộc Lengthtính, bạn nên luôn ưu tiên điều đó cho Count()phương thức, phương thức này thường lặp lại toàn bộ tập hợp để đếm số phần tử bên trong. Count()Ví dụ: ngoại lệ sẽ là khi phương thức chống lại nguồn LINQ tới SQL hoặc LINQ tới thực thể, trong trường hợp đó, nó sẽ thực hiện truy vấn đếm đối với nguồn dữ liệu. Thậm chí sau đó, nếu có một Counttài sản, bạn sẽ muốn thích nó hơn, vì nó có thể sẽ ít việc phải làm hơn.


3

Các Count()phương pháp là phương pháp LINQ hoạt động trên bất kỳ IEnumerable<>. Bạn sẽ mong đợi Count()phương pháp lặp lại toàn bộ tập hợp để tìm số lượng, nhưng tôi tin rằng mã LINQ thực sự có một số tối ưu hóa trong đó để phát hiện xem thuộc tính Đếm có tồn tại hay không và nếu có thì hãy sử dụng nó.

Vì vậy, cả hai nên làm những việc gần như giống hệt nhau. Thuộc tính Count có lẽ tốt hơn một chút vì không cần phải kiểm tra kiểu ở đó.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.