.Net Framework 4.5與Visual Studio 11 –工具與程式語言新功能

by vivid 2. 十一月 2011 01:11

.NET Magazine國際中文電子雜誌
作 者:許薰尹
審 稿:張智凱
文章編號:N111111801
出刊日期:2011/11/02

微軟在2011年9月14日,美國BUILD大會上發布了新的Visual Studio 2011開發工具預覽版–「Visual Studio 11 Developer Preview」,或簡稱「Dev 11」,以及下一版的開發程式庫 - .NET Framework 4.5。

若讀者想要測試這個工具,可以從微軟的網站下載安裝程式:

  • Microsoft® Visual Studio® 11 Developer Preview (Web Installer)

http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=27543#top

不過,若要使用ASP.NET MVC 4預覽版來進行開發的動作,則需要額外下載AspNetMVC4VisualStudio11Setup.exe:

  • ASP.NET MVC 4 Developer Preview下載

http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=27419

本文撰寫時使用的工具是Visual Studio 11 Developer Preview,資料庫則為SQL Server “Denali” Express版,因此本文探討的內容在正式版上市時可能不適用。

Visual Studio 11 Developer Preview開發工具

Visual Studio 2010與Visual Studio 11 Developer Preview開發工具兩者可以並存在相同的電腦環境上。更好的是,專案檔案與方案檔案具備向下相容的能力。不過,參考圖1所示,目前在筆者的電腦中安裝了.NET Framework 4版,從Visual Studio 11 Developer Preview專案的「Target Framework」設定來看,目前Visual Studio 11 Developer Preview不僅能夠開發預設的.NET Framework 4.5版程式,也能夠開發前版.NET Framework 4的應用程式。

clip_image002[9]

圖 1:Visual Studio 11 Developer Preview專案的「Target Framework」設定。

當你在Visual Studio 11 Developer Preview開啟使用Visual Studio 2010設計的方案或專案時,並不會有升級精靈跳出來,而是直接將專案與方案開啟。當然,被Visual Studio 11 Developer Preview開啟的專案,後續還是可以利用Visual Studio 2010開啟繼續進行設計的動作,但前題是不要使用到.NET Framework 4.5的新功能。不過,若是在Visual Studio 11 Developer Preview中將專案的目標Framework設定為.NET Framework 4.5,則使用Visual Studio 2010開啟此專案時,會跳出以下提示訊息,您可以選擇將專案重設為.NET Framework 4版本,再繼續編輯程式,參考圖2所示。

clip_image004[6]

圖 2:重設目標Framework訊息。

「Solution Explorer」視窗

「Solution Explorer」視窗可以用來檢視類別的成員、進行成員搜尋動作,或者開啟兩個以上的「Solution Explorer」視窗,便於在多個螢幕中顯示。

在「Solution Explorer」視窗中,每一個專案項目右方會多一個「Contains」選項,您也可以按下「Control+向右箭頭」來啟用「Contains」選項,參考圖3所示:

clip_image006[6]

圖 3:「Contains」選項。

點選「Contains」選項就可以檢視此項目包含的內容,例如,參考圖4所示,MainWindow.xaml.cs檔案中,MainWindow類別包含了MainWindow方法以及其它成員,您也可以檢視其基礎型別(Base Types)、衍生型別(Derived Types),或被哪些項目使用(Is Used By)。「Solution Explorer」視窗上方的向左、向右鍵頭可以回到上一個、或下一個檢視畫面。

clip_image008[6]

圖 4:檢視項目包含的內容。

此外「Solution Explorer」視窗也提供了簡易的搜尋功能,便於找尋專案中的程式碼,底下的圖5顯示輸入「Initial」關鍵字之後,表列出符合查詢條件的結果。

clip_image010[6]

圖 5:「Solution Explorer」視窗的搜尋功能。

另外您也可以利用「Solution Explorer」視窗來檢視方法的呼叫歷程,類似前版Visual Studio 2010 C#專案中的「Call Hierarchy」視窗的功能,參考圖6所示。

clip_image012[6]

圖 6:檢視方法的呼叫歷程。

當設計工具中開啟的檔案很多時,有時很難尋找,你可以利用將常用檔案釘選(Pin)起來,以便於找尋,參考圖7所示:

clip_image014[6]

圖 7:檔案釘選功能。

檔案預覽功能(File preview)

