C # - oder .Net-Funktionen zum Abschneiden unter der Annahme, dass keine Abwärtskompatibilität erforderlich ist? [geschlossen]

18

Jedes Produkt oder Framework entwickelt sich weiter. Dies geschieht hauptsächlich, um die Bedürfnisse der Benutzer zu befriedigen, neue Rechenkapazitäten zu nutzen und einfach besser zu machen. Manchmal ändert sich auch das primäre Designziel mit dem Produkt. C # - oder .net-Framework ist keine Ausnahme. Wie wir sehen, unterscheidet sich die heutige 4. Version stark von der ersten. Aber es ist eine Barrikade für diese evolutionäre Abwärtskompatibilität.

In den meisten Frameworks / Produkten gibt es Funktionen, die abgeschnitten worden wären, wenn die Abwärtskompatibilität nicht unterstützt werden müsste. Was sind Ihrer Meinung nach diese Funktionen in C # /. Net?

Bitte erwähnen Sie eine Funktion pro Antwort.

Gulshan
quelle
Keyword new
Nemanja Trifunovic
4
Die Frage ist nach den Richtlinien eindeutig nicht konstruktiv und auf der Grundlage der fantastischen Antworten eindeutig konstruktiv. Abstimmung zur Wiedereröffnung.
PSR
1
Schade, dass es geschlossen ist, vielleicht bloggt Eric das trotzdem, anstatt hier zu antworten?
jk.

Antworten:

35

Anonyme Methoden . Ich denke, alle sind sich einig, dass die für C # 2.0 gewählte anonyme Methodensyntax im Vergleich zu der Lambda-Syntax, die wir zu C # 3.0 hinzugefügt haben, klobig und klobig ist. Es ist sehr bedauerlich, zwei fast identische Syntaxen zu haben, um dasselbe zu tun.

Eric Lippert
quelle
1
Vereinbarte, anonyme Methoden waren großartig, wenn wir keine Lambdas hatten ... jetzt sind sie einfach überflüssig.
Michael Brown
9
Es gibt eine Besonderheit bei anonymen Methoden, die weitaus besser ist als Lambda-Ausdrücke .... ihr perfekter Name !!
Explorest
1
An dieser Stelle kann ich mich noch nicht einmal an die Syntax einer anonymen Methode in C # erinnern. Ich müsste es nachschlagen, wenn ich aus irgendeinem bizarren Grund einen anstelle eines Lambda verwenden müsste.
Kyralessa
33

Ich würde die nicht-generischen Sammlungen loswerden. Sie sind ein Gräuel ... und es gibt zu viele Fälle, in denen ich Linq benutze und so etwas tun muss

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

Jedes Mal, wenn ich das tun muss, stirbt ein kleiner Teil meiner Seele.

Michael Brown
quelle
Das ist zu groß.
1
Nicht alle .NET-Ports unterstützen Generics. .NET Micro ist ein Beispiel. Gilt möglicherweise nicht, wenn CustomObjects niemals auf diese Plattform verschoben wird.
goodguys_activate
2
Das ist der Vorteil, keine Seele zu haben.
CaffGeek
29

als Typ ungültig . Warum um alles in der Welt ist "void" ein Typ? Es hat keine Instanzen, es hat keine Werte, Sie können es nicht als generisches Typargument, formaler Parametertyp, lokaler Typ, Feldtyp oder Eigenschaftstyp verwenden. Es hat als Typ keine Bedeutung; Vielmehr geht es darum, welche Auswirkung ein Methodenaufruf auf den Stapel der virtuellen Maschine hat. Aber die virtuelle Maschine ist genau das: eine virtuelle Maschine. Die reale Maschine schreibt den zurückgegebenen Wert in ein Register (normalerweise EAX bei x86) und beeinflusst den Stack überhaupt nicht! Void als Typ ist einfach eine schlechte Idee.

Schlimmer noch: Wenn in einem Zeigertyp wie in void*diesem verwendet, bedeutet dies etwas völlig anderes als das, was es bedeutet, wenn es als Rückgabetyp verwendet wird. Jetzt bedeutet es "ein Zeiger auf einen Speicherort unbekannten Typs", der in keiner Weise mit seiner Bedeutung als "eine Methode, die keinen Wert zurückgibt" zu tun hat.

Wir können void*als Zeigertyp mit ersetzen IntPtr. (Und void**mit IntPtr*und so weiter.) Wir können void als Rückgabetyp durch "Unit" ersetzen, einen Typ mit einem einzelnen Wert, nämlich null. Eine Implementierung der CLR könnte dann entscheiden, dass ein Unit-typisierter Funktionsaufruf die Verwendung von Registern oder Stapeln entsprechend optimieren kann, da bekannt ist, dass die "zurückgegebene" Null sicher ignoriert werden kann.

