Odpowiadam na pytania „dlaczego nie”, ponieważ po pierwsze, odpowiedzi prawie nigdy nie są satysfakcjonujące - już otrzymałeś odpowiedź „funkcja nie jest taka, jakiej chcesz, ponieważ specyfikacja nie mówi tego, co chcesz, aby powiedzieć” , co, jak sądzę, nie było szczególnie satysfakcjonującą odpowiedzią. Po drugie, zespół projektantów nie musi uzasadniać, dlaczego świat nie jest taki, jaki chcesz; funkcje nie istnieją za darmo i są projektowane poza językiem; raczej funkcje muszą być najpierw uzasadnione, a następnie zaprojektowane.
Postarajmy się więc, aby Twoje pytanie „dlaczego nie” było trochę bardziej wyraźne. Istniejąca funkcja to „inicjalizator tablicy może być użyty (a) po prawej stronie równych w inicjalizacji lub (b) po prawej stronie konstrukcji obiektu typu tablica”. Proponowana funkcja to: „inicjalizator tablicy może być również użyty jako wyrażenie”. Pytanie brzmi: „jaką krytykę podałby Eric w stosunku do proponowanej funkcji?”
Pierwsza krytyka, którą chciałbym skierować, dotyczy tego, że nie jest jasne, jakiego rodzaju jest to wyrażenie. W inicjatorze zmiennej masz typ zmiennej, aw wyrażeniu tworzenia obiektu masz typ obiektu; z obu tych możemy wywnioskować typ skonstruowanej tablicy. Bez żadnej wskazówki, jaki typ powinniśmy wywnioskować?
W C # 1.0, kiedy ta funkcja została dodana, w języku było w sumie wnioskowanie o typie zerowym. We wczesnych latach C # zasadą projektowania było „bez niespodzianek”, a kompilator nie był „zbyt inteligentny”. Jeśli programista chce, aby wyrażenie było określonego typu, typ ten powinien być w pewnym sensie oczywisty w wyrażeniu. Kiedy powiesz
new double[] { 1, 2, 3.4 }
jest całkiem jasne, jaki typ jest przeznaczony. podobnie
new Animal[] { cat, dog, null }
Proponowana funkcja narusza tę zasadę. Wyrażenie musi mieć typ, ale w żadnym wypadku nie jest jasne, jaki jest typ argumentu
M({cat, dog, null})
Ponadto: załóżmy, że mamy dwa przeciążenia M, z których jeden przyjmuje tablicę, Animala drugi przyjmuje tablicę IPet. Które przeciążenie Mma zastosowanie? Czy jedna z konwersji jest lepsza od drugiej? Rodzaje elementów to Cati Dog; czy sensowne jest wywnioskowanie typu, który nawet tam nie występuje? To wszystkie pytania, na które zespół projektowy musi się zastanowić, i są to pytania, na które nie ma oczywistych odpowiedzi. Proponowana funkcja prowadzi nas w dość krótkim czasie na głębokie wody.
Teraz C # 3.0 rozwiązuje ten problem, ponieważ C # 3.0 dodał wiele funkcji, w których kompilator wnioskuje typy w imieniu dewelopera. Wcześniejsze zasady „bez niespodzianek” i „prostych reguł” były w konflikcie z innymi zasadami projektowania potrzebnymi do działania LINQ. Czy proponowana funkcja powinna zostać dodana w języku C # 3.0?
To mogło być. Funkcja faktycznie dodana w C # 3.0 to:
new[] { x, y, z }
wnioskuje o typ tablicy za pomocą algorytmu: weź wyrażenia dla elementów, które mają typy, określ, który z tych typów jest unikalnym, najbardziej ogólnym typem, na który wszystkie inne wyrażenia są konwertowane, a jeśli taki typ istnieje, wybierz go. W przeciwnym razie wystąpi błąd,
Ta funkcja mogła zostać jeszcze bardziej złagodzona, aby uczynić ją new[]opcjonalną. To nie zostało zrobione.
Teraz, gdybyś poprosił mnie w ramach czasowych C # 3.0 o skrytykowanie proponowanej funkcji, zwróciłbym uwagę, że (1) kompilator C # 3.0 był już w poważnym niebezpieczeństwie poślizgnięcia się harmonogramu dla całego wydania, więc nie dodawajmy więcej projekt, implementacja i testowanie całkowicie niepotrzebnej funkcji, która oszczędza użytkownikowi sześć naciśnięć klawiszy, a (2) C # 3.0 dodał także inicjatory kolekcji:
new List<int>() { 10, 20, 30 }
dlaczego ma być {10, 20, 30}automatycznie tablicą ? Dlaczego nie miałoby to być List<int>? Lub którykolwiek z wielu innych typów? Dlaczego tendencja do tablic? Pamiętaj, że kiedy już zdecydujemy się zapisać składnię tablic, utkniemy z nią na zawsze . Może to nigdy nie być nic innego, więc proponowana funkcja jest nie tylko niepotrzebna, ale także zapobiega możliwym przyszłym funkcjom, które wydają się prawdopodobne.
Podsumowując: proponowana funkcja bezpośrednio naruszyła niektóre zasady projektowania języka C # 1.0. Dodaje tylko niepotrzebne obciążenie do C # 3.0. We wszystkich wersjach języka, począwszy od C # 3.0, proponowana funkcja nie ma dobrego argumentu, aby zalecać poświęcanie na nią czasu, wysiłku i pieniędzy w porównaniu z wieloma innymi bardziej wartościowymi funkcjami.
Dlatego nie ma takiej funkcji.