Funkcje C # lub .Net do odcięcia przy założeniu, że nie jest wymagana kompatybilność wsteczna? [Zamknięte]

18

Ewoluuje każdy produkt lub struktura. Przede wszystkim ma to na celu zaspokojenie potrzeb użytkowników, wykorzystanie nowych mocy obliczeniowych i po prostu ulepszenie. Czasami główny cel projektu zmienia się również wraz z produktem. Framework C # lub .net nie jest wyjątkiem. Jak widzimy, obecna 4. wersja różni się znacznie od pierwszej. Ale rzecz stanowi barierę dla tej ewolucji - wstecznej kompatybilności.

W większości frameworków / produktów niektóre funkcje zostałyby odcięte, gdyby nie było potrzeby obsługi kompatybilności wstecznej. Według ciebie, jakie są te funkcje w C # /. Net?

Podaj jedną funkcję na odpowiedź.

Gulszan
źródło
Słowo kluczowe nowe
Nemanja Trifunovic
4
Pytanie wyraźnie nie jest konstruktywne zgodnie z wytycznymi i wyraźnie konstruktywne w oparciu o fantastyczne odpowiedzi. Głosowanie w celu ponownego otwarcia.
psr
1
szkoda, że ​​się zamknęło, ale może Eric opublikuje to na blogu zamiast tutaj?
jk.

Odpowiedzi:

35

Anonimowe metody . Myślę, że wszyscy zgadzają się, że anonimowa składnia metody wybrana dla C # 2.0 jest masywna i niezgrabna w porównaniu do składni lambda dodanej do C # 3.0. Bardzo niefortunnie jest mieć dwie prawie identyczne składnie, aby zrobić to samo.

Eric Lippert
źródło
1
Uzgodnione, anonimowe metody były świetne, gdy nie mieliśmy lambdów ... teraz są po prostu zbędne.
Michael Brown
9
Jest jedna szczególna cecha anonimowych metod, która jest znacznie lepsza niż wyrażenia lambda .... ich idealne imię !!
odkrywca
1
W tym momencie nawet nie pamiętam składni anonimowej metody w C #. Muszę to sprawdzić, jeśli z jakiegoś dziwnego powodu muszę użyć jednego zamiast lambda.
Kyralessa
33

Pozbyłbym się zbiorów innych niż ogólne. Są obrzydliwością ... i jest zbyt wiele przypadków, w których używam linq i muszę coś zrobić

var customObjects = container.CustomObjects.Cast<CustomObject>();

Za każdym razem, gdy muszę to robić, umiera niewielka część mojej duszy.

Michael Brown
źródło
To jest za świetne.
1
Nie wszystkie porty .NET obsługują rodzajowe. .NET Micro jest przykładem. Może nie mieć zastosowania, jeśli obiekty CustomObjects nigdy nie zostaną przeniesione na tę platformę.
goodguys_activate
2
To zaleta, że ​​nie ma duszy.
CaffGeek
29

nieważne jako typ . Dlaczego, u licha, „pustka” jest typem? Nie ma instancji, nie ma wartości, nie można go używać jako argumentu typu ogólnego, typu parametru formalnego, typu lokalnego, typu pola lub typu właściwości. Nie ma znaczenia jako typ; jest raczej faktem na temat wpływu wywołania metody na stos maszyny wirtualnej. Ale maszyna wirtualna to po prostu: maszyna wirtualna. Prawdziwa maszyna umieści zwracaną wartość w rejestrze (zazwyczaj EAX na x86) i nie wpłynie w ogóle na stos! Pustka jako typ to po prostu zły pomysł dookoła.

Gorzej: gdy jest używany jako typ wskaźnika, ponieważ w void*nim oznacza coś zupełnie innego niż to, co oznacza, gdy jest używany jako typ zwracany. Teraz oznacza „wskaźnik do miejsca przechowywania nieznanego typu”, co nie ma nic wspólnego z jego znaczeniem jako „metoda, która nie zwraca żadnej wartości”.

Możemy wymienić void* jako typ wskaźnika na IntPtr. (I void**z IntPtr*i tak dalej.) Możemy zastąpić void jako typ zwracany przez „Unit”, typ, który ma jedną wartość, a mianowicie null. Implementacja CLR mogłaby następnie zdecydować, że wywołanie funkcji typowanej dla jednostki może odpowiednio zoptymalizować wykorzystanie rejestrów lub stosów, wiedząc, że zwracane wartości null można bezpiecznie zignorować.

