タイトル: 文法
SEOタイトル: C# 言語基本文法完全ガイド (var/$文字列補間/null安全/records)
| この記事の要点 |
|
最小プログラム (C# 9+ top-level)
// Program.cs (C# 9+ top-level statements)
Console.WriteLine("Hello, World!");
int n = 10;
Console.WriteLine($"n = {n}");
従来は次のように書く必要がありました:
using System;
namespace HelloApp
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello, World!");
}
}
}
変数宣言と型推論
int n = 10;
string s = "hello";
double pi = 3.14;
bool flag = true;
char c = 'A';
// 型推論 (var)
var name = "Taro"; // string
var list = new List{1, 2, 3}; // List
var dict = new Dictionary();
// 定数 (const は コンパイル時定数)
const int MAX = 100;
// 読み取り専用 (実行時に決まる)
readonly DateTime startedAt = DateTime.Now;
文字列補間 ($ プレフィックス)
string name = "Taro";
int age = 30;
// $ で補間
string s1 = $"Hello, {name}! Age = {age}";
// 書式指定
double price = 1234.5;
Console.WriteLine($"price = {price:N2}"); // price = 1,234.50
Console.WriteLine($"date = {DateTime.Now:yyyy/MM/dd}");
// 複数行 (verbatim + 補間)
string sql = $@"
SELECT * FROM users
WHERE name = '{name}'
AND age > {age}";
// C# 11+ raw string literals
string json = $"""
{
"name": "{name}",
"age": {age}
}
""";
null 安全演算子
string? maybeNull = GetName(); // C# 8+ nullable reference types
// ?. null 条件演算子
int? length = maybeNull?.Length; // null なら null
// ?? null 合体演算子
string name = maybeNull ?? "anonymous";
// ??= null 代入演算子
maybeNull ??= "default"; // null の場合だけ代入
// ! null 抑制 (上級者向け)
int len = maybeNull!.Length; // 「null じゃないと断言」
// 例
User? user = await db.FindAsync(id);
string city = user?.Address?.City ?? "unknown";
Pattern Matching (C# 7+)
// is 型パターン
if (obj is string s)
{
Console.WriteLine(s.Length);
}
// switch 式 (C# 8+)
string category = item switch
{
Book b when b.Pages > 1000 => "thick",
Book => "book",
Music m => $"music ({m.Artist})",
null => "none",
_ => "other",
};
// Property pattern (C# 8+)
string description = user switch
{
{ Age: > 18, IsActive: true } => "active adult",
{ Age: <= 18 } => "minor",
_ => "unknown",
};
// List pattern (C# 11+)
int[] arr = { 1, 2, 3 };
if (arr is [1, _, 3]) { /* 真ん中は何でも */ }
records (C# 9+)
// 不変データクラス
public record User(string Name, int Age);
var u = new User("Taro", 30);
Console.WriteLine(u); // User { Name = Taro, Age = 30 }
Console.WriteLine(u == new User("Taro", 30)); // True (値比較)
// with 式で複製しつつ変更
var older = u with { Age = 31 };
// C# 10+ record struct (値型)
public record struct Point(int X, int Y);
init-only setters / required (C# 9+ / 11+)
public class User
{
public required string Name { get; init; } // C# 11+
public int Age { get; init; }
}
// オブジェクト初期化子で設定後は変更不可
var u = new User { Name = "Taro", Age = 30 };
// u.Name = "X"; ❌ コンパイルエラー
// required を忘れるとエラー
var bad = new User { Age = 30 }; // ❌ Name 必須
global using / file-scoped namespace
// GlobalUsings.cs (C# 10+)
global using System;
global using System.Collections.Generic;
global using System.Linq;
// → 全ファイルで自動 using
// MyClass.cs - ファイル全体が namespace 直下
namespace MyApp.Services;
public class UserService
{
// ...
}
Java / Kotlin との比較
| 項目 | C# | Java | Kotlin |
|---|---|---|---|
| 型推論 | var n = 10 | var n = 10 (Java 10+) | val n = 10 |
| 不変 | readonly / init | final | val |
| null 安全 | ?. ?? | Optional | ?. ?: |
| 文字列補間 | $"{x}" | String.format | "${x}" |
| データクラス | record | record (Java 14+) | data class |
| top-level コード | ✅ C# 9+ | ❌ | ✅ |
例外処理
try
{
var content = File.ReadAllText("data.txt");
}
catch (FileNotFoundException ex) when (ex.FileName.EndsWith(".txt"))
{
// when 句で追加条件 (フィルタ)
Console.WriteLine("テキストファイルなし");
}
catch (Exception ex)
{
Console.WriteLine($"エラー: {ex.Message}");
throw; // 再 throw (スタック維持)
}
finally
{
// 必ず実行
}
// using 宣言 (C# 8+)
using var file = File.OpenRead("data.txt");
// メソッド終了時に自動 Dispose
FAQ
Q: var を使うべきか型を書くべきか?
A: マイクロソフト推奨は「右辺から型が自明な場合 var、API 戻り値などで型が不明瞭なら明示」。チーム規約に従う。
Q: string と String どちらを使う?
A: 同じ型のエイリアス。ローカル変数は小文字 string、String.IsNullOrEmpty のようなクラスメソッド呼び出しは大文字、が慣習。
Q: Nullable Reference Types を有効にすべき?
A: 新規プロジェクトでは 推奨。NullReferenceException を激減できます。