Visual Studio 11 Developer Preview新增一個檔案預覽(File preview)功能,可以將未開啟在設計畫面中的檔案自動開啟提供預覽的動作。不過要使用此功能之前,需要先在Visual Studio 11 Developer Preview 的「Tools」->「Options」->「Environment」->「Tabs and Windows」頁面中,勾選「Allow new files to be opened in the preview tab」項目,您還可以視情況勾選「Single – click opens files in the preview tab for supported tool windows Press Alt to prevent files from being previewed during a single-click operation」項目,參考圖8所示。

clip_image016[6]

圖 8:啟用檔案預覽(File preview)功能。

舉例來說,參考圖9,當應用程式執行,進入中斷模式來除錯時,您可以直接點選程式碼視窗中的Employee類別上,按下滑鼠右鍵,從突顯示選單,選取「Go To Definition」項目,Visual Studio 11 Developer Preview會自動地開啟Employee類別定義所在的檔案,表列在編輯視窗的右上方。

clip_image018[6]

圖 9:檔案預覽。

你可以點選預覽視窗上的「Promote」按鈕,它就會變成是一般的分頁,參考圖10所示。

clip_image020[6]

圖 10:檔案預覽Promote功能。

若是使用Visual Studio 11 Developer Preview的功能搜尋程式碼,搜尋的結果會表列在「Find Results」視窗。現在「Find Results」視窗也提供檔案預覽的功能。例如底下範例搜尋應用程式中的Employee類別,當你點選「Find Results」視窗搜尋到的第一個項目時,預覽檔案的分頁也會自動顯示,參考圖11所示。

clip_image022[6]

圖 11:「Find Results」視窗檔案預覽的功能。

「Quick Launch」視窗

當Visual Studio開發工具的功能愈來愈複雜時,想要尋找選單中的選項就是一件相當困難的事。還好,在Visual Studio 11 Developer Preview工具的右上角有一個新的「Quick Launch」視窗,可以快速地找到Visual Studio 11 Developer Preview的選單選項,參考圖12所示。

clip_image024[6]

圖 12:「Quick Launch」視窗。

例如想要變更程式碼的字型,可以在「Quick Launch」視窗輸入「fonts」字串,按下鍵盤的「Enter」鍵,Visual Studio 11 Developer Preview便會自動表列出和Fonts相關的設定步驟,顯示在下方。當你點選列在下方的「Environment -> Fonts and Colors」選項時,Visual Studio 11 Developer Preview也會自動顯示「Options」對話盒,並停留在「Fonts and Colors」設定畫面,您便可以馬上更改相關的設定,非常的便利,參考圖13所示。

clip_image026[6]

圖 13:「Quick Launch」視窗。

「Quick Launch」視窗也可以應用在搜尋已開啟的文件,例如圖14顯示,若想要快速地切換到已開啟的MainWindow.xaml檔案,只要輸入關鍵字,如「MainWi」就行了:

clip_image028[6]

圖 14:在「Quick Launch」視窗搜尋已開啟的文件。

增強的搜尋功能

隨著.NET Framework版本的更新,可以使用在應用程式介面的控制項以及專案檔案也愈來愈多,不方便找尋。現在「Toolbox」、「Solution Explorer」與「Error List」…等多個視窗都具備搜尋的功能,方便尋找控制項、檔案或錯誤資訊等等。

要使用「Toolbox」搜尋的功能,您可以利用上方的「Search Toolbox」文字方塊輸入關鍵字來篩選控制項,或是直接將游標停留在工具箱上後,直接輸入關鍵字。例如以下輸入「ca」字串,Visual Studio 11 Developer Preview工具箱的游標會自動停留在Calendar控制項上,按下鍵盤的Tab鍵可以切換到下一個符合搜尋關鍵字的控制項上,若要取消查詢動作,可以按下鍵盤的ESC鍵,參考圖15所示。

clip_image030[6]

圖 15:搜尋控制項。

使用規則運算式搜尋

「Quick Find」、「Quick Replace」、「Find in Files」與「Replace in Files」視窗可以用來搜尋、取代專案或檔案中的內容。現在搜尋時又新增一個選項,可以使用規則運算式定義篩選條件來進行搜尋。