W takim świecie nie potrzebujesz już oddzielnych Func<A, R>i Action<T>delegatów. Action<T>jest po prostu Func<T, Unit>.

Eric Lippert
źródło
4
... i Taskjest po prostu Task<Unit>. Ponowne wdrożenie fragmentów biblioteki asynchronicznego CTP sprawiło, że naprawdę tego chciałem ...
Jon Skeet
24

Puste oświadczenie; . Podatny na błędy, prawie zawsze literówka, i nie daje żadnego dodatkowego znaczenia, które nie zostało jeszcze wyrażone przez {}.

Eric Lippert
źródło
7
Nie wspominając już o ogromnym spadku wydajności wynikającym z 64-bitowego JIT </snark>.
Jesse C. Slicer
7
Puste stwierdzenie ma negatywny wpływ na wydajność? Dlaczego?
quentin-starin
22

Niebezpieczna kowariancja dla tablic typu referencyjnego . Przy włączonej kowariancji typu IEnumerable<T>, przynajmniej część potrzeby kowariancji macierzowej zniknęła. (Gdybyśmy mieli kowariantny interfejs listy tylko do odczytu, to nie potrzebowalibyśmy go wcale).

Eric Lippert
źródło
Absolutnie zamierzałem to zapisać, kiedy zobaczyłem tytuł pytania - pobiłeś mnie do niego :(
Chris Smith
1
Przydatna jest możliwość otrzymania odniesienia do tablicy kowariantnej i bezpiecznego zapisu do odczytanych z niej odniesień do tablicy . Jeśli podobnie jak IList<T>dziedziczony IReadableList<out T>i nieprzewidziany IPemutable, może obsługiwać takie rzeczy jak sortowanie, ale tablice obsługują go łatwiej.
supercat
14

Jednoargumentowy operator plus . Najmniej użyteczny operator wszechczasów. Gdybyśmy nie musieli go trzymać dla kompatybilności wstecznej, wyjąłbym to w mgnieniu oka. Kto z tego korzysta, ktoś?

(Wyjaśnienie: Operator jednoargumentowy plus +xnie jest operatorem wstępnego zwiększania ++x, nie jest operatorem wstępnego zwiększania x++i nie jest operatorem dodawania binarnego x+y.)

Eric Lippert
źródło
1
dla (int i = 0; i <pułap; i ++)
Michael Brown
13
On nie mówi o preincrement i operatorów postincrement: on mówi o jednoargumentowego Plus, przeciwieństwo znakiem ujemnym na numer: +1 == 1. To dość cholernie blisko no-op.
Jesse C. Slicer
8
Nie chodzi tylko o wpływ na wyjściu czytelnej maszynowego, może poprawić wygląd kodu dla ludzi: if(a == +1 || a == -1){...}.
Thomas Bratt,
5
@ShuggyCoUK: Szczególnie dziwne jest to, że można go przeciążać . Ponieważ to się często zdarza. Wiesz, jak piszesz trochę JavaScript i myślisz, stary, chciałbym, żeby JS pozwolił mi tworzyć jednoargumentowe zdefiniowane przez użytkownika plus semantykę operatora, jak C # .
Eric Lippert,
2
@Eric Nie zdawałem sobie sprawy, że to jest przeciążalne. wow, możesz zrobić z tym okropne zaciemnienie :)
ShuggyCoUk
12

Domyślne literały liczbowe to double

W przypadku większości aplikacji biznesowychdecimal jest to bardziej odpowiednie ... a może lepiej byłoby po prostu usunąć ideę domyślnej i zmusić programistę do dokonania wyboru.

(To „usuń domyślne” byłoby również odpowiednie dla niektórych innych rzeczy. Na przykład zrezygnowałem z prób przekonania wszystkich, że klasy powinny być domyślnie zapieczętowane, ale podejrzewam, że łatwiej jest przekonać ludzi, że powinni o tym pomyśleć czy ich nowa klasa powinna być zapieczętowana, czy też nie, i wyraź to).

