2015-12-30 19 views
16

Hãy xem xét một phương pháp như thế nàyQuy tắc cho các đối số được đặt tên là gì và tại sao?

void RegisterUser(string firstname, string lastname, int age); 

Tôi thích đặt tên một cách rõ ràng các đối số của phương pháp như thế này khi tôi gọi cho họ bởi vì nó dễ dàng cho một người nào đó để trộn lên firstnamelastname đối số. Tuy nhiên, nó không thực sự cần thiết cho age. Ví dụ, tôi nghĩ rằng điều này nên được OK từ một quan điểm rõ ràng.

RegisterUser(firstname: "John", lastname: "Smith", 25); 

Nhưng các lỗi sau đây sẽ được ném:

Đặt tên kỹ thuật số phải xuất hiện sau khi tất cả các đối cố định đã được chỉ định

Một điều thú vị là nếu chữ ký là

void RegisterUser(int age, string firstname, string lastname); 

sau đó gọi nó là foll ows KHÔNG ném một lỗi

RegisterUser(25, firstname: "John", lastname: "Smith"); 

Tại sao C# được thiết kế như thế này? Có một biến chứng cho trình biên dịch nếu kịch bản đầu tiên được cho phép không?

+0

Tôi chắc chắn ngay cả Python cũng thi hành thiết kế này. Tôi muốn nói đó là một nguyên tắc tốt nếu như Python thực thi một cái gì đó, nó có lẽ rất cần thiết. Và thứ tự của các đối số là rất cần thiết. – James

+0

@ James có, python thi hành thứ tự, nhưng trong C# sắp xếp các đối số là không cần thiết sau khi bạn bắt đầu đặt tên chúng một cách rõ ràng. Tuy nhiên, nếu bạn thực thi việc đặt hàng khi đặt tên một phần các đối số xảy ra thì nó sẽ giúp làm cho mã tự tài liệu hơn và (imo) sẽ làm cho việc hiểu mã dễ dàng hơn. –

+0

Tôi biết rằng bạn có thể bắt đầu đặt tên đối số một cách rõ ràng bằng cả hai ngôn ngữ. Có lẽ tôi đã nói ra điều đó trước đây. Bạn có thể đi từ các đối số được đặt hàng để đặt tên rõ ràng trong cùng một cuộc gọi hàm, nhưng bạn không thể quay lại. Nó giống nhau giữa hai ngôn ngữ. – James

Trả lời

14

trình biên dịch có thể tìm ra nhưng đối với chúng tôi, con người sẽ gần như không thể biết được nếu 25 tham chiếu đến tham số thứ nhất hoặc thứ 3. Đặc biệt là kể từ khi nó mở ra sự posibility của các đối số trộn. tại sao không phải là

MyFunction(firstname: "josh", 25, "smith", someotherargument: 42) 

Bạn giải thích điều này như thế nào, 25 tuổi và Smith cho họ? làm cho một quy tắc cho nó và một trình biên dịch có thể thực hiện nó. Nhưng điều gì sẽ hợp lý với con người. Mã obfuscation không nên dễ dàng

Một ngôn ngữ nên làm cho nó khó có thể thực hiện sai sót, không phải dễ dàng hơn

LƯU Ý: những điều kỳ lạ bắt đầu xảy ra với thứ tự nếu tranh luận trước đó được đặt tên sau. (giống như firstname & smith trong ví dụ của tôi) bởi vì sau đó trở thành một câu đố cho các đối số chưa được đặt tên của bạn được ánh xạ tới các đối số đúng. nó có thể được thực hiện, nhưng mã không nên tạo ra các câu đố

+0

Vì vậy, ý tưởng, sau đó , liệu việc đặt tên một số đối số và không phải là những người khác có khiến việc viết mã khó theo dõi dễ dàng không? Trong đoạn code mà tôi đã viết, nó gần như là khó chịu khi phải đặt tên cho đối số 'age'. Tại sao không cho phép nó, đặc biệt là nếu nó được thi hành rằng việc đặt tên một phần yêu cầu các đối số phải theo thứ tự hoặc một cái gì đó? –

+0

Tôi không chắc liệu điều này có phù hợp như một chỉnh sửa cho câu hỏi của tôi hay không, nhưng tại sao quy tắc sau không phù hợp. "trong trường hợp đối số chưa được đặt tên xuất hiện sau một đối số được đặt tên, thì trình biên dịch sẽ sử dụng thứ tự CHỈ để giải quyết đối số nào là".Điều này sẽ loại bỏ sự mơ hồ, và imo sẽ không làm cho mã khó đọc hơn nếu vài đối số được đặt tên không được đặt tên. –

6

Điều này là do bạn đặt tên đối số trình biên dịch ánh xạ nó dựa trên tên và bỏ qua định nghĩa hàm miễn là tất cả các đối số bắt buộc có mặt. Trong trường hợp của bạn, nó không biết 25 là gì. Đối với chúng tôi rằng có vẻ hợp lý rằng nó phải là tuổi tác, nhưng nếu bạn thay đổi ví dụ của bạn để:

void RegisterUser(string firstname, string lastname, int age = 0, int weight = 0); 

và sau đó nói:

RegisterUser(firstname: "John", lastname: "Smith", 25); 

Sau đó trình biên dịch không biết phải làm gì với điều đó 25. Cách thức gọi hàm này chủ yếu được sử dụng trong các hàm có nhiều giá trị mặc định, nơi bạn chỉ muốn đặt một vài hàm.

Khi không đặt tên đối số của bạn về cơ bản bạn nói rằng bạn tuân thủ nghiêm ngặt cấu trúc được đặt theo định nghĩa hàm.

+0

ah, điều này có ý nghĩa. Các quy tắc thay đổi ngay sau khi trình biên dịch thấy một đối số được đặt tên. Trước khi các đối số được đặt tên được tìm thấy: các vấn đề trật tự. Sau: lệnh không còn quan trọng nữa. Điều gì xảy ra nếu quy tắc là nếu chỉ có một số đối số được đặt tên, thì các đối số chưa được đặt tên theo sau, rằng các đối số phải theo thứ tự? –

+0

Đó sẽ là một mớ hỗn độn và làm cho cách mã ít dễ đọc hơn. Nếu tôi làm điều gì đó như thế này: Người dùng đăng ký (tên: "John", "Smith", 25); "Smith" sẽ là gì? Tên đầu tiên? –

+0

Với tôi, đó là ít nhất là rõ ràng như 'RegisterUser (" John "," Smith ", 25)'. Mặc dù, tôi thấy bạn đến từ đâu. –

1

Tất cả các đối số được đặt tên phải đến sau các đối số vị trí; bạn không thể chuyển đổi giữa các kiểu.Đối số vị trí luôn tham chiếu đến tham số tương ứng trong khai báo phương thức. Bạn không thể đặt đối số vị trí bỏ qua tham số bằng cách chỉ định tham số sau với đối số được đặt tên. Trình biên dịch sử dụng các biến cục bộ tạm thời. Sau đó nó sắp xếp lại các locals đó trong các khe đối số, tôi đoán là trình biên dịch liên kết bởi các đối số theo thứ tự cho đến khi nó tìm ra một đối số đã đặt tên, sau đó nó loại bỏ các đối số đã bị ràng buộc mà không có tên và sắp xếp lại khi trình biên dịch sử dụng các biến cục bộ tạm thời. Các liên kết với các phần còn lại của tên, ví dụ nó liên kết với 25 với tuổi firstname sau đó sắp xếp lại: "John", lastname: "Smith"

1

các mục đích sử dụng, với:

void M(int a = -1, int b = -1, int c = -1, int d = -1, int e = -1); 

làm ví dụ, là bạn có thể chỉ định một tập hợp con của những thông số tùy chọn bằng cách ký hiệu vị trí:

M(42, 28, 101); // gives a, b, and c in order; omits d and e 

hoặc bạn có thể sử dụng tên đối số:

M(d: 50, a: 42, c: 101); // gives three arguments in arbitrary order 

hoặc bạn có thể kết hợp chúng, nơi mà bạn bắt đầu với các đối số vị trí và sau đó chuyển sang tranh luận đặt tên:

M(42, 28, e: 65537, d: 50); // mixed notation OK 

