2012-06-27 37 views
7

Tôi có một lớp bộ sưu tập như thế này:C# ngầm chuyển đổi từ lớp cơ sở

public class SomeDataCollection : List<ISomeData> 
{ 
    // some method ... 
} 

nhưng tôi không thể làm điều này:

SomeDataCollection someDatas = new List<ISomeData>(); 

Không thể ngầm chuyển đổi loại List<ISomeData>-SomeDataCollection . Một chuyển đổi rõ ràng tồn tại (là bạn thiếu một dàn diễn viên?)

vì vậy tôi cố gắng tạo ra một coverter tiềm ẩn bên trong lớp SomeDataCollection bộ sưu tập:

public static implicit operator SomeDataCollection(List<ISomeData> l) 
{ 
    var someDatas = new SomeDataCollection(); 
    someDatas.AddRange(l); 
    return someDatas; 
} 

nhưng nó nói rằng tôi không thể tạo chuyển đổi như vậy:

SomeDataCollection.implicit operator SomeDataCollection(List<ISomeData>): chuyển đổi người dùng định nghĩa hoặc từ một lớp cơ sở không được phép

Và khi tôi đúc nó như thế này:

SomeDataCollection someDatas = (SomeDataCollection)new List<ISomeData>(); 

nó ném một lỗi mà nói:

System.InvalidCastException: Không thể cast đối tượng kiểu List<ISomeData>SomeDataCollection.

Làm thế nào tôi có thể làm điều này:

SomeDataCollection someDatas = new List<ISomeData>(); 

mà không nhận được một lỗi? Hãy giúp tôi. Cảm ơn trước.

+0

có thể dupplicate: http://stackoverflow.com/questions/3401084/user-defined-conversion-operator-from-base-class – albertjan

Trả lời

6

A new List<ISomeData>(); vẫn chỉ là List<ISomeData>. Nó không phải là SomeDataCollection. Điểm của phân lớp là lớp con có thể có trạng thái phụ vv, nhưng một đối tượng (khi đã tạo) không bao giờ là loại thay đổi.

Bạn không được phép tạo toán tử giữa các loại trong cùng một hệ thống phân cấp, vì điều đó sẽ làm hỏng hành vi truyền bình thường và được mong đợi.

Bạn có thể sử dụng đơn giản:

var data = new SomeDataCollection(); 

Tuy nhiên tôi phải nói thêm rằng thẳng thắn đó là hiếm khi hữu ích để phân lớp List<T>. Không kém, nó không phơi bày bất kỳ phương thức hữu ích virtual nào, do đó bạn không thể chỉnh sửa hành vi. Tôi thực sự sẽ chỉ sử dụng List<ISomeData> (và xóa hoàn toàn SomeDataCollection) trừ khi tôi có mục đích rõ ràng và có thể chứng minh được. Và sau đó: tôi có thể đóng gói danh sách hoặc kế thừa từ Collection<T>.

Bạn luôn có thể thêm phương thức làm phương pháp mở rộng?

public static class Utils { 
    public static void SomeMethod(this IList<ISomeData> list) { 
     ... 
    } 
} 

thì:

var list = new List<ISomeData>(); 
... 
list.SomeMethod(); 
+0

Tôi không thực sự chỉ cần đặt một mới được khởi tạo 'Danh sách ' trong 'SomeDataCollection', đó chỉ là một mẫu: P. Tôi sử dụng 'List 'bởi vì nó đã có một số chức năng để thêm, loại bỏ, vv đối tượng, và tôi có một số phương pháp bổ sung và các thuộc tính trong lớp' SomeDataCollection' của tôi là cụ thể chỉ để gõ 'List '. –

+1

@ John IMO có thứ gì đó vừa là danh sách * và * có trạng thái riêng là một sai lầm; nhiều khuôn khổ/thư viện * ghét * đó - ràng buộc, tuần tự hóa, vật chất hóa, vv IMO bạn nên có một đối tượng mà * có * những thuộc tính đó, và cũng có * một 'IList Items {get;}' –

2

Trước hết, tại sao bạn muốn viết new List<ISomeData> vào một biến được xác định là SomeDataCollection? Có thể là bạn thực sự muốn SomeDataCollection someDatas = new SomeDataCollection();

Đối với các thông báo lỗi, thông báo lỗi đầu tiên nói với bạn rằng List<ISomeData> không có nguồn gốc từ SomeDataCollection, do đó bạn không thể làm gì với nó một cái gì đó bạn sẽ làm gì với SomeDataCollection, do đó bạn không thể ghi nó vào biến được định nghĩa là SomeDataCollection (hãy tưởng tượng ví dụ: nếu SomeDataCollectionpublic void someMethod() trong đó và sau đó trong mã bạn gọi là someDatas.someMethod()).

Thông báo lỗi thứ hai cho bạn biết rằng trình chuyển đổi được dự định để chuyển đổi giữa các loại hoàn toàn khác nhau, không phải giữa loại gốc và có nguồn gốc. Nếu không, bạn sẽ mong đợi điều gì, ví dụ: trong ví dụ sau:

SomeDataCollection a = new SomeDataCollection(); 
List<ISomeData> b = (List<ISomeData>)a; 
SomeDataCollection c = (SomeDataCollection)b; 

Nó có nên gọi cho công cụ chuyển đổi của bạn hay không?

Về cơ bản mã bạn đang cố viết là rất sai để bắt đầu, vì vậy chúng tôi cần biết bạn đang cố gắng làm gì, và sau đó có thể nói cho bạn biết giải pháp của vấn đề gốc của bạn (và không phải của vấn đề "làm thế nào để làm cho biên dịch mã này").

2

Không phải là nó tốt hơn để thực hiện một constructor trong SomeDataCollection?

public SomeDataCollection() : base() { } 

Điều này có thể đương nhiên được bổ sung với

public SomeDataCollection(IEnumerable<ISomeData> collection) 
    : base(collection) { } 

Sau đó, bạn sẽ có thể khởi tạo như SomeDataCollection bạn này thay vì:

SomeDataCollection someData = new SomeDataCollection(); 
SomeDataCollection someOtherData = 
    new SomeDataCollection(collectionOfSomeData); 

và vẫn có quyền truy cập vào tất cả các phương pháp công cộng và tài sản trong List<ISomeData>.

0

Nó không có vấn đề với generics. Trong C# bạn không được phép chuyển đổi một cách rõ ràng một lớp cơ sở thành một lớp dẫn xuất.

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