Im 
ersten Teil des Artikels fand das Thema der Überlegenheit von VB.NET gegenüber C # in Bezug auf die TIOBE-Bewertung in den Kommentaren eine lebhafte Antwort. 
Schauen wir uns daher auf 
Anraten von AngReload die 
Trends von StackOverflow an.

C # ist immer noch stark! Die Revolution, über die beim letzten Mal so lange gesprochen wurde, wird abgesagt! Hurra, Genossen! Oder nicht? Die TIOBE-Bewertung basiert auf Suchmaschinenabfragen und die SO-Bewertung basiert auf Tags aus gestellten Fragen. Vielleicht wissen die Entwickler von VB.NET, zu denen viele Leute gehören, die keine Spezialitäten haben, einfach nichts über die Existenz von StackOverflow? Oder wenn Sie über Google oder sogar Bing dort angekommen sind, wissen Sie nicht, wie Sie eine Frage stellen sollen? Oder vielleicht haben sie genug Miscrosoft-Dokumentation und alle wenigen Fragen wurden bereits beantwortet.
Auf die eine oder andere Weise ist der Anteil von VB.NET spürbar und stabil, wenn auch nicht in erster Linie in Bezug auf das Volumen. Und natürlich wäre ein solches Ergebnis ohne ein starkes Team von Designern und Sprachentwicklern nicht möglich gewesen. Unten finden Sie den zweiten Teil der Übersetzung eines Artikels eines Mitglieds dieses Teams, 
Anthony Green .
Inhalt
Konvertierungen
34. Boolesche Transformationen
Das Konvertieren von 
Boolean True in einen vorzeichenbehafteten numerischen Typ ergibt 
-1 und in einen vorzeichenlosen Typ den Maximalwert für diesen Typ, während es in C # keine solchen Konvertierungen gibt. Die 
Convert.ToInt32 Methode konvertiert jedoch beispielsweise 
True in 
1 , und so wird sie am häufigsten in 
IL . In der entgegengesetzten Richtung wird jede andere Zahl als 
0 in 
True .
Warum? Der Grund, warum VB die Verwendung von 
-1 bis 
1 bevorzugt, ist, dass die bitweise Negation von 0 (alle Bits werden auf 0 gesetzt) in einer beliebigen Sprache 
-1 (alle Bits werden auf 
1 ), sodass die Verwendung dieses Werts logisch und bitweise kombiniert Operationen wie 
And , 
Or und 
Xor .
Konvertierungen zu und von den Zeilen "True" und "False" werden ebenfalls unterstützt (natürlich ohne Berücksichtigung der Groß- und Kleinschreibung).
35. Konvertierungen zwischen Aufzählungstypen sowie zwischen Aufzählungstypen und ihren Basistypen sind völlig unbegrenzt, selbst wenn Option Strict auf Ein gesetzt ist
Aus philosophischer Sicht bezieht sich eine Sprache eher auf 
Enum als eine Menge benannter Konstanten eines grundlegenden Ganzzahltyps. Der Ort, an dem dies am offensichtlichsten ist, ist Gleichheit. Es ist immer zulässig, eine Ganzzahl mit einem Aufzählungswert zu vergleichen, während dies in C # einen Fehler ergibt.
Story Time: Die Roslyn-API wurde mehrfach intern überarbeitet. In jeder von ihnen wurde jedoch für jede Sprache eine 
SyntaxKind Aufzählung zugewiesen, die 
IfStatement , welche Syntax der Knoten darstellt (z. B. 
IfStatement , 
TryCastExpression ). Einmal verwendete ein Entwickler eine API, die versuchte, von der Sprache zu abstrahieren, und gab einen der 
SyntaxKind Werte zurück, jedoch nur als 
Integer . Ohne Fehler beim Vergleich von Raw 
Integer und 
SyntaxKind , kam dieser Entwickler sofort in mein Büro und beschwerte sich: 
„int is Implementierungsdetail, ich hätte gezwungen sein müssen, eine Besetzung zu machen! “ .
Im Laufe der Jahre haben wir bei der nächsten Überarbeitung der API die Eigenschaften ( 
Property Kind As SyntaxKind ), die auf einen sprachspezifischen Typ 
Property Kind As SyntaxKind , vollständig entfernt, und alle APIs haben begonnen, 
Integer . Der gesamte C # -Code war kaputt und der gesamte VB-Code funktionierte weiter, als wäre nichts passiert.
Wenig später beschlossen wir, diese Eigenschaft in 
RawKind und sprachspezifische Erweiterungsmethoden 
Kind() hinzuzufügen. Der gesamte C # -Code war fehlerhaft, da zum Aufrufen von Methoden Klammern erforderlich waren. Da sie jedoch in VB nicht benötigt wurden, funktionierte der gesamte VB-Code wieder, als wäre nichts passiert.
36. Die Prüfung auf Überlauf / negativen Überlauf für Ganzzahlarithmetik wird vollständig von der Kompilierungsumgebung (Projekteinstellungen) gesteuert, aber VB und C # verwenden unterschiedliche Standardwerte. In VB ist die Überlaufprüfung standardmäßig aktiviert
Integrale Typen haben einen Bereich, sodass 
Byte beispielsweise Werte von 0 bis 255 darstellen kann. Was passiert also, wenn Sie 
Byte 1 zu 
Byte 255 hinzufügen? Wenn die Überlauf- / Unterlaufprüfung deaktiviert ist, wird der Wert auf 0 
SByte . Wenn der Typ signiert ist, wird auf die niedrigste negative Zahl 
SByte (z. B. -128 für 
SByte ). Dies weist höchstwahrscheinlich auf einen Fehler in Ihrem Programm hin. Wenn die Überlauf- / Unterlaufprüfung aktiviert ist, wird eine Ausnahme ausgelöst. Um zu verstehen, was ich meine, werfen Sie einen Blick auf diese harmlose 
For Schleife.
 Module Program Sub Main() For i As Byte = 0 To 255 Console.WriteLine(i) Next End Sub End Module 
