VSCode で C# のブロック {} 前後の改行の設定を変更する 2023

本記事は C# Advent Calendar 2023 の2日目の記事だ。

1日目は @RyotaMurohoshi 氏の 【Allって】LINQ、この場合どうなる?【空配列は?】 #C# - Qiita だった。

以前バズった空配列議論のツイートを例に、 .NET の LINQ の各エッジケースでどう振る舞うかまとめた記事になっている。
なかなかのボリュームで読み応えがある。

慣れていないと迷ったり勘違いしやすい話なので、参考になる。

C# を K&Rスタイル で整形したい

さて、 C# の既定のコードフォーマットでは、名前空間やクラス、メソッドなど、各種ブロックの {} (中括弧・波括弧) の手前に改行が入る。(所謂、オールマンスタイル)

namespace MyNamespace
{
    class Class1
    {
        static void Main(string[] args)
        {
            if (args.Length > 0)
            {
                ;
            }
            else
            {
                ;
            }
            try
            {
                ;
            }
            catch
            {
                ;
            }
            finally
            {
                ;
            }
        }
    }
}

言語の既定に従うのも悪くは無いとは思う。思うのだが、 Java, JavaScript, Go, Rust 等々、他のメジャーな C言語 スタイルの言語では、 Java のコーディング規約に則って改行を入れないの(K&Rスタイル)が一般的なので、 C# で改行を入れるこのコードスタイルはどうにも気持ちが悪い(主張の強い個人の感想です)

手癖で改行を入れない書き方をしていても、 Shift+Alt+F でドキュメントのフォーマットをすると改行されてしまう。

…と言うことで、 Visual Studio Code (VSCode) を使って C# の開発する際に、各種ブロックの {} (中括弧・波括弧) の手前に改行が入らない形でフォーマットする方法を紹介する。

omnisharp.json は機能しない

vscode でこの設定を変更する場合、古くは omnisharp.json が使われていた。

ところが、 2023年中頃の VSCode の C# 拡張機能の更新 (v2.0.320) で、既定で Roslyn と Razor をベースとした新しい言語サーバーを利用するようになったため、 OmniSharp が使われなくなった。
このため、明示的に OmniSharp を有効 にしない限り、 omnisharp.json に書かれた設定は機能しなくなっている。

.editorconfig を使おう

続きを読む

.NET Interactive で C# と PowerShell を股に掛ける

この記事は、「C# Advent Calendar 2020」 9日目の記事、かつ 「PowerShell Advent Calendar 2020」 9日目の記事だ。

スミマセン。横着した。

この時期になれば .NET Interactive の Preview 4 が出てるだろうしその記事でも書こうかな~ などと目論んでいたものの、 残念ながら登場しなかった。

このため、 .NET Interactive .NET 5 対応版の導入と、 Variable sharing の内容でお茶を濁そうと思う。

.NET Interactive のなんたるかについては、以前の以下の記事で取り扱っているので、そちらを参照願いたい。

.NET Interactive を .NET 5 で動かしてみる

いきなり本題とは関係ない話になるが、 せっかく .NET 5 がリリースされたところなので、 .NET Interactive を .NET 5 で動かしてみよう。

続きを読む

.NET Interactive の C# REPL を Jupyter で

今回は、 .NET Interactive を利用し、ローカルマシンで C# や PowerShell Core の REPL を利用するまでをまとめる。

なお、 とりあえず動かしてみたいだけであれば、 Binder バッジのリンクをクリックして、 オンライン上の Binder にブラウザにアクセスするだけで、利用することができる。
Use Jupyter with .NET Interactive on Binder

.NET Interactive とは

.NET Interactive は、 以前 Try.NET と言う名前で提供されていた、 .NET のインタラクティブな機能を提供する API スイートだ。
JupyterLab に .NET カーネルを追加する形で、 REPL の実行やノートブックの作成する仕組みを提供することが、 主なユースケースとなっている。

REPL ではコード補完も効くので、非常に便利なものになっている。

Jupyter について

まず、 Jupyter についても軽く説明しておく。
既にご存じなら読み飛ばして欲しい。

JupyterLab とは?

続きを読む

