VB.NETずCの違いの完党なリスト。 パヌト1

画像

2018幎の TIOBEの評䟡によるず 、VB.NETはCを䞊回りたした。 偶然かどうかはわかりたせんが、2月にCの䜜成者の1人であるEric Lippertは、Roslynコンパむラの元チヌムメむトであり、熱烈なVB.NETファンであるAnthony Greenの友人のブログに泚目するよう読者に促したした。 「このようなリ゜ヌスは、専門家からの詳现な詳现情報であり、ドキュメントを読むだけでは簡単に芋぀けるこずはできたせん」ず゚リックは曞いおいたす。 Anthony Greenの蚘事「VB.NETずCの違いの網矅的なリスト」の翻蚳の最初の郚分に泚目しおください。 おそらく、これらの蚀語の栌付けのダむナミクスの秘密は、これらの違いにありたす。

私の人生のほが半分の期間、私は、最も人気のある2぀の.NET蚀語がどれだけ䌌おいるか、たたは異なっおいるかに぀いお、数え切れないほどの議論を目の圓たりにしお参加したした。 最初に、アマチュアずしお、次にプロずしお、そしお最埌に、顧客の擁護者、プログラムマネヌゞャヌ、蚀語デザむナヌずしお、私は次のようなこずを䜕床も聞いたり読んだりしおいるず蚀っおも過蚀ではありたせん。
「... VB.NETは、Cのように、実際にはILの䞊にある薄い局です...」
たたは
「... VB.NETは実際にはセミコロンなしの単なるCです...」
蚀語がXML倉換たたはスタむルシヌトであるかのように。

そしお、熱心な蚪問者がコメントでこれを曞いおいない堎合、これは次のような質問で暗瀺されるこずがよくありたす。 「こんにちは、アン゜ニヌ 1぀の堎所でこのような小さな違いに遭遇したした-これはバグですか この䞖界のすべおの善ず聖の名においお同䞀であるはずのこれらの2぀の同䞀の蚀語は、この1か所でどのように分散できたすか なぜそのような䞍正が必芁なのでしょうか

「 分離 」突然倉異が発生するたでは同じであるかのように、 その埌分離した皮になりたした。 ハァッ

しかし、私はそれを理解しおいたす。 マむクロ゜フトに入瀟する前は、このアむデアを挠然ず保持し、敵察者に察応したり、誰かを安心させるための議論ずしおそれを䜿甚したこずもありたした。 私は圌女の魅力を理解しおいたす。 理解しやすく、繰り返しも非垞に簡単です。 しかし、Roslyn本質的にVBずCをれロから完党に曞き換えるに5幎間取り組んで、私はこの考えがいかに明癜に間違っおいるかを理解したした。 開発者ずテスタヌのチヌムず協力しお、䞡方の蚀語のあらゆるむンチを再実装し、䞡方の蚀語で蚘述された数癟䞇行のコヌドを持぀巚倧なマルチプロゞェクト゜リュヌションでツヌルを再実装したした。 そしお、倚くの開発者が圌らの間を行き来するこず、以前のバヌゞョンの結果ず経隓ずの高いレベルの互換性、そしおAPIの巚倧なボリュヌムを非垞に詳现に確実に再珟する必芁性を考慮しお、私は違いを非垞に密接に知るこずを匷いられたした。 実際、私は毎日、VB.NET私の奜きな蚀語に぀いお䜕か新しいこずを孊んだように思えたした。

そしお最埌に、少なくずも次の時間を節玄できるこずを期埅しお、座っお、過去15幎間にVB.NETを䜿甚しお䜜成したこずを孊んだこずを脳から取り出したした。

リストに進む前に、基本的なルヌルの抂芁を説明したす。


期埅を定矩し、さらに遅延するこずなく...

内容


非衚瀺のテキスト

構文ず前凊理



お知らせなど



説明曞



構文ず前凊理


1.キヌワヌドずVB挔算子は党角文字を䜿甚できたす


䞀郚の蚀語正確にはいく぀あるかはわかりたせんが、少なくずも䞀郚の圢匏の䞭囜語、日本語、韓囜語では党角文字が䜿甚されたす。 芁するに、これは、ほずんどのプログラマヌがそうであるように固定幅フォントを䜿甚する堎合、挢字は西で芋たラテン文字の2倍の氎平スペヌスを占めるこずを意味したす。 䟋



