2016 年 1 月

第 31 卷,第 1 期

本文章是由機器翻譯。

基礎 .NET - C# 指令碼

Mark Michaelis |2016 年 1 月

Mark Michaelis隨著 Visual Studio 2015 Update 1,方便您更新 1 新 C# 讀取-評估-列印-循環 (REPL),可為 Visual Studio 2015 的新互動式視窗或新的命令列介面 (CLI) 呼叫 CSI。除了將 C# 語言與命令列,更新 1 也導入了新的 C# 指令碼語言,傳統上儲存成 CSX 檔案。

在探究之前的新 C# 指令碼詳細資料,是了解目標案例。C# 指令碼是用來測試您的 C# 和.NET 片段,而不需要建立多個單元測試或主控台專案介入的工具。它提供快速設定命令列上的 LINQ 彙總的方法呼叫撰寫程式碼、 檢查.NET API 解壓縮檔案,或叫用 REST API,找出它會傳回,或它的運作方式的輕量的選項。它提供簡單的方式,了解 API,而不需要在 %TEMP%目錄中的另一個 CSPROJ 檔案的額外負荷。

C# REPL 命令列介面 (CSI。EXE)

做為學習 C# 本身,若要開始學習 C# REPL 最好介面是執行它,並開始執行命令。若要啟動它,從 Visual Studio 2015 開發人員命令提示字元執行命令 csi.exe 或使用完整路徑,也就是 C:\Program Files (x86)\MSBuild\14.0\bin\csi.exe。從該處開始執行 C# 陳述式所 [圖 1

