一、解决方案与项目
1. Solution 与 project
在 C# 编程里,Solution(解决方案)和 Project(项目)是两个重要的概念,它们是组织代码的基础。
Solution(解决方案)
这是一个容器,其作用是管理多个相关的项目。它不会包含实际的代码,主要用于保存项目的配置信息以及项目间的依赖关系。在 Visual Studio 中,解决方案的文件扩展名为 .sln。主要功能:
- 对多个项目进行组织和管理,像一个应用程序可能由 Web 项目、类库项目、测试项目等共同组成。
- 对项目间的引用关系进行定义,例如 Web 项目会引用类库项目。
- 对全局设置进行配置,比如版本控制、编译顺序等。
Project(项目)
项目是代码的实际载体,它定义了编译单元,并且会生成输出文件,像 .exe 或者 .dll 等。每个项目都有自己独立的配置文件(.csproj)。
常见的项目类型:
- 控制台应用程序(Console App):生成 .exe 文件,可直接运行。
- 类库(Class Library):生成 .dll 文件,用于被其他项目引用。
- ASP.NET Web 应用程序:用于构建网站或者 API 服务。
- 单元测试项目:用于编写测试代码。
Visual Studio 下面的解决方案图
二、类与名称空间
1.类与名称空间
类(class)
类 (class) 是最基础的 C# 类型。类是一个数据结构,将状态(字段)和操作(方法和其他函数成员)组合在一个单元中。类为动态创建的类实例 (instance) 提供了定义,实例也称为对象 (object)。类支持继承 (inheritance) 和多态性 (polymorphism),这是派生类 (derived class) 可用来扩展和专用化基类 (base class) 的机制。
名称空间(namespace)
名称空间是一种组织机制,用于对代码进行逻辑分组,避免命名冲突,提升代码的可维护性。它就像是一个容器,能包含类、接口、结构体等类型
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HelloWorld
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World");
System.Console.WriteLine("Hello World");
}
}
}
- HelloWorld , System 则为名称空间
- Program,Console 则为类
- WriteLine 为方法
2.类库的引用
类库引用是使用名称空间的物理基础
1. DLL引用(黑盒引用,无源代码)
使用 FastReport 里面的方法
namespace HelloWorld
{
class Program
{
static void Main(string[] args)
{
FastReport.BandBase.GetData();
}
}
}
2. Nuget 引用
注意:
NuGet 管理器 有可能 一直在加载中,什么都没显示出来:
- 解决: visual Studio -> 工具 -> 扩展与更新,直接卸载重装 NuGet 即可。
- 解决: visual Studio -> 工具 -> 扩展与更新,直接卸载重装 NuGet 即可。
下面是注册表解决,不能确定这个可行:
reg add HKLM\SOFTWARE\Microsoft\.NETFramework\v4.0.30319 /v SystemDefaultTlsVersions /t REG_DWORD /d 1 /f /reg:64 reg add HKLM\SOFTWARE\Microsoft\.NETFramework\v4.0.30319 /v SystemDefaultTlsVersions /t REG_DWORD /d 1 /f /reg:64
3. 项目引用(白盒引用,有源代码)
添加本地的类库:
调用测试:
namespace HelloWorld
{
class Program
{
static void Main(string[] args)
{
int c = MyLibrary.Arithmetic.add(5,10);
System.Console.WriteLine(c);
}
}
}
3.依赖关系
- 类(或对象)之间的耦合关系
- 优秀的程序追求“高内聚,低耦合
- UML(通用建模语言)类图
三、类,对象,类成员
1.类(class)是现实世界事物的模型
- 类是对现实世界事物进行抽象所得到的结果
- 事物包括“物质”( 实体)与“运动"( 逻辑)
- 建模是一个去伪存真、由表及里的过程
2.类与对象的关系
2.1 概念
对象也叫实例,是类经过“实例化”后得到的内存中的实体
- Formally “instance"is synonymous with“object”–对象和实例是一回事
- “飞机"与”一架飞机"有何区别?天上有(一架)飞机一-必需是实例飞,概念是不能飞的
- 有些类是不能实例化的,比如“数学”( Math class),我们不能说”一个数学”
依照类,我们可以创建对象,这就是“实例化”
现实世界中常称“对象”,程序世界中常称“实例"
二者并无太大区别,常常混用,初学者不必迷惑
使用new操作符创建类的实例
引用变量与实例的关系
- 孩子与气球
- 气球不一定有孩子牵着
- 多个孩子可以使用各自的绳子牵着同一个气球,也可以都通过一根绳子牵着气球
2.2 代码
new 实例化类,设置实例属性,以及多个变量用一个实例
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace ClassAndInstance
{
class Program
{
static void Main(string[] args)
{
//(new Form()).Text = "my form";
//(new Form()).ShowDialog();
//Form myForm = new Form();
//myForm.Text = "my form";
//myForm.ShowDialog();
Form myForm1 = new Form();
Form myForm2 = myForm1;
myForm1.Text = "my form11";
myForm2.Text = "my form22";
myForm2.ShowDialog();
}
}
}
3. 类的三大成员
3.1 概念
- 属性(Property)
- 存储数据,组合起来表示类或对象当前的状态
- 方法(Method )
- 由C语言中的函数(function)进化而来,表示类或对象“能做什么”
- 工作中90%的时间是在与方法打交道,因为它是“真正做事”、“构成逻辑”的成员
- 事件(Event )
- 类或对象通知其它类或对象的机制,为C#所特有(Java通过其它办法实现这个机制)
- 善用事件机制非常重要
- 使用MSDN文档
- 某些特殊类或对象在成员方面侧重点不同
- 模型类或对象重在属性,如Entity Framework
- 工具类或对象重在方法,如Math ,Console
- 通知类或对象重在事件,如各种Timer
3.2 代码
1、打印数据表数据,属性类的实例
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PropertySample
{
class Program
{
static void Main(string[] args)
{
test2024Entities proxy = new test2024Entities();
foreach(tbPlmBcMaterData p in proxy.tbPlmBcMaterDatas){
Console.WriteLine(p.MaterialCode);
}
Console.WriteLine(proxy.tbPlmBcMaterDatas.Count());
}
}
}
添加数据模型:
调试打印数据列表,总数
2、事件类代码例子
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
namespace EventSample
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DispatcherTimer timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromSeconds(1);
timer.Tick += timer_Tick;
timer.Start();
}
void timer_Tick(object sender, EventArgs e)
{
this.timeTextbox.Text = DateTime.Now.ToString();
}
}
}
时间秒在跳动
4.类的静态成员与实例成员
静态(Static)成员在语义上表示它是“类的成员”
实例(非静态)成员在语义表示它是“对象的成员”
绑定( Binding)指的是编译器如果把一个成员与类或对象关联起来
- 不可小觑的"“操作符–成员访问
四、语言基本元素概览
1、构成C#语言的基本元素
关键字(Keyword )
- C# 编程语言中,关键字是被编译器预定义并保留的标识符,具有特殊意义,不能用作变量名或其他标识符
- C# 编程语言中,关键字是被编译器预定义并保留的标识符,具有特殊意义,不能用作变量名或其他标识符
操作符(Operator)
- C# 提供大量运算符,这些运算符是指定在表达式中执行哪些操作的符号。
标识符(ldentifier )
- 什么是合法的标识符
- 怎样阅读语言定义文档
- 大小写规范
- 命名规范
标点符号
文本(字面值)
- 整数
- 多种后缀
- 实数
- 多种后缀
- 字符
- 字符串
- 布尔
- 空(null )
注释与空白
- 单行
- 多行(块注释)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace identifiterSample
{
class Program
{
static void Main(string[] args)
{
int a = 100;
long aa = 100;
double b = 3.1;
char c = 'a';
string cc = "asdasas";
bool dd = true;
Console.WriteLine(dd.GetType().Name);
Console.WriteLine(dd);
}
}
}
2、初识类型、变量和方法
- 初识类型(Type)
- 亦称数据类型(Data Type)
- 变量是存放数据的地方,简称“数据"
- 变量的声明
- 变量的使用
- 方法(日称函数)是处理数据的逻辑,又称“算法"
- 方法的声明
- 方法的调用
- 程序=数据+算法
- 有了变量和方法就可以写有意义的程序了
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace identifiterSample
{
class Program
{
static void Main(string[] args)
{
Calculate cal = new Calculate();
int calRes = cal.Add(10, 5);
Console.WriteLine("计算结果是:" + calRes);
Console.WriteLine(cal.day());
cal.printRes(11, 12);
}
}
class Calculate
{
public int Add(int a, int b)
{
return a + b;
}
public string day()
{
string aa = DateTime.Now.Year.ToString();
return aa;
}
public void printRes(int a, int b)
{
Console.WriteLine(a+b);
}
}
}
3、算法简介
- 循环初体验
- 递归初体验
- 计算1到100的和
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace identifiterSample
{
class Program
{
static void Main(string[] args)
{
Calculate cal = new Calculate();
Console.WriteLine(cal.countXto1(100));
Console.WriteLine(cal.countXto1ByTT(100));
}
}
class Calculate
{
public int countXto1(int x)
{
int sum = 0;
for (int i = 0; i <= x; i++)
{
sum = sum + i;
}
return sum;
}
public int countXto1ByTT(int x)
{
if(x ==1){
return 1;
}
else
{
return x + countXto1ByTT(x - 1);
}
}
}
}
五、类型,变量与对象
1.什么是类型
- 又名数据类型( Data Type )
- 是数据在内存中存储时的“型号”
- 小内存容纳大尺寸数据会丢失精确度、发生错误
- 大内存容纳小尺寸数据会导致浪费编程语言的数据类型与数据的数据类型不完全相同
2.类型在C#语言中的作用
- 一个C#类型中所包含的信息有
- 存储此类型变量所需的内存空间大小
- 此类型的值可表示的最大、最小值范围
- 此类型所包含的成员(如方法、属性、事件等)
- 此类型由何基类派生而来
- 程序运行的时候,此类型的变量在分配在内存的什么位置
- Stack简介
- Stack overflow
- Heap简介
- 使用Performance Monitor查看进程的堆内存使用量
- 关于内存泄漏
- 此类型所允许的操作(运算)
3. C# 语言的类型系统
- C#的五大数据类型
- 类(Classes):如Window, Form, Console, String
- 结构体(Stmuctures):如Int32,Int64,Single, Double
- 枚举(Enumerations):如HorizontalAlignment, Visibility
- 接口(Interfaces)
- 委托(Delegates
- C#类型的派生谱系
4.变量、对象与内存
什么是变量
- 表面上来看(从C#代码的上下文行文上来看),变量的用途是存储数据
- 实际上,变量表示了存储位置,并且每个变量都有一个类型,以决定什么样的值能够存入变量
- 变量一共有7种
- 静态变量,实例变量(成员变量,字段),数组元素,值参数,引用参数,输出形参,局部变量
- 狭义的变量指局部变量,因为其它种类的变量都有自己的约定名称
- 简单地讲,局部变量就是方法体(函数体)里声明的变量
- 变量的声明
- 有效的修饰符组合。 类型 变量名 初始化器。.
值类型的变量
- 以byte/sbtye/short/ushort为例
- 值类型没有实例,所谓的“实例"与变量合而为一
引用类型的变量与实例
- 引用类型变量与实例的关系:引用类型变量里存储的数据是对象的内存地址
变量的默认值
常量(值不可改变的变量)
装箱与拆箱(Boxing & Unboxing )
六 、方法的定义,调用,调试
1、方法的由来
- 方法(method)的前身是C/C++语言的函数(function)
- 方法是面向对象范畴的概念,在非面向对象语言中仍然称为函数
- 使用C/C++语言做对比
- 永远都是类(或结构体)的成员
- C#语言中函数不可能独立于类(或结构体)之外
- 只有作为类(结构体)的成员时才被称为方法
- C++中是可以的,称为“全局函数”
- 是类(或结构体)最基本的成员之
- 最基本的成员只有两个–字段与方法(成员变量与成员方法),本质还是数据+算法
- 方法表示类(或结构体)“能做什么事情”
- 为什么需要方法和函数
- 目的1:隐藏复杂的逻辑
- 目的2:复用(reuse,重用)
示例: 计算圆面积、圆柱体积、圆锥体积
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CSharpMethodExample
{
class Program
{
static void Main(string[] args)
{
Calculator cal = new Calculator();
double cc = cal.GetConeVolume(10,15);
Console.WriteLine(cc);
}
}
class Calculator
{
//计算圆面积
public double GetCirceArea(double r)
{
return Math.PI * r * r;
}
//计算圆柱体积
public double GetCylinderVolume(double r, double h)
{
return GetCirceArea(r) * h;
}
//计算圆锥体积
public double GetConeVolume(double r, double h)
{
return GetCylinderVolume(r, h) / 3;
}
}
}
2、方法的声明与调用
声明方法的语法详解
- “方法”是包含一系列语句的代码块。 程序通过“调用”方法并指定所需的任何方法参数来执行语句。
- 在 C# 中,每个执行指令都是在方法的上下文中执行的。
- Main 方法是每个 C# 应用程序的入口点,在启动程序时由公共语言运行时 (CLR) 调用。
- Parameter全称为"formal parameter形式上的参数,简称“形参”
- Parameter是一种变量
方法签名
- 通过指定方法的访问级别(例如 public 或 private)、可选修饰符(例如 abstract 或 sealed)、返回值、名称和任何方法参数,可以在 类或 结构中声明方法。 这些部分统称为方法的“签名”。
方法的命名规范
- 大小写规范
- 需要以动词或者动词短语作为名字
重温静态(static)方法和实例方法
调用方法
- 在对象上调用方法类似于访问字段。 在对象名称之后,依次添加句点、方法名称和括号。 参数在括号内列出,并用逗号隔开。
- Argument中文C#文档的官方译法为“实际参数”,简称“实参”可理解为调用方法时的真实条件
- 调用方法时的argument列表要与定义方法时的parameter列表相匹配C#是强类型语言,arqument是值、parameter是变量,值与变量一定要匹配,不然编译器会报错
3. 构造器
- 构造器(constructor)是类的成员之一
- 任何时候,只要创建 类或 结构,就会调用它的构造函数。
- 类或结构可能有多个接受不同参数的构造函数。
- 构造函数使得程序员可设置默认值、限制实例化以及编写灵活且便于阅读的代码。
- 如果您没有为对象提供构造函数,则默认情况下 C# 将创建一个构造函数,该构造函数实例化对象,并将成员变量设置为 默认值表(C# 参考)中列出的默认值。
- 静态类和结构也可以有构造函数。
默认构造函数实例:
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CSharpMethodExample
{
class Program
{
static void Main(string[] args)
{
//没有为对象提供构造函数,则默认情况下 C# 将创建一个构造函数,该构造函数实例化对象,并将成员变量设置为 默认值表(C# 参考)中列出的默认值
Student stu = new Student();
Console.WriteLine(stu.ID);
}
}
class Student
{
public int ID;
public string Name;
}
}
类或结构可能有多个接受不同参数的构造函数实例
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CSharpMethodExample
{
class Program
{
static void Main(string[] args)
{
Student stu = new Student(11,"测试");
Console.WriteLine(stu.Name);
Student stuTwo = new Student();
Console.WriteLine(stuTwo.Name);
}
}
class Student
{
public Student(int ID,string Name)
{
this.ID = ID;
this.Name = Name;
}
public Student()
{
this.ID = 1;
this.Name = "测试111";
}
public int ID;
public string Name;
}
}
构造器的内存原理
4. 方法的重载(Overload)
4.1调用重载方法的示例
Console.WriteLine(100);
Console.WriteLine(100L);
Console.WriteLine("Hello");
Console.WriteLine(300D);
Console.WriteLine 有 19个重载
4.2 声明带有重载的方法
方法签名(method signature)由方法的名称、类型形参的个数和它的每一个形参(按从左到右的顺序)的类型和种类(值、引用或输出)组成。方法签名不包含返回类型。
实例构造函数签名由它的每一个形参(按从左到右的顺序)的类型和种类(值、引用或输出)组成。
重载决策(到底调用哪一个重载):用于在给定了参数列表和一组候选函数成员的情况下,选择一个最佳函数成员来实施调用。
方法签名不同的重载实例
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace OverloadDemo
{
class Program
{
static void Main(string[] args)
{
Calculator cal = new Calculator();
Console.WriteLine(cal.Add(1, 2));
Console.WriteLine(cal.Add(1.1, 2.5));
Console.WriteLine(cal.Add(11, 33, 55));
}
}
class Calculator
{
public int Add(int a, int b)
{
return a + b;
}
public int Add(int a, int b, int c)
{
return a + b + c;
}
public double Add(double a, double b)
{
return a + b;
}
}
}
5、 如何对方法进行debug
- 设置断点
- 观察方法调用时的 call stack
- Step-in(F11) Step-over(F10) Steep-out (shift+F11)
- 观察局部变量的值与变化