2015-02-12 14 views
5

Tôi cần phải chuyển cấu trúc dưới dạng loại giá trị trong danh sách. Giả sử tôi có một cấu trúc mà xuất phát từ một giao diện:Thêm cấu trúc: Giao diện vào danh sách <Interface>

interface IFoo 
{ 
    ... 
} 
struct Foo1 : IFoo { ... } 
struct Foo2 : IFoo { ... } 

//Some other class which contains this: 
List<IFoo> listOfFoo; 

Tôi biết nếu tôi đã làm điều đó như sau: IFoo foo = new Foo1(), nó sẽ biến các giá trị vào một tài liệu tham khảo (quyền Anh).

  1. có các cấu trúc không được thông qua như là một tài liệu tham khảo nếu tôi thêm Foo1 hoặc Foo2-List<IFoo>?
  2. Nếu không, có an toàn không khi làm List<object> và chỉ thêm vào các cấu trúc này, hoặc tốt hơn là nên làm MemberwiseClone trên một lớp học?

Tôi cũng đang tìm kiếm hiệu quả, vì điều này sẽ được phát hiện va chạm trong bản đồ ô.

+1

Một câu hỏi tham khảo: http://stackoverflow.com/questions/63671/is-it-safe-for-structs-to-implement-interfaces?rq=1 .. Và tôi sẽ đề xuất sử dụng phương pháp tiếp cận lớp học . –

Trả lời

2

Nếu bạn có một danh sách nơi tôi là một giao diện và bạn thêm phần tử kiểu F1F2 nơi cả hai thực hiện các giao diện tôi, sau đó khi bạn lấy bất kỳ của hai yếu tố từ danh sách bạn có thể kiểm tra loại tham chiếu bằng cách sử dụng từ khóa ** là ** và tiếp tục áp dụng dàn diễn viên thích hợp cho phần tử bạn nhận được từ Danh sách.

Ví dụ:

struct Foo1 : IFoo {...} 
struct Foo2 : IFoo {...} 

List<IFoo> listOfFoo = new List<IFoo>(); 

IFoo foo1 = new Foo1(); 
IFoo foo2 = new Foo2(); 
listOfFoo.Add(foo1); 
listOfFoo.Add(foo2); 

// lets retrieve the first element and check if it's a Foo1 value type 
if(listOfFoo[0] is Foo1){ 
    // cast element from List to Foo1 
    Foo1 foo = (Foo1) listOfFoo[0]; 
} 

Kể từ khi chúng tôi đang làm việc với cấu trúc, khi các phần tử từ danh sách được đúc trở lại kiểu giá trị ban đầu, cần được không có hộp bọc. Nhưng quá nhiều unboxing và boxing có thể đạt hiệu suất và vì bạn muốn thực hiện một cái gì đó giống như phát hiện va chạm, có thể mang lại cho bạn hiệu suất thấp.

Bạn có bắt buộc phải sử dụng cấu trúc không? Do sự thay đổi boxing được thực hiện cho các biến có thể không hoạt động đúng nếu bạn thực hiện các hoạt động trên các đối tượng đóng hộp được lưu trữ, và như tôi đã đề cập quá nhiều quyền anh có thể mang lại cho bạn kết quả kém.

Theo ý kiến ​​của tôi, một lớp học với MemberwiseClone sẽ tốt hơn.

Bạn có thể đọc this bài viết trên MSDN để nêu chi tiết ưu và khuyết điểm cho cả cấu trúc và lớp, điều này có thể giúp bạn hiểu rõ hơn khi nào sử dụng cái này hay cái kia.

+0

Cảm ơn bạn đã trả lời. Vì tôi có nhiều kinh nghiệm hơn với MemberwiseClone(), tôi đã quyết định chỉ đi với điều đó. –

5
  1. Cấu trúc sẽ được đóng hộp. Tại sao họ không? Mọi giá trị trong List<IFoo> phải là IFoo, vì vậy mỗi trường hợp cấu trúc bạn thêm được chuyển đổi - thông qua quyền anh.

  2. Các cấu trúc vẫn được đóng hộp vì object cũng là loại tham chiếu. Trong kịch bản của bạn, đơn giản là không có cách nào để tránh quyền anh trừ khi bạn khai báo danh sách là một loại giá trị cụ thể (List<Foo1> hoặc List<Foo2>).

Nói chung, việc sử dụng cấu trúc cho "hiệu quả" không hề đơn giản hoặc rõ ràng. Đặc biệt, chỉ cần nhét vào struct nơi bạn muốn viết class không được đảm bảo để làm cho mã của bạn hoạt động tốt hơn. Viết mã của bạn một cách rõ ràng trước tiên (và hiển nhiên ở đây có nghĩa là: sử dụng các lớp), sau đó xác định (thông qua lược tả) nếu bạn cần tối ưu hóa nó và nếu có, làm thế nào.

+0

Nhận xét tuyệt vời về tối ưu hóa - Tôi nghĩ lại suy nghĩ của bạn. – naspinski

0

Mỗi định nghĩa cấu trúc thực sự tạo hai loại điều trong .NET: một đối tượng heap ("đóng hộp") và vị trí lưu trữ ("không được hộp"). Các vị trí lưu trữ kiểu giao diện chứa các tham chiếu đối tượng đống, do đó lưu trữ một cấu trúc không có hộp thư đến một biến kiểu giao diện sẽ yêu cầu nội dung của nó được sao chép vào một thể hiện của kiểu đối tượng heap.

Có thể có thông số loại chung bị hạn chế đối với giao diện để xác định loại vị trí lưu trữ cấu trúc; sau đó, người ta có thể gọi các phương thức giao diện trên vị trí lưu trữ được đề cập mà không có quyền anh. Trong một số trường hợp, điều này có thể cung cấp một số lợi thế hiệu suất chính. Thật không may, không có cách nào để nói với trình biên dịch "Tôi không muốn điều này đóng hộp, và nếu tôi làm bất cứ điều gì mà sẽ yêu cầu boxing tôi thà có trình biên dịch squawk hơn âm thầm chèn một chuyển đổi đấm bốc". Do đó, việc chăm sóc cực kỳ là cần thiết khi sử dụng các cấu trúc thực hiện các giao diện; nếu một người không sẵn sàng để thực hiện chăm sóc như vậy, nó là tốt hơn để có tất cả các cấu trúc cố gắng để một trong hai:

  • hành xử giống như các đối tượng (trong trường hợp này họ cần phải được nhỏ và không cho phép bất kỳ phương pháp đột biến khác hơn là hoàn chỉnh thay thế) hoặc

  • không được gì hơn nhóm biến bị kẹt cùng với băng keo (tức là một loạt các trường công khai).

Những điều mà thực hiện các giao diện, ngoài một vài trường hợp đặc biệt như IEquatable<T>mục đích duy nhất trung tâm xung quanh cấu trúc, nói chung nên các lớp học.

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