4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Visual BasicAdvent Calendar 2022

Day 7

【VB.NET】Record型を使ってみる

Last updated at Posted at 2022-12-07

はじめに

これは、Visual Basic Advent Calendar 2022の7日目の記事となります。

VB.NETは、Microsoftの方針により新機能の対応はしなくなりました。そのため、C#9.0から追加されたレコード型は使用できません。
しかし、Mohammad Hamdy Ghanem(VBAndCs)さんが、2020年11月頃に代替案を提案してくれました。

レコード型

C# 9.0 の新機能

その中の機能の一つとして、新たな型「レコード(record)」が追加されました。
「レコード」の概要は以下のように説明されています。

C# 9.0 には "レコード型" が導入されています。これは、等価性の値のセマンティクスを提供するための合成されたメソッドを提供する参照型です。 既定では、レコードは変更できません。

VB.NET対応経緯

2020年11月頃にレコード型の代替案を提案されました。

この時はWinForm上で、レコード型を入力したものを代替クラスに変換するジェネレーターでした。

ソースジェネレータ対応版

その後、.NET SDK 5.0 から対応したに"ソースジェネレータ (Source Generators)" という機能を使用したものになりました。
"ソースジェネレータ" とは何かというと、いうなれば、.NET系開発言語のコンパイラに対するある種の"アドイン"を、アプリケーションプログラマが実装・配付できるようになる機能です。
ビルド時に追加の対象の開発言語のソースコードを動的に作成し、対象プロジェクトに付け加えるようになります。

実装

準備

NuGetで「VB-Record-Source-Generator」をインストールします。
NuGetで「RecGen」をインストールします。名前が変更になった。
image.png

レコード型を追加

プロジェクトにテキストを追加します。拡張子は「rec」を指定します。 
今回は例として「PersonRecord.rec」とします。
recordキーワードを使用できます。

PersonRecord.rec
Public Record PersonRecord (
    FirstName As String = "",
    LastName As String = ""
)

記述後に「PersonRecord.rec」ファイルのプロパティでビルドアクションを「VB アナライザー追加ファイル」に変更します。
保存すれば、自動的にソースコードを動的に作成されます。
image.png

シンタックスハイライト

拡張子「rec」のままだとシンタックスハイライトが効かないので、Visual Studioのツールメニューのオプションから、テキストエディターのファイル拡張子を選択します。拡張子に「rec」を指定してエディターに「Micorosoft Visual Basic」を指定して追加(適用)ボタンをクリックします。
image.png
image.png

確認

PersonRecordが使えるようになっています。
また、ソースジェネレータを使用するので毎回ビルドするといいでしょう。

参考にした記事

PersonClass.vb
Public Class PersonClass
    Public ReadOnly Property FirstName
    Public ReadOnly Property LastName

    Public Sub New(ByVal first As String, ByVal last As String)
        FirstName = first
        LastName = last
    End Sub
End Class
Program.vb
Module Program
    Sub Main(args As String())

        Dim personClass1 As PersonClass = New PersonClass("Bill", "Wanger")
        Dim personClass2 As PersonClass = New PersonClass("Bill", "Wanger")

        Console.WriteLine(personClass1.Equals(personClass2))
        Console.WriteLine(personClass1.ToString())

        Dim personRecord1 As PersonRecord = New PersonRecord("Bill", "Wanger")
        Dim personRecord2 As PersonRecord = New PersonRecord("Bill", "Wanger")

        Console.WriteLine(personRecord1.Equals(personRecord2))
        Console.WriteLine(personRecord1.ToString())

        Console.ReadKey()

    End Sub
End Module

結果

実行結果
false        ' PersonClass同士のEqualsの結果
PersonClass  ' PersonClassのToString
true         ' PersonRecord同士のEqualsの結果
PersonRecord { FirstName = Bill, LastName = Wagner }  ' PersonRecordのToString

オブジェクトが同一 = インスタンスが同じかどうかを比較するだけ、ということですね。
personClass1とpersonClass2はそれぞれnewされていて別のインスタンスなので、結果はfalseということです。
一方、PersonRecord同士は別のインスタンスとなっているにも関わらずEqualsの結果はtrueとなっています。
(中略)
また、classではToStringも既定ではそのclassの名称を出力するだけですが、recordではToStringもOverrideされてプロパティ名、その中の値も出力してくれるようになっています。
【C# 9.0 新機能】レコード(record)型はクラスと比べて何がオトクなのか

応用

応用として下記サイトで、Dictionaryのキーとして使用できると思ったんですよね。
ただ同じキーなら本来エラーか上書きされると思うのに、そのまま追加されてしまうので現在確認中です。
また追記します。

【2022/12/14追記】
Issueを書いて修正してもらいました。どうせなので別記事にします。

最後に

VB.NETでもレコード型が使用できることを確認できました。
ソースジェネレーターという機能自体は耳にはしていたが、自分では使い道が思いつかなかったですが、今回こういった形で使えることが分かっただけでも良かったです。

4
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?