Console.WriteLine () và sự cần thiết của quá nhiều đối số?


87

Tôi đang duyệt qua tài liệu và nhận thấy rằng Console.WriteLine()phương pháp có một số quá tải. Đặc biệt, sự tò mò và một phần bối rối của tôi liên quan đến những điều này:

public static void WriteLine(string format, params object[] arg);
public static void WriteLine(string format, object arg0);
public static void WriteLine(string format, object arg0, object arg1);
public static void WriteLine(string format, object arg0, object arg1, object arg2);
public static void WriteLine(string format, object arg0, object arg1, object arg2, object arg3);

Nó có vẻ thừa. Sự cần thiết của bốn quá tải khác trên đầu tiên là gì? Phương pháp đầu tiên có thể làm mọi thứ mà các phương pháp khác có thể làm. Có mối quan tâm về hiệu suất mà họ đang cố gắng giải quyết bằng cách cung cấp các quá tải bổ sung, xử lý tối đa bốn đối số (đối số cuối cùng) không? Chi phí của việc duyệt qua một mảng lên đến bốn đối số có đủ lớn để đáp ứng nhu cầu về các quá tải này không?

Câu trả lời:


102

Nói chung, bạn đúng rằng quá tải đầu tiên có thể đủ cho các quá tải khác. Tuy nhiên, điều này không hoàn toàn đúng vì paramstừ khóa không thể được sử dụng cho các trường hợp gián tiếp như ràng buộc nhóm phương thức. Ví dụ

delegate void E(string format, object o1);
E e = Console.WriteLine;

Quá paramstải sẽ không đáp ứng trường hợp này, nó sẽ chỉ hoạt động khi có hiện tượng quá tải cụ thể này

public static void WriteLine(string format, object arg0);

