C# protectedとは?private・publicとの違いから継承での使い方まで初心者向けに解説

はじめに

C#を学び始めると、publicprivateと一緒にprotectedというキーワードが出てきます。特にクラスの継承を学ぶ場面でよく登場するため、「privateやpublicと何が違うの?」「いつ使えばいいの?」と迷いやすいポイントです。

protectedは、簡単にいうと「同じクラス内と、継承したクラスから使えるようにする」ためのアクセス修飾子です。

この記事では、C#のprotectedについて、初心者にもわかりやすいように、privatepublicとの違い、基本的な書き方、継承での使い方、よくあるエラーまで順番に解説します。

1. C#のprotectedとは?初心者向けに意味をわかりやすく解説

C#のprotectedは、クラスのメンバーに対してアクセスできる範囲を制限するためのキーワードです。

ここでいうメンバーとは、フィールド、メソッド、プロパティなど、クラスの中に定義する要素のことです。

C#
class Parent
{
protected string message = "こんにちは";
}

この例では、messageというフィールドにprotectedを指定しています。

protectedを指定したメンバーは、クラスの外部からは直接アクセスできません。しかし、そのクラスを継承したクラスからはアクセスできます。

1-1. protectedは「継承先のクラスから使える」アクセス修飾子

protectedの大きな特徴は、継承先のクラス、つまり派生クラスから使えることです。

たとえば、次のような親クラスと子クラスがあるとします。

C#
class Animal
{
protected string name = "動物";
}

class Dog : Animal
{
public void ShowName()
{
Console.WriteLine(name);
}
}

DogクラスはAnimalクラスを継承しています。そのため、Animalクラスの中にあるprotectednameフィールドにアクセスできます。

privateであれば、継承先のDogクラスからもアクセスできません。protectedは、継承を前提としたクラス設計でよく使われます。

1-2. protectedでできること・できないこと

protectedでできることは、主に次のような内容です。

protectedを指定したメンバーは、同じクラス内からアクセスできます。また、そのクラスを継承した派生クラスからもアクセスできます。

一方で、クラスの外部からは直接アクセスできません。

C#
class Animal
{
protected string name = "動物";
}

class Dog : Animal
{
public void Bark()
{
Console.WriteLine(name); // 派生クラスなのでアクセスできる
}
}

class Program
{
static void Main()
{
Dog dog = new Dog();
// dog.name = "犬"; // エラー:外部からprotectedメンバーにはアクセスできない
}
}

このように、protectedは「外部には見せたくないけれど、継承したクラスでは使いたい」場合に便利です。

1-3. protectedがよく使われる場面

protectedは、主に継承を使った設計で利用されます。

たとえば、複数のクラスで共通して使う処理を基底クラスに用意し、それを派生クラスで再利用したい場合です。

C#
class BasePage
{
protected void Log(string message)
{
Console.WriteLine($"ログ: {message}");
}
}

class UserPage : BasePage
{
public void Show()
{
Log("ユーザーページを表示しました");
}
}

この例では、BasePageクラスにLogメソッドを用意しています。UserPageクラスはBasePageを継承しているため、Logメソッドを呼び出せます。

ただし、外部から直接Logメソッドを呼び出すことはできません。内部処理としてだけ使わせたい場合に適しています。

2. C#のアクセス修飾子とは?protectedを理解する前提知識

protectedを理解するには、まずC#のアクセス修飾子について知っておく必要があります。

アクセス修飾子とは、クラスやメンバーに対して「どこから使えるか」を指定するキーワードです。

代表的なものには、publicprivateprotectedがあります。

2-1. アクセス修飾子の役割

アクセス修飾子の役割は、プログラムの部品を安全に管理することです。

すべての変数やメソッドをどこからでも自由に使えるようにすると、意図しない場所から値を変更されたり、内部処理を直接呼び出されたりする可能性があります。

そのため、C#ではアクセス修飾子を使って、必要な範囲だけに公開します。

C#
class User
{
private string password;
public string Name { get; set; }

public void Login()
{
// ログイン処理
}
}

この例では、passwordprivateにして外部から直接触れないようにし、NameLoginpublicにして外部から使えるようにしています。

このように、アクセス修飾子はクラスの安全性や使いやすさを保つために重要です。

2-2. public・private・protectedの基本