In einer solchen Welt braucht man keine getrennten Func<A, R>und Action<T>delegierten mehr. Action<T>ist einfach Func<T, Unit>.

Eric Lippert
quelle
4
... und Taskist nur ein Task<Unit>. Das erneute Implementieren der Bibliotheks-Bits des asynchronen CTP ließ mich dies wirklich wünschen ...
Jon Skeet,
24

Die leere Aussage; . Fehleranfällig, fast immer ein Tippfehler, und gibt Ihnen keine zusätzliche Bedeutung, die nicht bereits von ausgedrückt wird {}.

Eric Lippert
quelle
7
Ganz zu schweigen von der enormen Leistungseinbuße beim 64-Bit-JIT </ snark>.
Jesse C. Slicer
7
Eine leere Anweisung hat eine Leistungsstrafe? Warum das?
Quentin-Starin
22

Unsichere Kovarianz bei Arrays des Referenztyps . Mit aktivierter typsicherer Kovarianz IEnumerable<T>ist zumindest ein Teil des Bedarfs an Array-Kovarianz weggefallen . (Wenn wir eine kovariante schreibgeschützte Listenschnittstelle hätten, würden wir sie überhaupt nicht brauchen.)

Eric Lippert
quelle
Ich wollte das unbedingt aufschreiben, als ich den Fragentitel sah - du hast mich geschlagen :(
Chris Smith
1
Die Möglichkeit, eine kovariante Arrayreferenz zu empfangen und sicher in die Arrayreferenzen zu schreiben, die aus ihr gelesen wurden, ist nützlich. Wenn es wie IList<T>geerbt von IReadableList<out T>und nicht generisch ist IPemutable, kann es Dinge wie Sortieren unterstützen, aber Arrays können es einfacher unterstützen.
Supercat
14

Der unäre Plus-Operator . Am wenigsten nützlicher Operator aller Zeiten. Wenn wir es nicht für Rückwärtskompatibilität aufbewahren müssten, würde ich es sofort herausnehmen. Wer benutzt dieses Ding?

(Erläuterung: Der unäre Plus-Operator +xist nicht der Vorinkrementierungsoperator ++x, nicht der Nachinkrementierungsoperator x++und nicht der Binäradditionsoperator x+y.)

Eric Lippert
quelle
1
für (int i = 0; i <Decke; i ++)
Michael Brown
13
Er spricht nicht über die Prä - und Postinkrement Operatoren: er spricht über das einstelligen plus, das Gegenteil von dem negativen Vorzeichen auf einer Reihe: +1 == 1. Es ist verdammt nah an einem No-Op.
Jesse C. Slicer
8
Es geht nicht nur um die Wirkung auf der maschinenlesbare Ausgabe, kann er das Aussehen des Code für die Menschen verbessern: if(a == +1 || a == -1){...}.
Thomas Bratt
5
@ShuggyCoUK: Besonders bizarr ist, dass es überlastbar ist . Weil das viel passiert. Sie wissen, wie Sie JavaScript schreiben und Sie denken, man, ich wünschte, JS hätte mir erlaubt, benutzerdefinierte unäre und Operator-Semantiken wie in C # zu erstellen .
Eric Lippert
2
@Eric Mir war nicht klar, dass es überlastbar war. wow, du könntest damit eine böse Verschleierung machen :)
ShuggyCoUk
12

Standardmäßig numerische Literale bis double

Für die meisten Unternehmen Anwendungen, decimalbesser geeignet ist sowieso ... oder vielleicht wäre es besser, nur zu entfernen , die Idee einer Standard und Kraft - Entwickler , um tatsächlich die Wahl zu treffen.

(Das „entfernen Sie die default“ würde für einige andere Dinge, auch geeignet sein. Zum Beispiel, ich habe es aufgegeben, alle davon zu überzeugen , dass Klassen standardmäßig abgedichtet werden sollte, aber ich vermute , dass es einfacher ist , die Menschen davon zu überzeugen , daß sie denken über ob ihre neue Klasse besiegelt werden soll oder nicht, und machen Sie es explizit.)

