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
String
in Char
konvertiert und repräsentiert sein erstes Zeichen.Char
auf String
einzig vernünftige Weise in String
konvertiert.
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
String
in ein Char
Array konvertiert, das aus allen Zeichen besteht.- Das
Char
Array wird in einen String
konvertiert, 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
Nothing
in einen aussagekräftigen Typ konvertiert wird und in einem nullable
signifikanten Typ nicht null
. - Erweitern Sie
Nothing
auf 0
, 0.0
, ChrW(0)
, False
, #1/1/0001 12:00:00 AM#
ChrW(0)
#1/1/0001 12:00:00 AM#
oder New 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!"
Null
Wie Null
oder Nothing?
- 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 # nur null
. - 2005 - C # fügt
default(T)
(ein Standardwert vom Typ T
), 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 von Nothing
geschlossen wird. - 2017 - C # fügt
default
hinzu ( default
im Kontext), da es viele Szenarien gibt, in denen die Angabe von T
redundant 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 über Nothing
und Nothing?
sprechen Nothing?
einer Person etwas erklären. - Die Syntax ist möglicherweise zu hässlich (z. B.
Nothing?
). - Das Nullausdrucksskript wird bereits von
Nothing
geschlossen, 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
Nothing
für veraltet erklärt. Nothing
und Null
verhalten 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)
:
- , — ( ).
System
System.Windows.Forms
— , , System
System.Windows
System.Windows
System.Windows.Forms
. - , , , .
System
Windows
, Windows
Form
.
, , . . 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.PropertyChangedEventArgs
System.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
:
- ;
- ( );
- , ,
Long
Integer
(. «»); - (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# (==, !=, >, <, >=, <=)
bool
bool?
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 . , . , . .