CSharp初级篇 1-4 this、索引器、静态、常量以及只读
.NET Core CSharp初级篇 1-4
本节内容为this、索引器、静态、常量以及只读
简介
在之前的课程中,我们谈论过了静态函数和字段的一小部分知识,本节内容中,我们将详细的讲解关于对象操作的例子,以及更加深入的解释面向对象。
常量
常量,顾名思义,就是一直为同一个值的变量,并且值不可以被改变。在C#中,定义一个常量需要使用const关键字声明。常量并不占用内存的空间。在C#程序编译的时候,编译器会把任何使用了该常量替换成这个值。
因为常量并不存储在内存中,因此常量只允许使用内置的数值类型,例如:bool、char、string、enum。并且声明的同时必须对常量进行初始化。
例如我们应用的版本号,通常在应用编译完成之后都是以一个常量存在,也不需要对他进行操作。看下列代码。
public const string Version="v2.1.1"
public string getString(string msg)
{
return "Copyright@2019" + msg + Version;
}
上述函数代码在编译时,将会变成:
public string getString(string msg)
{
return "Copyright@2019" + msg + "V2.1.1";
}
因为常量的上述特性,如果Y程序集使用了X程序集中的这个Version常量,如果X修改了该常量为“2.1.2”并重新编译,若Y不重新编译,Y中常量还是“2.1.1”,因为该常量会被直接固化于Y中并用常量值替换变量名。因此需要y进行重新编译才会使用新的常量值。
静态
静态是一个很常用的语法,我们可以在类中构造各种静态成员,例如静态字段、函数等等。再C#中定义静态成员的方法是使用修饰符static,调用的时候只需要使用“类名.成员名”。
在之前的课程中,我顺带提过一次,静态是一个只初始化执行一次,属于全体共有的一个东西,也可以说是该静态成员属于类本体所有,而不是每一个对象所有。我们就从静态构造函数、静态字段、静态函数这三块进行一个详细的讲解。
静态构造函数
我们之前以及对构造函数进行过一个简单的介绍,构造函数是在类被初始化(实例化)的时候调用,并且每创建一个对象就会调用一次构造函数。
而静态构造函数是每一个类型执行一次,也就是这个类型的所有对象公用一个静态构造函数。这区别与普通构造函数的一个对象执行一次。并且对于静态构造函数而言,一个类只允许有一个静态构造函数,并且必须无参。
静态构造函数在你访问一个类型的静态成员的时候,或者实例化一个类型的时候,编译器会自动的调用静态构造函数。
特别的,因为该初始化的构造函数(静态构造函数)属于所有变量共有并且会调用,那么假设该构造函数报错,那么这个类将再程序剩余生命周期内无法再被使用。
静态字段
静态字段也是一样,属于一切成员公有,在任何地方你都可以不实例化类的情况下对静态字段操作。
对于静态字段的初始化,分为两种情况:
- 假定类存在一个静态构造函数,那么静态字段在静态构造函数被调用的一瞬间就会初始化;
- 假定不存在静态构造函数,那么静态字段将会被类型被使用之前的一瞬间初始化(最晚执行),或者更早,在运行时的某一时间(并无法确定)被初始化。
静态字段初始化的顺序则与定义时的顺序一致,例如:
class A
{
public static int X = Y;
public static int Y = 15;
}
.....
Console.WriteLine("X:{0},Y:{1}",X,Y)
上例中,X,Y的初始化顺序是X先被初始化,此时Y没有初始化,则是0,因此输出是X:0,Y:15。
静态函数
与之前一样,静态函数可以在不实例化类的情况下调用,但是注意,在静态函数中,不允许使用任何非静态的字段。调用的时候直接使用类名.函数名()即可。
静态类
如果一个类,被声明为静态类,那么该类不可以被实例化,也不可以被继承,同时不可以包含非静态成员。非静态类中,可以包含静态成员。
只读
只读用于字段的访问控制,使用readonly关键字,通常情况下也可以使用无set访问器的属性进行实现。
class A
{
public string test{get;}
public readonly string _test;
}
静态成员的生命周期
从程序开始初始化到程序结束,因此滥用静态会导致性能问题。
this关键字
在C#中,this关键字表示操作的当前对象,在类里面,如果你使用this关键字,则this指代的是你每次操作对象时的当前对象。特别的,如果你的函数形参名称和字段名相同,并且你需要同时操作这个两个变量,那么你需要使用this关键字去指明你的操作对象,例如:
class A
{
private string data;
public string Data{get{return data;}}
public void SetData(string data)
{
//this.data表示是当前对象的字段data
this.data = data;
}
}
索引器
在之前的数组操作中,相信大家都发现了数组的访问通过了一个中括号和下标的方式进行访问,这个东西我们称为索引器。但是在类中的索引器可以以任何类型作为索引的key,这使得整个类的拓展性变得很好。
如何去定义一个索引器呢?这里就需要用到我们的this关键字了。定义的方式有点类似我们对于属性的定义
public class A
{
public double[] arry{get;set;}
public double this [int index]
{
get
{
return arry[index];
}
set
{
arry[index] = value;
}
}
}
通过索引器,我们可以自己定义各种不同的索引方式,而不用拘泥于下标访问
习题
1.请问下列代码输出什么?为什么?
class A
{
public static A a = new A();
public static int X = 3();
A()
{
Console.WriteLine(X);
}
}
class Program
{
static void Main()
{
Console.WriteLine(A.X);
}
}
2.试着使用索引器,写出一个二维数组的索引访问,要求实现倒序访问(即a[0]访问最后一位)
前往Github获取更多本节资料(PPT,实例代码)
如果我的教程帮到了您,希望您动动小手,在GitHub给我一个star
CSharp初级篇 1-4 this、索引器、静态、常量以及只读的更多相关文章
- .NET Core CSharp初级篇 1-8泛型、逆变与协变
.NET Core CSharp初级篇 1-8 本节内容为泛型 为什么需要泛型 泛型是一个非常有趣的东西,他的出现对于减少代码复用率有了很大的帮助.比如说遇到两个模块的功能非常相似,只是一个是处理in ...
- .NET Core CSharp初级篇 1-1
.NET Core CSharp初级篇 1-1 本节内容是对于C#基础类型的存储方式以及C#基础类型的理论介绍 基础数据类型介绍 例如以下这句话:"张三是一名程序员,今年15岁重50.3kg ...
- NET Core CSharp初级篇 1-3面向对象
.NET Core CSharp初级篇 1-3 本节内容为面向对象初级教程 类 简介 面向对象是整个C#中最核心最有特色的一个模块了,它很好的诠释了程序与现实世界的联系. 面向对象的三大特征:继承.多 ...
- .NET Core CSharp初级篇 类的生命历程
.NET Core CSharp初级篇 1-7 本节内容为类的生命周期 引言 对象究竟是一个什么东西?对于许多初学者而言,对象都是一个非常抽象的知识点.如果非要用一句话描述,我觉得"万物皆对 ...
- .NET Core CSharp初级篇 1-5 接口、枚举、抽象
.NET Core CSharp初级篇 1-5 本节内容类的接口.枚举.抽象 简介 问题 如果你需要表示星期或者是某些状态,使用字符串或者数字是否不直观? 你是否发现,无论何种电脑,它的USB口的设计 ...
- .NET Core CSharp初级篇 1-6 类的多态与继承
.NET Core CSharp初级篇 1-6 本节内容为类的多态与继承 简介 终于讲到了面向对象三大特性中的两大特性--继承与多态.通过继承与多态,我们能很好的将类的拓展性发挥到了极致.在下面的内容 ...
- .NET Core CSharp初级篇 1-2 循环与判断
.NET Core CSharp初级篇 1-2 本节内容循环与判断 循环 循环是一个在任何语言都是极为重要的语法,它可以用于很多东西,例如迭代数组等等.在C#中,语法层面的循环有:for , fore ...
- Kotlin——初级篇(二):变量、常量、注释
在Kotlin中的变量.常量以及注释多多少少和Java语言是有着不同之处的.不管是变量.常量的定义方式,还是注释的使用.下面详细的介绍Kotlin中的变量.常量.注释的使用.以及和Java的对比. 如 ...
- C# 索引器的理解和使用
概述 此部分内容引用自MSDN文档 使用索引器可以用类似于数组的方式为对象建立索引. get 取值函数返回值. set 取值函数分配值. this 关键字用于定义索引器. value 关键字用于定义 ...
随机推荐
- Android零基础入门第26节:layout_gravity和gravity大不同
原文:Android零基础入门第26节:layout_gravity和gravity大不同 上一期我们一起学习了LinearLayout线性布局的方向.填充模型和权重,本期来一起学习LinearLay ...
- C#字符类型
C#字符串类型采用Unicode字符集,一个Unicode标准字符长度位16位,它允许用单个编码方案表示世界上使用的所有字符. 字符类型表示位char. 关于字符的转义:C#也可以使用字符转义,用 ...
- 配置QtCreator+CDB远程调试环境(用到了符号表) good
相关环境信息:开发机Win7 x64.远程机器WinXP.调试器是CDB.Qt版本5.2.1 一.部署远程机器环境 我这里用的是虚拟机(Windows XP),根据你要调试的程序选择安装不同架构的Wi ...
- Qt多线程学习-用例子来理解多线程
文章出处:DIY部落(http://www.diybl.com/course/3_program/c/c_js/20090303/157373_3.html) POINT 1:QThread类的实例与 ...
- c++实现游戏开发中常用的对象池(含源码)
c++实现游戏开发中常用的对象池(含源码) little_stupid_child2017-01-06上传 对象池的五要素: 1.对象集合 2.未使用对象索引集合 3.已使用对象索引集合 4.当前 ...
- 预编译加速编译(precompiled_header),指定临时文件生成目录,使项目文件夹更干净(MOC_DIR,RCC_DIR, UI_DIR, OBJECTS_DIR),#pragma execution_character_set("UTF-8")"这个命令是在编译时产生作用的,而不是运行时
预编译加速编译 QT也可以像VS那样使用预编译头文件来加速编译器的编译速度.首先在.pro文件中加入: CONFIG += precompiled_header 然后定义需要预编译的头文件: PREC ...
- Gradle添加外部项目代码
为了测试一些功能,我想在公司的项目中引进外部项目的子模块代码进来调试,试验了好半天终于成功了... 原来不需要导入代码,只要在settings.gradle中这样就好了: 然后就可以和原项目中的代码一 ...
- 测试 Components 与 Controls 的区别(嵌套在Panel上的Edit,依然是Form1的Component)
本例效果图: 代码文件: unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, ...
- UILabel实现自适应宽高需要注意的地方(二)
需求图如下所示 UILabel "上期" 距离屏幕最左边 有35px UILabel "下期" 距离屏幕最右边 有35px 进行中文字在UIlabe ...
- return Json对象时序列化错误
当要序列化的表与另一个表是一对多的关系是,表1序列化时会找到另一个表2关联的字段,会将另一个表2进行序列化,然后表2中也有一个字段与表1关联,这样序列化就会产生循环序列化. 在网上进行搜索,其中大多数 ...