rksoftware

Visual Studio とか C# とかが好きです

C# 2.0 以降の新機能の確認 - C# 9.0 - localsinit フラグの出力を抑制する

C# 2.0 以降の新機能を一つづつ確認していきます。
以前に一度行ったのですが、公式ドキュメント再編でリンク切れしているところを見つけてしまったので。今ならもっと簡潔なサンプルが欠けるところもあるだろうし、せっかくなので今もう一度確認して行きます。

localsinit フラグの出力を抑制する

 https://docs.microsoft.com/ja-jp/dotnet/api/system.runtime.compilerservices.skiplocalsinitattribute
 System.Runtime.CompilerServices.SkipLocalsInit 属性がついている場合、ゼロ初期化がなされずパフォーマンスが向上する場合がある。

[System.Runtime.CompilerServices.SkipLocalsInit]
unsafe static void Main(string[] args)
{
    int i;
    int* j = &i;
    Console.WriteLine(*j);  // 0 でない値
}

C# 2.0 以降の新機能の確認 - C# 9.0 - 関数ポインター

C# 2.0 以降の新機能を一つづつ確認していきます。
以前に一度行ったのですが、公式ドキュメント再編でリンク切れしているところを見つけてしまったので。今ならもっと簡潔なサンプルが欠けるところもあるだろうし、せっかくなので今もう一度確認して行きます。

関数ポインター

 [ 良いリンクを見つけられませんでした ]
 関数ポインター。ポインターというからには unsafe で書く必要がある。

unsafe
{
    // delegate* で関数ポインターを格納する変数を宣言
    // &string.IsNullOrEmpty とメソッド名に & をつけることで関数のポインターを取得している
    delegate*<string, bool> f = &string.IsNullOrEmpty;
    // 普通の関数呼び出しの構文で呼べる
    Console.WriteLine(f(""));  // True
    Console.WriteLine(f("a")); // False
}

C# 2.0 以降の新機能の確認 - C# 9.0 - ネイティブ サイズの整数

C# 2.0 以降の新機能を一つづつ確認していきます。
以前に一度行ったのですが、公式ドキュメント再編でリンク切れしているところを見つけてしまったので。今ならもっと簡潔なサンプルが欠けるところもあるだろうし、せっかくなので今もう一度確認して行きます。

ネイティブ サイズの整数

 https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/builtin-types/nint-nuint
 nin と nuint という型が追加された。32 ビット環境では 32 ビット整数型に 64 ビット環境では 64 ビット整数型になるとのこと。

// nint のサイズを測ってみる
Console.WriteLine($"int   : Type = {typeof(int).FullName,14} : MinValue = {int.MinValue,20} : MaxValue : {int.MaxValue,20}");
Console.WriteLine($"nint  : Type = {typeof(nint).FullName,14} : MinValue = {nint.MinValue,20} : MaxValue : {nint.MaxValue,20}");
Console.WriteLine($"long  : Type = {typeof(long).FullName,14} : MinValue = {long.MinValue,20} : MaxValue : {long.MaxValue,20}");
// 64 ビット (x64) の場合
// int   : Type =   System.Int32 : MinValue =          -2147483648 : MaxValue :           2147483647
// nint  : Type =  System.IntPtr : MinValue = -9223372036854775808 : MaxValue :  9223372036854775807
// long  : Type =   System.Int64 : MinValue = -9223372036854775808 : MaxValue :  9223372036854775807
// 32 ビット (x86) の場合
// int   : Type =   System.Int32 : MinValue =          -2147483648 : MaxValue :           2147483647
// nint  : Type =  System.IntPtr : MinValue =          -2147483648 : MaxValue :           2147483647
// long  : Type =   System.Int64 : MinValue = -9223372036854775808 : MaxValue :  9223372036854775807

C# 2.0 以降の新機能の確認 - C# 9.0 - パターン マッチングの拡張機能

C# 2.0 以降の新機能を一つづつ確認していきます。
以前に一度行ったのですが、公式ドキュメント再編でリンク切れしているところを見つけてしまったので。今ならもっと簡潔なサンプルが欠けるところもあるだろうし、せっかくなので今もう一度確認して行きます。

