Visual Basic 初級講座 [改訂版] |
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
Visual Basic 中学校 > 初級講座[改訂版] >
2021/6/13
この記事が対象とする製品・バージョン
![]() |
Visual Basic 2019 | ◎ | 対象です。 |
![]() |
Visual Basic 2017 | ◎ | 対象です。 |
![]() |
Visual Basic 2015 | ◎ | 対象です。 |
![]() |
Visual Basic 2013 | ◎ | 対象です。 |
![]() |
Visual Basic 2012 | ◎ | 対象です。 |
![]() |
Visual Basic 2010 | ◎ | 対象です。 |
![]() |
Visual Basic 2008 | ○ | 対象ですが、動作しないサンプルもあります。 |
![]() |
Visual Basic 2005 | ○ | 対象ですが、動作しないサンプルもあります。 |
![]() |
Visual Basic.NET 2003 | △ | 対象外ですがほとんどの説明があてはまるので参考になります。 |
![]() |
Visual Basic.NET (2002) | △ | 対象外ですがほとんどの説明があてはまるので参考になります。 |
![]() |
Visual Basic 6.0 | × | 対象外です。 |
この記事は 後から追加したため、第28-2回という、中途半端な名称になってしまいました。
目次
インターフェースとはメソッド等の定義の集合体です。インターフェースではメソッド等の引数や型が定義されているだけであって、中身の処理は記述されません。インターフェースは単独で使用するものではなく、中身の処理をクラスで実装(記述)することで動作するようになります。
と書いても、全然イメージできないと思います。インターフェースとはどういうモノで、どういう風に役に立つのか順を追って説明します。
まず、IDisposable (読み方:IDisposable=アイディスポーザブル)というインターフェースを例として取り上げてみます。
IDisposableインターフェースには Dispose というメソッドが1つだけ定義されています。
インターフェースでは、メソッドの名前や引数や型などは定義しますが、処理の中身は記述しませんので、IDisposalbeインターフェースのプログラムは次のようになっています。
Public Interface IDisposable
Sub Dispose()
End Interface
実際にはIDisposableインターフェースはC#でプログラムされてるので、この例はVBに置き換えると上記のようなプログラムだと言う意味です。
フレームワークのクラスには Dispose メソッドを持つものがたくさんありますが、それらはすべて、この IDisposalbeインターフェースを実装しています。Disposeメソッドは終了処理を実行してくれるメソッドです。
たとえば、次のクラスは、どれもDisposeメソッドを持っています。
これらのクラスはそれぞれの機能にまったく関連がありませんが、終了処理が必要であるという点は共通しています。
この共通性を定義するのがインターフェースの役割です。
下記の図では、各クラスの代表的なメソッドとDisposeメソッドを抜粋してみました。Disposeメソッドはこのように横串で共通しているイメージです。
IDisposableインターフェースには、Disposeメソッドの中身は記述されていないので、Disposeメソッドが呼び出されたときに具体的にどのような終了処理を行うかは各クラスで定義します。この仕組みによって定義は共通だけで、処理はそれぞれのクラスで異なるという実装が可能になります。
|
インターフェースは「型」であるという点で、インターフェースを使わないでただ単に名前や定義が同じメソッドをいろいろなクラスで実装するのとは大きな違いがあります。
型であるということは Dim x As xxxxx のように As xxxxxx の部分に指定できるということです。
だから、次のプログラムは有効です。
Dim test As IDisposable
しかし、インターフェースは定義の集合体であって、処理はなにも記述されていませんので、New をしたり、何かの処理を、この例の変数 test から呼び出すことはできません。
HttpClient クラスは IDisposable を実装するので、IDisposable型の変数に代入することができます。
次のプログラムは有効です。
Dim client As New Net.Http.HttpClient
Dim test As IDisposable = client
.NET Framework の場合、このプログラムをエラーなしで実行するには System.Net.Http への参照設定が必要です。
このプログラムでは、test. と入力すると、すべてのクラスで共通で使用できるEquals, GetHashCode, GetType, ToString の他は、 Dispose メソッドしか表示されません。
変数 test は IDisposable 型であり、IDisposalbe には Dispose メソッドしか定義されていないからです。
変数 test の実体は HttpClient 型のインスタンス なので、本当はこれ以外にもたくさんのメソッドやプロパティが使用できます。でも、変数 test 経由で直接呼び出せるのはこれに限定されてしまいます。
試しに client. と入力すると、本当に使用可能な全メンバーが表示されます。当然 Dispose もこの中にあります。
インターフェースは型なので変数だけでなく、引数の型としても使用できます。
たとえば、次のメソッドはインターフェースである IDisposable型の引数を持ちます。
Public Sub EndObject(o As IDisposable)
If o IsNot Nothing Then
o.Dispose()
End If
End Sub
このメソッドの引数には IDisposable インターフェースを実装するものならなんでも指定できます。
それが何であれ、このメソッドは Dispose メソッドしか呼び出さないので他の機能は関係ないわけです。
Disposeメソッドだとありがたみがないので、今度はもうちょっとわかりにくいけれども、もうちょっと役に立つ例を紹介しましょう。
List(Of T) や Dictionary(Of T) などのコレクションは、要素を列挙することが可能であり、この要素を列挙する機能は IEnumerable(Of T)インターフェースとして定義されています。
IEnumerable(Of T)インターフェースには、 GetEnumerator というメソッドが1つだけ定義されています。このメソッドは要素を列挙するためのオブジェクトを取得します。このオブジェクトは「列挙子」(Enumerator)と呼ばれます。
列挙子には次の要素を取得する MoveNextメソッドと、現在の要素を取得する Currentプロパティがあります。次の要素がない場合MoveNextメソッドは False を返します。
ちょっと練習してみましょう。列挙子を使うと次のように List からすべて値を取り出すことができます。
Dim namesList As New List(Of String)({"Apple", "Banana", "Cat", "Dog"})
Dim itor = namesList.GetEnumerator
While itor.MoveNext
Debug.WriteLine(itor.Current)
End While
これを応用して、最もたくさん出現した項目を取得するプログラムを書いてみます。
たとえば、{"Apple", "Cat", "Banana", "Cat", "Apple", "Dog", "Cat"} というコレクションの場合、 Cat が最もたくさん出現したいます。
プログラムをメソッドとして記述すると次のようになります。
Private Function Mode(Of T)(source As IEnumerable(Of T)) As T
Dim counts As New Dictionary(Of T, Integer) '項目と出現回数の一覧
Dim maxItem As T '現在までに最多出現した項目
Dim maxCount As Integer '現在までに最多出現した項目の出現数
Dim itor = source.GetEnumerator
While itor.MoveNext
'現在の項目が既に一覧に含まれている確認する
If counts.ContainsKey(itor.Current) Then
'一覧に含まれている場合は、出現数に 1 をたす
counts(itor.Current) += 1
Else
'一覧に含まれていない場合は、一覧に追加し、出現数を 1 にする
counts(itor.Current) = 1
End If
'現在までの最多出現数をこの項目が上回っているかチェック
If maxCount < counts(itor.Current) Then
'上回っているなら、今の項目を最多出現項目として記録
maxCount = counts(itor.Current)
maxItem = itor.Current
End If
End While
'最多出現項目を返す
Return maxItem
End Function
このメソッドの定義が Mode(Of T) のようにジェネリックになっているのは、受け取る引数にList(Of String)や List(Of Integer) や Stack(Of Date)のようなジェネリックを想定しているからです。型パラメーターが何か事前にわからないので、メソッド側でも型パラメーターを定義することになります。実際に呼び出す場合は、VBが型推論してくれるので、型パラメーターに型を指定する必要はありません。
呼び出しは次のようになります。
Dim namesList As New List(Of String)({"Apple", "Cat", "Banana", "Cat", "Apple", "Dog", "Cat"})
Dim result As String = Mode(namesList)
Debug.WriteLine(result) ' Cat を出力します。
Modeメソッドの引数は IEnumerable(Of T)型です。インターフェースなので、このインターフェースを実装するものであればなんでも指定できます。
StringクラスもこのIEnumerable(Of T)を実装しているため、次のプログラムも有効です。
Dim value As String = "あめんぼ赤いなあえいうえおあお"
Dim result As String = Mode(value)
Debug.WriteLine(result) ' あ を出力します。
Stringクラスの列挙子は文字列に含まれる文字を1つずつ列挙します。この文字列では、「あ」が最多なので結果は「あ」になります。
このように「列挙する機能がある」という観点で、クラスを共通化して、同じ処理を実行できるところがインターフェースのメリットです。
名前が同じというだけのメソッドであれば、このような共通化はできません。
VB の ForEach ~ Next メソッドも IEnumerable インターフェースのGetEnumeratorメソッドを利用することで、どのようなオブジェクトであれ、列挙可能なものを列挙します。Using ~ End Using は IDisposable インターフェース の Dispose メソッドを利用することで、どのようなオブジェクトであれ、確実に終了処理を呼ぶという機能を実現しています。
今度はインターフェースを作って、処理を実装してみましょう。
これから1つのインターフェスト、それを実装する3つのクラスを作ります。 実際にやってみる人は コンソールアプリケーション で試していただくようにお願いします。説明の中でコンソールアプリケーションの機能を使うからです。
今回は何かの文字列変換機能である Translate メソッド を持つインターフェース ITranslator を定義してみます。
たとえば、ひらがなを受け取ってカタカナに変換したり、日本語を受け取って英語に変換したりいろいろな変換機能が考えられます。
インターフェースを定義するには Interface ~ End Interface (読み方:Interface = インターフェース)を使用します。
インターフェースの名前は慣例的に英語の大文字の I (アイ) から始めることになっています。機能上はそうでない名前を付けることもできますが、私のプログラム人生の中で I から始まらないインターフェースは見たことがありません。 I から始めておくことが事実上必須というレベルです。
インターフェースを定義するだけならとても簡単です。次のようになります。
Public Interface ITranslator
Function Translate(value As String) As String
End Interface
String型の引数を受け取って、String型の戻り値を返す Translateメソッドが定義されているということがお判りいただけると思います。処理内容がないため End Function は書きません。
それでは、このインターフェースを使って、ひらがなをカタカナに変換するクラスを作ってみます。
専用のクラス KatakanaConverter を定義してみましょう。この段階ではまだインターフェースとは無関係です。
Public Class KatakanaTranslator
End Class
インターフェースを実装するには、クラスの中の先頭で Implements キーワード (読み方:Implements = インプリメンツ)を使って、インターフェースを指定します。(初級講座では取り上げませんが、継承を指定する Inherits キーワードがある場合は、それよりは後に記述する必要があります。)
Visual Studio は Implements ITRanslator と入力して Enter を押すと、最低限必要なプログラムを自動的に生成してくれます。
Public Class KatakanaTranslator
Implements ITranslator '←ここまで入力したら Enter キーを押します。
End Class
上の状態で最後に Enter を押すとVisual Studio の支援機能が働いて次のようなプログラムになります。
Visual Studioのバージョンによっては少し異なる場合があります。
Public Class KatakanaTranslator
Implements ITranslator
Public Function Translate(value As String) As String Implements ITranslator.Translate
Throw New NotImplementedException()
End Function
End Class
ITranslatorインターフェースを実装するということは、Translateメソッドを定義する必要があるので、Visual Studio が自動的に定義してあげますよということです。
自動生成される Translateメソッドの後ろには Implements ITranslator.Translate と記述されており、 ITranlatorインターフェースのTranslateメソッドの実装であることを示しています。インターフェースを実装する場合は、必ずこのように明示的にどのインターフェースのどのメソッドの実装なのかを示す必要があります。ただ単に名前や引数や型が一致しているだけのメソッドがあるだけでは、インターフェースの実装とはみなされません。
Tranlateメソッドの中身は Throw New NotImpelmentedException() となっています。これは「まだ実装されていない」という意味の例外を必ず発生させるプログラムです。この部分を置き換えて、このメソッドを完成させればよいわけです。
VBは日本語環境のWindowsで実行している場合に限って、ひらがなをカタカナに変換できる StrConv (読み方:エスティーアールコンブ?)というメソッドを使用できます。このメソッドは正しく動作する条件がいまいちわかりにくいので、私は重要なプログラムでは使用しないようにしていますが、今回のようにお手軽に試すのには十分です。
次のようになります。
Public Class KatakanaTranslator
Implements ITranslator
Public Function Translate(value As String) As String Implements ITranslator.Translate
'↓.NET Framework で実行する場合、この RegisterProvider の行はコメントにしてください。
System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance)
Return StrConv(value,VbStrConv.Katakana)
End Function
End Class
インターフェースを実装しているとは言え、普通のクラスとしても使えるので次のように呼び出すことができます。
Dim translator As New KatakanaTranslator
Dim result As String = translator.Translate("鏡の国のアリス")
Console.WriteLine(result) '鏡ノ国ノアリス
'Console.ReadLine() '←Enterを押すまでコンソールを閉じないようにします。
インターフェースとは複数のクラスで共通して実装するから意味があるのであって、このクラスしか実装しないのであればメリットはありません。別の変換機能を持つクラスを作ってみましょう。
今度は日本語を英語に翻訳する EnglishTranslator クラスを作ってみます。本格的な翻訳機能を作る場合は、外部のサービスを呼び出すのが一般的です。たとえば、C#のものですがAzureのCognitive Serviceを使用する記事がここにあります。VBでも同じことができます。チュートリアル:WPF (C#) を使って翻訳アプリを作成する
今回は、単純に登録済みの単語を置き換えるだけの実装です。
次のようにしてみます。
Public Class EnglishTranslator
Implements ITranslator
Dim dic As Dictionary(Of String, String)
Public Sub New()
dic = New Dictionary(Of String, String) From
{{"雄略天皇", "Yuryaku Tennou"}, {"法隆寺", "Horyuji"}, {"日本の", "Japanese"},
{"第21代", "21th"}, {"天皇", "emperor"}, {"お寺", "temple"}, {"木造", "wooden"},
{"建築物", "building"}, {"考古学上の", "On archaeology,"}, {"実在する", "existing"},
{"想定のされうる", "possibility"}, {"最古の", "the oldest"}, {"である", ""},
{"、", ""}, {"。", "."}, {"は", "is"}}
End Sub
Public Function Translate(value As String) As String Implements ITranslator.Translate
For Each item In dic
Dim japanese As String = item.Key
Dim english As String = item.Value
value = Replace(value, japanese, english & " ")
Next
Return value
End Function
End Class
日本語と対する英語を持つ Dictionary をコンストラクターで準備しておいて、Translateメソッドの内部では、辞書の項目を1個ずつReplaceメソッドで置き換えていくだけの処理です。
呼び出し例は次の通りです。
Dim translator As New EnglishTranslator
Dim result As String = translator.Translate("法隆寺は日本のお寺。実在する最古の木造建築物である。")
Console.WriteLine(result) 'Horyuji is Japanese temple . existing the oldest wooden building .
'Console.ReadLine() '←Enterを押すまでコンソールを閉じないようにします。
あらかじめ「法隆寺」とか「お寺」を Dictionary に組み込んでいる出来レースなので、こんなレベルでもなんとかなくそれっぽい英語に翻訳してくれます。この英語は正しい英語ではありませんが、意味は通じるのではないかなと思います。
もう1個作ってみましょう。文字列を Base64 (ベースろくじゅうよん) に変換する Base64Translator を作ってみます。
Base64とは主にメールやWebの世界で使われるエンコード方式で、安全に通信できる文字だけを使って情報を表現する方式です。人間にはわけのわからない文字に変換されます。Base64は一見、暗号化しているようにも見えますが、決まったルールで変換しているだけなのでBase64から普通の人間が読める情報に変換することは簡単にできます。
VBでは Convertクラスの ToBase64Stringメソッドを使えばBase64へのエンコードができるのですが、このメソッドは引数をバイト型の配列で与える必要があるので、事前に文字列をバイト型の配列に変換する必要があります。
文字列をバイト型の配列に変換するとどうなるかは、文字の符号化方式(≒文字コード)によって変わります。今回は符号化方式として標準的に使われている UTF-8 を使ってバイト型の配列に変換してから、Base64に変換するようにプログラムしてみます。
次のようになります。
Public Class Base64Translator
Implements ITranslator
Public Function Translate(value As String) As String Implements ITranslator.Translate
Dim binary As Byte() = System.Text.Encoding.UTF8.GetBytes(value)
Return Convert.ToBase64String(binary)
End Function
End Class
実行するには次のようにします。
Dim translator As New Base64Translator
Dim result As String = translator.Translate("法隆寺")
Console.WriteLine(result) '5rOV6ZqG5a+6
'Console.ReadLine() '←Enterを押すまでコンソールを閉じないようにします。
実行すると、「5rOV6ZqG5a+6」と表示されます。これがUTF-8の「法隆寺」をBase64で表現したものということです。
ITransratorインターフェースを実装するクラスが3つできたので、インターフェースが型であるという特性を活かしてプログラムしてみましょう。
コンソールアプリケーションを前提として、どのような変換処理を行うかをユーザーに選択してもらうようにします。
Sub Main(args As String())
Dim translator = CreateTranslator()
Console.WriteLine(translator.Translate("雄略天皇は日本の第21代天皇。考古学上の実在する想定のされうる最古の天皇である。"))
Console.WriteLine(translator.Translate("法隆寺は日本のお寺。実在する最古の木造建築物である。"))
'Console.ReadLine() '←Enterを押すまでコンソールを閉じないようにします。
End Sub
Private Function CreateTranslator() As ITranslator
Do
Console.WriteLine("KATAKANA または BASE64 または ENGLISH を入力してください。")
Dim userInput As String = Console.ReadLine.ToUpper
If userInput = "KATAKANA" Then
Return New KatakanaTranslator
ElseIf userInput = "BASE64" Then
Return New Base64Translator
ElseIf userInput = "ENGLISH" Then
Return New EnglishTranslator
End If
Loop
End Function
プログラムが開始して Main メソッドが呼び出されたら、すぐに CreateTranlatorメソッドを呼び出します。CreateTranslatorメソッド内ではユーザーに KATAKANA または BASE64 または ENGLISH を入力させて、該当するXXXXTranslator クラスのインスタンスを戻り値として返します。それぞれのクラスは ITranslatorインターフェースを実装しているので、戻り値の型は ITranslator とします。
Main側では返ってきたインスタンスを変数 translator に格納して、Translateメソッドを呼び出します。
このプログラムのポイントは、Mainメソッド内では、変数translatorの実体が KatakanaTranslator なのか EnglishTranslator なのか Base64Translator なのかわからない点です。わからなくても Translate メソッドを呼び出す ことはできるので、問題ないというわけです。
このようなプログラムを書けるかどうかが、初級プログラマーから中級プログラマーへのステップアップの鍵です。
最後に、このサンプルの全体を掲載しておきます。
Imports System
Module Program
Sub Main(args As String())
Dim translator = CreateTranslator()
Console.WriteLine(translator.Translate("雄略天皇は日本の第21代天皇。考古学上の実在する想定のされうる最古の天皇である。"))
Console.WriteLine(translator.Translate("法隆寺は日本のお寺。実在する最古の木造建築物である。"))
'Console.ReadLine() '←Enterを押すまでコンソールを閉じないようにします。
End Sub
Private Function CreateTranslator() As ITranslator
Do
Console.WriteLine("KATAKANA または BASE64 または ENGLISH を入力してください。")
Dim userInput As String = Console.ReadLine.ToUpper
If userInput = "KATAKANA" Then
Return New KatakanaTranslator
ElseIf userInput = "BASE64" Then
Return New Base64Translator
ElseIf userInput = "ENGLISH" Then
Return New EnglishTranslator
End If
Loop
End Function
End Module
Public Interface ITranslator
Function Translate(value As String) As String
End Interface
Public Class KatakanaTranslator
Implements ITranslator
Public Function Translate(value As String) As String Implements ITranslator.Translate
'↓.NET Framework で実行する場合、この RegisterProvider の行はコメントにしてください。
System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance)
Return StrConv(value, VbStrConv.Katakana)
End Function
End Class
Public Class EnglishTranslator
Implements ITranslator
Dim dic As Dictionary(Of String, String)
Public Sub New()
dic = New Dictionary(Of String, String) From
{{"雄略天皇", "Yuryaku Tennou"}, {"法隆寺", "Horyuji"}, {"日本の", "Japanese"},
{"第21代", "21th"}, {"天皇", "emperor"}, {"お寺", "temple"}, {"木造", "wooden"},
{"建築物", "building"}, {"考古学上の", "On archaeology,"}, {"実在する", "existing"},
{"想定のされうる", "possibility"}, {"最古の", "the oldest"}, {"である", ""},
{"、", ""}, {"。", "."}, {"は", "is"}}
End Sub
Public Function Translate(value As String) As String Implements ITranslator.Translate
For Each item In dic
Dim japanese As String = item.Key
Dim english As String = item.Value
value = Replace(value, japanese, english & " ")
Next
Return value
End Function
End Class
Public Class Base64Translator
Implements ITranslator
Public Function Translate(value As String) As String Implements ITranslator.Translate
Dim binary As Byte() = System.Text.Encoding.UTF8.GetBytes(value)
Return Convert.ToBase64String(binary)
End Function
End Class
パソコンやスマホなどに USB がついていることが良くあります。いろいろな機器を簡単に接続して、便利な機能を使える優れものです。 しかし、USB自体はただの穴で、何が接続されるかは事前にわかりません。 これはまさにインターフェースです。 VBのインターフェース自体はただのメソッドの定義で、どんな処理が実装されるかは事前にわかりません。 USB や HDMI などパソコンについている口のことを「インターフェース」と呼ぶのは偶然ではなく、同じ概念のものだからです。 だから、インターフェースがいったい何なのかわからなくなったら、USBのプログラム版だと思うと理解しやすいかもしれません。口だけ先に作ってあるんです。 |
インターフェースには複数のメソッドを定義することもできますし、プロパティやイベントを定義することもできます。
インターフェースはインターフェースを継承できるので、たくさんのメソッドが定義されている巨大なインターフェースを作るのではなく、役割が細分化された細かいインターフェースをたくさん作る方が柔軟性があり優れています。
インターフェースがインターフェースを継承するには Inherits キーワードを使用します。
下記の例では InterfaceC が InterfaceA と InterfaceB を継承しています。
ClassTestクラスは InterfaceC だけを Implements していますが、A と B のメソッドも実装することになります。
Public Interface InterfaceA
Sub MethodA()
End Interface
Public Interface InterfaceB
Sub MethodB()
End Interface
Public Interface InterfaceC
Inherits InterfaceA, InterfaceB
Sub MethodC()
End Interface
Public Class ClassTest
Implements InterfaceC
Public Sub MethodA() Implements InterfaceA.MethodA
Throw New NotImplementedException()
End Sub
Public Sub MethodB() Implements InterfaceB.MethodB
Throw New NotImplementedException()
End Sub
Public Sub MethodC() Implements InterfaceC.MethodC
Throw New NotImplementedException()
End Sub
End Class
クラス自身が複数のインターフェースを実装することもできます。
複数のインターフェースを実装するには Implements の後ろにカンマで区切ってインターフェースを指定します。
Public Class ClassTest
Implements InterfaceA, InterfaceB
Public Sub MethodA() Implements InterfaceA.MethodA
Throw New NotImplementedException()
End Sub
Public Sub MethodB() Implements InterfaceB.MethodB
Throw New NotImplementedException()
End Sub
End Class
複数のインターフェースを実装すると、メソッド名など名前が重複してしまう場合があるので、クラス側では実装時にメソッド等の名前を変更することもできます。
たとえば、Cloneメソッド(読み方:Clone=クローン)を定義している IClonableインターフェース(読み方:IClonable=アイクローナブル)を実装するけれども、メソッド名は Copy にするということができます。
Public Class CloneTest
Implements ICloneable
Public Function Copy() As Object Implements ICloneable.Clone
Debug.WriteLine("Copyが呼び出されました。")
Return New CloneTest
End Function
End Class
次のように Clone メソッドを呼び出すと、実際に呼び出されるのは Copyメソッドです。
Dim test As New CloneTest
Dim ifTest As ICloneable = test
ifTest.Clone() 'ここで Copy メソッドが呼び出されます。
この例では複数のインターフェースを実装しているわけではないので、名前を変えることはお勧めしません。混乱のもとになるだけです。
ただ、サンプルがシンプルになるので説明用の例として取り上げました。
フレームワークのクラスにも複数のインターフェースを実装しているクラスが多数あります。Microsoft Docsのリファレンスを確認すると、クラスがどんなインターフェースを実装しているのかわかります。
たとえば、下記の String クラスのリファレンスを見ると、String クラスがIEnumerable(Of Char)、IEnumerable、 IComparable、 IComparable(Of String)、IConvertible、 IEquatable(Of String)、 ICloneableの7個のインターフェースを実装していることがわかります。
String クラス (System) | Microsoft Docs
クラスがあるインターフェースを実装しているかは TypeOf ... Is ... で判断できます。
たとえば、次の例では List(Of String)が IListインターフェースと IEnumerable(Of String)を実装していることを判断できます。
Dim list As New List(Of String)
If TypeOf list Is IList Then
Debug.WriteLine("IListを実装しています。")
End If
If TypeOf list Is IEnumerable(Of String) Then
Debug.WriteLine("IEnumrable(Of String)を実装しています。")
End If
これを利用して、クラスに何か目印をつける目的で何のメンバーも定義されていないインターフェースをImplementsすることがあります。こうしておくことで、そのインターフェースを持っているクラスだけ特別扱いするプログラムが記述できるようになります。このような目印として使うインターフェースをマーカーインターフェースと呼びます。
条件を付けて分岐する目印としては属性の方が柔軟で使いやすく、意味的にも目印の役割なので、マーカーインターフェースよりも属性を使う方が一般的です。
初級講座 第32回 モジュール で説明する拡張メソッド向けの目印としてインターフェースを付ける場合もあります。これは属性にはできないのでインターフェースを使うことに意義があります。