Niedawno dowiedziałem się, że możesz stworzyć metodę o nieograniczonych parametrach, na przykład:
SomeMethod(params int[] numbers);
ale moje pytanie brzmi: jaka jest różnica między tym a tworzeniem metody, która otrzymuje listę lub tablicę?
SomeMethod(int[] numbers);
SomeMethod(List<int> numbers);
może ma to jakiś wpływ na wydajność? Nie do końca rozumiem lub nie widzę, w jaki sposób wolisz ten z nieograniczonymi parametrami.
Szybkie wyszukiwanie w Google nie pomogło, mam nadzieję, że możesz mi pomóc.
params
również, aby typ argumentu był tablicą. Jeśli potrzebujesz zużyć kolekcję inną niż tablica, bardziej sensowne może być podanieparams
zamiast niej argumentu.Console.Write
.Odpowiedzi:
Różnica pomiędzy
i
jest to, że M można nazwać tak:
lub tak:
ale N można wywoływać tylko w drugi sposób, a nie w pierwszy sposób.
Wpływ na wydajność jest taki, że niezależnie od tego, czy wywołujesz
M
w pierwszy, czy w drugi sposób, tak czy inaczej, utworzysz tablicę. Utworzenie tablicy ma wpływ na wydajność, ponieważ zajmuje zarówno czas, jak i pamięć. Pamiętaj, że wpływ na wydajność należy mierzyć w stosunku do celów wydajności; jest mało prawdopodobne, aby koszt stworzenia dodatkowej tablicy był czynnikiem bramkowym, który jest różnicą między sukcesem a porażką na rynku.Jest to czysta i całkowicie wygoda dla autora kodu, który wywołuje metodę; jest po prostu krótszy i łatwiejszy do napisania
zamiast pisać
Zapisuje tylko kilka naciśnięć klawiszy po stronie dzwoniącego. To wszystko.
Kilka pytań, które nie zadałeś, ale być może chciałbyś poznać odpowiedź na:
Metody pozwalające na przekazywanie zmiennej liczby argumentów po stronie wywołującej nazywane są variadic . Metody Params są sposobem, w jaki C # implementuje metody variadic.
W obliczu problemu rozwiązania problemu z przeciążeniem, C # rozważy zarówno formy „normalną”, jak i „rozwiniętą”, a forma „normalna” zawsze wygrywa, jeśli oba mają zastosowanie. Rozważmy na przykład:
i mamy telefon
Istnieją dwie możliwe możliwości. W „normalnej” formie wywołujemy
P
i przekazujemy zerowe odwołanie do tablicy. W formie „rozszerzonej” dzwonimyP(new object[] { null })
. W takim przypadku wygrywa normalna postać. Gdybyśmy mieli połączenie,P(null, null)
wówczas normalna forma nie ma zastosowania, a forma rozszerzona wygrywa domyślnie.Wyzwanie : załóżmy, że mamy
var s = new[] { "hello" };
telefonP(s);
. Opisz, co dzieje się na stronie połączenia i dlaczego. Możesz być zaskoczony!Wyzwanie : Załóżmy, że mamy jedno
void P(object x){}
i drugievoid P(params object[] x){}
. Co robiP(null)
i dlaczego?Wyzwanie : Załóżmy, że mamy jedno
void M(string x){}
i drugievoid M(params string[] x){}
. Co robiM(null)
i dlaczego? Czym różni się to od poprzedniego przypadku?źródło
P(null)
vs.P((object)null)
vs.P((object[])null)
- gdzie mogę znaleźć wyjaśnienie tej różnicy? Wydaje się, żenull
miał jakiś specjalny typ , który konwertuje na tablicę zamiast object (P(null)
), ale znajdź konwersję na ciąg znaków lub tablicę ciągów niejednoznacznych (M(null)
) ... co wydaje się bardzo dziwne, spodziewałby się, że będzie albo niejednoznaczny w obu przypadkach, albo wybierze wersja z jednym argumentem (której nie ma). Ale myślę, że bardziej chodzi o to, byparams
być jakoś ogólnym , jak na przykład uniwersalne odwołanie (&&
) w szablonach C ++, a zatem lepiej pasować (w Ch2, a nie w Ch3).object[]
sąobject
, ale nie wszystkieobject
sąobject[]
, dlategoobject[]
są bardziej szczegółowe.string[]
sąstring
”. W rzeczywistości NIEstring[]
sąstring
i NIEstring
sąstring[]
, więcstring
nie jest bardziej konkretny ani bardziej ogólny niżstring[]
, i pojawia się błąd dwuznaczności, gdy prosi się o wybór.object[]
sąobject
...object[]
są bardziej szczegółowe, więcP(null)
chodzi o bardziej konkretną tablicę, dzięki, tego mi brakowało. Znaleziono kilka reguł tutaj: docs.microsoft.com/en-us/dotnet/csharp/language-reference/…Właśnie zrobiłem mały prototyp. Wydaje się, że odpowiedzią
params
jest po prostu cukier składniowy do przekazywania w tablicy. To naprawdę nie jest niespodzianka. Stworzyłem dwie wersje tej samej metody, w których jedyną różnicą jest słowo kluczowe „params”. IL wygenerowana dla obu była identyczna, z tą różnicą, żeSystem.ParamArrayAttribute
zastosowano ją doparams
wersji.Co więcej, IL wygenerowana w miejscu wywołania była również taka sama między moim wywołaniem metody z ręcznym zadeklarowaniem
new int[]
a wywołaniem metody za pomocąparams
argumentów.Tak więc odpowiedzią wydaje się być „wygoda”. Wydaje się, że nie ma różnicy w wydajności. Zamiast tego możesz wywołać
params
funkcję z tablicą, więc nie jest to również zaskakujące. Sprowadza się to do tego, czy konsumentowi twojej metody łatwiej jest wywołać ją z dowolną liczbą parametrów (np.someMethod(1, 2, 3)
), Niż zawsze najpierw tworzyć kolekcję (npsomeMethod(new List<int>() { 1, 2, 3 } )
.).źródło
Funkcja nieograniczonej liczby parametrów oferuje następujące korzyści w wielu scenariuszach:
Oto przykład, w którym opcja nieograniczonej liczby parametrów jest doskonałym wyborem
Weź pod uwagę, że należy zbudować aplikację do wysyłania wiadomości e-mail.
Funkcja wysyłająca wiadomość e-mail musi obsługiwać jedną lub wiele wartości pól „Do”, „CC” i „BCC”.
Jeśli typy parametrów są ustawione jako tablice lub listy dla wszystkich pól (Do, CC, BCC), wówczas funkcja wywołująca będzie zmuszona poradzić sobie z całą złożonością zdefiniowania 3 tablic lub list w celu wywołania funkcji nadawcy wiadomości e-mail .
Nawet jeśli dzwoniący chce wysłać wiadomość e-mail na tylko jeden adres, funkcja nadawcy wiadomości e-mail zmusi ją do zdefiniowania i wysłania 3 różnych tablic jako parametrów.
Jeśli funkcja nadawcy wiadomości e-mail przyjmuje podejście z nieograniczoną liczbą par, funkcja dzwoniącego nie musi zajmować się całą złożonością.
Podejście do nieograniczonych parametrów przyczynia się do lepszego działania aplikacji w czasie wykonywania, unikając tworzenia tablic lub list tam, gdzie jest to niepotrzebne.
źródło
Z nieefektywnego stylu,
params
słowo kluczowe jest naprawdę miłe, gdy chcesz wysłać opcjonalną listę parametrów.Osobiście korzystałbym,
params
gdy mój kod był podobnyZaletą tego jest to, że mogę korzystać z tej metody wszędzie, bez konieczności tworzenia tablicy lub listy za każdym razem.
Chciałbym użyć
array
lublist
gdy wiem, że zawsze przekażę tej funkcji zestaw danych, które już są zebrane razemWidzę zaletę
params
elastyczności, którą dodaje. Może to mieć stosunkowo niewielki wpływ na kod, ale nadal jest to miłe narzędzie.źródło
Konwencja wywoływania jest inna. Na przykład ...
W pierwszym przypadku możesz przekazać do metody tyle ints, ile osobnych parametrów. W drugim przypadku musisz utworzyć instancję listy i przekazać ją.
źródło