[圖 1 CSI REPL 範例

C:\Program Files (x86)\Microsoft Visual Studio 14.0>csi
Microsoft (R) Visual C# Interactive Compiler version 1.1.0.51014
Copyright (C) Microsoft Corporation. All rights reserved.
Type "#help" for more information.
> System.Console.WriteLine("Hello! My name is Inigo Montoya");
Hello! My name is Inigo Montoya
> 
> ConsoleColor originalConsoleColor  = Console.ForegroundColor;
> try{
.  Console.ForegroundColor = ConsoleColor.Red;
.  Console.WriteLine("You killed my father. Prepare to die.");
. }
. finally
. {
.  Console.ForegroundColor = originalConsoleColor;
. }
You killed my father. Prepare to die.
> IEnumerable<Process> processes = Process.GetProcesses();
> using System.Collections.Generic;
> processes.Where(process => process.ProcessName.StartsWith("c") ).
.  Select(process => process.ProcessName ).Distinct()
DistinctIterator { "chrome", "csi", "cmd", "conhost", "csrss" }
> processes.First(process => process.ProcessName == "csi" ).MainModule.FileName
"C:\\Program Files (x86)\\MSBuild\\14.0\\bin\\csi.exe"
> $"The current directory is { Environment.CurrentDirectory }."
"The current directory is C:\\Program Files (x86)\\Microsoft Visual Studio 14.0."
>

第一件事来注意很明顯 — 就像 C#,雖然新的方言的 C# (但沒有在完整生產程式而非必要應急的原型中感謝典禮)。因此,可想而知,如果您想要呼叫靜態方法可以寫出完整的方法名稱,並傳遞引數括號內。和在 C# 中,您可以宣告的變數加型別,並選擇性地將其指派新值在宣告時。同樣地,您所預期,任何有效的方法本文的語法 — try/catch/finally 區塊,變數宣告、 lambda 運算式和 LINQ — 密切整合。

即使是在命令列上,其他 C# 功能,例如字串建構 (區分大小寫,字串常值和字串插補),會維護和。因此,您使用,或要輸出路徑,需要反斜線逸出使用 C# 逸出字元 ("\") 或字串常值,也是如此,csi.exe 路徑的輸出中的兩個反斜線。字串插補的運作方式,也為 「 目前目錄 」 範例中的一行 [圖 1 示範。

C# 指令碼可讓更多比陳述式和運算式,不過。您可以自訂型別宣告、 內嵌型別中繼資料透過屬性,並甚至簡化使用 C# 指令碼特定 declaratives 的詳細資訊。請考慮中的拼字檢查範例 [圖 2

[圖 2] 的 C# 指令碼類別拼字 (Spell.csx)

#r ".\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll"
#load "Mashape.csx"  // Sets a value for the string Mashape.Key
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
public class Spell
{
  [JsonProperty("original")]
  public string Original { get; set; }
  [JsonProperty("suggestion")]
  public string Suggestion { get; set; }
  [JsonProperty(PropertyName ="corrections")]
  private JObject InternalCorrections { get; set; }
  public IEnumerable<string> Corrections
  {
    get
    {
      if (!IsCorrect)
      {
        return InternalCorrections?[Original].Select(
          x => x.ToString()) ?? Enumerable.Empty<string>();
      }
      else return Enumerable.Empty<string>();
    }
  }
  public bool IsCorrect
  {
    get { return Original == Suggestion; }
  }
  static public bool Check(string word, out IEnumerable<string> corrections)
  {
    Task <Spell> taskCorrections = CheckAsync(word);
    corrections = taskCorrections.Result.Corrections;
    return taskCorrections.Result.IsCorrect;
  }
  static public async Task<Spell> CheckAsync(string word)
  {
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(
      $"https://montanaflynn-spellcheck.p.mashape.com/check/?text={ word }");
    request.Method = "POST";
    request.ContentType = "application/json";
    request.Headers = new WebHeaderCollection();
    // Mashape.Key is the string key available for
    // Mashape for the montaflynn API.
    request.Headers.Add("X-Mashape-Key", Mashape.Key);
    using (HttpWebResponse response =
      await request.GetResponseAsync() as HttpWebResponse)
    {
      if (response.StatusCode != HttpStatusCode.OK)
        throw new Exception(String.Format(
        "Server error (HTTP {0}: {1}).",
        response.StatusCode,
        response.StatusDescription));
      using(Stream stream = response.GetResponseStream())
      using(StreamReader streamReader = new StreamReader(stream))
      {
        string strsb = await streamReader.ReadToEndAsync();
        Spell spell = Newtonsoft.Json.JsonConvert.DeserializeObject<Spell>(strsb);
        // Assume spelling was only requested on first word.
        return spell;
      }
    }
  }
}

大多數的情況下,這是只在標準 C# 類別宣告。不過,有幾個特定的 C# 指令碼功能。首先,#r 指示詞是用來參考外部組件。在此情況下,參考是 Newtonsoft.Json.dll,可協助剖析 JSON 資料。請注意,不過,這是設計用來參考檔案的檔案系統中的指示詞。因此,它不需要不必要的典禮的反斜線逸出序列。

第二,就可以在整個清單,將它儲存為 CSX 檔案,然後 「 匯入 」 或 「 內嵌 」 檔案中,使用 #load Spell.csx C# REPL 視窗。#Load 指示詞可讓您納入其他指令碼檔案,如同所有 #load 檔案已都包含在相同的 「 專案 」 或 「 編譯 」。 將程式碼放到個別的 C# 指令碼檔案,可讓一種檔案重構,更重要的是,保存一段時間的 C# 指令碼的能力。

使用宣告是另一個 C# 語言功能允許在 C# 指令碼,其中一個, [圖 2 運用數次。請注意,如同 C# 中,使用以檔案為範圍的宣告。因此,如果您呼叫 #load Spell.csx 從 REPL 視窗時,它不會保存使用宣告式外 Spell.csx Newtonsoft.Json。換句話說,使用 Newtonsoft.Json 從 Spell.csx 內不會保存到 REPL 視窗而不需重新宣告明確在 REPL 視窗 (反之亦然)。請注意,也支援使用靜態宣告式 C# 6.0。因此,「 使用靜態 System.Console 」 宣告式就不需要前置詞的任何 System.Console 成員型別,以便 REPL 命令,例如 「 WriteLine ("Hello! 我的名字是 Inigo Montoya")。 」

請注意,在 C# 指令碼的其他建構包含屬性,用於非同步/等候陳述式、 屬性和函式宣告和支援的使用。由於後者的支援,甚至可以利用 await REPL 視窗中:

 

(await Spell.CheckAsync("entrepreneur")).IsCorrect

以下是有關 C# REPL 介面一些其他注意事項:

  • 您無法執行 csi.exe 從在 Windows PowerShell 整合式指令碼環境 (ISE),因為它需要直接主控台輸入,不支援從 Windows PowerShell ISE 的 「 模擬 」 的主控台視窗。(基於這個理由,請考慮新增不受支援的主控台應用程式清單 — $psUnsupportedConsoleApplications。)
  • 沒有 「 結束 」 或 「 結束 」 命令將 CSI 程式。相反地,您可以使用 Ctrl + C 以結束程式。
  • 命令歷程記錄會在 csi.exe 工作階段啟動從相同的 cmd.exe 或 PowerShell.exe 工作階段之間保存。例如,如果啟動 csi.exe、 叫用 Console.WriteLine("HelloWorld"),若要結束,請使用 Ctrl + C,然後再重新啟動 csi.exe,向上箭號會顯示前一個 Console.WriteLine("HelloWorld") 命令。結束 cmd.exe 視窗並重新啟動它將會清除歷程記錄。
  • Csi.exe 支援 #help REPL 命令,會顯示輸出所示 [圖 3
  • Csi.exe 支援許多命令列選項,如示 [圖 4

[圖 3 REPL #help 命令輸出

> #help
Keyboard shortcuts:
  Enter         If the current submission appears to be complete, evaluate it.
                Otherwise, insert a new line.
  Escape        Clear the current submission.
  UpArrow       Replace the current submission with a previous submission.
  DownArrow     Replace the current submission with a subsequent
                submission (after having previously navigated backward).
REPL commands:
  #help         Display help on available commands and key bindings.

[圖 4 Csi.exe 命令列選項

Microsoft (R) Visual C# Interactive Compiler version 1.1.0.51014
Copyright (C) Microsoft Corporation. All rights reserved.
Usage: csi [option] ... [script-file.csx] [script-argument] ...
Executes script-file.csx if specified, otherwise launches an interactive REPL (Read Eval Print Loop).
Options:
  /help       Display this usage message (alternative form: /?)
  /i          Drop to REPL after executing the specified script
  /r:<file>   Reference metadata from the specified assembly file
              (alternative form: /reference)
  /r:<file list> Reference metadata from the specified assembly files
                 (alternative form: /reference)
  /lib:<path list> List of directories where to look for libraries specified
                   by #r directive (alternative forms: /libPath /libPaths)
  /u:<namespace>   Define global namespace using
                   (alternative forms: /using, /usings, /import, /imports)
  @<file>     Read response file for more options
  --          Indicates that the remaining arguments should not be
              treated as options

如前所述,csi.exe 可讓您指定自訂您的命令視窗的預設 「 設定檔 」 檔案:

  • 若要清除 CSI 主控台,來叫用 Console.Clear。(請考慮使用靜態 System.Console 宣告加入支援直接叫用清除。)
  • 如果您輸入多行命令,並在先前的行犯了錯誤,您可以使用 Ctrl + Z 再按 Enter 以取消,並傳回空的命令提示字元,而不執行 (請注意,^ Z 會出現在主控台中)。

Visual Studio C# 互動式視窗

我之前提過,另外還有新的 Visual Studio C# 互動式視窗中更新 1 中所示 [圖 5。C# 互動式視窗啟動從 [檢視 |其他視窗 |C# 互動式功能表上,開啟額外的停駐視窗。就像 csi.exe] 視窗中,C# REPL 視窗但具有少數的新增功能。首先,它包含語法色彩編碼及 IntelliSense。同樣地,編譯發生即時,當您編輯,因此語法錯誤和類似會自動紅色波浪線底線。

宣告 C# 指令碼函式類別,使用 Visual Studio C# 互動式視窗之外
[圖 5 宣告 C# 指令碼使用 Visual Studio C# 互動式視窗類別之外的函式

使用 C# 互動式視窗的一般關聯當然是 [Visual Studio [即時運算] 和 [命令視窗。重疊時 — 畢竟,它們是兩個 REPL 視窗上,您可以針對執行.NET 陳述式,它們有明顯不同的用途。C# 即時運算視窗是直接繫結至偵錯您應用程式的內容,因此可讓您插入至內容的其他陳述式,檢查偵錯工作階段內的資料和甚至操作和更新的資料和偵錯內容。同樣地,[命令] 視窗會提供 CLI 管理 Visual Studio 中,包括執行各種功能表,但 [命令] 視窗,而不是自己的功能表。(執行命令 View.C#Interactive,比方說,開啟 [C# 互動式視窗。) 相反地,C# 互動式視窗可讓您執行 C# 中,包括上一節所述的 C# REPL 介面與相關的所有功能。不過,C# 互動式視窗並沒有偵錯內容的存取。它是完全獨立 C# 工作階段不使用 Visual Studio 偵錯內容或甚至控點。像 csi.exe,就可讓您快速 C# 和.NET 程式碼片段,而不必啟動另一個 Visual Studio 主控台或單元測試專案中確認您了解實驗環境。不過,而不必啟動另一個程式,C# 互動式視窗被裝載在 Visual Studio,在開發人員假設已存在於。

以下是關於 C# 互動式視窗一些注意事項:

  • C# 互動式視窗支援其他的複寫命令中 csi.exe,找不到數包括:
    • #cls / #clear 純文字編輯器] 視窗的內容
    • #reset 還原至其初始狀態的執行環境,同時維持命令歷程記錄
  • 鍵盤快速鍵是有點意外,#help 中當做輸出 [圖 6 顯示。

[圖 6 C# 互動式視窗的鍵盤快速鍵

輸入 如果目前提交似乎是完成時,進行評估。否則,插入新行。
Ctrl + Enter 目前的提交,評估目前的送出。
Shift Enter + 插入新行。
逸出 清除目前的送出。
Alt + UpArrow 取代先前提交的目前送出。
Alt + DownArrow 目前提交取代提出後續 (之後需要先前瀏覽向後)。
Ctrl + Alt + UpArrow 目前提交取代先前提交開頭為相同的文字。
Ctrl + Alt + DownArrow 取代目前提交開頭提出後續有相同的文字 (如果您之後需要先前瀏覽向後)。
UpArrow

在目前的送出作業結束時,取代先前提交目前送出。

在其他地方,移動游標同一行上。

DownArrow

在目前的送出作業結束時,取代目前提交提出後續 (之後需要先前瀏覽向後)。

在其他地方,將游標下移一行。

Ctrl + K、 Ctrl + Enter 貼上選取互動式緩衝區的結尾,請將保留在結尾輸入插入號。
Ctrl + E、 Ctrl + Enter 貼上和之前的任何暫止輸入選取範圍中執行互動式的緩衝區。
Ctrl+A 按第一次,請選取包含游標的送出。按第二次,在視窗中選取所有文字。

請務必注意 Alt + UpArrow/DownArrow 會叫用命令歷程記錄的鍵盤快速鍵。Microsoft 會選取這些簡單的 UpArrow/DownArrow 透過因為小組以符合標準的 Visual Studio 程式碼視窗的互動式視窗體驗。

  • C# 互動式視窗裝載在 Visual Studio 中,因為沒有使用 declaratives 或透過命令列中,匯入,因為沒有與 csi.exe 的參考傳遞相同的機會。相反地,C# 互動式視窗會從 C:\Program Files (x86) \Microsoft Visual Studio 14.0\Common7\IDE\PrivateAssemblies\CSharpInteractive.rsp,它會識別預設參考的組件載入預設的執行內容:
# This file contains command-line options that the C# REPL
# will process as part of every compilation, unless
# \"/noconfig\" option is specified in the reset command.
/r:System
/r:System.Core
/r:Microsoft.CSharp
/r:System.Data
/r:System.Data.DataSetExtensions
/r:System.Xml
/r:System.Xml.Linq
SeedUsings.csx

此外,CSharpInteractive.rsp 檔案會參考預設 C:\Program Files (x86) \Microsoft Visual Studio 14.0\Common7\IDE\PrivateAssemblies\SeedUsings.csx 檔案:

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

您可以分別使用 Console.WriteLine Environment.CurrentDirectory 而非完整 System.Console.WriteLine 和 System.Environ ment.CurrentDirectory,正是這兩個檔案的組合。此外,參考組件,例如 Microsoft.CSharp 可讓語言功能,例如動態沒有任何作業使用。(修改這些檔案是如何您變更您的 「 設定檔 」 或 「 偏好設定 」,讓工作階段之間保存的變更)。

限 C# 指令碼語法的詳細資訊

要牢記在心,有關 C# 指令碼語法的一件事是大多不一定要以標準的 C# 會成為 C# 指令碼中適當地選擇性。例如,之類的方法主體不需要出現在函式,而 C# 指令碼函式可以宣告類別範圍之外。中所示,您可以例如,定義 NuGet 安裝函式的直接在 [複寫] 視窗中出現 [圖 5。此外,或許有點令人驚訝,C# 指令碼並不支援宣告命名空間。比方說,您無法包裝文法命名空間中的拼字類別: 命名空間文法 {類別拼字 {}}。

請務必注意,您可以宣告相同建構 (變數、 類別、 函式等) 和上一次。最後一個宣告遮蔽任何先前的宣告。

要了解另一個重要的項目是命令結束分號的行為。陳述式 (例如,變數指派) 需要分號。而不需要分號 REPL 視窗將會繼續提示 (透過句號) 的更多的輸入輸入分號。相反地,運算式中,將會執行而不需要分號。因此,System.Diagnostics.Process.Start("notepad") 會啟動 [記事本],即使沒有結束分號。此外,由於啟動方法呼叫會傳回處理程序,運算式的字串輸出會出現在命令列: [System.Diagnostics.Process ([記事本])]。關閉使用分號的運算式,不過,隱藏輸出。叫用開始,以結束分號,因此,不會產生任何輸出,即使仍會啟動 [記事本]。當然,Console.WriteLine ("可能要花費奇蹟。 」)。仍然會輸出文字,即使使用分號,因為該方法本身會顯示輸出 (不從方法傳回)。

運算式與陳述式之間的差異可能會導致細微差異有時候。例如,陳述式字串文字 ="完美 b 的不足。...」;將會導致任何輸出,但文字 ="停止該 rhyming 和我是說真的"會傳回已指派的字串 (因為作業會傳回指定的值,而且沒有分號來隱藏輸出)。

C# 指令碼指示詞參考其他組件 (#r) 和匯入現有 C# 指令碼 (#load) 是很棒的新增項目。(其中一個可以想像複雜的解決方案,以達到相同的動作不會那麼俐落的 project.json 檔案一樣)。 不幸的是,在撰寫本文時,不支援 NuGet 封裝。若要從 NuGet 參照的檔案需要安裝套件的目錄,然後參考特定 DLL 透過 #r 指示詞。(Microsoft 可確保我這即將。)

請注意,在此階段指示詞參考特定檔案。您比方說,不能在指示詞中指定的變數。雖然您會期盼下列指示詞,它會防止以動態方式載入的組件的可能性。例如,您就能夠以動態方式叫用 nuget.exe 的 「 安裝 」 來擷取組件 (再次看到 [圖 5)。這麼做,不過,不允許您 CSX 檔案,以動態繫結至擷取的 NuGet 封裝,因為沒有任何方法以動態方式將組件路徑傳遞至 #r 指示詞。

C# CLI

我承認,我有又愛又恨使用 Windows PowerShell。我喜歡在命令列上的包含 Microsoft.NET Framework 和可能的傳遞.NET 物件之間管道,而不是傳統的文字的前面 Cli 很多。話雖如此,就是 C# 語言中,我遊擊隊 — 我喜歡它兼顧從容性和電源。(至今,我仍然印象深刻造就 LINQ 的語言擴充功能。) 因此,目的在於,可能會有 Windows PowerShell.NET C# 語言的簡潔結合各種想法,我來取代接近 C# REPL 適用於 Windows PowerShell。啟動後 csi.exe,我會立即嘗試類似 cd、 dir、 ls、 pwd、 cls、 別名和類似的命令。您只要知道就說,我曾失望因為沒有任何工作。仔細思量經驗,並討論使用 C# 小組之後, 我發現,取代 Windows PowerShell 不小組為何是著重在第 1 版。此外,它是.NET Framework,因此,它支援擴充性加入自己的函式,如先前的命令以及甚至是藉由更新 Roslyn 上的 C# 指令碼實作。立即設定有關定義這類命令的函式。啟動這類程式庫是可供下載 GitHub 上的 github.com/CSScriptEx

對於尋求更具功能性 C# CLI 現在支援現成的先前的命令清單,請在 scriptcs.net 考慮 ScriptCS (也在 GitHub 上 github.com/scriptcs)。它,也會利用 Roslyn,並包含別名、 cd、 清除、 cwd、 結束、 說明、 安裝、 參考、 重設、 scriptpacks、 using 和變數。請注意,透過 ScriptCS,命令前置詞今天是冒號 (例如: 重設) 而不是數字符號 (如 #reset)。好處是,ScriptCS 也增加了支援 CSX 檔案形式的顏色標示和 IntelliSense,Visual Studio 程式碼。

總結

至少現在,C# REPL 介面的目的是未將 Windows PowerShell 或甚至是 cmd.exe。在開始這類方法會導致有多麼失望。相反地,我們建議您方法 C# 指令碼和 REPL Cli 輕量型取代 Visual Studio |新的專案: UnitTestProject105 或同樣地 purposed 的 dotnetfiddle.net。這些是 C# 和.NET 目標方法,以提高您的語言和.NET Api。C# REPL 提供一種簡短的程式碼片段或程式單位,直到它們準備好要剪下並貼到較大的程式,可以 noodle 撰寫程式碼。它可讓您撰寫更廣泛的指令碼在撰寫程式碼,其語法驗證 (即使是少許之類的事情大小寫不相符),而不是強迫您執行指令碼,只探索您輸入錯誤項目。一旦您了解它的位置、 C# 指令碼和其互動式視窗成為一種樂趣,此工具您一直在找從 1.0 版。

很有趣自行 REPL C# 和 C# 指令碼時,請考慮它們也提供以在您的應用程式擴充架構 — à la Visual Basic for Applications (VBA)。有了互動式視窗和 C# 指令碼支援,您可以想像一個 — 不太遠 — 您可以將.NET 「 巨集 」 到您的應用程式一次 — 而不會發明自訂語言,剖析器和編輯器。現在,那就是傳統的 COM 功能值得手抄本無太快。


Mark Michaelis是的 IntelliTect,他擔任其技術架構設計人員和培訓講師的創辦人。近二十他 Microsoft MVP 和 Microsoft 區域經理自已 2007年。Michaelis 服務於多個 Microsoft 軟體設計檢閱小組,包括 C#、 Microsoft Azure、 SharePoint 和 Visual Studio ALM。他開發人員會議上發表演說,並且已撰寫許多本書,包括他最新,「 基本 C# 6.0 (第 5 版) 」 (itl.tc/EssentialCSharp)。在 Facebook 上連絡他 facebook.com/Mark.Michaelis, ,他的部落格上 IntelliTect.com/Mark, ,在 Twitter 上: @markmichaelis 或透過電子郵件地 mark@IntelliTect.com

感謝以下的微軟技術專家對本文的審閱: Kevin Bost 和 Kasey Uhlenhuth