对C#的了解是从大二开始做xml大作业时候开始的,当时我们的项目是使用asp.net实现,所以接触到了c#,但接触并不深入,都只是,像java、c++的使用一样,简单使用。到了大三才有比较系统的学习C#,也是因为选了dotnet这门课,但也都是比较基础的部分。
选了微软实训这门实训方向课,学到了一些c#的高级使用方式,发现了C#编程好玩的地方。
首先,提到了泛型。
泛型是 2.0 版 C# 语言和公共语言运行库 (CLR) 中的一个新功能。泛型将类型参数的概念引入 .NET Framework,类型参数使得设计如下类和方法成为可能:这些类和方法将一个或多个类型的指定推迟到客户端代码声明并实例化该类或方法的时候。例如,通过使用泛型类型参数 T,您可以编写其他客户端代码能够使用的单个类,而不致引入运行时强制转换或装箱操作的成本或风险。使用泛型类型可以最大限度地重用代码、保护类型的安全以及提高性能。
泛型最常见的用途是创建集合类。您可以创建自己的泛型接口、泛型类、泛型方法、泛型事件和泛型委托。可以对泛型类进行约束以访问特定数据类型的方法。
在我看来,泛型其实跟c++的模板很像。都是用一个<T>标识类型参数,在实例化时才对类型赋值。这样,就能很好的重用功能相同,但使用类型不同的代码块。而.NET中类库新增的几个泛型集合类就是吸收了以前非泛型集合类的优点,衍生出来的泛型集合类,这样我们就可以根据自己的需求,为自定义的类创建泛型接口或类等。
泛型的特点:
1、如果实例化泛型类型的参数相同,那么JIT编译器会重复使用该类型,因此C#的动态泛型能力避免了C++静态模板可能导致的代码膨胀的问题。
2 C#泛型类型携带有丰富的元数据,因此C#的泛型类型可以应用于强大的反射技术。
3、C#的泛型采用“基类,接口,构造器,值类型/引用类型”的约束方式来实现对类型能数的“显式约束”,提高了类型安全的同时,也丧失了C++模板基于“签名”的隐式约束所具有的高灵活性。
// type parameter T in angle brackets
public class GenericList<T>
{
// The nested class is also generic on T.
private class Node
{
// T used in non-generic constructor.
public Node(T t)
{
next = null;
data = t;
}
private Node next;
public Node Next
{
get { return next; }
set { next = value; }
}
// T as private member data type.
private T data;
// T as return type of property.
public T Data
{
get { return data; }
set { data = value; }
}
}
private Node head;
// constructor
public GenericList()
{
head = null;
}
// T as method parameter type:
public void AddHead(T t)
{
Node n = new Node(t);
n.Next = head;
head = n;
}
public IEnumerator<T> GetEnumerator()
{
Node current = head;
while (current != null)
{
yield return current.Data;
current = current.Next;
}
}
}
另外,在定义泛型类时,可以对客户端代码能够在实例化类时用于类型参数的类型种类施加限制。如果客户端代码尝试使用某个约束所不允许的类型来实例化类,则会产生编译时错误。这些限制称为约束。约束是使用 where 上下文关键字指定的。
有六种约束类型:
T:结构 :类型参数必须是值类型。 可以指定除 Nullable 以外的任何值类型。 有关更多信息,请参见使用可以为 null 的类型(C# 编程指南)。
T:类 :类型参数必须是引用类型;这一点也适用于任何类、接口、委托或数组类型。
T:new() :类型参数必须具有无参数的公共构造函数。 当与其他约束一起使用时,new() 约束必须最后指定。
T:<基类名> :类型参数必须是指定的基类或派生自指定的基类。
T:<接口名称> :类型参数必须是指定的接口或实现指定的接口。 可以指定多个接口约束。 约束接口也可以是泛型的。
T:U :为 T 提供的类型参数必须是为 U 提供的参数或派生自为 U 提供的参数。
public class Employee
{
private string name;
private int id;
public Employee(string s, int i)
{
name = s;
id = i;
}
public string Name
{
get { return name; }
set { name = value; }
}
public int ID
{
get { return id; }
set { id = value; }
}
}
public class GenericList<T> where T : Employee
{
private class Node
{
private Node next;
private T data;
public Node(T t)
{
next = null;
data = t;
}
public Node Next
{
get { return next; }
set { next = value; }
}
public T Data
{
get { return data; }
set { data = value; }
}
}
private Node head;
public GenericList() //constructor
{
head = null;
}
public void AddHead(T t)
{
Node n = new Node(t);
n.Next = head;
head = n;
}
public IEnumerator<T> GetEnumerator()
{
Node current = head;
while (current != null)
{
yield return current.Data;
current = current.Next;
}
}
public T FindFirstOccurrence(string s)
{
Node current = head;
T t = null;
while (current != null)
{
//The constraint enables access to the Name property.
if (current.Data.Name == s)
{
t = current.Data;
break;
}
else
{
current = current.Next;
}
}
return t;
}
}
然后,提到了Lambda 表达式
Lambda 表达式是一种可用于创建委托或表达式目录树类型的匿名函数。 通过使用 lambda 表达式,可以写入可作为参数传递或作为函数调用值返回的本地函数。 Lambda 表达式对于编写 LINQ 查询表达式特别有用。若要创建 Lambda 表达式,需要在 Lambda 运算符 => 左侧指定输入参数,然后在另一侧输入表达式或语句块。
(int x, string s) => s.Length > x//使用空括号指定零个输入参数
() => SomeMethod()//没有参数是使用()
普通绑定
public void button1_Click(object sender, EventArgs e)
{
MessageBox.Show("ok");
}
this.button1.Click += button1_Click;
匿名委托
this.button1.Click += delegate(object sender, EventArgs e)
{
MessageBox.Show("Click");
};
表达式树表示树状数据结构的代码,树状结构中的每个节点都是一个表达式,例如一个方法调用或类似 x < y 的二元运算。
使用API创建表达式树
// Add the following using directive to your code file:
// using System.Linq.Expressions;
// Create an expression tree.
Expression<Func<int, bool>> exprTree = num => num < 5;
// Decompose the expression tree.
ParameterExpression param = (ParameterExpression)exprTree.Parameters[0];
BinaryExpression operation = (BinaryExpression)exprTree.Body;
ParameterExpression left = (ParameterExpression)operation.Left;
ConstantExpression right = (ConstantExpression)operation.Right;
Console.WriteLine("Decomposed expression: {0} => {1} {2} {3}",
param.Name, left.Name, operation.NodeType, right.Value);
// This code produces the following output:
// Decomposed expression: num => num LessThan 5
最后就是LINQ,LINQ即语言集成查询(Language Integrated Query)是一组用于c#和Visual Basic语言的扩展。它允许编写C#或者Visual Basic代码以查询数据库相同的方式操作内存数据。