January 2016

Volume 31 Number 1

Essential .NET - C# スクリプト

Mark Michaelis | January 2016

Mark MichaelisVisual Studio 2015 Update 1 (以下「Update 1」) がリリースされ、新しい C# REPL (Read-Evakuate-Print-Loop) が Visual Studio 2015 内の新しいインタラクティブ ウィンドウ、または CSI という新しいコマンドライン インターフェイス (CLI) として利用できるようになります。Update 1 では、コマンドラインで C# 言語を利用できるようになっただけでなく、新しい C# スクリプト言語も導入されます。この C# スクリプト言語は、以前 CSX ファイルに保存していたものです。

新しい C# スクリプトを詳しく説明する前に、対象となるシナリオを理解しておかなければなりません。C# スクリプトとは、単体テスト プロジェクトやコンソール プロジェクトをいくつも作成することなく、C# や .NET のスニペットをテストするためのツールです。これにより、コマンドラインでの LINQ 集計メソッドの呼び出し、解凍中のファイルに対する .NET API のチェック、REST API の戻り値やしくみの調査などを手早くコーディングするための簡易オプションが提供されます。つまり、自身の %TEMP% ディレクトリ内にもう 1 つ別の CSPROJ ファイルを用意するようなオーバーヘッドを伴わずに、API の調査や学習を簡単に実行できるようになります。

C# REPL コマンドライン インターフェイス (CSI.EXE)

C# 自体を学習するのと同じように、C# REPL インターフェイスを学習するのに最適な方法は、C# REPL インターフェイスを起動して、コマンドを実行してみることです。C# REPL インターフェイスを起動するには、Visual Studio 2015 開発者コマンド プロンプトから csi.exe コマンドを実行するか、フルパス (C:\Program Files (x86)\MSBuild\14.0\bin\csi.exe) を指定して実行します。起動したインターフェイス ウィンドウから、図 1 に示すような C# ステートメントを実行します。

図 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 ブロック、変数宣言、ラムダ式、LINQ) はすべて問題なく機能します。

コマンドラインでも、文字列の構成 (大文字小文字の区別、文字列リテラル、文字列の補間) など、他の C# 機能がそのまま使えます。したがって、パスを使用または出力するときは、円記号 (バックスラッシュ) を C# のエスケープ文字 ("\") または文字列リテラルを使用してエスケープする必要があります。つまり、上記の csi.exe のパスの出力で行っているように、円記号を 2 つ使用します。また、図 1 の "current directory" サンプル行のように、文字列の補間も機能します。

C# スクリプトでは、ステートメントや式以外も使用できます。カスタム型の宣言、属性による型メタデータの埋め込み、 C# スクリプト固有の using 宣言による冗長性の解消が可能です。図 2 に示すスペル チェックのサンプルを考えてみます。

図 2 C# スクリプトの Spell クラス (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# 言語機能に using 宣言があります。図 2 でも複数利用しています。C# と同様、using 宣言のスコープは当該ファイルに限定されます。つまり、REPL ウィンドウから #load Spell.csx を呼び出した場合、Spell.csx の外部では using Newtonsoft.Json 宣言が有効ではありません。Spell.csx に含まれる using Newtonsoft.Json 宣言は、REPL ウィンドウでもう一度明示的に宣言しない限り、REPL ウィンドウでは有効になりません (逆も同じです)。C# 6.0 の using static 宣言もサポートされます。したがって、using static System.Console を宣言すると、System.Console のメンバーに型プレフィックスを付けることなく、WriteLine("Hello! My name is Inigo Montoya") のような REPL コマンドを利用できるようになります。

他にも C# スクリプトの注目すべきコンストラクトとして、属性の使用、using ステートメント、プロパティと関数の宣言、async/await のサポートなどがあります。async/await のサポートにより、REPL ウィンドウで結果を待機することも可能になります。

 

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