C#でよく使われるアクセス修飾子には、次の3つがあります。

publicは、どこからでもアクセスできる指定です。外部から使わせたいメソッドやプロパティに使います。

privateは、同じクラスの中からしかアクセスできない指定です。外部に見せる必要がない内部データや内部処理に使います。

protectedは、同じクラス内と派生クラスからアクセスできる指定です。継承先で使いたいが、外部には公開したくないメンバーに使います。

C#
class Sample
{
public string PublicValue = "外部から使える";
private string PrivateValue = "同じクラス内だけ";
protected string ProtectedValue = "派生クラスから使える";
}

この3つの違いを理解すると、c# protectedの使いどころがかなりわかりやすくなります。

2-3. クラス・メソッド・フィールド・プロパティに指定できる

アクセス修飾子は、メソッド、フィールド、プロパティなどに指定できます。

C#
class Product
{
private int id;

protected decimal price;

public string Name { get; set; }

public void Show()
{
Console.WriteLine(Name);
}
}

ただし、通常のトップレベルクラスにprotectedを指定することはできません。

C#
// protected class Sample
// {
// }

このような書き方はできません。

protectedは主に、クラスの中にあるメンバーに対して使うものと考えるとわかりやすいです。なお、クラスの中に定義する入れ子クラスにはprotectedを指定できる場合がありますが、初心者のうちはフィールド、メソッド、プロパティでの使い方を優先して覚えれば問題ありません。

3. protectedとprivate・publicの違い

protectedは、privatepublicの中間のような位置づけです。

publicほど広く公開せず、privateほど厳しく隠さない、という特徴があります。

3-1. publicとの違い:どこからでもアクセスできるか

publicは、クラスの外部からでもアクセスできます。

C#
class User
{
public string Name = "山田";
}

class Program
{
static void Main()
{
User user = new User();
Console.WriteLine(user.Name); // アクセスできる
}
}

publicNameフィールドは、Programクラスからでも直接アクセスできます。

一方、protectedは外部から直接アクセスできません。

C#
class User
{
protected string Name = "山田";
}

class Program
{
static void Main()
{
User user = new User();
// Console.WriteLine(user.Name); // エラー
}
}

protectedは、あくまで同じクラス内または派生クラスから使うためのものです。外部に公開したい場合はpublicを使います。

3-2. privateとの違い:派生クラスからアクセスできるか

privateは、同じクラス内からしかアクセスできません。

C#
class Animal
{
private string name = "動物";
}

class Dog : Animal
{
public void ShowName()
{
// Console.WriteLine(name); // エラー:privateなので派生クラスからも使えない
}
}

DogクラスはAnimalクラスを継承していますが、privatenameにはアクセスできません。

これをprotectedにすると、派生クラスからアクセスできるようになります。

C#
class Animal
{
protected string name = "動物";
}

class Dog : Animal
{
public void ShowName()
{
Console.WriteLine(name); // OK
}
}

つまり、privateprotectedの大きな違いは、派生クラスからアクセスできるかどうかです。

3-3. protected・private・publicの比較表

アクセス修飾子同じクラス内派生クラス外部クラス
public
protected×
private××

この表を見ると、protectedpublicよりも公開範囲が狭く、privateよりも公開範囲が広いことがわかります。

外部に公開したいならpublic、完全に隠したいならprivate、継承先だけに使わせたいならprotectedと覚えるとよいでしょう。

3-4. 初心者が混同しやすいポイント

初心者が混同しやすいのは、「protectedならインスタンスからアクセスできる」と思ってしまう点です。

たとえば、次のコードはエラーになります。

C#
class Animal
{
protected string name = "動物";
}

class Program
{
static void Main()
{
Animal animal = new Animal();
// animal.name = "犬"; // エラー
}
}

protectedは、外部クラスからインスタンスを通してアクセスするためのものではありません。

また、「同じプロジェクト内ならアクセスできる」と誤解することもあります。しかし、protectedは同じプロジェクトかどうかではなく、継承関係があるかどうかが重要です。

同じプロジェクト内でも、継承していないクラスからはアクセスできません。

4. protectedの基本的な書き方とサンプルコード

ここからは、protectedの基本的な書き方を見ていきます。

protectedは、フィールド、メソッド、プロパティなどに指定できます。

4-1. protectedフィールドの書き方

