深入.NET框架和C#编程

深入.NET框架和C#编程

深入.NET框架

Microsoft.NET框架概述

1.1Microsoft.NET介绍

2000年,微软公司向全球提供其具有革命性的软件和服务平台,这对消费者、企业和软件开发商来说,预示着个人将获得更大的能力和充满更多商业机会的到来。

Microsoft.NET平台利用以互联网为基础的计算和通信激增的特点,通过先进的软件技术和众多的智能设备,从而提供更简单、更为个性化、更有效的互联网服务。.NET的战略目标是在任何时候(when)、任何地方(where)、使用任何工具(what)都能通过.NET获得网络上的任何信息,享受网络带给人们的便捷与快乐。

1.2.NET框架的优势
  • 提供了一个面向对象的编程环境,完全支持面向对象编程。.NET框架提高了软件的可复用性、可扩展性、可维护性和灵活性。
  • 对Web应用的强大支持,如今是互联网时代,大量的网络应用程序发挥着重要作用。比如红极一时的社交网站Myspace使用.NET开发的,.NET平台的强大功能与稳定性使得它可以面对庞大的用户群体的访问。
  • 对Web Service(Web服务)的支持。Web Service是.NET非常重要的内容,它可以实现不同应用程序之间的相互通信。
  • 实现SOA,支持云计算。SOA是一个重要的架构范例,它支持中间层解决方案的模块化实现。
  • 支持构建.NET程序的炫彩外衣。随着科技的发展,人们越来越多地使用计算机软件进行信息化办公,也越来越重视良好地用户体验和视觉效果。.NET提供WPF技术,帮助开发人员创建良好地3D效果。WPF提供了丰富地用户界面(User Interface,UI)框架,集成了矢量图形和丰富地流动文字支持。

.NET框架体系结构

.NET框架运行在操作系统之上,是.NET最基础地框架。它提供了创建、部署和运行.NET应用地环境,主要包含公共语言运行时(CLR)框架类库(.NET Framework类库,FCL),并且支持多种开发语言。

CLR

CLR全称公共运行语言时,它是所有.NET应用程序运行时的环境,是所有.NET应用程序都要使用的编程基础。

CLR的组成:

**CLS(公共语言规范):**每种编译语言可能都会在类型、语法或语言规范上有着区别,CLS限制了有这些不同点引发的互操作性问题,它是一种最低的语言标准,制定了一种以.NET平台为目标的语言所必须支持的最小特征,以及该语言与其他.NET语言之间实现互操作所需要的完备特征,凡是遵守这个标准的语言在.NET框架下都可以实现相互调用。

**CTS(通用类型系统):**用于解决不同语言数据类型不同的问题,如C#中的整型是int,而VB.NET中的整型是integer。通过CTS将它们编译成通用类型Int32。

**MSIL(中间语言):**也叫.NET编译技术。为了实现跨语言开发和跨平台的战略目标,.NET所编写的应用都不编译成本地代码,而是编译成微软中间代码(Microsoft Intermediate Language,MSIL)。

FCL

FCL(框架类库)提供对系统功能的调用,是建立.NET应用程序、组件和控件的基础。

.NET的核心类库:

​ System : 此命名空间包含所有其他的命名空间。

​ System.Collect.Generic : 支持泛型操作。

​ System.IO :支持对文件的操作。

​ System.NET : 支持对网络协议的编程。

​ System.Data : 提供对表示ADO.NET结构类的访问。

​ System.Windows.Forms : 用于开发Windows应用程序。

​ System.Drawing : 支持GDI+基本图形操作。

面向对象

1.类和对象

类和对象有着本质的区别,类定义了一组概念的模型,而对象是真正的实体。

它们之间的关系如下:

由对象归纳类,是归纳对象共性的过程。

在类的基础上,将状态和行为实体化为对象的过程称为实例化。

对于类的属性,通过get和set访问器进行访问和设置:

只写属性:只包含set访问器。

只读属性:只包含get访问器。

读写属性:同时包含get和set访问器。

示例:

private string _name;
public string Name
{
	get{return _name;}
	set{_name = value;}
}
2.封装

封装(Encapsulation)又称为信息隐藏,是指利用抽象数据类型将数据的操作结合在一起,使其构成一个不可分割的独立实体,尽可能隐藏内部的细节只保留一些对外接口,使之与外部发生联系。

封装带来的好处:

保证数据的安全性

提供清晰的对外接口

类内部实现可以任意修改,不影响其他类

3.类图