Lý do cho sự hạn chế bạn đã gặp phải, đó là những thứ như:

M(c: 101, 7, 9, b: 28, 666); // ILLEGAL! 

sẽ gây nhầm lẫn.

Tôi có thể thấy bạn đề xuất giữ trật tự vị trí trong cuộc gọi cụ thể của bạn, và sau đó chỉ bao gồm tên của một số đối số, để rõ ràng. Tuy nhiên, nó xuất hiện rằng việc sử dụng này không phải là một ưu tiên cho các nhà thiết kế ngôn ngữ.

Tôi đề nghị bạn đặt tên tất cả các đối số khi lý do sử dụng kiểu được đặt tên là rõ ràng (trái ngược với yêu cầu chỉ định một tập con thích hợp của các tham số).

+1

Cảm ơn câu trả lời của bạn. "nó xuất hiện rằng việc sử dụng này không phải là một ưu tiên cho các nhà thiết kế ngôn ngữ." Tôi nghĩ là khôn ngoan. Trong khi đây là những gì tôi muốn sử dụng nó cho tôi không bao giờ nghĩ rằng nó không phải là lý do thực tế mà nó đã được thêm vào như là một tính năng. –

0

Tôi nghĩ rằng thiết kế ngôn ngữ trong trường hợp này sẽ dẫn đến đối số được đặt tên đầu tiên của bất kỳ hàm nào.

Sử dụng ví dụ của bạn

void RegisterUser(int age, string firstname, string lastname); 

và gọi đó là

RegisterUser(25, firstname: "John", lastname: "Smith"); 

Trước khi gặp phải đối số đầu tiên trình biên dịch không biết liệu chức năng này sẽ sử dụng bất kỳ đối số tên ở tất cả. Vì vậy nó là một giả định an toàn cho trình biên dịch để lập bản đồ tuần tự.

25:

Trình biên dịch được đối số đầu tiên và nếu nó là một tổ chức phi tên một sau đó nó sẽ được ánh xạ với đối số đầu tiên từ định nghĩa chức năng ngay lập tức.

firstname:

Ngay sau khi nó gặp nó lần đầu tiên được đặt tên tranh luận, mọi thứ sẽ thay đổi khi trình biên dịch hiện nay sẽ phải rà soát tất cả các đối số còn lại được đề cập trong định nghĩa hàm để lập bản đồ tên là tranh luận hiện nay.

Sau khi bản đồ thành công, đối số được đặt tên đầu tiên của nó là dấu vết của ánh xạ tuần tự đã bị hỏng. Và do đó nó không khả thi để cung cấp một đối số không được đặt tên cho trình biên dịch bây giờ là bây giờ nó không thể thiết lập nơi để ánh xạ nó.

Nếu bạn nghĩ nó nên nhớ đối số không được đặt tên cuối cùng và bắt đầu ánh xạ tuần tự từ đó thì lỗi đó dễ bị quá khi đối số được đặt tên vừa được xác định có thể tuần tự đúng.

lastname:

Và đối với các đối số tên đó là một làn gió.

Hy vọng điều này sẽ giúp ích:

1

Đối số vị trí được đặt trước đối số được đặt tên. Đối số vị trí luôn tham chiếu đến tham số tương ứng trong khai báo phương thức.

Giả sử phương pháp của tôi là:

void Dimensions(int height, int breadth , int length); 

và tôi gọi nó như

Dimensions(3, length: 12, 24); 

Trong trường hợp này:

'3' là tham số đầu tiên và đề cập đến chiều cao, nhưng '24' là tham số thứ ba và đề cập đến chiều dài, nhưng chúng tôi đã chỉ định giá trị của độ dài.

Vì vậy, có thể khắc phục trở ngại này, theo mặc định, kiểu C# là vị trí đối số vị trí khi bắt đầu cung cấp tham chiếu chính xác.

Ngoài ra nếu chúng tôi xác định tham số tùy chọn, việc cung cấp thông số vị trí ở cuối có thể dẫn đến kết quả sai.

+0

nó có vẻ là câu trả lời đúng –

+0

hoạt động khá tốt đối với tôi –

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