C# 的语法基础
文章目录
1.int与int?
int? , 表示可空类型,即是值可以为null
int i = default(int);//默认值为0
int? j = default(int?);//默认值为null
Null 与任何运算符运算都是null
j = null;
int? k = j + 5;//k值为null
2.文本的输出
- 只有整条语句带分号,块是不带分号的。
- 直接使用:来指定数据的样式
static void Main(string[] args)
{
Console.WriteLine("Hello World!");// 语句后边带分号
Console.WriteLine($"{3000:C}");
Console.WriteLine($"{0,2}",600);
// 指定同上边第二位对齐
Console.WriteLine($"{0:C}", 600);
}// 块后面不带分号
数据样式:
- c:货币
- d:十进制
- f:浮点
- P: 百分比
- e:科学记数法
3.类
类包括数据成员和函数成员
与类平级的预定义类型
- 类
- 结构
- 枚举
- 数组
- 委托
- 接口
C # 与C++ 等有所不同,C# 没有全局变量的概念,即函数不能再类外声明,同样的,C#中也没有默认的返回类型,必须是指定的返回类型或者 void。
3.1类的实例
类的声明,是用来构建类的蓝图,一旦被声明,即可构建类的实例。既然要实例化一个类,就要用类的引用和实际数据都申请内存。
NewClass A = new NewClass();
实例化一个类,就要分配一个空间,分配空间,就要用new
关键字,而且后边要跟()
3.2类的访问修饰符
在类的内部,任何成员之间都可以相互访问。
- private:(不带访问符号,默认就是私有成员) 只能他自己的类访问
- public:
- protected:允许自己和派生类可以访问
- internal:程序集内部可见
- protected internal:派生类
或
程序集内部可见
3.3方法的参数类型
参数类型 | 修饰符 | 执行 |
---|---|---|
无 | 系统把形参的值复制给实参 | |
引用 | ref | 形参是实参的别名 |
输出 | out | 仅包含一个返回的值,形参是实参的别名 |
数组 | params | 允许传递可变数目的实参到方法 |
引用参数
public int Add(ref int a, ref int b)
输出参数
void Method (out int a)
static void Main(string[] args)
{
int sum;
Add(out sum, 5, 8);
Console.WriteLine(sum);
}
public static void Add(out int c, int a, int b)
{
c = a + b;
}
与引用参数不同,输出参数有以下要求:
- 输出参数在被读取之前,必须先被赋值。
- 在方法返回之前,方法内部任何可能路径,都必须为所有输出参数赋值一次。
数组参数
“数组参数”和数组是两码事,注意区分
- 一个参数列表里,只能有一个数组参数,而且必须放在最后
- 数组参数的所有参数都必须有相同的类型
声明方法如下:
void Method(int a,params int[] mm)
3.4命名参数
上边看到的都是位置参数,也就是说每个形参的位置都应该和实参的位置一一对应,除此之外,还可以使用命名参数,这样就可以任意顺序调用参数了。
Method(a: 3, b: 6, c: 3);
3.5可选参数
即给参数提供默认值
void Method(int a,int b=3)
{
}
如果这几种参数都存在的话,他们的声明的顺序之间的关系,如下图:
4.对象初始化语句
即在 new 对象的时候,就对里面的一些属性和字段赋值
注意写法
class ClassA
{
public int A { get; set; }
public int B { get; set; }
}
// 对象初始化语句
ClassA classA = new ClassA () { A = 9, B = 3; }
// 如果选择使用没有参数的构造函数,后面的()可以直接不写。
ClassA classA = new ClassA { A = 9, B = 3; }
对比实例构造函数的方法的声明方式,注意区分
class ClassA
{
public int Id { get; set; }
public string Name { get; set; }
public ClassA(int id) { Id = id; }
}
ClassA classA = new ClassA(3);
5.类和继承
6.1 屏蔽基类的成员
派生类不能删除他继承的任何成员,但是可以用与其基类名称相同的成员来屏蔽基类成员。(此时,要让编译器知道你在故意屏蔽继承的成员,所以要用 new 修饰符,否则编译器会弹出警告。)
class SomeClass {
public string str { get; set; }
}
class OtherClass : SomeClass
{
new public string str { get; set; }
}
6.2 关于继承需要注意的点:
- 除了特殊的 object 类,所有的类都是派生类,即使他们没有基类规格说明,类 object 是唯一的非派生类。
- 虽然类只能继承一个基类,但是继承的层次没有限制。
6.3 基类的访问
如果基类必须要完整的访问被隐藏的基类,可以可以使用 基类访问表达式 访问隐藏的基类
基类的表达式是由关键字 base
后边跟一个点和成员的名字组成。
class SomeClass {
public string str = "SomeClass 类";
public void Method1(string value)
{
Console.WriteLine($"SomeClass 中的 {value}");
}
}
class OtherClass : SomeClass
{
new public string str = "OtherClass";
public void Method2(string value)
{
Console.WriteLine($"OtherClass中的 {base.str}");
}
}
如果你代码中,经常使用这个特性(即访问隐藏的继承类),那么你可能要重新评估类的设计了,一般来说,都是在没有其他办法的时候,使用这个特征。
6.4 使用基类的引用
class Program
{
static void Main(string[] args)
{
OtherClass otherClass = new OtherClass();
SomeClass someClass = (OtherClass)otherClass;
someClass.Print();
otherClass.Print();
}
}
class SomeClass {
public void Print()
{
Console.WriteLine("这是基类");
}
}
class OtherClass : SomeClass
{
new public void Print()
{
Console.WriteLine("这是派生类");
}
}
输出:
这是基类
这是派生类
6.5 虚方法和覆写方法
上边无论是 base
还是 强制类型转换
,都是使用子类调用父类的方法,如果想用父类调用子类的方法,就要用到 虚方法
class Program
{
static void Main(string[] args)
{
OtherClass otherClass = new OtherClass();
SomeClass someClass = (OtherClass)otherClass;
someClass.Print();
otherClass.Print();
}
}
class SomeClass
{
virtual public void Print()
{
Console.WriteLine("这是基类");
}
}
class OtherClass : SomeClass
{
override public void Print()
{
Console.WriteLine("这是派生类");
}
}
输出:
这是派生类
这是派生类
注意:
- 覆写和被覆写的方法,都必须有相同的可访问性,不能被覆写的是
private
,而覆写的是public
- 不能覆写
static
和非虚方法。 - 这种方法,只能在类型转换过程中,才能使用,直接引用无效。
6.6 继承中构造函数的使用
- 要创建对象的基类部分,需要隐式调用基类的某个构造函数做为创建实例的一部分。
- 继承层次链中,每个类在执行自己的构造函数体之前,都要执行他基类的构造函数。
创建一个实例的过程如下:
class SomeClass
{
virtual public void Print()
{
Console.WriteLine("这是基类");
}
}
class OtherClass : SomeClass
{
int MyFiled1 = 5; // 成员初始化
int MyFiled2;
public OtherClass() // 构造函数执行,调用基类的无参构造函数 SomeClass()
{
}
override public void Print()
{
Console.WriteLine("这是派生类");
}
}
默认情况下,在构造对象的时候,会调用基类无参数的构造函数,但是构造函数可以重载,有可能有多个构造参数,所以如果派生类使用一个指定的基类构造函数,就要在构造函数初始化语句
中使用他。
有两种形式:
- 使用关键字
base
并指明使用哪一个基类构造函数。 - 使用关键字
this
指明应该使用当前类的哪一个构造函数。
base的用法:
class SomeClass
{
public string someClassString;
public SomeClass() // 这个无参的构造函数不能省
{
}
public SomeClass(string a)
{
someClassString = a;
}
}
class OtherClass : SomeClass
{
int MyFiled1 = 5; // 成员初始化
int MyFiled2;
public OtherClass(string a ):base(a) // 把构造函数,从子类传到父类。
{
}
}
6.7 抽象成员
抽象成员是指被设计为要被覆写的函数成员。他具有以下特征
- 必须是一个函数成员。字段和常量不行。
- 必须要用
abstract
修饰符。 - 不能有实现的代码块。
- 抽象成员只能在抽下类中声明。
abstract public void PrintStuff(string s);
虚成员和抽象成员的比较
虚成员 | 抽象成员 | |
---|---|---|
关键字 | virtual | abstract |
实现体 | 实现体 | 没有实现体 |
在派生类中覆写 | 能被覆写,使用 override | 必须被覆写,使用 override |
成员的类型 | 属性,事件,方法 ,索引器 | 属性,事件,方法 ,索引器 |
6.8 抽象类
抽象类是指定被继承的类。抽象类只能做其他类的基类
- 就是用来被继承的(只能用作其他类的基类)
- 不能被实例化
6.8 密封类
上边讲,抽象类必须用作基类,不能被实例化,而密封类恰恰与他相反。
- 密封类只能用作独立的类,不能用作基类
- 密封类使用
sealed
修饰符
6.this 关键字
- this 关键字在类中使用,是对当前实例的引用。
- 静态成员显然不是实例的一部分,所以不能再任何静态函数成员的代码中,使用 this 关键字
参考文献
[1]https://blog.csdn.net/weixin_38211198/article/details/96841992