Jon Skeet
quelle
Ich würde vielleicht gerne Literale identifizieren, die einen Wert implizieren, der nicht genau als double / float dargestellt werden kann ...
ShuggyCoUk
Wenn sie Java lieben - verweisen Sie sie auf die heiligen Texte von Joshua Bloch "Design oder Dokument zur Vererbung oder verbieten Sie es" martinfowler.com/bliki/DesignedInheritance.html IIRC kotlin macht standardmäßig Siegelklassen, also zieht die Branche um eine bessere Richtung in dieser Hinsicht.
Elazar Leibovich
Warum sollten Klassen versiegelt werden?
James
@ James: Aus genau den Gründen, die Josh angibt. Das Entwerfen einer Klasse, die die Vererbung auf vernünftige und konsistente Weise ermöglicht, erfordert Zeit - und dies, ohne zu wissen, wie die Vererbung verwendet werden soll, ist noch schlimmer.
Jon Skeet
1
@ Pacerier: Denken Sie zum Beispiel an Unveränderlichkeit. Eine nicht versiegelte Klasse kann nicht behaupten, unveränderlich zu sein, da Unterklassen die Veränderlichkeit einführen können.
Jon Skeet
7

Dies ist eher ein Leitfaden als ein Feature, aber ich denke, es ist wichtig, weil es den Menschen als die kanonische und beste Lösung bereits zu sehr einfällt:

Das offizielle zu implementierende MusterIDisposable .

Es ist umständlich und es gibt bessere Wege .

Jordão
quelle
6

Ich weiß, dass es große Unterschiede zwischen den verschiedenen Timer-Klassen gibt. Aber konnten wir nicht trotzdem einen oder zwei von ihnen loswerden?

Nikie
quelle
4

Methoden und Arten von Arrayund List<T>die mit Linq überholt wurden, zum Beispiel:

  • Array.TrueForAll kann durch ersetzt werden Enumerable.All
  • Array.FindAll kann durch ersetzt werden Enumerable.Where
  • List<T>.ConvertAll kann durch ersetzt werden Enumerable.Select
  • Predicate<T> kann durch ersetzt werden Func<T, bool>
  • Converter<T,R> kann durch ersetzt werden Func<T, R>
  • IComparer<T> sollte wirklich ein Delegierter sein Func<T, T, int>
Nikie
quelle
3
Ich mag das, Predicate<T>weil es die Absicht aufnimmt, wie die Funktion verwendet wird, und ein wenig Tipparbeit spart.
Zebi
2

Nicht generische Delegaten Wie nicht generische Auflistungen sind auch nicht generische Delegaten nutzlos, da wir über die Funktions- und Aktionsserien verfügen. Und ich hätte die Varianten bei drei Parametern abgeschnitten. Wenn Sie mehr als drei Parameter haben, erstellen Sie eine Struktur und verwenden Sie diese als einzigen Parameter. Das Deklarieren eines bestimmten Delegaten für die Ereignisbehandlung ist nicht sehr TROCKEN.

Michael Brown
quelle
3
Wie würden Sie einen Delegaten für eine Methode definieren, die einen ref int mit Action oder Func annimmt? Wie würden Sie einen Combinator mit Func definieren? Das heißt, es gibt keine Möglichkeit, "DD delegieren (D d)" zu sagen. mit Func.
Eric Lippert
2
hmmm ... ich stehe korrigiert. Deshalb überlasse ich es Ihnen, die Werkzeuge, die ich verwende, in Ihre Hände zu legen;)
Michael Brown
@EricLippert: Ich würde gerne eine spezielle Delegierten-Klasse sehen, die durch CLR-Magie Delegierte "jeder" Art und Kombination von Wert- / Referenzparametern enthält Geben Sie] ein und lassen Sie alle Delegierten der richtigen Signatur davon erben. Code, der einen bestimmten Delegaten haben möchte, würde immer noch einen genauen Typ erfordern, aber Code, der eine bestimmte Signatur haben möchte, könnte den magischen Namen verwenden.
Superkatze
-1

asmx Web Services

Ich denke, sie sind heutzutage mit WCF ziemlich veraltet.

fretje
quelle
6
Ja, aber manchmal viel einfacher zu grillen. . .
Wyatt Barnett
-2

Winforms
Es wäre schön, nicht zwischen zwei Desktop-Plattformen navigieren zu müssen. WPF ist genau das Richtige für Sie. Es ist daher frustrierend, über eine vollständige Redundanz auf Plattformebene zu verfügen.

Morgan Herlocker
quelle
Winforms scheint viel stabiler, schneller und weniger
fehlerhaft
Wenn Sie nur eine kleine Desktop-App hacken müssen, ist WPF ein großer Overkill.
Kyralessa,
Es scheint, dass WPF zwischenzeitlich zugunsten von WinRT ziemlich veraltet ist. Mir scheint jedoch, dass Winforms in der Geschäftsentwicklung lebendiger ist als WPF. Siehe auch stackoverflow.com/questions/913417/…
Doc Brown,