參考底下的「Quick Find」視窗,您可以按下「CTRL + F5」來開啟這個視窗,它會出現在程式編輯視窗的右上角。搜尋時只要輸入有意義的規則運算式,並勾選「Use Regular Expression」選項即可,搜尋到的內容會以黃色標示。若要檢視下一個符合篩選條件的內容,可以按下「Quick Find」視窗右上方的向右、向左箭頭,或按下鍵盤F3 (Find Next) 或SHIFT + F3 (Find Previous) ,參考圖16所示:

clip_image032[6]

圖 16:使用規則運算式搜尋。

Visual Basic與C#新功能-Async

Visual Basic與C#新增一個非同步功能(Async),讓非同步應用程式的開發能夠更簡單。

Visual Basic與C#都新增兩個運算子,Async (適用於Visual Basic),async(適用於C#)以及 Await (適用於Visual Basic),await(適用於C#)。 在定義方法時,方法的前方可以加上Async(async)關鍵字,以通知編譯程式某個方法或某一個Lambda運算式是非同步的,這個標識async關鍵字的方法稱為-非同步方法(async method)

非同步方法(async method)宣告時,要加上async關鍵字。

await運算子則是套用在一項非同步方法的作業(Task)上,停滯此方法程式的執行,直到作業執行完畢為止,才將執行權交還給呼叫的方法。作業(Task)就是你欲以非同步方式執行的動作。不過,await運算子只能夠在有標示async關鍵字的非同步方法中使用。

底下的程式碼片斷中的AsyncMethod方法就是一個非同步方法,方法中await關鍵字套用在叫用Task.Delay方法這一行程式,讓程式暫停一秒執行,然後再回傳「Hello」字串:

C#語法:

public static async Task< string > AsyncMethod()     
{
    await Task.Delay( 1000 );
    return "Hello" ;
}

Visual Basic語法:

Public Async Function AsyncMethod( ) As Task( Of String )
    Await Task.Delay( 1000 )
    Return "Hello"
End Function

await運算式並不會停滯目前正在執行中的執行緒,而是告知編譯器將非同步方法剩餘未執行的程式碼標示為一項await 工作,控制權會交還呼叫非同步方法的呼叫者。當非同步作業執行完畢時,就會執行非同步方法剩餘未執行的程式碼。

再者,以C#程式語言來說,非同步方法的回傳值只能夠是void、Task或Task<T>型別,T代表回傳值的型別。若以Visual Basic程式語言來說,非同步方法可以是一個sub,或function,但function的回傳值只能夠是Task或Task(of T)型別。此例中AsyncMethod非同步方法回傳的是一個Task<string>(C#),Task(Of String) (Visual Basic),這個方法回傳值的型別是string型別。在命名時按慣例,會以「Async」字串結尾。

C#語法:

private static async void GetNameAsync()
        {
            Task< string > myTask = (Task< string >) AsyncMethod();
            string result = await myTask;
            Console.WriteLine( result );
        }

Visual Basic語法:

Private Async Sub GetNameAsync()
      Dim myTask As Task( Of String ) = AsyncMethod()
      Dim result As String = Await myTask
      Console.WriteLine( result )
  End Sub

底下的主控台範例程式展示了非同步與同步的程式寫法,C#語法:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace CSNew
{
    class Class1
    {
        static void Main(string[] args)
        {
            Console.WriteLine( "Sync demo started.." );
            GetNameSync( );
            Console.WriteLine( "Main finished" );
            Console.ReadLine( );

            Console.WriteLine( "Async demo started.." );
            GetNameAsync ();
            Console.WriteLine( "Main finished" );
            Console.ReadLine();
        }
        public static async Task< string > AsyncMethod()     
        {
            await Task.Delay( 1000 );
            return "Hello";
        }
        public static async Task< string > SynchMethod()
        {
            Thread.Sleep( 1000 );
            return "Hello";
        }
        private static async void GetNameSync()
        {
            Task< string > myTask = (Task< string >) SynchMethod();
            string result = await myTask;
            Console.WriteLine( result );
        }
        private static async void GetNameAsync()
        {
            Task< string > myTask = (Task< string >) AsyncMethod();
            string result = await myTask;
            Console.WriteLine( result );
        }
    }
}

非同步方法中若沒有使用await關鍵字,編譯程式時,Visual Studio 11 Developer Preview會顯示警告訊息,但不代表錯誤,程式可以照常執行,不過,會被視為同步的方法來執行。此程式執行的結果參考如下,參考圖17所示:

clip_image034[6]