フィールドにprotectedを指定する場合は、次のように書きます。

C#
class Character
{
protected int hp = 100;
}

このhpフィールドは、Characterクラス内と、Characterを継承したクラスからアクセスできます。

C#
class Player : Character
{
public void ShowHp()
{
Console.WriteLine($"HP: {hp}");
}
}

PlayerクラスはCharacterクラスを継承しているため、hpフィールドを使えます。

ただし、フィールドを直接protectedにすると、派生クラスから自由に値を変更できるようになります。大きなプログラムでは、フィールドを直接公開するより、protectedなプロパティやメソッドを使う設計が好まれることもあります。

4-2. protectedメソッドの書き方

メソッドにprotectedを指定する場合は、次のように書きます。

C#
class Report
{
protected void PrintHeader()
{
Console.WriteLine("=== レポート ===");
}
}

派生クラスからは、このPrintHeaderメソッドを呼び出せます。

C#
class SalesReport : Report
{
public void Print()
{
PrintHeader();
Console.WriteLine("売上データを表示します");
}
}

PrintHeaderは外部から直接呼び出せませんが、SalesReportクラスの中では利用できます。

共通処理を基底クラスにまとめたいときに、protectedメソッドはよく使われます。

4-3. protectedプロパティの書き方

プロパティにprotectedを指定することもできます。

C#
class Account
{
protected decimal Balance { get; set; } = 1000;
}

派生クラスでは、このプロパティを使えます。

C#
class SavingsAccount : Account
{
public void AddInterest()
{
Balance += 100;
Console.WriteLine($"残高: {Balance}");
}
}

プロパティを使うと、単なるフィールドよりも後から処理を追加しやすくなります。

たとえば、値のチェックや計算処理を追加したい場合にも、プロパティの方が柔軟です。

4-4. protectedメンバーにアクセスできる例

次のコードは、protectedメンバーに正しくアクセスできる例です。

C#
using System;

class Vehicle
{
protected int speed = 0;

protected void SetSpeed(int value)
{
speed = value;
}
}

class Car : Vehicle
{
public void Drive()
{
SetSpeed(60);
Console.WriteLine($"速度: {speed}km/h");
}
}

class Program
{
static void Main()
{
Car car = new Car();
car.Drive();

// car.speed = 100; // エラー
// car.SetSpeed(100); // エラー
}
}

CarクラスはVehicleクラスを継承しているため、speedフィールドとSetSpeedメソッドを使えます。

しかし、ProgramクラスはVehicleCarを継承していないため、protectedメンバーにはアクセスできません。

5. protectedを継承で使う方法

protectedは、継承と組み合わせて使うことで意味を持ちます。

継承とは、あるクラスの機能を別のクラスが引き継ぐ仕組みです。

5-1. 基底クラスと派生クラスの関係

継承元のクラスを基底クラス、継承先のクラスを派生クラスと呼びます。

C#
class BaseClass
{
}

class DerivedClass : BaseClass
{
}

この例では、BaseClassが基底クラス、DerivedClassが派生クラスです。

protectedメンバーは、基底クラスの中に定義しておくと、派生クラスから利用できます。

C#
class BaseClass
{
protected void CommonMethod()
{
Console.WriteLine("共通処理です");
}
}

class DerivedClass : BaseClass
{
public void Execute()
{
CommonMethod();
}
}

このように、共通処理を基底クラスにまとめて、派生クラスで使い回すことができます。

5-2. 派生クラスからprotectedメンバーを呼び出す方法

派生クラスからprotectedメンバーを呼び出す場合は、通常のメソッドやフィールドと同じように使えます。

C#
class Employee
{
protected string department = "開発部";

protected void Work()
{
Console.WriteLine("仕事をします");
}
}

class Engineer : Employee
{
public void Develop()
{
Console.WriteLine(department);
Work();
Console.WriteLine("開発をします");
}
}

また、baseキーワードを使って、基底クラスのメンバーであることを明示することもできます。

C#
class Engineer : Employee
{
public void Develop()
{
Console.WriteLine(base.department);
base.Work();
}
}

baseを使うと、基底クラスのメンバーを呼び出していることがわかりやすくなります。特に、派生クラス側に同じ名前のメンバーがある場合に役立ちます。

5-3. 外部クラスからprotectedメンバーにアクセスできない理由

