一、base关键字

可以通过base关键字访问上一级父类方法的访问。静态static函数无法调用base

二、new 关键字new

new有2个作用。

new运算符   用来分配内存空间和初始化对象。

new修饰符   微软官方说明:可以显式隐藏从基类继承的成员,该成员的派生版本将替换基类版本。(以前一直不在乎这种场合,因为编译器就提示警告)他和overrider有什么区别呢?

   /// <summary>
/// 关键字
/// </summary>
public class KeywordA
{ public KeywordA()
{
Name = "apple";
}
public string Name { get; set; } public virtual void Test()
{
Console.WriteLine("KeywordA.Test()" + Name);
} public void Test1()
{
Console.WriteLine("KeywordA.Test1()" + Name);
}
} public class KeywordB : KeywordA
{
public KeywordB()
{
Name = "button";
}
public new string Name { get; set; }
public new void Test()
{
Console.WriteLine("KeywordB.Test()" + Name);
base.Test();
} public new void Test1()
{
Console.WriteLine("KeywordB.Test1()" + Name);
base.Test1();
}
} public class KeywordC : KeywordA
{
public KeywordC()
{
Name = "city";
} public override void Test()
{
Console.WriteLine("KeywordC.Test()"+Name);
base.Test();
}
}
        static void Main(string[] args)
{
KeywordA a = new KeywordA();
a.Test();
a.Test1();
Console.WriteLine("=========================");
KeywordB b = new KeywordB();
b.Test();
b.Test1();
a = new KeywordB();
a.Test();
a.Test1();
Console.WriteLine("=========================");
KeywordC c = new KeywordC();
c.Test(); a = new KeywordC();
a.Test();
a.Test1();
Console.WriteLine("=========================");
Console.ReadKey();
}

通过以上代码执行得出以下结果:

KeywordA.Test()apple
KeywordA.Test1()apple
=========================
KeywordB.Test()button
KeywordA.Test()apple
KeywordB.Test1()button
KeywordA.Test1()apple
KeywordA.Test()apple
KeywordA.Test1()apple
=========================
KeywordC.Test()city
KeywordA.Test()city
KeywordC.Test()city
KeywordA.Test()city
KeywordA.Test1()city
=========================

1.new 只是个修饰符,看IL代码和不加NEW的方法一样。都叫覆盖。为了减少warn,建议加把。

2.虚方法、实方法都可以被覆盖(new),抽象方法,接口 不可以。

3.不管是重写还是覆盖都不会影响父类自身的功能。

4.当用子类创建父类的时候,如 A c = new B(),重写会调用子类的功能;而覆盖不会,仍然调用父类功能。

三、abstract 修饰符 abstract关键字

关于virtual 虚方法和抽象方法 、抽象类网上资料太多了。也非常好区分。abstract继承类必须实现抽象定义。而virtual 可以选择是否重写基类虚方法。 这里就摘录微软的定义了:

  • abstract 修饰符指示所修饰的内容缺少实现或未完全实现。

  • abstract 修饰符可用于类、方法、属性、索引器和事件。

  • 标记为抽象或包含在抽象类中的成员必须通过从抽象类派生的类来实现。