Github-QuellcodeStandardmäßig löst diese Schleife eine Ausnahme in VB aus (da die letzte Iteration der Schleife über die 
Byte Grenze hinausgeht. Bei 
Byte Überlaufprüfung wird sie jedoch wiederholt, da i nach 255 wieder 0 wird.
Unterlauf ist die umgekehrte Situation, wenn das Subtrahieren unter den Minimalwert für den Typ den Maximalwert ergibt.
Eine häufigere Überlaufsituation ist einfach die Addition von zwei Zahlen. Nehmen Sie die Zahlen 130 und 150, beide als 
Byte . Wenn Sie sie zusammenfügen, lautet die Antwort 280, was nicht in Byte passt. Ihr Prozessor nimmt dies jedoch nicht wahr. Stattdessen berichtet er, dass die Antwort 24 ist.
Das hat übrigens nichts mit Conversions zu tun. Das Hinzufügen von zwei Bytes ergibt ein Byte; So funktioniert binäre Mathematik. Sie können jedoch auch einen Überlauf erhalten, indem Sie beispielsweise eine Konvertierung durchführen, wenn Sie versuchen, Long in Integer zu konvertieren. Ohne auf Überlauf zu prüfen, schneidet das Programm einfach die zusätzlichen Bits und Sachen so weit ab, wie es in diese Variable passt.
Was ist der Unterschied? Leistung. Das Überprüfen der CLR auf Überlauf erfordert im Vergleich zur Nichtprüfungsoption wie bei allen anderen Sicherheitsüberprüfungen etwas mehr Rechenzeit. VB basiert auf der Philosophie, dass Entwicklerproduktivität wichtiger ist als Rechenleistung. Daher ist die Sicherheitsüberprüfung standardmäßig aktiviert. Das 
heutige C # -Entwicklungsteam trifft 
möglicherweise eine andere Entscheidung über die Standardeinstellungen des Projekts. Angesichts der Tatsache, dass die ersten C # -Entwickler von C / C ++ - Entwicklern stammten, würde diese Gruppe wahrscheinlich verlangen, dass der Code nichts weiter tut, was Prozessorzyklen kosten könnte ;; 
Das ist ein schwieriger philosophischer Unterschied .
Nuance: Selbst wenn die Überlauf- / Unterlaufprüfung deaktiviert ist, 
NaN die Konvertierung von 
PositiveInfinity , 
NegativeInfinity und 
NaN von 
Single oder 
Double in 
Decimal eine Ausnahme aus, da keiner dieser Werte im Prinzip in Decimal dargestellt werden kann.
37. Beim Konvertieren von Gleitkommazahlen in ganzzahlige Typen werden Banker eher gerundet als abgeschnitten
Wenn Sie in VB 1,7 in eine Ganzzahl konvertieren, ist das Ergebnis 2. In C # ist das Ergebnis 1. Ich kann nichts über mathematische Regeln außerhalb Amerikas sagen, aber wenn ich von einer reellen Zahl zu einer Ganzzahl wechsle, runde ich instinktiv. Und keiner von denen, die ich außerhalb des Programmiererkreises kenne, glaubt, dass die nächste Ganzzahl zu 1,7 1 ist.
Es gibt tatsächlich mehrere Rundungsmethoden, und die in VB (und in der Math.Round-Methode) verwendete Rundungsart wird standardmäßig als Bankrundung oder Rundung von Statistikern bezeichnet. Sein Wesen ist, dass für eine Zahl in der Mitte zwischen zwei ganzen Zahlen VB auf die nächste gerade Zahl rundet. Also wird 1,5 auf 2 und 4,5 auf 4 gerundet. Was eigentlich nicht so funktioniert, wie wir es in der Schule gelernt haben - mir wurde beigebracht, von 0,5 aufzurunden (technisch gesehen von Null auf die Seite). Wie der Name schon sagt, hat die Bankrundung den Vorteil, dass Sie bei einer großen Anzahl von Berechnungen beim Runden in zwei Hälften teilen und nicht immer Geld ausgeben oder behalten. Mit anderen Worten, bei einem großen Satz begrenzt dies die Datenverzerrung auf die endgültige statistische Abweichung.
Woher kommt der Unterschied? Das Runden ist intuitiver und praktischer und wird schneller abgeschnitten. Wenn Sie die Verwendung von VB in LOB-Anwendungen in Betracht ziehen, insbesondere in Anwendungen wie Excel-Makros, die unter VBA ausgeführt werden, kann das einfache Löschen von Dezimalstellen ... Probleme verursachen.
Ich denke, es ist offensichtlich, dass die Konvertierungsmethode immer ein kontroverses Thema ist und explizit angegeben werden sollte, aber wenn Sie eine einzelne auswählen müssen ...
38. Es ist kein Fehler, NotInheritable-Klassen in / von Schnittstellen zu konvertieren, die sie zur Kompilierungszeit nicht implementieren
Wenn Sie eine nicht vererbbare Klasse auf eine Schnittstellenimplementierung prüfen, können Sie im Allgemeinen beim Kompilieren nachvollziehen, ob eine solche Konvertierung möglich ist, da Sie alle Schnittstellen dieses Typs und alle ihre Basistypen kennen. Wenn der Typ vererbt wird, können Sie nicht sicher sein, dass eine solche Konvertierung nicht möglich ist, da der Typ des referenzierten Laufzeitobjekts möglicherweise einen abgeleiteten Typ hat, der diese Schnittstelle implementiert. Es gibt jedoch eine Ausnahme aufgrund von COM-Interop, wenn zur Kompilierungszeit möglicherweise nicht sichtbar ist, dass der Typ etwas mit der Schnittstelle zu tun hat, dies jedoch zur Laufzeit der Fall ist. Aus diesem Grund generiert der VB-Compiler in solchen Fällen eine Warnung.
Warum? VB und COM sind zusammen aufgewachsen, als sie Kinder in der alten Nachbarschaft waren. Daher gibt es im Sprachdesign mehrere Lösungen, bei denen VB den Dingen große Aufmerksamkeit schenkt, die zum Zeitpunkt der Veröffentlichung von .NET 1.0 nur in COM vorhanden waren.
39. Der Versuch, null in einen aussagekräftigen Typ zu entpacken (zu entpacken), führt zu einem Standardwert des Typs und nicht zu einer NullReferenceException
Ich glaube, dass dies technisch auch für Referenztypen gilt, aber ja:
 CInt(CObj(Nothing)) = 0 
Warum? Weil 
CInt(Nothing) = 0 ist und die Sprache tendenziell etwas konsistent ist, unabhängig davon, ob Sie Ihre Variablen eingegeben haben oder nicht. Dies gilt für jede Struktur, nicht nur für integrierte sinnvolle Typen. Weitere Informationen finden Sie in der 
Begründung unter Nr. 25 .
40. Unboxing unterstützt primitive Typkonvertierungen
Sowohl in VB als auch in C # können Sie 
Short in 
Integer konvertieren. Was ist jedoch, wenn Sie versuchen, gepackte 
Short in 
Integer zu konvertieren? In VB wird 
Short zuerst entpackt und dann in 
Integer konvertiert. In C # wird eine 
InvalidCastException ausgelöst, es sei denn, Sie entpacken kurz vor der Konvertierung in 
int manuell.
Dies gilt für alle internen Konvertierungen, d. H. Gepackte numerische Typen, Konvertierungen zwischen Zeichenfolgen und numerischen Typen, Zeichenfolgen und Datumsangaben (ja, Dezimal und Datum sind primitive Typen).
Warum? Um ein konsistentes Verhalten sicherzustellen, unabhängig davon, ob Ihr Programm vollständig eingegeben, als Objekt eingegeben oder von einer Option zur anderen überarbeitet wurde. Siehe 
Nr. 39 oben.
41. Es gibt Konvertierungen zwischen String und Char
- Stringin- Charkonvertiert und repräsentiert sein erstes Zeichen.
- Charauf- Stringeinzig vernünftige Weise in- Stringkonvertiert.
Weil sich niemand außer mir an die Syntax eines Zeichenliteral in VB erinnert (und es sollte nicht).
42. Es gibt Konvertierungen zwischen String und Char Array
- Stringin ein- CharArray konvertiert, das aus allen Zeichen besteht.
- Das CharArray wird in einenStringkonvertiert, der aus allen seinen Elementen besteht.
Für die Bestimmtheit: Diese Transformationen erstellen neue Objekte, Sie erhalten keinen Zugriff auf die interne 
String Struktur.
Witzige Geschichte: Ich habe einmal eine Änderung zwischen .NET 3.5 und 4.0 gefunden (oder vielleicht gemeldet und recherchiert), weil das .NET-Team zwischen diesen Versionen den 
ParamArray Modifikator zum zweiten 
String.Join Überladungsparameter hinzugefügt hat, der ein Array von Zeichenfolgen enthält . Die genauen Annahmen gehen mit der Zeit verloren (wahrscheinlich zum Besseren), aber meiner Meinung nach liegt der Grund darin, dass Sie mit dem Modifikator 
ParamArray jetzt ein 
Char Array in eine Zeichenfolge konvertieren und als separates Element an das Parameter-Array übergeben können. Lustiges Thema.
43 und 44. Konvertierungen von Zeichenfolgen in numerische Typen und Datumsangaben unterstützen (normalerweise) die Literalsyntax.
- CInt("&HFF") = 255
- CInt("1e6") = 1_000_000
- CDate("#12/31/1999#") = #12/31/1999#
Dies funktioniert mit Basispräfixen und ermöglicht die bequeme Konvertierung hexadezimaler (oder oktaler) Eingaben in eine Zahl: 
CInt("&H" & input) . Leider verschlechtert sich diese Symmetrie zum Zeitpunkt dieses Schreibens, da die VB-Laufzeit nicht aktualisiert wurde, um das binäre Präfix & B oder das 
1_000 stellige Gruppentrennzeichen zu unterstützen, aber ich hoffe, dass dies in der nächsten Version behoben wird. Die wissenschaftliche Notation funktioniert, jedoch ohne 
CDate("2012-03-19T07: 22Z") = #3/19/2012 02:22:00 AM# unterstützen auch Standard-Datumsformate. 
CDate("2012-03-19T07: 22Z") = #3/19/2012 02:22:00 AM# funktioniert das in ISO-8601 verwendete JSON-Format auch: 
CDate("2012-03-19T07: 22Z") = #3/19/2012 02:22:00 AM# .
Warum? Ich kenne keinen anderen Grund als Bequemlichkeit. Aber ich möchte 
wirklich Unterstützung für andere gängige Formate anbieten, die heute im Netzwerk fast allgegenwärtig sind, wie #FF, U + FF, 0xFF. Ich denke, dies könnte das Leben in einigen Arten von Anwendungen erheblich erleichtern ...
45. KEINE Konvertierungen zwischen Char und Integer-Typen
WAS?!?!?Sind Sie überrascht, nachdem Sie über all diese zusätzlichen Transformationen gelesen haben? VB verbietet Konvertierungen zwischen 
Char und 
Integer :
- CInt("A"c)wird nicht kompiliert.
- CChar(1)wird nicht kompiliert.
Warum? Es ist nicht klar, was passieren wird. Normalerweise verwendet VB in solchen Situationen einen pragmatischen und / oder intuitiven Ansatz, aber um 
CInt("1") auszudrücken 
CInt("1") würde die Hälfte der Leser die Nummer 1 ( 
CInt("1") 1) und die Hälfte die Nummer 49 (ASCII / UTF-Code für) erwarten Zeichen 1). Anstatt in der Hälfte der Fälle die falsche Wahl zu 
ChrW verfügt VB über spezielle Funktionen zum Konvertieren von Zeichen in ASCII / Unicode-Codes und umgekehrt, 
AscW bzw. 
ChrW .
Ausdrücke
46. Nichts <> null
Das Literal 
Nothing in VB bedeutet nicht 
null . Dies bedeutet 
"der Standardwert für den Typ, für den es verwendet wird", und es kommt nur so vor, dass für Referenztypen der Standardwert null ist. Der Unterschied ist nur wichtig, wenn er in einem Kontext verwendet wird, in dem:
- Nichts nimmt einen bedeutenden Typ an und ...
- Aus dem Zusammenhang ist nicht ersichtlich, dass er dies tut.
Schauen wir uns einige Beispiele an, die veranschaulichen, was dies bedeutet.
Das erste, vielleicht ein bisschen seltsam, aber ich glaube nicht, dass die meisten Leute von dem Verständnis, dass dieses Programm "True" drucken wird, in die Luft gesprengt werden:
 Module Program Sub Main() Dim i As Integer = 0 If i = Nothing Then Console.WriteLine("True") End If End Sub End Module 
