Visual Basic 初級講座 [改訂版]
VB2005 VB2008 VB2010 VB2012 VB2013 VB2015 VB2017 VB2019

第6回 クラスの使い方

この記事が対象とする製品・バージョン

VB2019 Visual Basic 2019 対象です。
VB2017 Visual Basic 2017 対象です。
VB2015 Visual Basic 2015 対象です。
VB2013 Visual Basic 2013 対象です。
VB2012 Visual Basic 2012 対象ですが一部画面が異なる場合があります。
VB2010 Visual Basic 2010 対象ですが一部画面が異なる場合があります。
VB2008 Visual Basic 2008 対象ですが一部画面が異なる場合があります。
VB2005 Visual Basic 2005 対象ですが一部画面が異なる場合があります。
VB.NET 2003 Visual Basic.NET 2003 対象外ですがほとんどの説明があてはまるので参考になります。
VB.NET 2002 Visual Basic.NET (2002) 対象外ですがほとんどの説明があてはまるので参考になります。
VB6対応 Visual Basic 6.0 × 対象外です。

 

目次

 

1.共有メンバーと非共有メンバー

前回説明したようにクラスまたは構造体は、メソッド・プロパティ・フィールド・イベント・演算子を0個以上持っており、これらをメンバーと呼びます。

クラスのメンバーを自由に呼び出せるようになることが、クラスの機能を自由に使えることを意味します。

 

クラスのメンバーには共有メンバーと非共有メンバーの2種類があり、呼び出し方が大きく違います。

メンバーの種類によって、共有メソッド・非共有メソッド・共有プロパティ・非共有プロパティなどと呼びます。

 

共有メンバーはプログラム中、クラス名を記述して直接呼び出すことができます。

非共有メンバーは「インスタンス」というものを対象にし、プログラム中、インスタンスを記述して呼び出す必要があります。

 

例として、Windowsフォームアプリケーションで使用する TextBoxクラス を使って説明します。

(Windowsフォームアプリケーションを体験していない方は 入門講座で体験できます。)

 

WindowsフォームアプリケーションではTextBoxをぺたぺたといくつでもフォームに貼り付けることができます。

1つのTextBoxというクラスからたくさんの分身を作り出すことができます。この分身が「インスタンス」というものです。

Windowsフォームアプリケーションのフォームデザイナーでは既定ではインスタンスに「TextBox1」、「TextBox2」というような名前が付きます。

 

フォームに3つのTextBoxと1つのButtonを貼り付けるとこのような感じになります。

3つのTextBoxと1つのButton

 

TextBoxはAppendTextというメソッド(読み方:AppendText = アペンドテキスト) を持っており、このメソッドを呼び出すことで、表示されている文字列を追加する処理を呼び出すことができます。

このメソッドは非共有メソッドです。

非共有メソッドなので、プログラム時には TextBox1. や TextBox2. というようにインスタンスを指定して呼び出す必要があります。実行しても対象のTextBoxだけに文字が追加されます。

 

たとえば、TextBox2のAppendTextメソッドを呼び出すには次のように記述します。

VB.NET 2002 VB.NET 2003 VB2005 VB2008 VB2010 VB2012 VB2013 VB2015 VB2017 VB2019


TextBox2.AppendText("Hello!")

これを実行すると、TextBox2にだけ Hello! が追加されます。

TextBox2にだけ Hello! と表示されている

同じTextBoxクラスなのに、TextBox1とTextBox3という名前のインスタンスには何も起こらずTextBox2という名前のインスタンスだけが変化しています。

これがクラスとインスタンスの違いです。

 

一方、TextBoxには、MousePositionというプロパティ(読み方:MousePosition = マウスポジション)もあります。このプロパティはマウスの位置データを取得することができます。

このメソッドは共有メソッドです。

共有メソッドなので、プログラム時には TextBox というクラス名から呼び出すことができます。

VB.NET 2002 VB.NET 2003 VB2005 VB2008 VB2010 VB2012 VB2013 VB2015 VB2017 VB2019

Dim pos As Point = TextBox.MousePosition
MsgBox(pos)

このプログラムにはインスタンスの名前(TextBox1, TextBox2, TextBox3)は登場していません。

 

ここまでをまとめると、

・AppendTextメソッドとMousePositionプロパティはどちらも TextBoxクラスのメンバーです。

・非共有メンバーである AppendTextメソッドは TextBox2.AppendText のようにインスタンスを記述して呼び出しました。「TextBox2」がインスタンス名です。

・共有メンバーである MousePositionプロパティは TextBox.MousePosition のようにクラス名を記述して呼び出しました。「TextBox」がクラス名です。

 

 共有メンバーと非共有メンバーの区別はリファレンスにも記載してありますが、常識的に考えればわかります。

マウスの位置はどのTextBoxから取得しても同じ情報なので、インスタンスごとに持つ必要はありません。すべてのインスタンスで共有している情報ということなので共有プロパティです。

AppendTextメソッドは逆に全部のTextBoxが同時に書き換わっては困るので共有して欲しくない処理です。ですから非共有メソッドです。

 

発展 発展学習  -  マウスの位置はボタンから見ても同じ

発展学習では意欲的な方のために現段階では特に理解する必要はない項目を解説します。

