重新认识C#..
知识积累,重新回味下知识也许会有不少新认识..
1,C# 委托
委托: 是一种引用方法的类型。一旦为委托分配了方法,委托将与该方法具有完全相同的行为。委托方法的使用可以像其他任何方法一样,具有参数和返回值
将方法作为参数进行引用的能力使委托成为定义回调方法的理想选择。例如,可以向排序算法传递对比较两个对象的方法的引用。分离比较代码使得可以采用更通用的方式编写算法。委托概述
委托具有以下特点:
委托类似于 C++ 函数指针,但它是类型安全的。
委托允许将方法作为参数进行传递。
委托可用于定义回调方法。
委托可以链接在一起;例如,可以对一个事件调用多个方法。
方法不需要与委托签名精确匹配。
C# 2.0 版引入了匿名方法的概念,此类方法允许将代码块作为参数传递,以代替单独定义的方法。
C# 1.0声明委托
public delegate void Del<T>(T item);
public void Notify(int i) { }使用委托
Del<int> d1 = new Del<int>(Notify);C#2.0使用委托
Del<int> d2 = Notify;C#3.0以上版本可以使用Lambda表达式来取代C#2.0里面的匿名委托
Action<int> d3 = s => s;
下面分别做下比较
public class DelegateExample{//命名委托
delegate void Del(int i, double j);//匿名委托
delegate void Printer(string s);public static void Run(){//C#2.0之前的命名方法委托
Del dl = MultiplyNumbers;for (int i = 0; i < 5; i++){dl(i,2);}//C#2.0引入了匿名方法--匿名方法的参数的范围是匿名方法块
Printer print = delegate(string p) { Console.WriteLine(p); };//使用匿名委托
print("匿名函数");
//使用命名方法的委托
print = new Printer(DoWork);
print("命名方法委托");
// C# 3.0 及更高版本中,Lambda 表达式取代了匿名方法
//上面的例子可以改为Action有参数但无返回值的,如果是有返回值的用Func<>
Action<string> funcprint = s => Console.WriteLine(s);
funcprint("Lambda表达式");
Console.ReadKey();}static void MultiplyNumbers(int i, double j){Console.WriteLine("i * j = " + i * j);
}static void DoWork(string p){Console.WriteLine(p);}}
2,Lambda
“Lambda 表达式”是一个匿名函数,它可以包含表达式和语句,并且可用于创建委托或表达式树类型。 所有 Lambda 表达式都使用 Lambda 运算符 =>,该运算符读为“goes to”。 该 Lambda 运算符的左边是输入参数(如果有),右边包含表达式或语句块。 Lambda 表达式 x => x * x 读作“x goes to x times x”。可以将此表达式分配给委托类型.
delegate int del(int i); static void Main(string[] args) { del myDelegate = x => x * x; int j = myDelegate(5); //j = 25 }创建表达式树类型:
using System.Linq.Expressions; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { Expression<del> myET = x => x * x; } } }Lambda 的一般规则如下:
Lambda 包含的参数数量必须与委托类型包含的参数数量相同。
Lambda 中的每个输入参数必须都能够隐式转换为其对应的委托参数。
Lambda 的返回值(如果有)必须能够隐式转换为委托的返回类型。
Lambda 表达式本身没有类型,因为常规类型系统没有“Lambda 表达式”这一内部概念。但是,有时会不正式地论及 Lambda 表达式的“类型”。 在这些情况下,类型是指委托类型或 Lambda 表达式所转换为的 Expression 类型。
//此处显示了一个Lambda标准查询运算
int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
//筛选出满足该条件的唯一元素
int oddNumbers = numbers.Single(n => n == 0);
Console.WriteLine(oddNumbers.ToString());//只要满足条件就会返回元素
var fielNumbers = numbers.TakeWhile(n => n < 8);foreach (var item in fielNumbers){Console.WriteLine(item.ToString());}C# 2.0规范中提到的匿名方法规范同样适用于Lambda表达式。Lambda表达式是匿名方法在功能行上的超集,提供了下列附加的功能:l Lambda表达式允许省略参数类型并对其进行推断,而匿名方法要求参数类型必须显式地声明。
l Lambda表达式体可以是表达式或语句块,而匿名方法体只能是语句块。
l 在类型参数推导和方法重载抉择时,Lambda表达式可以被作为参数传递。
l 以一个表达式作为表达式体的Lambda表达式可以被转换为表达式树。
表达式树类型:表达式树表示树状数据结构的代码,树状结构中的每个节点都是一个表达式,例如一个方法调用或类似 x < y 的二元运算。
表达式树是Lambda表达式的一种高效的内存中数据表现形式,并且使得表达式的结构变得透明和明显。
C# Lambda表达式树要点:
1. Lambda表达式的参数类型可以忽略,因为可以根据使用的上下文进行推断。
2. Lambda表达式的主体(body)可以是表达式,也可以是语句块。
3. Lambda表达式传入的实参将参与类型推断,以及方法重载辨析。
4. Lambda表达式和表达式体可以被转换为表达式树。
5. 表达式树允许lambda表达式能够代表数据结构替代表示为执行代码。Expression<Func<int, int>> expression = x => x + 5; Console.WriteLine(expression.Parameters[0]); Console.WriteLine(expression.Body); //执行Expression表达式 Func<int, int> fx = expression.Compile(); Console.WriteLine(fx(5));
3,Linq
LINQ 提供一种跨各种数据源和数据格式使用数据的一致模型,所有 LINQ 查询操作都由以下三个不同的操作组成: 获取数据源。创建查询。执行查询。
public static void Run(){//用 Linq执行简单的数组查询
int[] numbers = new int[7] { 0, 1, 2, 3, 4, 5, 6 };//延迟执行
//var numberQuery = from num in numbers
// where (num % 2) == 0
// select num;
//强制立即执行
List<int> numberQuery = (from num in numberswhere (num % 2) == 0
select num).ToList();//或者
var numberArray = (from num in numbers
where (num % 2) == 0
select num).ToArray();//查询变量本身只是存储查询命令。实际的查询执行会延迟到在 foreach 语句中循环访问查询变量时发生。此概念称为“延迟执行”
foreach (var item in numberQuery){Console.WriteLine(item);}}Linq To List 集合查询
//本篇介绍Linq对集合的各种查询
public static void Run(){List<Customers> customerlist = new List<Customers>();
customerlist.Add(new Customers() { id = 1, Name = "Jack", Custom = "Mis" });customerlist.Add(new Customers() { id = 2, Name = "Lus", Custom = "Google" });customerlist.Add(new Customers() { id = 3, Name = "Qiao", Custom = "Baidu" });customerlist.Add(new Customers() { id = 4, Name = "Qiao", Custom = "Apple" });customerlist.Add(new Customers() { id = 5, Name = "Adb", Custom = "Adobe" });//简单的查询
var customerQuery = from query in customerlist
select query;//带where筛选
var customerWhereQuery = from query in customerlist
where query.id == 1 && query.Name == "Lus"select query;//排序Ordering
var customerOrderingQuery = from query in customerlist
where query.Name == "Lus"orderby query.id ascendingselect query;//分组Group by
var customerGroupbyQuery = from query in customerlist
group query by query.Name;//可以使用into进一步查询
var customerGroupbyIntoQuery = from query in customerlist
group query by query.Name into queryGroupwhere queryGroup.Key == "Qiao"select queryGroup;//联接查询 join 子句始终针对对象集合而非直接针对数据库表运行。
List<Customers> customerJoinlist = new List<Customers>();
customerJoinlist.Add(new Customers() { id = 1, Name = "Jack", Custom = "Mis" });customerJoinlist.Add(new Customers() { id = 2, Name = "Lus", Custom = "Google" });customerJoinlist.Add(new Customers() { id = 3, Name = "Qiao", Custom = "Baidu" });var customerJoinQuery = from query1 in customerlist
join query2 in customerJoinlist
on query1.id equals query2.idselect new { CustomerName = query1.Name, CustomerName2 = query2.Name };
//数据源的类型参数始终为查询中的范围变量的类型。
//比如List<Customers> 类型为Customers 在循环迭代的时候类型必须可以隐式转换为Customer 有一种情况是
//这种情况下Customers类型转换为了String ..在select query.Name已经将查询目标类型定位了String类型
var customerTypeQuery = from query in customerlist
where query.Name == "Lus"select query.Name;//结合Lamdba对List集合筛选(s => s.Name == "Qiao")
List<Customers> listString = customerlist.Where(s => s.Name == "Qiao").ToList();
}}public class Customers{public int id { get; set; }public string Name { get; set; }public string Custom { get; set; }}Linq To SQL
首先连接NORTHWRN数据库 为了做列子简单的把Customers表拖放到dbml文件.也就是LinqToSQL类
public static void Run(){DataClasses1DataContext dataContext = new DataClasses1DataContext();
//对Customers数据源执行简单查询
var custQuery = from custom in dataContext.Customers
where custom.City == "Seattle"select custom;//添加实体
Customers customers = new Customers()
{ContactName = "AdventureWorks Cafe",
Address = "Google",
CustomerID = "ADVAS"
};dataContext.Customers.InsertOnSubmit(customers);//更新实体
var updateCustomer = (from c in dataContext.Customers
where c.CustomerID == "ADVAS"select c).First();updateCustomer.ContactName = "New Name";
//提交更改
dataContext.SubmitChanges();//删除实体
List<Customers> deleteCustomer = (from c in dataContext.Customers
where c.id >= 1000
select c).ToList();//批量删除
dataContext.Customers.DeleteAllOnSubmit(deleteCustomer);}
4,Dynamic
Visual C# 2010 引入了一个新类型 dynamic。 该类型是一种静态类型,但类型为 dynamic 的对象会跳过静态类型检查。 大多数情况下,该对象就像具有类型 object 一样。 在编译时,将假定类型化为 dynamic 的元素支持任何操作。 因此,您不必考虑对象是从 COM API、从动态语言(例如 IronPython)、从 HTML 文档对象模型 (DOM)、从反射还是从程序中的其他位置获取自己的值。但是,如果代码无效,则在运行时会捕获到错误。
在通过 dynamic 类型实现的操作中,该类型的作用是绕过编译时类型检查, 改为在运行时解析这些操作。该类型简化了对 COM API(例如 Office Automation API)、例动态 API(如 IronPython 库)和 HTML 文档对象模型 (DOM) 的访问。
在大多数情况下, dynamic 类型与 object 类型的行为是一样的。 但是,不会用编译器对包含 dynamic 类型表达式的操作进行解析或类型检查。 编译器将有关该操作信息打包在一起,并且该信息以后用于计算运行时操作。在此过程中,类型 dynamic 的变量会编译到类型 object 的变量中。 因此,类型 dynamic 只在编译时存在,在运行时则不存在。
public class DynamicExample{public static void Run(){dynamic dyn = "j";
object obj = 1;
dynamic dyng = GetDyn("哈哈");
//运行时检查
Console.WriteLine((dyn + 3).GetType());//编译报错
//Console.WriteLine(obj + 3);
Console.WriteLine(dyng + " " + dyng.GetType());
}public static dynamic GetDyn(object obj){return obj;
}}