C#アクセス修飾子を理解する
この記事では、C#における型、メソッド、変数の可視性とアクセシビリティを定義するC#アクセス修飾子について説明します。 ティム・コーリーのビデオ"C# Access Modifiers (beyond public and private) - what they are, how to use them, and best practices"では、さまざまなアクセス修飾子について説明し、コンソールアプリケーションでの実際の使い方を実演しています。
この記事では、理解を深めるためのコード例とともに、Timがカバーする内容を説明します。 提供されるタイムスタンプは、より実践的な体験のためにビデオと一緒にフォローすることができます。
アクセス修飾子とは何ですか?
はじめに
Tim Corey氏はまず、アクセス修飾子について紹介し、C#ではアクセス修飾子がリソースを誰が見たり使ったりできるかを決定すると説明しています。 一般的に使用されるpublic修飾子やprivate修飾子についてはよく知られていますが、Timは6つの異なるアクセス修飾子とその使用例を探ります。
デモ アプリケーションの説明
Timは、さまざまなアクセス修飾子がどのように機能するかを示すために、簡単なアプリケーションをセットアップします。 アプリケーションは、.NETフレームワークのコンソールユーザーインターフェイスとデモライブラリで構成されています。
プロジェクトの構成:
- コンソールUI:アクセス修飾子をテストするためのコンソールアプリケーションです。
- デモライブラリ:さまざまなアクセス修飾子が実演されているクラスライブラリ。
public class AccessDemo
{
private void PrivateDemo() { }
internal void InternalDemo() { }
public void PublicDemo() { }
}public class AccessDemo
{
private void PrivateDemo() { }
internal void InternalDemo() { }
public void PublicDemo() { }
}1.プライベート
内容:
private 修飾子は、メソッド、フィールド、またはプロパティへのアクセスを、それが定義されているクラス内でのみ制限します。
コード例:
public class AccessDemo
{
private void PrivateDemo()
{
Console.WriteLine("Private method can only be accessed within this class.");
}
public void CallPrivateDemo()
{
PrivateDemo(); // Works because it's within the same class
}
}public class AccessDemo
{
private void PrivateDemo()
{
Console.WriteLine("Private method can only be accessed within this class.");
}
public void CallPrivateDemo()
{
PrivateDemo(); // Works because it's within the same class
}
}説明:PrivateDemo メソッドは AccessDemo クラス内でのみアクセス可能です。 ビデオの中でティムは、同じプロジェクト内に他のクラスがあっても、クラスの外からアクセスできないことを実演しています。
ベストプラクティス:クラスの内部動作へのアクセスを制限し、アプリケーションの他の部分から直接変更できないようにしたいときは、privateを使用してください。
2.内部
内容:
内部修飾子は、同じアセンブリ(プロジェクト)内でのみ、メソッドやプロパティへのアクセスを許可します。 これは、同じプロジェクト内のすべてのクラスを含むため、プライベートアクセス修飾子よりも広いです。
コード例:
public class AccessDemo
{
internal void InternalDemo()
{
Console.WriteLine("Internal method is accessible within the same assembly.");
}
}public class AccessDemo
{
internal void InternalDemo()
{
Console.WriteLine("Internal method is accessible within the same assembly.");
}
}説明:InternalDemo メソッドは、同じアセンブリ内の任意のクラスからアクセスできますが、他のアセンブリからはアクセスできません。 ビデオの中でティムは、internalが同じプロジェクト内でのアクセスを許可し、外部からのアクセスを拒否することを示しています。
ベストプラクティス:外部プロジェクトに公開されるべきでないヘルパー関数やユーティリティなど、現在のアセンブリ内でのみ使用されるメソッドやプロパティには internal を使用してください。
3.公開
内容:
public修飾子は、他のクラスやアセンブリからメソッドやプロパティにアクセスできるようにします。 これは最も寛容なアクセスレベルです。
コード例:
public class AccessDemo
{
public void PublicDemo()
{
Console.WriteLine("Public method can be accessed from any class.");
}
}public class AccessDemo
{
public void PublicDemo()
{
Console.WriteLine("Public method can be accessed from any class.");
}
}説明:PublicDemo メソッドは、同じアセンブリ内や他のアセンブリの他のクラスを含め、どこからでもアクセス可能です。 Timは、特にライブラリでメソッドを公開する場合、publicが最も一般的なアクセス修飾子であることを示します。
ベストプラクティス:APIエンドポイントや広く使われているユーティリティなど、アプリケーションの他の部分や外部プロジェクトからアクセスする必要があるメソッドやプロパティにはpublicを使用してください。
4.保護されている
内容:
protected 修飾子は、メソッドやプロパティが定義されているクラス内、および派生クラス(継承)内でのアクセスを許可します。 この修飾子は、オブジェクト指向プログラミング、特に継承の場合に便利です。
コード例:
public class AccessDemo
{
protected void ProtectedDemo()
{
Console.WriteLine("Protected method can be accessed within the class and derived classes.");
}
}
public class DerivedClass : AccessDemo
{
public void CallProtectedDemo()
{
ProtectedDemo(); // Accessible because of inheritance
}
}public class AccessDemo
{
protected void ProtectedDemo()
{
Console.WriteLine("Protected method can be accessed within the class and derived classes.");
}
}
public class DerivedClass : AccessDemo
{
public void CallProtectedDemo()
{
ProtectedDemo(); // Accessible because of inheritance
}
}説明:ProtectedDemo メソッドは、AccessDemo クラスおよびそのクラスを継承する任意のクラスからアクセスできます。 ティムは、protectedはあまり一般的ではないが、継承を扱うときに非常に役に立つと説明する。
ベストプラクティス:派生クラスが特定のメソッドやプロパティにアクセスできるようにしたいが、クラス階層の外からはアクセスさせたくない場合に protected を使用します。
5.プライベート保護
内容:
private protected修飾子は、privateとprotectedのルールを組み合わせたものです。 これは、定義クラスと同じアセンブリ内の派生クラス内のメソッドまたはプロパティへのアクセスを制限します。 つまり、protectedと比較して、継承ベースのアクセス制御の保護レベルと境界がより厳しくなります。
コード例:
public class AccessDemo
{
private protected void PrivateProtectedDemo()
{
Console.WriteLine("Private Protected method can be accessed within the same assembly and derived classes.");
}
}
public class DerivedClass : AccessDemo
{
public void CallPrivateProtectedDemo()
{
PrivateProtectedDemo(); // Accessible because of inheritance within the same assembly
}
}
public class UnrelatedClass
{
public void TestAccess()
{
// PrivateProtectedDemo(); // Error: Not accessible in unrelated classes
}
}public class AccessDemo
{
private protected void PrivateProtectedDemo()
{
Console.WriteLine("Private Protected method can be accessed within the same assembly and derived classes.");
}
}
public class DerivedClass : AccessDemo
{
public void CallPrivateProtectedDemo()
{
PrivateProtectedDemo(); // Accessible because of inheritance within the same assembly
}
}
public class UnrelatedClass
{
public void TestAccess()
{
// PrivateProtectedDemo(); // Error: Not accessible in unrelated classes
}
}説明:PrivateProtectedDemo メソッドは、AccessDemo から継承し、同じアセンブリに存在するため DerivedClass でアクセス可能です。 ただし、このクラスは AccessDemo を継承していないため、UnrelatedClass ではアクセスできません。
ベストプラクティス:private protected アクセス修飾子は、同じアセンブリ内の継承アクセスを厳密に制御する必要がある場合に、控えめに使用してください。 これは、アセンブリ間でメソッドやプロパティを公開するとカプセル化が損なわれる可能性がある場合に特に役立ちます。
6.保護された内部
内容:
protected internal修飾子は、protectedレベルとinternalアクセス修飾子レベルを組み合わせたものです。 同じアセンブリからのアクセスや、派生クラスが別のアセンブリにある場合でもアクセスできるようにします。
コード例:
public class AccessDemo
{
protected internal void ProtectedInternalDemo()
{
Console.WriteLine("Protected Internal method can be accessed within the same assembly or from derived classes.");
}
}
public class DerivedClass : AccessDemo
{
public void CallProtectedInternalDemo()
{
ProtectedInternalDemo(); // Accessible due to inheritance
}
}public class AccessDemo
{
protected internal void ProtectedInternalDemo()
{
Console.WriteLine("Protected Internal method can be accessed within the same assembly or from derived classes.");
}
}
public class DerivedClass : AccessDemo
{
public void CallProtectedInternalDemo()
{
ProtectedInternalDemo(); // Accessible due to inheritance
}
}説明:ProtectedInternalDemo メソッドは、同じアセンブリ内からアクセスでき、アセンブリに関係なく任意の派生クラスからもアクセス可能です。
ベストプラクティス:メソッドを(他のアセンブリの)派生クラスと同じアセンブリのクラスの両方に公開したいが、全員に公開したくない場合に protected internal を使用してください。
なぜすべてを公開しないのですか?
ティム・コリーは、アクセス修飾子を使用することの重要性と、すべてを公開するだけではいけない理由を説明しています。 すべてを公開することは便利に見えるかもしれませんが、データ漏洩、バグ、開発の混乱など、重大なリスクをもたらします。 アクセス修飾子は、情報を保護し、意図しない一般からのアクセスを防ぎ、コードベースを明確にするために存在します。
1.個人情報の保護
Timは、社会保障番号(SSN)やクレジットカード番号などの機密情報を公開すべきではない理由について説明します。 彼は、一般からのアクセスによってデータの漏洩が発生する"悪いクラス"の例を示しています:
悪い例:
public class User
{
public string SSN; // Anyone can access and modify it directly
}public class User
{
public string SSN; // Anyone can access and modify it directly
}良い例:
public class User
{
private string ssn;
public string GetMaskedSSN()
{
return "XXX-XX-" + ssn.Substring(ssn.Length - 4);
}
public void SetSSN(string value)
{
// Add validation if needed
ssn = value;
}
}public class User
{
private string ssn;
public string GetMaskedSSN()
{
return "XXX-XX-" + ssn.Substring(ssn.Length - 4);
}
public void SetSSN(string value)
{
// Add validation if needed
ssn = value;
}
}2.プライベートメソッドの保護
スタート35:11\ ティムは、プライベート・メソッドは、直接アクセスすべきでない動作をカプセル化するのに役立つと説明します。 彼は、従業員のオフボーディングのような大きなプロセスの一部として DeleteUser メソッドを例に用いています。
悪い例:
public class UserManager
{
public void DeleteUser(int userId)
{
// Deletes the user without considering related processes
}
}public class UserManager
{
public void DeleteUser(int userId)
{
// Deletes the user without considering related processes
}
}良い例:
public class UserManager
{
public void OffboardUser(int userId)
{
RevokeAccess(userId);
DeleteUser(userId); // Used privately as part of offboarding
}
private void DeleteUser(int userId)
{
// Internal logic to delete the user
}
private void RevokeAccess(int userId)
{
// Logic to revoke system access
}
}public class UserManager
{
public void OffboardUser(int userId)
{
RevokeAccess(userId);
DeleteUser(userId); // Used privately as part of offboarding
}
private void DeleteUser(int userId)
{
// Internal logic to delete the user
}
private void RevokeAccess(int userId)
{
// Logic to revoke system access
}
}3.バグの防止
アクセス修飾子は、データが適切なバリデーションで設定または取得されるようにすることで、バグを防止します。 Tim は Age プロパティに関する例を示してこれを解説しています。
悪い例:
public class Person
{
public int Age; // Can be directly set to an invalid value
}public class Person
{
public int Age; // Can be directly set to an invalid value
}良い例:
public class Person
{
private int age;
public int Age
{
get { return age; }
set
{
if (value < 0 || value > 120)
throw new ArgumentOutOfRangeException("Age must be between 0 and 120.");
age = value;
}
}
}public class Person
{
private int age;
public int Age
{
get { return age; }
set
{
if (value < 0 || value > 120)
throw new ArgumentOutOfRangeException("Age must be between 0 and 120.");
age = value;
}
}
}4.混乱を減らし、明瞭さを高める
アクセス修飾子を適切に使用することで、必要なものだけを公開して開発を簡素化し、混乱を避けることができます。 たとえば、何千ものメソッドがあるアプリケーションでは、パブリックなメソッドだけを公開することで、開発者は関連するオプションだけを見ることができます。
例:
public class MathLibrary
{
public int Add(int a, int b) => a + b;
public int Subtract(int a, int b) => a - b;
private void LogCalculation(string operation, int result)
{
// Logging is internal and not exposed
}
}public class MathLibrary
{
public int Add(int a, int b) => a + b;
public int Subtract(int a, int b) => a - b;
private void LogCalculation(string operation, int result)
{
// Logging is internal and not exposed
}
}5.大規模なアプリケーションやライブラリにおける利点
大規模なプロジェクトの場合、ティムは、アクセス修飾子を適切に使用することで、ライブラリの必要な部分のみを確実に公開し、ライブラリを使用する開発者の認識負荷を軽減する方法を説明します。
例:
public class MathLibrary
{
public int Add(int a, int b) => a + b;
public int Subtract(int a, int b) => a - b;
private void LogCalculation(string operation, int result)
{
// Logging is internal and not exposed
}
}public class MathLibrary
{
public int Add(int a, int b) => a + b;
public int Subtract(int a, int b) => a - b;
private void LogCalculation(string operation, int result)
{
// Logging is internal and not exposed
}
}これらのアクセス修飾語を正しく使用することで、あなたの仕事と次の人の仕事を楽にすることができます。
結論
Tim Coreyは、C#アクセス修飾子をマスターするための明確で実用的なガイドを提供し、安全で保守性の高い、プロフェッショナルなアプリケーションを作成するための効果的な使用方法を示します。 彼の詳細な説明と実例により、あらゆるレベルの開発者がこのトピックにアクセスできるようになっています。
より深い洞察や、これらのコンセプトが実際に使われている様子をご覧になりたい方は、ぜひティムのビデオをフルでご覧ください。また、C# やその他のプログラミング トピックに関する貴重なコンテンツについては、チャンネルをご覧ください。 開発スキルを向上させたいと真剣に考えている人には、必見のリソースです!