パターン マッチングの拡張機能

 https://docs.microsoft.com/ja-jp/dotnet/csharp/tutorials/pattern-matching#add-peak-pricing
 パターンマッチングが強化された。

// a に関する条件を a を何度も書かずに
int a = new Random().Next();
if (a is (> 1 and < 3) or (> 100 and < 200)) Console.WriteLine("match");

// 否定は not。null のチェックに使うのがおすすめらしい
string b = null;
if (b is not null) Console.WriteLine("not null");

// switch 式ですごいことに
string Method(object arg)
{
    var text = arg switch
    {
        > 1 => "> 1",
        "a" => "a",
        not null => "not null",
        _ => "null",
    };
    return text;
}
Console.WriteLine(Method(0));

C# 2.0 以降の新機能の確認 - C# 9.0 - 最上位レベルのステートメント

C# 2.0 以降の新機能を一つづつ確認していきます。
以前に一度行ったのですが、公式ドキュメント再編でリンク切れしているところを見つけてしまったので。今ならもっと簡潔なサンプルが欠けるところもあるだろうし、せっかくなので今もう一度確認して行きます。

最上位レベルのステートメント

 https://docs.microsoft.com/ja-jp/dotnet/csharp/programming-guide/main-and-command-args/top-level-statements
 C# はプロジェクト内のどれかのクラスの static void Main(string[] args) メソッドから実行されるものだったが、クラスを書かずにいきなりコードが書けるようになった。

using System;

// いきなりコード
Console.WriteLine("Hello World!");

// コンソールアプリのコマンドライン引数は args という名前で使える
Console.WriteLine(string.Join(", ", args));

C# 2.0 以降の新機能の確認 - C# 9.0 - init 専用セッター

C# 2.0 以降の新機能を一つづつ確認していきます。
以前に一度行ったのですが、公式ドキュメント再編でリンク切れしているところを見つけてしまったので。今ならもっと簡潔なサンプルが欠けるところもあるだろうし、せっかくなので今もう一度確認して行きます。

init 専用セッター

 https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/keywords/init
 初期化時にだけ値をセットできる素敵なプロパティを作れます。もっとわかりやすく簡単に言うと、イミュータブルなオブジェクトが作れる。
 初期化とは
 ・コンストラクタ
 ・初期化子 ( new XXXX { プロパティ名 = 値} )
 ・with 式 ( 型名 新しい変数 = 変数 with { プロパティ名 = 値 }; )

var saitama1 = new Saitama { InitProperty = "" };   // これはエラーにならない。初期化専用なので。うれしい
var saitama2 = saitama1 with { InitProperty = "" }; // これはエラーにならない。初期化専用なので。うれしい
//saitama2.InitProperty = "";                       // これはエラー。初期化専用なので。うれしい

public record Saitama
{
    // プロパティの宣言で普段 set と書いている所を init と書くと使える
    public string InitProperty { get; init; }
    public Saitama() => InitProperty = "value5";
}

C# 2.0 以降の新機能の確認 - C# 9.0 - レコード

C# 2.0 以降の新機能を一つづつ確認していきます。
以前に一度行ったのですが、公式ドキュメント再編でリンク切れしているところを見つけてしまったので。今ならもっと簡潔なサンプルが欠けるところもあるだろうし、せっかくなので今もう一度確認して行きます。

レコード

 https://docs.microsoft.com/ja-jp/dotnet/csharp/programming-guide/classes-and-structs/records
 GetHashCode()ToString()== なんかをいい感じに勝手に実装してくれる素敵な型。値を表現するクラスをいい感じに作ってくれます。プロパティもいい感じに作ってくれるのも魅力。

// 引数 string Value を持つコンストラクタが作られる
var saitama = new Saitama("せんべい");
// 引数と同名のプロパティが自動で作られて初期化も行われる
Console.WriteLine(saitama.Value);  // せんべい
// 良い感じの ToString も自動で実装
Console.WriteLine(saitama);  // Saitama { Value = せんべい }

// class の代わりに record と書く
// 引数を書くとコンストラクタとプロパティも作られる
public record Saitama(string Value)
{
}