C# REPL GUI Shell, Mono gsharp を Ubuntu に入れようとすると発生するエラーを回避する

.NET Core の登場で大分影が薄くなったものの、 まだまだ Xamarin でガンガン使われている Mono。
この Mono には, gsharp という C# GUI Shell が存在する。

CUI 版の Shell と比べると、 グラフがプロットできるとか、 画像が手軽に表示できるといったメリットしかないが、タブ補完も効くし、まぁ便利っちゃ便利なツールだ。

しかし Windows で gsharp を動かしたくても、 Windwos 用の Mono インストーラには gsharp が入っていないため、そのままでは gsharp を使えない。
このため、 WSL の Ubuntu に gsharp をインストールして、 VcXsrv などの X Server を使って動かすのが手っ取り早い。

以下の記事が詳しい。

ところが、 この gsharp などを含む、 Mono 拡張 GUI ツールを、 WSL を含む Ubuntu ベースのディストリビューションにインストールしようとすると、エラーになってしまう。

今回は、 その暫定的な回避策について。

TL;DR

早く mono/mono#16322 の不具合直した Mono パッケージを出してくれ。

続きを読む

同一ファイルに対して、 複数種類のファイルハッシュを高速に計算する

ネットワークドライブ上の GB オーダーのファイルに対して、複数のハッシュアルゴリズムでファイルハッシュを計算する必要に駆られていた。
「そんなシチュエーションが本当にあるのか?」と思うかも知れないが、あったのだから仕方ない。

最初は、 PowerShell を使って 愚直に Get-FileHash を 2回 計算していた。
しかし当たり前だが、 2回ファイルをダウンロードすることになるこの方法は遅くて仕方ない。

ということで、 C# でコンパイルしたコード上で、 一度メモリに読み込ませてから複数のハッシュアルゴリズムで計算できるようなコードを作成した。

バッファーサイズを 80KiB 程度とすると、 .NET の仕様で 85KB を境にメモリの扱いが変わる (LOH と呼ばれる特別なヒープに移動する) ことから、 このサイズを超えると一般的に動作速度が下がると言われている。
しかし、今回のコードの場合バッファーが小さいと、 Task 周りの処理がボトルネックになってしまうので、 8MiB くらいのサイズとしている。

80KiB としているのは、 .NET mscorlib の System.IO.Stream.CopyTo メソッドなどでもおなじみなのだが、これが必ずしも正解とは限らないわけだな。


パフォーマンス

800Mbps 位でシーケンシャルリードできるリモート上の 4GB のファイルを、 4回 ずつ計測した平均を計測した。
Get-FileHash の 2種類目 以外はクライアントキャッシュが効かないように注意し、 計測の各回でハッシュを計算するファイルはそれぞれ別のファイルで、中身はランダムバイナリとした。
Get-FileHash については、 計測の各回では同じファイルに対して -Algorithm パラメータを変えて複数回連続で呼び出した。

計算したハッシュの種類 Get-FileHash 上記の改良スクリプト
1種類 (SHA1) 48.8s 43.3s
2種類 (MD5, SHA1) 60.4s 44.2s
3種類 (MD5, SHA1, SHA256) 83.3s 48.2s

ん? 計算したハッシュが 1種類 の場合でも、改良スクリプトの方が早いぞ?


うわっ… HashAlgorithm.ComputeHash の実行速度、低すぎ…?

PowerShell v5 相当

PowerShell v6 相当

上記のように、 Get-FileHash は、内部的に HashAlgorithm.ComputeHash でハッシュ計算を実行している。

で、その HashAlgorithm.ComputeHash がどうなっているかというと、 4KiB 毎に ファイルの読み込みと、 ハッシュストリームへの書き込みを 同期的に 行っている。

ファイルの読み込みも、 (使うアルゴリズムにもよるけど) ハッシュの計算も、 どちらもコストがかかるので、同期的にやってたらそりゃ遅いわ。

System.Data.SQLite の NuGet パッケージ のうち どれをインストールするべきか

この記事は、(この記事が初公開された日を基準にして) 4年前に投稿された

の記事のフォロー記事だ。

