Oprócz innych dobrych odpowiedzi, dodam jeszcze jeden powód, dla którego nie należy umieszczać stałości w stylu C w C #. Powiedziałeś:
oznaczamy parametr jako const, aby mieć pewność, że jego stan nie zostanie zmieniony w metodzie.
Gdyby const faktycznie to zrobił, byłoby świetnie. Const tego nie robi. Stała to kłamstwo!
Const nie daje żadnej gwarancji, że mogę faktycznie użyć. Załóżmy, że masz metodę, która przyjmuje stałą rzecz. Jest dwóch autorów kodu: osoba pisząca dzwoniącego i osoba pisząca adres . Autor wywoływanego obiektu sprawił, że metoda przyjmuje stałą. Co obaj autorzy mogą założyć, że przedmiot jest niezmienny?
Nic. Wywoływany może odrzucić stałą i zmutować obiekt, więc wywołujący nie ma gwarancji, że wywołanie metody, która przyjmuje stałą, w rzeczywistości jej nie zmieni. Podobnie, odbiorca nie może zakładać, że zawartość przedmiotu nie zmieni się podczas działania wywoływanego; wywoływany mógłby wywołać jakąś metodę mutacji na aliasie innym niż const obiektu const, a teraz tak zwany obiekt const uległ zmianie .
Stała w stylu C nie gwarantuje, że obiekt się nie zmieni i dlatego jest zepsuta. Teraz C ma już słaby system typów, w którym możesz dokonać reinterpretacji rzutowania double na int, jeśli naprawdę chcesz, więc nie powinno być zaskoczeniem, że ma słaby system typów również w odniesieniu do const. Ale C # został zaprojektowany, aby mieć dobry system typów, system typów, w którym kiedy mówisz „ta zmienna zawiera ciąg znaków”, zmienna faktycznie zawiera odniesienie do ciągu (lub wartości null). Absolutnie nie chcemy umieszczać modyfikatora "const" w stylu C w systemie typów, ponieważ nie chcemy, aby system typów był kłamstwem . Chcemy, aby system typów był mocny , abyś mógł poprawnie uzasadnić swój kod.
Const w C to wskazówka ; w zasadzie oznacza to „możesz mi zaufać, że nie będę próbował tego modyfikować”. To nie powinno być w systemie typów ; rzeczy w systemie typów powinny być faktem o obiekcie, co do którego można uzasadnić, a nie wskazówką dotyczącą jego użycia.
Nie zrozum mnie źle; tylko dlatego, że const w C jest głęboko zerwane, nie oznacza, że cała koncepcja jest bezużyteczna. To, co chciałbym zobaczyć, to rzeczywiście poprawna i użyteczna forma adnotacji „const” w C #, adnotacja, której zarówno ludzie, jak i kompilatorzy mogliby użyć, aby pomóc im zrozumieć kod, i której środowisko wykonawcze mogłoby użyć do takich rzeczy, jak automatyczna paralelizacja i inne zaawansowane optymalizacje.
Na przykład, wyobraź sobie, że możesz „narysować prostokąt” wokół kawałka kodu i powiedzieć „ Gwarantuję, że ten fragment kodu nie wykona mutacji w żadnym polu tej klasy” w sposób, który mógłby zostać sprawdzony przez kompilator. Lub narysuj ramkę, która mówi: „ta czysta metoda zmienia stan wewnętrzny obiektu, ale w żaden sposób nie jest obserwowalny poza ramką”. Taki obiekt nie mógł być bezpiecznie wielowątkowy automatycznie, ale mógłby zostać automatycznie zapamiętany . Istnieje wiele interesujących adnotacji, które moglibyśmy umieścić w kodzie, które umożliwiłyby rozbudowane optymalizacje i głębsze zrozumienie. Możemy zrobić o wiele lepiej niż słaba adnotacja const w stylu C.
Podkreślam jednak, że to tylko spekulacje . Nie mamy konkretnych planów umieszczenia tego rodzaju funkcji w żadnej hipotetycznej przyszłej wersji C #, jeśli w ogóle istnieje, której nie ogłosiliśmy w taki czy inny sposób. Jest to coś, co chciałbym zobaczyć i coś, czego może wymagać nadchodzący nacisk na przetwarzanie wielordzeniowe, ale nic z tego nie powinno być w żaden sposób interpretowane jako przewidywanie lub gwarancja jakiejkolwiek konkretnej funkcji lub przyszłego kierunku C #.
Teraz, jeśli chcesz tylko adnotacji na zmiennej lokalnej, która jest parametrem, który mówi, że „wartość tego parametru nie zmienia się w całej metodzie”, to z pewnością byłoby to łatwe. Moglibyśmy obsługiwać ustawienia lokalne i parametry „tylko do odczytu”, które byłyby inicjowane raz, oraz błąd kompilacji w czasie zmiany metody. Zmienna zadeklarowana przez instrukcję „using” jest już taką lokalną; moglibyśmy dodać opcjonalną adnotację do wszystkich lokalnych i parametrów, aby zachowywały się jak „używanie” zmiennych. Nigdy nie była to funkcja o wysokim priorytecie, więc nigdy nie została zaimplementowana.