Github-QuellcodeDer Grund ist ganz einfach: Sie vergleichen 
Integer (0) mit dem Standardwert seines Typs (auch 0). Das Problem tritt in VB2005 / 2008 auf, wenn Sie nullfähige sinnvolle Typen hinzufügen. Schauen Sie sich dieses Beispiel an:
  Module Program Sub Main() Dim i = If(False, 1, Nothing) End Sub End Module 
Github-QuellcodeWie kann jemand vorschlagen, dass Typ 
i eine 
Integer? ( 
Nullable(Of Integer) ). Dies ist jedoch nicht der Fall, da 
Nothing den Typ aus dem Kontext erhält und der einzige Typ in diesem Kontext vom zweiten Operanden stammt. Dies ist eine einfache 
non-nullable Integer (technisch gesehen hat 
Nothing nie einen Typ). Eine andere Möglichkeit, dieses Problem zu betrachten, ist das folgende Beispiel:
 Module Program Sub Main() M(Nothing) End Sub Sub M(i As Integer) Console.WriteLine("Non-nullable") End Sub Sub M(i As Integer?) Console.WriteLine("Nullable") End Sub End Module 
Github-QuellcodeAuch hier scheint es intuitiv, dass 
Nothing einen "nullbaren" Hinweis hinzufügt und dass die Sprache eine Überladung auswählt, die 
nullable akzeptiert, dies jedoch nicht (wählt 
non-nullable , da es "am spezifischsten" ist). Zumindest kann davon ausgegangen werden, dass der 
Nothing Ausdruck wie null in C # überhaupt nicht für 
Integer gilt und dass die nullfähige Überladung von der Ausnahmemethode ausgewählt wird. Dies basiert jedoch wiederum auf der falschen Vorstellung, dass 
Nothing = null (Is null?) .
Nuance: In C # 7.1 wurde ein neuer 
default hinzugefügt, der mit 
Nothing in VB übereinstimmt. Wenn Sie alle drei obigen Beispiele in C # mit 
default anstelle von 
null neu schreiben, erhalten 
Sie genau das gleiche Verhalten .
Was kann man dagegen tun? Es gibt mehrere Vorschläge, aber noch keiner hat gewonnen:
- Zeigen Sie jedes Mal eine Warnung an, wenn Nothingin einen aussagekräftigen Typ konvertiert wird und in einemnullablesignifikanten Typ nichtnull.
- Erweitern Sie Nothingauf0,0.0,ChrW(0),False,#1/1/0001 12:00:00 AM#ChrW(0)#1/1/0001 12:00:00 AM#oderNew T(der Standardwert für jede Struktur) jedes Mal, wenn der Wert zur Laufzeit einer von ist oben aufgeführt.
- Fügen Sie eine neue Syntax hinzu, die "Null, nein, wirklich!" NullWieNulloderNothing?
- Fügen Sie eine neue Syntax in Form eines Suffixes (?) Hinzu, das den Wert in nullable umschließt, um den Typ abzuleiten, z. B. If(False, 0?, Nothing)
- Fügen Sie nullfähige Konvertierungsoperatoren für integrierte Typen hinzu, um Hinweise zur Typinferenz zu vereinfachen, z. B. If (False, CInt? (0), Nothing)
Ich würde gerne Ihre Gedanken in den Kommentaren und / oder 
auf Twitter hören .
Um es zusammenzufassen:
- Früher - VB6 und VBA haben "Nothing", "Null", "Empty" und "Missing", was verschiedene Dinge bedeutet.
- 2002 - In VB.NET gibt es nur Nothing(der Standardwert in einem bestimmten Kontext) und in C # nurnull.
- 2005 - C # fügt default(T)(ein Standardwert vom TypT), da neu hinzugefügte Generika eine Situation schaffen, in der Sie einen Wert initialisieren müssen, aber nicht wissen, ob es sich um einen Referenztyp oder einen signifikanten Wert handelt. VB unternimmt nichts, da dieses Skript bereits vonNothinggeschlossen wird.
- 2017 - C # fügt defaulthinzu (defaultim Kontext), da es viele Szenarien gibt, in denen die Angabe vonTredundant oder unmöglich ist
VB widersetzt sich weiterhin dem Hinzufügen eines 
Null Ausdrucks (oder eines Äquivalents), weil:
- Die Syntax wird die Änderung unterbrechen.
- Die Syntax wird die Änderung nicht unterbrechen, aber je nach Kontext unterschiedliche Bedeutungen haben.
- Die Syntax ist zu unauffällig (z. B. Nothing?). Stellen Sie sich vor, Sie müssen laut überNothingundNothing?sprechenNothing?einer Person etwas erklären.
- Die Syntax ist möglicherweise zu hässlich (z. B. Nothing?).
- Das Nullausdrucksskript wird bereits von Nothinggeschlossen, und diese Funktion ist die meiste Zeit vollständig redundant.
- Überall sollten alle Dokumentationen und Anweisungen aktualisiert werden, um die Verwendung einer neuen Syntax zu empfehlen, die für die meisten Szenarien grundsätzlich Nothingfür veraltet erklärt.
- Nothingund- Nullverhalten sich zur Laufzeit in Bezug auf späte Bindung, Transformationen usw. immer noch gleich.
- Es kann wie eine Waffe in einem Stich sein.
Irgendwie so.
Offtopic (aber verwandt)Hier ist ein Beispiel, das dem zweiten oben sehr ähnlich ist, jedoch ohne Typinferenz:
 Module Program Sub Main() Dim i As Integer? = If(False, 1, Nothing) Console.WriteLine(i) End Sub End Module 
