📄 修饰符.txt
字号:
重写声明不能更改虚方法的可访问性。重写方法和虚方法必须具有相同的访问级修饰符。
不能使用下列修饰符修改重写方法:
new static virtual abstract
重写属性声明必须指定与继承属性完全相同的访问修饰符、类型和名称,并且重写属性必须是虚拟的、抽象的或重写的。
有关访问基类成员的更多信息,请参见 7.5.8 基访问。
有关重写方法的更多信息,请参见 10.5.4 重写方法。
示例
请参见 virtual 关键字的示例。
从具有重写方法的派生类中,仍然可以通过使用 base 关键字来访问同名的重写基方法。例如,如果有虚方法 MyMethod() 和派生类上的重写方法,就可以通过下列调用从派生类访问此虚方法:
base.MyMethod()
将此方法与使用范围解析运算符 (::) 和基类名的 C++ 方法进行比较,例如:
My_Base_Class_Name::MyMethod()
示例
在该示例中,有一个基类 Square 和一个派生类 Cube。因为立方体的面积是六个正方形的面积之和,因此可以通过调用基类上的 Area() 方法来计算。
// cs_override_keyword.cs
// Calling overriden methods from the base class
using System;
class TestClass
{
public class Square
{
public double x;
// Constructor:
public Square(double x)
{
this.x = x;
}
public virtual double Area()
{
return x*x;
}
}
class Cube: Square
{
// Constructor:
public Cube(double x): base(x)
{
}
// Calling the Area base method:
public override double Area()
{
return (6*(base.Area()));
}
}
public static void Main()
{
double x = 5.2;
Square s = new Square(x);
Square c = new Cube(x);
Console.WriteLine("Area of Square = {0:F2}", s.Area());
Console.WriteLine("Area of Cube = {0:F2}", c.Area());
}
}
输出
Area of Square = 27.04
Area of Cube = 162.24
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
extern 修饰符
在方法声明中使用 extern 修饰符指示在外部实现方法。外部修饰符的常见用法是与 DllImport 属性一起使用。(有关更多信息,请参见 DllImportAttribute 类。)
将 abstract 和 extern 修饰符一起使用来修改同一成员是错误的。使用 extern 修饰符意味着方法在 C# 代码的外部实现,而使用 abstract 修饰符意味着在此类中未提供此方法的实现。
因为外部方法声明不提供实实现,所以没有方法体;此方法声明只是以一个分号结束,并且在签名后没有大括号 ({ })。例如:
public static extern int MyMethod(int x);
注意 extern 关键字在使用上比在 C++ 中有更多的限制。若要与 C++ 关键字比较,请参见 C++ Language Reference 中的使用 extern 指定链接。
有关外部方法的更多信息,请参见 10.5.7 外部方法。
有关属性的更多信息,请参见 17. 属性。
示例
在该示例中,程序接收来自用户的字符串并将该字符串显示在消息框中。程序使用从 User32.dll 库导入的 MessageBox 方法。
using System;
using System.Runtime.InteropServices;
class MyClass
{
[DllImport("User32.dll")]
public static extern int MessageBox(int h, string m, string c, int type);
public static int Main()
{
string myString;
Console.Write("Enter your message: ");
myString = Console.ReadLine();
return MessageBox(0, myString, "My Message Box", 0);
}
}
运行示例
Enter your message: Where do you want to go today?
输入以上文本后,屏幕上将弹出一个包含该文本的消息框。
示例
该示例使用两个文件 CM.cs 和 Cmdll.c 来说明 extern。C 文件是从 C# 程序中调用的外部 DLL。
文件:Cmdll.c
// cmdll.c
// compile with: /LD /MD
int __declspec(dllexport) MyMethod(int i)
{
return i*10;
}
文件:CM.cs
// cm.cs
using System;
using System.Runtime.InteropServices;
public class MyClass
{
[DllImport("Cmdll.dll")]
public static extern int MyMethod(int x);
public static void Main()
{
Console.WriteLine("MyMethod() returns {0}.", MyMethod(5));
}
}
输出
MyMethod() returns 50.
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
static 修饰符
使用 static 修饰符声明属于类型本身而不是属于特定对象的静态成员。static 修饰符可用于字段、方法、属性、运算符、事件和构造函数,但不能用于索引器、析构函数或类型。
备注
常数或者类型声明隐式地是静态成员。
不能通过实例引用静态成员。然而,可以通过类型名称引用它。例如,请考虑以下类:
public class MyBaseC
{
public struct MyStruct {
public static int x = 100;
}
}
若要引用静态成员 x,请使用完全限定名(除非可从相同范围访问):
MyBaseC.MyStruct.x
尽管类的实例包含该类所有实例字段的单独副本,但每个静态字段只有一个副本。
不可以使用 this 引用静态方法或属性访问器。
注意 static 关键字在使用上比在 C++ 中有更多限制。若要与 C++ 关键字进行比较,请参见 C++ Language Reference 中的 static。
为了说明实例成员,请看一个表示公司雇员的类。假设该类包含一种对雇员计数的方法和一个存储雇员数的字段。该方法和字段都不属于任何实例雇员,而是属于公司类。因此,应该将它们声明为此类的静态成员。
有关构造函数的更多信息,请参见 10.10 实例构造函数。
示例
该示例读取新雇员的名称和 ID,逐个增加雇员计数器并显示新雇员的有关信息以及新的雇员数。为简单起见,该程序从键盘读取当前的雇员数。在实际的应用中,应从文件读取此信息。
// cs_static_keyword.cs
// Static members
using System;
public class Employee
{
public string id;
public string name;
public Employee ()
{
}
public Employee (string name, string id)
{
this.name = name;
this.id = id;
}
public static int employeeCounter;
public static int AddEmployee()
{
return ++employeeCounter;
}
}
class MainClass: Employee
{
public 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();
// Create the employee object:
Employee e = new Employee (name, id);
Console.Write("Enter the current number of employees: ");
string n = Console.ReadLine();
Employee.employeeCounter = Int32.Parse(n);
Employee.AddEmployee();
// Display the new information:
Console.WriteLine("Name: {0}", e.name);
Console.WriteLine("ID: {0}", e.id);
Console.WriteLine("New Number of Employees: {0}",
Employee.employeeCounter);
}
}
输入
Tara Strahan
AF643G
15
示例输出
Enter the employee's name: Tara Strahan
Enter the employee's ID: AF643G
Enter the current number of employees: 15
Name: Tara Strahan
ID: AF643G
New Number of Employees: 16
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
virtual 修饰符
virtual 关键字用于修改方法或属性的声明,在这种情况下,方法或属性被称作虚拟成员。虚拟成员的实现可由派生类中的重写成员更改。
调用虚方法时,将为重写成员检查该对象的运行时类型。将调用大部分派生类中的该重写成员,如果没有派生类重写该成员,则它可能是原始成员。(有关运行时类型和大部分派生实现的更多信息,请参见 10.5.3 虚拟方法。)
默认情况下,方法是非虚拟的。不能重写非虚方法。
不能将 virtual 修饰符与以下修饰符一起使用:
static abstract override
除了声明和调用语法不同外,虚拟属性的行为与抽象方法一样。
在静态属性上使用 virtual 修饰符是错误的。
通过包括使用 override 修饰符的属性声明,可在派生类中重写虚拟继承属性。
有关虚方法的更多信息,请参见 10.5.3 虚拟方法。
示例
在该示例中,Dimensions 类包含 x 和 y 两个坐标和 Area() 虚方法。不同的形状类,如 Circle、Cylinder 和 Sphere 继承 Dimensions 类,并为每个图形计算表面积。每个派生类都有各自的 Area() 重写实现。根据与此方法关联的对象,通过调用正确的 Area() 实现,该程序为每个图形计算并显示正确的面积。
// cs_virtual_keyword.cs
// Virtual and override
using System;
class TestClass
{
public class Dimensions
{
public const double pi = Math.PI;
protected double x, y;
public Dimensions()
{
}
public Dimensions (double x, double y)
{
this.x = x;
this.y = y;
}
public virtual double Area()
{
return x*y;
}
}
public class Circle: Dimensions
{
public Circle(double r): base(r, 0)
{
}
public override double Area()
{
return pi * x * x;
}
}
class Sphere: Dimensions
{
public Sphere(double r): base(r, 0)
{
}
public override double Area()
{
return 4 * pi * x * x;
}
}
class Cylinder: Dimensions
{
public Cylinder(double r, double h): base(r, h)
{
}
public override double Area()
{
return 2*pi*x*x + 2*pi*x*y;
}
}
public static void Main()
{
double r = 3.0, h = 5.0;
Dimensions c = new Circle(r);
Dimensions s = new Sphere(r);
Dimensions l = new Cylinder(r, h);
// Display results:
Console.WriteLine("Area of Circle = {0:F2}", c.Area());
Console.WriteLine("Area of Sphere = {0:F2}", s.Area());
Console.WriteLine("Area of Cylinder = {0:F2}", l.Area());
}
}
输出
Area of Circle = 28.27
Area of Sphere = 113.10
Area of Cylinder = 150.80
在前面的示例中,注意继承的类 Circle、Sphere 和 Cylinder 都使用了初始化基类的构造函数,例如:
public Cylinder(double r, double h): base(r, h) {}
这类似于 C++ 的初始化列表。
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -