C#基本语法

数组

注意下面的两种方式的赋值取值遍历的方式均不一样。

方式1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
int[][] newArray = { new int[] { 1, 3, 4, 5, 6 }, new int[] { 2, 4, 6, 8, 2 } };

// 遍历
foreach (int[] item in newArray)
{

}

// 遍历
for (int i = 0; i < newArray.Length; i++)
{
int[] item = newArray[i];
for (int j = 0; j < item.Length; j++)
{
}
}

// 取值
int num = newArray[0][0];

初始化

1
2
3
4
Dictionary<string, object> dic = new Dictionary<string, object> {
{ "device", device },
{ "batchnum", batchnum },
};

方式2

二维数组的定义

1
2
3
4
5
6
7
8
9
10
11
int[,] arr = new int[2, 5] { { 1, 2, 3, 5, 6 }, { 1, 2, 3, 4, 5 } };
for (int i = 0; i < arr.GetLength(0); i++) {
for (int j = 0; j < arr.GetLength(1); j++) {
Console.Write(arr[i, j]+"\t");
}
//换行
Console.WriteLine();
}

// 取值
int num = arr[0,0];

JSON的转换

1
2
3
int[,] arr = new int[2, 5] { { 1, 2, 3, 5, 6 }, { 1, 2, 3, 4, 5 } };
string ss = ZJsonHelper.ToJson(arr);
int[,] arr2 = ZJsonHelper.JsonToObj<int[,]>(ss);

其中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static string ToJson(object t)
{
return JsonConvert.SerializeObject(
t,
Formatting.None,
new JsonSerializerSettings { NullValueHandling = NullValueHandling.Include }
);
}

public static T JsonToObj<T>(string strJson) where T : class
{
if (strJson != null && strJson != "") {
return JsonConvert.DeserializeObject<T>(strJson);
}
return null;
}

三维数组

1
int[,,] arr = new int[,,] { { { 1, 3 } }, { { 1, 2 } } };

Dictionary

Dictionary的描述

1、从一组键(Key)到一组值(Value)的映射,每一个添加项都是由一个值及其相关连的键组成

2、任何键都必须是唯一的

3、键不能为空引用null(VB中的Nothing),若值为引用类型,则可以为空值

4、Key和Value可以是任何类型(string,int,custom class 等)

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 去除重复的用户
Dictionary<int, OnlineUser> userMap = new Dictionary<int, OnlineUser>();

foreach (OnlineUser user in userListTemp)
{
int userid = user.userid;
if (userMap.ContainsKey(userid))
{
userMap[userid] = user;
}
else
{
userMap.Add(userid, user);
}
}

List<OnlineUser> userListNew = new List<OnlineUser>();
var users = userMap.Values;
foreach (OnlineUser user in users)
{
userListNew.Add(user);
}

List

包含

Any方法和All方法是比较常用

  • Any语义:任意一个元素满足条件则返回true,否则返回fase;

  • All语义:所有元素满足条件则返回true,否则返回false

判断ListA是否完整包含ListB

1
2
3
4
bool IsContainsAll(List<Class> ListA, List<Class> ListB)
{
return ListB.All(b => ListA.Any(a => a.name.equal(b.name)));
}

排序

Sort

调用sort方法,如果需要降序,进行反转:

1
2
3
List<int> list = new List<int>();
list.Sort();// 升序排序
list.Reverse();// 反转顺序

Sort+方法

使用lambda表达式,在前面加个负号就是降序了

1
2
3
List<int> list= new List<int>(){5,1,22,11,4};
list.Sort((x, y) => x.CompareTo(y));//升序
list.Sort((x, y) => -x.CompareTo(y));//降序

对于对象

1
2
3
4
5
6
list.Sort(
delegate(People p1,People p2)
{
return p1.Id.CompareTo(p2.Id);//升序
}
);

OrderBy

1
2
list = list.OrderBy(o => o.Id).ToList();//升序
list = list.OrderByDescending(o => o.Id).ToList();//降序

实现IComparable接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
class People: IComparable<People>
{
private int _id;
private string _name;

public People(int id,string name)
{
this._id = id;
this.Name = name;
}

public int Id
{
get
{
return _id;
}

set
{
_id = value;
}
}

public string Name
{
get
{
return _name;
}

set
{
_name = value;
}
}

//重写的CompareTo方法,根据Id排序
public int CompareTo(People other)
{
if (null == other)
{
return 1;//空值比较大,返回1
}
//return this.Id.CompareTo(other.Id);//升序
return other.Id.CompareTo(this.Id);//降序
}

//重写ToString
public override string ToString()
{
return "ID:"+_id+" Name:"+_name;
}
}

排序

1
list.Sort();

多权重排序

排序的方法我就知道这么多了(其实有更多),接下来还有一个问题,如果希望当ID相同时比较Name,上面的代码就需要改改了。

