サクサク読めて、アプリ限定の機能も多数!
トップへ戻る
Pixel 9
ufcpp.net
去年の3月にブログに書いたものの続報。 C# でも限定的に破壊的変更を許していこうかという話だったわけですが、 ちょっと具体化しました。 ある機能を実現するにあたって破壊的変更の原則と進め方についての話をしています。 破壊的変更の候補 C# 13 で導入したい field アクセス(自動プロパティのバッキングフィールドにアクセスするための field キーワード)と、 これまでに破壊的変更を避けるためにちょっと変な設計になっている var (型推論変数宣言)、_ (discard)が検討の対象になっています。 破壊的変更を認める基準 あくまで控えめな破壊的変更で、エンドユーザーに明確なメリットがある 破壊的変更を踏むようなコードは割かしレア 破壊的変更を起こす予定のコードはどういう理由でどこが問題で、どう直せばいいかが明確に示せる 破壊的変更を避けられるよう、完全に自動で、簡単で、堅牢で、
先日の C# 配信で、 「これはブログに書いておくと助かる人がいるんじゃないか」と言われたものをブログ化。 背景: カルチャー依存問題再び うちのブログでも何回か書いてるんですが、 .NET の文字列比較は、カルチャー依存比較するものと Ordinal (文字コード通り)比較するものが混在していて、なかなかにやばいです。 .NET のカルチャー依存 API 問題 忘れがちなカルチャー依存問題 例えば以下のようなやつ。 using static System.Console; // 正規化すると同じ文字になる、文字コード的には別の文字。 var s1 = "a\u0301"; // á = a + ́ var s2 = "\u00e1"; // á // これは false。Ordinal 比較。 WriteLine(new Dictionary<string, int> { { s1,
概要 Ver. 9 関数ポインターとは、メモリ上でメソッドなどの命令列が入ってるアドレスを指すポインターで、 「そのアドレスにジャンプすることでメソッド呼び出しが実現されている」みたいなものです。 .NET の内部的にはこれまでも関数ポインターがあったんですが、 それを C# から効率的に呼ぶ手段がありませんでした。 これに対して、C# 9 では delegate* という記法で関数ポインターを扱えるようになりました。 (unsafe コンテキスト内限定で使えます。) 以前からある関数ポインター 関数ポインター自体は .NET には昔からあって、 例えば、関数ポインターの値を IntPtr (nint) で取得する手段は .NET Framework 1.0 (初代。2002年リリース)の頃からありました。 ただ、関数ポインターを使ったメソッド呼び出しの側は、C# には関連機能が一切なく、
今日は、「Globalization Invariant Mode」に変更したら、意外と忘れがちなところで差が出たみたいな話。 Globalization Invariant Mode 以前に1回ブログに書いてるんですが、 .NET の文字列 API にはカルチャー依存なものが多くて、 例えば 1.2.ToString() すらカルチャー依存です。 大陸ヨーロッパだと小数点を , にすることが多く、そのあたりの OS でこの ToString を実行すると "1,2" になります。 一方で、カルチャーごとの書式情報みたいなのは結構データ量が多いので、 WebAssembly みたいなフットプリントを小さくしたい環境では「そのデータを除外したい」要件があったりします。 そこで導入されたのがGlobalization Invariant Mode。 CultureInfo.CurrentCul
C# は、進化していくにあたって、破壊的変更を極力起こさないようにかなり気を使っているプログラミング言語です。 細かい話をすると破壊的変更も皆無ではないんですが、 破壊的変更を認める(認めてでも追加したい新機能を実装する)ハードルは結構高めです。 そんな C# ですが、ちょっとそのハードルの基準を緩められないかというような話が出ています。 Dealing with limited breaking changes in C# その後の Design Meeting 議事録 補足: 影響範囲と、影響力の軽減 補足として、 ハードルを緩めるといっても本当にちょっとです。 C# チームは、「GitHub の public リポジトリを検索して、実際に影響を受けたコードを探す」とかやって既存のコードに対する影響を評価してたりするんですが、 これまで: 単体テストとかでわざと変なコードを書いているも
今日は「拡張」(拡張メソッド的なものの改良)の話。 (今日のこれは、C# 12 で全て実装されるかどうか怪しく、 一部 13 以降になる可能性も結構高いです。) 提案ドキュメント: Extension types Working Group 議事録 2022/11/10 2023/1/23 2023/1/25 2023/2/15 結構昔から、 Extension everything: 拡張メソッドと同じような仕組みでプロパティ、インデクサー、演算子などを「拡張」したい Roles: 「拡張」をある種の「型」扱いしたい みたいな案があったんですが、結局、この Roles をベースに、Extensions とか Extension types という名称で実装が進みそうです。 原案で「Roles/Extensions」と呼ばれていたものは、「Explicit /Implicit extens
今回はコレクション リテラルの話。 ・提案 issue: [Proposal]: Collection literals #5354 今日の話も、提案自体は去年から結構前向きに検討されてたものです。 リスト パターンの実装の過程で出てきた案で、元から「C# 11 には間に合わないかも」みたいな空気感だったもの。 昨年11月に C# 11 が世に出た後、改めて進捗が出始めたので、今日はその辺りの話になります。 ちなみに、Language Feature Status で、最近 "C# Next" の欄に並びました。 実装もちらほら始まっているので、割かし C# 12 入りが有望だと思います。 コレクション リテラルおさらい 去年から大体決まってそうなところをおさらい。 文法的には [] を使う案が有力です。 using System.Collections.Immutable; // いろん
今日は半自動プロパティの話。 提案 issue: Proposal: Semi-Auto-Properties; field keyword #140 約1年前にも書いてる通り、場合によっては C# 11 で入っていたかもしれないものです。 需要はそれなりに高いんですが、 案外課題があって結局スケジュール的に11からははずれ、「その後どうなったの?」とか思われていそうな機能です。 (12候補としては結構有力。) 半自動プロパティの話自体は去年度にしているので、 今日書くのはその「課題」をつらつらと。 半自動プロパティ概要 去年の繰り返しになるので概要のみ。 要は、手動で書く通常のプロパティ(以下、手動プロパティ)と自動プロパティの中間で、 バッキング フィールドのアクセスに field というキーワードを使おうというものです。 class A { // 手動プロパティ (manual pr
今日は、「主に自分が使う用ツールを Blazor WebAssembly で作って Static Web Apps に置いたよ」系の話を一応ブログ化。 ソースコード Static Web App よくある「JSON とかのデータの中身を確認するツール」です。 しばらく、JSON と MessagePack の読み書きをするコードを書いてて、 デバッグがしんどくなって作ったのがこのツール。 いろんな形式を同時に扱うことがニッチ需要なのであんまり自分の需要にあったツールがなかったんですよね。なら、まあ、自作。 こないだの C# 配信 で、UTF-8 とか MessagePack バイナリとかを手打ちで入力してたら @xin9le, @okazuki 両氏にドン引きされたやつ。 バイナリ読み込み (Parser) UTF-8 を ReadOnlySpan<byte> のまま扱ってて、 ブレイクポ
個人的に、前々から「T4 は将来性が見えなさ過ぎてもう使うのやめたい」と言い続けていたわけですが、 最近ようやく自分が保守している T4 を全部別の手段で書き換えたので、 今日はそれの話。 T4 (Text Template Transformation Toolkit) テキスト テンプレートというと、ひな形的なテキストを簡易な文法で生成するようなものです。 例えば、 public static bool TryParse(this string s, out {{T}} x) => {{T}}.TryParse(s, out x); みたいな文字列の、{{T}} のところに bool, byte, int, double を与えて、 public static bool TryParse(this string s, out bool x) => bool.TryParse(s, ou
C# 配信でちょくちょく出てくる話題の1つに 「Visual Studio (for Windows)はいまだに .NET Framework だから」 というものがあります。 もちろん、「.NET Core 化はよ」みたいな文脈です。 Visual Studio は .NET 製アプリの中でも大規模なものの1つなわけで、ドッグフーディング的な意味で早く .NET Core 化してほしいというのもありますし。 .NET Framework → .NET 5 → .NET 6 → .NET 7 と、毎度2・3割は速くなってるというベンチマークがあるわけで合計すると2倍以上速いかもしれず、 普通にパフォーマンス上の理由でも早く .NET Core 系になってほしかったりもします。 そしてもう1個、 実は .NET Framework の方は Unicode 8.0 で止まっているという話があっ
またちょっと Gist に書き捨ててたコードが増えてきたので供養ブログをしばらく書いていこうかと。 (今年はまだ少な目。一人アドベントカレンダーな量にはならず。) 配列の共変性 悪名高いんですが、C# のというか、.NET の配列は共変だったりします。 // ↓.NET 的に許されていはいるものの、 items[0] = new Base(); が例外を起こすので今となってはあんまり使いたくない機能。 // 意図的に使うことはめったにないものの… Base[] items = new Derived[1]; // これは問題ない items[0] = new Derived(); // これも問題ない。 Base に Derived を代入するのは安全。 Base item = items[0]; // これがダメ。 // 実行時例外が出る。 items[0] = new Base();
久々のブログになります。 C# 11 の機能追加があるたびに YouTube 配信ではちょくちょく紹介していましたが、 こっちではかなりの久々。 そういえば去年とかは新しい Preview が出るたびに「今回はこの機能が実装されたよ」一覧くらいはブログに書いてたなと思いつつ。 まあ、今年は早い段階から「C# 11.0 の新機能」の方を埋める作業をしているので、何もしてなかったわけでもないんですが。 ちなみに、「C# 11.0 の新機能」の方は現在、 進捗 12/19 です。 .NET 7 Preview 7 での C しばらくブログとしては書いてなかった Preview 版の紹介を、今回久々に書いているのは、 .NET 7 Preview 7 で、 予定されている C# 11 の機能が一通り全部入った。今ないものは RC/GA でもない LangVersion に preview を指定し
2月にブログに書きましたが、 Visual Studio 17.1 Preview 3の頃、C# 11 候補として「引数の null チェック」構文が入っていました。 m(null); // ArgumentNull 例外が出る。 void m(string x!!) { } 今現在(VS 17.2 Preview 5)でもこの構文は生きているんですが、次(たぶん、17.2正式リリースでも17.3 Preview 1でも)でいったん取りやめになるそうです。 取りやめの経緯 C# チームとしては、今、Preview リリースをしてみて反応を見てその後どうするかを決めたりしているわけですが。 LangVersion preview があるのはそのためです。 とはいえ、普通に考えて、Preview 機能まで追いかけている人がそんなに多いわけもなく、 正式リリースされるまでどんな機能が追加されてい
先日出た Visual Studio 17.1 Preview 3 で、引数 null チェックの簡素化構文が入りました。 m(null); // ArgumentNull 例外が出る。 void m(string x!!) { } 展開結果 上記の void m(string x!!) は以下のように展開されます。 (クラス名は実際には通常の C# では書けない変な名前で生成されます。) void m(string x) { Internal.ThrowIfNull(x, "x"); } internal class Internal { internal static void Throw(string paramName) { throw new ArgumentNullException(paramName); } internal static void ThrowIfNull(
.NET のアップデート 昔の C# アプリ (例えば去年作った TargetFramework net5.0 なアプリ)をそのまま最新のランタイム(例えば .NET 6 ランタイム)で動かすことを考えます。 .NET は API レベルでの破壊的変更はめったにないので、 「API が合わなくてロードできない」みたいな根本的な問題はほぼ起こりません。 一方、挙動レベルでは時々破壊的変更があるんで、確実に動く保証はなかったりします。 (それでも、体感、9割方は動きますが。) ここ数バージョンであった影響がありそうな変更でいうと、 .NET Core 3.0 の頃同期 I/O が例外を出すようになったものがちらほらある ネットワークなどを介する場合、非同期でないとパフォーマンスが出ないので .NET 5 で、国際化対応に ICU を使うようになった 文字列の紹介順や、IndexOf の挙動がち
昨日、C# 10.0 が正式リリースされたわけですが、皆様もう C# 10.0 へのアップグレードはお済でしょうか(当日アプグレが当たり前のような口調)。 まあ、 C# はそんなに大きな破壊的変更はしない言語ですし、 TargetFramework や LangVersion を書き換えるだけならそこまで大きな問題は起きないんじゃないかと思います。 (たぶん。 僕は CryptoStream の破壊的変更由来のテスト失敗を1件踏みましたが。) あえて踏み込むのであれば、 名前空間を namespace N {} からファイル スコープな namespace N; に書き換え ImplicitUsings を true にして未使用 using になる部分をごっそり削除 とかやると、機械的にできてリスクは低いものの大量の差分行を産むコミットを作れたりします。 ASP.NET では95万行の差
※一部、まだ記事化(めったに使わない機能や細かい修正の紹介)が完了していません: Async method builder override Enhanced #line directive 執筆予定: C# 10.0 トラッキング issue record struct C# 9.0 (レコード型の最初のバージョン)では、レコード型は常に参照型(クラスと同系統の型)になります。 これに対して C# 10.0 では値型も選べるようにしました。 そのため、以下のように、record class と record struct というキーワードで書き分けができるようになりました。 record class Reference(int X, int Y); // record だけ書いた場合こちらと同じ意味 record struct Value(int X, int Y); 詳しくは 「レコー
以下のコード、実行環境によって出力結果が変わります。 Console.WriteLine(new DateTime(2021, 8, 22)); 日本語 Windows 環境だと 2021/08/22 0:00:00 と表示されると思いますが、 OS 設定でカルチャーを変更すると別の書式になります。 例えば、en-US カルチャーにすると 8/22/2021 12:00:00 AM になります。 要するに、DateTime.ToString は OS のカルチャー依存になっています。 問題点はいくつかあるんですが… ToString みたいなよく使うメソッドの既定動作がカルチャー依存 WebAssembly みたいな、カルチャー情報を使いたくない環境がある カルチャー非依存にしたければ北米カルチャーを強要されがち 北米カルチャーが思った以上に世界から浮いてる 今日はこの辺りの話を書きたいと
.NET 6 ではプロジェクト テンプレートが更新されて、かなりシンプルになります。 例えば、コンソール アプリの場合(dotnet new console コマンドで生成)は(コメント行を除けば実質)以下の1行だけの C# ファイルが生成されます。 Console.WriteLine("Hello, World!"); 先日の .NET 6 Preview 7 から、コンソール アプリと Web アプリがこの新テンプレートになっています。 トラッキング issue を見るに、他のタイプのプロジェクトも同じ方針で書き換え中みたいです。 今日はこの新テンプレートがらみで、背景とか、内部挙動的な話とか、Preview 7 から正式リリースまでの間に掛かる予定の変更の話とか。 旧テンプレート まあ、これまでのテンプレートが以下のようなものでしたから、ずいぶんとすっきりしました。 using Sy
概要 C# 9.0 で、レコード型(records)という新しい種類の型が追加されました。 (また、C# 10.0 では構造体版レコード型(record structs)が追加されました。) record (記録)という名前通り、データの読み書きに使うことを意図した型です。 例えば以下のような書き方で、「Name という文字列と Birthday という日付」を読み書きできます。 using System; record Person(string Name, DateTime Birthday); データが主役のプログラミング プログラミングをしていると、データが主役・データが中心になる場面がちらほらあります。 「データが主役」(data centric)というのは、例えば以下のように、「Name という文字列と、Birthday という日付を持っている」というような「何の型がどういうデ
インターフェイスの静的メソッドを virtual/abstract 指定できるようにする話が出ています。 [Proposal]: Static abstract members in interfaces #4436 主な用途は、 ファクトリ 比較 (Equatable とか Comparable) 数値計算 とかになると思います。 一番求められている用途は数値計算で、要は NumPy みたいなことを C# でも苦痛なく、かつ、パフォーマンスを損なうことなく実現したいというものです。 ファクトリ 数値計算に特化した仕様かと言うとそんなこともないので、先に他の用途について触れておきます。 ジェネリックなメソッドを作るとき、new() 制約を付けることで引数なしのコンストラクターなら呼び出せるんですが… void m<T>() where T : new() { var x = new T()
今の Windows の IME は文字コード直打ちから F5 キーを押すことで任意の文字を入力できる機能を持っています。 いつからだろう。 Windows 10 が「新しい Micorsoft IME」になってからだとは思うんですが、気が付けばそんな機能が。 というか、逆に IME パッドはショートカットキーでは出せなくなった? (右クリック メニューからの選択では出せます。) 昨日の C# ライブ配信中で、「200B だけはよく使う」とおっしゃってる方が要らっしまして。 「ゼロ幅スペースって嫌がらせ以外の用途で使えるの?」、「あえとすさんって実用性ない黒魔術をよく使う人だっけ?」となって「どういう状況で使うんですか?」と聞いた結果が 「Twitter で ASP.NET をリンクにさせない技」 あっ… それは確かに使うわ… しかし、文字コード覚えて直打ちする手段に、 F5 なんていうわ
なんか割かし真面目に YouTube で C# ライブ配信するようになってから、気が付けばもう1年経ってるらしい。 ufcpp YouTube チャンネル 元々、「落ち着いたらちゃんとした告知的なものをここのブログでも書きたい」と思ってたら1年経ちました(今ここ)。 始めた当初の頃とか、ノート PC で無線 LAN で配信してましたからね、これ。 諸事情あって。 配信やるようになった経緯もまあ1回動画にしてますが、そういえばスライドを上げておらず、先ほどようやくアップロード。 ネタの仕入れ 概ねまあ、以下のスライドに全てが詰まっているわけですが。 「色々と自分の記憶にはあるけども、需要あるのかどうかわからなくて書くモチベーションが湧かない」みたいな「ネタはあるのにネタ切れ」状態だったので、なんかライブ配信でもやってみようかと。 ぶっちゃけて言うと「あれ? なんか Virtual YouTu
string interplation の改善するって。 現行仕様 C# 6.0 から以下のようなコードで string.Format 相当のことができるようになったわけですが。 var s = $"({a}, {b})"; これは、以下のように展開されます。 var s = string.Format("({0}, {1})", a, b); これがパフォーマンス的にあんまりよろしくなくて… 特に、冒頭の提案ドキュメントにもある通り、ロギング用途との相性が最悪で、 ILoggerのメソッドがなかなか使いにくそうな感じの引数になっています。 void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> format
今日はまた去年の作業が元ネタで、プログラミング言語の識別子に使える文字に関する話です。 レターか数字 「1文字目にはアルファベットか _、2文字目以降にはそれに加えて数字を使えます。」 30年くらい前にはこれが「プログラミング言語の識別子(変数名など)に使える文字列」の定義でした。 _ の部分はプログラミング言語次第ですが、「1文字目にアルファベット、2文字目以降に数字」の部分は結構いろんな言語でそうだったんじゃないかと思います。 まあ、昔のプログラミング言語は ASCII コードで書く物だったので、上記の条件は [a-zA-Z] とか [0-9] みたいな正規表現で書けたんですが。 Unicode の時代になると「アルファベットだけでいいのか」とか「アルファベットって何だ」という話になります。 レター まず、「アルファベット(alphabet)」というと母音と子音が分かれてる文字のことで
Visual Studio 16.9 Preview 3 が出たということでライブ配信をしていました。 冒頭で話しているんですが、Preview 1 は 16.8 正式リリースと同時だったので 16.8 の方を紹介、 Preview 2 はそんなに大きな変化もなかったので、Preview 3 で初めて 16.9 の話です。 ポロリ YouTube 配信前に作ってあるお品書き issueのタイトルには「C# Next ポロリもあるよ」とか書いているんですが。 まあ変なタイトルを付けたかっただけで、ポロリといっても「出ちゃいけないものが出ちゃった」みたいなことはないです。 C# にもちょっとした新 preview 機能追加あったよ 9.0 には間に合わなかったものがさらっと merge されたよ くらいの意味でポロリと言っています。 昨年、C# 9.0 のときは最初に Preview 機能追加
null、一般名詞としては「無効なもの」とか「0個」とかの意味の単語です。 zero も語源をたどるとアラビア語とかサンスクリット語の「空っぽ (nothing)」にあたる単語から来ていて、実のところ一般名詞としては出自が違うだけで null = zero だったり。 一方、C# (とそれに類するプログラミング言語)では、 null というキーワードを「無効なものを 0 を使って表す」という意味で使っていて、 一般名詞としての null が持つ2つの意味を同時に指していたりします。 とはいえ、別に null という英単語の意味を考慮して「無効なものを 0 を使って表す」にしたわけではなくて、 単に実装上「0 かどうかの判定は非常に高速なのでパフォーマンス的に都合がいい」という現実的な理由で 0 を使っています。 前置きが長くなりましたが、C# において null 判定をするというのは、内部
祝 .NET 5.0 GA。 Announcing .NET 5.0 C# 9.0 on the record Visual Studio 2019 v16.8 and v16.9 Preview 1 Release Today Announcing ASP.NET Core in .NET 5 Visual Studio 2019 16.8 リリースノート Visual Studio 2019 18.9 Preview 1 リリースノート .NET Conf 2019 - Day 1 ライブ配信 一応注釈なんですが、 .NET は以下のような状態です。 .NET 5.0 からは単に「.NET」になります .NET Framework, Standard, Core の統合結果です TargetFramework 名、 net5.0 で、 netstandard2.1 と netcorea
次のページ
このページを最初にブックマークしてみませんか?
『++C++; //未確認飛行 C++』の新着エントリーを見る
j次のブックマーク
k前のブックマーク
lあとで読む
eコメント一覧を開く
oページを開く