ここでは、日本語で曞かれた倉数宣蚀ず、同じく日本語で曞かれた文字列による初期化がありたす。 Bingトランスレヌタヌによるず、倉数は「挚拶」ず呌ばれ、行には「Hello World」ず衚瀺されたす。 日本語の倉数名の長さはわずか2文字ですが、最初のコメントが瀺すように、キヌボヌドが通垞提䟛する4぀の半角文字のスペヌスを占有したす。 数字の党角バヌゞョンず、日本語ず同じ幅のその他の印刷されたすべおのASCII文字がありたす。 これを実蚌するために、党角数字「1」ず「2」を䜿甚しお2番目のコメントを曞きたした。 これらは、最初のコメントず同じ「1」ず「2」ではありたせん。 数字の間にスペヌスはありたせん。 たた、文字のサむズが正確に2文字の幅ではなく、わずかなオフセットがあるこずがわかりたす。 これは、このプログラムが1行ず3行すべおで党角文字ず半角文字を混圚させるためです。

空癜は半角、英数字は党角です。 私たちは、テキストの配眮に倢䞭でない限り、プログラマヌではありたせん。 そしお、あなたが䞭囜語、日本語、韓囜語たたは蚀語にフルサむズの文字を䜿甚しおいる他の人で、母囜語で曞かれた識別子たたは文字列を䜿甚しおいる堎合、これらの小さなアラむメント゚ラヌは腹立たしいようです。

私の知る限り、日本語キヌボヌドによっおは、象圢文字ずラテン文字の切り替えは簡単ですが、党角のラテン文字を䜿甚するこずをお勧めしたす。 VBは、キヌワヌド、スペヌス、挔算子、さらには匕甚笊でこれをサポヌトしたす。 したがっお、これはすべお次のように蚘述できたす。



ご芧のずおり、このバヌゞョンでは、キヌワヌド、スペヌス、コメント、挔算子、匕甚笊でさえフルサむズバヌゞョンを䜿甚しおいたす。 カオスに秩序がもたらされたした。

はい 日本人はVBを䜿甚したす。 実際、英語に䌌た構文およびその理由にもかかわらず、フォヌラムで芋たほずんどのVBナヌザヌにずっお、英語は䞻芁蚀語ではありたせん。 マむクロ゜フトでの仕事䞭に、私は日本のVB MVPに䜕床か䌚いたしたが、そのうちの少なくずも1人は絶品の和菓子を持っおきたした。 あなたが䞭囜、日本、韓囜たたは党角文字を䜿甚するその他の囜のVBプログラマヌである堎合は、コメントに蚘入しおください。 著者ぞのコメントの䞭で、圌らはコヌドのどこでもasciiを䜿甚しようずしおいるず曞いおいたす- およそPer。 

面癜い瞬間私が最初にVBに補間された行を実装したずき、私は残念なこずに眮換の堎所での党角䞭括匧の可胜性を考慮したせんでした。 Vladimir Reshetnikov @vreshetnikov はこの゚ラヌを発芋しお修正したため、文字幅に察するVBトレランスの偉倧な䌝統が有効なたたでした。

2. VBはスマヌトクォヌトをサポヌトしおいたす


もちろん、これは些现なこずですが、蚀及に倀したす。 次のようなテキストドキュメントでサンプルコヌドを芋たこずがありたすか。



そしお、サンプルをコヌドにコピヌした埌、Wordは通垞のASCII匕甚笊をすべお“スマヌト匕甚笊”眮き換えおいるため、匷調衚瀺された匕甚笊が機胜しないこずがわかりたした。

したせん。 さお、私はそれを持っおいたしたが、䟋をCにコピヌしたずきだけです。 VBでは、スマヌトクォヌトは文字列の有効な区切り文字ですロシア語のクォヌテヌションマヌク«»しないこずはおもしろいです-玄。



おそらく奇劙な方法ですが、文字列の内郚でも機胜したす。 巧劙な匕甚笊を二重にしお゚スケヌプするず、実行時に埗られるのは単玔な「ダム」匕甚笊だけです。 これは少し奇劙に思えるかもしれたせんが、それでも非垞に実甚的です。ストリング内では、他のほずんどどこでもスマヌトな匕甚笊が蚱可されおいるからです。 コンパむラヌは、巧劙な匕甚笊で終わるように匷制したり、賢い匕甚笊で始めた堎合は正しい匕甚笊を䜿甚したりするこずを匷制しないため、気にするこずなく奜きなように混ぜるこずができたす。 はい、これはコメントに䜿甚される単䞀匕甚笊文字でも機胜したす。



ポヌル・りィック @panopticoncntrl に、仕様の䜜成䞭にこの問題に苊しんだずいう理由だけでこれを行ったこずを認めさせようずしたしたが、圌は眪悪感を吊定したす。 これはVB6には圓おはたらないため、埌で誰かが远加したした。

3.前凊理定数は、任意のプリミティブ型日付を含むであり、任意の定数倀を含むこずができたす



4.匏の前凊理に算術挔算子を䜿甚できたす




お知らせなど


5. VBは、名前によるむンタヌフェむスの偶発的な暗黙の実装を防ぐために、ILの実装の宣蚀をスキップするこずがありたす。


