JavaからVB.NETへ ―書き方対照メモ―

# この記事について
## 作成の経緯
新人研修で3ヶ月間Javaをやってきたけれども、配属先部署で使う言語はVisual Basic .NETだったので新しく学ぶ必要が生じた。
しかし、「JavaからVB.NETへ移行」というケースはそんなにないのか（今ならC#あたりが普通…？）、文法の比較などを細かくしているサイトが見つからなかったため、自分で書いてみることにした。

## 対象者・目的
- Javaの書き方やプログラミングの諸概念は一通り理解している
- これからVB.NETでもプログラムを書けるようになりたい

という人（まあ自分と数名の同期だけれど）にJavaとVB.NETの比較対象リファレンスを提供する。

## 環境
- Windows 10
- Visual Studio 2019
- .NET Framework 4.7.2

といっても、環境に依存するようなコードはほぼないはず。

## 記述上の注意
- Visual Basic .NET（VB.NET）のことは、以下単に「VB」と呼ぶ。
- 同じセクションにあるJavaとVBのコードは、基本的に同じ処理になるようにしている。

## 参考文献（総合）
- 羽山 博『基礎 Visual Basic 2019』（株式会社インプレス、2019年）
  - VBを学習する上でお世話になっている教本。Javaなど他の言語を知っていれば、フルタイム×1週間くらいで読めてしまうと思われる。
- [Java屋さんからVB.netプログラマになるために - Qiita](https://qiita.com/5zm/items/44d05463875ff0e29da0#3-%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB)
  - Javaの視点からVBを見た数少ない記事。
- [Visual Basic のドキュメント - はじめに、チュートリアル、リファレンス。 | Microsoft Docs](https://docs.microsoft.com/ja-jp/dotnet/visual-basic/)

# コードの基本構造

## main

```java:Main.java
public class Main {
    public static void main(String[] args) {
        System.out.println("Hello Java!");
        int a; String b; double c;
    }
}
```

- ブロックは `{}` で区切られる
- `public` などの修飾子は小文字
- `;`で文を終える（改行それ自体は意味をもたない）

```vb:Form1.vb
Public Class Form1
    Private Sub ShowMessage(sender As Object, e As EventArgs) _ 
    Handles Button1.Click
        Console.WriteLine("Hello VB!")
        Dim a As Integer : Dim b As String : Dim c As Double
    End Sub
End Class
```

- ブロックは `(修飾子) Class` 〜 `End Class` のように分けられる
- 行の終わりは文（ステートメント）の終わり。
  - 長い文中で意図的に改行させたいときは、行継続文字 `_` を入れる
  - ただし、VB2010からは、特定の条件下で行継続文字がなくても改行できるようになった（暗黙の行継続）。
  - 詳しいルールは[Visual Basic 2010の新機能 - @IT](https://www.atmarkit.co.jp/fdotnet/chushin/vb2010features_01/vb2010features_01_01.html)を参照
- 1行の中に複数のステートメントを入れたいときは、 `:` で区切る。

## コメント
```java:Comment.java
// 単数行コメント

/*
 * 複数行コメント
 */
```

```vb:Comment.vb
' 単数行コメント
```
※VBに複数行コメントはない

## ドキュメンテーションコメント
専用ツールでAPIドキュメントを生成したり、メソッド名上マウスオーバーで説明を表示したりできるやつ。

- **Java:** Javadoc形式で記述する。 `/**` ~ `*/`
  - Eclipseでは、対象メンバにカーソルを当ててから Alt+Shift+J で生成できる

```java:JavaDoc.java
/**
 * 引数で指定された2つの整数をかけ算し、その結果を返す。
 * @param a  かける数1
 * @param a  かける数2
 * @return かけ算の結果
 */
public static int doCalc(int a, int b) {
    return a * b;
}
```

- **VB:** XMLで記述する。 `'''`
  - Visual Studioでは、 対象メンバのすぐ上の行で `'''` と打つと生成できる。

```vb:XmlDoc.vb
''' <summary>
''' 引数で指定された2つの整数をかけ算し、その結果を返す。
''' </summary>
''' <param name="a">かける数1</param>
''' <param name="b">かける数2</param>
''' <returns>かけ算の結果</returns>
Public Shared Function DoCalc(a As Integer, b As Integer) As Integer
    Return a * b
End Function

```

### 参考
- [XML ドキュメントのコメントを挿入する - Visual Studio | Microsoft Docs](https://docs.microsoft.com/ja-jp/visualstudio/ide/reference/generate-xml-documentation-comments?view=vs-2019)


# ファイル・フォルダ構成
※一部省略あり
## Java (Eclipse)の例
- JavaProject
  - bin
    - package
      - `Main.class`（ビルドされたJavaバイトコード）
  - src
    - package
      - **`main.java`**（ソースコード）
  - lib
  - doc
  - `.project` （Eclipseプロジェクトファイル）
  - `.settings`
  - `.classpath`

## VB.NET Windows フォーム アプリケーション（Visual Studio）の例
- VisualStudioSolution
  - **`VisualStudioSolution.sln`** （VSソリューションファイル）
  - FirstProject
    - `FirstProject.vbproj` （VBプロジェクトファイル）
    - bin
      - Debug
        - **`FirstProject.exe`** （ビルドされたデバッグ用実行ファイル）
      - Release
    - My Project
    - obj
    - `App.config`
    - **`Form1.vb`** （ソースコード[動作]）
    - **`Form1.Designer.vb`** （ソースコード[デザイン]）
  - SecondProject
    - （FirstProjectと同様）

Visual Studioでは、複数のプロジェクトを**ソリューション**としてまとめることができる。（Eclipseでも**ワーキング・セット**というものもあるが）


# 変数
## データ型分類
- Java
  - 基本型（`byte`, `short`, `int`, `long`, `float`, `double`, `char`, `boolean`）
  - 参照型（`String`など）
- VB
  - 値型（`Byte`, `Short`, `Integer`, `Long`, **`Single`**（float相当）, `Double`, **`Decimal`**（10進型）, `Char`, `Boolean`, **`Date`** など）
  - 参照型（`String` など）

日付型は、Javaでは`java.util.Date`、`java.util.Calender`、`java.time`などの標準APIを使う必要がある（つまり必然的に参照型になる）。しかしVBでは、日付・時刻を管理できる[`Date`型](https://docs.microsoft.com/ja-jp/dotnet/visual-basic/language-reference/data-types/date-data-type)を標準で用意している。

## 宣言・アクセス修飾

```java:DeclareVariable.java
int number; // package private
String message; // package private
public int publicNumber;
private String privateMessage;
```

```vb:DeclareVariable.vb
Dim Something ' Private
Dim Number As Integer ' Private
Dim Message As String ' Private
Public PublicNumber As Integer
```

VB標準設定では、変数の宣言時に型の指定を省略することができる。その場合、初期値のデータ型に従って自動的に変数のデータ型も決められる（型の推定）。初期値がない場合はObject型とみなされる。`Option Strict On`にすると、型の推定は無効になる。

### 変数名の規則

|文字|Java|VB|備考|
|----|----|----|----|
|半角英数字|○|○||
|日本語文字|○|○|もちろんあまり推奨されない|
|`_`|○|○|アンダースコア|
|`&`|○|×||
|先頭が数字|×|×||

## 初期化
```java:InitiarizeVariable.java
int number = 100; 
String message = "Hello"; 

```

```vb:InitiarizeVariable.vb
Dim Number As Integer = 100
Dim Message As String = "Hello"
Dim Pi = 3.14 ' 自動的にDouble型として扱われる
Dim BlankNumber As Integer ' 初期値は自動的に「0」になる
Dim BlankMessage As String ' 初期値は自動的に「Nothing」になる
```

## 定数宣言
```java:Constant.java
final int MAX_STOCK = 100;
public static final String VERSION_ID = "v1.0.1-RELEASE";
```

```vb:Constant.vb
Const MAX_STOCK As Integer = 100
Const VERSION_ID As String = "v1.0.1-RELEASE" ' ConstステートメントではSharedは使えない
```


### 参考
- [データ型の概要 (Visual Basic) | Microsoft Docs](https://docs.microsoft.com/ja-jp/dotnet/visual-basic/language-reference/data-types/)


# 演算子
## 算術演算子
|機能|Java|VB.NET|備考|
|---|----|------|----|
|加算|`a + b`|`a + b`||
|減算|`a - b`|`a - b`||
|乗算|`a * b`|`a * b`||
|除算|`a / b`|`a / b`||
|整数除算（商）|N/A|**`a \ b`**|[VB] aとbはどちらも整数型でなければならない。<br>`23 \ 5` の結果は`4`になる|
|剰余（余り）|`a % b`|**`a Mod b`**|`23 % 5` ないし `23 Mod 5` の結果は`3`になる|
|累乗|（演算子としてはなし）|**`a ^ b`**|VBの`^`は算術演算子の中で優先順位が最も高いことに注意|
|インクリメント|`++a` または `a++`|**N/A**|VBでは`a += 1`などど書くしかない|
|インクリメント|`--a` または `a--`|**N/A**|VBでは`a -= 1`などど書くしかない|

### 整数同士の除算
Javaでは、割られる数`a`と割る数`b`の両方が整数だと、結果の小数点以下が切り捨てられ、整数になる。これは代入先が`double`型などの変数であっても変わらない。

```java:DivideInteger.java
double x;
x = 23 / 5; // xは4.0になる
```

少なくとも片方が小数（倍精度浮動小数点数）だと、結果も小数になる。

```java.DivideDouble.java
double x;
x = 23 / 5.0 //　xは4.6になる
```

一方、VBではできるだけ精度が落ちないように演算が行われる。

```vb:DivideInteger.vb
Dim x As Double
x = 23 / 5 ' xは4ではなく4.6になる
```

VBでもJavaのように整数同士の除算をしたい場合に、`\`演算子を使う。
```vb:DivideWithBackSlashOperator.
Dim x As Double
x = 23 \ 5 ' xは4になる
```

### Javaにおける累乗
Javaでは、 `java.lang.Math.pow(a, b)` を使う。
第1引数`a`が底、第2引数`b`が指数（つまりVBでいうところの `a ^ b`）。


## 代入演算子
|機能|Java|VB.NET|備考|
|---|----|------|----|
|そのまま代入|`a = b`|`a = b`||
|加算結果を代入|`a += b`|`a += b`||
|減算結果を代入|`a -= b`|`a -= b`||
|乗算結果を代入|`a *= b`|`a *= b`||
|除算結果を代入|`a /= b`|`a /= b`||
|整数除算の結果を代入|N/A|**`a \= b`**||
|剰余（余り）を代入|`a % b`|**N/A**|[VB]Modに対応するものはない|

（ビット演算系は省略）

## 比較演算子
|機能|Java|VB.NET|備考|
|---|----|------|----|
|aはbよりも小さい|`a < b`|`a < b`||
|aはb以下|`a <= b`|`a <= b`||
|aはbよりも大きい|`a > b`|`a > b`||
|aはb以上|`a >= b`|`a >= b`||
|aはbに等しい|`a == b`|**`a = b`**|VBでは`=`は1個|
|aはbに等しくない|`a != b`|**`a <> b`**||

## 論理演算子
以下の表では`A`や`B`は条件式（True/Falseを返す式）を表す。

|論理|機能|Java|VB.NET|
|---|---|----|------|
|論理積(AND)|AかつB|N/A|`A And B`|
|論理積(AND)|AかつB(短絡評価）|`A && B`|`A AndAlso B`|
|論理和(OR)|AまたはB|N/A|`A Or B`|
|論理和(OR)|AまたはB(短絡評価）|`A && B`|`A OrElse B`|
|論理積(NOT)|Aでない|`!A`|`Not A`|
|排他的論理和(XOR)|AまたはB、しかしAかつBではない|`^A`|`A Xor B`|

> **短絡評価：**
> AがFalseなら条件式全体がFalseになることが確定するので、Bを評価せずに先へ進むこと。
> このとき、Bに何らかのメソッドが書いてあっても実行されない。
> これを利用して、AがTrueにならないとエラーになる式をBに書くことができる。
> 例： `If Integer.TryParse(str, num) AndAlso num < 5 Then ...`

## 連結演算子
Javaでは文字列の連結に `+` を使うが、VBでは `&` を使う。

VBでも`+`で文字列連結をすることは可能だが、片方が文字列型でない場合に意図しない結果となったり、エラーになる可能性があるため、Microsoftは`&`の使用を推奨している。

## 演算子の参考ページ
- [演算子 | Javaコード入門](https://java-code.jp/64)
- [演算子 - Visual Basic | Microsoft Docs](https://docs.microsoft.com/ja-jp/dotnet/visual-basic/language-reference/operators/)

# 型変換

# 条件分岐
## if文 / Ifステートメント
```java:ConditionalBranch.java
if (age < 20) canBuyAlcohol = true;

if (age < 13) {
    fareType = "child";
} else if (age < 18) {
    fareType = "student";
} else {
    fareType = "adult";
}

```

```vb:ConditionalBranch.vb
If age < 20 Then canBuyAlcohol = True ' 1行ならばEnd Ifはいらない

If age < 13 Then
    FareType = "child"
ElseIf age < 18 Then
    FareType = "student"
Else
    FareType = "adult"
End If

```

VBでは、次のように「`:`」を使って複数のステートメントを1行に書くことも可能。

```vb:ConditionalBranchInOneLine.vb
If 20 < age Then FareType = "adult" : CanBuyAlcohol = true Else CanBuyAlcohol = false
```

## Switch / Select Caseステートメント
### 1つの値と一致させる
```java:ConditionalBranch2.java
switch (num) {
    case 1:
        gender = "男性";
        break;
    case 2:
        gender = "女性";
        break;
    case 3:
        gender = "その他";
        break;
    default:
        gender = "未回答";
        break;
}
```
switch文の式（上記の`num`）は、基本型＋String型（Java SE 7以降）のみ。

```vb:ConditionalBranch2.vb
Select Case Num
    Case 1
        Gender = "男性"
    Case 2
        Gender = "女性"
    Case 3
        Gender = "その他"
    Case Else
        Gender = "未回答"
End Select
```

### 複数の値に一致させる
```java:ConditionalBranch3.java
switch (phoneNumberPrefix) {
    case 090:
    case 080:
    case 070:
        isMobile = true;
        break;
    default:
        isMobile = false;
        break;
}
```

```vb:ConditionalBranch3.vb
Select Case PhoneNumberPrefix
    Case 090, 080, 070
        IsMobile = true
    Case Else
        IsMobile = false
End Select
```

### 値の範囲を指定する
```java:ConditionalBranch4.java
// JavaのSwitch文ではできない（やるとしても別の変数を噛ませるしかない）
```

```vb:ConditionalBranch4.vb
Select Case MonthNumber
    Case 3 To 5
        Season = "春"
    Case 6 To 8
        Season = "夏"
    Case 9 To 11
        Season = "秋"
    Case Else
        Season = "冬"
End Select
```

### 比較演算子を使う
```java:ConditionalBranch5.java
// JavaのSwitch文ではできない（素直にif文使った方が良い）
```

```vb:ConditionalBranch5.vb
Select Case Score
    Case Is < 60
        Grade = "F"
    Case Is < 70
        Grade = "C"
    Case Is < 80
        Grade = "B"
    Case Is < 90
        Grade = "A"
    Case Else
        Grade = "S"
End Select
```

# 繰り返し
## for文 / Forステートメント
```java:ForLoop.java
for (int i = 0; i <= 9; i++) {
    System.out.println(i + "回目の繰り返し処理です");
}
```

```vb:ForLoop.vb
For i As Integer = 0 To 9 Step 1 ' 増分値1の場合、Stepは省略可能
    Debug.WriteLine(i & "回目の繰り返し処理です")
Next
```

どちらの言語でも、For文の初期化式内でループカウンタを宣言するのではなく、For文の外で宣言した変数を使うこともできる。その場合、For文を抜けてもその変数を使うことができる。

```java:ForLoop2.java
int i;
for (i = 0; i <= 9; i++) {
    System.out.println(i + "回目の繰り返し処理です");
}
System.out.println(i + "回繰り返されました");
```

```vb:ForLoop2.vb
Dim i As Integer
For i = 0 To 9 Step 1 ' 増分値1の場合、Stepは省略可能
    Debug.WriteLine(i & "回目の繰り返し処理です")
Next
Debug.WriteLine(i & "回繰り返されました")
```

## 拡張for文 / For-Eachステートメント
```java:ForEachLoop.java
int[] scoreArray = {70, 80, 90};

// 通常のfor文
for (int i = 0; i < scoreArray.length(); i++) {
    System.out.println(scoreArray[i]);
}

// 拡張for文
for (int score : scoreArray) {
    System.out.println(score);
}
```

```vb:ForEachLoop.vb
Dim ScoreArray() As Integer = {70, 80, 90}

' 通常のfor文
For i As Integer = 0 To UBound(ScoreArray) 
    Debug.WriteLine(ScoreArray(i))
Next

' For Eachステートメント
For Each score As Integer In ScoreArray
    Debug.WriteLine(score)
Next
```


## while文 / While-End Whileステートメント
条件がtrueである限り実行し続ける。

```java:WhileLoop.java
int i = 0;
while (i < 10) {
    System.out.println(i + "回目の繰り返し処理です");
    i++;
}
```

```vb:WhileLoop.vb
Dim i As Integer = 0
While i < 10
    Debug.WriteLine(i & "回目の繰り返し処理です")
    i += 1
End While
```

※このサンプルではWhileよりもForのほうが適している

## do-while文 / Do-Loopステートメント
### 後判断型（1回は実行される）
```java:DoWhileLoop.java
Random rd = new Random();
int num = 0;
do {
    num = rd.nextInt(100) + 1;
    System.out.println(num);
} while (num % 2 == 0);
```

```vb:DoLoopWhile.vb
Dim rd As Random = new Random()
Dim Num As Integer = 0

Do
    Num = rd.Next(1, 100)
    Debug.WriteLine(Num)
Loop While Num Mod 2 = 0
```

VBでは、`Loop While 条件` （条件がfalseになるまで繰り返す）のほか、**`Loop Until 条件`**（条件がtrueになるまで繰り返す）というのも使える。

```vb:DoLoopUntil.vb
Dim rd As Random = new Random()
Dim Num As Integer = 0

Do
    Num = rd.Next(1, 100)
    Debug.WriteLine(Num)
Loop Until Num Mod 2 <> 0
```

`Until`以下の条件が逆転しているが、`DoLoopWhile.vb`と`DoLoopUntil.vb`はどちらも同じ処理になる。

### 前判断型（1回も実行されない可能性がある）
```vb:DoLoopWhile2.vb
Dim i As Integer = 0
Do While i < 10
    Debug.WriteLine(i & "回目の繰り返し処理です")
    i += 1
Loop
```

```vb:DoLoopUntil2.vb
Dim i As Integer = 0
Do Until i >= 10
    Debug.WriteLine(i & "回目の繰り返し処理です")
    i += 1
Loop
```

## ループを抜ける
- **Java**：`break;`
- **VB：**`Exit Do`、`Exit For`、`Exit While`

## 途中で次の繰り返しに進む
- **Java：**`continue;`
- **VB：**`Continue Do`、`Continue For`、`Continue While`

# 配列
## 宣言
カッコの中で指定する数字の意味が違う点に注意。

```java:ArrayDecralation.java
int[] numArray = new int[5];
```
インデックス `0`, `1`, `2`, `3`, `4` の合計**5個の要素**を持った配列になる。
`[n]` で指定するのは**配列の要素数**。

```vb:ArrayDeclaration.vb
Dim NumArray(4) As Integer
```

インデックス `0`, `1`, `2`, `3`, **`4`** の合計5個の要素を持った配列になる。
`(n)` で指定するのは**インデックスの最大値**。

## 初期化
```java:ArrayInit.java
int[] numArray = { 10, 20, 30, 40, 50 };
```

```vb:ArrayInit.vb
Dim NumArray() As Integer = { 10, 20, 30, 40, 50 }
```

## 代入・利用
```java:ArrayUse.java
numArray[3] = 31;

int a = numArray[3];
```

```vb:ArrayUse.vb
NumArray(3) = 31

Dim a As Integer = NumArray(3)
```

## 多次元配列
```java:MultiDArray.vb
int[][] numArray = new int[3][4];
double[][] doubleArray = { { 0.0, 0.1, 0.2 }, { 1.1, 2.2, 3.3, 4.4 } };
```

```vb:MultiDArray.vb
Dim NumArray(2, 3) As Integer
Dim DoubleArray(, ) As Double = { { 0.0, 0.1, 0.2 }, { 1.1, 2.2, 3.3, 4.4 } }
```
`(, )`は一見するとインデックス最大値を入れ忘れているようにも見えるが、Javaでいう`[][]`に相当するもの。

## 配列サイズの変更
Javaでは一度作った配列のサイズを変更することはできず、新たに配列を作ってそこに値を移し替えるしかない。

しかし、VBでは**`ReDim`ステートメント**を使うことで配列のサイズを変更できる。

```vb:ChangeArraySize.vb
Dim NumArray(9) As Integer

' ...

ReDim Preserve NumArray(6)
```
`Preserve` を付けると、元の要素の値が保持される（**付けないと全ての要素が空になる**）。
要素数を減らした場合、減らされた分の要素は削除される（上記例では、インデックス`7`, `8`, `9`の3要素は削除される）。

## 配列の長さ（要素数）
- **Java**
  - `配列名.length` （要素数を返す） を使う。

```java:ArrayLength.java
int[] numArray = new int[5];

for (int i = 0; i < numArray.length; i++) {
    numArray[i] = i; 
}
// 配列の中身は {0, 1, 2, 3, 4} になる
```

- **VB**:
  - `配列名.Length` （**要素数**を返す）を使う。
  - 繰り返しで全要素を処理する場合は、 `UBound(配列名)` （**インデックスの最大値**を返す）を使う。
    - For文の **`To`** は `<` ではなく **`<=`** の意味。
    - したがって、 `0 To 配列名.Length` と書くと、最終回で配列の長さを突き抜けてしまい `System.IndexOutOfRangeException` になる。
    - どうしても`UBound()` を覚えたくなければ、`配列名.Length - 1`でもいけなくはないが…

```vb:ArrayLength.java
Dim NumArray(4) As Integer

For i As Integer = 0 To UBound(NumArray)
    NumArray(i) = i
Next
' 配列の中身は {0, 1, 2, 3, 4} になる
```

# メソッド / プロシージャ
## 概念の整理（整理し切れていない）
基本的に、「メソッド」＝「プロシージャ」だと思っても実用上は困らない。

Javaでは「メソッド」しか出てこないのに対して、VBではどちらの単語も登場する。やっていることは同じ「一連の処理をまとめる」ということだが、「メソッド」は、プロシージャの中でもその所属元を意識している言葉、らしい。

「オブジェクト」が持つ「性質」（フィールド）と「**機能**」（**メソッド**）、という感じ。

ただ、英語で "what is the difference between a method and a procedure in visual basic" ってググると、"method vs procedure" じゃなくて "function vs procedure" って書いてあるページばかりがヒットする（method = function？）
このあたりはプログラム言語の歴史（関数 function とか サブルーチン subroutine）にかかわってきそう。

### 参考
- [VBA マクロ、プロシージャ、メソッドなどの用語について正確に理解する - t-hom’s diary](https://thom.hateblo.jp/entry/2017/01/29/101605)
- [関数、メソッド、プロシージャ。それぞれの違いは？ - Blank?=False](http://stonebeach-dakar.hatenablog.com/entry/2016/11/22/072344)

## 用語の比較
|対象|Java|VB|
|----|----|----|
|戻り値を返さない処理|メソッド（`void`）|`Sub`プロシージャー|
|戻り値を返す処理|メソッド（`void`以外）|`Function`プロシージャー|
|クラスフィールドの読み書きをする処理|`getter`/`setterメソッド`|`Property`プロシージャー|
|個々のインスタンスに属する処理|インスタンスメソッド|（普通の`Sub`/`Function`プロシージャー）|
|クラス全体に属する処理|`static`メソッド|共有（`Shared`）メソッド|
|イベントに応じた処理|N/A|イベントハンドラー（Subプロシージャーの一形態）

## Subプロシージャー
戻り値を**返さない** 処理。（直接の戻り値がないだけなので、参照渡しを使って呼び出し元に存在する変数やオブジェクトを書き換え、データを返すようなことは可能）

- **Java**: `アクセス修飾子 [static] void 名前(型名 引数名, ...) {` ～ `}`

```java:VoidMethod.java
public void showMessage(int a, int b) {
    System.out.println(a + b);
}
```

- **VB**: `アクセス修飾子 [Shared] Sub 名前(引数名 As 型名, ...)` ～ `End Function`
  - イベントハンドラーもここに属する（後ろに `Handles`句が付くやつ）

```vb:SubProc.vb
Public Sub ShowMessage(Str1 As String, Str2 As String)
    Debug.WriteLine(a + b)
End Sub
```

## Functionプロシージャー
戻り値を**返す**処理。

- **Java**: `アクセス修飾子 [static] 戻り値の型 名前(型名 引数名, ...) {` ～ `}`
  - `return` で戻り値を指定する

```java:ReturnMethod.java

public int doCalc(int a, int b) {
    return a * b;
}
```

- **VB**: `アクセス修飾子 [Shared] Function 名前(引数名 As 型名, ...) As 戻り値の型` ～ `End Function`
  - `Return` で戻り値を指定する

```vb:FunctionProc.vb
Public Function DoCalc(a As Integer, b As Integer) As Integer
    Return a * b
End Function
```

## Propertyプロシージャー
→ クラスの項目で解説

## プロシージャーを途中で抜ける
```java:ExitMethod.java
public void showMessage() {
    if (errFlag) {
        return; // 実はvoidメソッドでもこれで抜けられる
    } else {
        System.out.println("処理成功")
    }
}

public int doCalc(int a, int b) {
    int result = a * b;
    if (result > 10) {
        return 0; // 値を返さずに抜けることは許されない
    } else {
        return result;
    }
}
```

```vb:ExitProcedure.vb
Public Sub ShowMessage() 
    If ErrFlag Then
        Exit Sub ' VBではExit Sub
    Else
        Debug.WriteLine("処理成功")
End Sub

Public Function DoCalc(a As Integer, b As Integer) As Integer
    Dim result As Integer = a * b
    If (result > 10) Then
        Exit Function ' 戻り値がInteger型なので0を返す
    ElseIf (result > 50) Then
        DoCalc = result + 1
        Exit Function ' 変数DoCalcに設定した値を返す
    Else
        Return result
    End If
End Function
```

Javaだと`return`せずにvoid以外のメソッドを抜けることは不可能だが、VBのFunctionプロシージャーではできてしまう。
ただし、戻り値の型によってはぬるぽ例外を発生させるなど、予期しない動作を招く原因になりかねないので、必ず`Return`すべきと思われる。

## 可変長引数

- **Java:** 引数を `(データ型... 変数名)`とする
  - 当該メソッド内では、配列変数のように扱うことができる
  - 他の引数も指定する場合、可変長引数は引数リストの最後に置かなければならない

```java:VariadicMethod.java
public static int getSum(int... numbers) {
    int sum = 0;
    for (int i = 0; i < numbers.length; i++) {
        sum += numbers[i];
    }
    return sum;
}
```

- **VB**: `(ParamArray 変数名 As データ型[])` とする
  - 性質はJavaと同じ。

```vb:VariadicFunction.vb
Public Shared Function GetSum(ParamArray Numbers As Integer[]) As Integer
    Dim Sum As Integer = 0
    For i As Integer = 0 To UBound(Numbers)
        Sum += Numbers(i)
    Next i
    Return sum;
End Function 
```

### 可変長引数の参考文献
  - [可変長引数を持つメソッドを作成するには？［C#／VB］：.NET TIPS - ＠IT](https://www.atmarkit.co.jp/ait/articles/1711/01/news030.html)

## オブション引数
呼び出し時に省略可能な引数。

- **Java**: （たぶん）言語仕様として持っていない。
  - Java 8 から導入された`Optional`型は、全く違う概念なので混同しないこと。
- **VB**: `(Optional 変数名 As データ型 = 既定値)` とする
  - 呼び出し時に省略された場合、既定値が渡されたものとみなされる。
  - なので既定値は必ず指定しておく必要がある。
  - Optionalを指定した引数移行のすべての引数は、Optionalでなければならない（省略できない引数を全て書いた後、Optional引数を書く）
    - Optional引数を複数設けること自体はOK。

```vb:OptionalArguments.vb
Public Shared Function Calc(Num1 As Integer, Num2 As Integer, Optional CalcMethod As Integer = 0)
    If CalcMethod = 0 Then
        Return Num1 + Num2
    ElseIf CalcMethod = 1 Then
        Return Num1 - Num2
    ElseIf CalcMethod = 2 Then
        Return Num1 * Num2
    ElseIf CalcMethod = 3 Then
        Return Num1 / Num2
    Else
        Return 0
    End If
End Function
```

この例では、`Calc(5, 10)`のように呼び出した場合、`CalcMethod = 0`のパターン（つまり足し算）が実行される。

## 返り値として複数の値を受け取る

- **Java**: クラスにまとめて、そのオブジェクトを返すしかない。

```java:ReturnMultiValue.java
public static Result getResult(int a, int b) {
    Result result = new Result();
    result.setSum(a + b);
    result.setDiff(a - b);
    result.setProduct(a * b);
    result.setQuotient((double) a / b);
    Return result;
}
```

```java:Result.java
public Class Result {
    int Sum;
    int Diff;
    int Product;
    double Quotient;

    // getter / setter 
}
```

- **VB**: **タプル**を利用して複数の値を返すことができる
  - タプル：その場で複数の変数を1つにまとめたもの
  - 臨時のクラスを作る、というイメージだと分かりやすいだろうか

```vb:Tuple.vb
Public Sub Main()
    ' タプルを名前付きで宣言
    Dim Result As (Sum As Integer, Diff As Integer, Product As Integer, Quotient As Double)

    Result = GetResult(5, 10)

    ' タプルに入った値を利用
    Debug.WriteLine(Result.Sum)
    Debug.WriteLine(Result.Diff)
    Debug.WriteLine(Result.Product)
    Debug.WriteLine(Result.Quotient)
End Sub

' タプルを返すFunctionプロシージャー
Public Shared Function GetResult(a As Integer, b As Integer) As (Integer, Integer, Integer, Double)
    Return (a + b, a - b, a * b, a / c)
End Function
```

## エントリポイント
プログラムが起動されたときに、最初に実行されるメソッド。

Javaはmainと名の付くメソッドが必ずエントリポイントになるが、VBではそうとは限らない。Windows Formsプロジェクトを作成すると、最初に作成したフォームがエントリポイントになる。これを変更する方法については、[JavaのmainメソッドをVB.NETで作成してみる！ | ライズウィルスタッフブログ](https://www.risewill.co.jp/blog/archives/8286)が詳しい。

# クラス

## 構成

- **Javaクラス** `public class Main{ }`
  - フィールド
  - メソッド
    - `getter`/`setter`メソッド

※JavaBeansの形式に従った例。

```java:JavaClass.java
public class JavaClass {
    // フィールド（オブジェクトの状態/性質を示すもの）
    private int field;

    // メソッド（オブジェクトの動作・振る舞いを示すもの）
    public void method(){
        // ...
    }

    // メソッド > getter（カプセル化されているprivateフィールドの読み取り機能を提供）
    public int getField() {
        return field;
    }

    // メソッド > setter（カプセル化されているprivateフィールドへの書き込み機能を提供）
    public void setField(int value) {
        this.field = value;
    }
}
```

- **VBクラス** `Public Class Main ... End Class`
  - フィールド（メンバ変数）
    - プロパティとの区別のために、`_`を接頭辞として付ける場合がある
  - プロパティ
    - `Get`プロシージャー
    - `Set`プロシージャー
  - プロシージャ（メソッド）
  - イベント

```vb:VBClass.vb
Public Class VBClass
    ' フィールド（メンバー変数）
    Dim _field As Integer

    ' プロパティ
    Property field() As Integer
        Get
            Return _field
        End Get
        Set(ByVal value As Integer)
            _field = value
        End Set
    End Property

    ' プロシージャー
    Public Sub Procedure()
        ' ...
    End Sub
End Class
```

## プロパティについてもっと詳しく
### 基本
プロパティは、Javaでいうところのgetter/setterメソッドをまとめたもの（Getプロシージャ・Setプロシージャのうち片方だけを実装することもできる）。
Javaと異なるのは、プロパティは**当該クラスの外からはフィールドのように扱われる**という点である。

たとえば、上記サンプルコード `JavaClass.java` の プライベートフィールド `field` に他のクラスからアクセスするときには、次のようなコードを書く必要がある。

```java:AccessToField.java
public class Main {
    public static void main(String[] args) {
        JavaClass jc = new JavaClass();

        // 以下2行はコンパイルエラーになる
        int num = jc.field;
        jc.field = 100;

        // 代わりに、こう書く
        int num = jc.getField();
        jc.setField(100);
    }
}
```

このように、`オブジェクト変数名.フィールド名` ではアクセスが拒否されるので、代わりにgetterメソッドの返り値としてフィールドの内容を受け取ったり、setterメソッドに値を引数として渡すことでフィールドの内容を書き換えるというやり方になる。

これと同じような動きをVBで書くと、こうなる。

```vb:AccessToField.vb
Public Class Main
    Public Shared Sub Main
        Dim vbc As New VBClass()

        Dim num As Integer = vbc.field 'Get呼び出し
        vbc.field = 100 'Set呼び出し
    End Sub
End Class
```

プロパティ名をフィールドのように書くことで、そのプロパティに定義されたGet/Setプロシージャーが暗黙的に呼び出される。

### 自動実装プロパティ
なお、単に値を返す/書き込むだけのプロパティであれば、**自動実装プロパティ**を使うことでコードを簡略化できる。

```vb:AutoImplProperty.vb
Public Class AutoImplProperty
    Public Property Name As String
    Public Property Owner As String = "DefaultName"
    Public Property Items As New List(Of String) From {"M", "T", "W"}
    Public Property ID As New Guid()
End Class
```
（[自動実装プロパティ - Visual Basic | Microsoft Docs](https://docs.microsoft.com/ja-jp/dotnet/visual-basic/programming-guide/language-features/procedures/auto-implemented-properties) より）

このとき、プロパティ名に`_`を付けた隠しPrivateフィールド（**バッキング フィールド**）が自動的に作成される。上記の例では、`_Name`, `_Owner`, `_Items`, `_ID` というバッキングフィールドが作成される（従って、自分でこれらと同じ名前のフィールドを宣言するとコンパイルエラーになる）

### プロパティ：フィールド = 1：n もOK
また、**プロパティはフィールドと1対1で対応している必要はない**。言い換えると、複数のフィールドから値を拾ってきて、連結して1つのフィールドのように扱うこともできる。また、1つのまとまった値を受け取り、実際には2つ以上のフィールドに分割して格納する、ということもできる。（もちろんそれに見合ったGet/Setプロシージャを定義しておく必要はある）。
Microsoft Docsにわかりやすい例があったので、引用する（クラス内のメンバであることが分かりやすいよう、`Public Class` ~ `End Class`を付加している）。


> 次のプロパティは、フル ネームを 2 つの構成要素名 (名と姓) として格納します。 呼び出し元のコードが fullName を読み取ると、Get プロシージャが 2 つの構成要素名を結合し、フル ネームを返します。 呼び出し元のコードが新しいフル ネームを割り当てると、Set プロシージャがそれを 2 つの構成要素名に分割することを試みます。 スペースが見つからない場合は、すべてが名として格納されます。.
> [Property プロシージャ - Visual Basic | Microsoft Docs](https://docs.microsoft.com/ja-jp/dotnet/visual-basic/programming-guide/language-features/procedures/property-procedures)

```vb:CombinedProperty.vb
Public Class CombinedProperty
    Private firstName As String
    Private lastName As String

    Property fullName() As String
        Get
        If lastName = "" Then
            Return firstName
        Else
            Return firstName & " " & lastName
        End If

        End Get
        Set(ByVal Value As String)
            Dim space As Integer = Value.IndexOf(" ")
            If space < 0 Then
                firstName = Value
                lastName = ""
            Else
                firstName = Value.Substring(0, space)
                lastName = Value.Substring(space + 1)
            End If
        End Set
    End Property
End Class
```

呼び出し側：

```vb:CallProperty.vb
fullName = "MyFirstName MyLastName"
MsgBox(fullName)
```

その他、プロパティとメンバ変数の違いについては以下のページも参照。

- [プロパティと変数の違い - Visual Basic | Microsoft Docs](https://docs.microsoft.com/ja-jp/dotnet/visual-basic/programming-guide/language-features/procedures/differences-between-properties-and-variables)