1. 程式人生 > >1、ASP.NET MVC入門到精通——新語法

1、ASP.NET MVC入門到精通——新語法

在學習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", 2);
        }
    }

執行結果:

如果要name使用預設值,age給值怎麼辦?

_dog.Say(age: 3); //輸入結果:jf,3

物件集合初始化器

在.NET2.0中構造一個物件的方法一是提供一個過載的建構函式,二是用預設的建構函式生成一個物件,然後對其屬性進行賦值。在.NET3.5/C#3.0中我們有一種更好的方式來進行物件的初始化。那就是使用物件初始化器。這個特性也是匿名類的一個基礎,所以放在匿名類之前介紹。需要注意的是,它最終還是離不開建構函式,它其實是使用預設的建構函式生成了一個物件。

物件初始化:

  User user = new User { Id = 1, Name = "Zouqj", Age = 26 };

集合初始化:

  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 = 1, Name = " Zouqj ", Age = 26 };//屬性名字和順序不同會生成不同類

在編譯後會生成一個【泛型類】,包含:

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>5
//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 > 5 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#語法糖在它面前都將原形畢露。

相關推薦

1ASP.NET MVC入門精通——語法

在學習ASP.NET MVC之前,有必要先了解一下C#3.0所帶來的新的語法特性,這一點尤為重要,因為在MVC專案中我們利用C#3.0的新特性將會大大的提高我們的開發效率,同時,在MVC專案中你將到處可以看到C#3.0新特性的身影。其本質都是“語法糖”,由編譯器在編譯時轉成原始語法。 目錄 自動屬

19ASP.NET MVC入門精通——Unity

一、IOC介紹   IOC(Inversion of Control),中文譯為控制反轉,又稱為“依賴注入”(DI =Dependence Injection)   IOC的基本概念是:不建立物件,但是描述建立它們的方式。在程式碼中不直接與物件和服務連線,但在配置檔案中描述哪一個元件需要哪一項服務。容器負

2ASP.NET MVC入門精通——Entity Framework入門

實體框架(Entity Framework)簡介 簡稱EF 與ADO.NET關係 ADO.NET Entity Framework 是微軟以 ADO.NET 為基礎所發展出來的物件關係對應 (O/R Mapping) 解決方案,早期被稱為 ObjectSpace,最新版本是EF7【CodeOnly功能得

6ASP.NET MVC入門精通——ASP.Net的兩種開發方式

目前,ASP.NET中兩種主流的開發方式是:ASP.NET Webform和ASP.NET MVC。從下圖可以看到ASP.NET WebForms和ASP.NET MVC是並行的,也就是說MVC不會取代WebForms(至少目前是這樣)而是多了一個選擇,Webform在短期之內不會消亡,儘管存在許多缺點,

8ASP.NET MVC入門精通——View(檢視)

View檢視職責是向用戶提供介面。負責根據提供的模型資料,生成準備提供給使用者的格式介面。 支援多種檢視引擎(Razor和ASPX檢視引擎是官方預設給出的,其實還支援其它N種檢視引擎,甚至你自己都可以寫一套檢視引擎) View和Action之間資料傳遞(前後臺數據傳遞)   弱型別 View

5ASP.NET MVC入門精通——NHibernate程式碼對映

使用的是xml進行orm對映,那麼這一篇就來講下程式碼對映。 新建一個抽象的資料化持久基類AbstractNHibernateDao.cs /// <summary> /// 資料持久化基本 /// </summary> ///

12ASP.NET MVC入門精通——HtmlHelper

HtmlHelper:是為了方便View的開發而產生 HtmlHelper的演變 普通首頁超級連結為:<a href="/home/index">首頁</a> 當路由改變時候則可能需要修改為:<a href="/home/index1">首頁</a&

9ASP.NET MVC入門精通——Controller(控制器)

Controller主要負責響應使用者的輸入。主要關注的是應用程式流,輸入資料的處理,以及對相關檢視(View)輸出資料的提供。 繼承自:System.Web.Mvc.Controller 一個Controller可以包含多個Action. 每一個Action都是一個方法, 返回一個Act

22ASP.NET MVC入門精通——搭建專案框架

