本系列目录: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入门到精通——新语法的更多相关文章

  1. 25、ASP.NET MVC入门到精通——Spring.net-业务层仓储

    本系列目录:ASP.NET MVC4入门到精通系列目录汇总 上一节,我们已经把项目框架的雏形搭建好了,那么现在我来开始业务实现,在业务实现的过程当中,不断的来完善我们现有的框架. 1.假设我们来做一个 ...

  2. 26、ASP.NET MVC入门到精通——后台管理区域及分离、Js压缩、css、jquery扩展

    本系列目录:ASP.NET MVC4入门到精通系列目录汇总 有好一段时间没更新博文了,最近在忙两件事:1.看书,学习中...2.为公司年会节目做准备,由于许久没有练习双截棍了,难免生疏,所以现在临时抱 ...

  3. 6、ASP.NET MVC入门到精通——ASP.Net的两种开发方式

    本系列目录:ASP.NET MVC4入门到精通系列目录汇总 目前,ASP.NET中两种主流的开发方式是:ASP.NET Webform和ASP.NET MVC.从下图可以看到ASP.NET WebFo ...

  4. 12、ASP.NET MVC入门到精通——HtmlHelper

    本系列目录:ASP.NET MVC4入门到精通系列目录汇总 HtmlHelper:是为了方便View的开发而产生 HtmlHelper的演变 普通首页超级链接为:<a href="/h ...

  5. 15、ASP.NET MVC入门到精通——MVC-路由

    本系列目录:ASP.NET MVC4入门到精通系列目录汇总 Routing(路由) – URL url 作为广泛使用的Web用户接口,需要被重视 好的Url应该满足如下条件: URL应为获取某种资源提 ...

  6. 5、ASP.NET MVC入门到精通——NHibernate代码映射

    本系列目录:ASP.NET MVC4入门到精通系列目录汇总 上一篇NHibernate学习笔记—使用 NHibernate构建一个ASP.NET MVC应用程序 使用的是xml进行orm映射,那么这一 ...

  7. 7、ASP.NET MVC入门到精通——第一个ASP.NET MVC程序

    本系列目录:ASP.NET MVC4入门到精通系列目录汇总 开发流程 新建Controller 创建Action 根据Action创建View 在Action获取数据并生产ActionResult传递 ...

  8. 8、ASP.NET MVC入门到精通——View(视图)

    本系列目录:ASP.NET MVC4入门到精通系列目录汇总 View视图职责是向用户提供界面.负责根据提供的模型数据,生成准备提供给用户的格式界面. 支持多种视图引擎(Razor和ASPX视图引擎是官 ...

  9. 9、ASP.NET MVC入门到精通——Controller(控制器)

    本系列目录:ASP.NET MVC4入门到精通系列目录汇总 Controller主要负责响应用户的输入.主要关注的是应用程序流,输入数据的处理,以及对相关视图(View)输出数据的提供. 继承自:Sy ...

随机推荐

  1. Inter Core CPU 型号的尾字母含义

    Inter Core CPU 型号的尾字母含义: M:表示移动处理器(Mobile Processor):QM:四核移动处理器(Quad Mobile Processor):U:超低电压处理器(Ult ...

  2. Ubuntu 14 安装 .Net Core

    .Net Core的安装包的分发地址如下: https://apt-mo.trafficmanager.net/repos/dotnet-release/pool/main/d/ 方法一: 可以分别手 ...

  3. 程序中保存状态的方式之Cookies

    程序中保存状态的方式之 Cookies,之前写过一篇关于ViewState的.现在继续总结Cookies方式的 新建的测试页面login <%@ Page Language="C#&q ...

  4. [erl] erlang 进程注册和注销

    想要注册一个进程,必须先要创建一个进程. 如何创建一个进程,可以使用spawn.spawn_link,它们虽然都能创建进程,但是也有微妙的区别: 1)当前进程中创建一个并行进程,当被生成的进程崩溃时, ...

  5. JDK安装源码src和doc

    (1)src 打开JDK的安装目录如(C:\Program Files\Java\jdk1.8.0_91)有一个src.zip的压缩文件,这个压缩文件里就是源码. mkdir src copy src ...

  6. XML实体引用

    在 XML 中,一些字符拥有特殊的意义. 如果你把字符 "<" 放在 XML 元素中,会发生错误,这是因为解析器会把它当作新元素的开始. 这样会产生 XML 错误: < ...

  7. 【原创】开源.NET排列组合组件KwCombinatorics使用(一)—组合生成

           本博客所有文章分类的总目录:本博客博文总目录-实时更新 本博客其他.NET开源项目文章目录:[目录]本博客其他.NET开源项目文章目录 KwCombinatorics组件文章目录: 1. ...

  8. IOS数据存储之文件沙盒存储

    前言: 之前学习了数据存储的NSUserDefaults,归档和解档,对于项目开发中如果要存储一些文件,比如图片,音频,视频等文件的时候就需要用到文件存储了.文件沙盒存储主要存储非机密数据,大的数据. ...

  9. IO通道

    本文原创,转载需标明原处. 通道,主要负责传输数据,相当于流,但流只能是输入或输出类型中的其一,而通道则可以兼并二者. 通道的基类是:Channel boolean isOpen() void clo ...

  10. CocoaPods 安装 使用

    1.开启 terminal 2.移除现有 Ruby 默认源 $ gem sources --remove https://rubygems.org/ 3.使用新的源 $ gem sources -a ...