圖 17:async範例。

若改用Visual Basic程式語言, Async範例如下:

Imports System.Threading

Module Module1
    Sub Main()
        Console.WriteLine( "Sync demo started.." )
        GetNameSync( )
        Console.WriteLine( "Main finished" )

        Console.ReadLine( )

        Console.WriteLine( "Async demo started.." )
        GetNameAsync( )

        Console.WriteLine( "Main finished" )
        Console.ReadLine( )
    End Sub

    Private Async Sub GetNameSync()
        Dim myTask As Task( Of String ) = SynchMethod()
        Dim result As String = Await myTask
        Console.WriteLine( result )
    End Sub

    Private Async Sub GetNameAsync()
        Dim myTask As Task( Of String ) = AsyncMethod()
        Dim result As String = Await myTask
        Console.WriteLine( result )
    End Sub
    Public Async Function AsyncMethod() As Task( Of String )
        Await Task.Delay( 1000 )
        Return "Hello"
    End Function

    Public Async Function SynchMethod() As Task( Of String )
        Thread.Sleep( 1000 )
        Return "Hello"
    End Function
End Module

再者,async關鍵字可以套用在方法或Lambda運算式上,例如以下範例所示,C#語法:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace CSNew
{
    class Class1
    {
        static void Main( string[] args )
        {        
            Console.WriteLine( "Async demo started.." );
            GetNameAsync( );
            Console.WriteLine( "Main finished" );
            Console.ReadLine( );
        }      
      
        private static async void GetNameAsync()
        {
            Task< string > labexp = async ( ) =>
            {
                await Task.Delay( 1000 );
                Console.WriteLine( "Hello" );
            };
            await Run( labexp );          
        }
        public static Task Run( Func<Task> t )
        {
            if ( t != null )
                return Task.Run( t );
            return null;
        }
    }
}

Visual Basic語法:

Imports System.Threading

Module Module1
    Sub Main( )
        Console.WriteLine( "Async demo started.." )
        GetNameAsync( )
        Console.WriteLine( "Main finished" )
        Console.ReadLine( )
    End Sub

    Private Async Sub GetNameAsync( )
        Dim labexp As Func( Of Task ) = Async Function( )
                                          Await Task.Delay( 1000 )
                                          Console.WriteLine( "Hello" )
                                      End Function
        Await Run( labexp )
    End Sub
    Public Function Run( t As Func( Of Task ) )
        If ( t <> Nothing ) Then
            Return Task.Run( t )
        End If
        Return Nothing
    End Function
End Module

Task類別定義在System.Threading.Tasks命名空間下,代表一個非同步的作業,範例中叫用Run方法來執行Func<Task >,它可以用來呼叫一個沒有參數、會回傳一個Task型別的方法。

Visual Basic新語法-Iterator

Iterator通常都是應用在巡覽集合或陣列中的項目,C#在2005年Visual Studio 2005的版本中就已經支援,而Visual Basic直到Visual Studio 11 Developer Preview 版才新增了Iterator語法 - Yield。

我們先參考一個簡單的iterator範例,定義一個列舉方法 (Iterator method) - GetName,此方法定義時,前方標示了Iterator Modifer,方法中利用Yield關鍵字,依序回傳「Mary」、「Candy」、「Lily」以及「Sandy」等字串。Main方法中利用For Each..Next方法列舉GetName方法回傳的結果。

Module Module1
    Sub Main( )
        For Each n As String In GetName( )
            Console.Write( n & "," )
        Next
    End Sub
    Public Iterator Function GetName( ) As System.Collections.IEnumerable
        Yield "Mary"
        Yield "Candy"
        Yield "Lily"
        Yield "Sandy"
    End Function
End Module
支援泛型型別

列舉方法 (Iterator method)的回傳型別也可以是一個泛型型別,例如底下範例,GetName方法回傳的是System.Collections.Generic.IEnumerable(Of String)型別。

Module Module1
    Sub Main( )
        For Each n As String In GetName( )
            Console.Write( n & "," )
        Next
    End Sub
    Public Iterator Function GetName( ) As System.Collections.Generic.IEnumerable( Of String )
        Yield "Mary"
        Yield "Candy"
        Yield "Lily"
        Yield "Sandy"
    End Function
End Module
支援屬性語法

