首頁  >  文章  >  後端開發  >  C# 中的存取修飾符

C# 中的存取修飾符

WBOY
WBOY原創
2024-09-03 15:24:47714瀏覽

本文從 C# 程式語言的角度涵蓋了物件導向程式設計的最基本概念。這個概念被稱為-存取修飾符。要回答的第一個問題是 – 什麼是存取修飾符?簡而言之,存取修飾符控制可以在程式碼的哪一部分存取哪些物件/變數/常數/方法(實際上是所有內容)。存取修飾符在證明物件導向程式設計中的抽象概念方面發揮著重要作用。它們控製程式的哪些部分應該對最終使用者可見,哪些部分不應該對最終使用者可見。當然,最終用戶最不關心演算法中涉及的常數和變數。他只關心需要呼叫什麼方法來獲取輸出。

C# 中的存取修飾符類型

C#為我們提供了四種類型的存取修飾符:

  • 私有(預設存取修飾符,枚舉和介面除外)
  • 受保護(略有限制)
  • 公(無限制,枚舉和介面的預設選擇)
  • 內部(同一程序集中公開)

除了這四種存取修飾符之外,還有兩種存取等級組合 -

  • 受保護的內部
  • 私人保護

讓我們透過一個例子來理解每一個。

1.私人

私人是最受限制的存取等級。它也是所有常數、變數、使用者定義物件等的預設存取修飾符。預設情況下,只有枚舉和介面是公共的。因此,如果您沒有指定任何存取修飾符,C# 會為其指派預設修飾符。

私有物件無法在類別或結構體或聲明它們的程式部分之外存取。任何嘗試存取聲明物件的主體範圍之外的物件都會導致編譯時錯誤。

範例#1

using System;
class Employee //private by default
{
string name; //private by default
public string GetName()
{
return name;
}
public void SetName(string name)
{
this.name = name;
}
}
public class Program
{
public static void Main()
{
Employee emp = new Employee();
emp.SetName("John");
Console.Write("Employee name is " + emp.GetName());
// compile time error - 'Employee.name' is inaccessible due to its protection level
// Console.Write("Employee name is " + emp.name);
}
}

輸出:

C# 中的存取修飾符

範例 #2

using System;
public class Program
{
public static void Main()
{
int x = 5; //private to the Main method, accessible inside nested code blocks in the Main method
if (true)
{
int y = 10; //private to the if block, not accessible outside if block
Console.WriteLine("x = " + x);
Console.WriteLine("y = " + y);
}
Console.WriteLine("x = " + x);
// compile-time error - The name 'y' does not exist in the current context.
// Console.WriteLine("y = " + y);
}
}

輸出:

C# 中的存取修飾符

2.受保護

受保護的存取說明符限制物件只能從類別的派生實例存取。因此,如果子類別物件嘗試存取父類別的受保護對象,這是允許的。非派生類別不能存取任何類別的受保護成員。當然,受保護的物件可以透過其自己類別的方法存取。

範例:

using System;
class Parent
{
protected string x;
public Parent()
{
x = "abc"; //accessible to own class methods
}
}
class Child : Parent // derived class
{
public static void Main()
{
var parentObj = new Parent();
var childObj = new Child();
Console.WriteLine(childObj.x); //accessible to derived class object instances
// compile-time error - Cannot access protected member 'Parent.x' via a qualifier of type 'Parent'; the qualifier must be of type 'Child' (or derived from it)
// Console.WriteLine(parentObj.x);
}
}

輸出:

C# 中的存取修飾符

3.公眾

這是受限制最少的存取修飾符。公共物件實際上可供整個外部世界訪問,從而使它們成為允許的最高訪問修飾符。當然,這需要付出沉重的代價──最少保護的代價。

程式碼的任何部分都可以存取公共成員。這使得它們最不安全。任何程式碼邏輯都可以修改它們的值,這可能會導致意外的行為。因此,在公開任何對象之前必須非常謹慎。

在我們在私人存取修飾符範例中建立的同一個 Employee 類別中,如果我們更改公共的存取級別,我們將不需要任何 Getter 和 Setter 方法。事實上,最佳實踐是將物件設為私有並使用 C# Getter 和 Setter 屬性。

範例:

using System;
class Employee
{
public string name;
}
public class Program
{
public static void Main()
{
Employee emp = new Employee();
emp.name = "John";
Console.Write("Employee name is " + emp.name);
}
}

輸出:

C# 中的存取修飾符

4.內部

內部物件和方法只能在同一程式集中存取。當您想要將任何物件公開,但又希望將其存取限制為僅對您正在編碼的框架進行存取時,這是一個非常有用的存取修飾符。

