Những thiếu sót trong việc sử dụng các loại động trong C #


14

Gần đây tôi đã nghiên cứu thêm về các loại động trong C #. Với một số ví dụ tôi đã hiểu khi mã được biên dịch, nó không cần phải biên dịch lại mà có thể được thực thi trực tiếp.

Tôi cảm thấy sự linh hoạt được cung cấp bởi từ khóa để thực sự có thể thay đổi loại dữ liệu theo ý muốn là một lợi thế lớn .

Câu hỏi

bất kỳ thiếu sót cụ thể nào ngoài các lệnh gọi phương thức động sai mà đưa ra các ngoại lệ về thời gian chạy mà các nhà phát triển phải biết trước khi bắt đầu triển khai.


3
Trong C # 3, tôi luôn coi việc sử dụng các objectloại phôi trực tiếp là mùi mã. Trong hầu hết mọi trường hợp, điều đó có nghĩa là tôi hoặc một trong nhóm của tôi đã không thiết kế một giao diện phù hợp cho chức năng đó. Tôi đoán rằng nếu bây giờ tôi đang sử dụng C # 4, tôi cũng sẽ cảm thấy khá giống với cách sử dụng dynamic. Tôi có thể thấy trường hợp của nó nếu bạn làm mọi thứ động, nhưng trong trường hợp đó, bạn cũng có thể đã chọn một ngôn ngữ gõ động ở vị trí đầu tiên. * 8 ')
Đánh dấu gian hàng

@MarkBooth +1 cho phối cảnh. Có an toàn không khi nói rằng việc triển khai cốt lõi bằng C # vẫn sẽ được đánh máy mạnh mẽ mặc dù đã giới thiệu các loại động trong 4.0
Karthik Sreenivasan

Sử dụng dynamictrong C # có nghĩa là bạn không phải bỏ qua IronPython nếu tất cả những gì bạn cần là một số cách gõ động cho một phần nhỏ mã của bạn. Đối với người đánh giá biểu thức, tôi đã thành công lớn khi sử dụng dynamicđể biểu diễn các toán hạng của biểu thức và kết quả từ đánh giá.
Ed James

@EdJames - Nghe có vẻ như là một công dụng tuyệt vời dynamic, cộng với tôi ước tôi đã biết về IronPython khi tôi đang phát triển với .Net - nó có thể làm cho một số điều chúng tôi đang cố gắng làm dễ dàng hơn nhiều .
Đánh dấu gian hàng

Câu trả lời:


16

Thiếu sót chính là bạn vứt bỏ một trong những thuộc tính chính (không nhất thiết là lợi thế) của C # - rằng nó được gõ tĩnh (và đối với hầu hết các loại phần an toàn).

Vấn đề với kiểu gõ động là nó thường ẩn các lỗi sẽ được tiết lộ trong quá trình biên dịch. Lỗi như vậy sau đó chỉ xuất hiện trong thời gian chạy, điều này tất nhiên làm cho nó khó phát hiện hơn nhiều.

Có rất ít lý do để IMO sử dụng kiểu gõ động trong C #, lý do chính là sự hợp tác với các ngôn ngữ được gõ động (đó là AFAIK, lý do động được đưa ra ngay từ đầu).

Nếu bạn muốn thực hiện lập trình gõ hoàn toàn động, bạn nên xem một số ngôn ngữ được thiết kế là động, không hack C # để năng động. Bạn có thể sử dụng ví dụ IronPython nếu bạn muốn sử dụng các thư viện .Net


+1 cho IronPython. Điều này có nghĩa là điều này có thể dẫn đến các vấn đề bảo trì trong thời gian dài.
Karthik Sreenivasan

6
Điều quan trọng dynamicmang đến cho bạn là khả năng nâng cấp một đối tượng thành loại thực tế của nó mà không có bất kỳ loại hack phản chiếu nào. Ví dụ: nếu Base foo = new Derived();và có hai phương thức quá tải Moo(Base x)Moo(Derived x)sau đó Moo(foo)gọi Moo(Base x), nhưng Moo((dynamic)foo)gọi Moo(Derived x). Điều này dẫn đến việc triển khai mẫu Khách truy cập rất tao nhã, ví dụ: code.logos.com/blog/2010/03/ và nói chung là một kỹ thuật rất mạnh mẽ.

@TheMouthofaCow Rất tốt, chắc chắn cũng có một vài cách sử dụng "hợp pháp" khác cho năng động, tuy nhiên đây là một số ít và rất xa (và bạn chắc chắn phải biết những gì bạn đang làm trước khi thử một cái gì đó như thế này).
Matěj Zábský

