Console.WriteLine () i potrzeba tak wielu przeciążeń argumentów?

87

Przeglądałem dokumentację i zauważyłem, że Console.WriteLine()metoda ma kilka przeciążeń. W szczególności moja ciekawość i częściowe zmieszanie dotyczy tych:

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);

Wydaje się zbędne. Jaka jest potrzeba pozostałych czterech przeciążeń oprócz pierwszego? Pierwsza metoda jest w stanie zrobić wszystko, co inne metody. Czy jest jakiś problem z wydajnością, z którym próbowali sobie poradzić, zapewniając dodatkowe przeciążenia, które obsługują do czterech argumentów (ostatni)? Czy narzut związany z przechodzeniem przez tablicę maksymalnie czterech argumentów jest wystarczająco duży, aby zapewnić potrzebę tych przeciążeń?

BK
źródło

Odpowiedzi:

102

Generalnie masz rację, że pierwsze przeciążenie może wystarczyć dla innych przeciążeń. Nie jest to jednak prawdą, ponieważ paramssłowa kluczowego nie można używać w przypadkach pośrednich, takich jak wiązanie grupy metod. Na przykład

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

paramsPrzeciążenie nie zaspokoi tę sprawę, to będzie działać tylko wtedy, gdy ta szczególna przeciążenie jest obecny

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

To jednak dość ezoteryczny przypadek. Ważniejsze powody są następujące

  1. Nie każdy język CLI jest wymagany do obsługi paramssłowa kluczowego. Posiadanie przeciążeń zmniejsza obciążenie tych języków, eliminując potrzebę ręcznego tworzenia tablicy dla prostego wywołania WriteLine`
  2. Występ. Wywołanie paramsprzeciążenia zmusza obiekt wywołujący do przydzielenia tablicy, nawet jeśli jest to wykonywane niejawnie przez kompilator. Przydziały w .Net są tanie, ale nie darmowe. Takie drobne rzeczy szybko się sumują, zwłaszcza w przypadku powszechnie nazywanych metod, takich jak Console.WriteLine. Posiadanie innych przeciążeń pozwala na uniknięcie tej alokacji w typowych przypadkach
JaredPar
źródło
1
Myślałem o przypadku grupy metod w mojej odpowiedzi, ale jestem prawie pewien, że konwersja grupy metod nie została wprowadzona do C # 2.0, podczas gdy przeciążenia WriteLine sięgają co najmniej 1.1.
jaket
@jaket Wygodna składnia została dodana w C # 2.0. Ale ten sam punkt ma zastosowanie w przypadku korzystania wyraźne new E(Console.WriteLine)w C # 1.
CodesInChaos
5
Czy alokacja tablic jest w ogóle zauważalna przy powolnym działaniu Console.WriteLine?
Bryan Boettcher,
3
@insta to nie prędkość, ale nagromadzenie przydziałów jest problemem. GC jest tani, nie darmowy, aw skomplikowanych aplikacjach GC jest często dominującym czynnikiem wydajności. Zatrzymanie powszechnych źródeł niepotrzebnych przydziałów jest ważne dla wydajności
JaredPar
38

Przeciążenia są dla wygody programów C ++ / CLI, w których słowo kluczowe params nie istnieje.

jaket
źródło
1
To świetna odpowiedź na świetne pytanie, także IMHO.
Uwe Keim
1
Ahh ... to naprawdę ma sens. Wstyd mi, C ++ był moim pierwszym językiem. :)
BK
3
podstawy zaczynają się od pierwszego języka, sprytna odpowiedź kolego
dbw
4

Myślę, że wszyscy zapominacie, że parametry zostały wprowadzone w C # 2.0. W związku z tym przeciążenia istnieją również z platformy .NET 1.1, gdy nie było słowa kluczowego params.

Alan
źródło
jaket wspomniał o tym.
BK,
Przeczytaj jego komentarz do odpowiedzi JaredPara. To jeden z powodów, dla których nie uwzględnił wyjaśnienia parametrów w swojej odpowiedzi.
BK
@Noobacode, to prawda, że ​​tak zrobił, ale jest to wywnioskowane (jak to przeczytałem). Udzielam głosu za (za tak niewielką kwotę, jak to warte) tutaj Alan, ponieważ wyraził to w bardziej bezpośredni sposób.
Frank V
1
Z tego linku słowo kluczowe params istnieje również w .Net 1.1
Sriram Sakthivel
1

Myślę, że zadane pytanie ma już dobre i wyjaśniające odpowiedzi JaredPara i Jaketa, ale jedna kwestia może być również istotna,

Myślę, że łatwość użycia i swoboda dla użytkowników w korzystaniu z którejkolwiek z powyższych funkcji zgodnie z wymaganiami, w tym przypadku potrzeba jest znacznie wygodniejsza niż narzucanie im tworzenia tablicy, kiedy naprawdę tego nie potrzebują.

Myślę też o dawnych czasach, kiedy zacząłem uczyć się C # , prawie nie używałem tablic, a używanie tablic było dla mnie skomplikowanym zadaniem, przypisanie ich, a następnie zainicjowanie ich odpowiednimi wartościami było naprawdę skomplikowane i czasochłonne ...

dbw
źródło
3
Ale idea paramsjest taka, że ​​możesz albo przekazać tablicę, albo jawnie zapisać wszystkie argumenty. metodę taką jak void do(params object[])można wywołać za pomocą do(new object[] {"some", "stuff"}lub do("some", "stuff"). Nie sądzę, aby twój punkt widzenia miał tutaj zastosowanie.
Kroltan
2
@Kroltan, ale czy możesz powiedzieć, ilu początkujących naprawdę zna znaczenie paramsi wiedzą, czy paramstam jest, możesz przekazać zmienne oddzielone przecinkami.
dbw
1
@Kroltan Ja też nie wiedziałem, że użycie paramsmoże wyglądać tak przez długi czas iw sekcji pomocy wyświetlanej w Visual Studion, jeśli otrzymam array []jako argument, będę myśleć tak samo, aby podać tablicę jako argument ....
dbw
-3

To nie jest tak naprawdę kwestia wydajności jako takiej. Jednak zwiększenie użyteczności jest uzasadnionym powodem.

Poniższy kod da ci mały wgląd.

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;
        }
    }
}

Więcej informacji można znaleźć pod adresem: http://msdn.microsoft.com/en-us/library/aa324774(v=vs.71).aspx .

Deepak Sharma
źródło
9
Jak to zwiększa użyteczność? Pierwsza metoda może zrobić dokładnie to samo, co pozostałe cztery. Odsyłasz mnie do dokumentacji, a ja właśnie powiedziałem, że przeglądam dokumentację. Wiem, do czego służy ta metoda i jak z niej korzystać (w żadnym wypadku nie jestem nowy w C #). Ale dlaczego istnieje potrzeba dodatkowych przeciążeń oprócz pierwszego.
BK,
Myślę, że chodzi mu o to, że przekazując tylko jeden parametr, nie ma sensu tworzenie tablicy, która go przechowuje, i przekazywanie jej do metody - dlaczego nie przekazać tylko jednego parametru? To byłby mój powód, aby zrobić coś takiego
KingTravisG,
@ SCassidy1986: Nie tworzysz tablicy, gdy jest to metoda params, chyba że chcesz. Kompilator zrobi to automatycznie. O to chodzi w obu parametrach i na tym pytaniu.
Magus,