SE(たぶん)の雑感記

一応SEやっている筆者の思ったことを書き連ねます。会計学もやってたので、両方を生かした記事を書きたいと考えています。 でもテーマが定まってない感がすごい。

C#の復習 - C#7.1編

また前回記事の続きです。C#は5.0,6.0 みたいに1ずつバージョンが上がっていたのですが、なぜか7系だけ7.1, 7.2, 7.3みたいな上がり方をしています。なので記事を分けました。

今回はC# 7.1を見ていきます。下記ページを見ながら書いていきます。

docs.microsoft.com

C# バージョン 7.1

async Main メソッド

リンク

Mainメソッド(プログラムのエントリポイントなるメソッド)にasyncを付けられるようになりました。
= Mainメソッドでawaitキーワードを使用できるようになりました。

using System;
using System.Threading.Tasks;

namespace CSharp71
{
    class Program
    {
        static async Task Main(string[] args)
        {
            await Task.Run(() => Console.WriteLine("Run async method."));
            Console.WriteLine("Hello World!");
        }
    }
}

Mainメソッドが満たすべき要件はこちらに記載があります。以下の二つが増えています。

Main の戻り値の型は、void または int のいずれかになります。C# 7.1 以降では Task または Task になる場合もあります。

Main で Task または Task が返される場合に限り、Main の宣言に async 修飾子を含めることができます。

ちなみに、C#7.0以前のように戻り値Taskを認めないバージョンで戻り値をTaskにしたMainメソッドを定義した場合、プロジェクトファイルからMainメソッドの条件を満たすメソッドが無くなることから、コンパイルエラーが発生します。発生するエラーはこちらCS5001です。有効なMainメソッドがないよ、というエラーです。

なお、プロジェクトのC#バージョンを指定するには、.csprojファイルにLangVersionの指定を入れます。

例:CSharpSample/CSharp70.csproj at master · piroron/CSharpSample · GitHub

async Mainが書けないのは、コマンドラインアプリでは不便極まりないので、便利になった改訂だなと思いました。

default リテラル

リンク

default演算子は、default(int)のように、括弧で指定した型の初期値を生成するものでした。これが拡張されて、型が推測できる場合は括弧を省略できるようになりました。

class DefaultLiteral
{
    public DefaultLiteral()
    {
        // NG
        // var value = default;

        // OK
        int value = default;
    }
}

特定の条件で戻り値をその型のデフォルト値にする、というケースでコードがちょっと簡潔になるので良いのかなと。

推論されたタプル要素の名前

GitHub Issue

タプルの前に宣言した変数をタプルの要素とした場合、そのままタプル要素の名前として使用できるようにした、ということみたいです。

class TupleInitialize
{
    public TupleInitialize()
    {
        int x = 10;
        Action y = () => Console.WriteLine("Run something.");
        var pair = (x, y);

        pair.y(); // C#7.0だとこれが推論できない
    }
}

C#7.0のソースでも問題なくコンパイル通るようですが…何か間違っているかもしれません。

ジェネリック型パラメーターのパターン マッチ

GitHub Issue

メソッドのパラメータがジェネリック型である場合、パターンマッチングが使えなかった点を修正した、ということです。

以下のメソッドのジェネリック型のTで、パターンマッチングできなかったのを修正したそうです。

private void Run<T>(T value)
{
    switch(value)
    {
        case string v:
            break;
    }
}

C#7.0だとこんなエラーが出ます。内容がすごく親切ですね。

f:id:hiroronn:20201123132132p:plain

これがC#7.1だと問題ないコードになっています。

おわりに

一応一つ一つ見ていきましたが、小規模な改訂でした。メジャーバージョンで追加された機能に対する追加機能、みたいなものがマイナーバージョンで増えていく感じでしょうかね。

あと、このバージョンのソースサンプルは下記に上げています。ほぼ役に立たないと思いますが、参考までに。

github.com