C# partial classとは?使い方・メリット・注意点を初心者向けにわかりやすく解説
はじめに
C#を学んでいると、partial classという書き方を見かけることがあります。
たとえば、Windows FormsやWPF、Entity Frameworkなどを使っていると、次のようなコードが出てくることがあります。
C#public partial class MainWindow
{
}
classはクラスを定義するためのキーワードですが、前についているpartialが何を意味するのか、最初はわかりにくいかもしれません。
partial classは、日本語でいうと「部分クラス」のような意味です。1つのクラスの定義を、複数のファイルに分けて書ける仕組みです。
この記事では、C#のpartial classとは何か、基本的な使い方、メリット、注意点、よくあるエラー例まで、初心者向けにわかりやすく解説します。
1. C#のpartial classとは?
1-1. partial classの意味と基本的な役割
C#のpartial classとは、1つのクラス定義を複数のファイルに分割して記述できる機能です。
通常、C#では1つのクラスを1つのファイルに書くことが多いです。
C#public class User
{
public string Name { get; set; }
public void SayHello()
{
Console.WriteLine($"こんにちは、{Name}さん");
}
}
しかし、クラスの内容が大きくなったり、自動生成されたコードと自分で書くコードを分けたい場合があります。
そのようなときに使えるのがpartial classです。
C#public partial class User
{
public string Name { get; set; }
}
C#public partial class User
{
public void SayHello()
{
Console.WriteLine($"こんにちは、{Name}さん");
}
}
このように別々に書いても、コンパイル時には1つのUserクラスとして扱われます。
1-2. 1つのクラスを複数ファイルに分割できる仕組み
partial classでは、同じ名前空間の中に、同じクラス名でpartialを付けたクラスを複数定義できます。
たとえば、次のようにファイルを分けられます。
C#// User.Properties.cs
public partial class User
{
public string Name { get; set; }
public int Age { get; set; }
}
C#// User.Methods.cs
public partial class User
{
public void ShowProfile()
{
Console.WriteLine($"{Name} / {Age}歳");
}
}
開発者から見ると2つのファイルに分かれていますが、C#のコンパイラはこれらをまとめて1つのUserクラスとして認識します。
つまり、最終的には次のようなクラスと同じように扱われます。
C#public class User
{
public string Name { get; set; }
public int Age { get; set; }
public void ShowProfile()
{
Console.WriteLine($"{Name} / {Age}歳");
}
}
partial classは、実行時にクラスが分かれる仕組みではありません。あくまでソースコード上で分割して書ける仕組みです。
1-3. 通常のclassとの違い
通常のclassとpartial classの大きな違いは、クラス定義を複数に分けられるかどうかです。
通常のクラスは、基本的に1つのクラス定義として書きます。
C#public class Product
{
public string Name { get; set; }
}
一方、partial classでは、同じクラスを複数の場所に分けて書けます。
C#public partial class Product
{
public string Name { get; set; }
}
C#public partial class Product
{
public int Price { get; set; }
}
機能面では、完成したクラスとしては通常のクラスと大きな違いはありません。
partial classだからといって、特別なインスタンス化が必要になるわけではありません。
C#var product = new Product();
product.Name = "ノートPC";
product.Price = 120000;
通常のクラスと同じように使えます。
違いは「コードの書き方」と「ファイルの分け方」にあります。
1-4. partialキーワードが使える対象
C#のpartialキーワードは、主に次のようなものに使えます。
C#public partial class SampleClass
{
}
C#public partial struct SampleStruct
{
}
C#public partial interface ISample
{
}
C#public partial record SampleRecord
{
}
また、partial methodという機能もあります。
C#public partial class Sample
{
partial void OnCreated();
}
ただし、初心者がまず理解しておきたいのは、partial classです。
実務でもよく見るのは、Windows Forms、WPF、ASP.NET、Entity Frameworkなどで使われるpartial classです。
2. C# partial classの基本的な書き方
2-1. partial classの基本構文
partial classの基本構文は次のとおりです。
C#アクセス修飾子 partial class クラス名
{
// メンバー
}
たとえば、次のように書きます。
C#public partial class Customer
{
public string Name { get; set; }
}
ポイントは、classの前にpartialを付けることです。
C#public partial class Customer
partialは「このクラス定義は一部です」という意味を持ちます。
そのため、同じクラスの別の部分を、別ファイルに書けます。
C#public partial class Customer
{
public void DisplayName()
{
Console.WriteLine(Name);
}
}
2-2. 複数ファイルに分けてクラスを定義する例
実際に、Customerクラスを2つのファイルに分ける例を見てみましょう。
まず、プロパティを定義するファイルです。
C#// Customer.Properties.cs
public partial class Customer
{
public int Id { get; set; }
public string Name { get; set; }
}
次に、メソッドを定義するファイルです。
C#// Customer.Methods.cs
public partial class Customer
{
public void ShowInfo()
{
Console.WriteLine($"ID: {Id}, Name: {Name}");
}
}
この2つのファイルは、コンパイル時に1つのCustomerクラスとして扱われます。
そのため、次のように普通のクラスと同じ感覚で使えます。
C#var customer = new Customer();
customer.Id = 1;
customer.Name = "田中";
customer.ShowInfo();
実行結果は次のようになります。
C#ID: 1, Name: 田中
別ファイルに書いたIdやNameを、もう一方のファイルにあるShowInfoメソッドから参照できる点が重要です。
2-3. コンパイル時に1つのクラスとして扱われる仕組み
partial classは、実行時に複数のクラスが合体するわけではありません。
C#のコンパイラが、コンパイル時に複数のpartial class定義をまとめて、1つのクラスとして扱います。
たとえば、次の2つのファイルがあるとします。
C#// Employee.Info.cs
public partial class Employee
{
public string Name { get; set; }
}
C#// Employee.Work.cs
public partial class Employee
{
public void Work()
{
Console.WriteLine($"{Name}が作業しています");
}
}
コンパイラは、これを次のような1つのクラスとして解釈します。
C#public class Employee
{
public string Name { get; set; }
public void Work()
{
Console.WriteLine($"{Name}が作業しています");
}
}
そのため、partial classによってパフォーマンスが悪くなることは基本的にありません。
ソースコードの管理方法が変わるだけで、完成したクラスの使い方は通常のクラスと同じです。
2-4. 同じ名前空間・同じクラス名にする必要がある理由
partial classを使う場合、同じクラスとしてまとめるためには、基本的に同じ名前空間、同じクラス名で定義する必要があります。
たとえば、次のように同じ名前空間にある場合は、同じクラスとして扱われます。
C#namespace SampleApp.Models
{
public partial class User
{
public string Name { get; set; }
}
}
C#namespace SampleApp.Models
{
public partial class User
{
public void SayHello()
{
Console.WriteLine($"こんにちは、{Name}さん");
}
}
}
一方、名前空間が違うと、別のクラスとして扱われます。
C#namespace SampleApp.Models
{
public partial class User
{
public string Name { get; set; }
}
}
C#namespace SampleApp.Services
{
public partial class User
{
public void SayHello()
{
}
}
}
この場合、SampleApp.Models.UserとSampleApp.Services.Userは別の型です。
クラス名が同じでも、名前空間が違えば別物になるため注意しましょう。
3. C# partial classの具体的な使い方
3-1. 機能ごとにファイルを分ける使い方
partial classの使い方として、クラスの機能ごとにファイルを分ける方法があります。
たとえば、Orderクラスに次のような役割があるとします。
C#public partial class Order
{
public int Id { get; set; }
public decimal TotalPrice { get; set; }
}
C#public partial class Order
{
public void CalculateTotal()
{
// 合計金額を計算する処理
}
}
C#public partial class Order
{
public void PrintInvoice()
{
// 請求書を出力する処理
}
}
ファイル名を次のように分けると、役割がわかりやすくなります。
C#Order.Properties.cs
Order.Calculation.cs
Order.Printing.cs
ただし、何でもかんでも分ければよいわけではありません。
クラスが大きくなりすぎている場合は、partial classで分ける前に、そもそも別のクラスに分割できないかを考えることも大切です。
3-2. 自動生成コードと手書きコードを分離する使い方
partial classが特に便利なのは、自動生成コードと手書きコードを分けたい場合です。
ツールによって生成されるコードは、再生成されると上書きされることがあります。
もし自動生成されたファイルに直接コードを書き足してしまうと、再生成時に自分の変更が消えてしまう可能性があります。
そこで、次のように分けます。
C#// User.Generated.cs
public partial class User
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
C#// User.cs
public partial class User
{
public string FullName
{
get
{
return $"{FirstName} {LastName}";
}
}
}
User.Generated.csはツールが生成するファイル、User.csは開発者が手書きするファイルです。
このように分けておけば、自動生成コードが更新されても、自分で書いた拡張部分を守りやすくなります。
3-3. Windows FormsやWPFで使われる例
partial classは、Windows FormsやWPFでよく使われます。
Windows Formsでは、フォームの画面部品を配置すると、デザイナーがコードを自動生成します。
たとえば、次のような構成になります。
C#Form1.cs
Form1.Designer.cs
Form1.csには、開発者がイベント処理などを書きます。
C#public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show("ボタンがクリックされました");
}
}
Form1.Designer.csには、画面部品の配置や初期化コードが自動生成されます。
C#partial class Form1
{
private Button button1;
private void InitializeComponent()
{
button1 = new Button();
button1.Text = "クリック";
}
}
どちらもForm1という同じクラスの一部です。
開発者が編集するコードと、デザイナーが管理するコードを分けることで、コードの見通しがよくなります。
WPFでも同じように、XAMLに対応するコードビハインドでpartial classが使われます。
3-4. Entity Frameworkなどのコード生成との関係
Entity FrameworkなどのORMやコード生成ツールでも、partial classが使われることがあります。
データベースのテーブルからクラスを自動生成する場合、生成されたエンティティクラスに独自の処理を追加したいことがあります。
たとえば、次のような自動生成コードがあるとします。
C#// Product.Generated.cs
public partial class Product
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
}
ここに、税込価格を返すプロパティを追加したい場合、生成ファイルを直接編集するのではなく、別ファイルに書けます。
C#// Product.cs
public partial class Product
{
public decimal TaxIncludedPrice
{
get
{
return Price * 1.1m;
}
}
}
このようにすれば、データベース構造が変わって自動生成コードが更新されても、手書きしたTaxIncludedPriceを残しやすくなります。
3-5. チーム開発でのpartial class活用例
チーム開発でも、partial classが役立つ場合があります。
たとえば、1つの大きなクラスに対して、複数人が同時に作業する場合です。
C#Customer.BasicInfo.cs
Customer.Validation.cs
Customer.Display.cs
Aさんは基本情報、Bさんは入力チェック、Cさんは表示関連の処理を担当する、というように分けられます。
C#// Customer.Validation.cs
public partial class Customer
{
public bool IsValid()
{
return !string.IsNullOrEmpty(Name);
}
}
C#// Customer.Display.cs
public partial class Customer
{
public void Display()
{
Console.WriteLine(Name);
}
}
ただし、チーム開発でpartial classを使う場合は、分割ルールを決めておくことが重要です。
何の基準もなくファイルを増やすと、どこに何が書かれているのかわかりにくくなります。
4. C# partial classを使うメリット
4-1. クラスの見通しがよくなる
partial classを使うと、大きなクラスを複数のファイルに分けられるため、コードの見通しがよくなる場合があります。
たとえば、1つのファイルにプロパティ、計算処理、表示処理、検証処理がすべて入っていると、目的のコードを探しにくくなります。
C#Customer.cs
これを次のように分けると、どのファイルに何があるかがわかりやすくなります。
C#Customer.Properties.cs
Customer.Validation.cs
Customer.Display.cs
特に、フォーム画面や自動生成コードを含むクラスでは、partial classによる分割が役立ちます。
4-2. 自動生成コードを安全に拡張できる
partial classの大きなメリットは、自動生成コードを安全に拡張できることです。
ツールが生成したコードは、再生成時に上書きされる可能性があります。
そのため、自動生成ファイルを直接編集するのは危険です。
C#// 直接編集すると、再生成時に消える可能性がある
しかし、partial classを使えば、自動生成されたクラスと同じクラスを別ファイルで拡張できます。
C#// 自動生成ファイル
public partial class Member
{
public string Name { get; set; }
}
C#// 手書きファイル
public partial class Member
{
public void PrintName()
{
Console.WriteLine(Name);
}
}
これにより、生成コードを壊さず、自分の処理を追加できます。
4-3. 複数人で作業しやすくなる
partial classを使うと、複数人で同じクラスに関連する作業をしやすくなることがあります。
1つの大きなファイルを複数人が同時に編集すると、ソース管理ツールで競合が起きやすくなります。
ファイルを役割ごとに分けておけば、作業範囲を分離しやすくなります。
C#Order.Validation.cs
Order.Calculation.cs
Order.Export.cs
ただし、これはあくまで補助的なメリットです。
本来は、クラスの責務を適切に分けることが重要です。
複数人で作業しやすくするためだけに、無理に1つのクラスをpartial classで分割するのはおすすめできません。
4-4. 大きなクラスを管理しやすくなる
画面クラスや自動生成クラスなどは、どうしてもコード量が多くなることがあります。
そのような場合、partial classでファイルを分けることで、管理しやすくなることがあります。
たとえば、画面の初期化処理、イベント処理、入力チェック処理を分けると、目的の処理を探しやすくなります。
C#MainWindow.Initialize.cs
MainWindow.Events.cs
MainWindow.Validation.cs
ただし、大きなクラスを分割する前に、そのクラスが多くの責務を持ちすぎていないかを確認しましょう。
partial classは便利ですが、設計の問題を根本的に解決する機能ではありません。
4-5. 保守性を高められるケース
partial classは、正しく使えば保守性を高められます。
特に、次のようなケースでは効果があります。
C#// 自動生成コードと手書きコードを分ける
// UIデザイナーが生成するコードとイベント処理を分ける
// 大きなクラスの中で役割ごとに整理する
保守性が高いコードとは、変更箇所がわかりやすく、影響範囲を把握しやすいコードです。
partial classでファイルを分けることで、どこに何を書くべきかが明確になる場合があります。
ただし、分割ルールが曖昧だと逆効果です。
「なぜ分けるのか」が明確なときに使うのが、partial classを上手に使うコツです。
5. C# partial classを使う際の注意点
5-1. 分割しすぎると逆に読みにくくなる
partial classは便利ですが、分割しすぎると逆に読みにくくなります。
たとえば、1つのクラスが次のように細かく分かれているとします。
C#User.Name.cs
User.Age.cs
User.Email.cs
User.Login.cs
User.Logout.cs
User.Print.cs
User.Check.cs
このように分かれすぎていると、全体像を把握するのが難しくなります。
「このメソッドはどのファイルにあるのか」
「このプロパティはどこで定義されているのか」
「似たような処理が別ファイルにないか」
といった確認に時間がかかります。
partial classは、整理のために使うものです。分割そのものが目的にならないようにしましょう。
5-2. 同じメンバーを重複定義できない
partial classでは、同じクラスを複数ファイルに分けて書けますが、同じメンバーを重複して定義することはできません。
たとえば、次のようなコードはエラーになります。
C#// User.Part1.cs
public partial class User
{
public string Name { get; set; }
}
C#// User.Part2.cs
public partial class User
{
public string Name { get; set; }
}
どちらにもNameプロパティが定義されているため、コンパイラは重複定義として扱います。
メソッドも同じです。
C#public partial class User
{
public void Show()
{
}
}
C#public partial class User
{
public void Show()
{
}
}
同じシグネチャのメソッドを複数定義するとエラーになります。
partial classはクラスを分割できるだけで、同じメンバーを複数持てるわけではありません。
5-3. アクセス修飾子や継承指定の整合性に注意する
partial classを複数に分ける場合、アクセス修飾子や継承指定の整合性に注意が必要です。
たとえば、片方でpublic、もう片方でinternalのように矛盾する指定をすると問題になります。
C#public partial class User
{
}
C#internal partial class User
{
}
このように同じクラスなのにアクセス修飾子が一致していないと、エラーになります。
また、継承についても注意が必要です。
C#public partial class User : Person
{
}
C#public partial class User
{
}
このように、片方にだけ継承指定を書くことは可能な場合がありますが、複数の部分で矛盾した基底クラスを指定することはできません。
C#public partial class User : Person
{
}
C#public partial class User : CustomerBase
{
}
C#ではクラスの多重継承はできないため、このような指定はエラーになります。
partial classは最終的に1つのクラスになるため、クラス全体として矛盾がないように書く必要があります。
5-4. partial classに向いていないケース
partial classは、すべての場面に向いているわけではありません。
たとえば、次のようなケースでは使わないほうがよい場合があります。
C#// 単純で小さなクラス
// 責務が多すぎるクラスを無理に整理したいだけの場合
// ファイルを分ける明確な理由がない場合
// 分割すると処理の流れが追いにくくなる場合
小さなクラスをわざわざpartial classにすると、かえって複雑に見えます。
C#public partial class Status
{
public int Code { get; set; }
}
この程度であれば、普通のクラスで十分です。
partial classを使うかどうかは、「分けることで読みやすくなるか」を基準に考えるとよいでしょう。
5-5. 設計の悪さを隠す目的で使わない
partial classでファイルを分けると、一見コードが整理されたように見えます。
しかし、クラス自体が多くの責務を持ちすぎている場合、根本的な問題は残ったままです。
たとえば、1つのUserクラスが次のような処理をすべて持っているとします。
C#// ユーザー情報の管理
// 入力チェック
// データベース保存
// メール送信
// 画面表示
// ログ出力
これをpartial classで分割しても、Userクラスが多くの責務を持ちすぎていることには変わりません。
この場合は、次のように別クラスへ分けることを検討します。
C#User
UserValidator
UserRepository
UserMailer
UserLogger
partial classは、クラスを整理するための手段です。
設計の問題を隠すために使うものではありません。
6. partial classと関連機能の違い
6-1. partial classとpartial methodの違い
partial classは、クラス定義を複数に分ける機能です。
一方、partial methodは、メソッドの宣言と実装を分けるための機能です。
C#public partial class User
{
partial void OnCreated();
}
C#public partial class User
{
partial void OnCreated()
{
Console.WriteLine("作成されました");
}
}
partial methodは、主に自動生成コードの中に拡張ポイントを用意する目的で使われます。
たとえば、自動生成コード側で次のように呼び出しだけを書いておきます。
C#public partial class User
{
public User()
{
OnCreated();
}
partial void OnCreated();
}
そして、手書きコード側で必要に応じて実装します。
C#public partial class User
{
partial void OnCreated()
{
Console.WriteLine("Userが作成されました");
}
}
partial classはクラスの分割、partial methodはメソッドの一部定義と考えると理解しやすいです。
6-2. partial classと継承の違い
partial classと継承は、どちらもクラスに関係する機能ですが、目的がまったく違います。
partial classは、同じクラスを複数ファイルに分ける機能です。
C#public partial class User
{
public string Name { get; set; }
}
C#public partial class User
{
public void ShowName()
{
Console.WriteLine(Name);
}
}
これは最終的に1つのUserクラスになります。
一方、継承は、あるクラスをもとに別のクラスを作る機能です。
C#public class Person
{
public string Name { get; set; }
}
C#public class Employee : Person
{
public int EmployeeId { get; set; }
}
この場合、PersonとEmployeeは別々のクラスです。
partial classは「同じクラスを分けて書く」
継承は「別のクラスをもとに新しいクラスを作る」
という違いがあります。
6-3. partial classと拡張メソッドの違い
拡張メソッドは、既存の型にメソッドを追加したように見せる機能です。
C#public static class StringExtensions
{
public static bool IsEmpty(this string value)
{
return string.IsNullOrEmpty(value);
}
}
このように書くと、stringにIsEmptyメソッドが追加されたように使えます。
C#string text = "";
bool result = text.IsEmpty();
一方、partial classは、同じクラスの定義を複数ファイルに分ける機能です。
C#public partial class User
{
public string Name { get; set; }
}
C#public partial class User
{
public void ShowName()
{
Console.WriteLine(Name);
}
}
拡張メソッドは、元のクラスを直接変更できない場合にも使えます。
しかし、partial classは同じプロジェクト内で同じ型の定義を分割するためのものです。
partial classはクラス本体を分ける機能、拡張メソッドは外側からメソッドを追加したように見せる機能です。
6-4. partial classとnamespace分割の違い
namespaceは、クラスなどを分類するための名前の空間です。
C#namespace MyApp.Models
{
public class User
{
}
}
名前空間を使うことで、同じ名前のクラスでも区別できます。
C#namespace MyApp.Models
{
public class User
{
}
}
C#namespace MyApp.ViewModels
{
public class User
{
}
}
この場合、2つのUserは別のクラスです。
一方、partial classは、同じ名前空間内の同じクラスを複数ファイルに分ける機能です。
C#namespace MyApp.Models
{
public partial class User
{
public string Name { get; set; }
}
}
C#namespace MyApp.Models
{
public partial class User
{
public void Show()
{
Console.WriteLine(Name);
}
}
}
namespaceは型を分類するための仕組み、partial classは1つの型の定義を分割する仕組みです。
7. 初心者が理解しやすいpartial classのサンプルコード
7-1. 基本的なpartial classのサンプル
まずは、最も基本的なpartial classの例です。
C#// Person.Name.cs
public partial class Person
{
public string Name { get; set; }
}
C#// Person.Greeting.cs
public partial class Person
{
public void SayHello()
{
Console.WriteLine($"こんにちは、{Name}さん");
}
}
使う側のコードは通常のクラスと同じです。
C#var person = new Person();
person.Name = "佐藤";
person.SayHello();
実行結果は次のようになります。
C#こんにちは、佐藤さん
NameプロパティとSayHelloメソッドは別々のファイルにありますが、同じPersonクラスのメンバーとして扱われます。
7-2. プロパティとメソッドを別ファイルに分ける例
次に、プロパティとメソッドを別ファイルに分ける例です。
C#// Book.Properties.cs
public partial class Book
{
public string Title { get; set; }
public int Price { get; set; }
}
C#// Book.Methods.cs
public partial class Book
{
public void ShowDetail()
{
Console.WriteLine($"タイトル: {Title}");
Console.WriteLine($"価格: {Price}円");
}
}
呼び出し側は次のようになります。
C#var book = new Book();
book.Title = "C#入門";
book.Price = 3000;
book.ShowDetail();
実行結果は次のとおりです。
C#タイトル: C#入門
価格: 3000円
このように、データを表すプロパティと、処理を表すメソッドを分けて管理できます。
ただし、クラスが小さいうちは無理に分ける必要はありません。
7-3. 自動生成コードを想定した実用例
実務では、自動生成コードと手書きコードを分ける目的でpartial classがよく使われます。
たとえば、次のような自動生成ファイルがあるとします。
C#// Customer.Generated.cs
public partial class Customer
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
このファイルはツールによって生成されるため、直接編集しないほうが安全です。
そこで、手書き用のファイルを用意します。
C#// Customer.cs
public partial class Customer
{
public string FullName
{
get
{
return $"{LastName} {FirstName}";
}
}
public void ShowFullName()
{
Console.WriteLine(FullName);
}
}
使う側は次のようになります。
C#var customer = new Customer();
customer.FirstName = "太郎";
customer.LastName = "山田";
customer.ShowFullName();
実行結果は次のようになります。
C#山田 太郎
自動生成されたFirstNameやLastNameを使いながら、自分でFullNameやShowFullNameを追加できます。
7-4. エラーになりやすい書き方の例
partial classでは、いくつか初心者が間違えやすいポイントがあります。
まず、片方にpartialを付け忘れる例です。
C#public partial class User
{
public string Name { get; set; }
}
C#public class User
{
public int Age { get; set; }
}
同じクラスを分割したい場合は、すべての定義にpartialを付ける必要があります。
次に、名前空間が違う例です。
C#namespace App.Models
{
public partial class User
{
public string Name { get; set; }
}
}
C#namespace App.Services
{
public partial class User
{
public void Show()
{
}
}
}
この場合、同じUserという名前でも、別のクラスとして扱われます。
また、同じメンバーを重複して定義するのもエラーです。
C#public partial class User
{
public string Name { get; set; }
}
C#public partial class User
{
public string Name { get; set; }
}
partial classを使うときは、同じクラスにまとめられる条件と、重複定義に注意しましょう。
8. C# partial classを使うべき場面・使わないほうがよい場面
8-1. partial classを使うべき代表的な場面
partial classを使うべき代表的な場面は、自動生成コードと手書きコードを分けたい場合です。
たとえば、Windows Formsのデザイナーコード、WPFのコードビハインド、Entity Frameworkのエンティティ拡張などです。
C#// 自動生成コード
public partial class Invoice
{
public int Id { get; set; }
public decimal Amount { get; set; }
}
C#// 手書きコード
public partial class Invoice
{
public bool IsHighValue()
{
return Amount >= 100000;
}
}
また、大きなクラスを役割ごとに整理したい場合にも使えます。
C#Invoice.Properties.cs
Invoice.Calculation.cs
Invoice.Validation.cs
ただし、分割する理由が明確であることが重要です。
8-2. partial classを避けたほうがよい場面
partial classを避けたほうがよいのは、分割する理由がない場合です。
たとえば、小さなクラスであれば、1つのファイルにまとめたほうが読みやすいです。
C#public class Category
{
public int Id { get; set; }
public string Name { get; set; }
}
このようなクラスを無理にpartial classにする必要はありません。
また、クラスの責務が多すぎることを隠すために使うのも避けましょう。
C#User.Database.cs
User.Mail.cs
User.Log.cs
User.View.cs
このような分け方になっている場合、Userクラスが多くのことをしすぎている可能性があります。
その場合は、partial classではなく、クラス設計を見直すべきです。
8-3. クラス分割・設計見直しとの判断基準
partial classを使うべきか、別クラスに分けるべきか迷ったときは、責務に注目しましょう。
同じ概念の一部として自然にまとまる処理であれば、partial classで分けてもよい場合があります。
C#Customer.Properties.cs
Customer.Validation.cs
一方、明らかに別の役割を持つ処理は、別クラスに分けることを検討します。
C#Customer
CustomerValidator
CustomerRepository
CustomerService
判断の目安は次のとおりです。
C#// 同じクラスの一部として自然か
// 自動生成コードとの分離が目的か
// 分けることで読みやすくなるか
// 別クラスにしたほうが責務が明確にならないか
partial classはファイルを分ける機能であり、設計を改善する万能な方法ではありません。
8-4. 初心者が迷ったときの考え方
初心者がpartial classを使うべきか迷ったときは、まず普通のclassで書くのがおすすめです。
クラスが小さいうちは、1つのファイルにまとまっているほうが理解しやすいです。
partial classは、次のような必要性が出てきたときに使うとよいでしょう。
C#// 自動生成コードを直接編集したくない
// Windows FormsやWPFでデザイナーコードと分けたい
// 1つのクラスが大きくなり、役割ごとに整理したい
// チーム開発で編集箇所を分けたい
特に、自動生成コードが関係しない通常の業務ロジックでは、partial classよりもクラス設計の見直しを優先したほうがよいことが多いです。
「分けられるから分ける」のではなく、「分ける理由があるから使う」と考えましょう。
9. C# partial classに関するよくある質問
9-1. partial classは別々のクラスになるのか?
いいえ、partial classは別々のクラスになるわけではありません。
同じ名前空間、同じクラス名で定義されたpartial classは、コンパイル時に1つのクラスとして扱われます。
C#public partial class User
{
public string Name { get; set; }
}
C#public partial class User
{
public void Show()
{
Console.WriteLine(Name);
}
}
この2つは、最終的に1つのUserクラスになります。
そのため、片方のファイルで定義したNameを、もう一方のファイルのShowメソッドから使えます。
9-2. partial classは別のプロジェクトに分けられるのか?
基本的に、partial classとしてまとめられるのは、同じアセンブリとしてコンパイルされるコードです。
別のプロジェクトに分けたクラスは、通常は同じpartial classとして結合できません。
たとえば、プロジェクトAに次のクラスがあるとします。
C#public partial class User
{
public string Name { get; set; }
}
プロジェクトBに同じ名前のpartial classを書いても、通常は1つのクラスとして結合されるわけではありません。
C#public partial class User
{
public void Show()
{
}
}
partial classは、同じコンパイル単位内でクラス定義を分割するための機能です。
別プロジェクトから機能を追加したい場合は、継承や拡張メソッドなどを検討します。
9-3. partial classでprivateメンバーは共有できるのか?
はい、partial classでは、別ファイルに書かれていても同じクラスとして扱われるため、privateメンバーを共有できます。
C#// User.Part1.cs
public partial class User
{
private string name = "田中";
}
C#// User.Part2.cs
public partial class User
{
public void ShowName()
{
Console.WriteLine(name);
}
}
この場合、nameはprivateですが、同じUserクラスのメンバーなので、別ファイルにあるShowNameメソッドから参照できます。
これは、partial classが実際には1つのクラスとして扱われるためです。
ただし、privateメンバーを多用しすぎると、どのファイルで使われているのか追いにくくなることがあります。
9-4. partial classはパフォーマンスに影響するのか?
通常、partial class自体が実行時のパフォーマンスに影響することはありません。
partial classは、ソースコードを複数のファイルに分けて書くための機能です。
コンパイル時には1つのクラスとして扱われるため、実行時に分割ファイルを探したり、結合したりするわけではありません。
つまり、次のように書いても、
C#public partial class User
{
public string Name { get; set; }
}
C#public partial class User
{
public void Show()
{
Console.WriteLine(Name);
}
}
コンパイル後は通常のクラスと同じように扱われます。
パフォーマンスよりも、コードの読みやすさや管理しやすさを考えて使う機能です。
9-5. partial classはどんな現場で使われているのか?
partial classは、主に自動生成コードが関係する現場でよく使われています。
代表的な例は次のような場面です。
C#// Windows Formsのフォームクラス
// WPFの画面クラス
// Entity Frameworkなどのエンティティクラス
// ツールによって生成されるモデルクラス
// 大規模な業務アプリケーションの一部
特に、Windows FormsではForm1.csとForm1.Designer.csのように、開発者が書くコードとデザイナーが生成するコードを分けるために使われます。
WPFでも、XAMLと対応するコードビハインドでpartial classが使われます。
また、コード生成ツールで作られたクラスを、手書きコードで安全に拡張したい場合にも使われます。
実務では、partial classは「自動生成コードを壊さずに拡張するための仕組み」として使われることが多いです。
まとめ
C#のpartial classは、1つのクラスを複数のファイルに分けて定義できる機能です。
C#public partial class User
{
public string Name { get; set; }
}
C#public partial class User
{
public void ShowName()
{
Console.WriteLine(Name);
}
}
このように分けて書いても、コンパイル時には1つのUserクラスとして扱われます。
partial classの主なメリットは、自動生成コードと手書きコードを分離できること、大きなクラスを役割ごとに整理できること、チーム開発で作業範囲を分けやすいことです。
一方で、分割しすぎるとコードが読みにくくなったり、設計の悪さを隠してしまったりする可能性もあります。
partial classは便利な機能ですが、何でも分ければよいわけではありません。
初心者のうちは、まず通常のclassを基本として理解し、自動生成コードや画面デザイナーなどで必要になったときにpartial classを使うとよいでしょう。
partial classは、正しく使えばC#のコードを整理し、保守しやすくするための強力な仕組みです。

