Tại sao là sử dụng hệ thống; không được coi là thực hành xấu?


47

Tôi có một nền tảng C ++ và tôi hoàn toàn hiểu và đồng ý với các câu trả lời cho câu hỏi này: Tại sao là sử dụng không gian tên std; coi hành vi xấu?

Vì vậy, tôi rất ngạc nhiên rằng, bây giờ có một số kinh nghiệm với C #, tôi thấy điều hoàn toàn ngược lại ở đó: using Some.Namespace;được sử dụng ở mọi nơi. Bất cứ khi nào bạn bắt đầu sử dụng một loại, trước tiên bạn thêm một lệnh sử dụng cho không gian tên của nó (nếu nó chưa có). Tôi không thể nhớ đã thấy một .cs-file không bắt đầu bằng using System; using System.Collections.Generic; using X.Y.Z; etc.... Trong thực tế, nếu bạn thêm một tệp mới thông qua trình hướng dẫn Visual Studio, nó sẽ tự động thêm một số sử dụng các chỉ thị ở đó, mặc dù bạn có thể không cần đến chúng. Vì vậy, trong khi trong cộng đồng C ++ về cơ bản bạn bị nới lỏng, C # thậm chí còn khuyến khích làm điều này. Ít nhất đây là cách nó xuất hiện với tôi.

Bây giờ, tôi hiểu rằng việc sử dụng các lệnh trong C # và C ++ không hoàn toàn giống nhau. Ngoài ra, tôi hiểu rằng một trong những điều khó khăn nhất bạn có thể làm với using namespaceC ++, cụ thể là đặt nó trong tệp tiêu đề, không có đối tác khó chịu tương đương trong C # do thiếu khái niệm về tệp tiêu đề và #include.

Tuy nhiên, bất chấp sự khác biệt của chúng, việc sử dụng các lệnh trong C # và C ++ phục vụ cho cùng một mục đích, đó là chỉ phải gõ SomeTypemọi lúc, thay vì dài hơn nhiều Some.Namespace.SomeType(trong C ++ ::thay vì .). Và với cùng mục đích này, mối nguy hiểm dường như cũng giống tôi: đặt tên va chạm.

Trong trường hợp tốt nhất, điều này dẫn đến lỗi biên dịch, do đó bạn "chỉ" phải sửa nó. Trong trường hợp xấu nhất, nó vẫn biên dịch và mã âm thầm làm những việc khác với dự định của bạn. Vì vậy, câu hỏi của tôi là: Tại sao (rõ ràng) đang sử dụng các chỉ thị được coi là rất tệ trong C # và C ++?

Một số ý tưởng về một câu trả lời mà tôi có (mặc dù không ai trong số này thực sự làm tôi hài lòng):

  • Không gian tên có xu hướng dài hơn và được lồng trong C # nhiều hơn so với trong C ++ ( stdso với System.Collection.Generic). Vì vậy, có nhiều mong muốn hơn và đạt được nhiều hơn trong việc khử nhiễu mã theo cách này. Nhưng ngay cả khi điều này là đúng, đối số này chỉ áp dụng khi chúng ta nhìn vào các không gian tên tiêu chuẩn. Những cái tùy chỉnh có thể có bất kỳ tên ngắn nào bạn thích, trong cả C # và C ++.

  • Không gian tên dường như là "hạt mịn" hơn nhiều trong C # so với C ++. Như một ví dụ, trong C ++ toàn bộ thư viện chuẩn được chứa trong std(cộng với một số namespace lồng nhau nhỏ thích chrono) trong khi trong C # bạn có System.IO, System.Threading, System.Textvv Vì vậy, nguy cơ bị va chạm đặt tên là nhỏ hơn. Tuy nhiên, đây chỉ là một cảm giác ruột. Tôi thực sự không đếm được có bao nhiêu tên bạn "nhập" với using namespace stdusing System. Và một lần nữa, ngay cả khi điều này là đúng, đối số này chỉ áp dụng khi nhìn vào các không gian tên tiêu chuẩn. Những cái riêng của bạn có thể được thiết kế dạng hạt mịn như bạn muốn, trong cả C # và C ++.

Có nhiều tranh luận? Tôi đặc biệt quan tâm đến các sự kiện thực tế khó khăn (nếu có) và không có nhiều ý kiến.


2
@Timo OP rõ ràng không hỏi về ô nhiễm tiêu đề.
Konrad Rudolph

