C#入门经典(第6版)阅读笔记(第一篇)(1-10)
目录
<h5>第一章 C#简介</h5>
<h5>第二章 编写C#程序</h5>
<h5>第三章 变量和表达式(注释方式)</h5>
<h5>第五章变量的更多内容</h5>
<h5>第六章 函数 *</h5>
<h5>第八章 面向对象编程简介</h5>
<h5>第九章 定义类</h5>
<h5>第十章 定义类成员</h5>
<h5>第一章 C#简介</h5>
1.1 .NET Framework的含义
1.1.1 .NET Framework是Microsoft为开发应用程序而创建的一个具有革命意义的平台。
1.1.2中间语言: 在编译使用.net framework 库的代码时,不是立即创建专用操作系统的本机代码,而是把代码编译为通用中间语言(Common Intermediate Language,CIL)代码,这些代码并非专门用于任何一种操作系统,也非专门用于C#。
1.1.3编译器:Just-In-Time(JIT)编译器的任务,他把CIL编译为专用于OS和目标机器结构的本级代码。
1.1.4程序集:在编译应用程序时,所创建的CIL代码存储在一个程序集中。程序集包括可执行的应用程序文件(.exe)和其他应用程序使用的库(.dll)。
1.1.5托管代码:在将代码编译成为CIL,再用JIT编译器将它编译为本级代码后,CLR的任务尚未完成,还需要管理正在执行的用.net framework编写的代码。托管代码最重要的一个功能是垃圾回收(garbage collection)。
1.1.6总结图:
<h5>第二章 编写C#程序</h5>
2.1.1 第一个小程序---控制台程序HelloWorld
2.1.2 第二个小程序---桌面应用---WPF application
桌面应用---点击按钮弹窗using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace Test02_WPF
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("你竟然敢点我!");
}
}
}
<h5>第三章 变量和表达式(由于之前学过c语言和java,部分相通的章节不会记录过多)</h5>
3.1.1注释
3.3.2注意:组成string打的字符串数量没有上限,以为他可以使用可变大小的内存。
3.3.3注意:根据约定,名称空间通常采用PascalCase命名方式。
<h5>第五章变量的更多内容</h5>
5.1.1使用Convert命令进行显示转换。
5.1.2 变量类型:结构---》就是由几个数据组成的数据结构,这些数据可能具有不同的类型----》个人感觉像是c语言中的结构体。
小例子:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 枚举与结构的应用
{
//定义枚举类型
enum orientation : byte
{
north = 1,
soutth = 2,
east = 3,
west = 4
}
//定义结构体类型
struct route
{
public orientation direction;
public double distance;
}
class Program
{
static void Main(string[] args)
{
route myRoute;
int myDirection = -1;
double myDistance;
Console.WriteLine("1)North \n 2)South \n 3) East \n 4)West \n");
do
{
Console.WriteLine("Select a direction:");
myDirection = Convert.ToInt32(Console.ReadLine());
}
while((myDirection < 1) || (myDirection > 4));
Console.WriteLine("Input a distance:");
myDistance = Convert.ToInt32(Console.ReadLine());
myRoute.direction = (orientation)myDirection;
myRoute.distance = myDistance;
Console.WriteLine("myRoute specifiex a direction of {0} and a distance of {1}",myRoute.direction,myRoute.distance);
Console.ReadLine();
}
}
}
5.1.3定义数组时注意
定义数组注意5.2.1锯齿数组---》数组的数组
5.3.1string类型变量可以看成是char变量的只读数组。为了获得一个可写的char数组,可以使用下面代码
string myString = "a string";
char[] myChar = myString.ToCharArray();
<h5>第六章 函数</h5>
6.1.1函数的定义与使用
一般采用PascaCase形式编写函数名。
函数Main()是控制台应用程序的入口点函数。
void这个关键字表明函数没有返回值。
样例:
主函数:
static void Main(string[] args)
{
Console.WriteLine("请输入一个整数");
int x = Convert.ToInt32(Console.ReadLine());
Console.WriteLine(GetVal(x));
Console.ReadLine();
}
被调函数:
static double GetVal(int n)
{
if (n > 5)
{
return 5;
}
else
{
return 0;
}
}
结果显示:
函数的定义与使用6.1.2查看函数的参数值是否会改变
被调用函数:
主函数:
主函数结果:
结果可见,从主函数,将变量通过调用函数加工后,其本身并不会做出改变。若想让其发生本质的改变,需要使用ref。如下所示:
被调用的函数 主函数调用方式 执行结果代码:
static void ChangeParameterMethod1(int value)
{
value = value * 2;
Console.WriteLine("由定义函数输出:" + value);
}
static void ChangeParameterMethod2( ref int value)
{
value = value * 2;
Console.WriteLine("由定义函数输出:" + value);
}
static void Main(string[] args)
{
int myValue1 = 3;
ChangeParameterMethod1(myValue1);
Console.WriteLine("由主函数输出,查看myValue是否改变:" + myValue1);
int myValue2 = 3;
ChangeParameterMethod2(ref myValue2);
Console.WriteLine("由主函数输出,查看myValue是否改变:" + myValue2);
Console.ReadLine();
}
6.1.3输出参数(用法与ref相同)
把未赋值的变量用作ref参数是违法的,但可以把未赋值的变量用作out参数。
另外,在函数使用out参数时,必须把它看成是尚未赋值。
6.2.1结构函数
即把函数放到结构中,可以集中处理常见任务,从而简化过程。
6.3.1重载:函数名相同,参数不同。
6.4.1委托:
委托(delegate)是一种存储函数引用的类型。主要用于事件和事件处理。委托的声明非常类似函数,但不带函数体,且要使用delegate关键字,定义了委托后就可以声明该委托类型的变量。下面我们来看一段代码,使用委托访问两个函数中的一个。个人觉得,委托就像一个已经定义好的选择器,然后根据选择去挑选所需要的函数,然后再通过委托传参。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace 委托用法的练习
{
class Program
{
delegate double ProcessDelegate(double param1,double param2);//委托声明(类似函数)
static double Multiply(double param1, double param2)
{
return param1 * param2;
}
static double Divide(double param1, double param2)
{
return param1 / param2;
}
static void Main(string[] args)
{
ProcessDelegate process;
Console.WriteLine("Enter 2 numbers separated with a comma:");
string input = Console.ReadLine();
int commaPos = input.IndexOf(',');
double param1 = Convert.ToDouble(input.Substring(0,commaPos));
double param2 = Convert.ToDouble(input.Substring(commaPos + 1,input.Length -1-commaPos));
Console.WriteLine("Enter M to Multiply or D to Divide:");
input = Console.ReadLine();
//如果选M则调用函数Multiply否则使用函数Divide
if (input == "M")
{
process = new ProcessDelegate(Multiply);
}
else
{
process = new ProcessDelegate(Divide);
}
Console.WriteLine("Result:{0}",process(param1,param2));
Console.ReadLine();
}
}
}
执行结果:
委托的使用<h5>第八章 面向对象编程简介</h5>
8.1.1类与对象的区别
若拿汽车比喻,类是指汽车的模板,或者用于构建汽车的规划,汽车本身是这这些规划的实例,所以可以看做对象。
8.1.2对象的生命周期
构造阶段:第一次实例化一个对象时,需要初始化该对象。这个初始化过程称为构造阶段,由构造函数完成。
正在使用阶段:正常状态
析构阶段:在删除一个对象时,常常需要执行一些清理工作,例如,释放内存,这由析构函数完成。
8.2.1封装,继承,多态之类的就不多说了,扩展两个名词:继承--》派生;父类---》基类。
<h5>第九章 定义类</h5>
9.1定义
9.1.1抽象(abstract)类:不能实例化,只能继承。密封(sealed)类:不能继承。
9.1.2编译器不允许派生类的可访问性高于基类。也就是说,内部类可以继承于一个公共基类,但公共基类不能继承于一个内部类。
9.1.3如果没有基类,则被定义的类就只继承于基类System.Object(它在C#中的别名是object)。
9.1.4必须使用逗号来分隔基类名和接口名。此处与java不同。java使用的是两个关键字,extends 和implements,C#这两个都采用的方式是“:”。
9.1.5 类的修饰符
类的修饰符
类定义中可以使用的访问修饰符组合
none or internal 类只能在当前工程中访问
public 类可以在任何地方访问
abstract or internal abstract 类只能在当前工程中访问,不能实例化,只能继承
public abstract 类可以在任何地方访问,不能实例化,只能继承
sealed or internal sealed 类只能在当前工程中访问,不能派生,只能实例化
public sealed 类可以在任何地方访问,不能派生,只能实例化
9.2 System.object
9.2.1 在利用多态性时,GetType()是一个有用的方法,允许根据对象的类型来执行不同的操作,而不是像通常那样,对所有对象都执行相同的操作。
9.2.2抽象类和接口的相同与不同点
相同点:
<li>都包含可以由派生类继承的成员</li>
<li>都不能直接实例化</li>
不同点:
<li>派生类只能继承一个基类,相反,类可以使用任意多个接口</li>
<li>抽象类可以拥有抽象成员和非抽象成员</li>
<li>接口成员必须都在使用接口的类上实现-----他们没有代码体</li>
<li>接口成员是公有的,抽象类的成员是私有的</li>
<li>接口不能包含字段、构造函数、析构函数、静态成员或常量</li>
9.3 结构类型
9.3.1 结构和类非常相似,但结构是值类型,而类是引用类型。代码解释:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace 区分类和结构
{
//定义一个类
class MyClass
{
public int val;
}
//定义一个结构,注意命名规则
struct myStruct
{
public int val;
}
class Program
{
static void Main(string[] args)
{
//对定义的类实例化
MyClass objectA = new MyClass();
//此处实际上是复制了这个地址
MyClass objectB = objectA;
objectA.val = 20;
objectB.val = 30;
//对结构进行实例化
myStruct structA = new myStruct();
//此处赋值的是结构体的所有信息
myStruct structB = structA;
structA.val = 20;
structB.val = 30;
//输出上面的四个值
Console.WriteLine("objectA.val = {0}",objectA.val);
Console.WriteLine("objectB.val = {0}", objectB.val);
Console.WriteLine("structA.val = {0}", structA.val);
Console.WriteLine("structB.val = {0}", objectB.val);
Console.ReadKey();
}
}
}
执行结果:
类与结构9.4 浅度复制和深度复制
浅度复制:简单的按照成员复制对象,通过拍摄呢过于System.Object的MemberwiseClone()方法;
深度复制:如果要创建成员的新实例(复制值,而不复制引用),可以实现一个ICloneable接口,以标准方式进行深度复制。如果使用这个接口,就必须实现它包含的Clone()方法。这种方式跟java中的创建多线程,实现Runnable接口创建多线程的方式挺像的。
第十章 定义类成员
10.1 成员定义
10.1.1在类定义中,也提供了该类中所有成员的定义包括字段、方法和属性。所有成员都有自己访问级别,用下面的关键字之一来定义:
- public——成员可以由任何代码访问
- private——成员只能由类中的代码访问(如果没有使用任何关键字,就默认使用这个关键字)
- internal——成员只能由定义它的程序集(项目)内部的代码访问
- protected——成员只能由类或派生类中的代码访问
后两个关键字可以结合起来使用,protected internal,它们只能由项目中派生类的代码访问。
10.1.2公共字段以PascalCasing形式命名,公共方法也采用PascalCasing形式命名,私有字段通常使用camelCasing来命名。
10.1.3 如果使用了static关键字,这个方法就只能通过类来访问,不能通过对象实例来访问。也可以在方法定义中使用下述关键字: - virtual——方法可以重写
- abstract——方法必须在非抽象的派生类中重写(只用于抽象类中)。
- override——方法重写了一个基类方法(如果方法被重写,就必须使用该关键字)。&_&
- exten——方法定义放在其他地方
下面是一个方法重写的实例:
public class MyBaseClass
{
//virtual——方法可以重写
public virtual void DoSomething()
{
//Base implementation
}
}
//Extends a class(MyBaseClass) and overwrite it's method
//override——方法重写了一个基类方法(如果方法被重写,就必须使用该关键字)
public class MyDerivedClass : MyBaseClass
{
//To overwrite the method
public override void DoSomething()
{
//Drived class implementation,overrides base inplementation.
}
}
这个地方,如果第一个类中的方法没有加Virtual,这个方法就不可以被重写:
方法的重写如果使用的override,也可以使用sealed来指定在派生类中不能对这个方法做进一步的修改。
测试代码:
public class MyDerivedClass : MyBaseClass
{
//To overwrite the method
public override sealed void DoSomething()
{
//Drived class implementation,overrides base inplementation.
}
}
public class MyTestClass : MyDerivedClass
{
public override void DoSomething()
{
//this is test to see whether the method is rewritten
}
}
报错显示:
报错显示当然,此处去除sealed,程序时可以正常运行的。
10.1.4 定义属性
get块必须有一个属性类型的返回值,简单属性一般与私有字段相关联,以控制对这个字段的访问,此时get块可以直接返回该字段的值。
代码:
public class MyTestClass
{
//Field used by prtperty
private int myInt;
//Property
public int MyIntProp
{
get
{
return myInt;
}
set
{
myInt = value;
}
}
}
value 等于类型与属性相同的一个值,所以如果属性和字段使用相同的类型,就不必考虑数据类型转换了。
10.1.5 this 与 base
base关键字指定.NET实例化过程使用基类中具有指定参数的构造函数。
this这个关键字指定调用指定的构造函数前,.net实例化过程对当前类使用非默认的构造函数。
如果没有给构造函数指定构造函数初始化器,编译器就会自动添加base()。
this关键字与base一样,this也可以用在类成员内部,且该关键字也引用对象实例。只是this应用的是当前的对象实例(即不能在静态成员中使用this关键字,因为静态成员不是对象实例的一部分)。