2020年4月1日水曜日

久しぶりにプログラミングをした話

別にエイプリルフールネタじゃないよ。

最近仕事が忙しかったうえ、あまりこれを作りたいというインスピレーションも無く、全然プログラミングに触れていませんでした。
前回の記事は全然プログラミングに関係ないめちゃめちゃアナログな回路のお話でした。その前はリフルシャッフルをテーマにした算数のお話で、辛うじてこじつけ程度にプログラミングに触れた程度でした。

ですが、世の中はコロナパニック、二言目には「不要不急の外出は控え」ということで、先週末久しぶりに少しだけ文字列をいじくるC#プログラムを書きました。そのところ、未来にでもワープしてきたんじゃないかというくらいめちゃめちゃ環境が変わっていてびっくりしたので、ひとまずかるーく記事にしておこうと思います。

Range構文

まあ「未来にでもワープしてきた」と大げさに書きましたが、気づいたらC#8.0がリリースされていたというだけです。
C#8.0ではRange構文というものが導入されました。これまでは配列や文字列の一部分を切り取る際に、よくこんな書き方をしていました。

text.Substring(now, m.Index - now);

now~m.Indexの範囲の文字列を抽出するだけのプログラムですね。
余談ですが、mはMatchクラスの変数です。すなわち、now以降正規表現でマッチした部位より手前の文字列を抽出するだけのプログラムです。

おやおや、VisualStudioさんに煽られてしまったではありませんか。Substringを使うのはもう時代遅れと。

実質的にこのRange構文を使ったコードはSubstringに展開されるだけのようなので、バイナリとしては変わりませんが、冗長な引き算やメソッド名が省略できるうえ、構文として意味が明確に定義される(メソッドだとメソッドを実装した人の流儀で決まってしまう)のでとても良い構文だと思います。

今回は使いませんでしたが、これ以外にも「末尾から何文字」とかいう表現も容易にできます。かゆいところに手が届く、非常に強力な構文ですね。はい。

null許容参照型

さて、Range構文を採用したとなると、セットで出てくるのがSpan<T>です。
C#が言語としての安全性を求めるあまり、C言語ではゴリゴリ書けていたポインタをいじくりまわすようなプログラムは書けないようになっています(Unsafeは除く)。ですが、その代償として場合によってはあまり効率の良いプログラムは書けないもどかしい状況がありました。

そこで、安全にポインタらしい機能を実装しようということで導入されたのがSpan<T>です。これは「範囲」を指定するRange構文と非常に相性が良く、Range構文で示した範囲をSpan<T>で参照として返す、というのが非常に基本的な使い方となります。

というわけで、text.AsSpan()してRange構文を適用しようとしたら…

ん…?「string?」 …?

型名の後ろに着く「?」は、null許容型を意味しています。
そもそもnullが無い値型をNullable<T>構造体でラッピングし、nullという意味を追加しようというものです。
ですが、stringは参照型ですので、わざわざNull許容型にしなくてもnullを取ることができます。なので、後ろに「?」を付けると昔ならばコンパイルエラーになっていました。

はい、これもnull許容参照型という C#8.0から導入された機能、「null許容参照型」です。

「null」は参照型がどこも参照していない、という意味を表す定数です。参照型には、参照である以上「どこも参照していない」という状況が付いて回るのですが、それを使うかどうかはまた別問題です。実際問題、null状態の参照型を受け付けたくない状況は非常にたくさんあります。
その場合、今までならばメソッドを実装するときに最初にパラメーターのnull性を確認して、場合によってArgumentNullExceptionを投げるようなプログラムを書くことになりますが、めんどくさいですよね。そして使う側もその例外が発生する可能性を考慮しなければならない。本来の大切なロジックを書く以前のところで雑務が発生してしまうし、コードとしてもノイズが入るので見通しが悪くなってしまうわけです。

そこで、C#8.0では、ただ単に参照型の型名を書くと「null非許容」としてみなすようになりました(破壊的仕様変更になるので、オプションでONしないと有効にはならないようです)。その場合、コンパイラが非nullであることをしっかり確認し、どこかでnullになるような可能性があればエラーを出してくれるようになりました。
逆に、nullを使いたいという時は、敢えて型名に「?」を付けなければならなくなりました。これがnull許容参照型です。

気づいたのがプログラムを書いている途中だったので、今回は先延ばしです。オプションは有効にしないことにします。
ですが、厳格に運用できれば、逆にもっと効率よくすっきりとしたプログラムを書けるようになりますね。


ほかにもC#8.0には多くの機能が実装されています。
例えばswitch式とかインターフェースのデフォルト実装機能とか。

そもそも半年前にC#8.0が正式リリースされているにもかかわらず、そのことを知ったのが今って、本当に久しぶりにC#に触ったんだなあ。また余裕ができたら何か作りたいもの考えてプログラム書かないとな。

0 件のコメント:

コメントを投稿