2009-02-24 56 views
39

Bạn có nên sử dụng con trỏ trong mã C# của mình không? Những lợi ích là gì? Nó có được giới thiệu bởi The Man (Microsoft) không?Bạn có nên sử dụng con trỏ (mã không an toàn) trong C# không?

+0

Sử dụng con trỏ thường có liên quan đến p/invoke. Xem bài viết này: http://www.c-sharpcorner.com/UploadFile/pcurnow/usingpointers10022007082330AM/usingpointers.aspx – gsscoder

+0

Nếu bạn đang tận dụng nặng của mã không an toàn cho một sử dụng cụ thể, nó có thể giúp giữ lại tất cả điều đó mã trong một lớp bên trong riêng tư, được chứa bởi một lớp công cộng an toàn. Tôi không thích ý tưởng có phần còn lại của ứng dụng xử lý con trỏ. Bất kỳ lỗi tối nghĩa nào xuất hiện sau đó có thể được truy tìm đến cặp lớp này thay vì một vị trí không xác định trong phần còn lại của ứng dụng. Nó giữ sự phức tạp thêm từ rò rỉ ra vào phần còn lại của codebase. – Nuzzolilo

Trả lời

35

Từ "Người đàn ông":

Việc sử dụng con trỏ hiếm khi được yêu cầu trong C#, nhưng có một số trường hợp yêu cầu chúng.Như ví dụ, sử dụng một bối cảnh không an toàn để cho phép con trỏ được bảo đảm bởi các trường hợp sau:

  • Đối phó với cấu trúc hiện có trên đĩa
  • nâng cao COM hay nền tảng Gọi kịch bản có liên quan đến cấu trúc với con trỏ trong họ
  • Performance- mã quan trọng

Việc sử dụng ngữ cảnh không an toàn trong các tình huống khác không được khuyến khích.

Cụ thể, không nên sử dụng ngữ cảnh không an toàn để cố gắng viết mã C trong C#.

Chú ý:

Mã được viết bằng một bối cảnh không an toàn không thể được xác nhận là an toàn, vì vậy nó sẽ được thực hiện chỉ khi mã là hoàn toàn đáng tin cậy. Nói cách khác, mã không an toàn không thể được thực hiện trong một môi trường không tin cậy. Ví dụ: bạn không thể chạy mã không an toàn trực tiếp từ Internet.

Reference

+1

Thông thường, khi tôi thấy mã C# không an toàn trong các ví dụ trên internet, đó là một mùi mã. Có nghĩa là, ai đó đã cố gắng viết mã C trong C#. Tại thời điểm này, không gian tên Managed.Interop khá rộng và bạn có thể bọc IntPtr vào một cấu trúc đơn lẻ, vì vậy không an toàn thực sự là mã nhạy cảm với hiệu năng của các chuyên gia CLR. Nó không phải là một cách để giữ bí quyết cũ với con trỏ sống trong thế giới quản lý. –

11

Tôi không thể nhớ bao giờ phải làm như vậy - nhưng tôi chưa thực hiện nhiều tương tác. Đó là ứng dụng phổ biến nhất, tôi tin: gọi vào mã nguồn gốc. Có rất ít lần sử dụng con trỏ cho phép bạn tối ưu hóa một số mã, nhưng nó khá hiếm trong kinh nghiệm của tôi.

Nếu đó là bất kỳ hướng dẫn nào, tôi coi bản thân mình là khá kinh nghiệm trong C# nhưng nếu tôi phải làm bất kỳ mã không an toàn nào, tôi phải tham khảo spec/books/MSDN để hướng dẫn tôi. Tất nhiên sẽ có nhiều người hài lòng với mã không an toàn nhưng ít quen thuộc hơn với biểu thức truy vấn (nói) ...

+6

Tôi thực hiện rất nhiều xử lý hình ảnh và LockBits đã giúp tôi tiết kiệm rất nhiều công sức ở đó. Tôi chưa bao giờ sử dụng mã không an toàn ở bất kỳ nơi nào khác. –

+0

Tôi đã sử dụng nó đôi khi, nhưng hiếm khi ngay cả với interop. Chúng tôi gói 16 bit TWAIN và chỉ phải sử dụng IntPtr không mã không an toàn. Chỉ có nơi tôi đã nghĩ đến việc sử dụng nó là cho thao tác bitmap vì vậy tôi có thể ghim bộ nhớ. –

+1

Thời gian duy nhất tôi đã từng sử dụng nó cũng là để thao tác hình ảnh. Tôi đã phải đảo ngược một phần cụ thể của hình ảnh và thực hiện nó mà không có mã không an toàn có độ trễ đáng chú ý, nhưng với mã không an toàn nó đã được thực hiện trong <1 ms. –

2

Bạn nên sử dụng chúng nếu cần; hầu hết điều này sẽ xảy ra khi xử lý một số tình huống phức tạp (ví dụ khi tôi viết một trình bao bọc được quản lý cho DPAPI trong .NET 1.0) nhưng đôi khi nó có thể cải thiện hiệu suất (sau khi lược tả!) bằng cách sử dụng stackalloc hoặc tương tự.

