• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
jk-2048
博客园    首页    新随笔    联系   管理    订阅  订阅
刘铁猛C#学习笔记4 方法详解

方法的由来

C++中用两个冒号访问命名空间
如:std::cout << "Hello,World!";
“方法”是一个面向对象的概念,当一个函数作为类的成员出现时,就被称之为方法
方法也可以称作“成员函数”
C++中对类的声明放在.h文件中,而类的定义放在.cpp文件中
c#中类的声明和定义是放在一起的
 
C++:在.h头文件中声明类,包括作为其成员的方法
C++中因为有main函数,所以函数可以单独声明
 
而C#、JAVA是纯面向对象语言,将非面向对象的内容抛弃了
函数只能作为类(或结构体)的成员声明,即方法
C#中方法的声明和定义不分家
声明(可称作方法头)与定义(可称作方法体)必须相连
 
方法的定义格式(方法头):
修饰符 返回值类型 函数名 参数列表
(红色为不可省略)
 
方法修饰符大全:
意义不冲突的修饰符可以组合在一起
 

方法命名规范

给方法命名必须用一个动词或动词短语
使用大驼峰命名
 

形式参数

参数以变量的形式参与到方法内算法逻辑的构成
形式参数是一种变量
待续:ref
 

static(静态)方法

直接隶属于这个类,而非隶属于实例对象的方法
 
总结:
 

调用方法:与C语言完全相同

函数名+圆括号
Name(); 括号内写参数,这里写进去的参数称作实际参数
写进去的实际参数必须与声明的形式参数列表对应(参数个数、参数类型、参数顺序)
声明方法时写的“参数”是parameter,全称formal parameter,形式参数
调用方法时写的“参数”是argument,实际参数
形参是变量,实参是值,C#是强类型语言,变量与值的类型必须匹配才能写入
 
 
 

构造器(构造函数)

是类型(type)的成员之一
构造器用来创建实例在内存当中的内部结构
在之前常用的创造实例的语句
class Student
{
    public int ID;
    public string Name;
}
 
Student stu = new Student();
student();就是构造器,输出发现创建的这个实例ID字段的值为0
当声明了类但没有为类准备构造器时,编译器会自动为其准备一个默认构造器
默认构造器会在内存中创建对象并将把类中的成员初始化
 

创建自定义构造器:

构造器方法的名称必须和类的名称一模一样!
class Student
{
    this.ID = 1;     //初始化字段值
this.Name = "No name"
    }
    
    public int ID;
    public string Name;
}

带参数的构造器:

 
class Student
{
    public Student(int initId , string initName)     
    {                    
        this.ID = initId;     
        this.Name = initName;
    }
    
    public int ID;
    public string Name;
}
当带参数的构造器声明好之后,不带参数的默认构造器Student()将无法使用
必须在括号内写上参数:
Student stu = new Student(2,“Mr.JK”);

构造器重载

重载:一个函数可以有多种定义,通过调用时输入的不同参数来切换不同定义
当既需要能赋初始值的带参数构造器,又需要不赋初始值的无参数构造器时,可使用重载
class Student
{
    //第一定义  有参数
    public Student(int initId , string initName)     
    {                    
        this.ID = initId;     
        this.Name = initName;
    }
    
    //第二定义  无参数
    public Student()
    {
        this.ID = 1;
        this.Name = "No name";
    }
    
    
    public int ID;
    public string Name;
}

Student stu = new Student(2,"Mr.Okay");    //此处调用有参数的第一定义

Student stu2 = new Student();   //调用无参数的第二定义
重载函数根据调用时输入的参数不同来选择执行不同的定义

创建构造器的快捷键

在类中创建构造器的VS快捷键:
输入ctor,然后按两下TAB键
就会自动出现一个构造器

构造器的内存原理

使用默认构造器时
student类有两个字段,其中ID是int类型,是占用四个字节的结构体类型
而Name是string类型,是引用类型,占用四个字节,存储的是引用的实例的地址
 

1.分配内存空间