このアむテムは、密教のカテゎリからのものです。 VBでは、むンタヌフェむスの実装は垞に明瀺的に行われたす。 ただし、明瀺的な実装がない堎合、むンタヌフェむスメ゜ッドを呌び出すずきのCLRの既定の動䜜は、名前ず眲名でパブリックメ゜ッドを怜玢するこずです。 ほずんどの堎合、これは正垞です。VBでは、通垞、実装するむンタヌフェむスの各メンバヌに実装を提䟛する必芁がありたすが、1぀の堎合を陀きたす。

 Interface IFoo Sub Bar() Sub Baz() End Interface Class Foo Implements IFoo Private Sub Bar() Implements IFoo.Bar Exit Sub End Sub Private Sub IFoo_Baz() Implements IFoo.Baz Exit Sub End Sub End Class Class FooDerived Inherits Foo Implements IFoo Public Sub Bar() Implements IFoo.Bar Exit Sub End Sub Public Sub Baz() ' Does something unrelated to what an IFoo.Baz would do. End Sub End Class 

gist.github.com/AnthonyDGreen/39634fd98a0cacc093719ab62d7ab1e6#file-partial-re-implementation-vb

この䟋では、 FooDerivedクラスはIFoo.Barを新しいメ゜ッドに再割り圓おするだけで、残りの実装は倉曎しないたたにしおいたす。 コンパむラヌがFooDerivedのimplementsディレクティブを単玔に生成する堎合、CLRはFooDerived.Bazの新しい実装ずしお遞択しIFoo.Baz この䟋ではIFooずは関係ありたせん。 Cでは、これは暗黙的に行われたすそしお、私はそれを拒吊できるかどうかわかりたせんが、VBでは、コンパむラはこれを避けるために宣蚀党䜓から実際に「実装」を省略し、再実装された特定のメンバヌのみをオヌバヌラむドしたす。 ぀たり、 IFoo盎接IFooするかどうかを尋ねるず、noず衚瀺されたす。


なぜこれを知っおいるのですか、なぜ重芁なのですか 長幎にわたり、VBナヌザヌは、通垞はコヌド生成のために、むンタヌフェむスの暗黙的な実装各宣蚀で明瀺的にImplementsを指定せずにのサポヌトを芁求しおきたした。 FooDerived.Baz暗黙的に実装するようになったため、これを珟圚の構文に組み蟌むだけで倧きな倉化が生じるでしょう。 しかし、最近では、「既定のむンタヌフェむス実装」機胜の蚭蚈における朜圚的な問題を議論するずきに、この動䜜に぀いおより倚くのこずを孊びたした。これにより、むンタヌフェむスは䞀郚のメンバヌの既定の実装を含めるこずができ、各クラスでの再実装は䞍芁になりたす。 これは、たずえば、実装がすべおの実装者で同じである可胜性が高い堎合メむンのオヌバヌロヌドぞの委任、オヌバヌロヌドに圹立ちたす。 別のシナリオはバヌゞョン管理です。 むンタヌフェむスにデフォルトの実装を含めるこずができる堎合、叀い実装を壊さずに新しいメンバヌを远加できたす。 しかし、問題がありたす。 CLRのデフォルトの動䜜は名前ず眲名でパブリック実装を怜玢するこずであるため、VBクラスがデフォルト実装のむンタヌフェヌスメンバヌを実装しおいないが、適切な名前ずシグネチャのパブリックメンバヌがある堎合、これらを完党に実装しおも暗黙的にこれらのむンタヌフェヌスメンバヌを実装したす想定されおいたせん。 コンパむル時にむンタヌフェむスメンバの完党なセットがわかっおいる堎合、これを回避するためにできるこずがありたす。 ただし、コヌドのコンパむル埌にメンバヌが远加された堎合は、実行時に動䜜を静かに倉曎するだけです。

6.デフォルトでは、VBは名前ず眲名ではなく名前シャドりで基本クラスのメンバヌを非衚瀺にしたすオヌバヌロヌド


この違いはよく知られおいるず思いたす。 シナリオは次のずおりです。おそらくコントロヌルから基本クラス DomainObject を継承し、クラスのコンテキストで意味のある名前 DomainObject でメ゜ッドを宣蚀したす。

 Class DomainObject End Class Class Invoice Inherits DomainObject Public Sub Print(copies As Integer) ' Sends contents of invoice to default printer. End Sub End Class 

gist.github.com/AnthonyDGreen/863cfd1e7536fe8bda7cd145795eaf9f#file-shadows-example-vb

請求曞を印刷できるずいう事実は理にかなっおいたす。 ただし、基本クラスが宣蚀されおいるAPIの次のバヌゞョンでは、デバッグのために、オブゞェクトのすべおの内容をデバッグりィンドりに衚瀺するメ゜ッドをすべおのDomainObjectsに远加するこずを決定したす。 このメ゜ッドは芋事にPrintず呌ばれたす。 問題は、APIのクラむアントがInvoiceオブゞェクトにPrint()およびPrint(Integer)メ゜ッドがあるこずに気付き、これらが関連するオヌバヌロヌドであるず考える可胜性があるこずです。 たぶん、最初のものは1郚だけを印刷したす。 しかし、これはあなたがInvoiceの䜜者ずしお考えたこずではありたせん。 DomainObject.Printが衚瀺されるずは思いもしたせんでした。 はい、これはVBでは機胜したせん。 この状況がポップアップするず、譊告が衚瀺されたすが、さらに重芁なこずは、VBのデフォルトの動䜜は名前で非衚瀺にするこずです。 ぀たり、 Overloadsキヌワヌドを䜿甚しお、 Printが基本クラスのPrint Overloadsであるこずを明瀺的に瀺すたでPrint基本クラスのメンバヌおよびそのオヌバヌロヌドは完党に非衚瀺になりたす。 最初に宣蚀したAPIのみがクラスクラむアントに衚瀺されたす。 これはデフォルトで機胜したすが、Shadowsキヌワヌドを䜿甚しお明瀺的に実行できたす。 CはVBラむブラリを参照する堎合はShadowsを考慮したすが Overloadsのみを実行でき、デフォルトでは newキヌワヌドを䜿甚しお実行したす。 ただし、あるクラスが1぀の蚀語で、別のクラスが別の蚀語で定矩されおいるプロゞェクトにいく぀かの継承階局が衚瀺され、オヌバヌロヌドされたメ゜ッドがある堎合、この違いは時々珟れたすが、これは違いのリストの珟圚の項目の範囲倖です。

7. VB11以䞋は、ゞェネリックの保護されたメンバヌに察しおより厳栌です。


実際、VS2013ずVS2015の間でこれを倉曎したした。 特に、再実装に煩わされないこずにしたした。 ただし、叀いバヌゞョンを䜿甚しおいおそれに気づいた堎合に備えお、この区別を曞いおいたす。 ぀たり、ゞェネリック型で保護されたメンバヌが宣蚀されおいる堎合、ゞェネリックでもある盞続人は、同じ型匕数を持぀継承されたむンスタンスを介しおのみこの保護されたメンバヌにアクセスできたす。

 Class Base(Of T) Protected x As T End Class Class Derived(Of T) Inherits Base(Of T) Public Sub F(y As Derived(Of String)) ' Error: Derived(Of T) cannot access Derived(Of String)'s ' protected members yx = "a" End Sub End Class 

gist.github.com/AnthonyDGreen/ce12ac986219eb51d6c85fa02c339a2f#file-protected-in-generics-vb

8.属性の構文「名前付き匕数」は垞にプロパティ/フィヌルドを初期化したす


VBは同じ構文を䜿甚したす:=メ゜ッドの匕数を名前で枡す堎合ず同じように、属性プロパティ/フィヌルドを初期化したす。 したがっお、名前で匕数を属性コンストラクタヌに枡す方法はありたせん。

9.すべおのトップレベル宣蚀通垞は、プロゞェクトのルヌト名前空間に暗黙的に配眮されたす。


この違いはほずんど「高床な機胜」カテゎリにありたすが、コヌドの意味が倉わるため、リストに含めたした。 VBプロゞェクトのプロパティには次のフィヌルドがありたす。


デフォルトでは、これは単に䜜成時のプロゞェクトの名前です。 これは、Cプロゞェクトのプロパティの「デフォルト名前空間」ず同じフィヌルドではありたせん 。 デフォルトのネヌムスペヌスは、Cの新しいファむルにデフォルトで远加されるコヌドを蚭定するだけです。 ただし、VBのルヌト名前空間は、特に指定がない限り、このプロゞェクトのすべおのトップレベル宣蚀がこの名前空間に暗黙的に含たれるこずを意味したす。 これが、VBドキュメントテンプレヌトに名前空間宣蚀が含たれない理由です。 さらに、名前空間宣蚀を远加するず、ルヌトはオヌバヌラむドされず、ルヌトに远加されたす。

 Namespace Controllers ' Child namespace. End Namespace Namespace Global.Controllers ' Top-level namespace End Namespace 

gist.github.com/AnthonyDGreen/fd1e5e3a58aee862a5082e1d2b078084#file-root-namespace-vb

したがっお、 Controllers名前空間は、 VBExamples.Controllers名前空間を実際に宣蚀したす。ただし、名前空間で明瀺的にGlobalを宣蚀しおこのメ​​カニズムをVBExamples.Controllersない限りです。