Visual Studio 2012 に標準で含まれて以降、 NuGet を使ってライブラリパッケージをインストールすることが標準的になった。
しかし、 System.Data.SQLite に於いては、 NuGet パッケージの方も相変わらず多くのパッケージが公開されているので、 これらについてもどれをインストールすべきか解説してみようと思う。 160620_1

Entity Framework Core について書いたひとつ前の記事の

とは異なり、 こちらの記事は Full .NET で SQLite を使う場合で、 特に Entity Framework 6.x と組み合わせる際に有用な内容となっている。
(残念ながら、 System.Data.SQLite は .NET Core では使えないのだ。)

公開されている NuGet パッケージ

続きを読む

DI っぽく EF Core 1.0 + SQLite を Full .NET と .NET Core のコンソールアプリケーションで使ってみる [Entity Framework Core]

しばやん御大の Entity Framework Core についての以下の記事を読んで、


コンソールアプリでも、 ソースコードに 接続文字列 や ログの設定を書かずに、設定ファイルから Dependency Injection (依存性の注入: 以下DI) するにはどうしたらよいのかな? と思ったので、 ASP.NET Core の流儀を参考にしながら やってみようと思う。

データベースは、扱いが簡単な SQLite にする。

記事の最後に、 Visual Studio 2015 ですぐに使えるサンプルプロジェクトを用意しているので、 手っ取り早く結果を見たければ、 そのサンプルプロジェクトを見てみてほしい。

実現すること

まずは、何を実現させるのかをハッキリさせておこう。

  1. 接続文字列と ログ表示の設定を、外のファイルから指定すること
  2. マイグレーションなどを行うため、 EF Tools からも、上記設定が利用されるようにすること

ここで言う EF Tools とは、Entity Framework Core の コマンドラインツール のことだ。
このツールを使うと、 パッケージマネージャーコンソールから Add-Migration とか Update-Database と実行したり、 dotnet.exe から dotnet ef コマンドを 実行することで、 コード生成やマイグレーションなど を利用することができる。

EF Tools でデータベースを取り扱う際、その接続文字列は DbContext に設定されたものが使用される。
コード内に接続文字列を書いてしまうと、マイグレーションするためのデータベースファイルが決め打ちになってしまい、変更ができなくなる。
このため、 EF Tools を実行した際も、依存性の注入が行えるようにしたい。

前準備

続きを読む

PowerShell で 配列をシャッフルする

コード

PowerShell で 極力簡単に配列をシャッフル (ランダムにソート) する方法。
速度や制度などはガン無視して、簡単に書けることを重視。

$shuffled = $array | sort -prop @{Exp={[Guid]::NewGuid()}}

ハイ終わり。

検証

ホントに実用的なシャッフルになっているか心配なので、実際に 0~19 のシャッフルを 2000 回行って、先頭に来た数字と、10 が来たインデックスを集計してみる。

$r = 0..1999
$r | %{ $r[$_] = 0..19 | sort -prop @{Exp={[Guid]::NewGuid()}}; }
$r | %{ $_[0] } | group | Format-Table -AutoSize
$r | %{ $_.IndexOf(10) } | group | Format-Table -AutoSize
Count Name Group
----- ---- -----
  104 16   {16, 16, 16, 16...}
   91 19   {19, 19, 19, 19...}
  111 8    {8, 8, 8, 8...}
  102 7    {7, 7, 7, 7...}
   95 18   {18, 18, 18, 18...}
  105 3    {3, 3, 3, 3...}
   95 12   {12, 12, 12, 12...}
   83 15   {15, 15, 15, 15...}
  100 17   {17, 17, 17, 17...}
   89 5    {5, 5, 5, 5...}
  103 13   {13, 13, 13, 13...}
  103 11   {11, 11, 11, 11...}
  101 10   {10, 10, 10, 10...}
  110 4    {4, 4, 4, 4...}
  100 6    {6, 6, 6, 6...}
   88 2    {2, 2, 2, 2...}
  123 9    {9, 9, 9, 9...}
   92 1    {1, 1, 1, 1...}
  107 0    {0, 0, 0, 0...}
   98 14   {14, 14, 14, 14...}

