2009-03-19 8 views
7

Tôi đang tìm các phương pháp hay nhất để tạo bộ sưu tập được tạo từ các loại ẩn danh.Bộ sưu tập loại ẩn danh?

Có một số cách tiếp cận - this một và nhiều câu trả lời nhất trên this chuỗi giả định rằng toàn bộ bộ sưu tập ẩn danh có thể được tạo trong một tuyên bố.

Vì các loại vô danh thường được sử dụng để thay thế các lớp được sử dụng để lưu trữ tạm thời (như được đưa ra trong this SO answer), tôi muốn tránh tạo và sử dụng lớp cho các bộ sưu tập ẩn danh như this post gợi ý.

Trong trường hợp của mình, tôi đang lặp qua bộ sưu tập - cho mỗi mục trong bộ sưu tập, tôi muốn thu thập các đối tượng liên quan trong một loại ẩn danh (hoạt động như một bộ dữ liệu). Tôi cần những loại ẩn danh này để được đưa vào bộ sưu tập và sau đó sắp xếp chúng để tiếp tục công việc.

cách tiếp cận

khác tôi đã xem xét:

  1. Sử dụng một đối tượng [] hoặc ArrayList (mất lợi ích của loại vô danh)
  2. Tạo một lớp wrapper cho các mục yêu cầu (loại bỏ sự cần thiết của các ẩn danh loại)

Đây là nơi duy nhất trong mã của tôi mà tôi cần bộ sưu tập như vậy - cách tiếp cận tốt nhất là gì?

Thông tin bổ sung:

tôi đang làm việc với di sản Net 1.1 đối tượng, vì vậy các bộ sưu tập Tôi đang làm việc với các bộ sưu tập là gõ mạnh thực hiện IEnumerable, và như vậy hầu hết các phương pháp khuyến nông LINQ như .Chọn thắng' t công việc:

mẫu Mã

foreach (Item item in myItems) 
{ 
    foreach (Confirmation confirmation in item.GetConfirmations(true)) 
    { 
     if (lastParentId != item.ParentId) 
     { 
      lastParentId = item.ParentId; 
      parentObject = new ParentItem(lastParentId); 
     } 

     itemHolder = new ArrayList { item, confirmation }; 
     if (parentObject!= null) 
     { 
      itemHolder.Add(parentObject.Rate); 
     } 

     sortConfirmations.Add(confirmation.Date, itemHolder); 
    } 
} 

// Use sortConfirmations 

Nghị quyết

Tôi đã sử dụng từ điển chung để thu thập các mục liên quan với nhau và sử dụng .OrderBy() để sắp xếp chúng - xấu xí, nhưng nó hoạt động ... và tốt hơn mã hiện có.

+0

Để biết thông tin; để sử dụng LINQ với các bộ sưu tập cũ hơn, hãy sử dụng .Cast (), tức là myItems.Truyền () v.v. –

Trả lời

6

Đối với một câu trả lời rất khác nhau ... LINQ?

Trong trường hợp của tôi, tôi lặp lại trên một bộ sưu tập - cho từng hạng mục trong bộ sưu tập Tôi muốn thu thập đối tượng liên quan trong một loại vô danh (đóng vai trò như một tuple). Tôi cần các loại hình này ẩn danh để được đặt trong bộ sưu tập và sau đó sắp xếp chúng cho công việc tiếp theo.

Đó là âm thanh như:

var list = (from item in collection 
      from related in item.Relationship 
      order by ...something... 
      select new {item,related}).ToList() 
+0

Thật không may tôi cần phải làm mới một số đối tượng mà tôi sẽ thu thập theo loại ẩn danh. Tôi đang chuyển đổi một số mã hiện có đang đặt các đối tượng này trong một ArrayList và mỗi danh sách mảng vào một SorteList. Tôi cần phải đạt được một cái gì đó tương tự, nhưng sạch hơn. – Oded

+0

@Oded - thường vẫn có thể. Tất nhiên, thật khó để nói chắc chắn nếu không có một ví dụ cụ thể ... –

+0

+1 cho điểm "chúng tôi cần thêm thông tin". Tôi mạnh mẽ nghi ngờ rằng LINQ là con đường phía trước ở đây. –

4

Một lựa chọn là sử dụng một mục ví dụ để tạo ra bộ sưu tập qua generic suy luận kiểu, ví dụ:

static List<T> CreateEmptyList<T>(T template) { 
     return new List<T>(); 
    } 
    void Foo() { 
     var list = CreateEmptyList(new { Foo = "abc" }); 
     list.Add(new { Foo = "def" }); 
     //... 
    } 

Bạn cũng có thể làm được điều này mà không tạo một thể hiện (nhưng sử dụng một phương pháp ẩn danh mà không bao giờ được gọi), nhưng tôi không nghĩ rằng nó tiết kiệm bất cứ điều gì thực sự ... chúng tôi có thể không tạo ra một thể hiện của đối tượng, nhưng chúng tôi ... Điện thoại

Bạn cũng đề cập đến việc sắp xếp dữ liệu; xem reply here để biết cách sử dụng List<T>.Sort với lambda và do đó có các loại ẩn danh - tức là

list.Sort(x=>x.Foo); 
20

Nếu bạn hài lòng với một mảng, bạn có thể sử dụng một initializer mảng:

var items = new[] { 
    new { Foo = "def" }, 
    new { Foo = "ghi" }, 
    new { Foo = "jkl" } 
}; 

Sau đó bạn có thể gọi ToList() nếu bạn muốn có được một ra List<T>. Giải pháp của Marc sẽ hiệu quả hơn một chút so với việc gọi ToList() do không cần sao chép thêm, nhưng tôi nghĩ rằng Tôi có thể sử dụng giải pháp "mảng và sau đó ToList()" trong hầu hết các trường hợp vì có ít lộn xộn hơn. Tất nhiên, nếu hiệu suất là rất quan trọng cho bit mã đó, nó thay đổi mọi thứ.

EDIT: Khi bạn đang lặp lại trên một bộ sưu tập, chỉ cần sử dụng Select:

var anonymousItems = items.Select (item => new { Foo=item.Foo, 
               Bar=item.Other }) 
          .ToList(); 
+0

Không thể thực hiện điều đó, vì tôi đang lặp qua bộ sưu tập hiện có để truy xuất các đối tượng mà tôi muốn đưa vào loại anonymouse. Tôi đã có ý nghĩa để làm collection.Add (anonType). – Oded

+0

Một mẹo nhỏ: mảng là chỉ đọc, vì vậy nếu sử dụng phương pháp này hãy xem xét gọi '.ToList()' để tạo ra một bộ sưu tập có thể ghi. Điều này rất tiện lợi trong các kịch bản thử nghiệm đơn vị cho những thứ như các phương thức mở rộng. – STW

1

LINQ là con đường để đi. Giả sử bạn muốn tìm nạp các đối tượng liên quan A, B và C của mỗi mục trong một mục bộ sưu tập và sắp xếp theo đối tượng liên quan A bạn sẽ đi như sau.

var relatedObjects = items. 
     Select(item => new { A = item.A, B = item.B, C = item.C }). 
     OrderBy(item => item.A); 

Bạn nhận được một bộ sưu tập các mặt hàng của một loại vô danh với ba thuộc tính A, B và C thiết lập để các đối tượng có liên quan theo yêu cầu của các đối tượng có liên quan A.

tôi không xác minh rằng, nhưng bạn sẽ có thể mở rộng bộ sưu tập relatedObject sau này. Chỉ cần làm như sau để thêm một mục mới. Điều này sẽ làm việc bởi vì chỉ có một kiểu vô danh cho mỗi assembly tôi nghĩ rằng nếu tên và kiểu của mỗi thuộc tính khớp nhau.

relatedObjects = relatedObjects.Union(
    Enumerable.Repeat(new { A = someA, B = someB, C = someC }, 1)) 

Khá xấu vì có thể đếm được.Đặt lại() nhưng trở nên khá tốt nếu bạn kết hợp với một tập hợp các mục mới thay vì một mục mới.

0

này và hầu hết các câu trả lời trên chủ đề này giả định rằng toàn bộ giấu tên bộ sưu tập có thể được xây dựng trong một tuyên bố.

Có, bạn thường tạo một tập hợp loại ẩn danh trong một câu lệnh. Nếu bạn cần thêm câu lệnh, bạn có thể kết thúc với một bộ sưu tập khá vô dụng các loại ẩn danh khác nhau.

Các loại vô danh hữu ích khi bạn tạo chúng trong một câu lệnh duy nhất và sử dụng chúng ngay lập tức. Nếu việc tạo bộ sưu tập hoặc xử lý tiếp tục phức tạp hơn một chút, loại ẩn danh sẽ mất đi một số tính hữu dụng của nó.Ví dụ, bạn không thể chuyển một cách hiệu quả một kiểu vô danh cùng với một phương thức để xử lý, vì phương thức này không biết kiểu của đối tượng và do đó phải sử dụng sự phản chiếu để lấy ra bất kỳ thứ gì từ nó.