Github-QuellcodeDieses Programm zeigt 0 an. Es verhält sich aus demselben Grund genauso wie das zweite Beispiel, zeigt jedoch ein separates, wenn auch verwandtes Problem. Was ist 
Dim i as Integer? = If(False, 1, Nothing) intuitiv 
Dim i as Integer? = If(False, 1, Nothing) Dim i as Integer? = If(False, 1, Nothing) sich genauso verhält wie 
Dim i As Integer? : If False Then i = 1 Else i = Nothing Dim i As Integer? : If False Then i = 1 Else i = Nothing . In diesem Fall ist dies nicht der Fall, da der bedingte Ausdruck 
(If) keine Informationen des endgültigen Typs an seine Operanden weiterleitet. Es stellt sich heraus, dass dadurch alle Ausdrücke in VB aufgeschlüsselt werden, die auf der so genannten endgültigen (kontextuellen) Typisierung ( 
Nothing , 
AddressOf , ein Array von Literalen, Lambda-Ausdrücken und interpolierten Zeichenfolgen) 
AddressOf laut Ausnahmen werfen. Hier ist ein Beispiel für eine nicht kompilierte Option:
 Module Program Sub Main() Dim i As Integer? = If(False, 1, Nothing) Console.WriteLine(i) Dim operation As Func(Of Integer, Integer, Integer) = If(True, AddressOf Add, AddressOf Subtract) End Sub Function Add(left As Integer, right As Integer) As Integer Return left + right End Function Function Subtract(left As Integer, right As Integer) As Integer Return left - right End Function End Module 