作用:简洁、直观地表示众多类的结构及类与类之间的联系,将类的属性和行为以图的行为展示出来,使读者不用阅读大量的代码即可明白类的功能及类之间的关系。

深入C#数据类型

值类型和引用类型

值类型

值类型源于System.ValueType家族,每个值类型的对象都有一个独立的内存区域用于保存自己的值,它所在的区域称为栈(Stack)。值类型包括基本数据类型(如int,double,floa)和枚举类型等。

引用类型

引用类型源于System.Object家族,在C#中引用类型主要包括数组、类和接口等。

class Program
{
    static void Main(string[] args)
    {
        int[] infoZhang = new int[] { 170, 60 };
        int[] infoLi = infoZhang;
        Console.WriteLine("去年--张浩的身高是:" + infoZhang[0] + "体重是:" + infoZhang[1] + ",李明的身高是:" + infoLi[0] + "体重是:" + infoLi[1]);
        infoLi[0] = 180;
        infoLi[1] = 70;
        Console.WriteLine("今年--张浩的身高是:" + infoZhang[0] + "体重是:" + infoZhang[1] + ",李明的身高是:" + infoLi[0] + "体重是:" + infoLi[1]);
        Console.ReadLine();
    }
}

对引用类型,赋值就是把原对象的引用传递给另一个引用。对数组而言,当一个数组引用赋值给另一个数组引用后,这两个引用指向同一个数组,也就是指向同一块存储空间。

细分值类型和引用类型

值类型引用类型
基本数据类型整型:int基类:System.Object
长整型:long字符串:string
浮点型:float自定义类:class
双精度型:double接口接口:interface
字符型:char数组数组:int[],string[]
布尔型:bool
枚举类型枚举:enum
结构类别结构:struct

结构

结构是值类型,声明结构变量就存储一个结构的新副本,即系统要开辟一块新的存储空间,因此结构用得越多所消耗的存储空间也越多。

访问修饰符 struct  结构名
    {
        //结构体
    }

结构的定义有以下特点:

1.结构可以有方法也可以有字段
2.定义时,结构中的字段不能被赋初始值

结构的使用

结构的构成和类相似,在使用时注意以下几点:

1.可以不用new,直接定义结构的对象

2.声明结构的对象后,必须给结构的成员赋初始值

装箱和拆箱

拆箱:拆箱是引用类型转化为基本类型

装箱:装箱是基本类型转化为引用类型

static void Main(string[] args)
    {
          int i = 123;
          object o = i;//装箱
          i = 456;//改变i的内容
          Console.WriteLine("值类型的值为{0}",i);
          Console.WriteLine("引用类型的值为{0}", o);
    }


		static void Main(string[] args)
    {
          int i = 123;
          object o = i;//拆箱
          int j = (int)o;
          Console.WriteLine("j的值现在为:" + j);
          Console.ReadLine();
    }

不同类型的参数传递

使用值传递,在方法中对参数值的更改在调用后不保留。

使用ref方式传递,可以保留对参数值的更改。

值方式参数传递

在值方式传递参数时,参数可以是引用类型,也可以是值类型。

使用引用类型作为参数

class Program
{
    public void Vote(Class1 se)
    {
        //人气值增加1
        se.Popularity++;
    }
    static void Main(string[] args)
    {
        Class1 zhang = new Class1();
        zhang.Age = 25;
        zhang.Name = "张靓";
        zhang.Gender = "1201";
        zhang.Popularity = 10;
        //投票前 
        MessageBox.Show(zhang.SayHi());
        Program voter = new Program();
        voter.Vote(zhang);//引用类型做参数
        //投票后
        MessageBox.Show(zhang.SayHi());
    }
}

注意:当类作为参数传递时,参数被修改,类成员的值也会被修改。

使用值类型作为参数

class Program
{	
	public void Vote(StructSE se)
    {
        //人气值增加1
        se.Popularity++;
    }
    static void Main(string[] args)
    {
        StructSE zhang = new StructSE();
        zhang.Age = 25;
        zhang.Name = "张靓";
        zhang.Gender = "1201";
        zhang.Popularity = 10;
        //投票前 
        MessageBox.Show(zhang.SayHi());
        Program voter = new Program();
        voter.Vote(zhang);//值类型做参数
        //投票后
        MessageBox.Show(zhang.SayHi());
    }
}

注意:以值类型作为参数进行值方式传递参数时,不能改变值类型参数的值。

引用方式参数传递