抽象类具有以下特性:

  • 抽象类不能实例化。

  • 抽象类可以包含抽象方法和抽象访问器。

  • 不能用 sealed(C# 参考) 修饰符修饰抽象类,因为这两个修饰符的含义是相反的。 采用 sealed 修饰符的类无法继承,而 abstract 修饰符要求对类进行继承。

  • 从抽象类派生的非抽象类必须包括继承的所有抽象方法和抽象访问器的实际实现。

四、virtual 修饰符

virtual 关键字用于修饰方法、属性、索引器或事件声明,并使它们可以在派生类中被重写。

除了声明和调用语法不同外,虚拟属性的行为与抽象方法一样。

  • 在静态属性上使用 virtual 修饰符是错误的。

  • 通过包括使用 override 修饰符的属性声明,可在派生类中重写虚拟继承属性。

五、const / readonly

都是只读的意思。表面上看区别在于const首次赋值后就不可以改了,而readonly在初始化类后就不能修改了。

    public class Keyword2
{ public static string Name_static = "Name_static"; public readonly string Name_readonly = "Name_readonly"; public const string Name_const = "Name_const"; public static readonly string Name_static_readonly = "Name_static_readonly"; public Keyword2(string text="Init")
{
Name_static = "Name_static_" + text;
Name_readonly = "Name_readonly_" + text;
//Name_const = "Name_const" + text;
//Name_static_readonly = "Name_static_readonly" + text; } }
        static void Main(string[] args)
{
//DoKeyword1();
DoKeyword2(); Console.ReadKey();
} /// <summary>
/// const readonly
/// </summary>
private static void DoKeyword2()
{
Console.WriteLine("========初始化字段=================");
Console.WriteLine(Keyword2.Name_const);
Console.WriteLine(Keyword2.Name_static);
Console.WriteLine(Keyword2.Name_static_readonly); Console.WriteLine("========初始化构造函数=================");
Keyword2 kw = new Keyword2();
Console.WriteLine(kw.Name_readonly);
Console.WriteLine(Keyword2.Name_const);
Console.WriteLine(Keyword2.Name_static);
Console.WriteLine(Keyword2.Name_static_readonly); Console.WriteLine("========修改内容=================");
//Keyword2.Name_const = Keyword2.Name_const+"_Edit";
//Keyword2.Name_static_readonly = Keyword2.Name_static_readonly + "_Edit";
//kw.Name_readonly = Keyword2.Name_readonly + "_Edit";
Keyword2.Name_static = Keyword2.Name_static + "_Edit";
Console.WriteLine(Keyword2.Name_static);
}

IL代码:

.class public auto ansi beforefieldinit 关键字使用和执行顺序.Keyword2
extends [mscorlib]System.Object
{
// Fields
.field public static literal string Name_const = "Name_const"
.field public static string Name_static
.field public initonly string Name_readonly
.field public static initonly string Name_static_readonly // Methods
.method public hidebysig specialname rtspecialname
instance void .ctor (
[opt] string text
) cil managed
{
.param [] = "Init"
// Method begins at RVA 0x2156
// Code size 54 (0x36)
.maxstack IL_0000: ldarg.
IL_0001: ldstr "Name_readonly"
IL_0006: stfld string 关键字使用和执行顺序.Keyword2::Name_readonly
IL_000b: ldarg.
IL_000c: call instance void [mscorlib]System.Object::.ctor()
IL_0011: nop
IL_0012: nop
IL_0013: ldstr "Name_static_"
IL_0018: ldarg.
IL_0019: call string [mscorlib]System.String::Concat(string, string)
IL_001e: stsfld string 关键字使用和执行顺序.Keyword2::Name_static
IL_0023: ldarg.
IL_0024: ldstr "Name_readonly_"
IL_0029: ldarg.
IL_002a: call string [mscorlib]System.String::Concat(string, string)
IL_002f: stfld string 关键字使用和执行顺序.Keyword2::Name_readonly
IL_0034: nop
IL_0035: ret
} // end of method Keyword2::.ctor .method private hidebysig specialname rtspecialname static
void .cctor () cil managed
{
// Method begins at RVA 0x218d
// Code size 21 (0x15)
.maxstack IL_0000: ldstr "Name_static"
IL_0005: stsfld string 关键字使用和执行顺序.Keyword2::Name_static
IL_000a: ldstr "Name_static_readonly"
IL_000f: stsfld string 关键字使用和执行顺序.Keyword2::Name_static_readonly
IL_0014: ret
} // end of method Keyword2::.cctor } // end of class 关键字使用和执行顺序.Keyword2

总结:

1.const  它也是静态的。

2.Name_readonly  在编译时自动将赋值写入构造函数,完成初始化值。

3.初始化顺序是 先 const-> static ->构造函数。

六、volatile 修饰符

七、in/out 泛型修饰符

说得直白点就是泛型类型的类型转换。

out “子类”向“父类”转换,即泛型接口的协变

in “父类”向“子类”转换,即泛型接口的逆变

目前我已知的类库中 泛型枚举接口 ,还有泛型委托都已经改成协变逆变了。

public interface IEnumerable<out T> : IEnumerable

public delegate TResult Func<in T1, in T2, out TResult>(T1 arg1, T2 arg2);

public delegate void Action<in T>(T obj);

案例1 IEnumerable<out T>使用

        public static void 泛型类型转换()
{ // 普通的类型转换
Animal animal = new Dog(); //类型的隐式转换
Dog dog = (Dog)animal; //类型的强制转换 // 泛型的类型转换
IEnumerable<Animal> iAnimal = null;
IEnumerable<Dog> iDog = null;
//// “子类”向“父类”转换,即泛型接口的协变 out
iAnimal = iDog;
// “父类”向“子类”转换,即泛型接口的逆变 in ,
//由于IEnumerable没有提供IEnumerable<in T>,所以编译时出错
iDog = iAnimal;
} public class Animal
{
}
public class Dog : Animal
{
}

案例2  实际场景中遇到的协变

一般场景,用协变的机会会多点。

有2个继承关系的类。

基类是 RoomInfoVModel房间信息相关的VO1.

它的子类RoomInfoPriceConvertVModel用来计算价格的VO2.

因为VO2主要是参与价格计算最终生成实际价格会放入到VO1,我不想让VO1太过臃肿。

那么在以下方法中,我从DB中获取到VO2List如何返回VO1List

我原先用了方法2:遍历集合吧对象逐个进行类型转换。

现在换成方法1了。IList<> 没有提供in out 功能,又懒得去扩展ILIST。

所以就使用 public delegate TOutput Converter<in TInput, out TOutput>(TInput input);转换了。

        /// <summary>
/// 根据入住日期获取房型价格列表
/// </summary>
/// <param name="req"></param>
/// <returns></returns>
public IList<RoomInfoVModel> GetCustomerRoomPrices(HashRequest req)
{
var discountName = req.GetString("discoutname");
var bIsMustExistsRoom = req.GetBoolean("IsMustExistsRoom");
var inDate = req.GetString("inDate");
var exitDate = req.GetString("ExitDate");
Sql sql = new Sql();
sql.Append(""); var models = Repo.Fetch<RoomInfoPriceConvertVModel>(sql.SQL, sql.Arguments); ConvertPrices(discountName, inDate, models); // 1、通过逆变
return models.ConvertAll<RoomInfoVModel>((input) => input);
// 2.遍历集合吧对象逐个进行类型转换
//return models.Select(a => a as CustomerHotelInfoVModel).ToList();
// 3.对象属性自动映射
//return AutoMapper.Mapper.Map<List<CustomerHotelInfoVModel>>(models); }

最后,其他修饰符会在后期文章中结合具体内容出现,比如async , params。

.NET 关键字的更多相关文章

  1. 作为一个新手的Oracle(DBA)学习笔记【转】

    一.Oracle的使用 1).启动 *DQL:数据查询语言 *DML:数据操作语言 *DDL:数据定义语言 DCL:数据控制语言 TPL:事务处理语言 CCL:指针控制语言 1.登录 Win+R—cm ...

  2. JavaScript var关键字、变量的状态、异常处理、命名规范等介绍

    本篇主要介绍var关键字.变量的undefined和null状态.异常处理.命名规范. 目录 1. var 关键字:介绍var关键字的使用. 2. 变量的状态:介绍变量的未定义.已定义未赋值.已定义已 ...

  3. java面向对象中的关键字

    1,super关键字 super:父类的意思 1. super.属性名 (调用父类的属性) 2. super.方法名 (调用父类的方法) 3. super([参数列表])(调用父类的构造方法) 注意: ...

  4. 关于javascript中的this关键字

    this是非常强大的一个关键字,但是如果你不了解它,可能很难正确的使用它. 下面我解释一下如果在事件处理中使用this. 首先我们讨论一下下面这个函数中的this关联到什么. function doS ...

  5. transient关键字的用法

    本篇博客转自 一直在路上 Java transient关键字使用小记 1. transient的作用及使用方法 我们都知道一个对象只要实现了Serilizable接口,这个对象就可以被序列化,Java ...

  6. Java关键字:static

    通常,当创建类时,就是在描述那个类的外观和行为.只有用new创建类的对象时,才分配数据存储空间,方法才能被调用.但往往我们会有下面两种需求: 1.我想要这样一个存储空间:不管创建多少对象,无论是不创建 ...

  7. Core Java 总结(关键字,特性问题)

    2016-10-19 说说&和&&的区别 初级问题,但是还是加入了笔记,因为得满分不容易. &和&&都可以用作逻辑与的运算(两边是boolean类型), ...

  8. Net中的常见的关键字

    Net中的关键字有很多,我们最常见的就有new.base.this.using.class.struct.abstract.interface.is.as等等.有很多的,在这里就介绍大家常见的,并且有 ...

  9. php多关键字查询

      php单一关键字查询 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 tdansitional//EN" "http: ...

  10. Keil> 编译器特有的功能 > 关键字和运算符 > __weak

    __weak 此关键字指示编译器弱导出符号. 可以将 __weak 关键字应用于函数和变量声明以及函数定义. 用法 函数和变量声明 对于声明,此存储类指定一个 extern 对象声明,即使不存在,也不 ...

随机推荐

  1. HttpClent4.3 的例子

    package com.unbank.robotspider.util; import java.io.IOException; import java.net.MalformedURLExcepti ...

  2. 02_嵌套矩形(DAG最长路问题)

    来源:刘汝佳<算法竞赛入门经典--训练指南> P60 问题2: 问题描述:有n个矩形,每个矩形可以用两个整数a,b描述,表示它们的长和宽.矩形X(a,b)可以嵌套在矩形Y(c,d)中的条件 ...

  3. Bash Shell read file line by line and substring

    #read one file line by line for line in $(cat test1.txt); do echo $line ; done; #while read split li ...

  4. Helloworld -SilverN

    /*Hello World*/ #include<iostream> #include<cstdio> #include<cstring> using namesp ...

  5. Ubuntu 14.04 单机安装 CEPH

    0.如果先前安装过ceph,则先卸载 sudo stop ceph-all //停止所有CEPH进程 ceph-deploy uninstall [{ceph-node}] //卸载所有ceph程序 ...

  6. 合工大OJ 1330 种树

    Description 某校大门外长度为L的马路上有一排树,每两棵相邻的树之间的间隔都是1米.我们可以把马路看成一个数轴,马路的一端在数轴0的位置,另一端在L的位置:数轴上的每个整数点,即0,1,2, ...

  7. Zookeeper C API 指南一(转)

    Zookeeper 监视(Watches) 简介 Zookeeper C API 的声明和描述在 include/zookeeper.h 中可以找到,另外大部分的 Zookeeper C API 常量 ...

  8. Trie树-可持久化

    // Made by xiper // updata time : 2015 / 12 / 8 // test status: √ // 使用前调用初始化函数 init() 同时 root[0] = ...

  9. C++基础笔记(三)C++面向对象

    C++类 C++类与结构体类似 定义 class 类名{ <成员定义>; ........ }; 文件格式 *.mm 支持 C/C++ *.cpp C++源文件 *.h C++头文件   ...

  10. 每日一语:What is he getting at?

    What is he getting at? 他讲这话是什么意思? 2015-1-12