C# 修饰符 async、const、readonly、extern、in、out、new、override

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();
}

C# - 协变、逆变 看完这篇就懂了

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。
  • 23
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值