@TheMouthofaCow Một mẫu thiết kế tương đối mới (Mẫu khách truy cập) cần lưu ý. Cảm ơn.
Karthik Sreenivasan

1
Vâng, nó khá tuyệt. Tôi đã đưa ra nó một cách độc lập vào tuần trước, vì vậy thật tuyệt khi thấy rằng đó là một ý tưởng được chấp nhận đã được áp dụng vào kho vũ khí C #.

9

Tôi không chắc chắn bạn đang tìm kiếm loại thiếu sót nào, nhưng nếu bạn muốn biết về các tính năng hoạt động với kiểu gõ tĩnh, nhưng không phải với dynamic, có rất ít:

  1. Các phương pháp mở rộng không hoạt động. Đây có lẽ là một trong những lớn nhất. Nếu bạn có dynamic collection, bạn không thể sử dụng mã như collection.Distinct(). Đó là bởi vì các phương thức mở rộng có sẵn phụ thuộc vào không gian tên usingvà DLR không có cách nào để biết chúng.

    Như một giải pháp thay thế, bạn có thể gọi phương thức như thể đó là phương thức tĩnh bình thường : Enumerable.Distinct(collection). Hoặc bạn có thể thay đổi loại của bộ sưu tập thành một cái gì đó như IEnumerable<dynamic>.

  2. foreachyêu cầu IEnumerable. Trong C # bình thường, foreachlà dựa trên mô hình. Đó là, nó không yêu cầu bất kỳ giao diện cụ thể nào, chỉ là một GetEnumerator()phương thức trả về đối tượng phù hợp. Nếu bạn sử dụng foreachtrên dynamic, việc thực hiện IEnumerablelà bắt buộc. Nhưng vì lý do cho hành vi này là C # 1.0 không có chung chung, nên "thiếu sót" này không liên quan nhiều.


+1 cho phương thức tiện ích mở rộng. Điều này cũng áp dụng cho các toán tử truy vấn LINQ khác như GroupBy ()?
Karthik Sreenivasan

2
@Karthik: Có. Tôi nghĩ rằng các phương pháp mở rộng là biên dịch đường cú pháp thời gian, do đó thực tế là chúng không được giải quyết.

@TheMouthofaCow +1 - Cảm ơn bạn đã làm rõ.
Karthik Sreenivasan

1
Tôi đồng ý với các phương thức mở rộng, tức là cách động không thể tìm ra các phương thức mở rộng trong thời gian chạy nhưng tôi không thể làm theo bộ sưu tập động mà bạn đã giải thích.
Karthik Sreenivasan

7

Vấn đề với các loại động (không phải là các biến được khai báo là động) trong .net là chúng không có nhiều chức năng có sẵn cho các loại tĩnh.

  • không có sự phản ánh (bạn có thể lặp lại các thành viên nhưng không nhiều thứ khác)
  • không có siêu dữ liệu (có xác thực của bạn trong các trang web dữ liệu động / mvc)
  • hoàn toàn không kiểm tra tại thời điểm biên dịch (mọi lỗi chính tả sẽ không bị bắt)
  • vì đây là một tính năng mạnh mẽ nên các noobs có thể có xu hướng lạm dụng / lạm dụng / hiểu sai về nó
  • mã được viết với các kiểu động có xu hướng khó bảo trì và khó cấu trúc lại
  • bởi vì gõ vịt và các tính năng khác, các bậc thầy có thể viết mã không thể đọc được cho bất kỳ ai khác

Vì vậy, đừng viết mã với các loại động trừ khi bạn biết bạn đang làm gì.


6

dynamicchỉ là một đánh dấu objectnó hộp các loại giá trị.

Điều này có thể có ý nghĩa về hiệu suất, nhưng vì tôi đã sử dụng kiểu gõ tĩnh trong mã hiệu suất quan trọng dù sao đi nữa, đó có lẽ không phải là vấn đề trong thực tế.

Quyền anh này cũng can thiệp vào các loại giá trị đột biến. Nếu bạn sửa đổi chúng bằng dynamic, bạn chỉ sửa đổi bản sao được đóng hộp. Nhưng vì bạn không nên sử dụng các loại giá trị có thể thay đổi ở vị trí đầu tiên, đây cũng không phải là vấn đề lớn.


+1 tôi chắc chắn đồng ý. Gõ tĩnh sẽ là cách tiếp cận tốt nhất cho mã quan trọng hiệu năng.
Karthik Sreenivasan
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.