Count Name Group
----- ---- -----
  102 17   {17, 17, 17, 17...}
   93 15   {15, 15, 15, 15...}
  100 9    {9, 9, 9, 9...}
  109 18   {18, 18, 18, 18...}
   91 4    {4, 4, 4, 4...}
  104 5    {5, 5, 5, 5...}
  111 3    {3, 3, 3, 3...}
  107 7    {7, 7, 7, 7...}
   83 1    {1, 1, 1, 1...}
  106 10   {10, 10, 10, 10...}
  101 13   {13, 13, 13, 13...}
   93 8    {8, 8, 8, 8...}
  111 16   {16, 16, 16, 16...}
  101 0    {0, 0, 0, 0...}
   83 2    {2, 2, 2, 2...}
  104 14   {14, 14, 14, 14...}
  103 12   {12, 12, 12, 12...}
   98 11   {11, 11, 11, 11...}
   81 19   {19, 19, 19, 19...}
  119 6    {6, 6, 6, 6...}

だいたい 100 に収束しているし、問題ないんじゃない?

とはいえ、 Guid クラスは、一意性はある程度期待できると書かれているものの、ランダム性は特に言及されていない。
出現にパターンがある可能性もあるし、厳密にランダムである必要がある場合は、使わない方がいいかもしれない。

続きを読む

スクリプト言語などから、共有フォルダにある .NET アセンブリを完全信頼で読み込む

PowerShell や IronPython などで ネットワーク共有フォルダに置かれている .NET アセンブリを読み込むと、このアセンブリのパスが実行ファイルの起動パスと異なるため、部分信頼での実行となってしまい、ファイルの読み書きなどの多くのコードが実行できない。
参考: MSDN | イントラネット アプリケーションの完全信頼での実行

一旦バイナリファイルをメモリに読み込んでから、アセンブリとしてロードするなどと言う方法もあるが、アセンブリからの相対パスなどが利用できなくなったりと、若干使い勝手が悪くなってしまう。

その回避方法として、Vista 以降限定ながら、アセンブリのフォルダをローカルにシンボリックリンクを貼って、そのシンボリックリンクを経由してアセンブリにアクセスすれば、完全信頼として実行することができる。

例えば、複数の PC で同じスクリプトを実行する様な場合、バージョンアップするときに全部の PC をもれなく更新するなど環境をそろえるが面倒だ。
このようなとき、イントラネットの共有ディレクトリにスクリプト置いて、ローカルからシンボリックリンクを通して実行すれば、更新するときはネットワーク共有のスクリプトを書き換えるだけで済み、コードも完全信頼で実行されるので、なかなか便利になる。

サンプルコード

実際に nasne の共有ディレクトリに、ファイルの読み込みを行えるコードを持ったアセンブリを作成して、読み込んでみよう。

続きを読む

System.Data.SQLite でどれをインストールするべきか

ちょっとした宣伝:

NuGet パッケージマネージャを使う場合については、別途

の記事にまとめている。

以下、本題。

メモ: 内容が 2012 年当時のものなので、 引用元の文章がすでになくなっていたりするが、 内容的には問題ないはずだ。

System.Data.SQLite を導入する

SQLite の ADO.NET アダプタである、System.Data.SQLite。
単なるラッパではなく、SQLite 自体もパッケージに持っているので、別途 SQLite をパッケージに含めなくても良いのが利点。
しかも、ライセンスが Public Domain であるのが、非常に使い勝手が良い。

注意: 詳しくは System.Data.SQLite の 著作権表記 を読んでほしいが、"System.Data.SQLite.Linq" と "System.Data.SQLite.EF6" については、ソースコードの一部が Ms-PL ライセンスとなっている。
Ms-PL ライセンスとなっている SQL Generation ディレクトリ のソースは、public domain と明示されているものをのぞくと、すべて copyright (c) Microsoft Corporation と書いてある。 ビルド済みバイナリには Microsoft の著作権表記などが出てこないため、バイナリ配布であれば Public Domain と書かれたライセンスに従えば良いので、特に何も気にする必要はなさそうだ。 ソースコードを配布する場合は、上記ソースコード先頭などに書かれているの著作権表記等の部分をそのまま消さずに表示しなくてはならない点に注意すべきだろう。

さて、いざ使おうとダウンロードページに飛ぶと、それはもうすごい数のパッケージが配布されている。

続きを読む