【访问级别】【修饰】【返回类型】 类名 : 【被继承类】【被继承接口】
{
字段;
属性;
默认构造器;// 无参构造器
有参构造器;
私有方法;
public 公共方法;
【接口实现方法】
【委托方法】
}
【访问级别】不写,默认是私有
【修饰】静态,不安全代码等修饰
【返回类型】返回值类型或对象类型
【类名】当前类的名字
【被继承类】oop对象类型
【被继承接口】接口类型
字段;类内部的全局变量
属性;当前类与其他类或外部做输入输出用的。
默认构造器;// 无参构造器
有参构造器;//
私有方法;//不公开的方法
public 公共方法;//公开的方法
.........其他的一些方法
}
以下是一个C# class的完整格式Demo:
using System; // 引用命名空间
namespace MyNamespace // 自定义命名空间
{
// 定义一个类
public class MyClass
{
// 定义私有【字段】
private int myField;
// 定义公共【属性】
public int MyProperty
{
get { return myField; }
set { myField = value; }
}
// 定义【构造函数】
public MyClass(int myField) //用于new对象时使用。
{
this.myField = myField;
}
// 定义公共【方法】 //也叫函数方法
public void MyMethod()
{
Console.WriteLine("MyMethod is called.");
}
}
}
在上面的代码中,我们定义了一个名为MyClass的类,它包含一个私有字段myField、
一个公共属性MyProperty、一个构造函数和一个公共方法MyMethod。
注意,在类的定义中,我们使用了namespace关键字来定义命名空间,
这是一种组织代码的方式,可以避免命名冲突。
当一个类的方法有非常多,一个文件放不下或想按功能分几个组写,可以使用关键字【partial】修饰
把功能函数分开写到几个文件中。【现在工厂里也使用分布式io模块】
partial class account //分部类第一部分
{
public int addition(int a, int b) //创建一个整型方法
{
return a + b; //方法中的加法运算
}
}
partial class account //分部类第二部分
{
public int multiplication(int a, int b) //创建一个整型方法
{
return a * b; //方法中的乘法运算
}
}
partial class account //分部类第三部分
{
public int subtraction(int a, int b) //创建一个整型方法
{
return a - b; //方法中的减法运算
}
}
class 类是namespace 命名空间 下最小的成员单位;
class就和房子的平方米一样,是个公认的最小参考单位,虽然不是最小单位(有平方厘米等)
class的作用就和活字印刷术一样,利用派生出来的实际对象(印刷出来的纸)来解决生活中的问题。
举个例子:先做套试卷的模板(试卷模板就是class)然后印刷50张发给学生填写。(试卷纸就是class派生的实例对象)
class是对象类型,面向对象。解决生活中的问题。先有汽车图纸,然后再造出汽车。
比如生活中的种猪,派生后的子类(小猪仔)才是我们需要的。
byte num;是内存开辟8个bit。
学生对象 张三 = new 学生对象(); 开辟的内存大小由 学生类型 决定。
using 汽车设计;
public void 某个方法(void)
{
汽车图纸 苏D_LV977 = new 汽车图纸();//你主要看这行
new 汽车图纸();这句就是造出了一辆车;苏D_LV977我们称它为实体对象。我们经常把一个对象的值给另一个对象(把对象当参数一样传递),或者调用对象的方法。(就好比苏D_LV977这辆车,我可以按喇叭 苏D_LV977.喇叭(); )我们也可以把其他车的激光大灯拆下来给这辆车。(赋值操作)
注意:类是引用类型,苏D_LV977 = 苏D_1234; 这样赋值,会导致修改977这辆车,1234这辆车也会被改变。只能一个属性一个属性的赋值。或者用 new 方法。
结构体struct是值类型传递,是可以直接赋值。
//对象深度拷贝
List<tb课类> list = new List<tb课类>(list课类); // 复制一个 list课类 对象
汽车图纸就是一个class类,是负责生产对象的图纸。图纸的变化直接影响new出来的汽车实例对象。我们必须先来设计这张图纸:我们小学有数学和语文,为什么数学不能代替语文!(汽车也一样,它有字段和行为,我们没法用0123这样的数字数量来表示汽车喇叭这种行为,汽车转弯,加速等等。所以我们用字段来《表示》有几个轮子,几个大灯;用自定义方法来《描述》加速,减速,转弯等行为)
class由{字段,属性,构造方法,自定义方法}组成;
字段:int num=77;像这样的定义。(默认是private不与外界交互的。new出来的实例对象,字段是不能访问的,但如果修饰成公有字段public(public int num=77;)虽然new出的对象能直接修改num,但不建议这样操作。因为在控件中将不能被显示,默认是private,需要通过属性或方法来间接修改它)仿真调试时,字段最好设置默认值,不要写成 private int num;因为程序调试不会运行到这个字段,它默认值是0;(你不仿真调试就无所谓) 想查看的话就要写成private int num=0;必须给个默认值,程序才会运行到这条上。
#region 字段
public static int cat_电量=0;//static 会导致所有new出来的汽车都是上次修改的值
int cat_备胎=0;//这种是正确的,默认是private
public int cat_温度=25;//虽然new出来的对象能访问这个值,但控件不能访问。
#endregion
有static的字段,实例对象是取不出的。比如new出一个李四,李四.cat_电量 是取不出的。要用类型去取,如 int data = 汽车图纸.cat_电量; 只有这样才能取出来。(看class的名字)
static 和 new是有区别的,每次new出的实例对象都是独立的,不是同一个。而 static 始终是一个对象。
属性:作用是与外界交互数据,是public的,是在字段的基础上加了限制。属性并不存储数据,它的作用是间接的去修改字段,比如年龄不能为负数;与字段配合使用,这样就能保证输入的值不会超出范围。属性的作用是与外界交互的(new出来的对象,就可以给属性赋值)。(属性并不能保存数据,只有字段才能保存数据。虽然 public string name{get;set;}这样写,也能保存数据,但实际编译器内部默认生成了一个字段name,称为语法糖。最终效果是 private string name; public string name{get{return this.name;}set{this.name=Value;}你会发现他们重名,编译器是就近原则。全局变量和局部变量看此处变量离哪个最近。想用全局变量的,就要加this. 来限定(指定是class的,而不是局部的变量),想用继承的就要加base.来限定。 只有get就说明是只读属性,只有set是只写属性。有get和set才说明是可读写的。
#region get参数
//===get==================================================
public bool isopen { get { return serialPort1.IsOpen; } }
public string[] get可用串口 { get { return SerialPort.GetPortNames(); } }
public string[] get波特率
{
get
{
return new string[]{
"110","300","600","1200","2400","4800","9600","14400","28800","19200",
"38400","56000","57600","115200","230400","460800","921600"};
}
}
public string[] get数据位 { get { return new string[] { "5", "6", "7", "8" }; } }
public string[] get校验位 { get { return Enum.GetNames(typeof(Parity)); } } //
public string[] get停止位 { get { return Enum.GetNames(typeof(StopBits)); } } //
#endregion
string MY_工资=0;
public string my_工资{ get{return MY_工资;}set{MY_工资=Value;}}//value就是参数值
namespace help
{
//定义一个对象类型
public class dg_电工
{
//字段:用于实体对象的使用,比如电工祁成,new出的实例对象都是独立的,做参数传递时,是引用类型。
private string M名字;//字段
private int S身高;//没有默认值的字段
private int T体重 = 60;//有默认值的字段
private int N年龄;//和属性配合使用
private string[] N女友;//使用索引器
private int G工资;
public int C成绩 = 0; //公有字段: new出的对象能访问,但控件不能访问
//属性:用于和外界交互的。一定要用public ,让 其他来修改实体对象的某个属性。
public int s身高 { get { return S身高; } }//只读
public int 工资 { private get; set; } = 7777;//和字段类似,对于设置的值没有判断性,可以设置为不希望出现的负值。
public int 老婆查工资 { get { return 2500; } }//只读属性。外界不能修改这个值。
public string this[ulong key]//索引器
{
get
{
return N女友[key];//属性不能保存数据,只有字段才存储数据。
}
set
{
N女友[key] = value;
}
}
public int 我的工资
{
get//和外界交互时,给出私有的 内容
{
return G工资;
}
set//外界给入的值
{
if (value > 8000)//大于期望的值
{
//继续工作中
}
else
{
//提桶跑路。。。
}
}
}
//构造方法
public dg_电工(string name)
{//有参构造,new时
M名字 = name;//new时初始化实例
}
//自定义方法
public bool w维修设备(string data)//表示这些类的实体对象,都能实现的功能
{
if (data == "能修") return false;//表示能修好
else return true; //修不好
}
public bool w维修费用(int num,string data = "维修设备")//参数带默认值的方法
{
if (num > 200) return false;//表示完成
else return true; //表示失败
}
// 静态方法:(调用的时候是通过类名.方法名称调用的)
public static bool w维修记录(int num,string data = "地址不详" )//参数带默认值的静态方法
{
return true; //表示失败
}
}
// d电工 祁成=new d电工(); //在其他类内定义:表示新建了一个实体对象
// d电工 祁成2=new d电工("参数"); //系统默认定义无参构造,有参构造要自己定义,可以将对象当参数传入
// d电工 祁成3=new d电工("参数") //实例化的同时,初始化一些其他属性
//{
// c成绩=66,
// 工资=12345
//};
}
字段和属性的区别:
这2个都能保存数据,但用途不一样。
比如张三这个人,他的私房钱多少也需要用值类型保存(本就不想被外界知道),他的好朋友需要通过属性的逻辑判断,满足条件后,才能获取张三字段的值(张三的私房钱)。
类似于对象的局部变量和对象的全局变量。
构造方法:编译器默认给出一个无参的构造方法。但如果你写了一个有参构造方法,那无参构造方法就会消失,还想用无参构造就必须显示的写个无参构造方法。
Help_ModBus rs485 = new Help_ModBus(0x01);
你还想使用无参构造就必须写出无参构造方法,一个类必须至少有一个构造方法。每次new一个对象时,就会运行这个方法。就像女人的肚子。在这个方法内可以写初始化的值,也可以接收外部给的参数来赋值给内部的字段。无参new出的对象就好比:无性繁殖。
构造方法写法和类名一样,但缺class
public class Help_ModBus()//无参构造方法
{
public Help_ModBus()//无参构造方法
{
}
public Help_ModBus(string c_参数1 ,string c_参数2)//有参构造方法
{
}
public Help_ModBus(string c_参数1 ,string c_参数2 , c_参数3)//有参构造方法
:this(c_参数1 , c_参数2) //等效于调用 Help_ModBus(c_参数1 , c_参数2);
{
}
}
自定义方法:是描述这个类能有什么功能。比如这个是一个串口类,它能发送数据。那你就需要写出这个方法。使用的时候用new出的对象.dian来调出
串口.TX_发送数据();
public void TX_发送数据(byte[] data)//发送
{
try
{
serialPort1.Write(data, 0, data.Length);
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());//显示错误
throw;
}
}
总结:class是描述对象类型的。比如人类,class 人类建好后,就可以new出具体的人。
人类 张三=new 人类();
张三.电话="10086";
需要熟练掌握这种格式,就像写小说,小说无非这几种套路。要么挂逼开局,帅不过3秒,被打成菜逼,然后一级一级升,最后重回巅峰。要么菜逼开局,碰到老师,再一级一级升,最后到达巅峰。
对象初始化器:
在new出对象的同时给初始值。属性之间用逗号隔开,最后一个属性不写逗号。
人类 李四 = new 人类()
{
名字=李四,
电话=10086,
年龄=18
};
后面就可以取出它
int num= 李四.电话;
struct 结构体:
下面要讲 struct 结构体。 它与class最大的区别就是,class是引用类型。把对象当参数传给形参,你修改形参,上层的实参也会跟着改变。
struct 是值类型传递,每个对象都是独立的。
public class xs_学生
{
public int data;
}
struct dg_维修电工
{
int age;
void cs()
{
age++;
Console.ReadLine();
}
}
效果和int a,b=9;
a=b;
你修改a的值,b不会被改变。(这就是值类型)
总结:
static对象:在整个项目内,只有一个对象。任何地方调用,修改都是同一个对象。
struct对象:可以派生,每个对象都是独立的。赋值操作是值类型传递。
class对象:用new派生,每个对象也是独立,但赋值操作后,2个对象就变
成一个对象,任何修改都会影响另一个对象的值,是引用类型传递。
class案例:
using System;
namespace LineApplication
{
class Line
{
private double length; // 线条的长度
public Line(double len) // 参数化构造函数
{
Console.WriteLine("对象已创建,length = {0}", len);
length = len;
}
public void setLength( double len )
{
length = len;
}
public double getLength()
{
return length;
}
static void Main(string[] args)
{
Line line = new Line(10.0);
Console.WriteLine("线条的长度: {0}", line.getLength());
// 设置线条长度
line.setLength(6.0);
Console.WriteLine("线条的长度: {0}", line.getLength());
Console.ReadKey();
}
}
}