在形参和实参前都加ref,那么它们都会保存方法中的修改。

public void ShowInfo(ref int a){
	a = 5;
}
static void Main(string[] args)
{
	int a = 0;
	 MessageBox.Show(ShowInfo(ref a));
}
//输出结果为5

小结:

使用值方式(不用ref修饰)传递值类型参数时,参数在方法中的修改不会保留。

使用值方式(不用ref修饰)传递引用类型参数时,参数在方法中的修改会保留。

使用引用方式(不用ref修饰)传递值类型或引用类型参数时,参数在方法中的修改都会保留。

使用集合组织相关数据

集合概述

ArrayList

ArrayList非常类似于数组,也有人称它为数组列表,ArrayList可以动态维护。它的索引会根据程序的扩展而重新进行分配和调整。ArrayList提供了一系列方法对其中的元素进行访问、增加和删除操作。

语法:

ArrayList 集合名= new ArrayList();

ArrayList类属于System.Coolections命名空间,使用它使一定要导入命名空间。ArrayList是动态可维护的,因此定义时既可以指定容量,又可以不指定容量。

using System.Coolections;

ArrayList stu = new ArrayList();//创建容量为0的ArrayList对象

ArrayList stu1 = new ArrayList(5);//创建容量为5的ArrayList对象

ArrayList常用属性和方法:

属性名说明
Count获取ArrayList中实际包含的元素数
返回值方法名说明
intAdd(Object value)将对象添加到ArrayList的结尾处
voidRemove(int index)移除ArrayList指定索引处的元素
voidRemoveAt(Object vaule)从ArrayList中移除特定元素
voidClear()从ArrayList中移除所有元素

遍历ArrayList:

//for:通过下标循环输出
  for(int i = 0; i < ArrayList.Count; i++)
	{
		Console.WriteLine(ArrayList[i]);
	}
//foreach:通过Object包含ArrayList循环输出
  foreach(Object obj in ArrayList)
	{
		Console.WriteLine(obj);
	}

Hashtable

Hashtable的数据结构统称为哈希表,也有人称它为“字典”,Hashtable的数据时通过键(Key)和值(Value)来组织的。Hashtable属于System.Coolections命名空间,它的每一个元素都是键/值对。

语法:

Hashtable 集合名= new Hashtable();

Hashtable常用属性和方法:

属性名说明
Count获取包含在Hashtable中的键/值对的数目
Keys获取包含在Hashtable中键的集合
Values获取包含在Hashtable中值的集合
返回值类型方法名说明
voidAdd(Object key,Object values)将带有指定键和值的元素添加到Hashtable中
voidRemove(Object key)从Hashtable移除带有特定键的元素
voidClear()从Hashtable中移除所有元素

遍历Hashtable:

由于Hashtable不能用索引访问,所以遍历Hashtable只能使用foreach()方法。

Hashtable ht = new Hashtable();
//遍历Value
foreach (Object cvb in ht.Values)
{
       Console.WriteLine(cvb);
}
//遍历key
foreach (int item in ht.Keys)
{
       Console.WriteLine(item);
}
//遍历Key和Value
foreach(DictionaryEntry en in ht)
{
     Console.WriteLine(en.Key + en.Value);
}

泛型和泛型集合

泛型是C#2.0中的一个新特性。泛型引入了一个概念:类型参数,通过使用类型参数,大量减少了运行时强制转换或装箱操作的风险,通过泛型可以最大限度地重用代码,保护类型的安全和提高性能,它们最常见应用就是创建集合类,泛型集合可以约束它所储存的对象类型。

泛型集合List<T>

语法:

List<T> 对象名 = new List<T>();

T可以对集合中的元素类型进行约束,T表明集合中管理的元素类型。

List<T>常用的方法和属性:

属性名说明
Count获取List中实际包含的元素数
返回值方法名说明
intAdd(T value)将对象添加到List的结尾处
voidRemove(int index)移除List指定索引处的元素
voidRemoveAt(T vaule)从List中移除特定元素
voidClear()从List中移除所有元素

遍历List<T>:

 List<T> lsit = new List<T>();

  for(int i = 0; i < list.Count; i++)
	{
		Console.WriteLine(list[i]);
	}

  foreach(T item in list)
	{
		Console.WriteLine(item);
	}

泛型List与非泛型ArrayList的区别:

异同点List<T>ArrayList
不同点对所保存元素进行类型约束。添加/读取值类型元素无需拆箱和装箱。可以增加任何类型。添加/读取值类型元素需拆箱和装箱。
相同点通过索引访问集合的元素。添加、删除元素方法相同。

