[雑記] 構文の進化
この記事はソフトウェアデザインに寄稿した内容が元になっています。 初出: 技術評論社刊『ソフトウェアデザイン 2016 年 4 月 号 今すぐ実践できる良いプログラムの書き方 C#編 言語機能の進化から学ぶ「良いコードの書き方」 概要...
View Article数値
概要 本項では、組み込み型の補足として、整数型や浮動小数点数型など、いわゆる「数値」がらみの少し細かい話をします。 int型とdouble型 C#の数値型には、使用する記憶領域サイズ違いのものがいくつかあります。その中で代表的な位置づけにあるのは、整数ではint型(4バイト)、浮動小数点数ではdouble型(8バイト)です。 どう「代表的」かというと以下のような感じです。...
View ArticleC# 7 の新機能
C# 7 Ver. 7 リリース時期 未決定 同世代技術 Visual Basic 15 要約・目玉機能 タプル型 パターン マッチング 2016/6現在、C# 7の仕様策定・実装の真っ最中です。 状況は以下のページで確認できます。 Language Feature Status 実装が進んできたものから取り上げていきたいと思います。 ※同時に以下のページも随時更新 C#の言語バージョンと.NET...
View ArticleC# 1.0
C# 1.0 リリース時期 2002/2 同世代技術 Visual Studio .NET 2002 .NET Framework 1.0 Visual Basic 7 C#は2000年6月に発表され、それから間もなくプレビュー版が公開されました。その後、2002年に正式リリースになっています。 当時、C#開発の指揮を取っていたAnders Hejlsbergは、元々Borland社でTurbo...
View Article複合型のレイアウト
概要 複合型(クラスや構造体)では、フィールドをメモリ上にどうレイアウト(layout: 配置)するかという問題があります。 通常、メモリ上のレイアウトがどうなっているのかをプログラマーが気にする必要はありません。 大体はコンパイラーが最適な仕事をしてくれます。 それでも、時々、レイアウト方法を明示的に指定したい場合があります (おそらく、そのほとんどはC++などで書かれたネイティブ...
View Articleローカル関数と匿名関数
概要 C# には、関数内に関数を書く方法として、ローカル関数と匿名関数という2つの機能があります。 いずれも共通して、以下のような性質があります。 定義している関数の中でしか使えない 周りの(定義している関数側にある)ローカル変数を取り込める ローカル関数の方ができることは多いですが、書ける場所は少なくなります。 匿名関数はその逆で、できることに少し制限がある代わりに、どこにでも書けます。...
View Article名前のない複合型
概要 型名がなくても、メンバー名だけでその型が何をしたいものなのか十分にわかる場合があります。 このとき、むしろ、良い型名が付かない(メンバー名と重複した名前にしかならない)こともあります。 そういう場合に、「名前のない複合型」を作りたくなります。 C#には、歴史的経緯から、匿名型(anonymous type)とタプル(tuple)という2種類の「名前のない複合型」があります。...
View Articleタプル
概要 Ver. 7 「名前のない複合型」で説明したように、 型には常によい名前が付くわけではなく、名無しにしておきたいことがあります。 そういう場合に使うもののうちの1つがC# 7で導入されたタプルです。 タプルの最大の用途は多値戻り値です。 関数の戻り値は引数と対になるものなので、タプルの書き心地は引数に近くなるように設計されています。 ポイント (int x, int...
View Article複合型の分解
概要 Ver. 7 タプルから値を取り出す際には、メンバーを直接、それぞれバラバラに受け取りたくなることがあります。 「名前のない複合型」で説明したように、 メンバー名だけ見ればその型が何を意味するか分かるからこそ型に名前が付かないわけです。 このとき、その型を受け取る変数にも、よい名前が浮かばなくなるはずです。 そこでC#...
View Article型スイッチ
概要 Ver. 7 C# 7で、is演算子やswitchステートメントのcaseが拡張されて、以下のような機能が入りました。 caseでも、is演算子と同じように、インスタンスの型を見ての分岐ができるようになった x is T tや、case T tというように、型を調べつつ、型が一致してたらキャスト結果を変数tで受け取れるようになった この機能を型スイッチ(type switch)と呼びます。...
View Article式とステートメント
概要 「変数と式」で少し言葉としては出しましたが、 プログラミング言語の構文には大きく分けて式(expression)とステートメント(statement: 文、平叙文)という2種類のものがあります。 最近のプログラミング言語ほど式の比率が高くなっています。 C#でも、バージョンを重ねるごとに、式になっている構文が増えています。...
View Article変数宣言式
概要 C# 7のいくつかの機能は、将来的にパターン マッチング(pattern matching)という機能に発展する予定です。 型スイッチ is演算子の拡張 switchステートメントの拡張 出力変数宣言 分解代入 パターン マッチングは結構大きな言語機能ですが、 小さく切り出していった結果が型スイッチや分解になります。...
View Article[雑記] エントリーポイント
概要 C# では通常、1つのプログラムは複数の C# ソースコードからなり、そのソースコード中には複数の関数が含まれています。 その、多数ある関数の中で、プログラム起動時に最初に呼ばれるものをエントリーポイント(entry point: 入場地点)と呼びます。 「C# のプログラムの基本構造」で例を出したように、 C# では、Mainという名前の関数が自動的にエントリーポイントになります。...
View ArticleC# 7.1 の新機能
※2017年6月現在、プレビュー版の情報です。正式リリースまでに、機能の増減や、細かい仕様の変更がありえます。 C# 7.1 Ver. 7.1 リリース時期 2017/? 同世代技術 Visual Studio 2017 Update 3 要約・目玉機能 C# 7.0のちょっとした改善 2017年6月時点で「Preview 2」の状態ですが、C# 7.0のリリース(2017年2月)から半年程度で...
View ArticleC# 7.2 の新機能
C# 7.2 Ver. 7.2 リリース時期 未定 同世代技術 Visual Studio 2017 15.5 要約・目玉機能 構造体と参照の活用 ※ 現在、C# 7.2 はプレビュー版です。正式リリースまでに変更があり得ます。 少しずつ説明を埋めている最中です。 進捗管理用の GitHub issue C#...
View Articlereadonly の注意点
概要 「定数」で、読み取り専用のフィールドが作れるという話をしました。 この時点ではまだクラスや構造体、値型と参照型の違いなどについて触れていなかったのでreadonly修飾子の簡単な紹介だけに留めましたが、 本項で改めてreadonlyについて説明します。 整数などの基本的な型に対して使う分には特に問題は起きないんですが、構造体やクラスなど、複合型に対して使うときには注意が必要です。...
View ArticleSpan構造体
概要 Ver. 7.2 Span<T>構造体(System名前空間)は、span (区間、範囲)という名前通り、連続してデータが並んでいるもの(配列など)の一定範囲を読み書きするために使う型です。 この型によって、ファイルの読み書きや通信などの際の、生データの読み書きがやりやすくなります。...
View Articleref構造体
概要 前項では、C# 7.2 の新機能と深くかかわる Span<T> 構造体という型を紹介しました。 この型は、論理的には (ref T Reference, int Length) というような、「参照フィールド」と長さのペアを持つ構造体です。 「参照」を持っているので、参照戻り値や参照ローカル変数と同種の「出所の保証」が必要です。 またSpan<T>...
View Article[雑記] インライン化
概要 前述の通り、関数によって「同じ処理を何度も繰り返し書かない」、「意味のある単位で明確な名前を付ける」ということができ、プログラムを読みやすく・書きやすくすることができます。 一方で、ここでは、プログラムのパフォーマンスの面から関数を見てみましょう。関数呼び出しには多少のコストが掛かります。このコストをなくすため、コンパイラーによってインライン化という最適化が行われます。 関数呼び出しのコスト...
View Article[雑記] デリゲートの内部
概要 デリゲートは、内部実装的には「インスタンスと関数ポインターをペアで管理しているクラス」になっています。 ここではデリゲートの内部挙動と、 それを踏まえたパフォーマンス上の注意点を説明します。 デリゲートの内部 デリゲートは .NET ランタイム内で特殊な扱いをされていて、 デリゲート内部で起こっていることをそのまま C# で書くことはできないので、...
View ArticleC# 7.3 の新機能
Ver. 7.3 リリース時期 2018/未定 同世代技術 Visual Studio 2017 15.7 .NET Core 2.1 要約・目玉機能 C# 7.0~7.2のちょっとした改善 C# 7.0 以降の「小数点リリース」も3つ目となりました。 これまでのC# 7系リリースで追加されてきた、 タプルや構造体と参照の活用、式中での変数宣言になどに関する改善が含まれています。 ※ C# 7.3...
View Article[雑記] オーバーロード解決
概要 関数で説明しましたが、 C# では関数メンバーに対して、 同名で引数リストだけが違う物を定義でき、これをオーバーロードと呼びます。 同名の関数がいくつかあるので、M(0) などと書いた時、実際には「どのMが呼ばれるか」という検索処理が必要になります。 このような同名の関数のうちどれを呼ぶか探す処理をオーバーロード解決(overload resolution)と呼びます。 本項では、C#...
View Article[余談] 暗黙的な派生
概要 C# では「すべての値型はValueTypeクラス(System名前空間)から派生する」というような、暗黙的な派生があります。 また、通常、値型(組み込み型や、構造体、列挙型)は他の型からの派生、他の型への派生ができませんが、 本項の「暗黙的な派生」だけは許されています。 ただ、内部的には、派生しているように見せかけるための特殊な変換処理が掛かっています。 ポイント 全ての型は Object...
View Articleデストラクター
概要 デストラクターとは、オブジェクトがガベージ コレクションに回収されるときに呼び出される特別なメソッドです。 「リソースの破棄」で説明しているように、 基本的には、確保したリソースの後片付けはDisposeメソッドをusingステートメントを使って行います。 しかし、usingステートメントは呼び忘れる可能性があって、100%保証のある後片付けにはなりません。 一方で、ガベージ...
View Articleパターン マッチング
概要 前項で説明した通り、C# 7.0で、is演算子とswtichステートメントが拡張されて、is/caseの後ろにパターンを書けるようになりました。 パターンには以下のようなものがあります。 パターン バージョン 概要 例 型パターン C# 7.0 型の判定 int i、string s 定数パターン C# 7.0 定数との比較 null、1 discard C# 7.0 何にでもマッチ・無視...
View Article言語バージョンの指定
概要 ここでは、C# の言語バージョンを明示的に指定する方法について説明します。 言語バージョンの指定方法 C# コンパイラーのオプションで、言語バージョンを明示的に指定することができます。 特に何も指定しなかった場合、後述するdefaultに当たる挙動をします。 言語バージョンは、Visual Studio 上で行う場合、プロジェクトのプロパティを開いて、以下の場所から設定できます。...
View ArticleC# 8.0 の新機能
Ver. 8.0 随時更新。 予定: https://github.com/ufcpp/UfcppSample/issues/208 Visual Studio 2019 のリリース時点では、C# 8.0 はプレビュー版という扱いになります 予定している機能も全ては実装されておらず、実装されている機能も自己責任での利用をお願いします プレビューでもいいので C# 8.0...
View Articleインデックス/範囲処理
概要 Ver. 8.0 C# 8.0 で、配列などに対して以下のような書き方をできるようになります。 a[^i] で「後ろからi番目の要素」を参照 a[i..j] で「i番目からj番目の範囲」を参照 例えば、以下のような書き方で配列の前後1要素ずつを削ったものを得ることができます。 using System; class Program { static void Main() { var a =...
View Articleパターン ベースな構文
概要 C# の言語機能のいくつか(というか結構多くのもの)は、「所定のパターンを満たしている任意の型に使える」というものになっています。 そういう構文を指して「パターン ベース」(pattern-based)な構文と言ったりします。 本項では、パターン ベースにすることのメリットや、 実際にパターン ベースになっている構文について紹介します。 パターン ベース 例えば C# 3.0...
View Article非同期ストリーム
概要 Ver. 8.0 C# 8.0 で、非同期メソッドが大幅に拡張されます。 一連のデータ(data stream)を、非同期に生成(イテレーター)して非同期に消費(foreach)する機能なので、これらを合わせて非同期ストリーム(async stream)と呼ばれます。 await using (予定) await using await foreach (予定) await foreach...
View Articlenull 許容参照型
概要 Ver. 8.0 C# くらいの世代(1990年代後半~2000年代前半)のプログラミング言語では、 参照型には null が「つきもの」で、不可避なものでした。 (参考: 「null参照問題」。) ただ、2010年代ともなると、「つきもの」として惰性で null を認めるのはよくないとされています。 C# でも、少なくとも「意図して null...
View Article[雑記] 型の決定
概要 C# の変数や式はそれぞれが「型」を持っています。 例えば int x; として宣言した変数 x は int 型になりますし、"abc" という式(文字列リテラルも式の一種)は string 型になります。 そして、代入(=)などの処理では、左右両辺の型が一致しないとコンパイル時にエラーを起こします。 例えば以下のコードはコンパイルできません。 int x = "abc";...
View ArticleC# 9.0 の新機能
Ver. 9.0 リリース時期 未定(おそらく .NET 5 ど同じ 2020/11) 同世代技術 .NET 5 要約・目玉機能 .NET 5 Preview 2 (2020/3)頃から、C# 9.0 機能もちらほらプレビュー実装され始めました。 プレビュー状態なので言語バージョンに preview の指定が必要です。 執筆予定: C# 9.0 トラッキング issue
View Articleエントリー ポイント
概要 実行可能なプログラムを書くとき、最初に呼び出される処理をエントリー ポイント(entry point: 入場地点、入り口)と言います。 C# の場合、通常、Main という名前の静的メソッドを1個だけ書くことで、このメソッドがエントリー ポイントになります。 また、複数の Main メソッドを書いてそのうちの1つをエントリー ポイントに選ぶ方法があったり、 C# 9.0 からはトップ レベル...
View Articleコード解析とコード生成
概要 C# コンパイラーなどを含むいわゆる「開発ツール」にとって重要なことは開発者の生産性を高めることです。 開発ツールが発展してきた現在、コンパイラーの仕事は多岐にわたります。 例えば、以下のようなことをしたいという要求があったりします。 コード解析 (analyzer): 人的ミスを生みそうなコードははじく。場合によってはその修正方法も提示する(fixer) コード生成...
View Articleモジュール初期化子
概要 Ver. 9 プログラムの実行時、最初に1回だけ呼び出したい処理が必要になることがあります。 「静的コンストラクター」で説明しているように、この静的コンストラクターという機能を使っても「最初に1回だけ呼ばれる」ということができますが、C# 9.0 ではモジュール初期化子という書き方もできるようになりました。 モジュール初期化子...
View Articleレコード型
概要 C# 9.0 で、レコード型(records)という新しい種類の型が追加されました。 record (記録)という名前通り、データの読み書きに使うことを意図した型です。 例えば以下のような書き方で、「Name という文字列と Birthday という日付」を読み書きできます。 using System; record Person(string Name, DateTime...
View ArticleC# 10.0 の新機能
Ver. 10.0 ※ 2021/7/24 現在、プレビュー版です。 リリース時期 2021/? 同世代技術 .NET 6.0 Visual Studio 2022 要約・目玉機能 執筆予定: C# 10.0 トラッキング issue
View Article[雑記] コンパイル結果に影響を及ぼす属性
概要 「属性」の説明を「動的な処理」に並べているように、 多くの場合(特に属性を自作する場合)、 属性はリフレクションを使って実行時に型情報から読みだして使うものです。 (動的な処理自体、うちのサイト内では結構後半での説明なので、属性自体についての説明も後々になります。) ところが、いくつかの属性は C# コンパイラー自体が解釈して、 コンパイル結果に影響を及ぼします。 予約属性...
View ArticleC# 10.0 の補間文字列の改善
概要 Ver. 10 C# 10.0 で、補完文字列(interpolated string)のコンパイル結果に変更が掛かって、 これまでよりもかなり高速化されました。 詳細は気にせず単に高速化の恩恵だけを受けたい場合、 言語バージョン、SDK バージョンを C# 10.0/.NET 6.0 にアップデートして再コンパイルするだけで速くなります。 一方、本項では、 C# 9.0...
View ArticleC# 11.0 の新機能
Ver. 11.0 ※ 2022/5/4 現在、プレビュー版です。 リリース時期 2022/? 同世代技術 .NET 7.0 要約・目玉機能 執筆予定: C# 11.0 トラッキング issue その他 ジェネリックな属性 属性をジェネリック クラスにできるようになりました。 // 属性クラスをジェネリックにできるように。 class TypeConverter<T> :...
View Article【Generic Math】 C# 11 での演算子の新機能
概要 Ver. 11 C# 11 で、数値型の演算子関連で3つ新機能が追加されています。 符号なし右シフト checked 演算子オーバーロード シフト演算子の右オペランドの制限撤廃 背景: Generic Math C# 11 / .NET 7 でインターフェイスの静的メンバーを仮想・抽象にできる (static abstract members in interfaces)ようになります。...
View Articlefile ローカル型
Ver. 11 C# 11 で、file という修飾子を使って「書いたファイル内からだけアクセスできる型」を作れるようになりました。 これを file ローカル型 (file-local type)と言います。 例えば、あるファイルに以下のようなコードを書いたとします。 1.M(); file static class Extensions { public static void M(this...
View Article関数ポインター
概要 Ver. 9 関数ポインターとは、メモリ上でメソッドなどの命令列が入ってるアドレスを指すポインターで、 「そのアドレスにジャンプすることでメソッド呼び出しが実現されている」みたいなものです。 .NET の内部的にはこれまでも関数ポインターがあったんですが、 それを C# から効率的に呼ぶ手段がありませんでした。 これに対して、C# 9 では delegate*...
View Article[雑記] 明確な代入ルール
概要 C# には「明確な代入(definite assignment)ルール」と呼ばれる、未初期化変数を避ける仕組みがあります。 未定義動作問題 大昔のプログラミング言語では、 変数に対して誰も何の値も代入していないことで、不定な値が返ってくるということがありました。 不定な値が得られてしまうことで、未定義な動作になります。...
View ArticleC# 12.0 の新機能
Ver. 12.0 ※ 2023/6/21 現在、プレビュー版です。 リリース時期 2023/? 同世代技術 .NET 8.0 執筆予定: C# 12.0 トラッキング issue プライマリ コンストラクター 通常のクラス、構造体に対してプライマリ コンストラクターが使えるようになりました。 class A(int x) { public int X { get; } = x; }...
View Article[雑記] InlineArray
概要 Ver. 12 .NET 8 で、 InlineArray 属性 (System.Runtime.CompilerServices 名前空間) というものが入りました。 基本的には .NET ランタイム側の機能ですが、 いくつか、C# 側にもこの InlineArray 向けの特殊対応が入っています。 ちなみに、この機能は現状、 コレクション式の内部実装にこそ使っていますが、...
View Articleコレクション式
概要 Ver. 12 C# 12 で、[] 記号を使って配列などの初期化ができるようになりました。 配列だけではなく、コレクション(List<T> 型など)、Span<T> なども全く同じ書き方で初期化できます。 これをコレクション式(collection expression)と言います。 using System.Collections.Immutable; int[]...
View ArticleC# 13.0 の新機能
Ver. 12.0 ※ 2024/7/6 現在、プレビュー版です。 リリース時期 2024/11 同世代技術 .NET 9.0 執筆予定: C# 13.0 トラッキング issue その他 \e (エスケープ文字のエスケープ シーケンス) 文字・文字列リテラル中のエスケープ シーケンスに \e (U+001B、エスケープ文字)が追加されました。 例えば、コンソール...
View Article型の分割定義 (partial)
概要 Ver. 2.0 C# 2.0 で、partial 修飾子を付けることで、クラスや構造体、インターフェイスを複数のファイルに分けて型を定義できるようになりました。 この partial によるファイルの分割は、 「片方のファイルを手書き、もう片方のファイルを開発ツールなどによって自動生成」みたいな状況を想定しています。...
View Article