特集 より洗練されたVisual Studio .NET 2003の新機能を探る 株式会社ピーデー川俣 晶 2003/06/03 |
![]() |
|
Visual Basic. NET言語の追加機能
Visual Basic .NET(以下VB.NET)は、人気のあるVisual Basicの最新版ということになる。VS.NET 2003(より正確には.NET Framework 1.1)では、このVBの言語仕様にいくつか機能が追加されている。C#などではすでに使用できる機能が、VB.NETでも使えるようになったものである。それらを見てみよう。
■ループ変数の宣言
Forステートメントのように、ループのカウントに変数を使用するステートメントでは、ステートメント内で変数を宣言できるのがC++やC#などの言語の特徴である。これによりソース・コードをすっきりと記述できるのだが、この機能がVB.NETにも取り入れられた。例えば、従来は以下のようなコードを書いていた。
Dim i As Integer
For i = 1 To 10
Console.WriteLine(i)
Next
これは、VS.NET 2003のVB.NETでは、以下のように記述可能である。
For i As Integer = 1 To 10
Console.WriteLine(i)
Next
ここで「i As Integer」は、ループ変数が“i”であることを示すと同時に、この変数iを宣言している。
ただし、上の2つのソースは完全に等価ではない。例えば、以下のソースと等価の処理を、この機能を用いて記述することはできない。
Dim i As Integer
For i = 1 To 10
Console.WriteLine(i)
Next
Console.WriteLine(i)
これを以下のように書き換えるとコンパイル・エラーが発生する。
For i As Integer = 1 To 10
Console.WriteLine(i)
Next
Console.WriteLine(i)
ここでコンパイル・エラーが発生する理由は、変数iのスコープ(有効範囲)にある。従来型の宣言では、変数iはForループ外でも有効である。しかし、Forステートメント内で宣言された変数iは、ForステートメントとNextステートメントの間でのみ有効である。この機能のポイントは、ループ内でしか使用しないカウンタ用変数をわざわざ別のところで宣言する必要がなくなったということだ。
さて、この機能はFor Eachステートメントでも利用可能である。例えば、以下のコードはVS.NET 2003でコンパイル可能である。
Dim ar() As String = {"A", "B", "C"}
For Each s As String In ar
Console.WriteLine(s)
Next
■ビット・シフト演算子
あまり多くはないが、プログラムでビット単位のデータを処理する必要が生じることがある。例えば、整数値の特定のビットを、ほかのビットは変えないまま1にしたり、0にしたりする処理が必要とされる場合がある。これは、And演算子やOr演算子を活用すると実現できる。しかし、VB.NETですんなりと実現できない演算があった。それがビット・シフトである。ビット・シフトとは、任意のビット数だけ、右や左にビットの並びを移動させる演算をいう。これがVS.NET 2003ではサポートされている。左シフトは「<<」で、右シフトは「>>」で表現する。以下はそれを利用した例である。
Dim a As Integer = 256
Dim b As Integer = 4
Dim c As Integer = a << b
Console.WriteLine(c)
Dim d As Integer = a >> b
Console.WriteLine(d)
これを実行するとコンソールに以下のような結果を得る。
4096
16
256は2進数の100000000、4096は2進数の1000000000000、16は2進数の10000を表している。ここでは、つまり100000000を4個左にずらすと1000000000000になり、4個右にずらすと10000となるという結果を得ているわけである。
ビット・シフト演算子はByte型、Short型、Integer型、Long型に使用できる。
C#言語の仕様変更と追加機能
C#言語仕様は、ECMA(European Computer Manufacturer's Association)の公的な標準仕様として成立したことを受けて、いくつかの変更が行われている。
■foreachとIDisposable
ここは非常にややこしい話なので、慎重に読んでいただきたい。foreachステートメントで使用する列挙オブジェクトがIDisposableインターフェイスを実装している場合、列挙が終了したときに、このインターフェイスのDisposeメソッドが呼び出される。呼び出すかどうかの判定を、VS.NET 2002はコンパイル時に行っているため、たとえこのインターフェイスを実装したオブジェクトが使用されたとしても、コンパイル時に判断できない場合は呼び出されない。それに対して、VS.NET 2003では実行時に判定されるため、常にDisposeメソッドは呼び出される。
この相違を具体的にコードで示したものが下のサンプル・コードである。以下のコードをVS.NET 2002でコンパイルして実行すると「Dispose called」というメッセージは表示されないが、VS.NET 2003では表示される。
|
|
VS.NET 2003ではDisposeメソッドが呼び出される |
ここでポイントになるのは、GetEnumeratorメソッドの戻り値がBase型であるという点である。Base型はIDisposeインターフェイスを持たないので、VS.NET 2002ではDisposeメソッドはないと判断する。しかし、実際にはIDisposeインターフェイスを持つDerived型のオブジェクトが使われているので、Disposeメソッドは存在する。VS.NET 2003ではこれが検出されて呼び出される。もし、MyClassクラス内の「public Base GetEnumerator()」を、「public Derived GetEnumerator()」と書き換えると、VS.NET 2002でもDisposeメソッドの存在をコンパイラが認識して、呼び出すようにコードを生成してくれる。
■プロパティとアクセサ・メソッド
C#のプロパティは、プロパティを持たないプログラム言語から見ると、アクセサ・メソッドとして見える。例えば、SamplePropという名前のプロパティのgetアクセサはget_SamplePropというメソッドに、setアクセサはset_SamplePropというメソッドに見える。つまり、1つの実体に2つの名前があるわけで、ECMAのC#では、この混乱を避けるために、プロパティと紛らわしいget_SamplePropやset_SamplePropという名前のメソッドの作成を許さなくなったようである。その結果として、以下のようなソースは、VS.NET 2002では問題ないが、VS.NET 2003ではコンパイル・エラーとなる。
|
|
VS.NET 2003ではコンパイル・エラーとなるアクセサ・メソッドの定義 |
これをVS.NET 2003でビルドすると、get_SamplePropやset_SamplePropの行で、「明示的なメソッドの実装で、アクセサである '……' を実装することはできません。」といったエラーを受け取ることになる。
■ユーザー定義のビット・シフト演算子の制約
ビット・シフト演算子(「>>」や「<<」)を定義する場合、VS.NET 2002では以下の定義はいずれも可能だった。
|
|
VS.NET 2003ではコンパイル・エラーとなるビット・シフト演算子定義 |
しかしVS.NET 2003では、最初の定義で「オーバーロードされた shift 演算子では、最初のオペランドの型はそれを含む型で、2 番目のオペランドの型は int でなければなりません。」というコンパイル・エラーとなる。これはECMAのC#の制約を取り入れたもので、シフト演算子の引数は、エラー・メッセージに書かれたとおりの順番で記述されねばならないことになった。
■#line hiddenによるデバッグ情報の抑止
プリプロセッサの「#line hidden」ディレクティブを使うことで、ソース・コードの指定範囲のデバッグ情報の出力を抑止することができるようになった。これにより、自動生成されたデバッグ済みのコードはステップ実行で一気に飛ばす、といったことが可能になった。
対象となる範囲は、#line hiddenディレクティブから、次の有効な#lineディレクティブまでである。
例えば、以下のコードで、Console.WriteLine("1")の行にブレークポイントを仕掛けて停止させたとする。そこでステップ実行を1回行うと、次に停止する位置はConsole.WriteLine("4");の行である。中間の行はデバッグ情報がないので、一気に連続して実行され、止まることがない。
Console.WriteLine("1");
#line hidden
Console.WriteLine("2");
Console.WriteLine("3");
#line default
Console.WriteLine("4");
■/** …… */デリミタをドキュメント・コメントとして使う
C#では「///」に続いてXML形式のドキュメントを埋め込んで、コードからXML文書を生成できる機能がある。以下のように記述して使用する。
|
|
XML形式のドキュメントを埋め込むためのドキュメント・コメント |
これと等価なことが、VS.NET 2003では「/**……*/」形式でも可能になった(この書式は、Javaのドキュメンテーション・コメントと似ているが内部に書き込む内容は同じではない)。以下がそれを記述した例である。
|
|
VS.NET 2003で追加されたドキュメント・コメントの形式 |
この形式をVS.NET 2002に読ませてもエラーにならない。ただ単に普通のコメントとして扱われ、単純に無視されてしまう。つまり、機能しないということである。
![]() |
INDEX | ||
[特集]より洗練されたVisual Studio .NET 2003の新機能を探る | ||
1.Visual Studio .NET 2003の概要 | ||
2.より便利になったIntelliSense機能 | ||
3.デバッグ/ビルドに関する新機能 | ||
![]() |
4.VB.NETとC#の追加機能・仕様変更 | |
![]() |
- 第2回 簡潔なコーディングのために (2017/7/26)
ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている - 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう - 第1回 明瞭なコーディングのために (2017/7/19)
C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える - Presentation Translator (2017/7/18)
Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
![]() |
|
|
|
![]() |