2009-03-26 36 views
19

Tôi chắc chắn rằng câu hỏi này đề cập đến điều gì đó đã được nêu ra trong câu hỏi trước, nhưng tôi không thể tìm thấy nó.Chuyển đổi Danh sách loại cơ sở thành Danh sách loại thừa kế

Có một phương thức trong lớp C# lấy tham số là Danh sách chung của một Lớp cơ sở. Tôi cần phải vượt qua một danh sách của một lớp thừa kế và không biết chính xác làm thế nào để làm điều này. Tôi đang gặp lỗi trong nỗ lực của mình. Dưới đây là mã mẫu để minh họa điều này:

public class A 
{ 
    public static void MethodC(List<A>) 
    { 
     // Do Something here with the list 
    } 
} 
public Class B : A 
{ 
    // B inherits from A, A is the Base Class 
} 

// Code utilizing the above method 
List<B> listOfB = new List<B>(); 
A.MethodC((List<A>) listOfB); // Error: this does not work 
A.MethodC(listOfB.ToList<typeof(A)>()); // Error: this does not work 
A.MethodC(listOfB.ConvertAll<A>(typeof(A))); // Error: this does not work 
// how can I accomplish this? It should be possible I would think 

Lưu ý: Đây là phương pháp làm việc cuối cùng của tôi làm tài liệu tham khảo. Tôi đã có một giải pháp tốt hơn cho vấn đề của mình, nhưng về mặt kỹ thuật nó không phải là câu trả lời cho câu hỏi, vì câu hỏi của tôi đã bị phrased không đúng.

public static DataTable 
    ObjectCollectionToDataTable<GLIST> 
     (List<GLIST> ObjectCollection) where GLIST 
       : BaseBusinessObject 
     { 
      DataTable ret = null; 

      if (ObjectCollection != null) 
      { 
       foreach (var b in ObjectCollection) 
       { 

        DataTable dt = b.ToDataTable(); 
        if (ret == null) 
         ret = dt.Clone(); 
        if (dt.Rows.Count > 0) 
         ret.Rows.Add(dt.Rows[0].ItemArray); 
       } 
      } 

      return ret; 
     } 
+0

Đó là cùng một câu trả lời mà tôi đã cung cấp cho bạn ... –

+0

Và đó là về mặt kỹ thuật câu trả lời cho những gì bạn đã hỏi ban đầu, cũng! :) –

Trả lời

29

Nếu bạn có LINQ có sẵn, bạn có thể làm

var ListOfA = ListOfB.Cast<A>().ToList(); 
+0

Tôi không nghĩ rằng tôi có LINQ, nhưng nó làm việc anyway. cảm ơn bạn rất nhiều vì đã trả lời nhanh chóng. – stephenbayer

+0

Sự cố có thể xảy ra - MethodC có cần sửa đổi danh sách để các thay đổi đó có thể nhìn thấy bên ngoài MethodC không? –

+0

Rất vui khi nó hoạt động!Lý do duy nhất tôi tin rằng bạn có các phương pháp mở rộng LINQ có sẵn là việc sử dụng ToList trong ví dụ của bạn. –

4

Bạn đang giải quyết việc thiếu hiệp phương sai trong C# phiên bản hiện tại. Dưới đây là một cách để thực hiện:

listOfB.Cast<A>(); 
+0

Điều này chỉ cung cấp cho bạn một IEnumerable , không phải Danh sách . – tvanfosson

+0

@tvanfosson - Đẹp bắt! –

9

Bạn không thể làm điều đó. Để hiểu lý do tại sao nó không được phép, hãy tưởng tượng điều gì sẽ xảy ra nếu Add được gọi trên List<Derived> sau khi nó đã được chuyển đến List<Base>.

Ngoài ra, câu trả lời ngụ ý rằng C# 4.0 sẽ khác nhau sai. Danh sách sẽ không bao giờ được sửa đổi để cho phép bạn làm điều này. Chỉ IEnumerable sẽ - bởi vì nó không cho phép thêm các mục vào bộ sưu tập.

Cập nhật: Lý do hoạt động trong giải pháp bạn đã thực hiện là vì bạn không còn chuyển danh sách tương tự nữa. Bạn đang tạo một danh sách hoàn toàn mới là bản sao của bản gốc. Đây là lý do tại sao tôi hỏi về việc sửa đổi danh sách; nếu MethodC thay đổi số lượng mục trong danh sách, những thay đổi đó sẽ được thực hiện đối với bản sao chứ không phải danh sách gốc.

Tôi nghĩ rằng giải pháp lý tưởng cho bạn thực hiện như sau:

public abstract class A 
{ 
    public void MethodC<TItem>(List<TItem> list) where TItem : A 
    { 
     foreach (var item in list) 
      item.CanBeCalled(); 
    } 

    public abstract void CanBeCalled(); 
} 

public class B : A 
{ 
    public override void CanBeCalled() 
    { 
     Console.WriteLine("Calling into B"); 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     List<B> listOfB = new List<B>(); 

     A a = new B(); 

     a.MethodC(listOfB); 
    } 
} 

Thông báo như thế nào, với giải pháp này, bạn có thể vượt qua một List<B> trực tiếp đến MethodC mà không cần phải làm điều đó chuyển đổi kỳ lạ trên nó lần đầu tiên. Vì vậy, không cần sao chép không cần thiết.

Lý do là vì chúng tôi đã yêu cầu MethodC chấp nhận danh sách mọi thứ bắt nguồn từ A, thay vì nhấn mạnh rằng danh sách phải là danh sách A.

+0

Tôi không nghĩ đó là sự thật, nó hoạt động tốt. Phương thức gọi của tôi hoạt động lặp lại thông qua bộ sưu tập và hoạt động trên các phương thức và thuộc tính trừu tượng (ghi đè). Tôi đã sử dụng mã ở trên trong một phản hồi trước đó và nó hoạt động rất tốt. dự án là .NET 2.0 với trình biên dịch CSC.exe (C#) 3.0. – stephenbayer

+0

Xem cập nhật ở trên. –

+0

Tôi đoán bạn đang gặp khó khăn khi làm việc này? :) –

3

Đây là câu trả lời sẽ loại trừ bất kỳ đối tượng nào trong danh sách sai loại của bạn. Đây là cách an toàn hơn nhiều theo ý kiến ​​của tôi:

List<A> ListOfA = ListOfB.OfType<A>().ToList(); 

Phương pháp OfType sẽ loại trừ các mục của lớp có nguồn gốc sai khi Cast sẽ phát sinh lỗi.

Các vấn đề liên quan