泛型集合Dictionary<K,V>

泛型集合Dictionary<K,V>它具有泛型的全部特征,编译时检查类型约束,获取元素无需进行类型转换,存储方式和Hashtable相似,也是通过Key/Value(键/值)对元素保存的。

语法:

Dictionary<K,V> 对象名 = new Dictionary<K,V>();

Dictionary<K,V>常用的方法和属性:

同Hashtable的方法和属性一致。

泛型Dictionary<K,V>与非泛型Hashtable的区别:

异同点Dictionary<K,V>Hashtable
不同点对所保存元素进行类型约束。添加/读取值类型元素无需拆箱和装箱。可以增加任何类型。添加/读取值类型元素需拆箱和装箱。
相同点通过Key获取Values。添加、删除和遍历元素方法相同

泛型类

语法:

public class 类名<T>
{
	//...
}

T是类型参数,代表具体的数据类型,可以是类参数,也可以是基本数据类型。

泛型的优点:

1、性能高:泛型无需进行类型的转换操作。

2、类型安全:泛型集合对它所存储的对象进行了类型的约束。

3、实现代码的重用:泛型相当于模板,它支持任何数据类型。

深入类的方法

构造函数

类的构造函数是类中的一种特殊方法,它具有以下特点:

1.方法名与类名相同

2.没有返回值类型

3.主要完成对象的初始化工作

构造函数的作用:实例化对象

带参构造函数

它比无参构造函数的灵活性更好,它通过参数来动态控制对象的特征,避免了给众多属性赋值带来的麻烦。

语法

访问修饰符 类名(参数列表)
{
    //方法体
}

无参构造函数

在默认的情况下,系统将会给类分配一个无参构造函数,并且没有方法体。也可以自定义一个无参构造函数,在无参构造函数的方法体中对类的属性进行赋值。

语法:

访问修饰符 类名()
{
    //方法体
}

隐式构造函数

当不给类编写构造函数时,系统将自动给类分配一个无参构造函数,称为隐式构造函数。

方法重载

构造函数的重载

多个构造函数提供多种实例化一个类的方式称为构造函数重载。

在面向对象的语言中,允许我们在同一个类中定义多个方法名相同、参数列表(参数个数、参数类型)不同的方法,称为方法重载。调用时会根据实际传入的参数的形式,选择与其匹配的方法执行。构造函数的重载时方法重载的一种特殊方式。

方法重载的特点:

1.方法名相同。

2.方法参数类型不同或者参数个数不同。

3.在同一个类中。

方法重载示例:

public class Student{
public Car(string name,string id,int age)
{
            
}
public Car(string name, string id, int age,int number)
{
            
}
}

对象交互

在面向对象的世界里,一切皆为对象。对象与对象相互独立,互不干涉,但在一定外力作用下,对象开始共同努力。

每个类都有自己的特性和功能,我们把它们封装为属性和方法。对象之间通过属性和方法进行交互。可以认为方法的参数及方法的返回值都是对象间相互传递的信息。

继承和多态

继承概述

什么是继承

当两个类描述相同属性的代码时,如果要扩展这个程序,加入一些其他的类,编码时因为类的不同会编写大量关于相同属性的重复代码,造成冗余,随着系统规模的扩大,冗余将会越来越多,如何避免这种冗余,把冗余代码集中起来重复利用呢?

继承的概念

在C#中,一个类可以继承另一个类。继承是使用已存在的类的定义作为基础建立新类的技术,新类的定义可以增加新的数据或新的功能,也可以用已存在的类的功能。继承是面对对象编程中一个非常重要的特性,再有继承关系的两个类中,子类不仅具有自己独有的成员,还具有父类的成员。

public class Employee{	//父类
    public string Name{get;set;}
    public string NUmber{get;set;}
}

public class SE:Employee{  //子类
    this.Name = "小明";
    this.Number = "S1";
    //在子类调用父类的成员
}

Base关键字和protected修饰符

在继承关系中如何去访问父类的成员呢?this表示当前实例,通过它可以访问类本身的成员。

C#中还有一个关键字base,它表示父类,可以用于访问父类的成员。

public class School{
    public string Name{get;set;}
    private string Number{get;set;}
}

public class Student:School{
    base.Name = "小明同学";
    base.Number = "SS7"; //编译报错
}

在以上代码中,在子类中可以用base调用父类的属性。实际上,还可以用base关键字调用父类的方法或构造函数。