Github-QuellcodeDieses Programm wird nicht kompiliert. Stattdessen meldet es einen Fehler im 
If Ausdruck, der den Ausdruckstyp nicht bestimmen kann, wenn beide 
AddressOf Ausdrücke 
AddressOf Func(Of Integer, Integer, Integer) Delegaten 
Func(Of Integer, Integer, Integer) empfangen 
Func(Of Integer, Integer, Integer) .
, 
Nothing null (), 
Nothing nullability () 
If(,,) Nothing ( ) () — , 
.
47. ;
«3»:
 Module Program Sub Main() Dim i As Integer = 3 M((i)) Console.WriteLine(i) End Sub Sub M(ByRef variable As Integer) variable = -variable End Sub End Module 
GitHubC# «-3». , VB — , 
. , 
M(3) , 
M(i) , 
i , . C# ( ) , M .
Warum? VB 
. Quick Basic (Copyright 1985), . , 
2002 , .
№1: « » , Visual Basic .NET.
№2: Roslyn ( , 
( ) ( )), : . C# , 
((a + b) * c a + (b * c)) . , C#, C++, , , , . : « VB?» « C#?» 
source.roslyn.io — 
BoundParenthesized VB C#. , , .
48. Me —
VB.NET 
Me . , - , — , Me Structure . Me . C# 
this , 
this .
49.
VB, , :
 Class C Sub M() Extension() End Sub End Class Module Program Sub Main() End Sub <Runtime.CompilerServices.Extension> Sub Extension(c As C) End Sub End Module 