マウスの位置はTextBoxだけでなく、ButtonやForm本体やその他何から見ても同じです。そのため、Windowsフォームのコントロールにはすべて MousePositionという共有プロパティがあり、どのコントロールからこのププロパティを呼び出しても同じ位置を取得できます。 MousePositionはTextBoxだけではなく、Windowsフォームのコントロールの共通の既定クラスであるControlクラスで共有プロパティとして定義されているからです。

 

次の章ではインスタンスを作成する方法を説明し、今回はメソッド・プロパティの使い方まで説明します。

今回の説明内容を自分のものにできればプログラマーとしてのレベルが1つ上がります。重要なので、第8回では今回の知識を使った実践的な演習を予定しています。もし、今回完全に自分のものにできなかったとしても第8回の演習を通して習得できるかもしれません。

 

2.コンストラクター

 

2-1.コンストラクターでインスタンスを作成する

クラスのインスタンスを作成するにはコンストラクターというものを利用します。

WindowsフォームアプリケーションのフォームデザイナーではマウスでぺたぺたとTextBoxやButtonを貼り付けると自動的にコンストラクターを呼び出してインスタンスを作成してくれて、プロパティも設定してくれて大変便利ですが、この便利な機能を利用できるのはWindowsフォームアプリケーション用のコントロールとして設計されたクラスだけです。

この他の大部分のクラスは、自分のプログラムでインスタンスを作成することが必要になります。(必要であればTextBoxやButtonのインスタンスを自分のプログラムで作成することもできます。)

 

インスタンスを作成可能なクラスは、「コンストラクター」という種類のメンバーを持っており、これを使ってインスタンスを作成することができます。

メソッドやプロパティと違ってコンストラクターには名前がついていませんので名前で呼び出すことはできません。VBの New キーワード + クラス名 の構文を使ってコンストラクターを呼び出すことができます。

通常は作成したインスタンスを変数に代入して、後でメソッドやプロパティを呼び出すことができるようにしておきます。

 

たとえば、ランダムな値を生成するRandomクラス(読み方:Random = ランダム)クラスのインスタンスを作成して変数 r に代入するには次のようにします。

 VB2008 VB2010 VB2012 VB2013 VB2015 VB2017 VB2019


Dim r = New Random

「New Random」、New + クラス名 という構文によってRandomクラスのインスタンスが作成されます。

型推論により、変数 r は Random型になりますが、次のようにして明示的に型を指定することもできます。

VB.NET 2002 VB.NET 2003 VB2005 VB2008 VB2010 VB2012 VB2013 VB2015 VB2017 VB2019


Dim r As Random = New Random

この書き方だと Random というキーワードが2回でてきて、無駄なようにも思えますので、次のように省略して書く特別な構文もあります。

VB.NET 2002 VB.NET 2003 VB2005 VB2008 VB2010 VB2012 VB2013 VB2015 VB2017 VB2019


Dim r As New Random

この3つの書き方は機能・性能はまったく同じです。型推論は別途説明しますが使用できない箇所がある(クラス直下では使用できません)ので、3つ目の「Dim r As New Random」という書き方をするプログラマーが多いように私は感じます。

クラスのインスタンスを作成することを「インスタンス化」・「インスタンシング」と呼ぶ場合もあります。

 

インスタンスが作れれば非共有メンバーを呼び出せます。Randomクラスにはランダムな整数を生成するNextメソッド(読み方:Next = ネクスト)がありますので、呼び出してみましょう。

VB.NET 2002 VB.NET 2003 VB2005 VB2008 VB2010 VB2012 VB2013 VB2015 VB2017 VB2019

Dim r As New Random

Dim number1 As Integer = r.Next
Dim number2 As Integer = r.Next
Dim number3 As Integer = r.Next

MsgBox(number1)
MsgBox(number2)
MsgBox(number3)

 

2-2.コンストラクターの引数

クラスによってはコンストラクターでインスタンスを作成するときに追加情報が必要なものがあります。

たとえばフォルダーを表すDirectoryInfoクラス(読み方:DirectoryInfo = ディレクトリーインフォ)は、インスタンスを作成するときに「どのフォルダー?」という情報を追加で指定する必要があります。

VB.NET 2002 VB.NET 2003 VB2005 VB2008 VB2010 VB2012 VB2013 VB2015 VB2017 VB2019

'コンストラクターを呼び出すときにフォルダーのパスを指定します。
Dim folder As New IO.DirectoryInfo("C:\test")

'インスタンスの最終更新日を表すLastWriteTimeプロパティを呼び出します。
Dim updateTime As DateTime = folder.LastWriteTime

MsgBox(updateTime)

このようにコンストラクターに渡される追加情報のことを「引数」(ひきすう)と呼びます。

※後で出てくるようにメソッドやプロパティにも追加情報を渡す場合があり、それも「引数」と呼びます。

 

2つ以上の引数を要求するコンストラクターもあります。複数の情報が必要な場合 カンマで区切ります。

ファイルへの書き込みを行うStreamWriterクラス(読み方:StreamWriter = ストリームライター)は、第1引数として対象のファイルのパス、第2引数として追加書きするかどうかを指定します。第2引数にTrueを指定した場合、既に対象のファイルが存在する場合後ろに文字列を追加します。Falseの場合、既にファイルが存在すれば上書きします。