protectedメンバーに外部クラスからアクセスできないのは、クラスの内部実装を隠すためです。

たとえば、次のようなクラスがあるとします。

C#
class BankAccount
{
protected decimal balance = 1000;
}

もし外部から自由にbalanceを変更できると、不正な値を設定される可能性があります。

C#
class Program
{
static void Main()
{
BankAccount account = new BankAccount();
// account.balance = -999999; // エラーになるので安全
}
}

protectedにしておけば、外部から直接操作されることを防ぎつつ、派生クラスでは必要に応じて利用できます。

これは、オブジェクト指向プログラミングのカプセル化にも関係します。カプセル化とは、外部に見せる必要がない情報を隠し、必要な機能だけを公開する考え方です。

5-4. protectedを使った実践的な継承サンプル

次は、protectedを使った実践的なサンプルです。

C#
using System;

class Notification
{
protected string title;

public Notification(string title)
{
this.title = title;
}

protected void WriteLog(string message)
{
Console.WriteLine($"ログ: {message}");
}
}

class EmailNotification : Notification
{
public EmailNotification(string title) : base(title)
{
}

public void Send()
{
Console.WriteLine($"メール通知: {title}");
WriteLog("メール通知を送信しました");
}
}

class Program
{
static void Main()
{
EmailNotification notification = new EmailNotification("会員登録完了");
notification.Send();

// notification.title = "変更"; // エラー
// notification.WriteLog("テスト"); // エラー
}
}

このコードでは、NotificationクラスにprotectedtitleフィールドとWriteLogメソッドを定義しています。

EmailNotificationクラスはNotificationを継承しているため、titleWriteLogを利用できます。

一方で、Programクラスからは直接アクセスできません。これにより、外部に公開する操作はSendメソッドに限定できます。

6. protectedでよくあるエラーと原因

protectedは便利ですが、初心者がつまずきやすいエラーもあります。

ここでは、よくあるケースを紹介します。

6-1. 外部クラスからアクセスしてコンパイルエラーになるケース

最もよくあるのは、外部クラスからprotectedメンバーにアクセスしようとしてエラーになるケースです。

C#
class Person
{
protected string name = "太郎";
}

class Program
{
static void Main()
{
Person person = new Person();
// Console.WriteLine(person.name); // エラー
}
}

ProgramクラスはPersonクラスを継承していないため、nameにはアクセスできません。

外部から使わせたい場合は、publicなメソッドやプロパティを用意します。

C#
class Person
{
protected string name = "太郎";

public string GetName()
{
return name;
}
}

このようにすれば、内部データはprotectedのままにしつつ、必要な情報だけを外部に公開できます。

6-2. インスタンス経由でアクセスできないケース

派生クラスの中であっても、アクセスの仕方によってはエラーになることがあります。

C#
class Parent
{
protected int value = 10;
}

class Child : Parent
{
public void Test(Parent parent)
{
// Console.WriteLine(parent.value); // エラーになる場合がある
}
}

ChildクラスはParentを継承していますが、Parent型のインスタンスを通してprotectedメンバーへ自由にアクセスできるわけではありません。

派生クラス自身のメンバーとして使う場合は、次のように書けます。

C#
class Child : Parent
{
public void Test()
{
Console.WriteLine(value); // OK
Console.WriteLine(this.value); // OK
}
}

初心者のうちは、protectedは「派生クラスの中で、自分が引き継いだメンバーとして使う」と考えると理解しやすいです。

6-3. privateとprotectedを間違えて継承先で使えないケース

基底クラスでprivateにしているメンバーは、派生クラスからアクセスできません。

C#
class BaseClass
{
private void Setup()
{
Console.WriteLine("初期設定");
}
}

class DerivedClass : BaseClass
{
public void Start()
{
// Setup(); // エラー
}
}

派生クラスでも使いたい場合は、privateではなくprotectedにします。

C#
class BaseClass
{
protected void Setup()
{
Console.WriteLine("初期設定");
}
}

class DerivedClass : BaseClass
{
public void Start()
{
Setup(); // OK
}
}

ただし、何でもprotectedにすればよいわけではありません。本当に派生クラスで使う必要があるものだけをprotectedにしましょう。

6-4. エラーを防ぐ確認ポイント

protectedでエラーが出たときは、まずアクセスしている場所を確認しましょう。

