目次

キーワード

概要

変数と式」で少し言葉としては出しましたが、 プログラミング言語の構文には大きく分けて式(expression)とステートメント(statement: 文、平叙文)という2種類のものがあります。

最近のプログラミング言語ほど式の比率が高くなっています。 C#でも、バージョンを重ねるごとに、式になっている構文が増えています。

式とステートメント

基礎」と「構造化」のセクションで、C#の式とステートメントの結構な割合を紹介しました。ここで1度、この式とステートメントの区別についての話をしておきます。

式とステートメントは、大まかに言うと以下のようなものです。

  • (expression): 割とどこにでも書ける代わりに戻り値が必須
  • ステートメント(statement): 戻り値がなくてもいい代わりに書ける場所がブロック内に限られている

式(expression: 表現、語句、(数学用語で)式)は、 以下のような特徴がある構文です。

  • 書ける場所が多い
  • 必ず何かしらの値を返す
  • いろいろ組み合わせて書ける

式

名前からして数学用語の「式」がもとになっていますが、 名前通り、x + 1 というような数式みたいなものが多いです。 いかにも数式っぽいもの以外にも、x.PropertyNameawait x なども式です。

組み合わせて書けるというのは、例えば、 await Task.Run(() => new[] { "abc" }[0].Length) みたいなものも式になっています。 この式は、以下のような式を組み合わせた結果です。

組み合わせて書ける分、1つ1つはシンプルなものが多いです。

ステートメント

一方、ステートメント(statement: 文、声明)は、 以下のような特徴がある構文です。

  • ブロックの内側にしか書けない
  • 組み合わせが効かない
  • 1つ1つが大きい
  • 戻り値がない

ステートメント

if などの条件分岐や、for などの反復処理をはじめ、制御構文が多いです。

式との比較をまとめます。

ステートメント(文)
数式っぽい構文が多い 制御構文が多い
どこにでも書ける ブロック内(関数本体の中など)にしか書けない
いろいろ組み合わせて書ける そんなに組み合わせの幅はない
戻り値が必須 戻り値がない

式やステートメント(文)の一覧は、「C# の式と文の一覧」にまとめてあります。

式は増加傾向にある

近年では、ステートメントよりも式の方が好まれる傾向があります。 C# でも、バージョンアップを重ねるたびに、式の比率が増えています。

ステートメントだとそもそも書けない場所も多くて困ることがあります。 なので、以前でもステートメントを使って書けたものを、 式で書き直せるような構文の追加が結構あります。 また、式を使いやすくするような構文も増えています。

以下に例を挙げていきます。

C# 2.0
構文 新しい書き方 以前の書き方
null 合体演算子
var y = x ?? "";
var y = x;
if (y == null) y = "";
匿名メソッド式
static void Main()
{
    Func<int, int> f = delegate (int x)
    {
        return x * x;
    };
}
static void Main()
{
    Func<int, int> f = M;
}
 
static int M(int x)
{
    return x * x;
}
C# 3.0
構文 新しい書き方 以前の書き方
オブジェクト初期化子
var p = new Point { X = 1, Y = 2 };
var p = new Point();
p.X = 1;
p.Y = 2;
コレクション初期化子
var list = new List<int> { 1, 2 };
var list = new List<int>();
list.Add(1);
list.Add(2);
ラムダ式
Func<int, int> f = x => x * x;
Func<int, int> f = delegate (int x) { return x; };
C# 6.0
構文 新しい書き方 以前の書き方
null条件演算子
var y = x?.Length;
int? y;
if (x == null) y = null;
else y = x.Length;
インデックス初期化子
var dic = new Dictionary<string, int>
{
    ["one"] = 1,
    ["two"] = 2
};
var dic = new Dictionary<string, int>();
dic["one"] = 1;
dic["two"] = 2;
式形式メンバー
static int M(int x) => x * x;
static int M(int x)
{
    return x * x;
}
C# 7.0
構文 新しい書き方 以前の書き方
式形式メンバー(追加)
struct Point
{
    public int X, Y;
    public Point(int x, int y)
        => (X, Y) = (x, y);
}
struct Point
{
    public int X, Y;
    public Point(int x, int y)
    {
        X = x;
        Y = y;
    }
}
throw 式
static string M(string s)
        => s ?? throw new Exception();
static string M(string s)
{
    if (s == null) throw new Exception();
    return s;
}
出力変数宣言
static int M(string s)
         => int.TryParse(s, out var x) ? x : -1;
static int M(string s)
{
    int x;
    if (int.TryParse(s, out x)) return x;
    else return -1;
}
宣言パターン
static int M(object x)
        => x is string s ? s.Length : 0;
static int M(object x)
{
    var s = x as string;
    if (s != null) return s.Length;
    return 0;
}
C# 8.0
構文 新しい書き方 以前の書き方
switch 式
static int M(int? x, int? y)
    => (x, y) switch
    {
        (null, null) => 0,
        (null, { }) => 1,
        ({ }, null) => -1,
        (int i, int j) => i.CompareTo(j),
    };
static int M(int? x, int? y)
{
    if (x is int i)
    {
        if (y is int j) return i.CompareTo(j);
        else return -1;
    }
    else
    {
        if (y is int) return 1;
        else return 0;
    }
}

更新履歴

ブログ