rksoftware

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

C# 2.0 以降の新機能の確認 - C# 7.2 - メソッド戻り値の ref readonly 修飾子

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

メソッド戻り値の ref readonly 修飾子

 https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/keywords/ref#reference-return-values
 読み取り専用の参照を戻り値にできる

var val = 0;
// ref var rval =  ref Func(ref val);       ← ref readonly 戻り値は ref readonly でないとエラー
ref readonly var rval = ref Func(ref val);
// rval = 10;                               ← ref readonly 変数を変更するコードはエラー

// ref readonly 戻り値の関数
ref readonly int Func(ref int val) { return ref val; }

衝撃の事実! 埼玉に対する世間の認識は意外な結果に

衝撃の事実です。

正直、3 番目の選択肢が圧倒的だと確信していたのですが...

一番残念な、世間は埼玉に無関心という結果に。まあリアルでは、埼玉は降り立つ機会はないといわれているくらい私でも知っていましたけど。

いかがでしたか?

C# 2.0 以降の新機能の確認 - C# 7.2 - パラメーターの in 修飾子

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

パラメーターの in 修飾子

 https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/keywords/in-parameter-modifier
 引数を読み取り専用にできる。

// in 引数を持つ関数
void Func(St stNotIn, in St stIn)
{
    stNotIn = new();        // in 引数でないので変数を変更可能
    stNotIn.Val = new();    // in 引数でないのでフィールド変更可能
    // stIn = new();        // これはエラー in 引数は変数を変更できない
    // stIn.Val = new();    // これはエラー in 引数はフィールドを変更できない
}

// 構造体
struct St { public int Val; }

C# 2.0 以降の新機能の確認 - C# 7.2 - readonly 構造体

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

readonly 構造体

 https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/builtin-types/struct#readonly-struct
 ・readonly struct は readonly なメンバーしか持てない
 ・保持する値が変更されない(値が変更可能になる定義が禁止される)

readonly struct SA
{
    public readonly int PA;
    // public int PB; ← readonly 構造体なので これはエラー
    public SA(int a)
    {
        PA = a;
    }
    // public void Set(SA a) { this = a; } ← readonly 構造体なので これはエラー
}

struct SB
{
    public readonly int PA;
    public int PB; // ← readonly 構造体でないので これは OK
    public SB(int a, int b)
    {
        PA = a;
        PB = b;
    }
    public void Set(SB a) { this = a; } // ← readonly 構造体でないので これは OK
}

C# 2.0 以降の新機能の確認 - C# 7.2 - Span<T> 構造体

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

Span 構造体

 https://docs.microsoft.com/ja-jp/dotnet/standard/memory-and-spans/memory-t-usage-guidelines
 配列(など)の一部の範囲を切り出して値の参照を持てる。

var ary = Enumerable.Range(1, 10).ToArray();
var span = new Span<int>(ary, 2, 3);
var readonlySpan = (ReadOnlySpan<int>)span;
for (int i = 0; i < readonlySpan.Length; i++)
    Console.WriteLine(readonlySpan[i]);
// 3
// 4
// 5 と出力される
span[0] = 11;
Console.WriteLine(readonlySpan[0]); // コピーでなく参照を持っているため 11 と出力される
// readonlySpan[0] = 21; ← ReadOnlySpan<T> なのでこれはエラー
ary[2] = 31;
Console.WriteLine(readonlySpan[0]); // コピーでなく参照を持っているため  31 と出力される

C# 2.0 以降の新機能の確認 - C# 7.1 - “既定” リテラル

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

“既定” リテラル

 https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/operators/default#default-literal
 型を推論できる個所では、規定値を設定する際の default(型名) の型名を省略できるようになりました。

static void Main(string[] args)
{
    // これまでは default(int) の様に型の指定が必要だった
    int i = default;
    Console.WriteLine(i);

    // 戻り値の型から推論可能
    Console.WriteLine(D());

    // 戻り値の型から推論可能
    Func<string> l = () => default;
    Console.WriteLine(l() == null);

    // 変数の型から推論可能
    string s = default;
    // ?? でも
    Console.WriteLine(s ?? default);
    // 三項演算でも
    Console.WriteLine(s == null ? default : s);
}

static DateTime D()
{
    // 戻り値の型から推論可能
    return default;
}

C# 2.0 以降の新機能の確認 - C# 7.1 - ジェネリックによるパターン マッチング

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

ジェネリックによるパターン マッチング

 https://docs.microsoft.com/ja-jp/dotnet/csharp/pattern-matching
 ※リンクは掲載していますが、この機能についての言及はありません。言及のあるページは将来なくなりそうなページのため掲載していません。
 ジェネリック型の引数に対してのパターンマッチングが可能になりました。以前は、下記の例では、Match メソッドの引数 a に対するパターンマッチングはコンパイルエラーでした。

static async Task Main(string[] args)
{
static void Main(string[] args)
{
    Console.WriteLine(Match("test"));   // string
}

static string Match<T>(T a)
{
    switch (a)
    {
        case int v:
            return "int";
        case string v:
            return "string";
        default:
            return "default";
    }
}