そのコードは、同じクラス内にありますか。派生クラスの中にありますか。それとも、まったく関係のない外部クラスからアクセスしていませんか。

次に、メンバーのアクセス修飾子を確認します。派生クラスから使いたいのにprivateになっていないかを見てください。

また、外部から使いたいメンバーであれば、protectedではなくpublicにする必要があるかもしれません。

判断に迷う場合は、次のように考えると整理しやすいです。

外部から使わせたいならpublic、同じクラス内だけで使いたいならprivate、派生クラスでも使いたいならprotectedです。

7. protectedを使うメリット・デメリット

protectedには便利な点がありますが、使いすぎるとコードがわかりにくくなることもあります。

メリットとデメリットを理解したうえで使いましょう。

7-1. メリット:共通処理を派生クラスで再利用できる

protectedの大きなメリットは、基底クラスに共通処理をまとめて、派生クラスで再利用できることです。

C#
class ControllerBase
{
protected void Validate()
{
Console.WriteLine("入力チェックを行います");
}
}

class UserController : ControllerBase
{
public void CreateUser()
{
Validate();
Console.WriteLine("ユーザーを作成します");
}
}

この例では、Validateメソッドを基底クラスに定義し、派生クラスで利用しています。

複数の派生クラスで同じ処理を使う場合、重複したコードを書かずに済みます。

7-2. メリット:外部からの不要なアクセスを防げる

protectedを使うと、外部から直接アクセスされたくない処理を隠せます。

C#
class ServiceBase
{
protected void ConnectDatabase()
{
Console.WriteLine("データベースに接続します");
}
}

このConnectDatabaseメソッドは、派生クラスでは使えますが、外部からは直接呼び出せません。

外部に公開する必要がない内部処理を隠せるため、クラスの使い方を限定できます。

これは、誤った使われ方を防ぐうえでも重要です。

7-3. デメリット:継承関係が複雑になると管理しづらい

protectedのデメリットは、継承関係が複雑になると、どのクラスがどのメンバーを使っているのか把握しづらくなることです。

たとえば、基底クラスに多くのprotectedメンバーがあると、派生クラスがそれらに強く依存してしまいます。

C#
class BaseClass
{
protected int value1;
protected int value2;
protected int value3;
protected void Method1() { }
protected void Method2() { }
}

このような状態になると、基底クラスを変更したときに、どの派生クラスへ影響するのか確認が大変になります。

protectedは便利ですが、公開範囲を広げることには変わりありません。privateよりも慎重に扱う必要があります。

7-4. protectedを使いすぎないための考え方

protectedを使う前に、「本当に派生クラスから直接使う必要があるか」を考えましょう。

単に値を保持したいだけなら、privateにしておく方が安全です。

派生クラスごとに処理を変えたい場合は、protected virtualメソッドを用意して、必要に応じてoverrideする設計もあります。

C#
class Animal
{
public void Move()
{
Prepare();
Console.WriteLine("移動します");
}

protected virtual void Prepare()
{
Console.WriteLine("準備します");
}
}

class Bird : Animal
{
protected override void Prepare()
{
Console.WriteLine("羽を広げます");
}
}

このように、外部にはMoveだけを公開し、内部の一部処理だけを派生クラスで変更できるようにする方法もあります。

protectedは、必要な範囲だけに絞って使うことが大切です。

8. protected internal・private protectedとの違い

C#には、protectedに似たアクセス修飾子として、protected internalprivate protectedがあります。

名前が似ているため混乱しやすいですが、アクセスできる範囲が異なります。

8-1. protected internalとは

protected internalは、「同じアセンブリ内」または「派生クラス」からアクセスできる指定です。

C#
class BaseClass
{
protected internal void Show()
{
Console.WriteLine("protected internalメソッド");
}
}

同じプロジェクト内のクラスからアクセスできる場合があり、さらに別のアセンブリにある派生クラスからもアクセスできます。

ポイントは、「同じアセンブリ内」または「派生クラス」という条件です。どちらか一方を満たせばアクセスできます。

通常のprotectedよりもアクセスできる範囲が広くなることがあります。

8-2. private protectedとは

private protectedは、「同じアセンブリ内にある派生クラス」からアクセスできる指定です。

