python入門python的基本語法
1115
2025-03-31
使用 static 修飾符聲明屬于類型本身而不是屬于特定對象的靜態成員。
static 修飾符可用于類、字段、方法、屬性、運算符、事件和構造函數,但不能用于索引器、析構函數或類以外的類型。如,
static class CompanyEmployee
{
public static void DoSomething() { /*...*/ }
public static void DoSomethingElse() { /*...*/? }
}
常數或者類型聲明隱式地是靜態成員。
不能通過實例引用靜態成員。 然而,可以通過類名稱引用它。 如:
public class MyBaseC
{
public struct MyStruct
{ public static int x = 100; }
}
Console.WriteLine(MyBaseC.MyStruct.x);
類實例包含該類所有實例字段的單獨副本,但不包含靜態成員,靜態成員只有一個副本,屬于類。
不可以使用 this 來引用靜態方法或屬性訪問器。
如果對類應用 static 關鍵字,則該類的所有成員都必須是靜態的。
類和靜態類可以有靜態構造函數。 靜態構造函數在程序開始和類實例化之間的某個時刻調用。
static 關鍵字在使用上比在 C++ 中有更多限制。
例:靜態成員。
public class Employee4
{
public string id;
public string name;
public Employee4()?? {? }
public Employee4(string name, string id)
{
this.name = name;
this.id = id;
}
public static int employeeCounter;
public static int AddEmployee()
{ return ++employeeCounter;? }
}
class MainClass : Employee4
{? static void Main()
{?? Console.Write("Enter the employee's name: ");
string name = Console.ReadLine();
Console.Write("Enter the employee's ID: ");
string id = Console.ReadLine();
Employee4 e = new Employee4(name, id);
Console.Write("Enter the current number of employees: ");
string n = Console.ReadLine();
Employee4.employeeCounter = Int32.Parse(n);
Employee4.AddEmployee();
Console.WriteLine("Name: {0}", e.name);
Console.WriteLine("ID:?? {0}", e.id);
Console.WriteLine("New Number of Employees: {0}",
Employee4.employeeCounter);
}
}
/*Input:
Matthias Berndt
AF643G
15
*
Sample Output:
Enter the employee's name: Matthias Berndt
Enter the employee's ID: AF643G
Enter the current number of employees: 15
Name: Matthias Berndt
ID:?? AF643G
New Number of Employees: 16
*/
例:用一尚未聲明的靜態字段實例化另一個靜態字段。但直到向后者顯式賦值后,才能確定結果。
class Test
{
static int x = y;
static int y = 5;
static void Main()
{
Console.WriteLine(Test.x);
Console.WriteLine(Test.y);
Test.x = 99;
Console.WriteLine(Test.x);
}
}
/*Output:
0
5
99
*/
靜態類與非靜態類基本相同,唯一的區別是靜態類不能實例化。
即不能使用 new 關鍵字創建靜態類類型的變量。
因為沒有實例變量,所以要使用類名本身訪問靜態類的成員。
例如,如果靜態類UtilityClass 有一個名為 MethodA 的公共方法,則該方法的調用為:
UtilityClass.MethodA();
對于只對輸入參數進行運算而不獲取或設置任何內部實例字段的方法集,靜態類可以方便地用作這些方法集的容器。
例如,在 .NET Framework 類庫中,靜態類 System.Math 包含的一些方法只執行數學運算,而無需存儲或檢索特定 Math 類實例特有的數據。
double dub = -3.14;
Console.WriteLine(Math.Abs(dub)); // 3.14
Console.WriteLine(Math.Floor(dub)); // 3.14
Console.WriteLine(Math.Round(Math.Abs(dub))); // 3
靜態類的主要特性:
1、僅包含靜態成員。
2、無法實例化。
3、是密封的。
4、不能包含實例構造函數。
因此,創建靜態類與創建僅包含靜態成員和私有構造函數的類基本相同。 私有構造函數阻止類被實例化。
使用靜態類的優點在于, 編譯器將保證不會創建此類的實例。
靜態類是密封的,因此不可被繼承。
它們不能從除 Object 外的任何類中繼承。
靜態類不能包含實例構造函數,但可以包含靜態構造函數。
如果非靜態類包含需要進行重要的初始化的靜態成員,也應定義靜態構造函數。
靜態成員:
非靜態類可以包含靜態的方法、字段、屬性或事件。
始終通過類名而不是實例名稱訪問靜態成員。
無論對一個類創建多少個實例,它的靜態成員都只有一個副本。
靜態方法和屬性不能訪問其包含類型中的非靜態字段和事件,并且不能訪問任何對象的實例變量(除非在方法參數中顯式傳遞)。
通常聲明具有一些靜態成員的非靜態類,而不是將整個類聲明為靜態類。
靜態字段有兩個常見的用法:
一是記錄已實例化對象的個數;
二是存儲必須在所有實例之間共享的值。
靜態方法可以被重載但不能被重寫,因為它們屬于類,不屬于類的任何實例。
雖然字段不能聲明為 static const,但 const 字段的行為在本質上是靜態的。因此,可以同對待靜態字段一樣使用 ClassName.MemberName 表示法來訪問 const 字段。 不需要對象實例。
C# 不支持靜態局部變量(在方法范圍內聲明的變量)。
在成員返回類型之前,使用 static 關鍵字可以聲明靜態類成員,如:
public class Automobile
{
public static int NumberOfWheels = 4;
public static int SizeOfGasTank
{ get{? return 15;}
public static void Drive() { }
public static event EventType RunOutOfGas;
// Other non-static fields and properties...
}
靜態成員在第一次被訪問之前調用靜態構造函數(如有存在)進行初始化。
訪問靜態類成員,應使用類名而不是變量名來指定該成員的位置,如:
Automobile.Drive();
int i = Automobile.NumberOfWheels;
如果類包含靜態字段,需提供在加載類時初始化這些字段的靜態構造函數。靜態構造函數用于初始化任何靜態數據,或用于執行僅需執行一次的特定操作。
在創建第一個實例或引用任何靜態成員之前,將自動調用靜態構造函數。
class SimpleClass? {
// Static variable that must be initialized at run time.
static readonly long baseline;
// Static constructor is called at most one time, before any
// instance constructor is invoked or member is accessed.
static SimpleClass()
{? baseline = DateTime.Now.Ticks; }
}
靜態構造函數具有以下特點:
靜態構造函數既沒有訪問修飾符,也沒有參數。
在創建第一個實例或引用任何靜態成員之前,將自動調用靜態構造函數來初始化類。
無法直接調用靜態構造函數。
程序中用戶無法控制何時執行靜態構造函數。
靜態構造函數的典型用途:當類使用日志文件時,使用靜態構造函數向日志文件中寫入項。
靜態構造函數在為非托管代碼創建包裝類時也很有用,此時該構造函數可以調用 LoadLibrary 方法。
如果靜態構造函數引發異常,運行時不會再次調用該構造函數;并且在程序運行所在的應用程序域的生存期內,類型將保持未初始化。
例:靜態構造函數。
創建 Bus 的第一個實例(bus1)時,將調用該靜態構造函數來初始化該類。 輸出示例驗證了即使創建 Bus 的兩個實例,該靜態構造函數也僅運行一次,并且在實例構造函數運行之前運行。
public class Bus
{?? protected static readonly DateTime globalStartTime;
protected int RouteNumber { get; set; }
static Bus()
{
globalStartTime = DateTime.Now;
Console.WriteLine("Static constructor sets global start time to {0}", globalStartTime.ToLongTimeString());
}
public Bus(int routeNum)
{
RouteNumber = routeNum;
Console.WriteLine("Bus #{0} is created.", RouteNumber);
}
public void Drive()
{
TimeSpan elapsedTime = DateTime.Now - globalStartTime;
Console.WriteLine("{0} is starting its route {1:N2} minutes after global start time {2}.", this.RouteNumber,
elapsedTime.TotalMilliseconds,
globalStartTime.ToShortTimeString());
}
}
class TestBus
{
static void Main()
{
Bus bus1 = new Bus(71);
Bus bus2 = new Bus(72);
bus1.Drive();
System.Threading.Thread.Sleep(25);
bus2.Drive();
System.Console.WriteLine("Press any key to exit.");
System.Console.ReadKey();
}
}
/* Sample output:
Static constructor sets global start time to 3:57:08 PM.
Bus #71 is created.
Bus #72 is created.
71 is starting its route 6.00 minutes after global start time 3:57 PM.
72 is starting its route 31.00 minutes after global start time 3:57 PM.
*/
靜態類只包含從 Object 繼承的實例成員,也沒有可調用的構造函數。正確設計靜態類的準則:
慎用靜態類,靜態類只應用作面向對象的框架核心的支持類。
不要認為靜態類可無所不包。
Environment 類使用靜態類的方式值得學習。 此類提供對當前用戶環境的信息的訪問。
不要聲明或重寫靜態類中的實例成員。
如果某個類設計了實例成員,則該類不應標記為靜態的。
關于靜態的兩道題:
等同于:
Public static int x;
Static A()
{
x=3;
x=B.Y+1;
}
namespace JieKou
{
class A
{
public static int x = 3;
static A()
{
x = B.Y + 1;
}
}
class B
{
等同于:
public Static int Y;
static B()
{
Y=A.x+1;
Y=1;
}
public static int Y = A.x + 1;
static B()
{
Y = 1;
}
static void Main(string[] args)
{
Console.WriteLine("{0}.{1}",A.x,B.Y);
}
}
}
輸出結果: 1.1 ??解釋:執行時先執行Main主函數,先執行Y=0(系統默認Y=0;)Y=A.x+1;遇到A的時候轉到class A ?X=3; 然后執行x=B.Y+1(Y=0;x=1;所以A.x=1;);遇到B則執行class B。 StaticB()Y=1;將B賦值1,Y=1所以B.Y=1;
例2:
namespace JieKou
{
class A
{
public static int x;
static A()
{
x = 1;
}
public A()
{
x++;
}
}
class B
{
static void Main(string[] args)
{
A a = new A();
A c = new A();
Console.WriteLine(A.x);
}
}
}
輸出結果: A.x=3;
注意:static A()靜態函數執行一次
先執行 A a=new A();
↓
Static A(); x=1;
↓
Public A()
X++
↓
X=2
↓
A a=new A();
↓
Public A()
X++;
A.x=3;
一、靜態字段
與實例字段一樣,可以在聲明的同時進行初始化。
與實例字段不同,如果沒有對靜態字段進行初始化,靜態字段將自動獲取默認值(0,null,false等)。所以,一個靜態字段即使沒有被顯示地賦值,也可以被訪問。
二、靜態屬性
三、靜態方法
this關鍵字在靜態方法中是無效的。因為靜態方法不是通過一個特定的實例來引用的。
一般靜態方法不能訪問類中的實例字段和實例方法,除非事先獲得對字段和方法所從屬于的那個特定的實例的引用(通過傳遞參數)。
四、靜態構造器
靜態構造器用來對類而不是類實例進行初始化。靜態構造器并不是顯示調用的。”運行時“會在首次訪問類(可能是調用一個普通構造器,可能是訪問類的一個靜態方法或靜態字段)時自動調用靜態構造器。
我們使用靜態構造器將類中的靜態數據初始化成一個特定的值,尤其是在無法通過在聲明時的一次簡單地賦值來獲得初始值的時候。
例如:
class Employee
{
static Employee()
{??? Random randomGenerator=new Randow();
NextId=randomGenerator.Next(101,999);//生成一個100到1000的一個隨機整數
}
public static int NextId=42;
}
說明:由于初始值涉及一個方法調用,無法通過在聲明時的一次簡單地賦值來完成。所以NextId的初始化代碼被放到一個靜態構造器中,而沒有作為聲明的一部分。
注意:1、假如對NextId的賦值既在靜態構造器中進行,又在聲明時進行,那么當初始化結束的時候,最終獲得的是什么值?觀察C#編譯器生成的CIL代碼,發現聲明時的賦值被移動了位置,成為靜態構造器中的一個語句。因此,在靜態構造器中進行的賦值將優先于聲明字段時進行的賦值,這會實例字段的情況是一樣的。
2、沒有靜態終結器的說法。
3、最好是在聲明的同時完成靜態初始化,而不要使用靜態構造器。
五、靜態類
靜態類不包含任何實例字段 ,實例方法。當創建一個能實例化的類沒有意義是,就可以聲明為靜態類。
c#編譯器會自動在CIL代碼中把靜態類標記為abstract和sealed。這會將類指定為不可擴展即不能從他派生出其他類。
靜態變量使用 static 修飾符進行聲明,在類被實例化時創建,通過類進行訪問不帶有 static 修飾符聲明的變量稱做非靜態變量。
static變量在對象被實例化時創建,通過對象進行訪問一個類的所有實例的同一C#靜態變量都是同一個值,同一個類的不同實例的同一非靜態變量可以是不同的值。
靜態函數的實現里不能使用非靜態成員,如非靜態變量、非靜態函數等。
class StaticTest
{
static int x = 0;
int y = 0;
public void SetX(int a)
{ x = a; }
public void SetY(int a)
{
y = a;
}
public void Print()
{
Console.WriteLine("x = {0}? y = {1}", x, y);
}
static void Main(string[] args)
{
StaticTest st = new StaticTest();
StaticTest st1 = new StaticTest();
st.SetX(10); //將10賦給x;
st.SetY(10); //將10賦給y;
st.Print();????????????????? //顯示:x=10 y=10
st1.SetX(20); //將20賦給x
st1.SetY(20); //將20賦給x
st1.Print();????????????? //顯示:x=20 y=20
st.Print();???????????? ?????//由于x是靜態變量,所以在此調用第一次初始化實例st時,靜態變量已經變為20, 輸出:x=20 y=10
st.SetX(30);
st.SetY(30);
st.Print(); //由于x是靜態變量,所以在此調用初始化實例st時,靜態變量已經變為30, 輸出:x=30 y=30
st1.Print();?????????????? ?//由于x是靜態變量,所以在此調用st1實例時,靜態變量已經變為30, 輸出:x=30 y=20
}
}
靜態類:
聲明為static,它僅包含靜態成員,不能用new靜態類的實例。使用靜態類來包含不與特定對象關聯的方法。
功能:僅包含靜態成員,不能被實例化,是密封的,不能包含實例構造函數,可包含靜態構造函數以分配初始值或設置某個靜態變量。
優點:編譯器能夠執行檢查以確保不致偶然地添加勢力成員。編譯器將保證不會創建此類的實例。
靜態方法:
是一種特殊的成員方法,不屬于類的某一個具體的實例。非靜態方法可以訪問類中的任何成員,而靜態只能訪問類中的靜態成員。
靜態構造函數:
用于對靜態字段、只讀字段等的初始化。
添加static關鍵字,不能添加訪問修飾符,因為靜態構造函數都是私有的。
類的靜態構造函數在給定應用程序域中至多執行一次:只有創建類的實例或者引用類的任何靜態成員才激發靜態構造函數
靜態構造函數是不可繼承的,而且不能被直接調用。
如果類中包含用來開始執行的 Main 方法,則該類的靜態構造函數將在調用 Main 方法之前執行。任何帶有初始值設定項的靜態字段,則在執行該類的靜態構造函數時,先要按照文本順序執行那些初始值設定項。
如果沒有編寫靜態構造函數,而這時類中包含帶有初始值設定的靜態字段,那么編譯器會自動生成默認的靜態構造函數。
C#靜態方法及屬性在程序啟動的時候,就全部裝入內存的,而不管這些方法、屬性以后有沒有用到。即使是沒有人再訪問程序,這部分內存仍然不會釋放還有就是,所有訪問者看到的靜態屬性的數據幾乎都是一樣的,比如A用戶設置了UserName這個屬性,B用戶訪問的時候,得到的UserName仍然是A用戶設置的那個。這種特性,如果用在固定數據中,那不會有太大問題,比如連接字符串之類的
C#靜態方法/數據成員是屬于類的,不是屬于某一個對象的,因而調用它不需要實例化;靜態方法和靜態數據成員相當于共享變量。為該類的所有對象所共有,因而在需要共享數據時,定義這種類型時很好的選擇。 一但定義一個類后(不一定要實例化對象)該類的所有靜態成員就載入內存(并不是程序啟動,就裝入內存,沒有定義該類時它不會載入內存) 靜態成員的作用域與它所屬的類的作用域相同
C# 面向對象編程
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。