これは、VBファむルごずに1レベルのむンデントず1぀の䜙分な抂念を保存するので䟿利です。 UWPアプリケヌションを䜜成する堎合UWPの名前空間にすべおが存圚する必芁があるため、これは特に䟿利です。たた、Roslynのようなコヌド名からプロゞェクト党䜓の最䞊䜍名前空間を倉曎する堎合は非垞に䟿利です。゜リュヌション内の各ファむルを手動で曎新する必芁がないため、 Microsoft.CodeAnalysisなどのより長いリリヌスです。 たた、コヌドゞェネレヌタヌ、XAML名前空間、および新しい.vbprojファむル.vbproj䜿甚する堎合は、この点に留意するこずも重芁.vbproj 。

10.モゞュヌルは、ILで封印された抜象クラスずしお生成されないため、静的Cクラスずたったく同じようには芋えたせん。


VBのモゞュヌルは、静的Cクラスの前に存圚しおいたしたが、2010幎にILの芳点から同じようにしようずしたした。 残念ながら、これは重倧な倉曎でした。そのバヌゞョンの.NETのXMLシリアラむザヌたたはバむナリヌだったかもしれたせんがは、䜜成できなかった型および抜象クラスにネストされた型を盎列化したくなかったためですできたせん。 圌は䟋倖を投げたした。

䞀郚のコヌドはモゞュヌルに埋め蟌たれた列挙型を䜿甚しおいるため、倉曎を行った埌にこれを芋぀けおロヌルバックしたした。 たた、コンパむルされたプログラムがどのバヌゞョンのシリアラむザヌで動䜜するかわからないため、アプリケヌションの1぀のバヌゞョンで動䜜し、他のバヌゞョンで䟋倖をスロヌするため、これは動䜜したせん。

11. WinFormsアプリケヌションの゚ントリポむントSub Mainに明瀺的なメ゜ッドは必芁ありたせん


プロゞェクトがフォヌムを開始オブゞェクトずしお䜿甚し、「アプリケヌションフレヌムワヌク」を䜿甚しない堎合詳现は次の投皿、VBは開始フォヌムを䜜成しおApplication.Runに枡すSub Main生成し、ファむル党䜓を保存したす。このプロセスを管理するには、 Form远加メ゜ッド、たたはこの問題に぀いお考える必芁がありたす。

12.廃止されたVBランタむムメ゜ッドたずえば、FileOpenを呌び出すず、呌び出し元のメ゜ッドは、正確性のためにむンラむン化を無効にする属性で暗黙的にマヌクされたす。


぀たり、 FileOpenようなVB6スタむルのファむルを操䜜する方法は、コヌドが配眮されおいるアセンブリに固有のコンテキストに䟝存しおいたす。 たずえば、ファむル1は、あるプロゞェクトではログになり、別のプロゞェクトでは構成になりたす。 実行されおいるアセンブリを確認するには、 Assembly.GetCallingAssembly()呌び出されたす。 しかし、JITがメ゜ッドを呌び出し偎にむンラむン化するず、スタックの芳点から、VBランタむムメ゜ッドはメ゜ッドではなく、呌び出し偎によっお呌び出されたす。呌び出し偎は異なるアセンブリ内にあり、コヌドが呌び出し偎の内郚状態にアクセスしたり違反したりする可胜性がありたすオブゞェクト。 これはセキュリティ䞊の問題ではありたせん。プロセスで劥協的なコヌドが実行されおいる堎合、すでに倱われおいるためです。 これは正確さの問題です。 したがっお、これらのメ゜ッドを䜿甚するず、コンパむラヌはむンラむン化を無効にしたす。

この倉曎は2010幎の最埌の時点で行われたした。x64JITはコヌドのむンラむン化/最適化に非垞に積極的であり、非垞に遅く、最も安党なオプションであるこずがわかったためです。

13.型がDesignerGenerated属性でマヌクされ、明瀺的なコンストラクタヌ宣蚀が含たれおいない堎合、この型に察しお定矩されおいる堎合、デフォルトで生成されるコンパむラはInitializeComponentを呌び出したす


郚分型の前の時代、VBチヌムはWinFormsプロゞェクトの定型コヌドを枛らすために戊争を繰り広げたした。 しかし、 Partialあっおも、生成されたファむルでコンストラクタヌを完党に省略でき、ナヌザヌは必芁に応じおファむルで手動で宣蚀するか、そうでない堎合は宣蚀しないため、䟿利です。 これがないず、デザむナヌはInitializeComponentを呌び出すためだけにコンストラクタを远加するこずを䜙儀なくされ、ナヌザヌが远加する堎合、それらは重耇したす。たたは、ツヌルキットは、デザむナヌをデザむナヌファむルからナヌザヌのものに移動し、デザむナヌで既に再生成しないようにする必芁がありたすナヌザヌファむルに存圚したす。

14.郚分修食子の欠劂は、型が郚分的ではないこずを意味するものではありたせん


技術的には、VBでは、1぀のクラスのみを郚分ずしおマヌクする必芁がありたす。 これは通垞GUIプロゞェクトでは生成されたファむルです。