GitHubC# ( something.Extension). , C#, , 
this.Extension() .
Warum? , 
'Me.' , , , , . VB.NET . , .
50. (Static imports will not merge method groups)
VB « » (Java-, C# VB). , 
Imports System.Console WriteLine() . 2015 C# . VB Shared- , 
System.Console System.Diagnostics.Debug , 
WriteLine , . C# , , .
Warum? , , VB , C# ( ). , ( , ), … , .
, VB , VB , , , , , ( 
#6 ). VB . , VB 2002 .
51 52. (Partial-name qualification & Smart-name resolution)
:
- , — ( ). SystemSystem.Windows.Forms— , ,SystemSystem.WindowsSystem.WindowsSystem.Windows.Forms.
- , , , . SystemWindows,WindowsForm.
, , . . VB Imports , 
using C# .
, VB 
System , 
System , 
System . , . , 
ExtensionAttribute , 
<Runtime.CompilerServices.Extension> <System.Runtime.CompilerServices.Extension> .
C# . 
using System System.Threading Threading .
, C# , . , 
System , 
System.Threading Threading . , , , , .
, , VB, C# , 
Imports / 
using , C# using , , using .
(Quantum Namespaces) ( ), ! VB , . , 
System ComponentModel System.Windows.Forms ComponentModel ? 
ComponentModel . , 
ComponentModel.PropertyChangedEventArgs , ( , ). 
System.Windows.Forms (, , , , ), (ambiguity errors).
VB2015 (Smart Name Resolution), 
System System.Windows.Forms ComponentModel , , 
System.ComponentModel System.Windows.Forms.ComponentModel , . , , , , . , , , .. 
ComponentModel.PropertyChangedEventArgsSystem.ComponentModel.PropertyChangedEventArgs , 
System.Windows.Forms.ComponentModel.PropertyChangedEventArgs . , .
, 
Windows , ( ) ( ) ( ). 
WinForms/WPF UWP .
53. Add
#33 , VB - , . , , — , :
 Class Contact Property Name As String Property FavoriteFood As String End Class Module Program Sub Main() Dim contacts = New List(Of Contact) From { {"Leo", "Chocolate"}, {"Donnie", "Bananas"}, {"Raph", "The Blood of his Enemies"}, {"Mikey", "Pizza"} } End Sub <Runtime.CompilerServices.Extension> Sub Add(collection As ICollection(Of Contact), name As String, favoriteFood As String) collection.Add(New Contact With {.Name = name, .FavoriteFood = favoriteFood}) End Sub End Module 
GitHubC# , Roslyn C#, . , ( 
, ), VS2015.
54. ,
, VB 
Dim buffer(expression) As Byte Dim buffer = New Byte(expression) {} expression + 1 .
Microsoft BASIC, 
DIM ( dimension — ). , , , : 0 expression. Microsoft BASIC 1 ( , 1984), ( ), 2002 .
, - , , VB , BASIC C , , C, C- . , 
buffer(10) 0 10, 9!
55. VB - , C#
, . , VB ( ) , — . :
- CType({1, 2, 3}, Short())- CType(New Integer() {1, 2, 3}, Short ()),- Integer- Short.
- CType({1, 2, 3}, Short())- New Short() {1, 2, 3}. .
, , VB , C#. , :
- Dim empty As Integer() = {}
:
- Dim array As Predicate(Of Char)() = {AddressOf Char.IsUpper, AddressOf Char.IsLower, AddressOf Char.IsWhitespace}
( ):
- Dim byteOrderMark As Byte() = {&HEF, &HBB, &HBF} '.
, 
IList(Of T) , 
IReadOnlyList(Of T) , 
ICollection(Of T) , 
IReadOnlyCollection(Of T) IEnumerable(Of T) , , , 
ParamArray IEnumerable .
Warum? , VB. , . 2008 VB C# «» {}, - ( , , ). , , , + , . .
56.
, LINQ. , .
, , 
.
57. CType, DirectCast C#
/ VB C#.
VB 
CType :
- ;
- ( );
- , , LongInteger(. «»);
- (unboxes) ;
- ;
- ( CTypeDynamic).
VB 
DirectCast :
- ;
- ;
- ( Integer Byte);
- ;
- ( );
- .
C# — 
(Type)expression :
CType C# , . , . VB C# , IL . 
, C#, , . .
, 
CType , (, ). 
CType , 
DirectCast , . , , IL : 
Object ( 
ValueType ) CLR «unbox» VB-, , (, 
Short Integer ). , , C#. . , .
Warum? . , , , , .
58. «»
, , 
5 Mod 2 * 3 5 VB, «» C# 
5 % 2 * 3 3.
, , . , (, (\) VB), , , 
. 
!59. ; + & ; + VB <> + C#
, + () & () VB + C#.
String :VB- “1” + 1 = 2.0
- “1” & 1 = “11”
C#, + &VB- “obj: “ + AppDomain.CurrentDomain ' Error: + not defined for String and AppDomain.
- ”obj: “ & AppDomain.CurrentDomain ' Error: & not defined for String and AppDomain.
- ”obj: “ + CObj(AppDomain.CurrentDomain) ' Exception, no + operator found.
- ”obj: “ & CObj(AppDomain.CurrentDomain) ' Exception, no & operator found.
C#- «obj: » + AppDomain.CurrentDomain == «obj: » + AppDomain.CurrentDomain.ToString()
- «obj: » + (object)AppDomain.CurrentDomain == «obj: » + AppDomain.CurrentDomain.ToString()
- «obj: » + (dynamic)AppDomain.CurrentDomain == «obj: » + AppDomain.CurrentDomain.ToString()
:VBC#String Enum:VB- “Today: ” + DayOfWeek.Monday ' Exception: String «Today: » cannot be converted to Double.
- “Today: ” & DayOfWeek.Monday = “Today: 1”
- “Today: ” & DayOfWeek.Monday.ToString() = “Today: Monday”
C#- «Today: » + DayOfWeek.Monday == «Today: Monday»
: , + VB, - . + , , - . Warum? :
- “10” — “1” = 9.0,
- “5” * “5” = 25.0,
- “1” << “3” = 8,
- “1” + 1 = 2.0,
- “1” + “1” = “11”
. — .
: +, 
. , &, , ( 
, ). , , .
60. : 3 / 2 = 1,5
— : 
« ?» . «». : 
« . ?»VB C#.
C, , , 
« 5 9?» , \. , , , , 0 ( , - 
INumeric ).
61. ^ Math.Pow
Math.Pow . , . , ( 
custom ) ( , 
System.Numerics.BigInteger ).
: F# **, VB F# : 
op_Exponent op_Exponentiation . F# 
Pow . . , .
62. =/<> /
C# '==' () , , ( ). VB . VB ( 
Is/IsNot ) .
: - Roslyn , . . . VB , = , C# , , , .
63. =/<> ( )
VB .
-, ( ) - ( ), , 
Option Compare Binary Option Compare Text . 
Option Compare Binary , , VS.
( ), , 
API. :
- /: “A” = “a”/“A” <> “a”
- : “A” > “a”
- Select Case: Select Case “A” : Case “a”
:
- Equals: “A”.Equals(“a”)
- Contains: ”A”.Contains(“a”)
- Distinct: From s In {“A”, “a”} Distinct
, , : VB . , 
Option Compare , «Empty».
 Module Program Sub Main() Dim s As String = Nothing If s = "" Then Console.WriteLine("Empty") End If End Sub End Module 
