VB.NETでもLenメソッドを・・・

はじめに

VB.NET特有*1Microsoft.VisualBasic.Strings.Lenメソッドってありますよね。

Strings.Len メソッド (Microsoft.VisualBasic)

正直弊社はアレは好きになれないんですよね。 説明文が正直意味がよくわかんないし。

文字列内の文字数または変数を格納するために必要な公称バイト数を表す整数を返します。

ってあるんですけど、そもそも文字列内の文字数と変数を格納する公称バイト数を返すメソッドをオーバーロードする意味が分からないし、変数を格納するための公称バイト数って何に格納するのかが分かんないし、文字列を何かに格納するにしても文字符号化方式によってバイト数って変わるじゃんって思ってた訳ですよ。 まず16個もオーバーロードするって意味が分からない。

格納先

とりあえず、何に格納するかはっきりさせましょう。 Microsoft.VisualBasic.FileSystem.FilePutメソッドで値をファイルに書き込む時のバイト数らしいです。 こいつもやたらと多重にオーバーロードされてますが、もうゆるしてください。

興味

とりあえず弊社としてはLen()が返すInt32の値が何を意味するのかが非常に気になるのです。

とりあえずLen(Object)以外は下の表にまとめました。

関数 返す値
Len(Boolean) 2(定数)
Len(Byte) 1(定数)
Len(Char) 2(定数)
Len(DateTime) 8(定数)
Len(Decimal) 8(定数)
Len(Double) 8(定数)
Len(Int16) 2(定数)
Len(Int32) 4(定数)
Len(Int64) 8(定数)
Len(SByte) 1(定数)
Len(Single) 4(定数)
Len(String) 引数として与えられた値のLengthプロパティの値
Len(UInt16) 2(定数)
Len(UInt32) 4(定数)
Len(UInt64) 8(定数)

まさかの15個中14個中が定数。 たしかVBではオーバーロードは静的に決定されるはずですからインライン展開が捗りますね。

そしてLen(String)はなんとString.Lengthを呼び出すというVBにしてはひねりのない結果に。

他のは実際にファイルに書き出す時のバイト数(らしい)のにStringだけ文字数*2ってのはなんと言いますか、ビミョーに一貫性の無いオーバーロードですね。

こんな現実を見せつけられるとLen(Object)もあらゆるオブジェクトに使えるって訳じゃなさそうです。

Len(Object)

基本的には以下のパターンで長さを求めてるみたいです。

Nothingの場合

0

System.IConvertibleを実装している場合

System.IConvertibleを実装している場合はオブジェクトのGetTypeCode()を呼び出して、EmptyObjectDBNull以外の型だったらそれそれのオーバーロードしているバージョンのLen()が返す値と同じ値を返します。

StringIConvertibleを実装しているので、なんやかんやでString.Lengthの値が返ります。

Charの配列の場合

配列の長さを返します。

上記以外もしくはGetTypeCode()がEmpty、Object、DBNullの場合

よくわかんない。構造体のバイト数?

まとめ

なんかスパッと答えが分からなくてもやもやした結果となりました。 まぁ、ほとんどの場合はLen()は文字列の長さを求める為に用いられていると思いますので、素直にString.Lengthを使いましょう。

こんなにたくさんオーバーロードされたり引数としてObjectを取るバージョンも定義されているのはバリアント型が存在したレガシーVBとの互換性的な何かを求めての事でしょうけど、.NETにおいてここまでレガシーVBを引きずらなくてもいいんじゃないかな〜みたいな。

そういえばFileSystem.FilePutメソッドって文字列はどのエンコードで書き出すのでしょうか。 無難にUTF-8UTF-16かな? ロケールに合わせて変えていたら面白いですね。 気が向いたら調べてみましょう。

おわり

*1:C#でも使えるが使う意味・理由が無い。

*2:正確には文字数って訳じゃないけど今回は文字コードメインじゃないので