サクサク読めて、アプリ限定の機能も多数!
トップへ戻る
Appleイベント
ufcpp.net
前回の Lock クラスの話を見てから、とりあえず以下のコードを見てほしい。 using System.Runtime.Versioning; [module: RequiresPreviewFeatures] class MultiThreadCode { private static readonly object _syncObj = new(); private static readonly Lock _syncLock = new(); public static IEnumerable<object?> MIterator() { lock (_syncObj) { } // 旧来 lock。 lock (_syncLock) { } // 新しい lock (VS 17.10p2 以降)。 yield return null; } public static async V
今日は、 .NET 9 で Lock クラスというのが入る予定で、 それに伴って C# コンパイラーにも対応が必要そうという話。 一応雰囲気的には C# 13 に入りそう。 任意のオブジェクトを lock C# はなぜか任意のオブジェクト インスタンスを使って排他制御ができます。 ロックを掛けるために以下のようなコードを書くことになります。 class MultiThreadCode { private readonly object _syncObj = new object(); public void Run() { lock (_syncObj) { // いろんなスレッドから同時に呼ばれるコード。 } } } Java からの習慣(= 1995年頃の発想)ですかね。 Java の synchronized ブロックも同じ仕様のはず。 本来の思想としては「lock() の () 内
C# 3.0 から拡張メソッドが使えるわけですが、 もうちょっといろんな「拡張」をしたいという話が前々からあります。 例えば以下のような要求。 既存の型に静的メンバーも足したい プロパティや演算子も足したい インターフェイスの後付けもしたい 今では Extensions とか呼ばれていまして、以下の issue でトラッキング中。 Exploration: Shapes and Extensions #164 ここからさかのぼって、かつては Extension everything とか呼ばれていたり、 個別に「インターフェイスを実装したい」「演算子を拡張したい」など個別の issue がありました。 Extension Everything Extension classes with Interfaces Extension operators 2015年(Roslyn が GitHu
C# 13でのコレクション式関連、量が多いのでちょっとずつ取り上げシリーズ。 [Proposal]: Collection Expressions Next (C#13 and beyond) 今日はディクショナリ式の話を。 ディクショナリ式 ← 今日はこれ 自然な型 インラインなコレクション式 コレクションに対する拡張メソッド 現状でコレクション式に対応してない型 非ジェネリックなコレクションのサポート 制限の緩和 C# 12 でコレクション式が入りましたが、Dictionary<TKey, TValue> などのディクショナリ系の型に対しては使えませんでした。 // C# 12 でも空っぽのディクショナリは作れるのに… Dictionary<string, int> d = []; // 要素があるものは書く手段がない(以下はいずれもエラー)。 // スケジュールの都合で意図的に「C#
C# 12 でコレクション式が入ったわけですが、 スケジュールの都合で「C# 12 後に改めて検討する」ということになった機能がたくさんあります。 C# 12 リリース(2023/11)直後から再検討が始まっていて、先月にはある程度まとまった計画が出ています。 [Proposal]: Collection Expressions Next (C#13 and beyond) 量が多いのでちょっとずつ取り上げ… ディクショナリ式 自然な型 インラインなコレクション式 コレクションに対する拡張メソッド 現状でコレクション式に対応してない型 非ジェネリックなコレクションのサポート 制限の緩和 ← 今日はこれ 今、コレクション式の要素の型は IEnumerable<T> の T で判定しています。 using System.Collections; foreach (var x in new A(
.NET が長らく抱えている「なぜ IList<T> は IReadOnlyList<T> ではないのか」問題、 .NET 9 で解消するかもしれないみたい。 ちなみに、問題を抱えるに至った原因は IReadOnlyList<T> が後付けということです。 1から作り直すのであれば、誰がどう考えても IList<T> は IReadOnlyList<T> から派生させるのが自然です。 それがかえって、IReadOnlyList<T> 導入以降に .NET 利用を始めた人に混乱を招いているというのが現状になります。 当初設計: インターフェイスは増やしすぎない インターフェイスを増やすというのは、 型情報で DLL サイズが増えるとか、 実行時にインターフェイスを検索するコストが増えるとか、 多少なりともコストを生じます。 一方で、.NET Framework の最初のβ版が出たのは2000
ほぼ1年ぶりの params の話。 params を配列以外のコレクションに対して使えるようにするという話ですが、 雰囲気的に C# 13 でついに 入りそうです。 なので、最近そこそこ高頻度で Language Design Meeting の議題に上がっています。 Params Collection C# Language Design Meeting November 15th, 2023 January 29th, 2024 January 31st, 2024 February 21st, 2024 まあ、割かしもう詳細を詰めている感じの話題が多めですね。 params ‘コレクション’ 去年には「ReadOnlySpan<T> 以外需要低め」、「他はコレクション式を使って M([a, b, c]) でいいのでは」などという話も出ていましたが。 コレクション式を実装した今改めて
ラムダ式で、ref 引数などに対して ref x => { } みたいに書けるようにしたいという話が出ています。 ラムダ式での ref 引数、out 引数 ラムダ式は、状況が許すなら、x => { } などといったように非常に簡素に書けます。 ところが、ref や out が絡むとそうもいかなくて、型推論が効く状況でも型名を省略できません。 // 通常、ラムダ式は型推論が効く限り、引数の型を省略できる。 Action<int> a = x => { }; // ところが ref, out などの修飾が付いた引数は省略不可。 // これなら OK。 RefAction<int> r = (ref int x) => { }; OutFunc<int> o = (out int x) => x = 1; // ダメ。CS1676 エラー。 RefAction<int> r1 = x => {
C# 13 向けに検討されている機能の一つに、 「半自動プロパティ」とか「field キーワード」と呼ばれているものがあります。 元々は C# 12 向けに考えられていて、去年、うちのブログでも書いているやつです。 【C# 12 候補】半自動プロパティ 簡単におさらいすると、 プロパティの get/set アクセサー内で、field を使って バッキング フィールド(自動プロパティの値を保存するためにコンパイラーが生成するフィールド)に明示的にアクセスするというものです。 class A { // 手動プロパティ (manual property) // (と、自前で用意したフィールド)。 // こういう、プロパティからほぼ素通しで値を記録しているフィールドを「バッキング フィールド」(backing field)という。 private int _x; public int X { ge
今日は「負の遺産整理で消したいけども消せないメソッド対処」の話。 紆余曲折合って、現状、OverloadResolutionPriority 属性でオーバーロード解決に優先度をつけて、 優先度の高いものだけを見るようにするという案になっています。 最近のわかりやすい例だと、「パフォーマンス改善のために配列引数を ReadOnlySpan 引数に変えたい」というのをやりたいとします。 元々、配列引数で作っていたとして、 int[] x = [1, 2, 3]; C.M(x); // 元コード。 public class C { // これの引数を変えたい。 public static void M(int[] x) { } } 暗黙的型変換があるものであれば、多少型を変えても「再コンパイルすれば大丈夫」という状態になることはあります。 int[] x = [1, 2, 3]; // int[
C# のジェネリック型引数の推論を賢くしたいという話は、issue として記録されている分に限っても5年くらい前からあります。 Champion: "Partial Type Inference" 現状の C# の型推論は割と "All or Nothing" で、 new() みたいに型全体の省略はできても、new List<>() みたいな「一部分だけ省略」ができません。 // 型全体の推論は可能。 // 左辺から型が決定されて、new() は new List<int>() と解釈される。 List<int> x1 = new(); // 一方、型引数だけの省略というのができない。 List<int> x2 = new List<>(); // 要は Java のダイヤモンド演算子みたいなのとか、 List<int> x3 = new List<_>(); // あるいは「ここは推論
今日は「Span<T>、ReadOnlySpan<T> をコンパイラーで特別扱いしたい」という話。 C# 7.2 の頃、Span<T> 型が追加されて、 安全性を損なわずに unsafe コード並みにパフォーマンスのよいコードが書けるようになりました。 それ以来、.NET の標準ライブラリでもいろんな場面でSpan<T> 型が活用されています。 いまや結構重要なポジションを担う型なわけですが、 現状の扱いはあくまで「普通の構造体の1つ」です。 そのため微妙にオーバーロード解決とかで困り気味。 例えば直近では、C# 12 でコレクション式を導入するにあたって「普通にやってたら使い勝手が悪いので Span を特別扱い」みたいなことをやっています。 // 普通にやると IEnumerable と Span の優先度はつかなくてコンパイルエラー。 EnumerableVsSpan.M(new in
「最近動きがあったもの」ブログをいくつか書いてて、 「続報」みたいなものも書いてるわけですが。 今日のも「まあ、去年から動く実装すでにあるんだけど」という意味では続報なものの、 今日のインターセプターはあまりうちのサイトで取り上げておらず、初めて説明を書く話。 (ライブ配信では時々話に出てるんですが。) 今日話すインターセプターは、まあ、Source Generator向けの機能です。 既存の Source Generator でも、 クラスを丸ごと生成するとか、メソッドの中身を生成とかはできます。 .NET が標準で提供しているやつだと GeneratedRegex とか。 partial メソッドに属性を付けて、メソッドの中身をコード生成しています。 partial class Reg { // この属性を付けた partial メソッドに対して、 // Sytem.Text.Regu
ref 構造体で説明しているように、 Span<T> 型など一部の型は「スタック上にないといけない」という強い制約があります。 この制約を守るため、これまで、ref 構造体は インターフェイスを実装できなかった ジェネリック型引数に使えなかった という制限が掛かっていました。 C# 13 では、この制限を緩和するため、 ジェネリック型引数に「allows ref struct」という「アンチ制約」を追加する予定です。 こういう案自体は ref フィールドが追加された C# 11 (2022年)の頃から温められてはいたんですが、 いよいよ C# 13 で本格的に取り組むみたいです。 .NET 8/C# 12 がリリースされた後くらいからちらほら提案ドキュメントの更新あり。 Add draft for demonstrating ref-struct-constraint soundness
今日の C# 話はちょこっとした修正の話になります。 これまで new C { [^1] = 1 }; がコンパイル通らなかったみたいで、これが最近修正されました。 (Visual Studio 17.9 Preview 3 (1月17日リリース済み)の時点で実装されていました。 気づいてはいたけども、小さすぎてブログにするかどうか迷ってるうちに3週間ほど経過。) 以下のコードで示すような修正内容です。 // これがコンパイル エラーを起こす。 // (Visual Studio 17.9 Preview 3 以降を使うとコンパイルできるようになった。) var c = new C { [^1] = 1 }; // これなら昔からコンパイル通る。 // (オブジェクト初期化子はこれと同じコードに展開されるはずなのに。) c[^1] = 1; class C { // インデクサーと Len
去年の3月にブログに書いたものの続報。 C# でも限定的に破壊的変更を許していこうかという話だったわけですが、 ちょっと具体化しました。 ある機能を実現するにあたって破壊的変更の原則と進め方についての話をしています。 破壊的変更の候補 C# 13 で導入したい field アクセス(自動プロパティのバッキングフィールドにアクセスするための field キーワード)と、 これまでに破壊的変更を避けるためにちょっと変な設計になっている var (型推論変数宣言)、_ (discard)が検討の対象になっています。 破壊的変更を認める基準 あくまで控えめな破壊的変更で、エンドユーザーに明確なメリットがある 破壊的変更を踏むようなコードは割かしレア 破壊的変更を起こす予定のコードはどういう理由でどこが問題で、どう直せばいいかが明確に示せる 破壊的変更を避けられるよう、完全に自動で、簡単で、堅牢で、
先々月書いた「C# 13 向けトリアージ」で紹介してた C# 13 候補の1つ、「\e エスケープ シーケンス」が早々に実装されてたという話です。 .NET 8 正式リリース記念の配信ではちょこっと触れてたんですが、そういえばブログには書いてなかったので紹介。 キーボードで打てないような文字や、画面に表示されない文字を入力したりするために、 「\n と書いたら改行(U+000A, new line, line feed)に置き換える」みたいな仕様があり、これをエスケープ シーケンス(escape sequence, 回避用の一連の文字列)と言います。 C# をはじめ、C 言語の影響を受けて作られた言語の多くは \ (reverse solidus, 逆スラッシュ)で始まる文字列によってエスケープします。 プログラミング言語だと他には ` (逆引用符、グレイブ アクセント, grave ac
概要 2010年代に入って、C# コンパイラー開発チームは、C# のコンパイラーを再設計・再実装していました。 (プロジェクトとしては C# 5.0 の実装と並行して動いていたようなので少なくとも2010年以前からある。) 以下のような作りで再実装されています。 最初から Visual Studio などの IDE との連携を意識した作り 最大の恩恵を受けるのは .NET チーム自身ですが、結果として、Visual Studio の高機能化が促進され、.NET 開発者全体への恩恵が期待できます。 API がオープンなので、第三者による Visual Studio プラグイン開発も容易になります。 C# 実装 これは単純に実装難易度を下げるためと思われます。 副次的に、かかるコストの割には効果が薄いということでこれまで実装されてこなかったような、ちょっとした便利機能が実装されやすくなります。
概要 Ver. 12 C# 12 で、[] 記号を使って配列などの初期化ができるようになりました。 配列だけではなく、コレクション(List<T> 型など)、Span<T> なども全く同じ書き方で初期化できます。 これをコレクション式(collection expression)と言います。 using System.Collections.Immutable; int[] array = [1, 2, 3]; List<int> list = [1, 2, 3]; Span<int> span = [1, 2, 3]; ReadOnlySpan<int> ros = [1, 2, 3]; ImmutableArray<int> immutable = [1, 2, 3]; また、コレクション式中では、.. を使うことで「別のコレクションの中身の展開」ができます。 これを スプレッド (s
.NET 8 も RC 2 な段階になって、ここから GA までの間に仕様が変わるということはほとんどなくなってきました。 となると、話題はもうその次。来年向け(C# 13 / .NET 9 ターゲット)の話が出てきます。 C# Design Meeting でも、13向けのトリアージがちらほら始まりました。 とりあえず現状、2件。 LDM Notes for October 9th, 2023 LDM Notes for October 16th, 2023 以下のようなものがトリアージされました。 10/9 議事録 ReadOnlySpan initialization from static data 5295 #5295 C# 7.2 辺りから、以下のような「配列のアロケーションを消す」最適化が掛かります。 // 定数だけで構成された byte 配列は最適化で消える。 // new
概要 Ver. 12 .NET 8 で、 InlineArray 属性 (System.Runtime.CompilerServices 名前空間) というものが入りました。 基本的には .NET ランタイム側の機能ですが、 いくつか、C# 側にもこの InlineArray 向けの特殊対応が入っています。 ちなみに、この機能は現状、 コレクション式の内部実装にこそ使っていますが、 本稿で書いているようなコードを直接書く必要はほぼありません。 (実質、本稿はコレクション式の内部実装(の一部)の説明みたいなものです。) InlineArray 属性 .NET 8 から、 以下のように、構造体に属性を付けると構造体のサイズが変わります。 using System.Runtime.CompilerServices; // この属性を付けると、 .NET ランタイムが特別扱いして、構造体のサイズを
執筆予定: C# 12.0 トラッキング issue コレクション式 [] 記号を使って配列などの初期化ができるようになりました。 配列だけではなく、コレクション(List<T> 型など)、Span<T> なども全く同じ書き方で初期化できます。 これをコレクション式(collection expression)と言います。 using System.Collections.Immutable; int[] array = [1, 2, 3]; List<int> list = [1, 2, 3]; Span<int> span = [1, 2, 3]; ReadOnlySpan<int> ros = [1, 2, 3]; ImmutableArray<int> immutable = [1, 2, 3]; また、コレクション式中では、.. を使うことで「別のコレクションの中身の展開」ができ
概要 Ver. 7 タプルから値を取り出す際には、メンバーを直接、それぞれバラバラに受け取りたくなることがあります。 「名前のない複合型」で説明したように、 メンバー名だけ見ればその型が何を意味するか分かるからこそ型に名前が付かないわけです。 このとき、その型を受け取る変数にも、よい名前が浮かばなくなるはずです。 そこでC# 7では、タプルと同時に、分解(deconstruction)のための構文が追加されました。 以下のような、整数列の個数(count)と和(sum)を同時に計算するメソッドがあったとします。 「名前のない複合型」で説明したように、 戻り値の型として「個数と和」みたいな名前(CountAndSumとか)しか思い浮かばないようなものです。 static (int count, int sum) Tally(IEnumerable<int> items) { var coun
「そういやブログに書いてなかった」ネタ。 Pull Request が通った プレビュー版(Visual Studio 16.6 Preview 1)でよければ今年の2月頃から使えてた話です。 文字列に対する switch に新しい最適化手法が導入されました。 元々の switch のコスト 例として以下のような switch を考えます。 static int StringSwitch(string s) => s switch { "abc" => 0, "def" => 1, "ghi" => 2, "01234a" => 3, "01234b" => 4, "01234c" => 5, "aaaaaaaa" => 6, _ => -1, }; C# コンパイラー的には、 case 少なければ単に上から順に if (s == "...") を並べる 多ければ IL の switch
前回のブログに続き、 先日の C# 配信で出てたネタ。 まあ、今回のは知ったところで誰が助かるということもないようなトリビア的な話です。 後だし優先で上書き その C# 配信内で、 「CultureInfo.DefaultThreadCurrentCulture を上書きすれば対処はできるけども」 みたいな話が出まして。 ただ、まあ、こういう「グローバルに影響がある静的プロパティの書き換え」は決してお行儀はよくないじゃないですか。 誰でも、いつでも上書き可能。 すぐに競合しかねません。 例えばここで出した DefaultThreadCurrentCulture だと、 人それぞれ、以下のようなバラバラの主張が混ざったとします。 常に InvariantCulture にしたい 常に ja-jp カルチャーにしたい 基本、InvariantCulture でいいものの、日付の書式だけは MM
先日の 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,
公理とは「数学の理論体系で定理を証明するにあたって、前提として仮定するいくつかの事柄」を指します。 どのような理論体系にも公理、すなわち「前提とする仮定」が存在します。 もちろん、この「仮定」が間違っていれば、理論全体が間違いになりますが、 そもそもの仮定が正しいのかどうかを証明するすべはありません。 正しいかどうか分からないものは少ないに越したことはありません。 したがって、公理と言うものは必要最小限である必要があります。 極力少ない仮定から出発して、より多くの結論を導き出せるものこそが優れた理論であると言えます。 では、自然数や実数などの、数学の集合を構築するためには、 最低限どのような公理が必要になるのでしょうか。 自然数という集合の存在そのものや、1+1=2という計算法則は公理として仮定しなければいけないのでしょうか。 それとも、もっとシンプルな公理から出発して証明できるものなので
概要 C# には「明確な代入(definite assignment)ルール」と呼ばれる、未初期化変数を避ける仕組みがあります。 未定義動作問題 大昔のプログラミング言語では、 変数に対して誰も何の値も代入していないことで、不定な値が返ってくるということがありました。 不定な値が得られてしまうことで、未定義な動作になります。 特にまずいのは、「テストの時にはたまたまうまくいっていた(うまくいく値が返っていた)けども、本番でだけ失敗する」みたいな状況です。 この未定義動作はかなりまずい状態なので、 最近のプログラミング言語では大体これを防いでいます。 大体以下のいずれかの手段を取ります。 既定値: ある決まった値(C# の場合は 0 や null)を自動的に代入する 明確な代入: 開発者が明示的な代入をすることを義務付ける C# では、クラスのフィールドや配列の中身については前者の「既定値に
概要 Ver. 9 関数ポインターとは、メモリ上でメソッドなどの命令列が入ってるアドレスを指すポインターで、 「そのアドレスにジャンプすることでメソッド呼び出しが実現されている」みたいなものです。 .NET の内部的にはこれまでも関数ポインターがあったんですが、 それを C# から効率的に呼ぶ手段がありませんでした。 これに対して、C# 9 では delegate* という記法で関数ポインターを扱えるようになりました。 (unsafe コンテキスト内限定で使えます。) 以前からある関数ポインター 関数ポインター自体は .NET には昔からあって、 例えば、関数ポインターの値を IntPtr (nint) で取得する手段は .NET Framework 1.0 (初代。2002年リリース)の頃からありました。 ただ、関数ポインターを使ったメソッド呼び出しの側は、C# には関連機能が一切なく、
次のページ
このページを最初にブックマークしてみませんか?
『++C++; //未確認飛行 C++』の新着エントリーを見る
j次のブックマーク
k前のブックマーク
lあとで読む
eコメント一覧を開く
oページを開く