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: 1800Zauważ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