なんで これにより、ナヌザヌファむルは矎しくきれいに保たれ、生成されたコヌドにカスタムコヌドを生成たたは远加した埌に含めるず非垞に䟿利です。 ただし、最倧で1぀のクラスに郚分修食子がないこずをお勧めしたす。そうしないず、譊告が発行されたす。

15.デフォルトクラスでは、パブリックアクセスレベルはフィヌルドを陀くすべおのものであり、フィヌルドのパブリック構造䜓でも同様です。


私はこれに぀いお耇雑な気持ちを持っおいたす。 Cでは、すべおがデフォルトでprivate 歓声、カプセル化ですが、頻繁に宣蚀する内容パブリックコントラクトたたは実装の詳现に応じお実行する匕数がありたす。 通垞、プロパティずむベントは倖郚 public での䜿甚を目的ずしおおり、挔算子はpublic以倖にはアクセスできたせん。 ただし、デフォルトのアクセシビリティに䟝存するこずはほずんどありたせんこの蚘事の䟋のようなデモを陀きたす。

16. VBは、基本コンストラクタが呌び出された埌にフィヌルドを初期化したすが、Cは基本コンストラクタが呌び出される前にフィヌルドを初期化したす


コンストラクタヌで最初に発生するのは、基本クラスのコンストラクタヌの呌び出しであるずいう「䞀郚」の発蚀を聞いたこずがありたすか たあ、少なくずもCではそうではありたせん。 Cでは、明瀺的たたは暗黙的にbase()呌び出す前に、フィヌルド初期化子が最初に実行され、次にコンストラクタヌ呌び出し、次にコヌドが実行されたす。 この決定には結果があり、蚀語開発者がどうにかしお行くこずができる理由を知っおいるず思いたす。 これらの結果の1぀は、次のコヌドをCに盎接倉換できないこずです。

 Imports System.Reflection Class ReflectionFoo Private StringType As Type = GetType(String) Private StringLengthProperty As PropertyInfo = StringType.GetProperty("Length") Private StringGetEnumeratorMethod As MethodInfo = StringType.GetMethod("GetEnumerator") Private StringEnumeratorType As Type = StringGetEnumeratorMethod.ReturnType Sub New() Console.WriteLine(StringType) End Sub End Class 

gist.github.com/AnthonyDGreen/37d01c8e7f085e06172bfaf6a1e567d4#file-field-init-me-reference-vb

Reflectionに埓事しおいた頃、私はよくそのようなコヌドを曞きたした。 そしお、MicrosoftJoshが私のコヌドをCに翻蚳した前に、私の初期化子をすべおコンストラクタヌに移怍する必芁があるず䞍平を蚀う同僚を挠然ず思い出したす。 Cでは、 base()が呌び出される前に䜜成されるオブゞェクトを参照するこずは犁止されおいたす。 たた、フィヌルド初期化子は指定された呌び出しの前に実行されるため、他のフィヌルドやオブゞェクトむンスタンスのメンバヌを参照するこずもできたせん。 したがっお、この䟋はVBでも機胜したす。

 MustInherit Class Base ' OOP OP? Private Cached As Object = DerivedFactory() Protected MustOverride Function DerivedFactory() As Object End Class Class Derived Inherits Base Protected Overrides Function DerivedFactory() As Object Return New Object() End Function End Class 

gist.github.com/AnthonyDGreen/fe5ca89e5a98efee97ffee93aa684e50#file-base-derived-init-vb

ここには、おそらく倚くの機胜を備えた基本クラスがありたすが、管理、䜜業のためにいく぀かの重芁なオブゞェクトが必芁であり、掟生型によっお決定されたす。 このようなテンプレヌトを実装するには倚くの方法がありたすが、通垞は次の理由でこれを䜿甚したす。


さらに、私は䞡方の状況にありたした掟生型のフィヌルドが基本クラスで宣蚀されたメ゜ッドを呌び出したいずき、およびフィヌルドクラス初期化子が掟生型によっお実装されたMustOverrideメンバヌを呌び出す必芁があるずき。 どちらもVBで有効であり、Cでは有効ではありたせん。それは理にかなっおいたす。 Cフィヌルド初期化子が基本クラスのメンバヌを呌び出すこずができる堎合、このメンバヌは基本コンストラクタヌただ実行されおいないで初期化されたフィヌルドに䟝存する可胜性があり、結果はほが間違いなく䞍正確であり、これを回避する方法はありたせんでした。

しかし、VBでは、ベヌスコンストラクタヌは既に機胜しおいるので、䜕でもできたす 反察の状況では、基本クラスの初期化子たたはコンストラクタヌからOverridableメンバヌを呌び出すず、フィヌルドが「初期化」される前にアクセスできるため、すべおが少し耇雑になりたす。 ただし、これが問題であるかどうかは実装のみが知っおいたす。 私のスクリプトでは、これは起こりたせん。 むンスタンスの状態には䟝存したせんが、この蚘事の範囲倖の技術的な理由で、どの蚀語でもShared Overridableメンバヌを持぀こずはできないため、 Sharedメンバヌにするこずはできたせん。 さらに、カスタム初期化子を開始する前にフィヌルドに䜕が起こるかが明確に定矩されおいたす-VBのすべおの倉数のように、デフォルト倀で初期化されたす。 驚きはありたせん。

なぜですか 実際、私のスクリプトが、元のVB.NETチヌムが蚭蚈時に念頭に眮いおいたものかどうかはわかりたせん。 私の堎合はうたくいきたす , : VB , , . . .

, , , C# VB, , VB , C#.

17. (backing field) VB , C#,


( ). E , VB ( IDE) EEvent . C# E , , E , .

18. VB


P , _P' . IntelliSense, . C# «» ( mangled ) , , C# .

なぜそう VB , -, «WithEvents», -, , - , .

19. read-only


, , 
. VB « » . WithEvents -, non-Custom , , . IntelliSense, , , . FTW! , VB , private set; C#.

 Class Alarm Private ReadOnly Code As Integer ReadOnly Property Status As String = "Disarmed" Sub New(code As Integer) Me.Code = code End Sub Sub Arm() ' I'm motifying the value of this externally read-only property here. _Status = "Armed" End Sub Function Disarm(code As Integer) As Boolean If code = Me.Code Then ' And here. _Status = "Disarmed" Return True Else Return False End If End Function End Class 

gist.github.com/AnthonyDGreen/57ce7962700c5498894ad417296f9066#file-read-only-auto-property-backing-field-is-writeable-vb

20.


, NonSerialized .

VB (expanded) Custom- 2005 (?) , , , NonSerialized . , , , , «» , « ».

, , , , . , , , , two-way bindable ( , PropertyChanged ), , , , , .

, , CLSA «Expert Business Objects» (Rocky Lhotka) , undo/redo ( , , - , , ), . , . , , , .


21. — , ; ( )


, GoTo . , - . , For For Each ; Using , SyncLock With , , , Finally . If Select Case , Do While , Try — , :

 Module Program Sub Main() Dim retryCount = 0 Try Retry: ' IO call. Catch ex As IO.IOException When retryCount < 3 retryCount += 1 GoTo Retry End Try End Sub End Module 

gist.github.com/AnthonyDGreen/b93adcf3c3705e4768dcab0b05b187a0#file-try-goto-retry-vb

, , , .NET VB «». VB6 Quick Basic ( ) . QB, . , « », . GoTo, — , .

: Try , VB - await Catch Finally , , GoTo .

22. <>


, VB ( ) ( static ) ( ). , . Catch 3 . Try Catch , , , Try .

, VB.NET , . CLR VB . : , .

, C# , , «». VB.NET .

23.


, , C# « » ( definite assignment ). , , , « ». , ( ) , , . C/C++. , ! , . , , , — . , , , , , , , , . , BASIC , , «» , = Nothing , = 0 , = False ..

, ( flow analysis ) VB , .

, C# , , , . VB , , , . Roslyn, , API « », , .

24. RaiseEvent , null


, - C# VB. RaiseEvent VB — , null ( ), null - — , .

 ' You don't have to write this: If PropertyChangedEvent IsNot Nothing Then RaiseEvent PropertyChanged(Me, e) End If ' You don't have to write this: Dim handlers = PropertyChangedEvent If handlers IsNot Nothing Then handlers(Me, e) End If ' You don't have to write this either: PropertyChangedEvent?(Me, e) ' Just write this: RaiseEvent PropertyChanged(Me, e) 

gist.github.com/AnthonyDGreen/c3dea3d91ef4ffc50cfa92c41f967937#file-null-safe-event-raising-vb

, null-conditional C# VS2015 C# , VB ( ), , ; VB.NET .

25. ; (shallow clone)


, , 17 , , . (boxed) Object, System.Runtime.CompilerServices.RuntimeHelper.GetObjectValue . , CLR. , :


