2017-11-16 28 views
23

C# 7.2 giới thiệu hai loại mới: Span<T>Memory<T> có hiệu suất tốt hơn so với các loại C# trước đó như string[].Sự khác nhau giữa Span <T> và Bộ nhớ <T> trong C# 7.2 là gì?

Câu hỏi: Sự khác biệt giữa Span<T>Memory<T> là gì? Tại sao tôi lại sử dụng cái kia?

+3

Xem thêm: [C# 7.2: Tìm hiểu về Span] (https://channel9.msdn.com/Events/Connect/2017/T125) –

+1

@JeffMercado Có danh sách đầy đủ ở đâu đó về loại C# mà họ có thể thay thế ngoài chuỗi không []? Chúng chỉ dành cho mảng hoặc chúng có thể được sử dụng thay cho các loại như Danh sách không? – user3610374

Trả lời

22

Span<T> là bản chất chỉ có ngăn xếp trong khi Memory<T> có thể sử dụng vùng heap.

Span<T> là một loại mới, chúng tôi đang bổ sung thêm cho nền tảng để đại diện cho vùng tiếp giáp bộ nhớ tùy ý, với hiệu suất đặc điểm ngang bằng với T []. API của nó tương tự như mảng, nhưng không giống như mảng, nó có thể trỏ đến bộ nhớ được quản lý hoặc riêng hoặc tới bộ nhớ được cấp phát trên ngăn xếp.

Memory <T> là loại bổ sung Span<T>. Như đã thảo luận trong tài liệu thiết kế , Span<T> là loại chỉ có ngăn xếp. Bản chất chỉ có ngăn xếp của Span<T> làm cho nó không phù hợp với nhiều trường hợp yêu cầu lưu trữ các tham chiếu vào bộ đệm (được biểu diễn bằng Span<T>) trên heap, ví dụ: cho thường trình thực hiện cuộc gọi không đồng bộ.

async Task DoSomethingAsync(Span<byte> buffer) { 
    buffer[0] = 0; 
    await Something(); // Oops! The stack unwinds here, but the buffer below 
         // cannot survive the continuation. 
    buffer[0] = 1; 
} 

Để giải quyết vấn đề này, chúng tôi sẽ cung cấp một tập hợp các loại bổ sung, dự định sẽ được sử dụng như các loại trao đổi mục đích chung đại diện, giống như Span <T>, một loạt các bộ nhớ tùy ý, nhưng không giống như Span <T> các loại này sẽ không được xếp chồng lên nhau, với chi phí đáng kể là các hình phạt về hiệu suất cho việc đọc và ghi vào bộ nhớ.

async Task DoSomethingAsync(Memory<byte> buffer) { 
    buffer.Span[0] = 0; 
    await Something(); // The stack unwinds here, but it's OK as Memory<T> is 
         // just like any other type. 
    buffer.Span[0] = 1; 
} 

Trong ví dụ trên, các Memory <byte> được sử dụng để đại diện cho các bộ đệm. Đây là loại thông thường và có thể được sử dụng trong các phương thức thực hiện cuộc gọi không đồng bộ. Thuộc tính Span của nó trả về Span<byte>, nhưng giá trị trả lại không được lưu trữ trên heap trong các cuộc gọi không đồng bộ, mà là giá trị mới được tạo ra từ giá trị Memory<T>. Theo nghĩa nào đó, Memory<T> là một nhà máy của Span<T>.

tham khảo tài liệu: here

+1

"Bản chất chỉ ngăn xếp" có nghĩa là gì? – Enigmativity

+0

@Coding, điều đó không đúng, nó cũng có thể trỏ đến bộ nhớ được quản lý (ví dụ: mảng). Thực tế là một khoảng chỉ có thể được trong ngăn xếp không có nghĩa là bộ nhớ nó chỉ đến cũng được yêu cầu để được trong ngăn xếp. –

+0

Bạn có thể vui lòng đăng liên kết đến các tài liệu thiết kế mà bạn đang đề cập đến không? –

10

lại: điều này có nghĩa nó chỉ có thể điểm vào bộ nhớ cấp phát trên stack.

Span<T> có thể trỏ đến bất kỳ bộ nhớ nào: được phân bổ trên ngăn xếp hoặc vùng lưu trữ. Bản chất chỉ có ngăn xếp của Span<T> có nghĩa là bản thân Span<T> (không phải bộ nhớ mà nó trỏ đến) chỉ có thể nằm trên ngăn xếp. Điều này trái ngược với cấu trúc C# "bình thường", có thể nằm trên ngăn xếp hoặc trên heap (khi chúng được nhúng trong các lớp/tham chiếu).Ý nghĩa thực tế rõ ràng nhất là bạn không thể có một trường Span<T> trong một lớp, bạn không thể hộp Span<T> và bạn không thể đặt chúng bên trong mảng.

+0

Ah, một loại khác trong số các loại như vậy. – IllidanS4

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