C# REPL インターフェイスに関する注意点を一部以下に示しておきます。

  • Windows PowerShell Integrated Scripting Environment (ISE) 内から csi.exe を実行することはできません。これは直接コンソール入力が必要になるためです。Windows PowerShell ISE が "シミュレーションしている" コンソール ウィンドウからの直接コンソール入力はサポートされません (そのため、サポート対象外のコンソール アプリケーションのリスト $psUnsupportedConsoleApplications への追加を検討してください)。
  • CSI プログラムを終了する "exit" コマンドや "quit" コマンドがありません。CSI プログラムを終了する場合は、Ctrl キーを押しながら C キーを押します。
  • コマンド履歴が保持されるのは、cmd.exe または PowerShell.exe の同じセッションから起動された csi.exe セッションの間のみです。たとえば、csi.exe を起動し、Console.WriteLine("HelloWorld") を呼び出してから、Ctrl キーを押しながら C キーを押して csi.exe を終了します。その状態で、もう一度 csi.exe を起動すると、上矢印キーによって直前の Console.WriteLine("HelloWorld") コマンドが表示されます。ただし、cmd.exe ウィンドウを閉じてから、ウィンドウを再起動すると、履歴はクリアされます。
  • csi.exe は REPL コマンド #help をサポートします (図 3 参照)。
  • また、多くのコマンドライン オプションもサポートします (図 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 では、既定の "profile" ファイルを指定して、コマンド ウィンドウをカスタマイズすることができます。

  • CSI コンソールをクリアする場合は、Console.Clear を呼び出します (Clear だけを呼び出せるように、using static System.Console 宣言の使用を検討してください)。
  • 複数行にも及ぶコマンドを入力している最中に前に入力した行でエラーが発生した場合は、Ctrl キーを押しながら Z キーを押してから Enter キーを押すと、そのコマンドを実行しないでキャンセルすることができます。その結果、空のコマンド プロンプトに戻ります (コンソールには ^Z が表示されます)。

Visual Studio C# インタラクティブ ウィンドウ

最初に触れたように、Update 1 には Visual Studio C# インタラクティブ ウィンドウが新たに用意されています (図 5 参照)。C# インタラクティブ ウィンドウは、[表示] をクリックし、[その他のウィンドウ] をポイントして、[C# インタラクティブ] をクリックすると、ドッキング ウィンドウとして追加表示されます。csi.exe ウィンドウと同様 C# REPL ウィンドウですが、いくつか機能が追加されています。まず、構文の色分け表示と IntelliSense が含まれています。同様に、コンパイルが編集時にリアル タイムで行われるため、構文エラーの類には該当箇所の下に赤い波線が引かれます。

Visual Studio C# インタラクティブ ウィンドウを使用したクラス外での C# スクリプト関数の宣言
図 5 Visual Studio C# インタラクティブ ウィンドウを使用したクラス外での C# スクリプト関数の宣言

C# インタラクティブ ウィンドウとつながりがあるのは、当然、Visual Studio のイミディエイト ウィンドウとコマンド ウィンドウです。結局どちらも .NET ステートメントを実行できる REPL ウィンドウなので重複する部分はありますが、それぞれの目的は大きく異なります。C# イミディエイト ウィンドウは、アプリケーションのデバッグ コンテキストに直接結び付いています。そのため、デバッグ コンテキストへの新たなステートメントの挿入や、デバッグ セッション内でのデータのテスト、データやデバッグ コンテキストの操作や更新も可能です。コマンド ウィンドウは Visual Studio を操作するための CLI を提供します。これにより、さまざまなメニューの実行などを、メニュー自体からではなく、コマンド ウィンドウから実行できるようになります (たとえば、View.C#Interactive コマンドを実行すると、C# インタラクティブ ウィンドウが開きます)。これらとは異なり、C# インタラクティブ ウィンドウでは、前述の C# REPL インターフェイスに関連する機能すべてを含めて、C# を実行することができます。ただし、C# インタラクティブ ウィンドウからデバッグ コンテキストにアクセスすることはできません。C# インタラクティブ ウィンドウは、デバッグ コンテキストや Visual Studio でさえ操作する必要のない、完全に独立した C# セッションです。csi.exe と同様、C# や .NET のスニペットを試して理解度を確かめるための環境で、Visual Studio コンソールや単体テスト プロジェクトを別途開始する必要がありません。別のプログラムを起動する必要はありませんが、C# インタラクティブ ウィンドウは Visual Studio 内でホストされます。ホストするのは、おそらく開発者が既に操作している Visual Studio です。

C# インタラクティブ ウィンドウに関する注意点を一部以下に示しておきます。

  • C# インタラクティブ ウィンドウは、csi.exe にはない REPL コマンドを追加でサポートします。以下にその例を示します。
    • #cls/#clear: 編集ウィンドウの内容をクリアします。
    • #reset: コマンド履歴を保持した状態で実行環境を初期状態にリセットします。
  • やや想定外ですが、キーボード ショートカットがあります (図 6 の #help 出力参照)。

図 6 C# インタラクティブ ウィンドウのキーボード ショートカット

Enter 現在の送信が完了している場合は、評価します。完了していない場合には、新しい行を挿入します。
Ctrl+Enter       現在の送信内で、現在の送信を評価します。
Shift+Enter      新しい行を挿入します。
Escape 現在の送信をクリアします。
Alt+UpArrow      現在の送信を前の送信に置き換えます。
Alt+DownArrow 現在の送信を次の送信に置き換えます (前に戻っている場合)。
Ctrl+Alt+UpArrow 現在の送信を、同じテキストで始まる前の送信に置き換えます。
Ctrl+Alt+DownArrow 現在の送信を、同じテキストで始まる次の送信に置き換えます (前に戻っている場合)。
UpArrow

現在の送信の最後で、現在の送信を前の送信に置き換えます。

他の場所では、カーソルを 1 行上に移動します。

DownArrow

現在の送信の最後で、現在の送信を次の送信に置き換えます (前に戻っている場合)。

他の場所では、カーソルを 1 行下に移動します。

Ctrl+K, Ctrl+Enter 対話型バッファーの最後に選択内容を貼り付け、キャレットを入力の末尾に付けます。
Ctrl+E, Ctrl+Enter 対話型バッファー内の保留中の入力の前に、選択内容を貼り付けて実行します。
Ctrl+A 最初に押すと、カーソルの置かれた送信が選択されます。もう一度押すと、ウィンドウ内のすべてのテキストが選択されます。

Alt + ↑/↓ キーは、コマンド履歴を呼び出すキーボード ショートカットです。マイクロソフトは、インタラクティブ ウィンドウのエクスペリエンスと Visual Studio の標準コード ウィンドウのエクスペリエンスが一致するように、単なる ↑/↓ キーではなく、このような組み合わせを採用しています。

  • C# インタラクティブ ウィンドウは Visual Studio 内でホストされるため、csi.exe とは違って、コマンドライン経由で参照、using 宣言、またはインポートを受け渡す機会がありません。代わりに、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;

この 2 つのファイルの組み合わせにより、完全修飾形式の System.Console.WriteLine や System.Environment.CurrentDirectory ではなく、Console.WriteLine や Environment.CurrentDirectory が使えるようになります。また、Microsoft.CSharp などのアセンブリを参照すれば、dynamic のような言語機能も使用可能になります (これらのファイルを変更することで、"プロファイル" や "ユーザー設定" への変更がセッション間で保持されます)。

C# スクリプト構文の詳細

C# スクリプトの構文で留意する点の 1 つは、標準の C# で重要とされている形式部分の大半が、C# スクリプトでは適宜省略可能になることです。たとえば、メソッドの本文などが関数内に存在する必要はなく、C# スクリプトの関数をクラスの境界外で宣言してもかまいません。たとえば、REPL ウィンドウで NuGet の Install 関数を直接定義することができます (図 5 参照)。少し驚きますが、C# スクリプトは名前空間の宣言をサポートしません。たとえば、namespace Grammar { class Spell {} } のように、Spell クラスを Grammar 名前空間にラップすることはできません。

同じコンストラクト (変数、クラス、関数など) を何度でも宣言できます。前の宣言は最後の宣言に置き換えられます。

他にも、コマンド末尾のセミコロンの動作にも注意が必要です。ステートメント (変数、代入てなど) にはセミコロンが必要です。セミコロンがないと、REPL ウィンドウはセミコロンが入力されるまで (ピリオド用いて) 入力を要求し続けます。一方、式はセミコロンを入力しなくても実行されます。そのため、System.Diagnostics.Process.Start("notepad") は、末尾にセミコロンがなくても、メモ帳を起動します。さらに、Start メソッド呼び出しはプロセスを返すので、コマンドラインには式の文字列出力 [System.Diagnostics.Process (Notepad)] が表示されます。ただし、式をセミコロンで完結すると、この出力は表示されなくなります。つまり、末尾にセミコロンを付けて Start を呼び出すと、メモ帳は起動されても出力は行われません。もちろん、Console.WriteLine("It would take a miracle."); では、(メソッドが文字列を返すのではなく) このメソッド自体が出力を表示するので、セミコロンを付けてもテキストが出力されます。

式とステートメントにわずかな違いがでることもあります。たとえば、string text = "There’s a shortage of perfect b...."; というステートメントの場合、出力は表示されませんが、text="Stop that rhyming and I mean it" という式の場合、(この代入は代入後の値を返し、出力を抑制するセミコロンを付けていないため) 代入後の文字列が返されます。

追加のアセンブリ (#r) の参照や、既存の C# スクリプト (#load) のインポートを指示する C# スクリプトのディレクティブは、すばらしい追加機能です (同じ目的を達成できても、それほど洗練されていない project.json ファイルのような複雑なソリューションもあります)。残念ながら、本稿執筆時点では、NuGet パッケージはサポートされていません。NuGet のファイルを参照するには、NuGet パッケージをディレクトリにインストールしてから、#r ディレクティブを使って具体的な DLL を参照する必要があります (NuGet パッケージをサポート予定だという確約をマイクロソフトから得ています)。

現時点では、ディレクティブは特定のファイルを参照します。たとえば、ディレクティブで変数を指定することはできません。ディレクティブで変数を指定できるようになることを期待しているかもしれませんが、その結果アセンブリを動的に読み込むことができなくなります。たとえば、nuget.exe install を動的に呼び出して、アセンブリを抽出することができます (ここでも図 5 を参照)。ただし、このようにする場合、アセンブリのパスを #r ディレクティブに動的に渡す方法がないため、CSX ファイルは抽出後の NuGet パッケージを動的にバインドすることができません。

C# CLI

個人的には、Windows PowerShell に対して愛着もあり、嫌悪もあります。以前のように多数の CLI を用いる従来のテキストよりも、コマンドラインで Microsoft .NET Framework を利用できる便利さと、パイプを通じて .NET のオブジェクトを渡す機能に愛着を持っています。とは言うものの、C# 言語の洗練さと機能を好んでいるため、C# 言語にも愛着があります (今でも、LINQ を可能にする C# 言語の拡張機能にまだ感銘を受けています)。そのため、広大な Windows PowerShell を洗練された C# 言語と組み合わせることができるという考えから、Windows PowerShell の代わりとして C# REPL にアプローチしました。csi.exe を起動してすぐに、cd、dir、ls、pwd、cls、alias などのコマンドを試してみました。しかし、このようなコマンドはいずれも機能せず、失望しました。このエクスペリエンスについて思いを巡らせ、C# チームと議論を持ちかけたところ、チームは、バージョン 1 で Windows PowerShell の代わりになることには力を入れていなかったことがわかりました。また、これは .NET Framework です。したがって、拡張性をサポートするには、先行するコマンドに独自の関数を追加し、かつ Roslyn で C# スクリプトの実装を更新する必要があります。そこで、このようなコマンド用の関数を定義することにすぐに着手しました。このようなライブラリの冒頭部分は、GitHub (github.com/CSScriptEx、英語) からダウンロードできます。

上記で示したコマンドを既定でサポートする、豊富な機能を備えた C# CLI をお探しの方は、scriptcs.net (GitHub github.com/scriptcs、英語) の ScriptCS をご検討ください。こちらは Roslyn も利用でき、alias、cd、clear、cwd、exit、help、install、references、reset、scriptpacks、usings、vars なども実行できます。ScriptCS のコマンド プレフィックスは、現在 (#reset のような) シャープ記号ではなく、(:reset のような) コロンです。さらに、CSX ファイルのサポートを、構文の色分け表示と IntelliSense の形式で Visual Studio Code に追加します。

まとめ

少なくとも現時点では、C# REPL インターフェースは、Windows PowerShell や cmd.exe の代わりになることが目的ではありません。このように考えてアプローチすると、失望することになります。むしろ、Visual Studio の [新しいプロジェクト] (UnitTestProject105 や同様の目的を持つ dotnetfiddle.net) に代わるものとして、C# スクリプトと REPL CLI に接することをお勧めします。どちらも、C# と .NET を対象としたツールで、C# 言語や .NET API に対する理解を深めるための手段です。C# REPL は、簡単なコード スニペットやプログラム単位をコーディングする手段を提供します。こうして確かめたコードは、切り取ってより大きなプログラムに貼り付けることができます。その結果、構文の検証を終えた幅広いスクリプトをコーディングできるようになります (大文字と小文字の不一致のようなささいなことも検証できます)。長々とスクリプトをコーディングし、実行してみたらタイプミスが見つかったというような結果に陥ることがなくなります。C# REPL の目的を理解すれば、バージョン 1.0 でも C# スクリプトと C# インタラクティブ ウィンドウに満足できるようになります。

C# REPL や C# スクリプト自体も興味深いものですが、かつての Visual Basic for Applications (VBA) のように、独自のアプリケーション用の拡張フレームワークになる足がかりも提供しています。インタラクティブ ウィンドウと C# スクリプトのサポートにより、カスタム言語、パーサー、エディターなどを考案する必要なく、.NET "マクロ" を独自のアプリケーションに追加できるような世界を想像してください。昔の COM 機能を現代によみがえらせ、価値をもたらすことができるようになります。


Mark Michaelis は、IntelliTect の創設者で、チーフ テクニカル アーキテクトとトレーナーを務めています。20 年にわたって Microsoft MVP の一員であり、2007 年から Microsoft Regional Director を務めています。また、C#、Microsoft Azure、SharePoint、Visual Studio ALM など、マイクロソフト ソフトウェアの設計レビュー チームにもいくつか所属しています。開発者を対象としたカンファレンスで講演を行い、多数の書籍を執筆しています。最近では、『Essential C# 6.0 (5th Edition)』(Addison-Wesley Professional、2015 年) を執筆しています (itl.tc/EssentialCSharp、英語)。連絡先の Facebook は facebook.com/Mark.Michaelis (英語)、ブログは IntelliTect.com/Mark (英語)、Twitter は @markmichaelis (英語)、メールは mark@IntelliTect.com (英語のみ) です。

この記事のレビューに協力してくれたマイクロソフト技術スタッフの Kevin Bost および Kasey Uhlenhuth に心より感謝いたします。