一 c#数组
class Program
{
static void Main(string[] args)
{
//实例化对象
Student s = new Student(1, "zixuan") { Score = 100 };
Console.WriteLine("{0} {1} {2}\n", s.Id,s.Name, s.Score);
int[] array1 = new int[5];
int[] array2 = new int[] { 1, 1, 2, 3, 5 };
int[] array3 = { 1, 1, 2, 3, 5 , 2, 1};
array2.CopyTo(array1, 0);
//数组的拷贝
Array.Sort(array3);
//数组排序
}
}
查看帮助文档知,数组的CopyTo()方法,第一个参数是一个数组,第二个是索引值(从哪个位置开始拷贝)
打印数组
static void Main(string[] args)
{
//实例化对象
Student s = new Student(1, "zixuan") { Score = 100 };
Console.WriteLine("{0} {1} {2}\n", s.Id,s.Name, s.Score);
int[] array1 = new int[5];
int[] array2 = new int[] { 1, 1, 2, 3, 5 };
int[] array3 = { 1, 1, 2, 3, 5 , 2, 1};
array2.CopyTo(array1, 0);
//数组的拷贝
Array.Sort(array3);
//数组排序
for (int i = 0; i < array1.Length; i++)
Console.Write("{0}", array1[i]+"\n");
//打印输出
Console.WriteLine();
//foreach循环
foreach (var n in array3)
Console.Write("{0}", n+"\n");
Console.WriteLine();
}
}
二 字符串
C# 支持两种形式的字符串:常规字符串和原义字符串。
在原义字符串中,分隔符之间的字符逐字解释,不处理简单转义序列以及十六进制和Unicode 转义序列。原义字符串可以跨多行。
class Program
{
static void Main(string[] args)
{
string s1 = "d:\\temp"; //常规字符串
string s2 = @"d:\temp"; //原义字符串
Console.WriteLine("{0}", s1);
Console.WriteLine("{0}", s2);
Console.WriteLine("{0}", s1.Equals(s2));
Console.WriteLine("{0}", s1 == s2);
Console.WriteLine("{0}", s1[4]); // 可使用索引器访问串的的每一个字符
Console.WriteLine("{0}", s1[0]);
//字符串索引,从0开始索引
foreach (var n in s2)
Console.Write("{0}", n);
}
}
三。索引器
索引器用于以更便捷的方式访问对象中包含的成员数组或集合。索引器与属性类似,不同的是索引器的访问是带参的。
例1:用整数作为下标
class Student {
private double[] _scores = new double[2];
public int Id { get; set; }
public string Name { get; set; }
public Student(int id, string name) {
Id = id;
Name = name;
}
public double this[int index] {
get { return _scores[index]; }
set { _scores[index] = value; }
}
}
class Program {
static void Main(string[] args) {
Student s = new Student(1, "zixuan");
s[0] = 68;
s[1] = 89;
Console.WriteLine("{0} {1} {2} {3}\n", s.Id, s.Name, s[0],s[1]);
}
}
[点击并拖拽以移动]
例2: 用字符串做下标
class Student {
public int Id { get; set; }
public string Name { get; set; }
public Dictionary<string, double> Scores { get; set; }
//字典索引
public Student(int id, string name) {
Scores = new Dictionary<string, double>();
Id = id;
Name = name;
}
public double this[string index] {
get { return Scores[index]; }
set { Scores[index] = value; }
}
}
class Program {
static void Main(string[] args) {
Student s = new Student(1, "zixuan");
s.Scores.Add("English", 89); //方式1
s["Math"] = 99; //方式2
Console.WriteLine("{0} {1} {2} {3}", s.Id, s.Name, s["English"], s["Math"]);
}
}
}
4.集合
4.1 System.Collections 命名空间
传统集合
4.2 System.Collections.Generic 命名空间
泛型集合
五:委托和Lambda表达式
在C/C++中,通过函数指针可将函数的入口地址传递给另一个函数。
C#中使用委托(delegate)来提供相同的功能,它将方法作为对象封装起来,允许在运行时绑定一个或多个方法。委托和类一样属于引用类型。
Lambda表达式与委托直接相关。当参数是委托类型时,就可以使用Lambda表达式实现委托的方法。
5.1 定义委托类型和委托的实例化
使用delegate关键字来声明委托数据类型
public delegate bool ComparisonHandler(int first, int second);
class BanJi {
int[] scores;
public BanJi() {
scores = new int[] { 67, 33, 66, 99, 87, 11 };
}
public void SortScore( ComparisonHandler ComparisonMethod) {
int temp;
int flag = 1; //当flag为0则停止排序
for (int i = 1; i < scores.Length; i++) { //i表示趟数,最多n-1趟
flag = 0; //开始时元素未交换
for (int j = scores.Length - 1; j >= i; j--)
if (ComparisonMethod(scores[j] , scores[j - 1])) { //发生逆序
temp = scores[j];
scores[j] = scores[j - 1];
scores[j - 1] = temp;
flag = 1;
} //交换,并标记发生了交换
if (flag == 0)
return;
}
}
public void PrintScore() {
foreach (int s in scores)
Console.Write("{0} ", s);
Console.WriteLine();
}
}
class Program {
static bool Compare1(int first, int second) {
return first > second;
}
static bool Compare2(int first, int second) {
return first < second;
}
static void Main(string[] args) {
BanJi b = new BanJi();
ComparisonHandler compare = Compare1;
b.SortScore(compare);
b.PrintScore();
//传入一个比较器
b.SortScore(Compare2);
b.PrintScore();
}
}
}
5.2 匿名方法
所谓匿名方法就是没有实际方法声明的委托实例,其定义直接内嵌在代码中。
static void Main(string[] args) {
BanJi b = new BanJi();
//匿名方法
ComparisonHandler comparisonMethod = delegate(int first, int second) {
return first > second;
};
b.SortScore(comparisonMethod);
b.PrintScore();
b.SortScore(delegate(int first, int second) {
return first < second;
});
b.PrintScore();
}
5.3 Lambda表达式
Lambda表达式是比匿名方法更加简洁的一种匿名函数语法。分为两种类型:语句Lambda和表达式Lambda。
class Program {
static void Main(string[] args) {
BanJi b = new BanJi();
b.SortScore((int first, int second) => {
return first > second;
}); //语句Lambda
b.SortScore((first, scond) => {
return first > scond;
}); //只要编译器能推断出类型,就允许省略参数类型
b.SortScore((first, scond) => first > scond); //表达式Lambda
b.PrintScore();
}
}
5.4 多播委托
可以将多个方法绑定到同一个委托,即多播委托。当调用这个委托时,将依次调用其所绑定的方法。
通过重载运算符“+=”向委托添加方法,用“-=”取消绑定。
class Student {
public delegate void ScoreChangeHandler(int score);
//声明委托
private int _score;
public ScoreChangeHandler OnScoreChange;
public string Name { get; set; }
public int Score {
get { return _score; }
set {
if (_score != value) {
_score = value;
OnScoreChange(_score);
}
}
}
}
class Mother {
public void OnScoreChanged(int score) {
if (score < 60)
Console.WriteLine("失败乃成功之母!");
else if (score > 90)
Console.WriteLine("再接再厉!");
}
}
class Father {
public void OnScoreChanged(int score) {
if (score < 60)
Console.WriteLine("你在想屁吃!");
else if (score > 90)
Console.WriteLine("还可以!");
}
}
class Program {
static void Main(string[] args) {
Student son = new Student();
Father dad = new Father();
Mother mom = new Mother();
son.OnScoreChange += dad.OnScoreChanged;
// 添加方法到委托
son.OnScoreChange += mom.OnScoreChanged;
son.Score = 60;
}
}
5.5 事件
事件是类的主要成员之一,是一个对象用来通知某一动作的发生而发出的消息。在面向对象程序设计中,消息传递都通过事件触发来实现的。
包含事件成员的类型可以提供以下功能:
①其他对象可以在事件上注册处理方法;
②删除事件处理方法的注册;
③拥有事件的对象可以维护注册到事件上的对象,并在某些动作发生时通知这些对象。
.NET Framework中的事件机制是建立在委托模型基础上的。用关键字event来声明事件,事件实质上一个封装得更好的委托对象。
class ScoreEventArgs : EventArgs {
//声明事件参数类
public readonly int score;
public ScoreEventArgs(int score) {
this.score = score;
}
}
class Student {
public string Name { get; set; }
private int _score;
public delegate void ScoreChangeEventHandler(Object sender, ScoreEventArgs e); //声明委托
public event ScoreChangeEventHandler ScoreChanged; //声明事件
protected virtual void OnScoreChanged(ScoreEventArgs e) {
if (ScoreChanged != null) {
ScoreChanged(this, e);
//定义响应事件的操作
}
}
public int Score {
get { return _score; }
set {
if (_score != value) {
_score = value;
ScoreEventArgs e = new ScoreEventArgs(Score);
OnScoreChanged(e);
}
}
}
}
class Mother {
public void OnScoreChanged(Object sender,ScoreEventArgs e) {
if (e.score < 60)
Console.WriteLine("失败乃成功之母!");
else if (e.score > 90)
Console.WriteLine("再接再厉!");
}
}
class Father {
public void OnScoreChanged(Object sender, ScoreEventArgs e) {
if (e.score < 60)
Console.WriteLine("你在想屁吃!");
else if (e.score > 90)
Console.WriteLine("奖奖奖!");
}
}
class Program {
static void Main(string[] args) {
Student son = new Student();
Father dad = new Father();
Mother mom = new Mother();
son.ScoreChanged += dad.OnScoreChanged;
son.ScoreChanged += mom.OnScoreChanged;
son.Score = 50;
}
}
5.6 可空类型
对于一个类型,如果既可以给它分配一个值,也可以给它分配 null(表示没有任何值),我们就说这个类型是可空的。 因此,可以为 null 的类型可表示一个值,或表示不存在任何值。
例如,类似 String 的引用类型就是可以为 null 的类型,而类似 Int32 的值类型不是可以为 null 的类型。
Nullable是.NET 2.0中新提供的一种用于标明一个值类型是否可以为空的技术。
Nullable<T> 结构支持将值类型扩展为可以为null,但不支持在引用类型上使用,因为引用类型本身就是可空的。
T?:表示可空类型,就是一种特殊的值类型,它的值可以为null。
语法 T? 是 System.Nullable<T> 的简写,此处的 T 为值类型,这两种形式可以互换。
T??:用于判断前一个操作数是否为null,如为null则返回后一个操作数,否则返回前一个操作数。
public static class Program
{
public static void Main(string[] args)
{
int? a = 3;
//设置a可空
Console.WriteLine(a);
Console.WriteLine(a.HasValue);
a = null;
Console.WriteLine(a.HasValue);
if (a == null)
Console.WriteLine("null");
int b = a ?? 0;
Console.WriteLine(b);
int c = a.GetValueOrDefault();
Console.WriteLine(c);
}
}