类型、变量与对象
一、类型
1、什么是类型?
- 又名数据类型(Data Type)
- A data type is a homogeneous collection of values,effectively presented,equipped with a set of operations which manipulate these values.
- 是数据在内存中存储时的“型号”
- 小内存容纳大尺寸数据会丢失精确度、发生错误
- 大内存容纳小尺寸数据会导致浪费
- 编程语言的数据类型与数据的数据类型不完全相同
- 强类型语言与弱类型语言的比较
- C语言示例:if条件
//
int x = 100;
//弱类型的坏处:为了防止出错可以写为
//if(200==x)
if (x=200)
{
printf("It,s OK!
");
}
return 0;
std::cout << "Hello World!
";
- JavaScaript示例:动态类型
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script>
function ButtonClicked() {
var MyVar = 100;
MyVar = "Mr. Okay";
alert(MyVar);
}
</script>
</head>
<body>
<h1>Hello,JavaScript</h1>
<input type="button" value="Click me" onclick="ButtonClicked()"/>
</body>
</html>
- C#语言对弱类型/动态类型的模仿
dynamic myVar=100;
Console.WriteLine(myVar);
myVar="Mr.Okey";
Console.WriteLine(myVar);
2、类型在C#语言中的作用
- 一个C#类型中所包含的信息有:
- ① 存储此类型变量所需的内存空间大小
- ② 此类型的值可表示的最大、最小值范围
- ③ 此类型所包含的成员(如方法、属性、事件等)
Type myType = typeof(Form);
Console.WriteLine(myType.BaseType.FullName);
PropertyInfo[] pInfos = myType.GetProperties();
foreach (var p in pInfos )
{
Console.WriteLine(p.Name);
}
MethodInfo[] mInfos = myType.GetMethods();
foreach (var m in mInfos )
{
Console.WriteLine(m.Name);
}
- ④ 此类型由何基类派生而来
- ⑤ 程序运行的时候,此类型的变量在分配在内存的什么位置
- Stack简介
- Stack overflow
- Heap简介
- 使用Performance Monitor查看进程的堆内存使用量
- 关于内存泄漏
//例子一:
class Program
{
static void Main(string[] args)
{
BadGuy bg = new BadGuy();
bg.BadMethod();
}
}
class BadGuy
{
public void BadMethod()
{
int x = 100;
this.BadMethod();
}
}
//例子二:右键属性勾选“允许不安全的代码”
unsafe
{
int* p = stackalloc int[999999999];
}
//例子三:观察内存
List<Window> winList;
private void Button1_Click(object sender, RoutedEventArgs e)
{
winList = new List<Window>();
for (int i = 0; i < 15000; i++)
{
Window w = new Window();
winList.Add(w);
}
}
private void Button2_Click(object sender, RoutedEventArgs e)
{
winList.Clear();
}
- ⑥ 此类型所允许的操作(运算)
C#语言的类型系统
C#的五大数据类型
- C#的五大数据类型
- 类(Classes)
- 结构体(Structure)
- 枚举()
- 接口(Interface)
- 委托(Delegate)
//类:
Type myType = typeof(Form);
Console.WriteLine(myType.FullName);
Console.WriteLine(myType.IsClass);
//F12可以看到是类
//结构体:int、long
//枚举:
Form f = new Form();
//FormWindowState.Maximized
f.WindowState = FormWindowState.Maximized;
f.ShowDialog();
-
C#类型的派生谱系
变量、对象与内存
1、什么是变量
- 表面上来看,变量的用途是存储数据
- 实际上,变量表示了存储位置,并且每个变量都有一个类型,以决定什么样的值能够存入变量
- 变量一共有7中
- 静态变量、实例变量(成员变量,字段),数组元素,值参数,引用参数(ref),输出形参(out),局部变量
Student stu = new Student();
Student.Amount = 100; //静态变量
stu.Age = -1; //实例变量
int[] array = new int[100]; //数组变量
array[0] = 1; //数组元素
//学生类
class Student
{
public static int Amount;
public int Age;
public string Name;
public double Add(double a,double b)
{
double result; //局部变量
result = a + b;
return a + b;
}
}
- 狭义的变量指局部变量,因为其它种类的变量都有自己的约定名称
- 简单的讲,局部变量就是方法体(函数体)里声明的变量
- 变量的声明
- 有效的修饰符组合opt类型 变量名 初始化器opt
变量=以变量名所对应的内存地址为起点、以其数据类型所要求的存储空间为长度的一块内存区域
2、值类型的变量
- 以byte/sbyte/short/ushort为例
byte b=100;
sbyte sb=100;
ushort us=1000;
short s = -1000;
string str = Convert.ToString(s, 2);
Console.WriteLine(str);
- 值类型没有实例,所谓的“实例”与变量合二为一
3、引用类型的变量与实例
- 引用类型变量与实例的关系:引用类型变量里存储的数据是对象的内存地址
4、局部变量实在stack上分配内存
5、变量的默认值
6、常量(值不可改变的变量)
- const
7、装箱与拆箱(Boxing&Unboxing)
- (值类型和引用类型相互转换)
方法
方法的定义、调用和调试
1、方法的由来
- 方法(method)的前身是C/C++语言的函数(function)
- 方法是面向对象范畴的概念,在非面向对象语言中仍然称为函数
- 使用C/C++语言做对比
#include <stdio.h>
double Add(double a, double b)
{
return a + b;
}
int main()
{
//
printf("Hello World!");
//
double x = 3.0;
double y = 5.0;
double result = Add(x, y);
printf("%f+%f=%f", x, y, result);
return 0;
}
#include <iostream>
double Add(double a, double b)
{
return a + b;
}
int main()
{
std::cout << "Hello World!";
double x = 3.0;
double y = 5.0;
double result = Add(x, y);
std::cout << x << "+" << y << "=" << result;
return 0;
}
- 永远都是类(或结构体)的成员
- C#语言中函数不可能独立于类(或结构体)之外
- 只有作为类(结构体)的成员才被成为方法
- C++中是可以的,称为“全局函数”
- 是类(或结构体)最基本的成员之一
- 最基本的成员只有两个--字段与方法(成员变量与成员函数),本质还是数据+算法
- 方法表示类(或结构体)“能做什么事”
- 为什么需要方法和函数
- 隐藏复杂的逻辑
- 把大算法分解为小算法
- 复用(reuse,重用)
- 计算圆面积、圆柱体积、圆锥体积
2、方法的定义与调用
- 声明方法的语法详解
- 参见C#语言文档(声明/定义不分家)
- Parameter全称为“formal parameter”形式上的参数简称“形参”
- Parameter是一种变量
- 方法的命名规范
- 大小写规范
- 需要以动词或者动词短语作为名字
- 重温静态(static)方法和实例方法
- 调用方法
- Argument中文C#文档的官方译法为“实际参数”,简称“实参”,可理解为调用方法时的真实条件
- 调用方法时的argument列表要与定义方法时的parameter列表匹配
- C#是强类型语言,argument是值,parameter是变量,值与变量一定要匹配
3、构造器(一种特殊的方法)
- 构造器(Constructor)是类型的成员之一
- 狭义的构造器值得是“实例构造器”(instance constructor)
- 如何调用构造器
- 声明构造器
- 构造器的内存原理
4、方法的重载(Overload)
- 调用重载方法的实例
- 声明带有重载的方法
- 方法签名(method signature)由方法的名称、类型形参的个数和它的每一个形参(按从左到右的顺序)的类型和种类(值、引用或输出)组成。方法签名不包括返回类型。
class Calclator
{
public int Add(int a,int b)
{
return a + b;
}
public double Add(double a,double b)
{
return a + b;
}
public int Add<T>(int a,int b)
{
return a + b;
}
}
- 实例构造函数签名由它的每一个形参(按从左到右的顺序)的类型和种类(值、引用或输出)组成。
- 重载决策(到底调用哪一个重载):用于在给定了参数列表和一组候选函数成员的情况下,选择一个最佳函数成员来实施调用。
5、如何对方法进行debug
- 设置断点(breakpoint)
- 观察方法调用时的call stack
- Step-in,Setp-over,Step-out
- 观察局部变量值得变化
6、方法的调用与栈
- 方法调用时栈内存的分配
- 对stack frame的分析