Jon Skeet
źródło
Być może skłaniam się do identyfikowania literałów, które sugerują wartość, której nie można przedstawić jako podwójne / zmiennoprzecinkowe dokładnie ...
ShuggyCoUk
Jeśli są w Javie - odnieś je do świętych tekstów Joshua Blocha „projekt lub dokument do dziedziczenia, albo zabraniają go” martinfowler.com/bliki/DesignedInheritance.html IIRC kotlin domyślnie uszczelnia klasy, więc przemysł przechodzi do lepszy kierunek w tym względzie.
Elazar Leibovich
Dlaczego klasy powinny być zapieczętowane?
James
@James: Dokładnie z powodów, które podaje Josh. Zaprojektowanie klasy, która umożliwia dziedziczenie w rozsądny, spójny sposób, zajmuje dużo czasu - a zrobienie tego bez wiedzy o tym, w jaki sposób zostanie zastosowane dziedziczenie, jest jeszcze gorsze.
Jon Skeet
1
@Pacerier: Pomyśl na przykład o niezmienności. Klasa niezapieczętowana nie może twierdzić, że jest niezmienna, ponieważ podklasy mogą wprowadzać zmienność.
Jon Skeet
7

Jest to raczej wskazówka niż funkcja, ale myślę, że jest ważna, ponieważ jest już zbyt głęboko zakorzeniona w ludzkich umysłach jako kanoniczne i najlepsze rozwiązanie:

Oficjalny wzór do wdrożenia IDisposable.

Jest to uciążliwe i istnieją lepsze sposoby .

Jordão
źródło
6

Ja wiem, istnieją duże różnice między poszczególnymi klasami timera. Ale czy w ogóle nie moglibyśmy się ich pozbyć?

nikie
źródło
4

Metody i typów Arrayi List<T>które stały się przestarzałe wraz z Linq, na przykład:

  • Array.TrueForAll można zastąpić Enumerable.All
  • Array.FindAll można zastąpić Enumerable.Where
  • List<T>.ConvertAll można zastąpić Enumerable.Select
  • Predicate<T> można zastąpić Func<T, bool>
  • Converter<T,R> można zastąpić Func<T, R>
  • IComparer<T> naprawdę powinien być delegatem Func<T, T, int>
nikie
źródło
3
Podoba mi się, Predicate<T>ponieważ wychwytuje cel użycia tej funkcji i oszczędza trochę pisania.
Zebi
2

Nieogólni delegaci Podobnie jak nieogólne kolekcje, nieogólni delegaci są bezużyteczni teraz, gdy mamy serię Func i Action. I odciąłbym warianty przy trzech parametrach. Jeśli masz więcej niż trzy parametry, utwórz strukturę i użyj tego jako pojedynczego parametru. Zadeklarowanie konkretnego delegata do obsługi zdarzeń nie jest zbyt OSADNE.

Michael Brown
źródło
3
Jak zdefiniowałbyś delegata do metody, która przyjmuje odwołanie za pomocą Action lub Func? Jak zdefiniowałbyś kombinator za pomocą Func? Oznacza to, że nie można powiedzieć „delegować DD (D d);” z Func.
Eric Lippert,
2
hmmm ... Poprawiłem się. Dlatego zostawiam zadanie tworzenia narzędzi, których używam w twoich zdolnych rękach;)
Michael Brown
@EricLippert: Chciałbym zobaczyć specjalną klasę delegatów, która poprzez magię CLR zawiera delegatów „każdego” arity i kombinacji parametrów wartości / referencji [wyszukiwanie delegata w klasie magii o odpowiednio sformatowanej nazwie stworzyłoby typ] i niech odziedziczą po nim wszyscy delegaci odpowiedniego podpisu. Kod, który chce konkretnego delegata, nadal wymaga dokładnego typu, ale kod, który chce konkretnego podpisu, mógłby użyć magicznej nazwy.
supercat
-1

Usługi sieciowe asmx

Myślę, że obecnie są dość przestarzałe w WCF.

fretje
źródło
6
Tak, ale czasem o wiele łatwiejsze w użyciu. . .
Wyatt Barnett
-2

Winforms
Byłoby miło nie musieć nawigować między dwiema platformami stacjonarnymi. WPF to miejsce, w którym wszystko się dzieje, więc frustrujące jest posiadanie pełnej nadmiarowości na poziomie platformy.

Morgan Herlocker
źródło
Winforms wydaje się znacznie bardziej stabilny, szybszy i mniej
błędny
Kiedy musisz tylko zhakować małą aplikację komputerową, WPF jest poważną przesadą.
Kyralessa
Wydaje się, że pomiędzy WPF stał się dość przestarzały na korzyść WinRT. Wydaje mi się jednak, że Winforms żyje bardziej niż WPF w rozwoju biznesu. Zobacz także stackoverflow.com/questions/913417/…
Doc Brown