构造函数、返回值类型、重载、函数参数、ref、out、partial、属性、访问器、索引器、委托
构造函数
使用默认字面量设置字段
internal class Program
{
static void Main(string[] args)
{
Person person1 = new Person("Lee", null);
person1.say(); // Lee ---> 0
Person person2 = new Person("Lee", 18);
person2.say(); // Lee ---> 18
}
}
class Person
{
private string name;
private int age;
public Person(string name, int? age)
{
this.name = name;
this.age = age ?? default; // this.age = age ?? default(int);
}
public void say() {
Console.WriteLine($"{
this.name} ---> {
this.age}");
}
}
构造函数重复定义赋值问题解决
- 在调用构造方法之前查找其他构造方法先行调用
- 在构造
Person(string name, int age, char sex)
方法时先行调用Person(string name)
方法
class Person
{
string Name;
int Age;
char Sex;
public Person(string name) {
Name = name;
}
//public Person(string name, int age, char sex)
//{
// Name = name; // 重复定义
// Age = age;
// Sex = sex;
//}
// 修改重复定义方法
public Person(string name, int age, char sex) : this(name)
{
Age = age;
Sex = sex;
}
}
Person person = new Person("Lee", 23, '1');
静态构造函数
- 不允许使用访问权限修饰符
- 不允许存在参数
- 在第一次使用这个类的时候执行(当类被加载到内存中的时候执行), 再次实例化不会被调用
class MainClass
{
public static void Main(string[] args)
{
// 解决打印中文乱码问题
Console.OutputEncoding = System.Text.Encoding.UTF8;
new Person(); // 静态构造方法被执行 非静态构造方法被执行
new Person(); // 非静态构造方法被执行
}
}
class Person
{
static Person() {
Console.WriteLine("静态构造方法被执行");
}
public Person() {
Console.WriteLine("非静态构造方法被执行");
}
}
函数返回值类型
internal class Program
{
static void Main(string[] args)
{
Person person = new Person("Lee", 18);
Console.WriteLine(person.GetName()); // Lee
Console.WriteLine(person.GetAge()); // 18
(string, int) info1 = person.GetInfo();
Console.WriteLine(info1); // (Lee, 18)
Console.WriteLine($"{
info1.Item1} ---> {
info1.Item2}"); // Lee ---> 18
(string Name, int Age) info2 = person.GetInfo();
Console.WriteLine(info2); // (Lee, 18)
Console.WriteLine($"{
info2.Name} ---> {
info2.Age}"); // Lee ---> 18
// 解构元组赋值
(string name, int age) = person.GetInfo();
Console.WriteLine($"{
name} ---> {
age}"); // Lee ---> 18
}
}
class Person
{
private string name;
private int age;
public Person(string name, int age)
{
this.name = name;
this.age = age;
}
// 返回字符串
public string GetName()
{
return name;
}
// 返回int类型
public int GetAge()
{
return age;
}
// 返回(string, int)元组
// 或者 (string Name, int Age) return (Name: name, Age: age)
public (string, int) GetInfo()
{
return (name, age);
}
}
重载
构造函数重载
internal class Program
{
static void Main(string[] args)
{
new Person(); // 无参构造函数
new Person("Lee"); // Lee
new Person(18); // 18
new Person("Lee", 18); // Lee: 18
new Person(18, "Tom"); // 18: Tom
new Person("Tom", 18, Sex.male); // Tom: 18--->male
}
}
enum Sex
{
male, female
}
class Person
{
public Person()
{
Console.WriteLine("无参构造函数");
}
public Person(string name)
{
Console.WriteLine($"{
name}");
}
public Person(int age)
{
Console.WriteLine($"{
age}");
}
public Person(string name, int age)
{
Console.WriteLine($"{
name}: {
age}");
}
public Person(int age, string name)
{
Console.WriteLine($"{
age}: {
name}");
}
public Person(string name, int age, Sex sex)
{
Console.WriteLine($"{
name}: {
age} ---> {
sex}");
}
}
一般函数重载
internal class Program
{
static void Main(string[] args)
{
Person person = new Person("Tom", 20, Sex.female);
person.say(); // Tom 20 female
person.say("Lee", 18); // Lee 18 female --返回--> Lee
}
}
enum Sex
{
male, female
}
class Person
{
string name;
int age;
Sex sex;
public Person(string name, int age, Sex sex)
{
this.name = name;
this.age = age;
this.sex = sex;
}
public void say()
{
Console.WriteLine($"{
name} {
age} {
sex}");
}
// 重载方法与有无返回值无关
public string say(string name, int age)
{
Console.WriteLine($"{
name} {
age} {
sex}");
return name;
}
}
可选参数
和 命名参数
internal class Program
{
static void Main(string[] args)
{
Person person = new Person();
// 可选参数
person.GetInfo("Tom", 20, "男"); // Tom 20 男
person.GetInfo("Lee", 25); // Lee 25 男
// 命名参数
person.GetInfo(name: "Tom", age: 20, sex: "男"); // Tom 20 男
person.GetInfo(age: 20, sex: "男", name: "Tom"); // Tom 20 男
}
}
class Person
{
// 可选参数
public void GetInfo(string name, int age = 18, string sex = "男")
{
Console.WriteLine($"{
name} {
age} {
sex}");
}
}
ref
和 out
ref
- 用来修饰参数
- 如果一个形参用
ref
修饰,那么实参也需要用ref
修饰 a
的改变是因为用ref
修饰的参数最终传的是实参的地址
public static void Change(ref int x) { x = 20; } int a = 10; Change(ref a); Console.WriteLine(a); // 20
out
- 用来修饰参数
- 如果一个形参用
out
修饰,那么实参也需要用out
修饰 a
的改变是因为用out
修饰的参数最终传的是实参的地址
public static void Change(out int x) { x = 20; } Change(out int a); Console.WriteLine(a);
- 区别
- 在方法结束之前必须对
out
参数赋值public static void Change(out int x) { } // Error 没有对参数x进行赋值
ref
参数可以直接使用,而out
参数需要进行赋值后才能使用(ref参数默认被赋值了而out参数默认没有被赋值
)public static void Change(ref int x) { Console.WriteLine(x); // ok } public static void Change(out int x) { Console.WriteLine(x); // Error 使用了未赋值的变量x x = 20; Console.WriteLine(x); // ok }
- 在方法结束之前必须对
partial
partial
类
internal class Program
{
static void Main(string[] args)
{
Person person = new Person();
person.SayInfo("Tom", 20, "男"); // Tom 20 男
person.SayName("Lee"); // Lee
}
}
partial class Person
{
public void SayInfo(string name, int age, string sex)
{
Console.WriteLine($"{
name} {
age} {
sex}");
}
}
partial class Person
{
public void SayName(string name)
{
Console.WriteLine($"{
name}");
}
}
partial
方法
internal class Program
{
static void Main(string[] args)
{
Person person = new Person();
person.Say("abc"); // abc
}
}
partial class Person
{
public void Say(string text)
{
SayText(text);
}
partial void SayText(string text);
}
partial class Person
{
partial void SayText(string text)
{
Console.WriteLine(text);
}
}
属性和访问器
Person person = new Person
{
Age = 1
};
Console.WriteLine(person.Age);
class Person
{
private static int age;
// Age属性
public int Age {
// 读 属性访问器
get
{
return age;
}
// 写 属性访问器
set {
if (value <= 100)
{
age = value;
}
}
}
}
索引器
using System;
using System.Collections.Generic;
namespace ConsoleApp
{
internal class Program
{
static void Main(string[] args)
{
Person person = new Person();
for (int i = 0; i <= 4; i++)
{
// 【get】 ---> Lee ---> 18 (Lee, 18)
// 【get】 ---> Tom ---> 20 (Tom, 20)
// 【get】 ---> 李四 ---> 11 (李四, 11)
// 【get】 ---> 王五 ---> 30 (王五, 30)
// 【get】 ---> 赵六 ---> 22 (赵六, 22)
Console.WriteLine(person[i]);
}
person[1] = ("张三", 20); // 【set】 ---> Tom ---> 20
Console.WriteLine(person[1]); // 【get】 ---> 张三 ---> 20 (张三, 20)
Console.WriteLine(person[1].Name); // 【get】 ---> 张三 ---> 20 张三
Console.WriteLine(person[1].Age); // 【get】 ---> 张三 ---> 20 20
}
}
class Person
{
public List<(string Name, int Age)> list = new List<(string Name, int Age)> {
("Lee", 18),
("Tom", 20),
("李四", 11),
("王五", 30),
("赵六", 22),
};
public (string Name, int Age) this[int index]
{
get
{
Console.WriteLine($"【get】 ---> {
list[index].Name} ---> {
list[index].Age}");
return list[index];
}
set
{
Console.WriteLine($"【set】 ---> {
list[index].Name} ---> {
list[index].Age}");
list[index] = value;
}
}
}
}
简写赋值
internal class Program
{
static void Main(string[] args)
{
Person person = new Person
{
name = "Lee",
age = 20,
};
Console.WriteLine(person.name); // Lee
}
}
class Person
{
public string name;
public int age;
}
委托 delegate
委托特点
- 是方法类型
- 事件是属于类的成员,所以是要放在类的内部的。而委托,属于一个定义。其实是和类、接口类似的。通常是放在外部的。因为大多数委托都是要被重用的。
- 实例化委托对象需要传入方法来实例化
- 这个方法的
返回值类型
和参数列表
需要和委托保持一致delegate void FunA(); // 委托的声明 class MainClass { public static void Main(string[] args) { // 方法类型 - 委托 // 实例化委托对象需要传入方法来实例化 // 这个方法的返回值类型和参数列表需要和委托保持一致 FunA a = new FunA(FunDemo); // => FunA a = FunDemo; a(); // FunDemo Show ~ } public static void FunDemo() { Console.WriteLine("FunDemo Show ~"); } }
委托的使用情景
存在不同角色,每个角色都存在一个F技能,但是每个角色的F技能的表现形式不同
class MainClass
{
public static void Main(string[] args)
{
Hero mengya = new Hero();
mengya.F = Skill.Jibu;
mengya.F(); // Jibu - 疾步~
Hero guiguzi = new Hero();
guiguzi.F = new SkillDelegate(Skill.Zhiliao);
guiguzi.F(); // Zhiliao - 治疗~
Hero dianwei = new Hero
{
F = Skill.Chengjie
};
dianwei.F(); // Chengjie - 惩戒~
}
}
delegate void SkillDelegate(); // 声明技能委托
// 英雄类
class Hero {
public SkillDelegate F;
}
// 技能类
static class Skill {
public static void Jibu()
{
Console.WriteLine("Jibu - 疾步~");
}
public static void Chengjie()
{
Console.WriteLine("Chengjie - 惩戒~");
}
public static void Zhiliao()
{
Console.WriteLine("Zhiliao - 治疗~");
}
}
组合委托 相当于按了一个按键施展多个技能
public delegate void SkillDelegate();
class MainClass
{
public static void Main(string[] args)
{
SkillDelegate ab = MethodA;
ab += MethodB;
ab(); // MethodA Show ~ MethodB Show ~
ab -= MethodA;
ab(); // MethodB Show ~
ab -= MethodA;
ab(); // MethodB Show ~
ab -= MethodB;
Console.WriteLine(ab == null); // True
ab -= MethodB;
Console.WriteLine(ab == null); // True
}
public static void MethodA()
{
Console.WriteLine("MethodA Show ~");
}
public static void MethodB()
{
Console.WriteLine("MethodB Show ~");
}
}
匿名函数
class MainClass
{
delegate int NumberChanger(int n);
public static void Main(string[] args)
{
NumberChanger nc = delegate (int x)
{
Console.WriteLine("Anonymous Method: {0}", x);
return x;
};
nc(123);
}
}
Lambda =>
class MainClass
{
delegate void NumberChanger(int n);
public static void Main(string[] args)
{
// 写法一
NumberChanger nc1 = delegate (int x)
{
Console.WriteLine("Anonymous Method: {0}", x);
};
nc1(123);
// 写法二
NumberChanger nc2 = (int x) =>
{
Console.WriteLine("Anonymous Method: {0}", x);
};
nc2(123);
// 写法三
NumberChanger nc3 = (int x) => Console.WriteLine("Anonymous Method: {0}", x);
nc3(123);
// 写法四
NumberChanger nc4 = x => Console.WriteLine("Anonymous Method: {0}", x);
nc4(123);
}
}
回调
public delegate int Callback(int res);
class MainClass
{
public static void Main(string[] args)
{
FunA(1, 2, Result);
}
public static int FunA(int x, int y, Callback callback) {
int res = x + y;
return callback(res);
}
public static int Result(int res) {
Console.WriteLine(res);
return res;
}
}