Đó là một trường hợp khá bí truyền. Những lý do quan trọng hơn là sau đây

  1. Không phải mọi ngôn ngữ CLI đều được yêu cầu để hỗ trợ paramstừ khóa. Việc có quá tải làm giảm gánh nặng cho các ngôn ngữ đó bằng cách loại bỏ nhu cầu tạo một mảng theo cách thủ công cho một lệnh gọi WriteLine` đơn giản
  2. Hiệu suất. Việc gọi paramsquá tải buộc người gọi phải cấp phát một mảng, ngay cả khi nó được thực hiện ngầm bởi trình biên dịch. Phân bổ rẻ trong .Net nhưng không miễn phí. Những thứ nhỏ nhặt như thế này sẽ nhanh chóng cộng lại, đặc biệt là trên các phương thức thường được gọi là như Console.WriteLine. Việc có các quá tải khác cho phép các trường hợp phổ biến tránh được phân bổ này

1
Tôi đã nghĩ về trường hợp nhóm phương thức trong câu trả lời của mình nhưng tôi khá chắc chắn rằng việc chuyển đổi nhóm phương thức đã không được giới thiệu cho đến C # 2.0 trong khi quá tải WriteLine ngày trở lại ít nhất là 1.1.
— jaket

@jaket Cú pháp tiện lợi đã được thêm vào trong C # 2.0. Nhưng điểm này cũng áp dụng nếu bạn sử dụng rõ ràng new E(Console.WriteLine)trong C # 1.
— CodesInChaos

5
Việc phân bổ mảng thậm chí còn đáng chú ý với Console.WriteLine chậm như thế nào?
— Bryan Boettcher

3
@insta không phải là tốc độ mà là vấn đề tích lũy phân bổ. GC rẻ không miễn phí và trong các ứng dụng phức tạp, GC thường là yếu tố hiệu suất chi phối. Dừng nguồn chung của phân bổ không cần thiết là quan trọng đối với hiệu suất
— JaredPar

38

Quá tải là để thuận tiện cho các chương trình C ++ / CLI mà từ khóa params không tồn tại.


1
Đó là một câu trả lời tuyệt vời, cho một câu hỏi hay, IMHO, cũng vậy.
— Uwe Keim

1
Ahh ... điều đó thực sự có ý nghĩa. Thật xấu hổ cho tôi, C ++ là ngôn ngữ đầu tiên của tôi. :)
— BK

3
những điều cơ bản bắt đầu từ ngôn ngữ đầu tiên, thông minh câu trả lời bạn thân
— dBW

4

Tôi nghĩ rằng tất cả các bạn đang quên rằng các thông số đã được giới thiệu trong C # 2.0. Do đó, sự quá tải cũng tồn tại từ .NET 1.1, khi từ khóa params thì không.


jaket đã đề cập đến điều đó.
— BK

Đọc bình luận của anh ấy về câu trả lời của JaredPar. Đó là một trong những lý do tại sao anh ta không đưa lời giải thích tham số vào câu trả lời của mình.
— BK

@Noobacode, đúng là anh ấy đã làm nhưng đó là suy luận (như cách tôi đọc nó). Tôi dành một phiếu ủng hộ (với giá trị ít nhất có thể) cho Alan ở đây vì anh ấy đã nói điều đó trong một trang viên trực tiếp hơn.
— Frank V

1
Từ này liên kết params từ khóa tồn tại trong Net 1.1 cũng
— Sriram Sakthivel

1

Tôi nghĩ rằng câu hỏi được hỏi đã có câu trả lời hay và giải thích bởi JaredPar và jaket nhưng một điểm mà tôi nghĩ cũng có thể liên quan,

Tôi nghĩ rằng sự dễ sử dụng và tự do cho người dùng sử dụng bất kỳ chức năng nào ở trên tùy theo yêu cầu đó, có nghĩa là, có nhu cầu sẽ thuận tiện hơn nhiều thay vì áp đặt họ tạo một mảng, khi họ thực sự không yêu cầu.

Tôi cũng nghĩ về những ngày xưa khi tôi bắt đầu học C #, tôi hầu như không sử dụng mảng và sử dụng mảng là một nhiệm vụ phức tạp đối với tôi, để gán nó và sau đó khởi tạo chúng với các giá trị thích hợp thực sự rất phức tạp và mất thời gian ...


3
Nhưng ý tưởng paramslà bạn có thể truyền một mảng hoặc viết rõ ràng tất cả các đối số. một phương thức như void do(params object[])có thể được gọi với do(new object[] {"some", "stuff"}hoặc do("some", "stuff"). Tôi không nghĩ rằng quan điểm của bạn có thể áp dụng chính xác ở đây.
— Kroltan

2
@Kroltan nhưng bạn có thể cho biết có bao nhiêu người mới bắt đầu thực sự biết ý nghĩa của nó paramsvà họ biết nếu paramscó thì bạn có thể chuyển các biến dưới dạng dấu phẩy được phân tách.
— dbw

1
@Kroltan Tôi cũng không biết việc sử dụng paramscó thể như thế này trong một thời gian dài và trong phần trợ giúp được hiển thị trong Visual Studion nếu tôi nhận được array []là đối số, tôi cũng sẽ nghĩ như vậy để cung cấp mảng làm đối số ....
— dbw

-3

Điều này không thực sự dành cho vấn đề hiệu suất như vậy. Tuy nhiên, tăng khả năng sử dụng là một lý do xác đáng đằng sau nó.

Đoạn mã dưới đây, sẽ cung cấp cho bạn một cái nhìn sâu sắc.

public class TipCalculator {
    private const double tipRate = 0.18;
    public static int Main(string[] args) {
        double billTotal;
        if (args.Length == 0) {
            Console.WriteLine("usage: TIPCALC total");
            return 1;
        }
        else {
            try {
                billTotal = Double.Parse(args[0]);
            }
            catch(FormatException) {
                Console.WriteLine("usage: TIPCALC total");
                return 1;
            }
            double tip = billTotal * tipRate;
            Console.WriteLine();
            Console.WriteLine("Bill total:\t{0,8:c}", billTotal);
            Console.WriteLine("Tip total/rate:\t{0,8:c} ({1:p1})", tip, tipRate);
            Console.WriteLine(("").PadRight(24, '-'));
            Console.WriteLine("Grand total:\t{0,8:c}", billTotal + tip);
            return 0;
        }
    }
}

Vui lòng tham khảo liên kết: http://msdn.microsoft.com/en-us/library/aa324774(v=vs.71).aspx để biết thêm thông tin.


9
Làm thế nào để tăng khả năng sử dụng? Phương pháp đầu tiên có thể làm chính xác điều tương tự như bốn phương pháp còn lại. Bạn đang giới thiệu tôi với tài liệu, trong khi tôi chỉ nói rằng tôi đang xem qua tài liệu. Tôi biết phương pháp đó được sử dụng để làm gì và sử dụng như thế nào (tôi không phải là người mới sử dụng C #). Nhưng tại sao lại có nhu cầu quá tải bổ sung trên đầu trang.
— BK

Tôi nghĩ ý của anh ấy là, chỉ truyền một tham số, không có ích lợi gì khi tạo một mảng để giữ nó và truyền nó cho phương thức - tại sao không chỉ truyền một tham số? Đó sẽ là lý do để tôi làm điều gì đó như vậy
— KingTravisG Ngày

@ SCassidy1986: Bạn không tạo mảng khi đó là một phương thức params, trừ khi bạn muốn. Trình biên dịch sẽ tự động tạo một. Đó là điểm của cả params và câu hỏi này.
— Magus
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 cookie và Chính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.