1
Tôi cho rằng đó là vì không có sự cạnh tranh nào cho không gian tên toàn cầu ở cùng mức độ có trong C ++ (chủ yếu là do thư viện chuẩn C). Nhưng tôi chờ đợi câu trả lời của những người hiểu rõ nhất.
Wyck

2
@ThomasWeller Trong C ++ thì rõ ràng. Trong C # hãy xem xét một phương thức mở rộng với phương thức Ext(this T t, long l)được gọi thông qua t.Ext(0). Nếu sau đó bạn thêm một không gian tên khác có chứa một phương thức mở rộng Ext(this T t, int i), thì nó sẽ được gọi thay thế. Nhưng tôi không phải là chuyên gia về C # (chưa).
sebrockm

2
@Franck ngay cả khi tôi đã cho bạn điểm đó, thì lập luận tương tự cũng áp dụng cho C ++, đẩy thêm câu hỏi của tôi về việc không thấy sự khác biệt giữa C ++ và C #
sebrockm

3
@Franck C ++ sẽ ném lỗi biên dịch cho bạn trong trường hợp không rõ ràng. Cũng như C #.
Timo

Câu trả lời:


28

Tại sao là sử dụng hệ thống; không được coi là thực hành xấu?

"sử dụng hệ thống;" không phải là phổ biến không được coi là một thực hành xấu. Xem ví dụ: Tại sao bạn không sử dụng chỉ thị 'bằng cách sử dụng' trong C #?

Nhưng có thể đúng là nó không được coi là xấu như using namespace std. Có lẽ vì:

  1. C # không có tệp tiêu đề. Việc "bao gồm" một tệp nguồn C # vào một tệp khác bằng bộ xử lý trước là không phổ biến.

  2. stdkhông gian tên gần như bằng phẳng tức là gần như tất cả các hàm, kiểu và biến thư viện tiêu chuẩn nằm trong đó (có một vài ngoại lệ như không gian tên phụ của hệ thống tập tin). Nó chứa số lượng định danh rất, rất cao. Theo hiểu biết của tôi, Systemchứa ít tên hơn, và thay vào đó có nhiều không gian tên phụ hơn.

  3. Trong C #, không có hàm hoặc biến toàn cục. Do đó, số lượng định danh toàn cầu thường khá nhỏ so với C ++ có số đó: Ngoài ra, thông thường sử dụng các thư viện C (thường là gián tiếp) không có không gian tên và do đó đặt tất cả tên của chúng vào toàn cầu không gian tên.

  4. Theo tôi biết, C # không có tra cứu phụ thuộc đối số. ADL kết hợp với ẩn tên, quá tải, vv có thể tạo ra các trường hợp trong đó một số chương trình không bị ảnh hưởng bởi xung đột tên, trong khi các chương trình khác bị ảnh hưởng tinh vi và việc bắt tất cả các trường hợp góc là không khả thi khi thử nghiệm.

Vì những khác biệt này, nên sử dụng hệ thống; có cơ hội xung đột tên thấp hơn using namespace std.


Ngoài ra, "nhập" không gian tên là một cách, một quy ước tự tồn tại: Nếu thông thường là nhập một không gian tên tiêu chuẩn, thì các lập trình viên sẽ cố gắng tránh chọn tên từ không gian tên đó cho các định danh riêng của họ, giúp giảm các vấn đề với quy ước như vậy.

Nếu việc nhập như vậy được coi là một thực tiễn xấu, thì các lập trình viên sẽ ít có khả năng thậm chí cố gắng tránh sự xung đột như vậy với các không gian tên được nhập. Như vậy, các quy ước có xu hướng bị phân cực cho hoặc chống lại thực tiễn, ngay cả khi các trọng số của các đối số giữa các lựa chọn ban đầu là tinh tế.


3
Điều này chỉ xem xét những hạn chế tiềm năng của việc mở các không gian tên. Đó là một khởi đầu, nhưng tôi nghĩ chúng ta cũng cần xem xét các ưu điểm: trong trường hợp C ++, trong hầu hết các trường hợp, nó tiết kiệm được năm ký tự ( std::). Trong C #, nó đáng kể hơn ( System.chỉ có 7 ký tự, nhưng các không gian tên lồng nhau khác có nhiều ký tự hơn và viết chúng ra khắp mọi nơi sẽ khiến mã hoàn toàn không thể đọc được).
Konrad Rudolph

Có phải cũng không phải là trường hợp độ phân giải quá tải C # tốt hơn so với C ++ và rất nhiều sự mơ hồ được rút ra thông qua các lỗi biên dịch? (Không có nghĩa là một lời chỉ trích câu trả lời của bạn có vẻ có thẩm quyền.)
Bathsheba