因此,本質上,同一組件的所有區域都可以存取所有內部物件。

讓我們建立兩個控制台應用程式來了解此工作原理。

範例:

第 1 步:建立一個 C# 控制台應用程式並將以下程式碼放入其中:

using System;
namespace ConsoleApp1
{
public class Parent
{
internal int x;
public Parent()
{
x = 10;
}
}
public class Program
{
public static void Main()
{
var parentObj = new Parent();
// accessible within the same assembly
Console.Write("The value of x = " + parentObj.x);
}
}
}

第 2 步:建置解決方案以從 bin 資料夾取得 .dll 檔案。

C# 中的存取修飾符

第 3 步:建立另一個控制台應用程式並引用 ConsoleApp1 中的組件檔案。按一下下圖中的“新增參考”,然後瀏覽到步驟 2 中的 .dll 檔案的位置。它必須類似於 ~/ConsoleApp1/bin/Debug/ConsoleApp1.dll。

C# 中的存取修飾符

新增 .dll 檔案後,您應該在組件下找到它。

C# 中的存取修飾符

Step4: Place the below code in ConsoleApp2.

using System;
using ConsoleApp1; //referencing the first assembly
namespace ConsoleApp2
{
class Program
{
static void Main(string[] args)
{
var parentObj = new Parent();
//not accessible outside the assembly
Console.Write(parentObj.x);
}
}
}

Step5: When you build ConsoleApp2, you will get a compile-time error indicating that ‘x’ from ConsoleApp1 cannot be accessed in other assemblies due to its protection level.

C# 中的存取修飾符

5. Protected Internal

This is a combination of both Protected and Internal access modifiers. An important concept to understand here is that Protected Internal means Protected OR Internal. It is a union of both access modifiers. It must never be thought to be an intersection.

So, Internal objects are not accessible outside the assembly, while Protected objects are accessible to any derived class in any assembly. What if I want to protect my object only in other assemblies and not in the same assembly? Simple solution – declare it as protected internal.

Example:

Step 1: Let us modify our ConsoleApp1 to reflect the code below. Notice we have changed the access level of our variable ‘x’ to protected internal.

using System;
namespace ConsoleApp1
{
public class Parent
{
protected internal int x;
public Parent()
{
x = 10;
}
}
public class Program
{
public static void Main()
{
var parentObj = new Parent();
// accessible within the same assembly
Console.Write("The value of x = " + parentObj.x);
}
}
}

Step 2: Build the solution again and replace the .dll in ConsoleApp2 with the updated one.

Step 3: Update the code in ConsoleApp2 as below:

using System;
using ConsoleApp1; //referencing the first assembly
namespace ConsoleApp2
{
class Program: Parent
{
static void Main(string[] args)
{
var progObj = new Program();
//accessible only via an object of the derived class.
Console.Write(progObj.x);
Console.Read();
}
}
}

Step 4: Run ConsoleApp2 to see the output.

C# 中的存取修飾符

6. Private Protected

This is a union combination of both Private and Protected access modifiers. Protected Internal means Protected OR Internal. So, Private objects are not accessible outside the code block in which it is declared, while Protected objects are accessible to any derived class in any assembly. What if I want to restrict my object’s access even in derived classes in other assemblies? Simple solution – declare it as protected internal.

Example:

Let us modify the access level of ‘x’ in ConsoleApp1 to Private Protected.

using System;
namespace ConsoleApp1
{
public class Parent
{
private protected int x;
public Parent()
{
x = 10;
}
}
public class Child: Parent {
public void DisplayX() {
// accessible only via derived class objects
Console.Write("Value of x = " + x);
}
}
public class Program
{
public static void Main()
{
var childObj = new Child();
childObj.DisplayX();
Console.Read();
}
}
}

Output:

C# 中的存取修飾符

Tabular Comparison

Following is a tabular comparison of Access Modifiers in C#:

Access Specifier Same Assembly Other Assembly
Same Class Derived Class Non-Derived Class Derived Class Non-Derived Class
Private Yes No No No No
Public Yes Yes Yes Yes Yes
Protected Yes Yes No Yes No
Internal Yes Yes Yes No No
Protected Internal Yes Yes Yes Yes No
Private Protected Yes Yes No No No

Conclusion

We have seen in the above article that access modifiers control the access of everything in the project. Various combinations of access levels cover the needs of various kinds of accessibility. The developers must choose wisely, keeping in mind the security and the absolute necessity of the object to be accessible in a certain block of code.

以上是C# 中的存取修飾符的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn