async
使用 async 修饰符可将方法、lambda 表达式或匿名方法指定为异步。 如果对方法或表达式使用此修饰符,则其称为异步方法 。 如下示例定义了一个名为 ExampleMethodAsync 的异步方法:
public async Task<int> ExampleMethodAsync()
{
//...
}
const
使用 const 关键字来声明某个常量字段或局部变量。 常量字段和常量局部变量不是变量并且不能修改。 常量可以为数字、布尔值、字符串或 null 引用。
const int X = 0;
public const double GravitationalConstant = 6.673e-11;
private const string ProductName = "Visual C#";
readonly
在字段声明中,readonly 指示只能在声明期间或在同一个类的构造函数中向字段赋值。 可以在字段声明和构造函数中多次分配和重新分配只读字段。
在此示例中,即使在类构造函数中给字段 year 赋了值,也无法在方法 ChangeYear 中更改其值:
class Age
{
private readonly int _year; //可在初始化时赋值
//可同个类在构造函数中赋值
Age(int year)
{
_year = year;
}
void ChangeYear()
{
//_year = 1967; // Compile error if uncommented.
}
}
只能在下列上下文中对 readonly 字段进行赋值:
- 在声明中初始化变量时,例如:public readonly int y = 5;
- 在包含实例字段声明的类的实例构造函数中。
- 在包含静态字段声明的类的静态构造函数中。
readonly 关键字不同于 const 关键字。 const 字段只能在该字段的声明中初始化。 可以在字段声明和任何构造函数中多次分配 readonly 字段。 因此,根据所使用的构造函数,readonly 字段可能具有不同的值。 另外,虽然 const 字段是编译时常量,但 readonly 字段可用于运行时常量,如下面的示例所示:
public static readonly uint timeStamp = (uint)DateTime.Now.Ticks;
extern
extern 外部修饰符,常与DllImport属性一起使用,用于支持在外部实现方法。 在这种情况下,还必须将方法声明为 static,如下面的示例所示:
[DllImport("avifil32.dll")]
private static extern void AVIFileInit();
in(泛型修饰符)
对于泛型类型参数,in 关键字可指定类型参数是逆变的。 可以在泛型 接口 和 委托 中使用 in 关键字。
逆变泛型接口
下面的示例演示如何声明、扩展和实现逆变泛型接口。 它还演示如何对实现此接口的类使用隐式转换。
// Contravariant interface.
interface IContravariant<in A> { }
// Extending contravariant interface.
interface IExtContravariant<in A> : IContravariant<A> { }
// Implementing contravariant interface.
class Sample<A> : IContravariant<A> { }
class Program
{
static void Test()
{
IContravariant<Object> iobj = new Sample<Object>();
IContravariant<String> istr = new Sample<String>();
// You can assign iobj to istr because
// the IContravariant interface is contravariant.
istr = iobj;
}
}
逆变泛型委托
以下示例演示如何声明、实例化和调用逆变泛型委托。 它还演示如何隐式转换委托类型。
// Contravariant delegate.
public delegate void DContravariant<in A>(A argument);
// Methods that match the delegate signature.
public static void SampleControl(Control control)
{ }
public static void SampleButton(Button button)
{ }
public void Test()
{
// Instantiating the delegates with the methods.
DContravariant<Control> dControl = SampleControl;
DContravariant<Button> dButton = SampleButton;
// You can assign dControl to dButton
// because the DContravariant delegate is contravariant.
dButton = dControl;
// Invoke the delegate.
dButton(new Button());
}
out(泛型修饰符)
对于泛型类型参数,out 关键字可指定类型参数是协变的。 可以在泛型接口和委托中使用 out 关键字。
协变泛型接口
// Covariant interface.
interface ICovariant<out R> { }
// Extending covariant interface.
interface IExtCovariant<out R> : ICovariant<R> { }
// Implementing covariant interface.
class Sample<R> : ICovariant<R> { }
class Program
{
static void Test()
{
ICovariant<Object> iobj = new Sample<Object>();
ICovariant<String> istr = new Sample<String>();
// You can assign istr to iobj because
// the ICovariant interface is covariant.
iobj = istr;
}
}
协变泛型委托
// Covariant delegate.
public delegate R DCovariant<out R>();
// Methods that match the delegate signature.
public static Control SampleControl()
{ return new Control(); }
public static Button SampleButton()
{ return new Button(); }
public void Test()
{
// Instantiate the delegates with the methods.
DCovariant<Control> dControl = SampleControl;
DCovariant<Button> dButton = SampleButton;
// You can assign dButton to dControl
// because the DCovariant delegate is covariant.
dControl = dButton;
// Invoke the delegate.
dControl();
}
new (成员修饰符)
在用作声明修饰符时,new 关键字可以显式隐藏从基类继承的成员。 隐藏继承的成员时,该成员的派生版本将替换基类版本。
new 关键字还可用于创建类型的实例或用作泛型类型约束。
若要隐藏继承的成员,请使用相同名称在派生类中声明该成员,并使用 new 修饰符对其进行修饰。 例如:
public class BaseC
{
public int x;
public void Invoke() { }
}
public class DerivedC : BaseC
{
new public void Invoke() { }
}
在此示例中,使用 DerivedC.Invoke 隐藏了 BaseC.Invoke。 字段 x 不受影响,因为未使用类似名称将其隐藏。
对同一成员同时使用 new 和 override 是错误的做法,因为这两个修饰符的含义互斥。 new 修饰符会用同样的名称创建一个新成员并使原始成员变为隐藏。 override 修饰符会扩展继承成员的实现。
在不隐藏继承成员的声明中使用 new 修饰符将会生成警告。
override
扩展或修改继承的方法、属性、索引器或事件的抽象或虚拟实现需要 override 修饰符。
- override 方法提供从基类继承的方法的新实现。 通过 override 声明重写的方法称为重写基方法。 override
方法必须具有与重写基方法相同的签名。 override 方法支持协变返回类型。 具体而言,override
方法的返回类型可从相应基方法的返回类型派生。 - 不能重写非虚方法或静态方法。 重写基方法必须是 virtual、abstract 或 override。
- override 声明不能更改 virtual 方法的可访问性。 override 方法和 virtual
方法必须具有相同级别访问修饰符。 - 不能使用 new、static 或 virtual 修饰符修改 override 方法。
- 重写属性声明必须指定与继承的属性完全相同的访问修饰符、类型和名称。 只读重写属性支持协变返回类型。 重写属性必须为
virtual、abstract 或 override。