C#
class BaseClass
{
private protected void Show()
{
Console.WriteLine("private protectedメソッド");
}
}

protected internalが「同じアセンブリ内、または派生クラス」なのに対して、private protectedは「同じアセンブリ内、かつ派生クラス」という条件です。

つまり、private protectedの方が公開範囲は狭くなります。

8-3. protectedとの使い分け

protectedは、アセンブリに関係なく、派生クラスからアクセスできます。

protected internalは、同じアセンブリ内からもアクセスさせたい場合に使います。

private protectedは、同じアセンブリ内の派生クラスだけに限定したい場合に使います。

比較すると、次のようになります。

アクセス修飾子アクセスできる範囲
protected派生クラスからアクセスできる
protected internal同じアセンブリ内、または派生クラスからアクセスできる
private protected同じアセンブリ内の派生クラスからアクセスできる

ただし、初心者の段階では、まずpublicprivateprotectedをしっかり理解することが大切です。

8-4. 初心者はまずprotected・private・publicを優先して覚える

protected internalprivate protectedは、ライブラリ開発や複数プロジェクトに分かれた開発で使うことがあります。

しかし、C#を学び始めたばかりであれば、最初からすべてを覚える必要はありません。

まずは、次の3つを優先して覚えましょう。

アクセス修飾子覚え方
publicどこからでも使える
private同じクラス内だけで使える
protected同じクラス内と派生クラスから使える

この3つを理解してから、必要に応じてinternalprotected internalprivate protectedを学ぶとスムーズです。

9. protectedを使うべきケース・使わない方がよいケース

protectedは、継承を前提とした設計で役立ちます。

一方で、何でもprotectedにすると、クラスの内部構造が派生クラスに漏れすぎてしまいます。

ここでは、protectedを使うべきケースと、使わない方がよいケースを整理します。

9-1. 継承先で共通処理を利用したい場合

派生クラスで共通処理を使いたい場合は、protectedが適しています。

C#
class FileProcessor
{
protected void CheckFileExists(string path)
{
Console.WriteLine($"{path} の存在を確認します");
}
}

class CsvProcessor : FileProcessor
{
public void ReadCsv(string path)
{
CheckFileExists(path);
Console.WriteLine("CSVを読み込みます");
}
}

このように、ファイルの存在確認など、複数の派生クラスで共通して使う処理を基底クラスにまとめられます。

9-2. 外部には公開したくないが派生クラスには公開したい場合

外部からは使わせたくないけれど、派生クラスには使わせたい処理にもprotectedが向いています。

C#
class GameCharacter
{
protected void TakeDamage(int damage)
{
Console.WriteLine($"{damage}のダメージを受けました");
}
}

class Monster : GameCharacter
{
public void Attacked()
{
TakeDamage(10);
}
}

TakeDamageは外部から直接呼び出す必要はありませんが、派生クラスの中では使いたい処理です。

このような場合にprotectedを使うと、公開範囲を適切に制限できます。

9-3. 単純な値の保持だけならprivateを検討する

単純に値を保持するだけなら、まずprivateを検討しましょう。

C#
class User
{
private string password;
}

たとえば、パスワードや内部IDのような値は、派生クラスからも直接触らせない方が安全です。

派生クラスで使う必要がないなら、protectedにする理由はありません。

必要であれば、publicprotectedのメソッドを通じて、制御された形で値を扱うようにします。

C#
class User
{
private string password;

protected bool CheckPassword(string input)
{
return password == input;
}
}

このように、値そのものはprivateにして、必要な処理だけをprotectedにする方法もあります。

9-4. 外部APIとして使わせたい場合はpublicを検討する

外部のクラスから呼び出して使わせたい機能には、publicを使います。

C#
class Calculator
{
public int Add(int a, int b)
{
return a + b;
}
}

このAddメソッドは、外部から使うことを目的としているためpublicが適切です。

一方、計算前のチェック処理など、外部に公開する必要がないものはprivateprotectedにします。

C#
class Calculator
{
public int Add(int a, int b)
{
Validate(a, b);
return a + b;
}

protected void Validate(int a, int b)
{
Console.WriteLine("値をチェックします");
}
}

外部に使わせる機能はpublic、内部または派生クラス用の補助機能はprivateprotectedと考えると整理しやすいです。

10. C# protectedに関するよくある質問

