1、ASP.NET MVC入门到精通——新语法
本系列目录:ASP.NET MVC4入门到精通系列目录汇总
在学习ASP.NET MVC之前,有必要先了解一下C#3.0所带来的新的语法特性,这一点尤为重要,因为在MVC项目中我们利用C#3.0的新特性将会大大的提高我们的开发效率,同时,在MVC项目中你将到处可以看到C#3.0新特性的身影。其本质都是“语法糖”,由编译器在编译时转成原始语法。
目录
- 自动属性
- 隐式类型 var
- 参数默认值 和 命名参数
- 对象初始化器与集合初始化器
- 匿名类& 匿名方法
- 扩展方法
- 系统内置委托:Func / Action
- Lambda表达式
- 标准查询运算符(SQO)
- LINQ
自动属性
这个概念很简单,其简化了我们在.NET的时候手写一堆私有成员+属性的编程方式,我们只需要使用如下方式声明一个属性,编译器会自动生成所需的成员变量。
回顾传统属性概念,属性的目的:封装字段,控制 1.读写权限 及 2.字段的访问规则(如:年龄范围)。但平时,主要是用来封装读写权限。
基本用法:
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public Address Address { get; set; }
}
在C#3.0之前,我们是这样来实现属性的:
private int id;
public int Id
{
get
{
return id;
}
set
{
id = value;
}
}
思考:
用自动属性的话程序员写的代码少了,机器做的事情就多了,那我们到底要不要使用它?
如果是针对读写权限的封装,就推荐使用,因为它是在编译的时候产生了负担,并不是在运行的时候。(不会影响客户运行程序时的效率!)
但是编译生成的代码也有一个显而易见的缺点,语法太完整,编译后的程序集会比较大。
隐式推断类型
这个名称可能对你很陌生,但是var这个关键字应该都用过,在C#中使用var声明一个对象时,编译器会自动根据其赋值语句推断这个局部变量的类型。赋值以后,这个变量的类型也就确定而不可以再进行更改。另外var关键字也用于匿名类的声明。
应用场合:var主要用途是表示一个LINQ查询的结果。这个结果可能是ObjectQuery<>或IQueryable<>类型的对象,也可能是一个简单的实体类型的对象。这时使用var声明这个对象可以节省很多代码书写上的时间。
var customer = new Customer();
var隐式类型的限制
1.被声明的变量是一个局部变量,而不是静态或实例字段;
2.变量必须在声明的同时被初始化;编译器要根据初始化值推断类型
3.初始化不能是一个匿名函数;
4.初始化表达式不能是 null;
5.语句中只声明一次变量,声明后不能更改类型;
6.赋值的数据类型必须是可以在编译时确定的类型;
参数默认值 和 命名参数
public class Dog
{
public void Say(string name = "jf", int age=1)
{
Console.WriteLine(name + "," + age);
}
}
class Program
{
static void Main(string[] args)
{
Dog _dog = new Dog();
_dog.Say();
_dog.Say("haha");
_dog.Say("wuwu", );
}
}
运行结果:

如果要name使用默认值,age给值怎么办?
_dog.Say(age: 3); //输入结果:jf,3
对象集合初始化器
在.NET2.0中构造一个对象的方法一是提供一个重载的构造函数,二是用默认的构造函数生成一个对象,然后对其属性进行赋值。在.NET3.5/C#3.0中我们有一种更好的方式来进行对象的初始化。那就是使用对象初始化器。这个特性也是匿名类的一个基础,所以放在匿名类之前介绍。需要注意的是,它最终还是离不开构造函数,它其实是使用默认的构造函数生成了一个对象。
对象初始化:
User user = new User { Id = , Name = "Zouqj", Age = };
集合初始化:
List<Dog> list = new List<Dog>() { new Dog() { Name = "Tom", Age = 1 }, new Dog() { Name = "Lucy", Age = 3 } };
创建并初始化数组:
string[] array = { "aaa", "bbb" };
匿名类
有了前文初始化器的介绍,匿名类就很简单了。我们可以使用new { object initializer }或new[]{ object, …}来初始化一个匿名类或不确定类型的数组。匿名类的对象需要使用var关键字声明。示例代码:
var p = new { Id = , Name = " Zouqj ", Age = };//属性名字和顺序不同会生成不同类
在编译后会生成一个【泛型类】,包含:
a. 获取所有初始值的构造函数,顺序与属性顺序一样;
b.公有的只读属性,属性不能为null/匿名函数/指针;
c.属性的私有只读字段;
d.重写的Equals,GetHashCode,ToString()方法
用处:
a.避免过度的数据累积
b.为一种情况特别进行的数据封装
c.避免进行单调重复的编码
应用场合:当直接使用select new { object initializer }这样的语法就是将一个LINQ查询的结果返回到一个匿名类中。
注意:
1. 当出现“相同”的匿名类的时候,编译器只会创建一个匿名类
2. 编译器如何区分匿名类是否相同?
根据:属性名,属性值(因为这些属性是根据值来确定类型的),属性个数,属性的顺序。
3、匿名类的属性是只读的,可放心传递,可用在线程间共享数据
匿名方法
函数式编程的最大特点之一:把方法作为参数和返回值。 DGShowMsg -> MulticastDelegate(intPtr[]) -> Delegate(object,intPtr)
匿名方法:编译后会生成委托对象,生成方法,然后把方法装入委托对象,最后赋值给 声明的委托变量。
匿名方法可以省略参数:编译的时候 会自动为这个方法 按照 委托签名的参数 添加参数
public delegate void ConsoleWrite(string strMsg);
public void WriteMsg(string strMsg)
{
Console.WriteLine("myMsg=" + strMsg);
}
//测试
ConsoleWrite delCW1 = new ConsoleWrite(WriteMsg);
delCW1("哈哈哈哈"); ConsoleWrite delCW2 = delegate(string strMsg) {
Console.WriteLine(strMsg);
};
delCW2("哈哈哈哈");
扩展方法
扩展方法的本质:编译时,直接将 str.WriteSelf(2015) 替换成 StringUtil.WriteSelf(str,2015);
想为一个类型添加一些成员 , 怎么办?
扩展方法:
public static class StringUtil
{
public static void WriteSelf(this string strSelf , int year)
{
Console.WriteLine(strSelf);
}
}
测试:
string str="中国钓鱼岛";
str.WriteSelf(2015);
本质就是静态方法
编译器认为一个表达式是要使用一个实例方法,但没有找到,就会检查导入的命名空间和当前命名空间里所有的扩展方法,并匹配到适合的方法.
注意:1.实例方法优先于扩展方法(允许存在同名实例方法和扩展方法)2.可以在空引用上调用扩展方法!3.可以被继承4.并不是任何方法都能作为扩展方法使用,必须有特征:
它必须放在一个非嵌套、非泛型的静态类中(的静态方法);
它至少有一个参数;
第一个参数必须附加 this 关键字;
第一个参数不能有任何其他修饰符(out/ref)
第一个参数不能是指针类型
看看这两个接口的方法:IEnumerable<T> ,IQueryable<T>
系统内置委托:Func / Action
委托使用可变性 :
Action<object> test=delegate(object o){Console.WriteLine(o);};
Action<string> test2=test;
Func<string> fest=delegate(){return Console.ReadLine();};
fest2=fest;
public delegate void Action();
public delegate bool Predicate<in T>(T obj);
public delegate int Comparison<in T>(T x, T y);
协变指的是委托方法的返回值类型直接或间接继承自委托签名的返回值类型,逆变则是参数类型继承自委托方法的参数类型
System.Func 代表有返回类型的委托
public delegate TResult Func<out TResult>();
public delegate TResult Func<in T, out TResult>(T arg);
......
注:输入泛型参数-in 最多16个,输出泛型参数 -out 只有一个。
System.Action 代表无返回类型的委托
public delegate void Action<in T>(T obj); //list.Foreach
public delegate void Action<in T1, in T2>(T1 arg1, T2 arg2);
......
注:参数最多16个
System.Predicate<T> 代表返回bool类型的委托 - 用作执行表达式
public delegate bool Predicate<in T>(T obj); //list.Find
System.Comparison<T> 代表返回int类型的委托 - 用作比较两个参数的大小
public delegate int Comparison<in T>(T x, T y); //list.Sort
为什么要定义这么多简单的委托? 方便!
Lambda表达式
Lambda表达式的本质就是匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),是一个匿名函数,即没有函数名的函数。“Lambda 表达式”是一个匿名函数,它可以包含表达式和语句,并且可用于创建委托或表达式树类型。
Lambda 表达式的运算符 =>,该运算符读为“goes to”。
=> 运算符具有与赋值运算符 (=) 相同的优先级
Lambda的基本形式:(input parameters) => expression
只有在 Lambda 有一个输入参数时,括号才是可选的;否则括号是必需的。 两个或更多输入参数由括在括号中的逗号分隔: (x, y) => x == y
有时,编译器难于或无法推断输入类型。 如果出现这种情况,您可以按以下示例中所示方式显式指定类型: (int x, string s) => s.Length > x
使用空括号指定零个输入参数: () => SomeMethod()
最常用的场景:Ienumable和Iqueryable接口的Where<>(c=>c.Id>3)
下列规则适用于 Lambda 表达式中的变量范围:
捕获的变量将不会被作为垃圾回收,直至引用变量的委托超出范围为止。
在外部方法中看不到 Lambda 表达式内引入的变量。
Lambda 表达式无法从封闭方法中直接捕获 ref 或 out 参数。
Lambda 表达式中的返回语句不会导致封闭方法返回。
Lambda 表达式不能包含其目标位于所包含匿名函数主体外部或内部的 goto 语句、break 语句或 continue 语句。
Lambda表达式缩写推演

