C#解析とは?コード・JSON・ログ・構文解析のやり方を初心者向けに徹底解説
はじめに
C#で開発をしていると、「文字列を数値に解析する」「JSONを解析する」「ログを解析する」「C#コードを解析する」「構文解析を行う」といった表現をよく見かけます。
一口に「C# 解析」といっても、対象によって意味は大きく変わります。たとえば、ユーザーが入力した "123" という文字列を int に変換する処理も解析ですし、APIから受け取ったJSONをクラスに変換する処理も解析です。さらに、ログファイルからエラー情報を取り出したり、C#コードそのものを読み取ってメソッド名を取得したりする処理も解析に含まれます。
この記事では、初心者向けにC#解析の基本から、文字列解析、JSON解析、ログ解析、コード解析、構文解析までを幅広く解説します。実践で使えるサンプルコードも紹介するので、「C#で解析処理を書きたいけれど、何から始めればよいかわからない」という方はぜひ参考にしてください。
1. C#解析とは?初心者がまず押さえるべき基礎知識
1-1. C#における「解析」の意味
C#における「解析」とは、あるデータをプログラムで扱いやすい形に読み解く処理のことです。
たとえば、次のような処理が解析にあたります。
C#string text = "123";
int number = int.Parse(text);
このコードでは、文字列 "123" を整数 123 として読み取っています。人間にとっては "123" が数値であることはすぐにわかりますが、プログラム上では文字列と数値は別の型です。そのため、文字列の内容を読み取り、数値として扱える形に変換する必要があります。
これが基本的な解析です。
また、JSONのような構造化データを読み取る場合も解析と呼びます。
JSON{
"name": "Taro",
"age": 30
}
このJSONをC#のクラスに変換すれば、person.Name や person.Age のように扱えるようになります。これも「JSON解析」です。
1-2. Parse・TryParse・パース・構文解析の違い
C#解析を学ぶと、Parse、TryParse、パース、構文解析といった言葉が出てきます。それぞれの意味を整理しておきましょう。
Parse は、文字列を特定の型に変換するためのメソッドです。
C#int number = int.Parse("100");
TryParse は、解析に失敗しても例外を発生させず、成功したかどうかを true または false で返すメソッドです。
C#bool success = int.TryParse("100", out int number);
「パース」は英語の parse をカタカナにした言葉で、解析すること全般を指します。特にプログラミングでは、文字列やデータを読み取って意味のある構造に変換する処理を指すことが多いです。
一方、「構文解析」は、文字列やコードの文法構造を読み取る処理です。たとえば、C#コードを解析して「これはクラス定義」「これはメソッド定義」「これは変数宣言」と判定するような処理が構文解析です。
つまり、Parse や TryParse は比較的シンプルな型変換で使われることが多く、構文解析はより複雑な文法構造を読み解く処理と考えるとわかりやすいです。
1-3. C#解析でできること
C#では、さまざまな解析処理を実装できます。
代表的なものは次のとおりです。
文字列を数値、日付、真偽値などに解析できます。
C#int age = int.Parse("25");
DateTime date = DateTime.Parse("2026-06-16");
bool enabled = bool.Parse("true");
JSONを解析して、C#のオブジェクトに変換できます。
C#var user = JsonSerializer.Deserialize<User>(json);
ログファイルを解析して、日時、ログレベル、メッセージなどを抽出できます。
C#string[] parts = line.Split(' ');
正規表現を使って、文字列から必要な情報だけを取り出せます。
C#var match = Regex.Match(text, @"\d+");
Roslynを使えば、C#コードそのものを解析できます。
C#var tree = CSharpSyntaxTree.ParseText(code);
このように、C#解析は入力データを理解し、必要な情報を取り出し、プログラムで扱いやすい形にするための重要な技術です。
1-4. 解析処理が必要になる代表的な場面
解析処理は、実務でも非常によく使われます。
たとえば、Webフォームで入力された文字列を数値や日付として扱う場合、文字列解析が必要です。ユーザーが入力した年齢、金額、予約日などは、最初は文字列として受け取られることが多いため、C#の型に変換する必要があります。
APIからJSONを受け取る場合も解析が必要です。Web APIのレスポンスはJSON形式で返されることが多いため、C#のクラスに変換して扱います。
サーバーのログを調査するときも、ログ解析が役立ちます。エラーログから日時やエラー内容を抽出すれば、障害調査や監視に活用できます。
また、コード品質チェックや自動レビューを行う場合は、C#コード自体の解析が必要です。Roslynを使えば、命名規則のチェック、不要なコードの検出、独自ルールによる静的解析なども実装できます。
1-5. 初心者が混同しやすい「変換」「読み取り」「検証」との違い
解析と似た言葉に、「変換」「読み取り」「検証」があります。
「変換」は、ある形式のデータを別の形式に変えることです。たとえば、文字列 "123" を整数 123 にする処理は変換です。ただし、その前提として文字列の内容を数値として理解する必要があるため、解析の一部ともいえます。
「読み取り」は、ファイルや入力値などからデータを取得することです。たとえば、ログファイルの内容を1行ずつ読む処理は読み取りです。ただし、読んだだけでは意味を取り出していないため、解析とは少し異なります。
「検証」は、データが正しい形式かどうかを確認することです。たとえば、入力値が数値として有効かどうかを確認する処理は検証です。
解析は、読み取ったデータの意味を理解し、必要な形に分解・変換・抽出する処理です。実際の開発では、読み取り、検証、変換、解析が組み合わさって使われることが多いです。
2. C#で文字列を解析する基本
2-1. int.Parse・DateTime.Parseなどの基本的な使い方
C#で最も基本的な解析処理は、文字列を別の型に変換することです。
数値を解析する場合は、int.Parse や double.Parse を使います。
C#string text = "123";
int number = int.Parse(text);
Console.WriteLine(number);
日付を解析する場合は、DateTime.Parse を使います。
C#string text = "2026-06-16";
DateTime date = DateTime.Parse(text);
Console.WriteLine(date);
真偽値を解析する場合は、bool.Parse を使います。
C#string text = "true";
bool result = bool.Parse(text);
Console.WriteLine(result);
これらの Parse メソッドは、文字列が正しい形式であることを前提に解析します。そのため、入力値が不正な場合は例外が発生します。
C#int number = int.Parse("abc"); // FormatException
ユーザー入力や外部ファイルのように、内容が必ず正しいとは限らないデータを扱う場合は注意が必要です。
2-2. ParseとTryParseの違い
Parse と TryParse の大きな違いは、解析に失敗したときの動作です。
Parse は失敗すると例外を発生させます。
C#int number = int.Parse("abc");
この場合、"abc" は整数として解析できないため、FormatException が発生します。
一方、TryParse は失敗しても例外を発生させず、戻り値で成功・失敗を判断できます。
C#bool success = int.TryParse("abc", out int number);
if (success)
{
Console.WriteLine($"解析成功: {number}");
}
else
{
Console.WriteLine("解析失敗");
}
TryParse は、解析に成功した場合は true を返し、解析結果を out パラメーターに格納します。失敗した場合は false を返します。
ユーザー入力、CSV、ログ、APIレスポンスなど、外部から来るデータを扱う場合は、基本的に TryParse を使う方が安全です。
2-3. 例外を避けるならTryParseを使うべき理由
Parse を使うと、入力値が不正なときに例外処理が必要になります。
C#try
{
int number = int.Parse("abc");
}
catch (FormatException)
{
Console.WriteLine("数値として解析できませんでした。");
}
この書き方でも動作しますが、通常の入力チェックに例外を使うとコードが読みにくくなります。また、大量データを処理する場合、例外が頻繁に発生するとパフォーマンスにも悪影響を与える可能性があります。
そのため、失敗が想定される解析では TryParse を使うのが一般的です。
C#if (int.TryParse("abc", out int number))
{
Console.WriteLine(number);
}
else
{
Console.WriteLine("数値ではありません。");
}
特に初心者は、「外部入力にはTryParse」と覚えておくと安全です。
2-4. 数値・日付・真偽値を解析するサンプルコード
数値、日付、真偽値を安全に解析するサンプルです。
C#string numberText = "100";
string dateText = "2026-06-16";
string boolText = "true";
if (int.TryParse(numberText, out int number))
{
Console.WriteLine($"数値: {number}");
}
else
{
Console.WriteLine("数値の解析に失敗しました。");
}
if (DateTime.TryParse(dateText, out DateTime date))
{
Console.WriteLine($"日付: {date}");
}
else
{
Console.WriteLine("日付の解析に失敗しました。");
}
if (bool.TryParse(boolText, out bool flag))
{
Console.WriteLine($"真偽値: {flag}");
}
else
{
Console.WriteLine("真偽値の解析に失敗しました。");
}
TryParse を使うことで、入力値が不正でもプログラムが突然停止するのを防げます。
日付の形式を厳密に指定したい場合は、DateTime.TryParseExact を使います。
C#string text = "2026/06/16";
bool success = DateTime.TryParseExact(
text,
"yyyy/MM/dd",
null,
System.Globalization.DateTimeStyles.None,
out DateTime date
);
if (success)
{
Console.WriteLine(date);
}
else
{
Console.WriteLine("指定した形式の日付ではありません。");
}
日付解析では、国や環境によって解釈が変わることがあるため、実務では TryParseExact が便利です。
2-5. 解析に失敗する原因と対処法
文字列解析に失敗する主な原因は、形式が期待と違うことです。
たとえば、数値解析では次のような文字列が失敗しやすいです。
C#int.Parse("abc");
int.Parse("");
int.Parse("12.5");
int.Parse("1,000");
"abc" は数値ではありません。空文字も数値ではありません。"12.5" は小数なので int では解析できません。"1,000" はカルチャや設定によっては解析に失敗する場合があります。
対処法としては、まず TryParse を使うことが基本です。
C#if (!int.TryParse(input, out int value))
{
Console.WriteLine("入力値が整数ではありません。");
}
小数を扱うなら double.TryParse や decimal.TryParse を使います。
C#if (decimal.TryParse("12.5", out decimal price))
{
Console.WriteLine(price);
}
日付の場合は、期待する形式を明確にして TryParseExact を使うと安全です。
C#DateTime.TryParseExact(
input,
"yyyy-MM-dd",
null,
System.Globalization.DateTimeStyles.None,
out DateTime date
);
解析に失敗する可能性があるデータでは、「失敗する前提」でコードを書くことが重要です。
3. C#でJSONを解析する方法
3-1. C#でJSON解析が必要になるケース
C#でJSON解析が必要になる場面は非常に多いです。
代表的なのは、Web APIから受け取ったレスポンスを処理する場合です。APIの多くはJSON形式でデータを返します。たとえば、ユーザー情報、商品情報、天気情報、決済結果などがJSONで返されます。
設定ファイルをJSONで管理する場合もあります。アプリケーションの設定値をJSONファイルに保存し、起動時に読み込むようなケースです。
また、JavaScriptのフロントエンドとC#のバックエンドでデータをやり取りする場合にもJSONがよく使われます。
C#では、JSON解析には主に System.Text.Json または Newtonsoft.Json を使います。現在のC#開発では、標準ライブラリとして使える System.Text.Json がよく利用されます。
3-2. System.Text.Jsonを使ったJSON解析
System.Text.Json は、.NET標準で利用できるJSON処理用の名前空間です。
まず、次のようなJSONを考えます。
JSON{
"Name": "Taro",
"Age": 30
}
このJSONをC#で解析するには、対応するクラスを用意します。
C#public class User
{
public string? Name { get; set; }
public int Age { get; set; }
}
そして、JsonSerializer.Deserialize を使ってJSONをオブジェクトに変換します。
C#using System.Text.Json;
string json = """
{
"Name": "Taro",
"Age": 30
}
""";
User? user = JsonSerializer.Deserialize<User>(json);
if (user != null)
{
Console.WriteLine(user.Name);
Console.WriteLine(user.Age);
}
これがC#における基本的なJSON解析です。
3-3. JsonSerializer.Deserializeでオブジェクトに変換する方法
JsonSerializer.Deserialize<T> を使うと、JSON文字列を指定した型に変換できます。
C#using System.Text.Json;
public class Product
{
public string? Name { get; set; }
public decimal Price { get; set; }
}
string json = """
{
"Name": "Keyboard",
"Price": 4980
}
""";
Product? product = JsonSerializer.Deserialize<Product>(json);
if (product != null)
{
Console.WriteLine($"商品名: {product.Name}");
Console.WriteLine($"価格: {product.Price}");
}
JSONのプロパティ名とC#クラスのプロパティ名が一致していれば、自動的に値が設定されます。
JSONが配列の場合は、リストとして解析できます。
C#using System.Text.Json;
public class User
{
public string? Name { get; set; }
public int Age { get; set; }
}
string json = """
[
{ "Name": "Taro", "Age": 30 },
{ "Name": "Hanako", "Age": 25 }
]
""";
List<User>? users = JsonSerializer.Deserialize<List<User>>(json);
if (users != null)
{
foreach (var user in users)
{
Console.WriteLine($"{user.Name}: {user.Age}");
}
}
APIレスポンスを処理する場合は、このようにクラスを定義してデシリアライズする方法がよく使われます。
3-4. JsonDocument・JsonNodeで柔軟にJSONを読む方法
JSONの構造が固定されていない場合や、一部の値だけ取り出したい場合は、JsonDocument や JsonNode が便利です。
JsonDocument を使う例です。
C#using System.Text.Json;
string json = """
{
"user": {
"name": "Taro",
"age": 30
}
}
""";
using JsonDocument document = JsonDocument.Parse(json);
JsonElement root = document.RootElement;
string name = root.GetProperty("user").GetProperty("name").GetString() ?? "";
int age = root.GetProperty("user").GetProperty("age").GetInt32();
Console.WriteLine(name);
Console.WriteLine(age);
JsonDocument は読み取り専用で、効率よくJSONを扱いたい場合に向いています。
一方、JsonNode はより柔軟にJSONを扱えます。
C#using System.Text.Json.Nodes;
string json = """
{
"name": "Taro",
"age": 30
}
""";
JsonNode? node = JsonNode.Parse(json);
string? name = node?["name"]?.GetValue<string>();
int? age = node?["age"]?.GetValue<int>();
Console.WriteLine(name);
Console.WriteLine(age);
JSONの一部だけを取り出したい場合は、クラスを作らずに JsonDocument や JsonNode を使うと簡潔に書けます。
3-5. Newtonsoft.Jsonとの違い
C#でJSON解析といえば、以前からよく使われているのが Newtonsoft.Json です。パッケージ名から Json.NET と呼ばれることもあります。
Newtonsoft.Json を使う場合は、次のように書きます。
C#using Newtonsoft.Json;
public class User
{
public string? Name { get; set; }
public int Age { get; set; }
}
string json = """
{
"Name": "Taro",
"Age": 30
}
""";
User? user = JsonConvert.DeserializeObject<User>(json);
System.Text.Json は.NET標準で使えるため、新規開発では導入しやすいです。一方、Newtonsoft.Json は歴史が長く、柔軟な機能や既存プロジェクトでの利用実績が豊富です。
基本的なJSON解析であれば System.Text.Json で十分です。ただし、既存システムで Newtonsoft.Json を使っている場合や、細かい変換ルールが必要な場合は Newtonsoft.Json を選ぶこともあります。
3-6. JSON解析時によくあるエラーと解決策
JSON解析でよくあるエラーのひとつは、JSON形式が壊れているケースです。
C#string json = "{ \"Name\": \"Taro\", ";
このような不完全なJSONを解析しようとすると、例外が発生します。外部から受け取ったJSONを扱う場合は、try-catch で例外処理を行うと安全です。
C#try
{
User? user = JsonSerializer.Deserialize<User>(json);
}
catch (JsonException ex)
{
Console.WriteLine($"JSON解析に失敗しました: {ex.Message}");
}
プロパティ名が一致しない場合も注意が必要です。
JSON{
"name": "Taro",
"age": 30
}
C#側が Name、Age で、JSON側が name、age のように小文字の場合、設定によっては期待通りにマッピングされないことがあります。
大文字小文字を区別せずに解析したい場合は、オプションを指定します。
C#var options = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
};
User? user = JsonSerializer.Deserialize<User>(json, options);
また、数値のはずの項目に文字列が入っている場合もエラーになります。
JSON{
"Name": "Taro",
"Age": "abc"
}
JSON解析では、受け取るデータの形式を事前に確認し、不正なデータが来たときの処理を決めておくことが大切です。
4. C#でログを解析する方法
4-1. ログ解析とは何をする処理なのか
ログ解析とは、ログファイルやログ文字列を読み取り、必要な情報を取り出す処理です。
たとえば、次のようなログがあるとします。
2026-06-16 10:15:30 INFO User login succeeded
2026-06-16 10:16:05 ERROR Database connection failed
このログから、日時、ログレベル、メッセージを取り出す処理がログ解析です。
解析結果は、エラー調査、障害監視、アクセス分析、処理時間の集計などに使えます。
ログ解析では、ログの形式が決まっているかどうかが重要です。形式が一定であれば Split や正規表現で比較的簡単に解析できます。形式が複雑な場合は、専用のパーサーやログ管理ツールとの連携を検討します。
4-2. ファイルからログを読み込む方法
C#でログファイルを読み込むには、File.ReadLines が便利です。
C#foreach (string line in File.ReadLines("app.log"))
{
Console.WriteLine(line);
}
File.ReadAllLines はファイル全体を一度に読み込みます。
C#string[] lines = File.ReadAllLines("app.log");
小さなファイルなら問題ありませんが、大きなログファイルではメモリを多く使う可能性があります。そのため、大きなログを解析する場合は File.ReadLines を使って1行ずつ処理するのがおすすめです。
C#foreach (string line in File.ReadLines("app.log"))
{
// 1行ずつ解析する
}
文字コードを指定したい場合は、Encoding を使います。
C#using System.Text;
foreach (string line in File.ReadLines("app.log", Encoding.UTF8))
{
Console.WriteLine(line);
}
ログファイルの文字コードがUTF-8ではない場合、文字化けすることがあります。その場合は、実際の文字コードに合わせて読み込みます。
4-3. Split・正規表現を使ってログを分解する方法
ログ形式が単純な場合は、Split で分解できます。
2026-06-16 10:15:30 INFO User login succeeded
このログでは、日付、時刻、レベル、メッセージが空白で区切られています。
C#string line = "2026-06-16 10:15:30 INFO User login succeeded";
string[] parts = line.Split(' ', 4);
string date = parts[0];
string time = parts[1];
string level = parts[2];
string message = parts[3];
Console.WriteLine(date);
Console.WriteLine(time);
Console.WriteLine(level);
Console.WriteLine(message);
Split(' ', 4) のように最大分割数を指定すると、メッセージ内の空白を保持できます。
より厳密に解析したい場合は、正規表現を使います。
C#using System.Text.RegularExpressions;
string line = "2026-06-16 10:15:30 INFO User login succeeded";
var match = Regex.Match(
line,
@"^(?<date>\d{4}-\d{2}-\d{2}) (?<time>\d{2}:\d{2}:\d{2}) (?<level>\w+) (?<message>.*)$"
);
if (match.Success)
{
Console.WriteLine(match.Groups["date"].Value);
Console.WriteLine(match.Groups["time"].Value);
Console.WriteLine(match.Groups["level"].Value);
Console.WriteLine(match.Groups["message"].Value);
}
正規表現を使うと、形式に合う行だけを抽出したり、名前付きグループで必要な情報を取り出したりできます。
4-4. 日時・レベル・メッセージを抽出するサンプルコード
ログ行から日時、レベル、メッセージを抽出する実践的なサンプルです。
C#using System;
using System.IO;
using System.Text.RegularExpressions;
public class LogEntry
{
public DateTime Timestamp { get; set; }
public string Level { get; set; } = "";
public string Message { get; set; } = "";
}
class Program
{
static void Main()
{
string path = "app.log";
foreach (string line in File.ReadLines(path))
{
LogEntry? entry = ParseLogLine(line);
if (entry != null)
{
Console.WriteLine($"{entry.Timestamp} [{entry.Level}] {entry.Message}");
}
}
}
static LogEntry? ParseLogLine(string line)
{
var match = Regex.Match(
line,
@"^(?<timestamp>\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}) (?<level>\w+) (?<message>.*)$"
);
if (!match.Success)
{
return null;
}
if (!DateTime.TryParse(match.Groups["timestamp"].Value, out DateTime timestamp))
{
return null;
}
return new LogEntry
{
Timestamp = timestamp,
Level = match.Groups["level"].Value,
Message = match.Groups["message"].Value
};
}
}
このサンプルでは、ログ行が期待した形式でなければ null を返します。解析に失敗する可能性を前提にしているため、安全にログ処理を行えます。
4-5. 大きなログファイルを効率よく解析するポイント
大きなログファイルを解析するときは、メモリ使用量に注意する必要があります。
File.ReadAllText や File.ReadAllLines はファイル全体を一度に読み込むため、数百MBや数GBのログではメモリ不足になる可能性があります。
大きなログでは、File.ReadLines を使って1行ずつ処理するのが基本です。
C#foreach (string line in File.ReadLines("large.log"))
{
// 必要な行だけ処理する
}
エラー行だけを抽出する場合は、早めに条件判定して不要な処理を避けます。
C#foreach (string line in File.ReadLines("large.log"))
{
if (!line.Contains("ERROR"))
{
continue;
}
Console.WriteLine(line);
}
正規表現を使う場合は、毎回パターンを作らないようにします。
C#var regex = new Regex(
@"^(?<timestamp>\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}) (?<level>\w+) (?<message>.*)$",
RegexOptions.Compiled
);
foreach (string line in File.ReadLines("large.log"))
{
var match = regex.Match(line);
}
大量データでは、できるだけ少ないメモリで、必要な行だけを処理する設計が重要です。
4-6. ログ解析で注意すべき文字コード・改行・例外処理
ログ解析では、文字コードの違いによる文字化けに注意が必要です。
UTF-8のログを読み込む場合は、次のように指定できます。
C#using System.Text;
foreach (string line in File.ReadLines("app.log", Encoding.UTF8))
{
Console.WriteLine(line);
}
Shift_JISなど別の文字コードで保存されているログでは、対応するエンコーディングを指定する必要があります。
また、WindowsとLinuxでは改行コードが異なる場合があります。通常、File.ReadLines を使えば改行コードの違いを意識せず1行ずつ読み取れます。
ファイルが存在しない、アクセス権がない、読み込み中に別プロセスがファイルをロックしている、といったケースも考慮しましょう。
C#try
{
foreach (string line in File.ReadLines("app.log"))
{
Console.WriteLine(line);
}
}
catch (FileNotFoundException)
{
Console.WriteLine("ログファイルが見つかりません。");
}
catch (UnauthorizedAccessException)
{
Console.WriteLine("ログファイルにアクセスできません。");
}
catch (IOException ex)
{
Console.WriteLine($"ログファイルの読み込みに失敗しました: {ex.Message}");
}
ログ解析は外部ファイルを扱うため、例外処理を丁寧に書くことが大切です。
5. C#でコードを解析する方法
5-1. C#コード解析とは何か
C#コード解析とは、C#のソースコードをプログラムで読み取り、クラス、メソッド、変数、構文などの情報を取得する処理です。
たとえば、次のようなことができます。
C#コードからクラス名を取得できます。
C#public class UserService
{
}
メソッド名を一覧化できます。
C#public void CreateUser()
{
}
変数宣言やプロパティ定義を検出できます。
C#public string Name { get; set; }
命名規則に違反しているコードを見つけたり、特定のAPIを使っている箇所を探したりすることもできます。
C#コード解析には、主にRoslynと呼ばれるコンパイラプラットフォームを使います。
5-2. Roslynを使うとできること
Roslynは、C#やVisual Basicのコンパイラ機能をAPIとして利用できる仕組みです。C#コードを解析したり、構文ツリーを操作したり、静的解析ツールを作ったりできます。
Roslynを使うと、次のようなことができます。
C#コードを構文ツリーとして解析できます。
C#var tree = CSharpSyntaxTree.ParseText(code);
クラス宣言を取得できます。
C#root.DescendantNodes().OfType<ClassDeclarationSyntax>();
メソッド宣言を取得できます。
C#root.DescendantNodes().OfType<MethodDeclarationSyntax>();
コードの自動修正やリファクタリング支援にも活用できます。
Visual Studioのコード分析、補完、リファクタリングなどにもRoslynの仕組みが使われています。自分で静的解析ツールを作りたい場合にも、Roslynは非常に強力です。
5-3. CSharpSyntaxTree.ParseTextでコードを解析する流れ
RoslynでC#コードを解析する基本的な流れは、次のとおりです。
まず、必要なパッケージとして Microsoft.CodeAnalysis.CSharp を利用します。
コードでは、次の名前空間を使います。
C#using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
C#コード文字列を用意し、CSharpSyntaxTree.ParseText で解析します。
C#string code = """
public class Sample
{
public void Hello()
{
Console.WriteLine("Hello");
}
}
""";
SyntaxTree tree = CSharpSyntaxTree.ParseText(code);
CompilationUnitSyntax root = tree.GetCompilationUnitRoot();
Console.WriteLine(root.ToString());
SyntaxTree は構文ツリーを表します。GetCompilationUnitRoot を呼び出すと、ソースコード全体を表すルートノードを取得できます。
このルートノードから、クラス宣言やメソッド宣言などをたどっていきます。
5-4. 構文ツリー・ノード・トークンの基本
Roslynでコード解析を行うには、構文ツリー、ノード、トークンの考え方を理解しておくと便利です。
構文ツリーは、コード全体を木構造で表したものです。C#コードは、クラス、メソッド、文、式などの要素に分解できます。これらが親子関係を持つ木構造として表現されます。
ノードは、構文上のまとまりを表します。たとえば、クラス宣言、メソッド宣言、if文、変数宣言などがノードです。
トークンは、キーワード、識別子、記号などの最小単位です。たとえば、class、Sample、{、} などがトークンです。
トリビアは、空白、改行、コメントなどの情報です。Roslynでは、コメントや空白も保持できるため、コード整形や自動修正にも利用できます。
たとえば、次のコードを考えます。
C#public class Sample
{
public void Hello()
{
}
}
class Sample はクラス宣言ノード、Hello はメソッド宣言ノード内の識別子トークンとして扱われます。
5-5. クラス名・メソッド名・変数名を取得するサンプル
Roslynを使って、C#コードからクラス名、メソッド名、変数名を取得するサンプルです。
C#using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
string code = """
public class UserService
{
private int count;
public void CreateUser()
{
string name = "Taro";
}
public int GetCount()
{
return count;
}
}
""";
SyntaxTree tree = CSharpSyntaxTree.ParseText(code);
CompilationUnitSyntax root = tree.GetCompilationUnitRoot();
var classes = root.DescendantNodes().OfType<ClassDeclarationSyntax>();
foreach (var classDeclaration in classes)
{
Console.WriteLine($"クラス名: {classDeclaration.Identifier.Text}");
}
var methods = root.DescendantNodes().OfType<MethodDeclarationSyntax>();
foreach (var method in methods)
{
Console.WriteLine($"メソッド名: {method.Identifier.Text}");
}
var variables = root.DescendantNodes().OfType<VariableDeclaratorSyntax>();
foreach (var variable in variables)
{
Console.WriteLine($"変数名: {variable.Identifier.Text}");
}
このコードでは、DescendantNodes() で構文ツリー内のすべてのノードを取得し、OfType<T>() で特定の種類の構文ノードだけを抽出しています。
C#コード解析では、このように構文ツリーから目的のノードを探すのが基本です。
5-6. 静的解析ツールや自動チェックへの活用例
C#コード解析は、静的解析ツールや自動チェックに活用できます。
たとえば、次のようなチェックを自動化できます。
メソッド名が命名規則に従っているか確認できます。
C#if (!char.IsUpper(method.Identifier.Text[0]))
{
Console.WriteLine("メソッド名は大文字で始めてください。");
}
特定の禁止APIを使っていないかチェックできます。
C#// Console.WriteLine を本番コードで禁止する、など
クラスやメソッドの数を集計して、コードの複雑さを把握できます。
C#int methodCount = root.DescendantNodes().OfType<MethodDeclarationSyntax>().Count();
独自のコーディングルールを適用したり、レビュー前に自動チェックしたりすることで、品質向上につながります。
6. C#で構文解析を行う方法
6-1. 構文解析とは何か
構文解析とは、入力された文字列がどのような文法構造を持っているかを解析する処理です。
たとえば、次のような計算式を考えます。
1 + 2 * 3
この式は、単なる文字の並びではなく、「1に、2と3を掛けた結果を足す」という構造を持っています。構文解析では、このような構造を読み取ります。
プログラミング言語のコードも構文解析の対象です。
C#int x = 10;
このコードは、型 int、変数名 x、代入演算子 =、数値リテラル 10、文末の ; という構造を持っています。
構文解析は、コンパイラ、インタプリタ、テンプレートエンジン、設定ファイル解析、独自DSLの実装などで使われます。
6-2. 字句解析・構文解析・意味解析の違い
構文解析を理解するには、字句解析、構文解析、意味解析の違いを押さえておくとよいです。
字句解析は、文字列をトークンに分解する処理です。
int x = 10;
この文字列は、次のようなトークンに分解できます。
int
x
=
10
;
構文解析は、トークンの並びが文法に合っているかを確認し、構造として組み立てる処理です。たとえば、「型 変数名 = 値 ;」という変数宣言の形になっているかを判断します。
意味解析は、構文として正しいだけでなく、意味的にも正しいかを確認する処理です。たとえば、存在しない変数を使っていないか、型が一致しているか、といったチェックです。
C#のコンパイルでも、内部的にはこのような段階を経てコードが処理されます。
6-3. 構文ツリーとASTの考え方
構文解析の結果は、木構造で表現されることが多いです。
たとえば、次の式を考えます。
1 + 2 * 3
この式は、次のような構造として考えられます。
+
├─ 1
└─ *
├─ 2
└─ 3
このように、演算子や値の関係を木構造で表したものが構文ツリーです。
ASTは、Abstract Syntax Treeの略で、日本語では抽象構文木と呼ばれます。構文ツリーから不要な記号や細かい文法要素を省き、プログラムの意味を扱いやすくしたものです。
Roslynの構文ツリーは、空白やコメントなどの情報も保持できるため、非常に詳細です。一方、自作パーサーで作るASTでは、必要な情報だけを持たせることが多いです。
6-4. 自作パーサーが必要になるケース
通常の開発では、文字列解析、JSON解析、CSV解析などは既存ライブラリで対応できます。しかし、次のような場合は自作パーサーが必要になることがあります。
独自の設定ファイル形式を扱う場合です。
server: localhost
port: 8080
独自の検索条件やフィルター式を扱う場合です。
age >= 20 AND status = active
簡単な計算式を評価したい場合です。
1 + 2 * 3
テンプレート構文を解析したい場合です。
Hello, {{ user.name }}
このように、既存の形式では表現できない独自ルールを扱う場合、自作パーサーやパーサーライブラリを検討します。
6-5. 正規表現で足りる場合とパーサーが必要な場合
解析処理では、正規表現で十分な場合と、パーサーが必要な場合があります。
正規表現で足りるのは、形式が単純で、入れ子構造がない場合です。
たとえば、ログから日時やレベルを取り出す処理は正規表現に向いています。
2026-06-16 10:15:30 ERROR Message
メールアドレス、電話番号、郵便番号、IDなどの抽出も正規表現で対応しやすいです。
一方、入れ子構造や演算子の優先順位がある場合は、正規表現だけでは難しくなります。
(1 + 2) * (3 + 4)
if (x > 0) { return x; }
このような構造を扱う場合は、構文解析器を使った方が安全です。
初心者は、「単純な抽出なら正規表現」「文法や入れ子があるならパーサー」と考えると判断しやすいです。
6-6. Spracheなどのパーサーライブラリを使う選択肢
C#で自作パーサーを作る場合、すべてをゼロから実装する必要はありません。パーサーライブラリを使う方法があります。
代表的な選択肢のひとつが Sprache です。Spracheは、C#でパーサーを組み立てるためのライブラリです。小規模なDSLや設定式の解析に使いやすいです。
また、より本格的な構文解析には ANTLR というパーサージェネレーターも使えます。ANTLRでは、文法定義を書いてパーサーを生成できます。複雑な言語やDSLを扱う場合に向いています。
単純な解析なら Split や Regex、JSONなら System.Text.Json、C#コードなら Microsoft.CodeAnalysis、独自構文なら Sprache や ANTLR というように、解析対象に合わせて道具を選ぶことが重要です。
7. C#解析でよく使うライブラリ・API
7-1. System.Text.Json
System.Text.Json は、.NET標準のJSON解析APIです。JSON文字列をC#のオブジェクトに変換したり、C#オブジェクトをJSON文字列に変換したりできます。
基本的な使い方は次のとおりです。
C#using System.Text.Json;
User? user = JsonSerializer.Deserialize<User>(json);
JSONの一部だけを読みたい場合は、JsonDocument や JsonNode も使えます。
C#using JsonDocument doc = JsonDocument.Parse(json);
string? name = doc.RootElement.GetProperty("name").GetString();
標準機能で使えるため、新規開発ではまず検討したいライブラリです。
7-2. Newtonsoft.Json
Newtonsoft.Json は、長く使われてきた定番のJSONライブラリです。
C#using Newtonsoft.Json;
User? user = JsonConvert.DeserializeObject<User>(json);
柔軟な設定や豊富な機能があり、既存プロジェクトでも多く使われています。
新規開発では System.Text.Json を優先し、既存コードとの互換性や必要な機能に応じて Newtonsoft.Json を選ぶとよいでしょう。
7-3. Microsoft.CodeAnalysis
Microsoft.CodeAnalysis は、Roslynを利用するためのライブラリです。C#コードを解析し、構文ツリーからクラス、メソッド、変数などを取得できます。
C#using Microsoft.CodeAnalysis.CSharp;
var tree = CSharpSyntaxTree.ParseText(code);
var root = tree.GetCompilationUnitRoot();
静的解析ツール、コード生成、リファクタリング支援、独自ルールチェックなどに活用できます。
C#コード自体を解析したい場合は、Microsoft.CodeAnalysis が有力な選択肢です。
7-4. Regex
Regex は、正規表現を使って文字列を解析するためのクラスです。
C#using System.Text.RegularExpressions;
var match = Regex.Match(text, @"\d+");
ログ解析、入力チェック、特定パターンの抽出などに使えます。
たとえば、文字列から数値だけを取り出す場合は次のように書けます。
C#string text = "商品ID: 12345";
var match = Regex.Match(text, @"\d+");
if (match.Success)
{
Console.WriteLine(match.Value);
}
正規表現は便利ですが、複雑になりすぎると読みにくくなります。複雑な文法を解析する場合は、パーサーライブラリの利用も検討しましょう。
7-5. CsvHelper
CSV解析を行う場合は、CsvHelper がよく使われます。
CSVは一見するとカンマで分割すればよいように見えますが、実際にはダブルクォート、改行、エスケープなどを考慮する必要があります。
csvName,Age
Taro,30
Hanako,25
単純に Split(',') で分解すると、値の中にカンマが含まれる場合に正しく解析できません。そのため、実務ではCSV専用ライブラリを使う方が安全です。
CsvHelper を使えば、CSVをクラスにマッピングして読み込むことができます。
7-6. Sprache・ANTLR
独自の構文を解析したい場合は、Sprache や ANTLR が選択肢になります。
Sprache は、C#コード上でパーサーを組み立てるライブラリです。比較的小規模なDSLや独自式の解析に向いています。
ANTLR は、文法ファイルからパーサーを生成するツールです。複雑な構文や本格的な言語処理に向いています。
簡単な文字列抽出なら正規表現、構造が複雑ならパーサーライブラリというように使い分けるとよいでしょう。
8. C#解析の実践サンプル集
8-1. 文字列を数値に解析するサンプル
文字列を整数に解析する基本サンプルです。
C#string input = "123";
if (int.TryParse(input, out int number))
{
Console.WriteLine($"解析成功: {number}");
}
else
{
Console.WriteLine("整数として解析できません。");
}
小数を解析する場合は double や decimal を使います。
C#string input = "123.45";
if (decimal.TryParse(input, out decimal value))
{
Console.WriteLine($"金額: {value}");
}
else
{
Console.WriteLine("数値として解析できません。");
}
金額のように誤差を避けたい値では、double より decimal が使われることが多いです。
8-2. JSONをクラスに解析するサンプル
JSONをC#クラスに解析するサンプルです。
C#using System.Text.Json;
public class Customer
{
public string? Name { get; set; }
public int Age { get; set; }
}
string json = """
{
"Name": "Yamada",
"Age": 35
}
""";
Customer? customer = JsonSerializer.Deserialize<Customer>(json);
if (customer != null)
{
Console.WriteLine(customer.Name);
Console.WriteLine(customer.Age);
}
JSONとクラスのプロパティ名が一致していれば、自動的に値が設定されます。
8-3. JSONの一部だけを取り出すサンプル
JSON全体をクラスに変換せず、一部の値だけ取り出す場合は JsonDocument が便利です。
C#using System.Text.Json;
string json = """
{
"status": "success",
"data": {
"id": 101,
"name": "Sample"
}
}
""";
using JsonDocument document = JsonDocument.Parse(json);
JsonElement root = document.RootElement;
string status = root.GetProperty("status").GetString() ?? "";
int id = root.GetProperty("data").GetProperty("id").GetInt32();
string name = root.GetProperty("data").GetProperty("name").GetString() ?? "";
Console.WriteLine(status);
Console.WriteLine(id);
Console.WriteLine(name);
APIレスポンスから特定の項目だけ取りたい場合に使いやすい方法です。
8-4. ログファイルを1行ずつ解析するサンプル
ログファイルを1行ずつ読み込み、ERROR行だけを出力するサンプルです。
C#using System.IO;
foreach (string line in File.ReadLines("app.log"))
{
if (line.Contains("ERROR"))
{
Console.WriteLine(line);
}
}
大きなログファイルでも、File.ReadLines を使えば全体を一度にメモリへ読み込まずに処理できます。
ログレベルを抽出したい場合は、Split を使えます。
C#string line = "2026-06-16 10:15:30 ERROR Database connection failed";
string[] parts = line.Split(' ', 4);
if (parts.Length == 4)
{
string date = parts[0];
string time = parts[1];
string level = parts[2];
string message = parts[3];
Console.WriteLine($"{date} {time}");
Console.WriteLine(level);
Console.WriteLine(message);
}
8-5. 正規表現で必要な情報を抽出するサンプル
文字列からメールアドレスを抽出するサンプルです。
C#using System.Text.RegularExpressions;
string text = "お問い合わせ先は support@example.com です。";
var match = Regex.Match(
text,
@"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}"
);
if (match.Success)
{
Console.WriteLine($"メールアドレス: {match.Value}");
}
ログからログレベルを抽出する例です。
C#using System.Text.RegularExpressions;
string line = "2026-06-16 10:15:30 WARN Disk space is low";
var match = Regex.Match(line, @"\b(INFO|WARN|ERROR|DEBUG)\b");
if (match.Success)
{
Console.WriteLine($"ログレベル: {match.Value}");
}
正規表現を使うと、特定のパターンに一致する情報を簡単に取り出せます。
8-6. C#コードからメソッド一覧を取得するサンプル
Roslynを使って、C#コードからメソッド一覧を取得するサンプルです。
C#using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
string code = """
public class Calculator
{
public int Add(int a, int b)
{
return a + b;
}
public int Subtract(int a, int b)
{
return a - b;
}
}
""";
var tree = CSharpSyntaxTree.ParseText(code);
var root = tree.GetCompilationUnitRoot();
var methods = root.DescendantNodes().OfType<MethodDeclarationSyntax>();
foreach (var method in methods)
{
Console.WriteLine(method.Identifier.Text);
}
実行すると、次のメソッド名を取得できます。
Add
Subtract
C#コード解析を使えば、ドキュメント生成、コード品質チェック、命名規則チェックなどにも応用できます。
9. C#解析でよくあるエラーと対処法
9-1. FormatExceptionが発生する原因
FormatException は、文字列の形式が期待した型に合っていないときに発生します。
C#int number = int.Parse("abc");
"abc" は整数ではないため、解析に失敗します。
対処法は、Parse ではなく TryParse を使うことです。
C#if (int.TryParse("abc", out int number))
{
Console.WriteLine(number);
}
else
{
Console.WriteLine("整数として解析できません。");
}
日付でも同じです。
C#if (DateTime.TryParse("invalid-date", out DateTime date))
{
Console.WriteLine(date);
}
else
{
Console.WriteLine("日付として解析できません。");
}
外部入力を扱う場合は、FormatException が起きる前提で設計することが大切です。
9-2. NullReferenceExceptionを防ぐ方法
NullReferenceException は、null のオブジェクトにアクセスしたときに発生します。
JSON解析では、デシリアライズ結果が null になる可能性があります。
C#User? user = JsonSerializer.Deserialize<User>(json);
Console.WriteLine(user.Name); // user が null なら例外
対処法は、null チェックを行うことです。
C#User? user = JsonSerializer.Deserialize<User>(json);
if (user != null)
{
Console.WriteLine(user.Name);
}
else
{
Console.WriteLine("ユーザー情報を解析できませんでした。");
}
プロパティが null になる可能性がある場合も考慮します。
C#string name = user?.Name ?? "名前なし";
C#では、nullable参照型を有効にしておくと、null に関する問題に気づきやすくなります。
9-3. JSONのプロパティ名が一致しない場合
JSONのプロパティ名とC#クラスのプロパティ名が一致しない場合、値が正しく設定されないことがあります。
JSONが次のようになっているとします。
JSON{
"user_name": "Taro"
}
C#クラスが次のようになっている場合、そのままでは対応しないことがあります。
C#public class User
{
public string? UserName { get; set; }
}
この場合は、JsonPropertyName 属性を使います。
C#using System.Text.Json.Serialization;
public class User
{
[JsonPropertyName("user_name")]
public string? UserName { get; set; }
}
これにより、JSONの user_name をC#の UserName に対応付けできます。
大文字小文字の違いだけであれば、次のオプションも使えます。
C#var options = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
};
JSON解析では、JSON側の名前とC#側のプロパティ名の対応を確認することが重要です。
9-4. 文字コードが原因でログ解析に失敗する場合
ログファイルを読み込んだときに文字化けする場合、文字コードが原因の可能性があります。
UTF-8のファイルなら、次のように読み込めます。
C#using System.Text;
foreach (string line in File.ReadLines("app.log", Encoding.UTF8))
{
Console.WriteLine(line);
}
Shift_JISのログを扱う場合は、環境によって追加設定が必要になることがあります。
文字コードが合っていないと、日本語が文字化けし、正規表現のマッチや文字列検索がうまく動かないことがあります。
ログ解析では、ログファイルがどの文字コードで保存されているかを確認してから読み込むことが大切です。
9-5. 正規表現が想定通りにマッチしない場合
正規表現が想定通りにマッチしない原因は、パターンの書き方や入力文字列の違いにあります。
たとえば、次の正規表現は日付にマッチします。
C#var match = Regex.Match("2026-06-16", @"\d{4}-\d{2}-\d{2}");
しかし、入力が "2026/06/16" の場合はマッチしません。区切り文字が - ではなく / だからです。
複数の区切り文字に対応したい場合は、次のように書けます。
C#var match = Regex.Match("2026/06/16", @"\d{4}[-/]\d{2}[-/]\d{2}");
また、行全体に一致させたい場合は、^ と $ を使います。
C#var match = Regex.Match(line, @"^\d{4}-\d{2}-\d{2}$");
正規表現がうまく動かないときは、実際の入力文字列を確認し、空白、改行、全角文字、区切り文字の違いをチェックしましょう。
9-6. 解析処理を安全に書くためのチェックポイント
C#解析を安全に書くためには、次のポイントを意識します。
まず、外部入力を信用しないことです。ユーザー入力、ファイル、APIレスポンス、ログは、期待通りの形式とは限りません。
次に、Parse より TryParse を優先します。失敗する可能性がある解析では、例外ではなく戻り値で判定する方が扱いやすいです。
JSON解析では、null チェックと例外処理を行います。
C#try
{
var result = JsonSerializer.Deserialize<User>(json);
if (result == null)
{
Console.WriteLine("JSONの解析結果が空です。");
}
}
catch (JsonException ex)
{
Console.WriteLine(ex.Message);
}
ログ解析では、1行ごとに失敗を許容する設計にします。1行の不正なログで全体の処理が止まらないようにすることが重要です。
また、解析処理はテストしやすいように、メソッドとして分離するとよいです。
C#static bool TryParseLogLine(string line, out LogEntry? entry)
{
entry = null;
// 解析処理
return true;
}
安全な解析処理では、「成功すること」だけでなく「失敗したときにどうするか」を先に決めておくことが大切です。
10. C#解析を実装するときの設計ポイント
10-1. 解析対象の形式を明確にする
解析処理を実装する前に、まず解析対象の形式を明確にします。
数値なのか、日付なのか、JSONなのか、CSVなのか、ログなのか、C#コードなのかによって、使う方法は変わります。
たとえば、数値なら int.TryParse、JSONなら System.Text.Json、ログなら Regex や Split、C#コードならRoslynを検討します。
ログ解析では、ログの形式を具体的に決めておくことが重要です。
yyyy-MM-dd HH:mm:ss LEVEL Message
このように形式を明確にしておけば、正規表現や分割処理を設計しやすくなります。
形式が曖昧なまま解析処理を書くと、例外や解析漏れが増えやすくなります。
10-2. 失敗時の処理を先に決める
解析処理では、失敗時の扱いを先に決めておくことが重要です。
たとえば、数値解析に失敗した場合、次のような選択肢があります。
デフォルト値を使う。
C#int value = int.TryParse(input, out int result) ? result : 0;
エラーメッセージを表示する。
C#Console.WriteLine("数値を入力してください。");
ログに記録して処理を続行する。
C#Console.WriteLine($"解析失敗: {input}");
例外として上位に通知する。
C#throw new InvalidOperationException("解析に失敗しました。");
どれが正解かは処理内容によります。ユーザー入力ならエラーメッセージを返し、ログ解析なら失敗行をスキップし、重要な設定ファイルならアプリケーション起動を止める、といった判断が必要です。
10-3. ParseよりTryParseを優先すべき場面
Parse は、入力値が必ず正しいとわかっている場合に使います。
C#int number = int.Parse("123");
一方、次のような場面では TryParse を優先すべきです。
ユーザーが入力した値を解析する場合です。
C#int.TryParse(userInput, out int age);
CSVやログなどの外部ファイルを解析する場合です。
C#DateTime.TryParse(dateText, out DateTime timestamp);
APIレスポンスや外部システムの値を解析する場合です。
C#decimal.TryParse(priceText, out decimal price);
つまり、自分のプログラム外から来るデータは、基本的に不正な可能性があると考えます。そのため、TryParse を使って安全に処理するのがおすすめです。
10-4. 例外処理とログ出力の考え方
解析処理では、例外処理とログ出力も重要です。
通常の入力ミスや形式不一致は、例外ではなく TryParse や条件分岐で扱う方が自然です。
C#if (!int.TryParse(input, out int value))
{
Console.WriteLine("数値ではありません。");
}
一方、ファイルが読めない、JSON形式が壊れている、想定外の状態になったといった場合は、例外処理が必要です。
C#try
{
string json = File.ReadAllText("settings.json");
var settings = JsonSerializer.Deserialize<AppSettings>(json);
}
catch (IOException ex)
{
Console.WriteLine($"ファイル読み込みエラー: {ex.Message}");
}
catch (JsonException ex)
{
Console.WriteLine($"JSON解析エラー: {ex.Message}");
}
ログ出力では、失敗した入力値、エラー内容、発生箇所がわかるようにすると調査しやすくなります。
ただし、個人情報やパスワードなどの機密情報をログに出さないよう注意が必要です。
10-5. 大量データを扱う場合のパフォーマンス対策
大量データを解析する場合は、パフォーマンスを意識する必要があります。
大きなファイルは一度に読み込まず、1行ずつ処理します。
C#foreach (string line in File.ReadLines("large.log"))
{
// 1行ずつ解析
}
不要なオブジェクト生成を減らすことも重要です。正規表現を繰り返し使う場合は、あらかじめ Regex オブジェクトを作成しておきます。
C#var regex = new Regex(@"ERROR", RegexOptions.Compiled);
foreach (string line in File.ReadLines("large.log"))
{
if (regex.IsMatch(line))
{
Console.WriteLine(line);
}
}
JSONが非常に大きい場合は、すべてをオブジェクトに変換するのではなく、必要な部分だけを読み取る方法も検討します。
大量データ解析では、メモリ使用量、処理時間、例外発生時の継続可否を考えて設計しましょう。
10-6. テストしやすい解析処理にする方法
解析処理は、テストしやすい形に分離しておくと保守が楽になります。
たとえば、ログ解析を直接 Main メソッドに書くのではなく、1行を解析するメソッドに分けます。
C#static LogEntry? ParseLogLine(string line)
{
// 解析処理
}
さらに、成功・失敗を明確にしたい場合は、TryParse 形式にします。
C#static bool TryParseLogLine(string line, out LogEntry? entry)
{
entry = null;
// 解析に失敗したら false
// 成功したら entry に値を入れて true
return true;
}
このようにしておくと、単体テストでさまざまな入力を確認できます。
C#// 正常なログ
// 不正なログ
// 空文字
// 日付形式が不正
// レベルが不明
解析処理では、正常系だけでなく異常系のテストが重要です。
11. C#解析に関するよくある質問
11-1. C#のParseとは何ですか?
C#の Parse とは、文字列を特定の型に変換するためのメソッドです。
たとえば、文字列を整数に変換する場合は int.Parse を使います。
C#int number = int.Parse("123");
日付に変換する場合は DateTime.Parse を使います。
C#DateTime date = DateTime.Parse("2026-06-16");
ただし、Parse は解析に失敗すると例外を発生させます。そのため、入力値が正しいと保証できない場合は TryParse を使う方が安全です。
11-2. ParseとTryParseはどちらを使うべきですか?
ユーザー入力や外部ファイル、APIレスポンスなどを解析する場合は、基本的に TryParse を使うべきです。
C#if (int.TryParse(input, out int number))
{
Console.WriteLine(number);
}
else
{
Console.WriteLine("数値ではありません。");
}
Parse は、値が必ず正しいとわかっている場合に使います。
C#int number = int.Parse("123");
初心者は、「外部から来る値にはTryParse」と覚えておくとよいでしょう。
11-3. C#でJSONを解析するには何を使えばよいですか?
C#でJSONを解析する場合は、まず System.Text.Json を検討するとよいです。
C#using System.Text.Json;
User? user = JsonSerializer.Deserialize<User>(json);
JSONの一部だけを読みたい場合は、JsonDocument や JsonNode も使えます。
既存プロジェクトで Newtonsoft.Json を使っている場合や、より柔軟な機能が必要な場合は、Newtonsoft.Json も選択肢になります。
新規開発で基本的なJSON解析を行うなら、標準で使える System.Text.Json が扱いやすいです。
11-4. C#でログ解析をするにはどう書けばよいですか?
C#でログ解析をする場合は、まず File.ReadLines でログを1行ずつ読み込みます。
C#foreach (string line in File.ReadLines("app.log"))
{
Console.WriteLine(line);
}
ログ形式が単純であれば Split を使います。
C#string[] parts = line.Split(' ', 4);
より厳密に日時、レベル、メッセージを取り出したい場合は、正規表現を使います。
C#var match = Regex.Match(
line,
@"^(?<timestamp>\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}) (?<level>\w+) (?<message>.*)$"
);
大きなログファイルでは、全体を一度に読み込まず、1行ずつ処理することが重要です。
11-5. C#コード自体を解析することはできますか?
はい、C#コード自体を解析することはできます。
C#コード解析には、Roslynの Microsoft.CodeAnalysis を使います。
C#using Microsoft.CodeAnalysis.CSharp;
var tree = CSharpSyntaxTree.ParseText(code);
var root = tree.GetCompilationUnitRoot();
クラス名やメソッド名を取得することもできます。
C#var methods = root.DescendantNodes().OfType<MethodDeclarationSyntax>();
foreach (var method in methods)
{
Console.WriteLine(method.Identifier.Text);
}
Roslynを使えば、静的解析ツール、自動レビュー、コード生成、命名規則チェックなどを実装できます。
11-6. 正規表現だけで構文解析はできますか?
単純な文字列抽出であれば、正規表現で対応できます。
たとえば、ログから日時を取り出す、メールアドレスを抽出する、特定のIDを見つけるといった処理には正規表現が向いています。
しかし、入れ子構造や演算子の優先順位があるような複雑な構文解析には、正規表現だけでは限界があります。
(1 + 2) * (3 + 4)
このような式を正しく解析するには、パーサーを使う方が安全です。
C#コードを解析するならRoslyn、独自構文を解析するならSpracheやANTLRなどのライブラリを検討するとよいでしょう。
まとめ
C#解析とは、文字列、JSON、ログ、コード、構文などを読み取り、プログラムで扱いやすい形に変換・抽出する処理です。
基本的な文字列解析では、int.Parse、DateTime.Parse、bool.Parse などを使います。ただし、ユーザー入力や外部データのように失敗する可能性がある場合は、Parse より TryParse を使う方が安全です。
JSON解析では、標準機能の System.Text.Json がよく使われます。JSONをクラスに変換するなら JsonSerializer.Deserialize、一部だけを読み取るなら JsonDocument や JsonNode が便利です。既存プロジェクトや柔軟な変換が必要な場合は、Newtonsoft.Json も選択肢になります。
ログ解析では、File.ReadLines で1行ずつ読み込み、Split や Regex を使って日時、レベル、メッセージなどを抽出します。大きなログファイルでは、メモリを使いすぎないように1行ずつ処理することが重要です。
C#コード自体を解析したい場合は、Roslynの Microsoft.CodeAnalysis を使います。CSharpSyntaxTree.ParseText でコードを構文ツリーに変換し、クラス名、メソッド名、変数名などを取得できます。
構文解析が必要な場合は、正規表現で足りるのか、パーサーが必要なのかを見極めましょう。単純な抽出なら正規表現で十分ですが、入れ子構造や文法ルールがある場合は、SpracheやANTLRのようなパーサーライブラリを検討するのがおすすめです。
C#解析を実装するときは、解析対象の形式を明確にし、失敗時の処理を先に決め、安全に処理できる設計にすることが大切です。解析処理は実務で頻繁に使う重要な技術なので、まずは TryParse、System.Text.Json、Regex、File.ReadLines から少しずつ使い慣れていきましょう。