ここでは、C#のprotectedについて初心者が疑問に感じやすい点をQ&A形式で解説します。

10-1. protectedは同じクラス内から使える?

はい、使えます。

protectedメンバーは、同じクラス内からアクセスできます。

C#
class Sample
{
protected int value = 10;

public void Show()
{
Console.WriteLine(value); // OK
}
}

protectedは、同じクラス内と派生クラスから使えるアクセス修飾子です。

同じクラス内だけでよい場合はprivateでも十分ですが、派生クラスでも使いたい場合はprotectedを使います。

10-2. protectedは別ファイルのクラスから使える?

別ファイルかどうかは関係ありません。

重要なのは、そのクラスが継承関係にあるかどうかです。

C#
class Parent
{
protected void Hello()
{
Console.WriteLine("Hello");
}
}

class Child : Parent
{
public void CallHello()
{
Hello(); // OK
}
}

ParentクラスとChildクラスが別ファイルに書かれていても、ChildParentを継承していればprotectedメンバーにアクセスできます。

一方で、同じファイルに書かれていても、継承していないクラスからはアクセスできません。

C#
class Other
{
public void Test()
{
Parent parent = new Parent();
// parent.Hello(); // エラー
}
}

protectedはファイル単位ではなく、クラスの継承関係で判断されます。

10-3. protectedはインターフェイスで使える?

初心者のうちは、インターフェイスでは基本的にprotectedを使わないと考えて問題ありません。

一般的なインターフェイスは、「外部に対してどのメソッドを実装するか」を示す契約として使われます。そのため、通常はpublicなメンバーとして扱われます。

C#
interface IPrintable
{
void Print();
}

このように、インターフェイスではアクセス修飾子を書かずにメソッドを定義することが多いです。

なお、新しいC#ではインターフェイスに既定実装を持たせる機能などがあり、アクセス修飾子を指定できる場面もあります。ただし、通常のクラスで使うprotectedとは考え方が少し異なるため、初心者はまずクラスの継承におけるprotectedを理解することを優先しましょう。

10-4. protectedとoverrideの関係は?

protectedは、virtualoverrideと一緒に使われることがあります。

基底クラスでprotected virtualメソッドを定義すると、派生クラスでその処理を上書きできます。

C#
class Animal
{
public void Speak()
{
MakeSound();
}

protected virtual void MakeSound()
{
Console.WriteLine("何かの音");
}
}

class Dog : Animal
{
protected override void MakeSound()
{
Console.WriteLine("ワン");
}
}

この例では、外部から呼び出すのはSpeakメソッドです。

内部ではMakeSoundメソッドが呼び出されますが、DogクラスではMakeSoundoverrideして独自の処理に変更しています。

このように、protectedoverrideを組み合わせると、外部に公開する処理は固定しつつ、一部の処理だけを派生クラスで変更できます。

10-5. protectedは初心者でも使うべき?

初心者でも、継承を学ぶ段階ではprotectedを理解しておくべきです。

ただし、最初から多用する必要はありません。

まずは、privatepublicをしっかり使い分けることが大切です。そのうえで、継承したクラスから共通処理を使いたい場面が出てきたら、protectedを使うとよいでしょう。

判断に迷った場合は、次のように考えてください。

外部から使わせる必要があるならpublic、クラス内部だけで使うならprivate、派生クラスでも使う必要があるならprotectedです。

まとめ

C#のprotectedは、同じクラス内と派生クラスからアクセスできるアクセス修飾子です。

publicはどこからでもアクセスでき、privateは同じクラス内からしかアクセスできません。その中間にあるのがprotectedです。

protectedを使うと、外部からの不要なアクセスを防ぎながら、継承先のクラスで共通処理や共通データを利用できます。

一方で、protectedを使いすぎると、基底クラスと派生クラスの関係が複雑になり、管理しづらくなることがあります。

初心者はまず、次のように覚えるとよいでしょう。

アクセス修飾子使える場所主な用途
publicどこからでも外部に公開する機能
private同じクラス内だけ内部だけで使う値や処理
protected同じクラス内と派生クラス継承先で使う共通処理

c# protectedを理解するうえで重要なのは、「外部には公開しないが、継承先には使わせる」という考え方です。

継承を使ったクラス設計では、protectedを適切に使うことで、再利用しやすく安全なコードを書けるようになります。