GitHubs = "" VB — 
String.IsNullOrEmpty(s) .
, , , , , . , , .
Warum? Option Compare Text , , . , , .
, , , , .
, , . , . , , (collation) SQL Server, . , VB VB6, VBA Office, Excel Access, VBScript Windows, -, -… . , , .NET API , Option Compare Text, . , .NET API, .
null, , . VB6 . 
String "". , VB 
String . VB, 
Left Mid , 
String . null . 
Len(CStr(Nothing)) = 0 Left(CStr(Nothing) , 
5) = "" , 
CStr(Nothing).Length CStr(Nothing).Trim() .
, 
? . ( ).
:, , , . ! VB , , 
"String A" = "String B" , 
Microsoft.VisualBasic.CompilerServices.Operators.CompareString , - , , . LINQ- . , VB ( ). , , - , . LINQ-to-SQL, LINQ-to-Entities , Microsoft. , VB , !
, C#, VB, LINQ . : 1) , VB , , 2) , VB , , LINQ-. , VB ().
: , « API». 
Option Compare VB, 
InStr.Replace Microsoft.VisualBasic.Strings . , ?
, , , ? , , , : , , .
64. Nullable ( null )
VB C# - nullable. , (null-propagation).
SQL, , , null. , (, +), null, null. 
"?." : 
obj?.Property obj null, null, .
nullable , VB, C# . - : .
VB, nullable , null, null . 1 + null null null + null null. , (, = <>) C#:
- VB, Is/IsNot,Boolean?
- C# (==, !=, >, <, >=, <=) boolbool?
VB ( nullable ) null 
null . 
Boolean = 
Boolean? , 
True , 
False null . 
. C# 
non-nullable bool , 
.
, 
. null. VB 
NULL = 
NULL — 
NULL , TRUE.
, :