Đó là khuyến cáo của Microsoft trong nhiều như họ là những nhà thiết kế của C#, và họ đưa ra quyết định thêm khả năng để viết unsafe mã trong đó. Bạn có thể thấy từ việc lựa chọn từ khóa và yêu cầu để phân định các phương pháp/lớp học mà bạn viết nó bằng cách sử dụng từ khóa, rằng nó không được thiết kế để trở thành sự lựa chọn thực tế.

1

khóa học không phải là "được đề xuất", đó là lý do tại sao nó được gắn nhãn "không an toàn". Nhưng đừng để điều đó làm bạn sợ hãi. Mặc dù, nó sẽ làm cho bạn nhìn hai lần vào mã của bạn. Có lẽ có một cách quản lý để làm điều đó?

3

Unsafe code là chức năng được hỗ trợ đầy đủ của .NET CLR. Những lợi ích là hiệu suất và khả năng tương thích với mã nhị phân. Thời gian chạy là một hộp cát giúp bạn không bị rơi và cháy, nhưng đi kèm với một chi phí. Trong các tình huống mà bạn đang thực hiện các hoạt động cực kỳ chuyên sâu chống lại các đốm màu lớn trong bộ nhớ, ví dụ như thao tác hình ảnh, nó sẽ nhanh hơn để bước ra ngoài sự an toàn bình thường mà thời gian chạy cung cấp.

Điều đó đã được nói, tôi nghĩ rằng nhất những người ở đây sẽ nói "không làm điều đó". Phần lớn các nhà phát triển .NET sẽ không chạy vào một trường hợp trong các hoạt động bình thường của họ mà chỉ có thể được giải quyết bằng cách sử dụng mã không an toàn.

19

Nếu bạn có.

Giả sử bạn cần màu giả một hình ảnh có thang độ xám lớn, có kích thước 2000x2000 pixel. Trước tiên hãy viết phiên bản 'an toàn' bằng cách sử dụng GetPixel()SetPixel(). Nếu nó hoạt động, tuyệt vời, hãy tiếp tục. nếu điều đó chứng minh là quá chậm, bạn có thể cần phải nhận được ở các bit thực tế tạo nên hình ảnh (quên về ma trận màu vì lợi ích của ví dụ). Không có gì 'xấu' về việc sử dụng mã không an toàn, nhưng nó làm tăng thêm sự phức tạp cho dự án và do đó sẽ chỉ được sử dụng khi cần thiết.

+0

Lưu ý rằng việc xử lý hình ảnh có lẽ là cách sử dụng phổ biến nhất trong việc sử dụng mã không an toàn để tăng hiệu suất. Tuy nhiên, tôi cho rằng bạn nên sử dụng 'LockBits' chỉ trước khi đi đến 'unsafe' và' LockBits' tức là bước trung bình. – TheLethalCoder

+0

@TheLethalCoder: eh, có thể, nếu bạn không có kinh nghiệm. Một khi bạn đã hoàn thành công việc trước khi bạn biết nó có cần thiết hay không.Nó không phải là một tối ưu hóa sớm. –

+1

Tôi không thể đồng ý nhiều hơn. Xem xét chuyển đổi hình ảnh từ nền tảng này sang nền tảng khác, mỗi hình ảnh sử dụng các lớp và định dạng khác nhau để thể hiện hình ảnh. Bạn có thể sao chép ra một mảng, lặp qua nó để chuyển đổi, sau đó sao chép nó vào mục tiêu, hoặc ... bạn có thể sử dụng con trỏ để sao chép và chuyển đổi trong một lần, từ nguồn đến đích. Cách "an toàn" là không hiệu quả nếu bạn biết bạn đang làm gì. – Daniel

3

Tôi đã sử dụng mã không an toàn để sử dụng mạo danh để cho phép các dịch vụ truy cập vào chia sẻ mạng. Nó không phải là một vấn đề nếu bạn biết những gì bạn đang làm.

1

sử dụng mã không an toàn là như quên benenfits của Net Framework, tôi sử dụng chúng một lần để cấu trúc cũ thời tạo ra như ngăn xếp và các công cụ nhưng đó là chỉ dành cho trường học, hiện nay tôi havent có nhu cầu sử dụng chúng.

1

Làm điều đó nếu nó làm cho mã của bạn ngắn hơn và rõ ràng hơn.

"Theo dõi khuynh hướng của bạn liên quan đến việc cảnh sát vòng quanh góc." WSM

+0

Con trỏ phải làm gì với việc lặp lại chính mình ...? –

+0

sẽ không ném một mã khóa không an toàn vào ứng dụng .NET an toàn khác. Tôi nghĩ rằng bạn có thể nhầm C/C++, nhiều người đến từ đó cau mày trên mã được quản lý rất nhiều bởi vì họ nghĩ rằng nó chậm hơn. Đó là trong các phiên bản trước đó, nhưng ngày nay nhanh hơn và đáng tin cậy hơn cả mã gốc, đặc biệt là trên các hệ thống Linux, nơi hầu như không có bloat trong đó, trên thực tế, ứng dụng .NET của tôi chạy nhanh hơn các ứng dụng C++ của tôi. – osirisgothra