使用默认的Student stu = new Student(); 时,stu是一个局部变量,应该存储在栈中
图中绿色为声明stu变量时为其准备的内存空间,现在还是空的,要等new操作符执行完后将实例地址存入
new操作符创建实例时在堆上开辟内存
该类的int字段占4字节,string字段占4字节,所以共开辟8个字节的存储空间
 

2.初始化

实例占用的内存空间分配好后,就要调用构造器函数了
构造器会按类型的字段切割分到的内存空间,默认构造器会将空间内值全部刷成0
string变量值都为0时,是NULL值
 

3.将地址存入引用变量

内存分配、初始化结束后,会将创建的实例地址存入引用变量stu
 

自定义构造函数

会在第二步初始化时将值存入实例的字段
string是引用变量,赋值时存的又是另一个实例的地址
 

方法的重载(Overload)

如图所示
Console类里有19个名字叫WriteLine的方法定义
方法名相同,但这19个方法的“方法签名”的不同,按上下键可以切换不同的重载定义,会显示不同的参数
只要方法签名不同,就可以同时定义同名方法作为重载!

方法签名

方法签名由
1.方法的名字
2.方法的类型形参(待续)
3.每一个参数(从左到右)的类型、种类(值、引用或输出)
组成,但方法的签名不包括方法的返回值类型、形参变量名!
错例1:
如图所示两个参数数量、类型、种类完全相同,但返回值类型不同的方法
这样两个方法是不能同时定义的!
错例2:
形参类型、数量、种类相同,但形参变量名不同,这样两个方法也不能同时定义!
再次强调:
构成方法签名的:方法名、类型形参(目前未接触)、从左到右每一个参数类型、种类
两个方法方法名相同,签名不同时,就可以重载
 

补充1:类型形参

使用在泛型方法中
参数的类型也参与到方法体组成的方法
public int Add<T>(int a, int b)
{
    T t;               //声明一个类型为T的变量
    return a + b;
}
以上的<T>就是类型形参
类型形参参与构成方法签名
 

补充2:参数种类(引用传递、值传递)

public int Add(ref int a, int b)
{
    return a + b;
}
以上不加额外修饰符的参数默认为值参数
若在参数类型前加上修饰符ref,就会将其转换为引用传递的参数
若在参数类型前加上修饰符out,就会将其转换为输出参数
称作参数的种类,参数的种类参与构成参数签名
 
实例构造器也可以使用重载,构造器的签名由方法名(与类型名相同的)、形参列表构成
 

重载决策

根据调用时传递进方法的参数的数量、类型来决定使用哪个方法定义
 
 

方法的debug(以VS中为例)

1.断点

在代码一行前面的空白点一下,设置断点后,在调试模式运行时,程序运行到这一行时会暂停,此时可以观察程序的状态,在VS中此时将鼠标放在任意一个变量上,会显示该变量当前的值

2.Call stack(调用栈)

“call stack”窗口会显示调用了断点所在语句的地方
有几层牵涉到断点的调用关系,call stack就有几层,就更深
可以称作调用栈
递归方法如果出现无限递归,调用栈就会越来越深,最后导致内存爆栈
 

3.Step into(步入、逐步执行)

快捷键为F11
单步执行,遇到子函数就进入并且继续单步执行
按F11键,跳转到当前选中的正在被调用的函数的函数体
每按一次F11,call stack窗口就会减少一层
(在调用关系上走到上一层,对调用关系抽丝剥茧)
“最细腻的debug方式”
 

4.Step over(步过)

快捷键为F10
在单步执行时,在函数内遇到子函数时不会进入子函数内单步执行,而是将子函数整个执行完在停止,也就是把子函数整个作为一步
遇到调用函数时,直接走完此函数得到结果
对确认无问题的函数,可以用F10跳过,对有怀疑的函数,可以按F11走进去逐步检查
“稍粗旷一些的debug方式”
 

5.Step out

在单步执行到子函数内时,用Step out就可以执行完子函数余下部分,并返回上一层函数。
 

6.观察局部变量的值的变化

在local窗口中可观察当前打有断点的函数内的局部变量的值
 
posted on 2024-02-23 18:47  JK降谷羽  阅读(78)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3