Nếu bạn định liên tục tìm kiếm các mục trong bộ sưu tập các loại ẩn danh này, bạn có thể muốn tạo một loại có tên để bạn có thể đặt chúng vào từ điển để tra cứu nhanh hơn nhiều.

+0

Bộ sưu tập A * đã nhập *, ngay cả các loại ẩn danh, sẽ không bị "số lượng các loại vô danh khác nhau" số phận; bạn không thể đặt "new {Foo =" acb "}" trong bộ sưu tập "new {Bar [int]}" –

+0

@Marc Gravell: Vâng, tất nhiên, bạn sẽ cần một thứ như Danh sách để xử lý cả hai loại, mất kết nối trực tiếp đến thông tin loại ẩn danh. – Guffa

0

Tôi tình cờ gặp câu hỏi này trong khi tìm cách tạo danh sách tạm thời các đối tượng tạm thời. Tại sao tôi muốn tạo một thứ như vậy? Tôi đang tìm kiếm một cách nhanh chóng để trả về JSON cho một danh sách các đối tượng được làm từ một số giá trị của một đối tượng khác. Đây là ý tôi.

Giả sử tôi có một class Employee ở phía máy chủ mà trông giống như sau trong C#:

public class Employee 
{ 
      public int Id; 
     public int businessGroupId; 
     public string title; 
     public int positionId; 

     public string firstName; 
     public string lastName; 
     ... 
} 

Hơn nữa tôi có một bộ sưu tập của các đối tượng mà tôi có thể dễ dàng lặp qua, giống như sau:

List<Employee> allEmployees = new List<Employee>(); 

Bây giờ, tôi muốn trở lại trang web kêu gọi của tôi toàn bộ bộ sưu tập của nhân viên, nhưng tôi chỉ muốn firstName, lastName cho mỗi. Tôi muốn họ trở lại như JSON.

Dưới đây là điểm quan trọng

Tôi không muốn quay trở lại mọi thuộc tính trong đối tượng người lao động.

Tôi biết tôi có thể dễ dàng tạo một loại ẩn danh bằng cách lặp qua bộ sưu tập allEmployees và xây dựng một đối tượng mới mỗi lần.

Nó sẽ trông giống như sau:

foreach (Employee e in allEmployees) 
{ 
    var tempObj = new {F_Name=e.firstName, L_Name=e.lastName}; 
} 

Các Loại một loại vô danh là gì? :)

Bí quyết bây giờ là tôi muốn toàn bộ bộ sưu tập (Danh sách <>) của các đối tượng ẩn danh này. Tuy nhiên, tôi không có cách nào để cung cấp Danh sách loại mà tôi sẽ sử dụng. Tôi không thể tạo List<unknown> allTempObjects = new List<unknown>();

Hoặc tôi có thể?

Với năng động, có thể

tôi có thể làm như sau và nó hoạt động tuyệt vời:

List<dynamic> allEmployees = new List<dynamic>(); 

foreach (Employee e in allEmployees) 
{ 
      var tempObj = new {F_Name=e.firstName, L_Name=e.lastName}; 
     allEmployees.Add(tempObj); 
} 

// use the JavaScript Serializer to serialize the dynamic collection 
JavaScriptSerializer jss = new JavaScriptSerializer(); 
// write the result out to the HTTP Stream (HtmlTextWriter in overridden Render method) 

writer.Write(jss.Serialize(allEmployees)); 

Bạn sẽ thấy JSON trên các mặt hàng mà trông giống như sau:

[ 
    { 
     F_Name: "Seth", 
     L_Name: "Godin" 
    }, 
    { 
     F_Name: "Charles", 
     L_Name: "Petzold" 
    }, 
    { 
     F_Name: "Jeff", 
     L_Name: "Prosise" 
    } 
] 

Cuối cùng, bạn có thể đặt câu hỏi tại sao tôi muốn làm điều này. Câu trả lời đơn giản là tôi muốn loại mới chỉ được sử dụng để sắp xếp để gửi cho khách hàng của tôi. Một lý do tuyệt vời cho một loại ẩn danh và một bộ sưu tập vô danh các loại ẩn danh, bạn có nghĩ vậy không?