2

Reinterpretive như phôi không được cung cấp bởi BitConverter.
Cụ thể chuyển đổi một unint thành một hàm int cho hàm băm mà tất cả những gì bạn quan tâm là các bit.

Sử dụng một số hữu ích, cũng lý luận về các hàm thành ngữ c hoặc C++ trên cấu trúc mà bạn cần xử lý chúng dưới dạng byte * có chiều dài nổi tiếng, một lần nữa hữu ích nhất cho băm.

Nối tiếp nhị phân cực nhanh (rất cụ thể) trong cấu trúc bộ nhớ (bằng cách thực hiện nó cho một mảng) mặc dù thành thật, tốt hơn là chỉ cần thả xuống C++/CLI. Nó phải được cho rằng trong nhiều trường hợp nhiệm vụ đòi hỏi con trỏ thường có thể được giải quyết tốt hơn bằng cách làm nó trong C + +/CLI và sau đó nhập khẩu này vào bạn C# dự án như là một dll. Nó không thay đổi cho dù mã là 'an toàn' hay không nhưng nó làm cho một loạt các chức năng hữu ích cho hoạt động trên các cấu trúc dựa trên con trỏ dễ tiếp cận hơn. Nó cũng cho phép bạn mess với các loại chung hoặc enums nếu bạn thực sự muốn.

Khả năng hầu hết các nhà phát triển cần thực hiện điều này thực sự là điều khiển từ xa. Hữu ích khi bạn cần đến nó mặc dù ...

5

tôi sẽ nói những vấn đề chính là: -

  • Mã không an toàn là không thể xác minh được. Điều này có nghĩa là mã có thể chỉ được người dùng chạy từ ngữ cảnh hoàn toàn đáng tin cậy, do đó nếu bạn cần người dùng chạy mã từ bất kỳ nơi nào ít hơn hoàn toàn đáng tin cậy (ví dụ: chia sẻ mạng không được định cấu hình), bạn đang hơi say.
  • Thiếu kiểm chứng (hm không chắc chắn nếu đó thực sự là một từ) cũng có nghĩa là bạn có thể có khả năng mess lên bộ nhớ trong chương trình của bạn. Bạn đang có khả năng đưa toàn bộ các lớp lỗi trở lại ứng dụng của bạn - tràn bộ đệm, con trỏ lơ lửng, yada yada yuck yuck. chưa kể đến khả năng có khả năng làm hỏng cấu trúc dữ liệu trong bộ nhớ mà không nhận ra khi nào con trỏ của bạn trở nên lạ.
  • Nếu bạn muốn mã không an toàn của mình truy cập các đối tượng được quản lý, bạn cần 'ghim' chúng. Điều này có nghĩa là GC không được phép di chuyển đối tượng của bạn xung quanh trong bộ nhớ và do đó heap được quản lý có thể bị phân mảnh. Điều này có ý nghĩa hiệu suất; do đó nó luôn luôn quan trọng để xác định xem bất kỳ lợi nhuận perf có tiềm năng không phải là lớn hơn bởi vấn đề này.
  • Mã của bạn trở nên khó khăn hơn để hiểu cho các lập trình viên không được sử dụng để tiếp cận không được quản lý. Sau đó, họ có thể phải chịu trách nhiệm hơn khi quay chân với một số mã không an toàn 'tự do' cung cấp cho họ.
  • Bạn có thể viết mã không an toàn loại; điều này thực sự thay vì loại bỏ rất nhiều lợi thế của một ngôn ngữ được quản lý mờ đẹp ấm áp. Bây giờ bạn có thể gặp phải vấn đề an toàn loại khủng khiếp. Tại sao lại lùi bước đó?
  • Nó làm cho mã của bạn uglier.

Tôi chắc chắn có nhiều thứ có thể được thêm vào danh sách; nói chung, như những người khác đã nói - tránh trừ khi bạn phải làm như vậy. Ví dụ gọi một phương thức không được quản lý thông qua p/invoke yêu cầu một số con trỏ đặc biệt. Thậm chí sau đó, marshaller chủ yếu sẽ ngăn chặn sự cần thiết cho nó, chủ yếu.

'Người đàn ông' cũng nói tránh trừ khi cần thiết, về cơ bản.

Oh, bài viết tốt đẹp về ghim here on MSDN bằng cách này.

+0

hãy nhớ rằng thông thường (dưới sự tin cậy đầy đủ) bộ xác minh bị vô hiệu hóa có nghĩa là 'an toàn' của bạn thực sự phụ thuộc vào trình biên dịch để thực hiện công việc của nó một cách chính xác. Về cơ bản bạn có thể tạo IL thực hiện các hành động không an toàn –

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