Iterator Modifer除了可以應用在Function之外,也可以應用在屬性的語法上。例如以下範例Module1中GetNames屬性內宣告一個做為iterator的Get存取子(Get Accessor)。Main方法中則利用for each迴圈列出屬性中的所有字串。

Module Module1
    Sub Main( )
        For Each n As String In Module1.GetNames( )
            Console.Write( n & "," )
        Next
    End Sub

    Public ReadOnly Iterator Property GetNames( ) As IEnumerable( Of String )
        Get
            Yield "Mary"
            Yield "Candy"
            Yield "Lily"
            Yield "Sandy"
        End Get
    End Property
End Module

 

自訂類別

自訂的類別若需要實作列舉功能,可以實作IEnumerable介面,它包含一個GetEnumerator方法,只要實作這個方法就可以了。例如以下範例,EmployeeNameList類別實作IEnumerable介面,EmployeeNameList類別的建構函式建立了代表名稱的字串加入nameList集合中,GetEnumerator方法則透過for each搭配yield語法,一次傳回集合中的一個字串:

Module Module1
    Sub Main( )
        Dim empList As New EmployeeNameList ()
        For Each n As String In empList
            Console.Write( n & "," )
        Next
    End Sub
End Module

Public Class EmployeeNameList
    Implements IEnumerable
    Dim nameList As New List( Of String )
    Sub New()
        nameList.Add( "Mary" )
        nameList.Add( "Candy" )
        nameList.Add( "Lily" )
        nameList.Add( "Sandy" )
    End Sub
    Public Iterator Function GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
        For Each n In nameList
            Yield n
        Next
    End Function
End Class

匿名方法

Visual Basic中的匿名方法也可以是一個列舉方法(C#不適用),例如以下定義的匿名方法前方加註了Iterator關鍵字,方法中使用Yield一次回傳一個字串:

Dim nameList = Iterator Function( ) As IEnumerable( Of String )
                           Yield "Mary"
                           Yield "Candy"
                           Yield "Lily"
                           Yield "Sandy"
                       End Function

        For Each n As String In nameList.Invoke( )

            Console.Write( n & "," )
        Next

呼叫階層(Call Hierarchy)

Visual Basic新增了呼叫階層(Call Hierarchy)視窗,這個功能在前一版Visual Studio 2010的C#開發工具中便已提供。由於Visual Studio 11 Developer Preview 的方案總管(Solution Explorer)視窗也有類似「呼叫階層」視窗的功能,因此這項新功能似乎不太令人驚豔了,參考圖18所示。

clip_image036[6]

圖 18:Visual Basic 的「Call Hierarchy」視窗。

Global關鍵字

Global關鍵字可以讓你存取到.NET的System命名空間,在你自訂命名空間和System下命名空間名稱相衝突時非常的有用。例如以下範例,自訂的A命名空間下包含一個子System命名空間。此命名空間和.NET Framework的System命名空間名稱相同,造成衝突。

Namespace A
    Namespace System
        Class Test
            Sub Print( )
                System.Console.WriteLine( "Hello" )
            End Sub
        End Class
    End Namespace
End Namespace

因此,當你在Test類別中,撰寫System.Console.WriteLine這行程式碼時,Visual Studio便會出現錯誤訊息,無法識別System下的Console類別,參考圖19所示:

clip_image038[6]

圖 19:Global關鍵字可以解決名稱衝突。

我們可以將程式碼變更為改用Global關鍵字存取到.NET Framework中的System命名空間來解決這個命名空間衝突的問題:

Namespace A
    Namespace System
        Class Test
            Sub Print( )
                Global.System.Console.WriteLine( "Hello" )
            End Sub
        End Class
    End Namespace
End Namespace

Tags:

NET 開發 | 許薰尹Vivid Hsu | .NET Magazine國際中文電子雜誌

新增評論




  Country flag
biuquote
  • 評論
  • 線上預覽
Loading






NET Magazine國際中文電子雜誌

NET Magazine國際中文電子版雜誌,由恆逸資訊創立於2000,自發刊日起迄今已發行超過500篇.NET相關技術文章,擁有超過40000名註冊讀者群。NET Magazine國際中文電子版雜誌希望藉於電子雜誌與NET Developer達到共同學習與技術新知分享,歡迎每一位對.NET 技術有興趣的朋友們多多支持本雜誌,讓作者群們可以有持續性的動力繼續爬文。<請加入免費訂閱>

月分類Month List