3
@KonradRudolph Nếu các nhược điểm được coi là đáng kể và số lượng gõ bằng nhau (so với số lượng gõ std::), nó sẽ không phải là kiểu điển hình để sử dụng using Sys = System;thay vì không gian tên gây ô nhiễm không bí danh using?
eerorika

2
@Bathsheba liên quan đến "có thẩm quyền", tôi muốn từ chối rằng tôi biết rất ít về C # và câu trả lời của tôi dựa trên kiến ​​thức về C ++ và một vài tìm kiếm trên google về C #. Vì vậy, tôi đánh giá cao nếu ai đó thực tế kiểm tra các phần C # :)
eerorika

2
Về phần ADL: C # có các phương thức mở rộng. Đây là một thiết kế khác với ADL, nhưng chúng có chung các vấn đề liên quan đến xung đột đặt tên.
Timo

-2

Tuy nhiên, bất chấp sự khác biệt của chúng, việc sử dụng các lệnh trong C # và C ++ phục vụ cho cùng một mục đích, điều này chỉ phải gõ một số Kiểu mọi lúc, thay vì một số dài hơn.Namespace.SomeType (trong C ++ với :: thay vì.). Và với cùng mục đích này, mối nguy hiểm cũng xuất hiện trong tôi: đặt tên cho các vụ va chạm.

Có, nhưng bạn đã không xuất khẩu mối nguy hiểm đó (đọc: buộc người khác phải đối phó với nó), vì:

Bây giờ, tôi hiểu rằng việc sử dụng các lệnh trong C # và C ++ không hoàn toàn giống nhau. Ngoài ra, tôi hiểu rằng một trong những điều khó chịu nhất bạn có thể làm khi sử dụng không gian tên trong C ++, cụ thể là đặt nó trong tệp tiêu đề, không có tương đương trong C # do thiếu khái niệm về tệp tiêu đề và #include.

Vì vậy, nó là một loại khác nhau của điều.

Ngoài ra, C ++ không được "thiết kế" để được phát triển trong IDE giống như cách C #. C # về cơ bản luôn được viết trong Visual Studio với Intellisense và không có gì. Nó được thiết kế để được sử dụng theo cách đó, bởi những người đã tạo ra nó. Bất kể có bao nhiêu người sử dụng IDE để phát triển trong C ++, nó không được thiết kế với trường hợp sử dụng đó như một mối quan tâm lớn.

Không gian tên dường như là "hạt mịn" hơn nhiều trong C # so với C ++.

Vâng đó cũng vậy. using namespace stdusing System.Collection.Generickhông thể so sánh được.

Vì vậy, đừng so sánh chúng!


2
Điều này không trả lời mối quan tâm của OP, rõ ràng không phải về việc mở các không gian tên trong các tiêu đề, mà trong các tệp thực hiện .
Konrad Rudolph

2
@KonradRudolph Lời khuyên nên tránh using namespace stdtrong C ++ chủ yếu là về các tệp tiêu đề. Câu trả lời điều này không áp dụng trong C #.
Tiểu hành tinh có cánh

8
@AsteroidsWithWings lời khuyên nên tránh using namespace stdchắc chắn không phải là chủ yếu về tiêu đề. Sử dụng nó trong tiêu đề là nguy hiểm. Sử dụng nó trong việc thực hiện của bạn được khuyến khích chống lại.
Tommy Andersen

1
Lời khuyên nên tránh using namespace ...trong c ++ là về cách tránh va chạm đặt tên, usingchỉ thị trong C # cũng giới thiệu khả năng đặt tên va chạm, vậy thì tại sao không tránh nó? Mặc dù có thực hiện khác nhau.
Tommy Andersen

@TommyAndersen, thật khó để giải quyết xung đột như vậy nếu nó xảy ra? Phải mất một giây. Vì các usingkhai báo C # trên mỗi tệp xác định loại / lớp đơn và loại thường phải thực hiện với một tập hợp các khái niệm miền ứng dụng tương đối hẹp (lý tưởng, nguyên tắc trách nhiệm duy nhất) nên xác suất của các xung đột không gian tên đó là rất thấp. Nhưng khi xảy ra dễ dàng sửa chữa. Các công cụ phát triển .NET / IDE thông thường giúp bạn rất nhiều với điều đó. Hãy xem xét toàn bộ hệ sinh thái phát triển được thiết kế để giúp bạn làm việc hiệu quả hơn bằng cách kết hợp tốt nhất của nhiều hoạt động phát triển
AKornich
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.