. 
Null , , , C# .
. C# VB, 
« null?» C# 
(if (value == null)) . VB , VB (=/<>) 
(Is/IsNot) , VB 
Is Nothing non-nullable Boolean .
, VB null, null. 
And/AndAlso Or/OrElse .
Integer? ( ), VB, C# null, :
- 1 AND NULL NULL
- 1 OR NULL NULL
Boolean? , VB .
- FALSE AND NULL FALSE
- TRUE OR NULL TRUE
- TRUE AND NULL NULL
- FALSE OR NULL NULL
, 
True/False , , null. , 
AndAlso OrElse .
C# (&&/||) (&/|) 
nullable boolean (bool?) . , , non-nullable boolean nullable boolean .
?VB , - :
 Imports System.ComponentModel Class BindableRange Implements INotifyPropertyChanged Property _EndDate As Date? Property EndDate As Date? Get Return _EndDate End Get Set(value As Date?)  
GitHub, , , , «EndDate change» . , , 
VB null ? , 
EndDate , , , 
Nothing .
VB : 
«, , . » :
 If value <> _EndDate Then _EndDate = value RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(NameOf(EndDate))) End If 
! . , 
non-nullable . , 
. , :
 If value Is Nothing AndAlso _EndDate Is Nothing Then Return If value <> _EndDate Then Return 
?, C# , VB. ( nullable , ), , null.
null — 
«» « » . .
null « » «» . , , : comparer, , comparer . Roslyn, 
Optional(Of T) , , , null, , .
, NULL « », VB :
- , « , ?» « ».
- : « , ?» « ».
, , 
SQL- . , NULL SQL , NULL. . , , NULL . , . , , ( ). , , , , , NULL , SQL ( ).
VB. 
nullable 2008 , VB ?LINQ to SQL
VB , , , , , , LINQ- . !
. SQL Server, , 
SET ANSI_NULLS OFF , SQL- C#, 
WHERE Column = NULL . , , OFF ( ). SQL Server ( ) . : 
« ? . , - Option ANSI_NULLS Off VB.NET?» . :

, , , , , SQL Server, VB.
Irgendwie so.
65. 1:1
, VB , , , . VB - , .
, , , , . VB , , , , , VB .
9.8.4 .
66. Function() a = b () => a = b
. , 
() => expression C# 
Function() expression VB. 
Function() -, - , VB. 
a = b , 
a b ( 
Boolean ), 
b . - (delegate relaxation) VB ( -) Sub- ( ). . 
() => a = b C# VB — 
Sub() a = b . — - 
, .
=, , . ( 
Sub -) , ( 
Function -) .
67. Async Function async void
C# 
async -, , , 
Task void , , 
Task , .
VB.NET , .. 
void Async Async Sub , 
Task Task(Of T) — 
Async Function . , , VB, (relaxing) 
Task Async void . 
Async Sub , , .
68. () VB
, VB:
 Class Foo  
GitHubVB, 
C#. -, 
Foo Select , , 
Where . 
Select , , 
Select , 
Integer . C# , 
.Where ( 
Select ). , , .
LINQ API. , VB C#, . , C# , « », , , , . - , «» , , -.
, VB 
, , C# , .
, Roslyn, : 
« (range variables)?» « ?» . . , VB , 
Let , C# — . , VB, C# 2012 , :
 using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace CSharpExamples { struct Point { public int X { get { return 0; } } public int Y { get { return 0; } } } class Foo { public IEnumerable<Point> Select<T>(Func<string, T> selector) { return new Point[0]; } } static class Program { static void Main(string[] args) { var c = new Foo(); var q = from X in c let Y = "" select Y.CompareTo(-1); } } } 
GitHub, — ? X, — 
string . 
let Y , string. , Point, 
X Y , , 
int X Y , «» . 
Y select , 
int int `, … .
, 
« ?» . VS2015 C# , «». , Roslyn C#, . , ( , ), - .
Warum? , , , . , , VB C# .
69 70. As From cast ; 'As'
( , …)
From x As Integer In y VB, , 
from int x in y C#.
-, C# , ( ) . 
.Cast<T>() . VB , , , , .
-, , 
.Cast ( ). , , , 
.Cast .Select .
Warum? . VB . , 
For Each x As T In collection , 
As T . 
From As For Each ( , 
As ).
71-75. Select , ,
Zum Beispiel:
- From x In y Where x > 10. ,- Select.
- From x In y Select x Where x > 10.
- From x In y Select x,- From x In y Select x = x,- x—- x,- x—- Select.- Select- From x In y Select z = x.ToString(),- x.
- From x In y Select x.FirstName,- From x In y Select FirstName = x.FirstName.
- From x In y Select x.FirstName, x.LastName—- From x In y Select New With {x.FirstName, y.LastName}, , .- IEnumerable(Of $AnonymousType$), .
Warum? ( 
Amanda Silver ). !
- , Select, SQL ,Select, . LINQ VB Select , SQL, From .
- , , .
- , Select, SQL, - - . VB comma separated ( ) -.
- , Select, , , , , , , — .
? , , - , , :
 Module Program Sub Main() Dim numbers = {1, 2, 3}  
GitHubBC36606: Range variable name cannot match the name of a member of the 'Object' class BC30978: Range variable '…' hides a variable in an enclosing block or a range variable previously defined in the query expression — , 
Object , , , , . ( 
n.ToString() ), . , .
76+.
. … … . … 20-25 ( 
— .. ).
Minute der Werbung. 15-16 - .NET- DotNext 2019 Piter . , . , . .