封装
概念
装箱即封装,封装是为了将数据的一些操作封闭起来,避免不正当操作。比如事件就是对委托的一种封装。
装箱与拆箱
装箱和拆箱是值类型和引用类型之间相互转换是要执行的操作。
- 装箱在值类型向引用类型转换时发生
- 拆箱在引用类型向值类型转换时发生
int x=100然后Object o=x;这时候会在堆内存中开辟一个地址,然后100装箱放入这地址中,最后栈内存中记录地址
拆箱 int y=(int)o,找到o在堆内存的值,然后cp到栈内存中
装箱操作和拆箱操作是要额外耗费cpu和内存资源的,所以在c# 2.0之后引入了泛型来减少装箱操作和拆箱操作消耗。
方法(里面有关重载描述,重写规则暂无)
概念
方法是对于面向对象语言,函数是对于非面向对象语言,面对对象的方法是依赖于对象或者结构体的的,c这些就不是,直接调用即可
重载规则:
- 被重载的方法必须改变参数列表(形参个数、类型和顺序不一样);
- 有无类型形参、out ref等都可以构成重载(Add T计算类型形参)
- 被重载的方法可以改变返回类型,**但是无法以返回值类型作为重载函数的区分标准。**很简单,因为这样无法确定给你什么返回什么类型给你
- 被重载的方法可以改变访问修饰符;
- 被重载的方法可以声明新的或更广的检查异常;
- 方法能够在同一个类中或者在一个子类中被重载。
重写规则
重写相关在数据类型中的类中
new与重写
关于new与重写,详情在关键字一篇中
参数
传值参数
传值参数->值类型
传值参数->引用类型
(传值参数->引用类型)与(传值参数->值类型)的自我理解
主要内容
说白了,就像做算法题中传数组那样,如果你传引用类型参数给方法的,你在方法里面修改这个值,调用者的参数也会跟着修改,但是值参数是直接存在栈当中copy的,所以不会修改调用者的参数。而引用类型的传参是传地址的,方法中修改了 ,调用者的参数也跟着修改
注意, 如果方法中重新给了参数新的地址(比如赋值给了一个刚new的对象),你再修改这个参数,不会影响到调用者的参数(虽然实际上没人这么写)
引用参数ref(可以直接搜索ref查看定义)
引用参数->值类型
修改参数可以修改到调用者的变量
引用参数->引用类型
如果方法中形参不赋予了一个new对象,那么和传值参数一样,没有区别
如果在方法中形参赋予了一个new对象,这样不单止会修改调用者的变量的值,甚至把调用者的对象都改变了,原理好像式在方法中创建了一个局部变量,修改局部变量以及方法结束后,调用者的变量指向地址会改为局部变量的地址。
输出参数
也就是说,调用者可以不给输出参数赋值,赋值了也传递不了,但是方法中,结束前一定要明确赋值
数组参数
params
使用 params
关键字可以指定采用数目可变的参数的方法参数。 参数类型必须是一维数组。
在方法声明中的 params
关键字之后不允许有任何其他参数,并且在方法声明中只允许有一个 params
关键字。
如果 params
参数的声明类型不是一维数组,则会发生编译器错误 CS0225。
使用 params
参数调用方法时,可以传入:
- 数组元素类型的参数的逗号分隔列表。
- 指定类型的参数的数组。
- 无参数。 如果未发送任何参数,则
params
列表的长度为零。
public class MyClass
{
public static void UseParams(params int[] list)
{
for (int i = 0; i < list.Length; i++)
{
Console.Write(list[i] + " ");
}
Console.WriteLine();
}
public static void UseParams2(params object[] list)
{
for (int i = 0; i < list.Length; i++)
{
Console.Write(list[i] + " ");
}
Console.WriteLine();
}
static void Main()
{
// You can send a comma-separated list of arguments of the
// specified type.
UseParams(1, 2, 3, 4);
UseParams2(1, 'a', "test");
// A params parameter accepts zero or more arguments.
// The following calling statement displays only a blank line.
UseParams2();
// An array argument can be passed, as long as the array
// type matches the parameter type of the method being called.
int[] myIntArray = { 5, 6, 7, 8, 9 };
UseParams(myIntArray);
object[] myObjArray = { 2, 'b', "test", "again" };
UseParams2(myObjArray);
// The following call causes a compiler error because the object
// array cannot be converted into an integer array.
//UseParams(myObjArray);
// The following call does not cause an error, but the entire
// integer array becomes the first element of the params array.
UseParams2(myIntArray);
}
}
/*
Output:
1 2 3 4
1 a test
5 6 7 8 9
2 b test again
System.Int32[]
*/
具名参数
提高代码的可读性,而且可以让参数顺序改变位置
可选参数
让声明时具有默认值
扩展方法(this参数)
效果
例如double中式没有Round方法的,而double式C#自带的,我们无法更改double的源码,这时候如何给 double加方法了,就式下面那样,搞好静态方法后,input就是x本身,所以不需要输入了,只需要输入digits就可以了
参数总结
重写与重载之间的区别
区别点 | 重载方法 | 重写方法 |
---|---|---|
参数列表 | 必须修改 | 一定不能修改 |
返回类型 | 可以修改 | 一定不能修改 |
异常 | 可以修改 | 可以减少或删除,一定不能抛出新的或者更广的异常 |
访问 | 可以修改 | 一定不能做更严格的限制(可以降低限制) |
重写是重写父类方法Override Override Override
Overload才是重载,别再搞混了
调试
callstack 调用堆栈,从这里可以看到谁调用了这方法,调用顺序
step-in 逐语句,会进入深层次的方法中
step-over 逐过程,按本方法顺序执行,不会进入深层次
step-over 跳出
vs中鼠标移动到对应的变量就会显示当前方法这个位置当前的值对应的值,比如int x=0然后x=100, 哪怕运行到x=100了,鼠标移动到x时是0
操作符