例子:
delegate int AddDel(int a,int b); //定义一个委托
#region lambda AddDel fun = delegate(int a, int b) { return a + b; }; //匿名函数
//Console.WriteLine(fun(1, 3));
//lambda 参数类型可以进行隐式推断,可以省略类型 lambda本质就是匿名函数
AddDel funLambda = ( a, b) => a + b;
List<string> strs = new List<string>() { "1","2","3"
}; var temp = strs.FindAll(s => int.Parse(s) > 1);
foreach (var item in temp)
{
Console.WriteLine(item);
}
//Console.WriteLine(funLambda(1,3)); #endregion static void Main(string[] args)
{
List<int> nums = new List<int>() { 1,2,3,4,6,9,12};
//使用委托的方式
List<int> evenNums = nums.FindAll(new Program().GetEvenNum);
foreach (var item in evenNums)
{
Console.WriteLine(item);
} Console.WriteLine("使用lambda的方式"); List<int> evenNumLamdas = nums.FindAll(n => n % 2 == 0);
foreach (var item in evenNumLamdas)
{
Console.WriteLine(item);
}
Console.ReadKey();
//nums.FindAll(
} public bool GetEvenNum(int num)
{
if (num % 2 == 0)
{
return true;
}
return false;
}
标准查询运算符(SQO)
标准查询运算符:定义在System.Linq.Enumerable类中的50多个为IEnumerable<T>准备的扩展方法,这些方法用来对它操作的集合进行查询筛选.
- 筛选集合Where:需要提供一个带bool返回值的“筛选器”,从而表明集合中某个元素是否应该被返回。
- 查询投射,返回新对象集合 IEnumerable<TSource> Select()
- 统计数量int Count()
- 多条件排序 OrderBy().ThenBy().ThenBy()
- 集合连接 Join()
- ......
延迟加载:Where
即时加载:FindAll
SQO缺点:语句太庞大复杂
LINQ
C#3.0新语法:查询表达式,和SQL风格接近的代码
IEnumerable<Dog> list = from dog in dogs
where dog.Age>
//let d=new{Name=dog.Name}
orderby dog.Age descending
select dog;
//select new{Name=dog.Name}
以"from"开始,以"select 或 group by子句"结尾。输出是一个 IEnumerable<T> 或 IQueryable<T> 集合;
注:T 的类型 由 select 或 group by 推断出来。
LINQ分组:
IEnumerable<IGrouping<int, Dog>> listGroup = from dog in listDogs where dog.Age > group dog by dog.Age;
遍历分组:
foreach (IGrouping<int, Dog> group in listGroup)
{
Console.WriteLine(group.Key+"岁数:");
foreach (Dog d in group)
{
Console.WriteLine(d.Name + ",age=" + d.Age);
}
}
最后:LINQ 查询语句 编译后会转成 标准查询运算符
此外,我建议大家多使用reflector工具来查看C#源码和IL语言,reflector就像一面照妖镜,任何C#语法糖在它面前都将原形毕露。
1、ASP.NET MVC入门到精通——新语法的更多相关文章
- 25、ASP.NET MVC入门到精通——Spring.net-业务层仓储
本系列目录:ASP.NET MVC4入门到精通系列目录汇总 上一节,我们已经把项目框架的雏形搭建好了,那么现在我来开始业务实现,在业务实现的过程当中,不断的来完善我们现有的框架. 1.假设我们来做一个 ...
- 26、ASP.NET MVC入门到精通——后台管理区域及分离、Js压缩、css、jquery扩展
本系列目录:ASP.NET MVC4入门到精通系列目录汇总 有好一段时间没更新博文了,最近在忙两件事:1.看书,学习中...2.为公司年会节目做准备,由于许久没有练习双截棍了,难免生疏,所以现在临时抱 ...
- 6、ASP.NET MVC入门到精通——ASP.Net的两种开发方式
本系列目录:ASP.NET MVC4入门到精通系列目录汇总 目前,ASP.NET中两种主流的开发方式是:ASP.NET Webform和ASP.NET MVC.从下图可以看到ASP.NET WebFo ...
- 12、ASP.NET MVC入门到精通——HtmlHelper
本系列目录:ASP.NET MVC4入门到精通系列目录汇总 HtmlHelper:是为了方便View的开发而产生 HtmlHelper的演变 普通首页超级链接为:<a href="/h ...
- 15、ASP.NET MVC入门到精通——MVC-路由
本系列目录:ASP.NET MVC4入门到精通系列目录汇总 Routing(路由) – URL url 作为广泛使用的Web用户接口,需要被重视 好的Url应该满足如下条件: URL应为获取某种资源提 ...
- 5、ASP.NET MVC入门到精通——NHibernate代码映射
本系列目录:ASP.NET MVC4入门到精通系列目录汇总 上一篇NHibernate学习笔记—使用 NHibernate构建一个ASP.NET MVC应用程序 使用的是xml进行orm映射,那么这一 ...
- 7、ASP.NET MVC入门到精通——第一个ASP.NET MVC程序
本系列目录:ASP.NET MVC4入门到精通系列目录汇总 开发流程 新建Controller 创建Action 根据Action创建View 在Action获取数据并生产ActionResult传递 ...
- 8、ASP.NET MVC入门到精通——View(视图)
本系列目录:ASP.NET MVC4入门到精通系列目录汇总 View视图职责是向用户提供界面.负责根据提供的模型数据,生成准备提供给用户的格式界面. 支持多种视图引擎(Razor和ASPX视图引擎是官 ...
- 9、ASP.NET MVC入门到精通——Controller(控制器)
本系列目录:ASP.NET MVC4入门到精通系列目录汇总 Controller主要负责响应用户的输入.主要关注的是应用程序流,输入数据的处理,以及对相关视图(View)输出数据的提供. 继承自:Sy ...
随机推荐
- FPGrowth算法总结复习
摘要: 1.算法概述 2.算法推导 3.算法特性及优缺点 4.注意事项 5.实现和具体例子 6.适用场合 内容: 1.算法概述 关联规则(associatio rules):从大规模数据集中寻找物品建 ...
- Node.js教程系列~目录
Node.js这个东西在近几年火起来了,而且会一直火下去,无论在infoq还是在cnblogs,csdn上,都可以到处看到它的样子,它主推的应该就是异步式I/O 吧,是的,设计的很完美,很吸引人,虽然 ...
- java compiler level does not match the version of the installed java project facet 解决方案
项目出现 java compiler level does not match the version of the installed java project facet 错误,一般是项目移植出现 ...
- MongoDB 分片管理
在MongoDB(版本 3.2.9)中,分片集群(sharded cluster)是一种水平扩展数据库系统性能的方法,能够将数据集分布式存储在不同的分片(shard)上,每个分片只保存数据集的一部分, ...
- 回发或回调参数无效。在配置中使用 pages enableEventValidation=true 或在页面中使用 %@ Page EnableEventValidation=true % 启用了事件验证
WebForm中回发或回调参数无效问题的解决 解决 .NET中回发或回调参数无效问题的解 该错误的详细提示信息为: 回发或回调参数无效.在配置中使用 <pages enableEventVali ...
- 如何转型成为SQL Server DBA
本篇PPT是我在2015 MVP OPEN Day Comunity Camp上分享的课程.之所以选择这个主题是因为有很多人曾经问过这方面的问题,而与之相关的主题却少之又少,因此我希望将自己的 ...
- WPF textblock加入超链接
<TextBlock Grid.Row=" Margin="75,0,0,0"> <Hyperlink Name="BlogHl" ...
- 深入理解DOM事件机制系列第四篇——事件模拟
× 目录 [1]引入 [2]模拟机制 [3]自定义事件 前面的话 事件是网页中某个特别的瞬间,经常由用户操作或通过其他浏览器功能来触发.但实际上,也可以使用javascript在任意时刻来触发特定的事 ...
- 【开源】OSharp框架解说系列(4):架构分层及IoC
OSharp是什么? OSharp是个快速开发框架,但不是一个大而全的包罗万象的框架,严格的说,OSharp中什么都没有实现.与其他大而全的框架最大的不同点,就是OSharp只做抽象封装,不做实现.依 ...
- MySQL学习笔记十七:复制特性
一.MySQL的复制是将主数据库(master)的数据复制到从(slave)数据库上,专业一点讲就是将主数据库DDL和DML操作的二进制日志传到从库上,然后从库对这些二进制日志进行重做,使得主数据库与 ...