Zasady dotyczące konwersji są w C# podobne do tych z C++, choć są bardziej wzorowane na Javie. W szczególności, konwersje prowadzące do utraty informacji muszą być jawne.
Warto za to pokrótce wspomnieć o różnicach w definiowaniu i wywoływaniu funkcji. W C# nie ma bezpośredniej implementacji typu wskaźnikowego i referencyjnego jaki znamy z C/C++. Istnieją za to mechanizmy które pozwalają definiować funkcje semantycznie równoważne funkcjom C++ z parametrami wskaźnikowymi i referencyjnymi, a więc pozwalające funkcji na dostęp do oryginału a nie kopii argumentu wywołania.
Deklarację parametru w nagłówku funkcji można poprzedzić modyfikatorem ref lub out. Znaczenie jest następujące:
Inaczej również zaimplementowany jest mechanizm przekazywania do funkcji zmiennej liczby argumentów. Ostatni parametr funkcji można zadeklarować z modyfikatorem params. Parametr ten powinien wtedy być typu tablicowego. Jeśli tak zadeklarowaliśmy funkcję, to w miejsce tego parametru podczas wywołania możemy dostarczyć dowolną liczbę argumentów typu odpowiadającego typowi tablicy: wszystkie one będą dostępne w funkcji jako elementy tablicy. W szczególnym przypadku zadeklarowanym typem elementów tablicy może być typ object. Wtedy odpowiadające tej tablicy argumenty mogą być dowolnego typu, w tym typu wbudowanego, jak na przykład int. W tym ostatnim przypadku ich wartości zostaną „opakowane” w zmiennych obiektowych (odpowiadających obiektom klas opakowujących z Javy, jak klasa Integer czy Double). Wewnątrz funkcji można je wtedy „odpakować” za pomocą rzutowania.
Rozpatrzmy następujący program:
1. using System;
2.
3. class Raport {
4.
5. static int LIMIT = 1050;
6.
7. public static int licz(ref String str, out int sum,
8. params object[] dane) {
9. Console.WriteLine("...Dane od " + str);
10. int ile =0;
11. sum = 0;
12. for (int i = 0; i < dane.Length; i++) {
13. if (dane[i] is String) ile++;
14. else sum += (int) dane[i];
15. }
16. str = sum >= LIMIT ? "POWYZEJ" : "PONIZEJ";
17. return ile;
18. }
19. }
20.
21. class Fun {
22. public static void Main() {
23. int sum, ile;
24. String str;
25.
26. str = "Kasjer_1";
27. ile = Raport.licz(ref str, out sum,
28. "Nowak", 100, 50, 50, 80, 20,
29. "Byrski", 50, 50,
30. "Kociniak", 100, 50, 100, 50,
31. "Malinowski", 70, 30);
32. pr(str,ile,sum);
33.
34. str = "Kasjer_2";
35. ile = Raport.licz(ref str, out sum,
36. "Tarski", 200, "Zdziarski", 700,
37. 700, 100, 100);
38. pr(str,ile,sum);
39. }
40.
41. private static void pr(String str, int ile, int sum) {
42. Console.WriteLine(str + " limitu. Klientow: " +
43. ile + ". Utarg: " + sum);
44. }
45. }
Jako pierwszy argument funkcja pobiera napis str który drukuje (linia 9), a następnie zmienia (linia 16) na napis 'POWYZEJ' lub 'PONIZEJ' w zależności od wartości zmiennej sum. Zmiana ta będzie widoczna w funkcji wywołującej.
Zmienna sum jest rodzaju out więc jej wartość wejściowa nie jest używana; zmienna ta w ogóle nie musiała być zainicjowana. Funkcja oblicza sumę wpłat od klientów i umieszcza ją w tej zmiennej dzięki czemu wartość jej będzie widoczna w funkcji wywołującej.
Pozostałe argumenty są zbierane w tablicy dane. W pętli (linie 12-15) za pomocą operatora is sprawdzany jest typ kolejnego argumentu. Jeśli był to String to znaczy, że argumentem tym było nazwisko kolejnego klienta i zwiększamy wartość zmiennej ile która jest licznikiem klientów. Jeśli nie był to napis, to znaczy, że jest to opakowana liczba całkowita; rozpakowujemy ją za pomocą rzutowania (operator (int) wyłuskuje z obiektu zapakowaną tam liczbę). O otrzymaną wartość zwiększamy zmienną sum.
W ten sposób funkcja zwraca trzy wartości: poprzez return liczbę klientów, poprzez zmienną str (rodzaju ref) napis mówiący czy suma wpłat była poniżej czy powyżej limitu zdefiniowanego w linii piątej, i wreszcie poprzez zmienną sum rodzaju out sumę wszystkich wpłat.
Funkcja wywołująca, czyli Main z klasy Fun, posyła te dane do funkcji pr która drukuje rezultat obliczeń. Ta funkcja nie modyfikuje otrzymywanych danych, więc przekazywane są one tym razem przez wartość:
...Dane od Kasjer_1
PONIZEJ limitu. Klientow: 4. Utarg: 800
...Dane od Kasjer_2
POWYZEJ limitu. Klientow: 2. Utarg: 1800
Zauważmy, że wywołując funkcję
licz
w liniach
27 i 35 przed odpowiednimi argumentami musieliśmy umieścić
modyfikatory
ref
i
out. Pozostałe argumenty
(siedemnaście w pierwszym wywołaniu, siedem w drugim) są
przemieszanymi wartościami typu
String
i
int
— wszystkie
one znajdą się w funkcji jako elementy tablicy
dane.
T.R. Werner, 21 lutego 2016; 20:17