前面的章節,說了ASP.NET MVC專案中常用的一些技術和知識點,更多的是理論上面的東西,接下來,我將通過一個簡單的OA專案來應用我們之前涉及到的一些技術,為了兼顧初學者,所以我儘量把操作步驟說得足夠詳細。(本來想用VS2015來演示MVC5開發的,無奈家裡的筆記本是11年2月份的老爺機了,一直未曾捨得

7ASP.NET MVC入門精通——第一個ASP.NET MVC程式

開發流程 新建Controller 建立Action 根據Action建立View 在Action獲取資料並生產ActionResult傳遞給View。 View是顯示資料的模板 Url請求→Controller.Action處理→View響應 url請求→Controller.Ac

3ASP.NET MVC入門精通——Entity Framework增刪改查

這裡我接上講Entity Framework入門。從網上下載Northwind資料庫,新建一個控制檯程式,然後重新新增一個ado.net實體資料模型。 EF中操作資料庫的"閘道器"(操作上下文) DBContext封裝 .NET Framework 和資料庫之間的連線。此類用作“建立”、“讀取”、“更

11ASP.NET MVC入門精通——AspnetMVC分頁

說起分頁,這基本上是我們Web開發中遇見得最多的場景,沒有之一,可即便如此,要做出比較優雅的分頁還是需要技巧的。這裡我先說一種ASP.NET MVC中很常見的一種分頁的實現方式,很low,但是很多公司的專案就是這麼用的,我現在公司的專案就是也是,有時候面對公司專案屎一樣的使用者體驗和雜亂的程式碼,真是恨不

13ASP.NET MVC入門精通——MVC請求管道

ASP.NET MVC的請求管道和ASP.NET請求管道基本上一模一樣,如果你對ASP.NET請求管道十分熟悉的話,你只要關注一下不同點。看懂下面兩張圖,你就基本上明瞭了,這兩張圖是從鄒華棟部落格上面取的。(說明:我不是給傳智帶鹽的,這圖確實畫得通俗易懂)不明白的地方,用reflector工具檢視MVC的

25ASP.NET MVC入門精通——Spring.net-業務層倉儲

上一節,我們已經把專案框架的雛形搭建好了,那麼現在我來開始業務實現,在業務實現的過程當中,不斷的來完善我們現有的框架。 1、假設我們來做一個使用者登入的業務 那麼我們可以現在IDAL專案中定義的的介面IOu_UserInfoDAL,注意是部分類partial,為了方便管理,把這些擴充套件的部分介面都統

20ASP.NET MVC入門精通——WebAPI

微軟有了Webservice和WCF,為什麼還要有WebAPI? 用過WCF的人應該都清楚,面對那一大堆複雜的配置檔案,有時候一出問題,真的會叫人抓狂。而且供不同的客戶端呼叫不是很方便。不得不承認WCF的功能確實非常強大,可是有時候我們通常不需要那麼複雜的功能,只需要簡單的僅通過使用Http或Https

17ASP.NET MVC入門精通——Spring.net入門

Spring.NET環境準備 下載後解壓   Spring.NET-1.3.2.7z:這個裡面有我們需要用到的所有東西。 Spring.NET-1.3.2.exe:安裝檔案 Spring.NET-1.3.2-API.chm:幫助文件 NHibernate 3.2 的下載地址:   

26ASP.NET MVC入門精通——後臺管理區域及分離Js壓縮cssjquery擴充套件

有好一段時間沒更新博文了,最近在忙兩件事:1、看書,學習中...2、為公司年會節目做準備,由於許久沒有練習雙截棍了,難免生疏,所以現在臨時抱佛腳。深圳最近的天氣反常,許多人感冒了,我也成為其中之一,大家注意身體... 這一篇,我來簡單的講一下接下來專案中會用到的一些雜七雜八的技術。 區域及分離

21ASP.NET MVC入門精通——ASP.NET MVC4優化

刪除無用的檢視引擎 預設情況下,ASP.NET MVCE同時支援WebForm和Razor引擎,而我們通常在同一個專案中只用到了一種檢視引擎,如Razor,那麼,我們就可以移除掉沒有使用的檢視引擎,提高View檢視的檢索效率。在沒有刪除WebForm引擎之前,檢索控制器中不存在的檢視時,我們可以從下圖看

23ASP.NET MVC入門精通——業務層和資料層父類及介面-T4模板

在上一篇中,我們已經把專案的基本框架搭起來了,這一篇我們就來實現業務層和資料層的父介面及父類。 1、我們先來定義一個業務層父介面IBaseBLL.cs using System; using System.Collections.Generic; using System.Linq; u

10ASP.NET MVC入門精通——Model(模型)和驗證

模型就是處理業務,想要儲存、建立、更新、刪除的物件。 註解(通過特性實現) DisplayName Required StringLength(20,MinimumLength=2) DataType(System.ComponentModel.DataAnnotations.Dat