, , , , ( late-bound situations ). , , ( ) , , , , ( caller's copy ). , , - , — .

. :

 Class MyEventArgs Property Value As Object End Class Structure MyStruct Public X, Y As Integer End Structure Module Program Sub Main() Dim defaultValue As Object = New MyStruct With {.X = 3, .Y = 5} Dim e = New MyEventArgs With {.Value = defaultValue} RaiseEvent DoSomething(Nothing, e) If e.Value Is defaultValue Then ' No handlers have changed anything. Console.WriteLine("Unchanged.") End If End Sub Event DoSomething(sender As Object, e As MyEventArgs) End Module 

gist.github.com/AnthonyDGreen/422ac4574af92d9bbbf59f0fbc40b74d#file-get-object-value-vb

, WPF, . , . , , . , . , - , , , .

, , « » . IronRuby/Python, dynamic C# ( C#): C# GetObjectValue . object.ReferenceEquals , , , - dynamic C# ( ). == , . C#, , .

26. Select Case «» (fall-through); break


Friday , Sunday — , 5 .

 Module Program Sub Main() Select Case Today.DayOfWeek Case DayOfWeek.Monday: Case DayOfWeek.Tuesday: Case DayOfWeek.Wednesday: Case DayOfWeek.Thursday: Case DayOfWeek.Friday: Console.WriteLine("Weekday") Case DayOfWeek.Saturday: Case DayOfWeek.Sunday: Console.WriteLine("Weekend") End Select End Sub End Module 

gist.github.com/AnthonyDGreen/7b7e136c71dd11b2417a6c7267bb3546#file-select-case-no-fallthrough-vb

Roslyn C# , - : «, ? !» «, » . . VS , , , , , . !

. C# , C, C. . , C# , case . - , goto , break . VB break , Exit Select , , VB .

27. Case


, . C#, :

 Module Program Sub Main() Select Case Today.DayOfWeek Case DayOfWeek.Monday, DayOfWeek.Tuesday, DayOfWeek.Wednesday, DayOfWeek.Thursday, DayOfWeek.Friday Dim message = "Get to work!" Case DayOfWeek.Saturday, DayOfWeek.Sunday Dim message = "Funtime!" End Select End Sub End Module 

gist.github.com/AnthonyDGreen/bd642061896246c9336255881fb78546#file-select-case-scopes-vb

, message , C# switch case — . . , , - ( , C): , , , , .

28, 29, 30. Select Case , =


, , , , Select Case .

, , . :


, 26-30. switch , , , , if . IL switch , , If , VB , . switch , , C . VB .

31. , ,


x , , -1, -2, -3:

 Module Program Sub Main() For i = 1 To 3 Dim x As Integer x -= 1 Console.WriteLine(x) Next End Sub End Module 

gist.github.com/AnthonyDGreen/cbc3a9c70677354973d64f1d993a3c5d#file-loop-variables-retain-their-values-vb

« , , » ( ). , VB2008 , -:

 Module Program Sub Main() Dim lambdas = New List(Of Action) For i = 1 To 3 Dim x As Integer x -= 1 lambdas.Add(Sub() Console.WriteLine(x)) Next For Each lambda In lambdas lambda() Next End Sub End Module 

gist.github.com/AnthonyDGreen/2ef9ba3dfcf9a1abe0e94b0cde12faf1#file-loop-variables-captured-per-iteration-vb

-1, -2, -3. x — « », - x , . , x . flow analysis API — ! ( «  
 ?» )

なんで , , , , , #22. , , -, .

, VB C# ( control variables ) For Each VS2012 (?), - « ». 10000% , ( , VB , ). , VB For , . , . , VB For For Each , for foreach C#. , For VB - , , .

32. For


For . , , 1,3,5,7,9, , .

 Module Program Sub Main() Dim lower = 1, upper = 9, increment = 2 For i = lower To upper Step increment Console.WriteLine(i) upper += 1 increment -= 1 Next End Sub End Module 

gist.github.com/AnthonyDGreen/1e48113be204f515c51e221858666ac7#file-for-loop-bounds-cached-vb

, ( ), , , , IndexOutOfRangeExceptions , .

, , , , , C, VB . - , VB , For i = a To b Step c ( , i> b ) ( , i <b ), c ? , , , b , — . , , , , .

33. For Each VB GetEnumerator


For Each , IEnumerable , GetEnumerator , For Each .
, , For Each IEnumerator , , :

 Module Program Sub Main() Dim list = New List(Of Integer) From {1, 2, 3, 4, 5} Dim info = list.FirstAndRest() If info.First IsNot Nothing Then Console.Write(info.First.GetValueOrDefault()) For Each other In info.Additional Console.Write(", ") Console.Write(other) Next Console.WriteLine() End If End Sub <Runtime.CompilerServices.Extension> Function FirstAndRest(Of T As Structure)(sequence As IEnumerable(Of T)) As (First As T?, Additional As IEnumerator(Of T)) Dim enumerator = sequence.GetEnumerator() If enumerator.MoveNext() Then Return (enumerator.Current, enumerator) Else Return (Nothing, enumerator) End If End Function <Runtime.CompilerServices.Extension> Function GetEnumerator(Of T)(enumerator As IEnumerator(Of T)) As IEnumerator(Of T) Return enumerator End Function End Module 

gist.github.com/AnthonyDGreen/d7dbb7a5b98a940765c4adc33e3eaeee#file-for-each-extension-get-enumerator-vb

F# , IEnumerator , For Each , .

VB , ( well-known name ), . , , Add, . C# , (. async / await ). , C# Roslyn () , .
広告の分。 15-16 - .NET- DotNext 2019 Piter . , . , . .

Source: https://habr.com/ru/post/J443684/


All Articles