プログラムの事とか

お約束ですが「掲載内容は私個人の見解です」

文字列のソート

文字列で昇順ソートしている部分の並べ替えが間違っている、と指摘されてどういうことなのかよく聞いたら漢字部分が"(訓)読み"通りになっていないということらしく「そこは文字コードでソート」と説明したんですが、最近の若い子は並べ替えの時に文字コード順にしないんですかね

と、わけのわからない事を書いてみましたが、プログラミングの勉強でソートは出てくるはずでそこで文字列を相手にやったりもすると思うんですよね

そんなときに

var list = new[] { "青森", "山形", "秋田" };
foreach (var s in list.OrderBy(s => s))
{
    Console.WriteLine(s);
}

この結果が

山形
秋田
青森

こうなってわけがわからなくなったりしないんでしょうか。ちなみに↑はどういう順番で並べ替えるのが正解なんでしょ

文字コード順は見ただけではわからない

ということで当て字なんかまで考慮して日本人になじみのある並べ替えなんてやっていられないので、並べ替えは基本的にシステム(フレームワーク)依存にします。多分文字コード順になるでしょう。そういう仕様にした場合、文字コード順に並べ替えられているか、をチェックする人がいるわけですがこのチェックがなかなか厄介っぽいです

このまえ C# の人のブログ 任意色絵文字? | ++C++; // 未確認飛行 C ブログ を見たのでこのあたりで以下のような cshtml を書いてみます (スクショですんません)

9~13行目で文字列リストを作って、20行目のループでそのまま出力。27行目のループで並べ替えて出力しています。出力はその文字列とデフォルトエンコーディングエンコード(?)したbyte配列です

上記 C# の人のブログにも書いてありますが Windows10では正しく表示されないので、Windows11のEdgeで見た結果がこちら

この結果はそれなりの経験者でも頭をひねるのではないでしょうか

ソート後の黒猫の位置がおかしいですね。 でもその横のデータを見るとおかしくないですね

ということで文字列部分でソートする時は気を付けましょう、というお話だったような気がします

おしまい

C#で値の入れ替え(Swap)

すごいテクニックとかじゃないです,ごめんなさい

昔作ったソースを久しぶりに開いたらR#先生から新しい教えをいただいたのでメモ

お題

2つの数値(a,b)の入れ替えをします

昔の

var a = 1;
var b = 2;

var temp = a;
a = b;
b = temp;

Console.WriteLine($"a={a} , b={b}"); // a=2 , b=1

プログラミングの勉強始めて1日目に書くコードですね. どんな言語でも同じような感じだとおもいます

新しい教え

var a = 1;
var b = 2;

(a, b) = (b, a);

Console.WriteLine($"a={a} , b={b}");

3行が1行になった!!

違い

↑の二つが同じものになるとは思えなかったので,ビルド後の生成物の値の入れ替え部分だけdnSpyでサクッと見てみます

昔の

int a = 1;
int b = 2;
int num = a;
a = b;
b = num;

新しいの

int a = 1;
int b = 2;
int num = b;
int num2 = a;
a = num;
b = num2;

新しい方はテンポラリー用の変数が増えています.デスヨネーという感じでですがまぁ誤差です.速度やメモリを気にする方は要注意でしょうか

まとめ

最近(?)のC#のバージョンからこのように書けるようになったんだと思いますが,これは私的には非常にありですね.

それにしてもこれをヒントで出してくれるR#先生(トップ画像)がすごいと思いました. おしまい

Windowsサービスを作るときに自動回復に頼りすぎてはいけない話

今回もやらかしネタをネタにしています。相変わらずちゃんとした裏どりはしていないのであまり信じすぎないでください。

自動回復オプション

Windowsサービスには自動回復のオプションがあります。基本的にWindowsサービスとして実行したいアプリケーションは常時起動している必要があるからサービスにしているわけで、停止していることがばれたら困るアプリの最後の砦として重宝します。クライアントアプリなどは操作中に落ちたら再起動をユーザーがすぐにしてくれますが、サービスの場合はそれが難しいですからね。

.NET Framework時代

太古の昔、C#( .NET Framework )でWindowsサービスを作ろうとしたときに重宝したのが Topshelf というライブラリで、コンソールアプリとして動かすこともできるしそのままサービスとして動かすこともできる、とても素晴らしいものでした。

先に書きましたがサービスとして動かすアプリですから、簡単に落ちてしまっては困ります。コード内で例外をキャッチしまくって落ちないようにするわけですね。

ですがなんでもかんでも例外を拾って無理やり動かしていても、ただ落ちていないだけで正常に動き続けているわけではないサービスになってしまい、最終的に落ちているよりたちが悪い状況を引き起こすかもしれません。

そこでWindowsサービスの自動回復の登場です。想定される(復旧可能な)例外はアプリ内で拾って、想定外の例外はそのまま放置でアプリを落としてしまいます。落ちたサービスはWindowsが指定時間後に再起動してくれるので、想定外だったけど再起動で直るような現象をこれでカバーしていました。

.NET 時代

現在Windowsサービスを作ろうと思ったら、Visual Studioで「ワーカー サービス」のテンプレートを使ってUseWindowsService()でしょう。

IHost host = Host.CreateDefaultBuilder(args)
    .ConfigureServices(services =>
    {
        services.AddHostedService<Worker>();
    })
    .UseWindowsService()
    .Build();

host.Run();

これでWorkerの中でいろいろ処理をやるわけですが、今まで通りWindowsが指定時間後に再起動してくれるつもりで例外を拾わない、ように作ってしまうとやってしまいます。

これはログに

The HostOptions.BackgroundServiceExceptionBehavior is configured to StopHost. A BackgroundService has thrown an unhandled exception, and the IHost instance is stopping. To avoid this behavior, configure this to Ignore; however the BackgroundService will not be restarted.
Application is shutting down...

訳(?)「例外拾ってなくてBackgroundService 続けられないから終わるわ」

と出ているように、正常に終了しているのでWindowsはサービスがエラーで終了したとは認識してくれないからです。

自動回復の恩恵を受ける方法

継続不可能っぽいので再起動したいときにどうするのかというと簡単で

Environment.Exit(-1);

を呼ぶだけでいけます。かなり乱暴な方法なので最後の手段にしましょう。呼ぶときも解放できるリソースはできるだけ解放してからにしましょう。

というやらかしネタでした。

おしまい