父类的成员如果用private修饰,它将作为私有成员,其他任何类都无法访问。

C#中提供了另一种访问修饰符protected,被这个访问修饰符修饰的成员允许被其他子类访问,而不允许其他非子类访问。

public class School{
    public string Name{get;set;}
    protected string Number{get;set;}
    //只需将访问修饰符改为protected就不会报错了
}

public class Student:School{
    base.Name = "小明同学";
    base.Number = "SS7"; 
}
修饰符类内部子类其他类
public可以可以可以
protected可以可以不可以
private可以不可以不可以

子类构造函数

1.隐式调用父类构造函数

创建子类对象时会首先调用父类的构造函数,然后才会调用子类本身的构造函数,如果没有指明要调用父类的哪一个构造函数,系统默认调用父类的无参构造函数。

public class School{
    public School(){
        Console.WriteLine("姓名:"+Name);
    }
    public string Name{get;set;}
    public string Number{get;set;}
}

public class Student:School{
    base.Name = "小明同学";
    base.Number = "SS7"; 
    public Student(){
        Console.WriteLine("学号:"+base.Number);
    }
}
//这段代码会先输出姓名,再是学号
2.显示调用父类构造函数

只要在子类的构造函数后添加“base(参数列表)”,就可以指定该子类的构造函数调用父类的哪一个构造函数了。

public class School{
    public string Name{get;set;}
    public string Number{get;set;}
	
    public School(string name,string number){
        Console.WriteLine("姓名:" + Name + "学号:" + Number);
    }
}

public class Student:School{
   public Student(string name,string number):base(name,number){ //调用父类含两个参数的构造函数
       this.Name = name;
       this.Number = number;
   }
}

继承的使用

继承的特性
1.继承的传递性

举例:小型卡车is a卡车,卡车is a汽车,所以小型卡车is a汽车,这就是继承的传递性。

2.继承的单根性

在C#中明确规定一个子类不能同时继承多个父类。

is a的应用

is关键字用来判断对象是否属于给定的类型,如果属于返回true,否则返回false。

if(empl is SE) //表示判断empl对象是否是SE类型
继承的价值

1.继承模拟了现实世界的关系,OOP中强调一切皆对象,这符合我们面向对象编程的思考方向。

2.继承实现了代码的重用性。

3.继承使得程序结构清晰,子类和父类的层次结构清晰,最终的目的是使子类只关注子类的相关行为和状态,无须关注父类的相关行为和状态。

多态

解决继承带来的问题

当一个父类中含有多个子类,每个子类中的方法相同,参数个数,类型不同时,那么在程序中就要对众多的对象编写非常多的is关键字的if判断语句了,使程序变得庞大,扩展困难。

什么是多态

从面向对象编程的角度思考,三种不同的对象对于同一个方法调用表现出了不同的行为。

多态按字面的意思就是“多种形态”,指同一操作作用于不同的对象时,可以有不同的解释,产生不同的执行结果。

里氏替换原则(LSP):

是软件设计应该遵守的重要原则之一,有了它,才使继承复用成为可能,只有当子类可以替换父类时,软件的功能不受影响,父类才能真正被复用。

实现多态

重载:

同一个多态的实现方式。

**特点:**在同一个类中,相同的方法名,参数的个数、类型不同。

重写:

**前提:**两个类存在继承关系

不同类多态的实现方式。

**特点:**在不同类中,相同的方法名,参数的个数、类型不同。

1.虚方法

语法:

访问修饰符 virtual 返回类型 方法名(){
    //方法体;
}
//在父类中用virtual

访问修饰符 override 返回类型 方法名(){
    //方法体;
}
//在子类中用override
2.抽象方法

抽象方法是一个没有实现的方法

语法:

访问修饰符 abstract 返回类型 方法名();

**注意:**含有抽象方法的类必定是抽象类!

虚方法和抽象方法的区别
虚方法抽象方法
用virtual修饰用abstract修饰
要有方法体,即使是一个分号不允许有方法体
可以被子类override必须被子类override
除了密封类外都可以定义只能在抽象类中定义
抽象类

父类不被实例化,只提供方法的定义,让子类实现方法。

语法:

访问修饰符 abstract class 类名(){
    
}

特点:

1.不能用sealed和static修饰。sealed表示禁止继承,C#中静态方法只能通过类名去点,static类中只能有static方法。

2.不能实例化(new)对象。

3.抽象类可以有抽象方法,可以有非抽象方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值