MyClass[] array;
List<MyClass> list;
Các kịch bản khi một là tốt hơn so với cái khác là gì? Và tại sao?
MyClass[] array;
List<MyClass> list;
Các kịch bản khi một là tốt hơn so với cái khác là gì? Và tại sao?
Câu trả lời:
Trên thực tế, rất hiếm khi bạn muốn sử dụng một mảng. Chắc chắn sử dụng List<T>
bất cứ lúc nào bạn muốn thêm / xóa dữ liệu, vì thay đổi kích thước mảng là tốn kém. Nếu bạn biết dữ liệu có độ dài cố định và bạn muốn tối ưu hóa vi mô cho một số lý do rất cụ thể (sau khi đo điểm chuẩn), thì một mảng có thể hữu ích.
List<T>
cung cấp rất nhiều chức năng hơn một mảng (mặc dù LINQ phát triển nó lên một chút) và hầu như luôn là lựa chọn đúng đắn. Ngoại trừ params
tranh luận, tất nhiên. ;-p
Như một bộ đếm - List<T>
là một chiều; trong đó như bạn có các mảng hình chữ nhật (vv) nhưint[,]
hoặc string[,,]
- nhưng có nhiều cách khác để mô hình hóa dữ liệu đó (nếu bạn cần) trong một mô hình đối tượng.
Xem thêm:
Điều đó nói rằng, tôi sử dụng rất nhiều mảng trong dự án protobuf-net của mình ; hoàn toàn cho hiệu suất:
byte[]
rất cần thiết cho việc mã hóa;byte[]
bộ đệm cuộn cục bộ mà tôi điền trước khi gửi xuống luồng bên dưới (và vv); nhanh hơnBufferedStream
vv;Foo[]
chứ không phải làList<Foo>
), vì kích thước được cố định một khi được xây dựng và cần phải rất nhanh.Nhưng đây chắc chắn là một ngoại lệ; để xử lý ngành kinh doanh nói chung, List<T>
mỗi lần thắng.
Thực sự chỉ cần trả lời để thêm một liên kết mà tôi ngạc nhiên chưa được đề cập: mục blog của Eric Lippert trên "Mảng được coi là có hại."
Bạn có thể đánh giá từ tiêu đề mà nó gợi ý bằng cách sử dụng các bộ sưu tập ở bất cứ nơi nào thực tế - nhưng như Marc chỉ ra một cách đúng đắn, có rất nhiều nơi mà một mảng thực sự là giải pháp thực tế duy nhất.
Mặc dù các câu trả lời khác được đề xuất List<T>
, bạn sẽ muốn sử dụng mảng khi xử lý:
List<T>
ở đây hơn là một mảng byte?
Trừ khi bạn thực sự quan tâm đến hiệu suất, và ý tôi là, "Tại sao bạn lại sử dụng .Net thay vì C ++?" bạn nên gắn bó với Danh sách <>. Nó dễ dàng hơn để duy trì và thực hiện tất cả các công việc bẩn thỉu thay đổi kích thước một mảng phía sau hậu trường cho bạn. (Nếu cần, Danh sách <> khá thông minh về việc chọn kích thước mảng nên thường không cần.)
Mảng nên được sử dụng để ưu tiên cho Danh sách khi tính bất biến của chính bộ sưu tập là một phần của hợp đồng giữa mã khách hàng và nhà cung cấp (không nhất thiết là tính bất biến của các mặt hàng trong bộ sưu tập) VÀ khi IEnumerable không phù hợp.
Ví dụ,
var str = "This is a string";
var strChars = str.ToCharArray(); // returns array
Rõ ràng là việc sửa đổi "strChars" sẽ không làm thay đổi đối tượng "str" ban đầu, bất kể kiến thức ở cấp độ triển khai của loại cơ sở của "str".
Nhưng giả sử rằng
var str = "This is a string";
var strChars = str.ToCharList(); // returns List<char>
strChars.Insert(0, 'X');
Trong trường hợp này, không rõ ràng từ đoạn mã đó nếu phương thức chèn sẽ hoặc không làm thay đổi đối tượng "str" ban đầu. Nó đòi hỏi kiến thức về mức độ triển khai của String để đưa ra quyết định đó, phá vỡ thiết kế theo phương pháp Hợp đồng. Trong trường hợp của String, nó không phải là một vấn đề lớn, nhưng nó có thể là một vấn đề lớn trong hầu hết các trường hợp khác. Đặt Danh sách thành chỉ đọc sẽ giúp nhưng dẫn đến lỗi thời gian chạy, không phải thời gian biên dịch.
To
sẽ tạo ra một đối tượng không có khả năng sửa đổi thể hiện ban đầu, trái ngược với strChars as char[]
điều đó nếu hợp lệ sẽ đề nghị bạn có thể sửa đổi đối tượng ban đầu.
str
bên trong sử dụng một mảng và ToCharArray
trả về một tham chiếu đến mảng này thì máy khách có thể biến đổi str
bằng cách thay đổi các phần tử của mảng đó, ngay cả khi kích thước vẫn cố định. Tuy nhiên, bạn viết 'Rõ ràng rằng việc sửa đổi "strChars" sẽ không làm thay đổi đối tượng "str" ban đầu. Tôi đang thiếu gì ở đây? Từ những gì tôi có thể thấy, trong cả hai trường hợp, khách hàng có thể có quyền truy cập vào biểu diễn bên trong và, bất kể loại nào, điều này sẽ cho phép đột biến một số loại.
Hầu hết thời gian, sử dụng một List
sẽ đủ. A List
sử dụng một mảng bên trong để xử lý dữ liệu của nó và tự động thay đổi kích thước mảng khi thêm nhiều phần tử vào List
dung lượng hiện tại, điều này giúp dễ sử dụng hơn một mảng, nơi bạn cần biết trước dung lượng.
Xem http://msdn.microsoft.com/en-us/l Library / ms379570 (v = vs.80) .aspx # docatuctures20_1_topic5 để biết thêm thông tin về Danh sách trong C # hoặc chỉ dịch ngược System.Collections.Generic.List<T>
.
Nếu bạn cần dữ liệu đa chiều (ví dụ: sử dụng ma trận hoặc trong lập trình đồ họa), có lẽ bạn sẽ đi với một array
thay thế.
Như mọi khi, nếu bộ nhớ hoặc hiệu suất là một vấn đề, đo lường nó! Nếu không, bạn có thể đưa ra các giả định sai về mã.
Mảng Vs. Danh sách là một vấn đề duy trì cổ điển so với vấn đề hiệu suất. Nguyên tắc chung mà gần như tất cả các nhà phát triển tuân theo là bạn nên bắn cho cả hai, nhưng khi họ xảy ra xung đột, hãy chọn khả năng duy trì trên hiệu suất. Ngoại lệ cho quy tắc đó là khi hiệu suất đã được chứng minh là một vấn đề. Nếu bạn thực hiện nguyên tắc này trong Mảng Vs. Danh sách, sau đó những gì bạn nhận được là đây:
Sử dụng danh sách gõ mạnh cho đến khi bạn gặp vấn đề về hiệu suất. Nếu bạn gặp phải một vấn đề về hiệu năng, hãy đưa ra quyết định về việc liệu bỏ ra các mảng sẽ có lợi cho giải pháp của bạn với hiệu suất nhiều hơn nó sẽ gây bất lợi cho giải pháp của bạn về mặt bảo trì.
Một tình huống khác chưa được đề cập là khi một người sẽ có một số lượng lớn các mục, mỗi mục bao gồm một bó các biến cố định nhưng độc lập liên quan được gắn với nhau (ví dụ: tọa độ của một điểm hoặc các đỉnh của tam giác 3d). Một loạt các cấu trúc trường tiếp xúc sẽ cho phép các phần tử của nó được sửa đổi một cách hiệu quả "tại chỗ" - điều không thể với bất kỳ loại bộ sưu tập nào khác. Do một mảng cấu trúc giữ các phần tử của nó liên tiếp trong RAM, nên việc truy cập tuần tự vào các phần tử mảng có thể rất nhanh. Trong các tình huống mà mã sẽ cần thực hiện nhiều chuỗi tuần tự đi qua một mảng, một mảng các cấu trúc có thể vượt trội hơn một mảng hoặc tập hợp các tham chiếu đối tượng lớp khác theo hệ số 2: 1; thêm nữa,
Mặc dù các mảng không thể thay đổi kích thước, nhưng không khó để mã lưu trữ một tham chiếu mảng cùng với số lượng phần tử đang sử dụng và thay thế mảng bằng một phần tử lớn hơn theo yêu cầu. Ngoài ra, người ta có thể dễ dàng viết mã cho một loại hoạt động giống như một List<T>
cửa hàng sao lưu của nó, do đó cho phép một người nói MyPoints.Add(nextPoint);
hoặc MyPoints.Items[23].X += 5;
. Lưu ý rằng cái sau sẽ không nhất thiết phải đưa ra một ngoại lệ nếu mã cố truy cập ngoài cuối danh sách, nhưng về mặt sử dụng thì về mặt khái niệm khá giống với List<T>
.
Point[] arr;
, mã có thể nói, ví dụ arr[3].x+=q;
. Sử dụng ví dụ List<Point> list
, nó sẽ là cần thiết để thay thế nói Point temp=list[3]; temp.x+=q; list[3]=temp;
. Nó sẽ hữu ích nếu List<T>
có một phương pháp Update<TP>(int index, ActionByRefRef<T,TP> proc, ref TP params)
. và trình biên dịch có thể biến list[3].x+=q;
thành {list.Update(3, (ref int value, ref int param)=>value+=param, ref q);
nhưng không có tính năng như vậy tồn tại.
list[0].X += 3;
sẽ thêm 3 vào thuộc tính X của phần tử đầu tiên của danh sách. Và list
là một List<Point>
và Point
là một lớp với các thuộc tính X và Y
Danh sách trong .NET là các hàm bao trên các mảng và sử dụng một mảng bên trong. Độ phức tạp thời gian của các thao tác trên danh sách giống như với các mảng, tuy nhiên có thêm một chút chi phí với tất cả các chức năng được thêm vào / dễ sử dụng danh sách (như thay đổi kích thước tự động và các phương thức đi kèm với lớp danh sách). Khá nhiều, tôi sẽ khuyên bạn sử dụng danh sách trong mọi trường hợp, trừ khi có một lý do thuyết phục không làm như vậy, chẳng hạn như nếu bạn cần phải viết mã cực kỳ tối ưu hóa, hoặc đang làm việc với các mã khác được xây dựng xung quanh mảng.
Thay vì đi qua so sánh các tính năng của từng loại dữ liệu, tôi nghĩ câu trả lời thực tế nhất là "sự khác biệt có lẽ không quan trọng đối với những gì bạn cần thực hiện, đặc biệt là khi cả hai đều thực hiện IEnumerable
, vì vậy hãy tuân theo quy ước phổ biến và sử dụng List
cho đến khi bạn có lý do để không, tại thời điểm đó bạn có thể sẽ có lý do để sử dụng một mảng trên a List
. "
Hầu hết thời gian trong mã được quản lý, bạn sẽ muốn ưu tiên các bộ sưu tập dễ làm việc nhất có thể hơn là lo lắng về tối ưu hóa vi mô.
Họ có thể không phổ biến, nhưng tôi là một fan hâm mộ của Mảng trong các dự án trò chơi. - Tốc độ lặp có thể quan trọng trong một số trường hợp, foreach trên Array có chi phí thấp hơn đáng kể nếu bạn không làm nhiều việc trên mỗi phần tử - Thêm và xóa không khó lắm với các hàm trợ giúp - Nó chậm hơn, nhưng trong trường hợp bạn chỉ xây dựng nó một lần nó có thể không quan trọng - Trong hầu hết các trường hợp, lãng phí ít bộ nhớ hơn (chỉ thực sự có ý nghĩa với Mảng của các cấu trúc) - Ít rác hơn và con trỏ và đuổi theo con trỏ
Điều đó đang được nói, tôi sử dụng Danh sách thường xuyên hơn Mảng trong thực tế, nhưng mỗi cái đều có vị trí của chúng.
Sẽ thật tuyệt nếu Liệt kê nơi có một kiểu dựng sẵn để họ có thể tối ưu hóa chi phí bao bọc và liệt kê.
Dân số một danh sách dễ dàng hơn một mảng. Đối với mảng, bạn cần biết độ dài chính xác của dữ liệu, nhưng đối với danh sách, kích thước dữ liệu có thể là bất kỳ. Và, bạn có thể chuyển đổi một danh sách thành một mảng.
List<URLDTO> urls = new List<URLDTO>();
urls.Add(new URLDTO() {
key = "wiki",
url = "https://...",
});
urls.Add(new URLDTO()
{
key = "url",
url = "http://...",
});
urls.Add(new URLDTO()
{
key = "dir",
url = "https://...",
});
// convert a list into an array: URLDTO[]
return urls.ToArray();
Vì không ai nhắc đến: Trong C #, một mảng là một danh sách. MyClass[]
và List<MyClass>
cả hai thực hiện IList<MyClass>
. (ví dụ void Foo(IList<int> foo)
có thể được gọi như Foo(new[] { 1, 2, 3 })
hoặc Foo(new List<int> { 1, 2, 3 })
)
Vì vậy, nếu bạn đang viết một phương thức chấp nhận một List<MyClass>
đối số, nhưng chỉ sử dụng tập hợp con các tính năng, bạn có thể muốn khai báo IList<MyClass>
thay vì để thuận tiện cho người gọi.
Chi tiết:
List
, nó chỉ thực hiện IList
giao diện.
Nó hoàn toàn phụ thuộc vào bối cảnh trong đó cấu trúc dữ liệu là cần thiết. Ví dụ: nếu bạn đang tạo các mục được sử dụng bởi các chức năng hoặc dịch vụ khác bằng Danh sách là cách hoàn hảo để thực hiện mục đó.
Bây giờ nếu bạn có một danh sách các mục và bạn chỉ muốn hiển thị chúng, hãy nói trên một mảng trang web là nơi bạn cần sử dụng.
IEnumerable<T>
- sau đó tôi có thể truyền phát các đối tượng thay vì đệm chúng.
Đó là giá trị đề cập về khả năng làm đúc tại chỗ.
interface IWork { }
class Foo : IWork { }
void Test( )
{
List<Foo> bb = new List<Foo>( );
// Error: CS0029 Cannot implicitly convert type 'System.Collections.Generic.List<Foo>' to 'System.Collections.Generic.List<IWork>'
List<IWork> cc = bb;
Foo[] bbb = new Foo[4];
// Fine
IWork[] ccc = bbb;
}
Vì vậy, Array cung cấp linh hoạt hơn một chút khi được sử dụng trong kiểu trả về hoặc đối số cho các hàm.
IWork[] GetAllWorks( )
{
List<Foo> fooWorks = new List<Foo>( );
return fooWorks.ToArray( ); // Fine
}
void ExecuteWorks( IWork[] works ) { } // Also accept Foo[]