其中,接口IComparable这样写:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//重写的CompareTo方法,根据Id排序
public int CompareTo(People other)
{
if (null == other)
{
return 1;//空值比较大,返回1
}

//等于返回0
int re = this.Id.CompareTo(other.Id);
if (0 == re)
{
//id相同再比较Name
return this.Name.CompareTo(other.Name);
}
return re;
}

IComparer和delegate还有lambda里可以这样:

1
2
3
4
5
6
7
8
9
public int Compare(People x, People y)
{
int re = x.Id.CompareTo(y.Id);
if (0 == re)
{
return x.Name.CompareTo(y.Name);
}
return re;
}

OrderBy方法有点不同:

1
2
list = list.OrderBy(o => o.Id).ThenBy(o=>o.Name).ToList();
list = list.OrderByDescending(o => o.Id).ThenByDescending(o=>o.Name).ToList();//降序

public new和new public

在变量上 new要写在public前面,方法上 new写在public 后面 。

public new

当基类和派生类都有Method2()时,派生类的对象会调用派生类的Method2()方法,而屏蔽基类的方法,不过编译器会warning;

当在派生类方法定义时,在修饰符public加上new,显式地屏蔽基类方法,此时编译器将不会报warning。

1
2
3
4
public new void Method2()
{
Console.WriteLine("Derived - Method2");
}

new public

嵌套类隐藏了基类中同名的类。使用 new 修饰符来消除警告消息。

1
2
3
4
5
6
new public class NestedC
{
public int x = 100;
public int y;
public int z;
}

抽象和虚拟

C#中抽象(abstract)和虚拟(virtual)的主要区别有:

  1. 抽象成员必须在抽象类中,而虚拟成员可以在非抽象类中。

    抽象类不能被实例化,只能被继承。

    虚拟成员允许在子类中被重写,实现多态。

  2. 抽象成员(抽象方法和抽象属性)必须在子类中被重写并实现,而虚拟成员在子类中可以不重写。

  3. 抽象成员不能有具体实现,只是一个签名,而虚拟成员在基类中必须有自己的实现。

  4. 抽象成员不需要使用任何关键字修饰符,而虚拟成员必须明确使用virtual关键字进行修饰。

  5. 子类实现抽象成员时必须使用override关键字,而重写虚拟成员可以使用override,也可以不使用。

  6. 抽象类不能被密封,而包含虚拟成员的类可以使用sealed关键字把该类密封,阻止被继承。

  7. 抽象成员用于表示子类必须实现的成员,而虚拟成员用于提供可以被重写的默认实现。

所以抽象要求子类必定重写,虚拟允许子类可选重写,二者在继承多态中的作用不同。

虚拟

在Java中父类的方法都可以被重写,而C#中必须设置为虚拟方法才能被重写

虚拟方法不要求类为抽象类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class A
{
//虚拟方法;关键字virtual
public virtual void Dog()//虚拟方法
{
Console.WriteLine("父类中的虚拟方法:我叫小狗");
}

public void Eat()//普通方法
{
Console.WriteLine("吃东西");
}
}

class B:A
{
public override void dog()//重写的虚拟方法
{
base.Dog();//重写以后如果想调用父类中的方法则输入base.[父类中的方法名称]
Console.WriteLine("子类:我叫哈士奇");
}
}

抽象

抽象方法要求类必须为抽象类

抽象类不能实例化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
abstract class  A
{
//抽象方法;关键字abstract
public abstract void Junk();//抽象方法
public abstract void He();//抽象方法

}
class B:A
{
public override void Junk()
{
Console.WriteLine("子类中重写的抽象方法我喜欢喝可乐");
}

public override void He()
{
Console.WriteLine("子类中重写的抽象方法:我喜欢喝雪碧");
}
}

抽象类和接口

抽象类和接口在C#中的主要区别有:

  1. 抽象类可以包含抽象方法和非抽象方法,而接口中所有的成员都必须是抽象的。
  2. 抽象类可以包含字段、属性、事件等成员,接口只能包含方法、属性、事件、索引器。
  3. 抽象类可以包含构造函数,而接口不能包含。
  4. 一个类只能继承一个抽象类,而一个类可以实现多个接口。
  5. 抽象类中的成员可以是不同的访问权限(public、protected等),接口的成员默认都是public的。
  6. 接口不能直接实例化,必须有类实现接口后才能实例化,抽象类可以实例化其非抽象子类。
  7. 抽象类表示对类层次结构的抽象,是一种模板设计,接口表示对行为的抽象,是一种行为的规范。
  8. 抽象类侧重设计整体框架,接口侧重设计细节归纳。

总结:

抽象类是对类的抽象,接口是对行为的抽象。

抽象类可以实现部分功能,接口全是抽象成员。

抽象类覆盖面宽,接口覆盖面窄。

一个类可以继承一个抽象类并实现多个接口。