VB.NET 2002 VB.NET 2003 VB2005 VB2008 VB2010 VB2012 VB2013 VB2015 VB2017 VB2019

'第1引数は書き込み対象のファイル、第2引数は追加書きするか。Falseの場合上書き。
Dim writer As New IO.StreamWriter("C:\test\sample.txt", False)

writer.Write("Hello!")

'StreamWriterは使用終了後必ず Close メソッドを呼び出すようにします。
writer.Close()

 

発展 発展学習  -  通常は Using を使います。

発展学習では意欲的な方のために現段階では特に理解する必要はない項目を解説します。

StreamWriterのように必ず終了処理が必要なクラスは Using を使って記述するのが普通です。初級講座ではまだ終了処理やUsingを説明してないため、自分で Close メソッドを呼び出す記述方法で紹介しています。Usingを使うと想定外のエラーが発生した場合でもかならず終了処理(Dispose)を実行してくれるので優秀です。

 VB2005 VB2008 VB2010 VB2012 VB2013 VB2015 VB2017 VB2019

Using writer As New IO.StreamWriter("C:\test\sample.txt", False)
    writer.Write("Hello!")
End Using

 

2-3.コンストラクターのオーバーロード

StreamWriterクラスは機能が複雑なためコンストラクターを8個も持っています。対象ファイルのパス、追加書きかどうか、文字コード、書き込みに使用するメモリーのサイズ、ファイル以外(ストリームと呼ぶもの)への書き込みなどさまざまな情報を指定できます。

このようにコンストラクターを複数持つことを「コンストラクターのオーバーロード」、「オーバーロードされたコンストラクター」と呼びます。

コンストラクターには名前がないため、どのコンストラクターを呼び出す場合でも New を使用します。

 

StreamWriterクラスの8個のコンストラクターは次の通りです。 ( ) 内は引数の型です。

  引数1 引数2 引数3 引数4
コンストラクター1 対象のストリーム(Stream)      
コンストラクター2 対象のファイル(String)      
コンストラクター3 対象のストリーム(Stream) エンコード(Encoding)    
コンストラクター4 対象のファイル(String) 追加書きか?(Boolean)    
コンストラクター5 対象のストリーム(Stream) エンコード(Encoding) メモリサイズ(Integer)  
コンストラクター6 対象のファイル(String) 追加書きか?(Boolean) エンコード(Encoding)  
コンストラクター7 対象のストリーム(Stream) エンコード(Encoding) メモリサイズ(Integer) 書き込み後にストリームを閉じるか?(Boolean)
コンストラクター8 対象のファイル(String) 追加書きか?(Boolean) エンコード(Encoding) メモリサイズ(Integer)

どのコンストラクターを呼び出しているかは、引数の型で判断されます。表を良く見ると、どのコンストラクターも引数の型の順番が違うようになっていることがわかります。

さきほどの New IO.StreamWriter("C:\test\sample.txt", False) というコンストラクターの呼び出しは、2つの引数が指定されていて、第1引数がStringで、第2引数がBooleanです。

該当するのはコンストラクター4ですので、このコンストラクターが呼び出されます。

 

Visual Studioで入力するときは入力支援機能を利用できます。

New IO.StreamWriter( まで入力すると、コンストラクターの呼び出しであることが確定するので、Visual Studioは呼び出し可能なコンストラクターのヒントを表示します。

画像の赤線のところに 1/8 と書いてあり、これはコンストラクターが全部で8個あり、今、そのうち、1つ目のヒントを表示しているという意味になります。

右側の下矢印をクリックするか、キーワードの候補リストが出ていない状態(もし、出ていればEscキーで閉じてから)、キーボードの下矢印を押すと次のコンストラクターのヒントに切り替わります。

ヒントはあくまでも単なるヒントですので、無視してプログラムしてもかまいません。2つ目のコンストラクターのヒントが入力されている状態で、自分で4つ目のコンストラクラーの呼び出しを記述してもまったく問題ありません。

 

メモ メモ  -  空の かっこ ( )
引数がないコンストラクターの呼び出しでも空の ( ) を記述することができます。次の例はどちらも正しいコンストラクターの呼び出しです。

VB.NET 2002 VB.NET 2003 VB2005 VB2008 VB2010 VB2012 VB2013 VB2015 VB2017 VB2019

Dim d1 As New DataTable
Dim d2 As New DataTable()

VBではメソッドやコンストラクターの後ろに ( ) をつけると、それを呼び出す という意味になりますが、特例として引数がない場合は、そのかっこを省略して書くことができます。

 

2-4.変数を経由しないインスタンス

インスタンスを変数に代入することは多くの場合お勧めではありますが、必須ではありません。

次の例は PerformanceCounterクラス (読み方:PerformanceCounter = パフォーマンスカウンター)クラスを使って実行時点で使用可能なメモリ量をメガバイト単位で取得します。

VB.NET 2002 VB.NET 2003 VB2005 VB2008 VB2010 VB2012 VB2013 VB2015 VB2017 VB2019

Dim counter As New PerformanceCounter("Memory", "Available MBytes")

Dim freeMemory As Single = counter.NextValue()

MsgBox(freeMemory)

この例は、PerformaceCounterクラスのインスタンスを変数 counterに代入し、変数を経由して非共有メソッドの NextValue を呼び出しています。

これを変数counter を経由しないで直接インスタンスからNextValueメソッドを呼び出すには次のようにします。

VB.NET 2002 VB.NET 2003 VB2005 VB2008 VB2010 VB2012 VB2013 VB2015 VB2017 VB2019

Dim freeMemory As Single = (New PerformanceCounter("Memory", "Available MBytes")).NextValue()

MsgBox(freeMemory)

変数への代入を省略したので、プログラム行数は1行減りましたが、あまりわかりやすくはありませんね。特に理由がなければ変数に代入したほうがわかりやすいので代入することをお勧めします。

この例ではどちらの場合も New を1回しか使用していないため機能・性能は同じです。インスタンスの作成は、プログラムの処理の中では比較的重い処理なので不必要に大量のインスタンスを作成することは推奨されません。通常は New を実行する数がインスタンスを作成する数の目安なので(というのも、New以外の手段でインスタンスが作成される場合もあるため)、Newの数が不必要に多くならないように気をつけてください。

無駄なNewが1個や2個あるというレベルは気にしません。100個・200個というレベルで無駄なNewがある場合はプログラムを変えるべきです。

※今後説明する For ~ Nextを使った構文などを利用すると、プログラムを繰り返し実行することが可能であり、この場合、信じられないことに無駄なNewを何万回も実行してしまう場合があります。(本当にあります。私はシステム開発の現場で何度か目撃しています。)

 

2-5.練習問題

問1.ButtonクラスはフォームにButton1, Button2、・・・ というように複数貼り付けることができます。このButton1やButton2のことをなんと呼びますか?
クラス
インスタンス
コンストラクター
非共有メンバー(Decimal)
問2.MathクラスのPowメソッドは、Math.Powと記述して呼び出すことができます。Powメソッドの種類は何でしょうか?
共有メソッド
非共有メソッド
問3.メソッド・プロパティ・コンストラクター・フィールド・イベント・演算子のことをまとめてなんと言いますか?
メンバー
予約語
問4.クラスのインスタンスを作成するメンバーはどれでしょうか?
メソッド
プロパティ
コンストラクター
フィールド
問5.Dim player As New SoundPlayer と記述したときに呼び出されているものはどれでしょうか?
メソッド
プロパティ
コンストラクター
フィールド

3.メソッド

3-1.共有メソッド

3-1-1.呼び出し

インスタンスの作成方法がわかれば共有メソッドも非共有メソッドも呼び出すことができます。

メソッドには名前がついているので、名前を使って呼び出します。

共有メソッドの呼び出し方

クラス名.メソッド名

 非共有メソッドの呼び出し方

インスタンス.メソッド名

追加情報が必要なメソッドにはかっこを使って引数を指定します。このあたりの使い方はコンストラクターを同じです。

 

まずは共有メソッドの呼び出しを説明します。

次の例は、共有メソッドの正しい呼び出し例です。

VB.NET 2002 VB.NET 2003 VB2005 VB2008 VB2010 VB2012 VB2013 VB2015 VB2017 VB2019

'クリップボードに「あいうえお」をコピーします。右クリック「貼り付け」できるようになります。
Clipboard.SetText("あいうえお")

'電卓を起動します。
Process.Start("calc.exe")

'新しいフォルダーを作成します。
IO.Directory.CreateDirectory("C:\test\newfolder\子フォルダー")

何かの値を取得するメソッドからは、変数などで値を受け取ることができます。

VB.NET 2002 VB.NET 2003 VB2005 VB2008 VB2010 VB2012 VB2013 VB2015 VB2017 VB2019

'196の平方根を取得します。
Dim root As Double = Math.Sqrt(196)
MsgBox(root)

'マウスのNumLockが押されているかを取得します。Trueの場合、押されています。
Dim isNumLocked As Boolean = Control.IsKeyLocked(Keys.NumLock)
MsgBox(isNumLocked)

'500を16進数で表記した値を取得します。
Dim hexValue As String = Convert.ToString(500, 16)
MsgBox(hexValue)

この例の Keys.NumLock は列挙体です。

 

3-1-2.戻り値

メソッドが返す値のことをメソッドの「戻り値」(もどりち)または「返り値」(かえりち)と呼びます。

戻り値の型が何であるか知る方法はいくつかあります。

1つは入力時のヒントです。

Math.Sqrt( と入力すると、As Double と表示されています。これは戻り値がDouble型であるという意味です。

なお、カッコの中にも d As Double と表示されています。これはDouble型の引数が1つ必要であることを示しています。

もう1つは型推論です。

とりあえずAs xxx を省略して書いてから、変数名の上にマウスをホバーさせると型が表示されます。

もう1つはリファレンスを見る方法です。

フレームワークのクラスやメソッドの説明はすべてMicrosoft Docsに記載されています。

VBではF1キーを押すとリファレンスを表示する便利な機能があるので、Sqrtのテキストのカーソルがある状態でF1キーを押します。

→この操作は入門講座 第8回 ヘルプの使い方 でも説明しています。

リファレンスには戻り値がDouble型であることが明記されています。

 

戻り値がないメソッドもあります。何かの機能は実行するけれども値として何かを取得するわけではないという種類のものです。

たとえば、TextBoxに文字列を追加するAppendTextメソッドは値としては何も返しません。ヒントには「As xxxx」という部分が記述されておらず、戻り値がないことが示されています。

 

3-1-3.引数とオーバーロード

同じ名前のメソッドがオーバーロードされて複数定義されている場合があります。この場合も、コンストラクラーと同じで、引数の型で何番目の定義が呼び出されるのか区別されます。

たとえば、Convert.ToStringメソッドでは1つの数値を指定すると単なる文字列型への型変換を行いますが、2つ目の引数に16や2などを指定すると16進数・2進数で表記したときの文字列を返します。

VB.NET 2002 VB.NET 2003 VB2005 VB2008 VB2010 VB2012 VB2013 VB2015 VB2017 VB2019

'数値の254を文字列の"254"に変換します。単純な型変換です。
Dim st1 As String = Convert.ToString(254)
MsgBox(st1)

'数値の254を16進数で表現した文字列 "fe" に変換します。
Dim st2 As String = Convert.ToString(254, 16)
MsgBox(st2)

'数値の254を2進数で表現した文字列 "11111110" に変換します。
Dim st3 As String = Convert.ToString(254, 2)
MsgBox(st3)

なお、Microsoft DocsのリファレンスにはConver.ToStringのオーバーロードで第2引数に指定できるのは 2, 8, 10, 16 の4つであると書いてあります。試しに3や4などを指定するとエラーになります。

https://docs.microsoft.com/ja-jp/dotnet/api/system.convert.tostring?view=netframework-4.8#System_Convert_ToString_System_Int32_System_Int32_

 

3-2.非共有メソッド

非共有メソッドはインスタンスから呼び出すメソッドです。メソッドの多くは非共有メソッドです。

コンストラクターなどを使用してインスタンスを作成してから呼び出します。

下記は非共有メソッドの利用例です。

※途中で使用している Taskクラスが .NET Framework 4.5以上で使用できるため、古いVisual Studioのバージョンではこの例は実行できませんが、非共有メソッドの呼び出し方はVisual Basic.NET (2002)以上では同じです。Taskから始まる行を削除すると古いバージョンのVisual Studioでも実行できます。

VB2012 VB2013 VB2015 VB2017 VB2019

'▼JapaneseCalendarクラスのGetEraメソッドの呼び出し

Dim calendar As New Globalization.JapaneseCalendar
'1:明治, 2:大正, 3:昭和, 4:平成, 5:令和
Dim eraNumber As Integer = calendar.GetEra(#2020/6/27#)
MsgBox(eraNumber,, "GetEra") '「5」が表示されます。

'▼DirectoryInfoクラスのCreateメソッドとMoveToメソッドの呼び出し

Dim folder As New IO.DirectoryInfo("C:\temp\testfolder")
'フォルダーを作成します。
folder.Create()

'名前を testfolder2 に変更します。(2回目の実行ではエラーになります。)
folder.MoveTo("C:\temp\testfolder2")

'▼StopwatchクラスのStartメソッドとStopメソッドの呼び出し

Dim watch As New Stopwatch
watch.Start()

Task.Delay(3000).Wait() '3秒間何もしないで待ちます。

watch.Stop()

MsgBox(watch.ElapsedMilliseconds / 1000 & "秒経過しました。",, "StopWatch")

インスタンスを作成するためにNewを使ってコンストラクターを呼び出している以外は共有メソッドと変わりありません。

この例のなかでフォルダーを作成して名前変更している部分は、既に同じ名前のフォルダーがあるとエラーになるため、2回目の実行ではエラーになります。2回以上実行する場合は事前にフォルダーを削除してから実行してください。

 

1箇所目立たないのですが、 Task.Delay(3000).Wait() と書いてある部分は、ちょっと難しく、変数を経由しないインスタンスの一種です。

Delayメソッド (読み方:Delay = ディレイ)は、Taskクラス (読み方:Task = タスク)の共有メソッドでTaskクラスのインスタンスを作成しています。これは New でコンストラクラーを呼び出さないでインスタンスを作成する機能です。

どういうカラクリかというと、Delayメソッドの中で、コンストラクターが呼ばれてインスタンスが作成されています。そして、Delayメソッドはそのインスタンスを戻り値として返すわけです。

つまり、Delayメソッドをプログラムしたマイクロソフトのプログラマーがこの中にTaskクラスのコンストラクターを呼び出すプログラムを書いているわけです。DelayメソッドはC#で作成されているため、コンストラクターの呼び出し方はVBとは違いますが、もしVBで作られているならこの中でNewが使われていたことになります。

この部分を変数を経由するインスタンスに書き換えると次のようになります。

VB2012 VB2013 VB2015 VB2017 VB2019

Dim t As Task = Task.Delay(3000)
t.Wait()

この形だとピンと来ると思います。Delayが共有メソッド、Wait(読み方:Wait = ウェイト)が非共有メソッドです。

なお、これの機能はDelayで3000ミリ秒何もしない処理を作成し、Waitでその処理を実行し、処理が完了するまで待機するというものです。

 

3-3.Call

メソッドを呼び出して、戻り値を受け取らない場合、呼び出しの先頭に Call (コール) と記述してメソッドの呼び出しであることを明確化することができます。

VB.NET 2002 VB.NET 2003 VB2005 VB2008 VB2010 VB2012 VB2013 VB2015 VB2017 VB2019


Call Clipboard.SetText("あいうえお")

Callはあってもなくても機能・性能に変わりありません。共有メソッドでも非共有メソッドでも使用できます。

書かなくても良いので書かないプログラマーの方が圧倒多数です。おそらく見かけることはないと思いますが、昔(1998年頃)はCallを好むプログラマーもいたため、古いプログラムで見かけることがあるかもしれません。

発展 発展学習  -  Call の有無で意味が変わる例もなくはないです。

発展学習では意欲的な方のために現段階では特に理解する必要はない項目を解説します。

Call の有無で意味が変わる例もなくはないです。

https://stackoverflow.com/questions/2573597/should-i-use-call-keyword-in-vb-vba

 

3-4.練習問題

EnvironmentクラスのExitメソッドを呼び出そうとしたところ、次のようなヒントが表示された。このヒントとプログラムから読み取れることをすべて選択してください。

引数が1個必要
第1引数はInteger型
Exitは非共有メソッド
戻り値はInteger型
Callをつけても呼び出せる
オーバーロードなし

 

 

4.プロパティ

プロパティは値の代入と値の参照ができます。使い方は変数と同じように = を記述します。

次の例はOpenFileDialogクラス(読み方:OpenFileDialog = オープンファイルダイアログ)のプロパティに値を代入したり、プロパティを参照して値を取得する例です。

OpenFileDialogクラスはWindowsフォームアプリケーションで使用するようにデザインされているためこの例を試すにはWindowsフォームアプリケーションのプロジェクトで実行する必要があります。

この例を実行するとWindowsで良く見かけるファイルを開くダイアログが表示され、ファイルの選択をうながされます。

VB.NET 2002 VB.NET 2003 VB2005 VB2008 VB2010 VB2012 VB2013 VB2015 VB2017 VB2019

'OpenFileDialogクラスのコンストラクター呼び出し
Dim dialog As New OpenFileDialog

'InitialDirectoryプロパティへの代入
dialog.InitialDirectory = "C:\Windows\"

'ShowDialogメソッドの呼び出し。
dialog.ShowDialog()

'FileNameプロパティの参照
Dim result As String = dialog.FileName

MsgBox(result)

この例では、ファイルを選択して選択したファイルの名前を表示するだけです。ファイルの内容が書き換わるようなことはありません。ファイルの読み込みすら行っていません。

コンストラクター・メソッド・プロパティの3種類が登場しています。

 

プロパティは値の代入と参照ができるという点で変数に似ていますが、変数とは違って代入や参照を行ったタイミングで何かの処理が実行されることがあります。されないこともあります。何かの処理が実行されるかどうかはそのプロパティの定義によります。

たとえば、次の例は四角形を現すRectangle構造体の例です。

VB.NET 2002 VB.NET 2003 VB2005 VB2008 VB2010 VB2012 VB2013 VB2015 VB2017 VB2019

Dim rect As New Rectangle
rect.X = 2 '四角形の左上の点の X座標は 2
rect.Y = 5 '四角形の左上の点の Y座標は 5
rect.Width = 20 '四角形の幅は 20
rect.Height = 15 '四角形の高さは 15

'Rightプロパティを参照して、四角形の「右下」のX座標を取得する。
Dim r As Integer = rect.Right

'22 と表示されます。
MsgBox(r)

四角形の左上の座標が(2, 5)、四角形の幅が100、四角形の高さが50 になるようにプロパティを代入しています。

学校数学とは異なり、Y座標軸は上がマイナスで下がプラスですので、次のような四角形を定義した上で最後に Right の値を取得するのが上記のプログラムの意味です。

Rightの値は、ちょっと計算すればすぐにわかります。 2 + 20 で 22 ですね。実際 22 と表示されます。

Rightプロパティ (読み方:Right = ライト) を参照するときも実際のところ、Rectangle構造体のプログラムの中でこの計算処理が実行されており、計算結果が返されているだけです。つまり、Rectangle構造体では、Rightプロパティに相当する値は実際には持っておらず計算によって値を返しているというわけです。

この点がプロパティと変数の違いです。変数は計算などの処理を実行することはできず単純に値を読み書きできるだけですが、プロパティは値を代入・参照するときに何かの処理を実行することができるということです。

どのような処理をするかはプログラム次第であり、計算以外の機能をもった処理を実行することも可能です。が、私はマイクロソフトが作ったプログラムの中でプロパティを使って計算以外の機能があるクラスや構造体が思いつかないので例は割愛します。もしかしたら、マイクロソフト製のクラス・構造体の中ではそのような処理を行っているものはないかもしれません。でも、仕様上そのような処理もありえるということを覚えておくと、マイクロソフト以外のプログラマーが作成したクラス・構造体のプロパティを使うときに役立つでしょう。

 

5.フィールド

なお、クラスや構造体のメンバーの一種である「フィールド」は変数と同じであり単純に値を読み書きするだけです。フィールドを持っているクラス・構造体はかなり少数派です。たとえば、Mathクラス(読み方:Math = マス)のPIフィールド(読み方:PI = パイ)は円周率を表すフィールドです。共有メンバーなのでクラス名を記述して呼び出します。

VB.NET 2002 VB.NET 2003 VB2005 VB2008 VB2010 VB2012 VB2013 VB2015 VB2017 VB2019

Dim value As Double = Math.PI

'3.14159265358979 と表示されます。
MsgBox(value)

フィールドには代入と参照の両方ができるものと、代入しかできないもの、参照しかできないものがあり得ます。PIフィールドは参照しかできないフィールドです。

 

6.共有メンバーと非共有メンバーを区別する方法

共有メンバーと非共有メンバーを区別する方法はいくつかあります。

1つはMicrosoft Docsのリファレンスを確認する方法です。リファレンス上には必ずメンバーの定義が書かれています。メンバーの定義に Shared というキーワード(読み方:Shared = シェアード)が含まれている場合、それは共有メンバーです。

https://docs.microsoft.com/ja-jp/dotnet/api/system.math.sqrt?view=netframework-4.8

Sharedは青い時で Public Shared Function Sqrt・・・のように記述されています。

 

もう1つはVisual Studio上で試しにクラス名. と入力して、インテリセンスの入力候補に何が表示されるか見ることです。

Visual Studioは賢いので、入力候補にはその時入力できるものを表示します。クラス名. に続けて入力できるものは共有メンバーなのでこの一覧の中に含まれていれば共有メンバーです。

 

他には表示メニューから起動できるオブジェクトブラウザーというツールで確認する方法もあります。

 

確認が必要な場合、私はインテリセンスで見てみることが多いです。

発展 発展学習  -  私の場合

発展学習では意欲的な方のために現段階では特に理解する必要はない項目を解説します。

慣れてくると共有メンバーと非共有メンバーの区別は自然とできるようになってくるので確認をすることは少ないです。基本的には大多数は非共有メンバーなので、知らないメソッドやプロパティを見たらまず非共有メンバーだと思います。それを使う上で引数だけですべてが判断できる情報量がある場合、その情報だけで処理ができるので共有メンバーです。非共有メンバーは事前に与えた別の情報を基に処理します。

たとえば、ファイルを削除するFile.Deleteメソッドは引数にファイル名をとります。ということはこれだけでやるべき処理が確定し、その情報だけで処理ができるので共有メンバーであると考えるのが妥当です。

興味深いことにファイルを削除するメソッドはもう1つあります。 FileInfo.Deleteメソッドです。こちらは引数をとりません。ということはこれだけではなにをやるべきなのか判断できず、別途他に対象を指定する手段があるはずです。それはプロパティかコンストラクターか他の何かのメソッドかもしれません。とにかく、Deleteメソッド以外のメンバーと連携する必要が発生するのでこれはインスタンスを使用する必要があり、非共有メンバーと考えるの妥当です。

もっとも、プログラムにはいろいろな作り方があるので、これだけで判断できない場合もあります。たとえば、外部の設定ファイルに書かれているものをすべて削除する機能であれば、引数なしのDeleteメソッドが共有メソッドということもありえます(あまり良い作りではありませんが・・・)。ここで紹介したのはあくまで考え方の話です。考えたことと実際が違う場合もあります。はっきりさせるにはMicrosoft Docsのリファレンスを見るのが一番ですが、毎回リファレンスを見るのも大変です。

 

7.引数

7-1.省略可能引数

コンストラクターやメソッドには引数があるものがあります。ごくまれにプロパティに引数が付いている場合もあります。

ここまでの説明では、引数が必要な場合、定義されている順番に カンマ で区切って指定する方法だけを説明してきましたが、少し補足することがあります。

まず、引数には名前が付いています。引数の名前はVisual Studioで表示されるヒントやリファレンスで確認できます。

 

普段良く使っている MsgBoxは、実体はInteractionモジュール(読み方:Interaction = インタラクション)の共有メソッドです。モジュールはクラスの1種です。詳しくは次回説明します。

 

ヒントを見ると、第1引数に Prompt という名前がついているのがわかります。それから、3つ目の引数に Title という名前がついています。

ヒントが長いので引数が何番目なのかわかりにくいかもしれません。カンマで何回区切られているか見れば、どのヒントが何番目の引数のものなのかわかります。

このヒントから読み取れる引数の情報の一部を表にすると下記の通りです。

  引数の名前 引数の型 省略可能?
第1引数 Prompt Object ×
第2引数 Buttons MsgBoxStyle 省略可能
第3引数 Title Object 省略可能

第2引数と第3引数はヒントの中で [ ] で囲まれています。これは省略可能であることを表しています。

そのため、MsgBoxは最低限第1引数の Prompt だけ指定すれば呼び出せるわけです。

VB6 VB.NET 2002 VB.NET 2003 VB2005 VB2008 VB2010 VB2012 VB2013 VB2015 VB2017 VB2019


MsgBox("Hello!")

省略可能引数は1998年のVB6のころが最盛期でした。現在(2020年)ではかなり少数派です。見かけることはあまりないでしょう。MsgBoxは大昔(1991年頃?)から存在する生きている化石のような機能なので省略可能引数が使われています。省略可能引数が少数派になった理由は、2002年に導入されたオーバーロード機能を使っても同じようなことを表現できるということと、同じく2002年に生まれた兄弟言語であるC#には省略可能引数という機能がなかったため、C#からVBを呼び出す場合に省略可能引数が使われていると不便だったことが挙げられます。

第1引数と第3引数だけ指定するには、第2引数を省略していることを示すためにカンマだけは必要です。

VB.NET 2002 VB.NET 2003 VB2005 VB2008 VB2010 VB2012 VB2013 VB2015 VB2017 VB2019


MsgBox("Hello!", , "タイトル")

省略された引数にはコンパイル時に既定値が割り当てられます。引数はヒントの中で = xxxx という形で示されています。

MsgBoxの場合第2引数を省略すると自動的に MsgBoxStyle.ApplicationModal が指定されます。第3引数はNothingです。

メモ メモ  -  MsgBoxStyle
MsgBoxStyle.ApplicationModal (読み方:MsgBoxStyle = メッセージボックススタイル、ApplicationModal = アプリケーションモーダル)は列挙体です。MsgBoxの第2引数に指定すると、メッセージボックスを閉じるまで本体のアプリケーションが操作できなくなります。・・・が、この列挙体のほかの値を指定してもこの動作は変わらないので、ApplicationModalという値自体には特に意味はないようです。実際に定義されている値は 0 です。
この列挙体のほかの値を指定するとMsgBoxの表示や動作が少し変わります。複数の値を or でつなげて指定することもできます。たとえば、MsgBoxStyle.Information はメッセージボックスに情報を示すアイコンを表示します。MsgBoxStyle.YesNo はメッセージボックスに「はい」「いいえ」のボタンを表示します。この2つを同時に指定するには or を使います。

VB.NET 2002 VB.NET 2003 VB2005 VB2008 VB2010 VB2012 VB2013 VB2015 VB2017 VB2019


MsgBox("見えますか?", MsgBoxStyle.Information Or MsgBoxStyle.YesNo)


リファレンス上では省略可能な引数は [ ] ではなく、Optional というキーワード (読み方:Optional = オプショナル)で表現されます。

 

 

7-2.名前付き引数

順番ではなく、名前で引数に値を設定することもできます。

VB.NET 2002 VB.NET 2003 VB2005 VB2008 VB2010 VB2012 VB2013 VB2015 VB2017 VB2019


MsgBox("Hello!", Title:="タイトル")

名前で引数を指定する場合は、 引数名 := 値 という構文を使用します。

この例では第1引数は順番で指定し、Title引数は名前で指定しています。

 

複数の引数を名前で指定することもできます。

VB.NET 2002 VB.NET 2003 VB2005 VB2008 VB2010 VB2012 VB2013 VB2015 VB2017 VB2019


MsgBox(Prompt:="Hello!", Title:="タイトル")

引数を区切るために間にカンマが必要ですが、すべての引数が名前で指定されているため、順番は関係なくなります。

次のように書き換えても動作します。

VB.NET 2002 VB.NET 2003 VB2005 VB2008 VB2010 VB2012 VB2013 VB2015 VB2017 VB2019


MsgBox(Title:="タイトル", Prompt:="Hello!")

 

名前で引数を指定するメリットは意味がわかりやすくなることです。

たとえば、先ほども例で紹介したConvertクラスのToStringメソッドを、引数の値を変えてもう1度紹介します。

VB.NET 2002 VB.NET 2003 VB2005 VB2008 VB2010 VB2012 VB2013 VB2015 VB2017 VB2019

Dim st As String = Convert.ToString(8, 16)

MsgBox(st)

このメソッドは 8 を 16進数で表現した文字列に変換するか、16 を 8進数で表現した文字列に変換するかどちらかなのですが、どっちが正解か覚えているでしょうか?

ちょっと混乱してしまいますよね。

下記のように名前付き引数として指定してあれば、英語がわかる人に限りますが、8 を 16進数で表現するんだなという意味が伝わりやすくなります。

VB.NET 2002 VB.NET 2003 VB2005 VB2008 VB2010 VB2012 VB2013 VB2015 VB2017 VB2019

Dim st As String = Convert.ToString(value:=8, toBase:=16)

MsgBox(st)

 

とはいえ、私は誰かが名前付き引数を使ってプログラムしているのを見たことはないです。実際のプログラムでは 8, 16 のようなリテラルで値を指定することは少なく、変数を使用することが多いためです。変数自体に名前がついているため、引数の名前を利用しなくても意味がわかるようにできるのです。そのため名前付き引数を使っている人はかなり少数派だと思います。

参考に、変数の名前を使って同じようなことをする例も紹介しておきます。

VB.NET 2002 VB.NET 2003 VB2005 VB2008 VB2010 VB2012 VB2013 VB2015 VB2017 VB2019

Dim value As Integer = 8
Dim toBase As Integer = 16

Dim st As String = Convert.ToString(value, toBase)