ImmutableArrays 用の Roslyn アナライザーとコード対応ライブラリ
.NET Compiler Platform ("Roslyn") は、コード対応ライブラリの構築に役立ちます。 コード対応ライブラリには、ライブラリを最適な方法で使用したり、エラーを回避したりするのに役立つツール (Roslyn アナライザー) を使用できる機能が用意されています。 このトピックでは、System.Collections.Immutable NuGet パッケージを使用するときに一般的なエラーをキャッチする実際の Roslyn アナライザーを構築する方法について説明します。 この例では、アナライザーによって検出されたコードの問題に対してコード修正を提供する方法も示します。 Visual Studio 電球 UI にコード修正プログラムが表示され、コードの修正プログラムを自動的に適用できます。
作業の開始
この例をビルドするには、次のものが必要です。
- Visual Studio 2015 (Express Edition ではありません) 以降のバージョン。 Visual Studio Community Edition
無料で使用できます - Visual Studio SDK。 また、Visual Studio をインストールするときに、
Common Tools の下にある Visual Studio Extensibility Toolsを確認して、SDK を同時にインストールすることもできます。 Visual Studio を既にインストールしている場合は、メイン メニューの [ファイル] [新しい プロジェクト ] に移動し、左側のナビゲーション ウィンドウで [C#] を選択し、[拡張 を選択して、この SDK をインストールすることもできます。 [Visual Studio Extensibility Tools をインストール] 階層リンク プロジェクト テンプレートを選ぶと、SDK をダウンロードしてインストールするように求められます。 - .NET Compiler Platform ("Roslyn") SDK。 この SDK をインストールするには、メイン メニューの
[ファイル] [新しい プロジェクト ] に移動し、左側のナビゲーション ウィンドウで [C#] を選択し、[機能拡張 選択します。 [.NET Compiler Platform SDKのダウンロード] を選択すると、階層リンク プロジェクト テンプレートをダウンロードしてインストールするように求められます。 この SDK には、Roslyn Syntax Visualizer が含まれています。 この便利なツールは、アナライザーで検索する必要があるコード モデルの種類を把握するのに役立ちます。 アナライザー インフラストラクチャは特定のコード モデルの種類に対してコードを呼び出します。そのため、コードは必要なときにのみ実行され、関連するコードの分析にのみ集中できます。
何がそんなに問題ですか。
ImmutableArray (たとえば、System.Collections.Immutable.ImmutableArray<T>) サポートを備えたライブラリを提供するとします。 C# 開発者には、.NET 配列に関する多くの経験があります。 ただし、実装で使用される ImmutableArrays と最適化手法の性質により、C# 開発者の直感により、ライブラリのユーザーは、次に説明するように壊れたコードを記述します。 さらに、ユーザーには実行時までエラーが表示されません。これは、Visual Studio と .NET で使用される品質エクスペリエンスではありません。
ユーザーは、次のようなコードの記述に慣れている。
var a1 = new int[0];
Console.WriteLine("a1.Length = {0}", a1.Length);
var a2 = new int[] { 1, 2, 3, 4, 5 };
Console.WriteLine("a2.Length = {0}", a2.Length);
後続のコード行を入力する空の配列を作成し、コレクション初期化子構文を使用することは、C# 開発者にとってよく知られています。 ただし、ImmutableArray に対して同じコードを記述すると、実行時にクラッシュします。
var b1 = new ImmutableArray<int>();
Console.WriteLine("b1.Length = {0}", b1.Length);
var b2 = new ImmutableArray<int> { 1, 2, 3, 4, 5 };
Console.WriteLine("b2.Length = {0}", b2.Length);
最初のエラーは、基になるデータ ストレージをラップするために構造体を使用する ImmutableArray 実装が原因です。 default(T)
式がゼロまたは null のすべてのメンバーを持つ構造体を返すことができるように、構造体にはパラメーターなしのコンストラクターが必要です。 コードが b1.Length
にアクセスすると、ImmutableArray 構造体に基になるストレージ配列がないため、実行時の null 逆参照エラーが発生します。 空の ImmutableArray を作成する正しい方法は ImmutableArray<int>.Empty
です。
コレクション初期化子のエラーは、ImmutableArray.Add
メソッドが呼び出すたびに新しいインスタンスを返すからです。 ImmutableArrays は変更されないため、新しい要素を追加すると、新しい ImmutableArray オブジェクトが返されます (パフォーマンス上の理由から、以前に既存の ImmutableArray とストレージを共有する可能性があります)。 b2
は、Add()
を 5 回呼び出す前に最初の ImmutableArray を指しているため、b2
は既定の ImmutableArray です。 その Length を呼び出すと、null 逆参照エラーでクラッシュします。 手動で Add を呼び出さずに ImmutableArray を初期化する正しい方法は、ImmutableArray.CreateRange(new int[] {1, 2, 3, 4, 5})
を使用する方法です。
アナライザーをトリガーする関連する構文ノードの種類を検索する
アナライザーの構築を開始するには、まず、検索する必要がある SyntaxNode の種類を調べてください。 メニューの [表示]>[その他のウィンドウ]>[Roslyn Syntax Visualizer] から Syntax Visualizer を起動します。
b1
を宣言する行にエディターのキャレットを配置します。 構文ビジュアライザーで、あなたが構文ツリーの LocalDeclarationStatement
ノードにいることが示されています。 このノードには VariableDeclaration
があり、VariableDeclarator
があり、EqualsValueClause
があり、最後に ObjectCreationExpression
があります。 ノードの構文ビジュアライザー ツリーをクリックすると、エディター ウィンドウの構文が強調表示され、そのノードによって表されるコードが表示されます。 SyntaxNode サブタイプの名前は、C# 文法で使用される名前と一致します。
アナライザー プロジェクトを作成する
メイン メニューから [ファイル]>[新規]>[プロジェクト] を選択します。 [新しいプロジェクト] ダイアログで、左のナビゲーションバーの[C# プロジェクト]の下にある[機能拡張]を選択し、右側のウィンドウで[Analyzer with Code Fix]プロジェクトテンプレートを選択します。 名前を入力し、ダイアログを確認します。
テンプレートによって DiagnosticAnalyzer.cs ファイルが開きます。 そのエディター バッファー タブを選択します。このファイルには、DiagnosticAnalyzer
(Roslyn API 型) から派生したアナライザー クラス (プロジェクトに指定した名前から形成されます) があります。 新しいクラスには、アナライザーが C# 言語に関連していることを宣言する DiagnosticAnalyzerAttribute
があり、コンパイラがアナライザーを検出して読み込みます。
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public class ImmutableArrayAnalyzer : DiagnosticAnalyzer
{}
C# コードを対象とする Visual Basic を使用してアナライザーを実装できます。その逆も同様です。 DiagnosticAnalyzerAttribute では、アナライザーが 1 つの言語または両方を対象とするかどうかを選択する方が重要です。 言語の詳細なモデリングを必要とするより高度なアナライザーは、1 つの言語のみを対象とすることができます。 たとえば、アナライザーで型名またはパブリック メンバー名のみをチェックする場合、Visual Basic と C# 全体で Roslyn が提供する共通言語モデルを使用できる場合があります。 たとえば、FxCop は、クラスが ISerializableを実装することを警告しますが、クラスには言語に依存しない SerializableAttribute 属性はなく、Visual Basic と C# の両方のコードで機能します。
アナライザーを初期化する
Initialize
メソッドを表示するには、DiagnosticAnalyzer
クラスで少し下にスクロールします。 コンパイラは、アナライザーをアクティブ化するときにこのメソッドを呼び出します。 このメソッドは、アナライザーがコンテキスト情報を取得し、分析するコードの種類のイベントのコールバックを登録できるようにする AnalysisContext
オブジェクトを受け取ります。
public override void Initialize(AnalysisContext context) {}
このメソッドで新しい行を開き、「context.」と入力して、IntelliSense の入力候補一覧を表示します。 完了リストには、さまざまな種類のイベントを処理する Register...
メソッドが多数あります。 たとえば、1 つ目の RegisterCodeBlockAction
は、ブロックのコードにコールバックします。これは通常、中かっこの間のコードです。 ブロックに登録すると、フィールドの初期化子、属性に指定された値、または省略可能なパラメーターの値のコードも呼び出されます。
別の例として、RegisterCompilationStartAction
コンパイルの開始時にコードを呼び出します。これは、さまざまな場所で状態を収集する必要がある場合に便利です。 たとえば、使用されているすべてのシンボルを収集するデータ構造を作成できます。また、アナライザーが何らかの構文またはシンボルに対して呼び出されるたびに、データ構造内の各場所に関する情報を保存できます。 コンパイルの終了が原因で呼び出された場合は、保存したすべての場所を分析して、たとえば、各 using
ステートメントからコードで使用されるシンボルを報告できます。
構文ビジュアライザーを使用して、コンパイラが ObjectCreationExpression を処理するときに呼び出す必要があることを学習しました。 コールバックを設定するには、次のコードを使用します。
context.RegisterSyntaxNodeAction(c => AnalyzeObjectCreation(c),
SyntaxKind.ObjectCreationExpression);
構文ノードに登録し、オブジェクト作成構文ノードのみをフィルター処理します。 慣例により、アナライザー作成者はアクションを登録するときにラムダを使用します。これは、アナライザーをステートレスに保つのに役立ちます。 AnalyzeObjectCreation
メソッドを作成するには、Visual Studio 機能 [Generate From Usage]\(使用状況から生成\) を使用できます。 これにより、コンテキスト パラメーターの正しい型も生成されます。
アナライザーのユーザーのプロパティを設定する
アナライザーが Visual Studio UI に適切に表示されるように、次のコード行を探して変更し、アナライザーを識別します。
internal const string Category = "Naming";
"Naming"
を "API Guidance"
に変更します。
次に、ソリューション エクスプローラーを使用して、プロジェクト内の Resources.resx ファイルを見つけて開きます。 アナライザー、タイトルなどの説明を入力できます。現時点では、これらのすべての値を "Don't use ImmutableArray<T> constructor"
に変更できます。 文字列の書式設定引数を文字列 ({0}、{1}など) に配置できます。後で Diagnostic.Create()
を呼び出すときに、渡される引数の params
配列を指定できます。
オブジェクト作成式を分析する
AnalyzeObjectCreation
メソッドは、コード アナライザー フレームワークによって提供される異なる種類のコンテキストを受け取ります。 Initialize
メソッドの AnalysisContext
を使用すると、アクション コールバックを登録してアナライザーを設定できます。 たとえば、SyntaxNodeAnalysisContext
には CancellationToken
があり、これを渡すことができます。 ユーザーがエディターで入力を開始すると、Roslyn は実行中のアナライザーを取り消して作業を保存し、パフォーマンスを向上させます。 別の例として、このコンテキストには、オブジェクト作成構文ノードを返す Node プロパティがあります。
ノードを取得します。これは、構文ノード アクションをフィルター処理した型であると想定できます。
var objectCreation = (ObjectCreationExpressionSyntax)context.Node;
初めてアナライザーを使用して Visual Studio を起動する
アナライザーをビルドして実行して Visual Studio を起動します (F5キーを押します)。 ソリューション エクスプローラー のスタートアップ プロジェクトは VSIX プロジェクトであるため、コードを実行すると、コードと VSIX がビルドされ、その VSIX がインストールされた Visual Studio が起動されます。 この方法で Visual Studio を起動すると、個別のレジストリ ハイブで起動されるため、アナライザーのビルド中に Visual Studio の主な使用がテスト インスタンスの影響を受けなくなります。 この方法で初めて起動すると、Visual Studio をインストールした後に Visual Studio を初めて起動したときと同様に、いくつかの初期化が実行されます。
コンソール プロジェクトを作成し、コンソール アプリケーション Main メソッドに配列コードを入力します。
var b1 = new ImmutableArray<int>();
Console.WriteLine("b1.Length = {0}", b1.Length);
var b2 = new ImmutableArray<int> { 1, 2, 3, 4, 5 };
Console.WriteLine("b2.Length = {0}", b2.Length);
ImmutableArray
を含むコード行には波線が表示されます。これは、不変の NuGet パッケージを取得し、コードに using
ステートメントを追加する必要があるためです。
ImmutableArray
の下に赤い波線が引き続き表示されるので、その識別子にキャレットを置き、Ctrl + . (ピリオド) キーを押して修正候補メニューを表示し、適切な using
ステートメントを追加することを選択します。
すべて保存して閉じ、 2つ目の Visual Studio インスタンスを閉じて、クリーンな状態にして続行します。
"編集と継続機能を使用してアナライザーの作業を完了する"
Visual Studio の最初のインスタンスで、AnalyzeObjectCreation
メソッドの先頭にブレークポイントを設定するには、まず1行目にカーソルを移動し、F9 キーを押します。
F5でアナライザーを再度起動し、Visual Studio の 2 番目のインスタンスで、前回作成したコンソール アプリケーションをもう一度開きます。
Roslyn コンパイラがオブジェクト作成式を検出してアナライザーを呼び出したため、ブレークポイントで最初の Visual Studio のインスタンスに戻ります。
オブジェクト作成ノードを取得します。 F10 キーを押して objectCreation
変数を設定する行をステップオーバーし、[イミディエイト ウィンドウ] で式 "objectCreation.ToString()"
を評価します。 変数が指す構文ノードは、探しているコード "new ImmutableArray<int>()"
であることがわかります。
ImmutableArray<T> Type オブジェクトを取得します。 作成される型が ImmutableArray であるかどうかを確認する必要があります。 まず、この型を表すオブジェクトを取得します。 セマンティック モデルを使用して型をチェックして、正確に適切な型があることを確認し、ToString()
の文字列を比較しません。 関数の末尾に次のコード行を入力します。
var immutableArrayOfTType =
context.SemanticModel
.Compilation
.GetTypeByMetadataName("System.Collections.Immutable.ImmutableArray`1");
メタデータでは、バックティック (') とジェネリック パラメーターの数を使用してジェネリック型を指定します。 そのため、メタデータ名に "ImmutableArray<T>" が表示されないのです。
セマンティック モデルには、シンボル、データ フロー、可変有効期間などに関する質問をできる便利なものが多数用意されています。Roslyn は、さまざまなエンジニアリング上の理由 (パフォーマンス、誤ったコードのモデリングなど) のために、構文ノードをセマンティック モデルから分離します。 正確な比較のために、コンパイル モデルで参照に含まれる情報を検索する必要があります。
エディター ウィンドウの左側にある黄色の実行ポインターをドラッグできます。 immutableArrayOfType
変数の上にマウス ポインターを置くと、セマンティック モデルで正確な型が見つかったことがわかります。
オブジェクト作成式の型を取得します。 この記事では "Type" をいくつかの方法で使用しますが、これは "新しい Foo" 式がある場合は、Foo のモデルを取得する必要があることを意味します。 オブジェクト作成式の型を取得して、ImmutableArray<T> 型であるかどうかを確認する必要があります。 セマンティック モデルをもう一度使用して、オブジェクト作成式の型シンボル (ImmutableArray) のシンボル情報を取得します。 関数の末尾に次のコード行を入力します。
var symbolInfo = context.SemanticModel.GetSymbolInfo(objectCreation.Type).Symbol as INamedTypeSymbol;
アナライザーはエディター バッファー内の不完全なコードまたは正しくないコードを処理する必要があるため (たとえば、using
ステートメントが不足しています)、symbolInfo
が null
されているかどうかを確認する必要があります。 分析を完了するには、シンボル情報オブジェクトから名前付き型 (INamedTypeSymbol) を取得する必要があります。
型を比較します。 探しているオープン ジェネリック型 T があり、コード内の型は具体的なジェネリック型であるため、型の構築元 (オープン ジェネリック型) のシンボル情報に対してクエリを実行し、その結果を immutableArrayOfTType
と比較します。 メソッドの末尾に次のように入力します。
if (symbolInfo != null &&
symbolInfo.ConstructedFrom.Equals(immutableArrayOfTType))
{}
診断を報告します。 診断の報告は非常に簡単です。 プロジェクト テンプレートで作成したルールを使用します。これは Initialize メソッドの前に定義されています。 コード内のこの状況はエラーであるため、rule を初期化した行を変更して、DiagnosticSeverity.Warning
(緑の波線) を DiagnosticSeverity.Error
(赤い波線) に置き換えることができます。 ルールの残りの部分は、チュートリアルの冒頭付近で編集したリソースから初期化されます。 また、波線の場所を報告する必要もあります。これは、オブジェクト作成式の型指定の場所です。 if
ブロックに次のコードを入力します。
context.ReportDiagnostic(Diagnostic.Create(Rule, objectCreation.Type.GetLocation()));
関数は次のようになります (形式が異なる場合があります)。
private void AnalyzeObjectCreation(SyntaxNodeAnalysisContext context)
{
var objectCreation = (ObjectCreationExpressionSyntax)context.Node;
var immutableArrayOfTType =
context.SemanticModel
.Compilation
.GetTypeByMetadataName(
"System.Collections.Immutable.ImmutableArray`1");
var symbolInfo = context.SemanticModel.GetSymbolInfo(objectCreation.Type).Symbol as
INamedTypeSymbol;
if (symbolInfo != null &&
symbolInfo.ConstructedFrom.Equals(immutableArrayOfTType))
{
context.ReportDiagnostic(
Diagnostic.Create(Rule, objectCreation.Type.GetLocation()));
}
}
アナライザーの動作を確認できるようにブレークポイントを削除します (Visual Studio の最初のインスタンスへの戻りを停止します)。 実行ポインターをメソッドの先頭にドラッグし、F5 ImmutableType<int>
の下に波線が表示されます。
コードの問題に対する "コード修正" の追加
開始する前に、Visual Studio の 2 番目のインスタンスを閉じ、Visual Studio の最初のインスタンス (アナライザーを開発している場所) でデバッグを停止します。
新しいクラスを追加します。 ソリューション エクスプローラーの でプロジェクト ノードのショートカット メニュー (右ポインター ボタン) を使用し、新しい項目を追加することを選択します。 BuildCodeFixProvider
というクラスを追加します。 このクラスは ExportCodeFixProvider
属性で注釈を付ける必要もあります。また、LanguageNames
列挙型を解決するには、using
ステートメントを追加する必要があります。 クラス ファイルには、次のコードが含まれている必要があります。
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeFixes;
namespace ImmutableArrayAnalyzer
{
[ExportCodeFixProvider(LanguageNames.CSharp)]
class BuildCodeFixProvider : CodeFixProvider
{}
派生メンバーをスタブします。 次に、エディターのキャレットを識別子 CodeFixProvider
に配置し、Ctrl キーを押しながら を押して、+ (ピリオド)を入力し、この抽象基底クラスの実装をスタブ化します。 これにより、プロパティとメソッドが生成されます。
プロパティを実装します。 FixableDiagnosticIds
プロパティの get
本体に次のコードを入力します。
return ImmutableArray.Create(ImmutableArrayAnalyzer.DiagnosticId);
Roslyn は、これらの識別子 (単なる文字列) を照合することで、診断と修正をまとめます。 プロジェクト テンプレートによって診断 ID が生成され、自由に変更できます。 プロパティ内のコードは、アナライザー クラスから ID を返すだけです。
RegisterCodeFixAsync メソッドはコンテキストを受け取ります。 コード修正が複数の診断に適用される場合や、コード行に複数の問題が発生する可能性があるため、コンテキストは重要です。 メソッドの本体に「context.」と入力すると、IntelliSense の入力候補一覧に、有用なメンバーがいくつか表示されます。 CancellationToken メンバーがあり、何かが修正をキャンセルしようとしているかどうかを確認できます。 多くの有用なメンバーを持つ Document メンバーがあり、プロジェクトおよびソリューション モデル オブジェクトにアクセスできます。 診断を報告する際に指定したコードの位置に対応する、開始および終了を示す Span メンバーが存在します。
メソッドを非同期にします。 最初に行う必要があるのは、生成されたメソッド宣言を async
メソッドに修正することです。 抽象クラスの実装をスタブアウトするためのコード修正には、メソッドが Task
を返す場合でも、async
キーワードは含まれません。
構文ツリーのルートを取得します。 コードを変更するには、コード修正によって行う変更を含む新しい構文ツリーを生成する必要があります。 GetSyntaxRootAsync
を呼び出すには、コンテキストからの Document
が必要です。 これは非同期メソッドです。これは、構文ツリーを取得するための不明な作業があるためです。これには、ディスクからのファイルの取得、解析、Roslyn コード モデルの構築などが含まれます。 この間、async
を使用することで Visual Studio の UI は応答性が向上します。 メソッド内のコード行を次のように置き換えます。
var root = await context.Document
.GetSyntaxRootAsync(context.CancellationToken);
問題のあるノードを見つけます。 コンテキストのスパンを渡しますが、見つけたノードが変更する必要があるコードではない可能性があります。 報告された診断では、(波線が属している) 型識別子のスパンのみが指定されていましたが、オブジェクト作成式全体を置き換える必要があります。これには、先頭の new
キーワードと末尾のかっこが含まれます。 次のコードをメソッドに追加します (Ctrl+. を使用して、ObjectCreationExpressionSyntax
の using
ステートメントを追加します)。
var objectCreation = root.FindNode(context.Span)
.FirstAncestorOrSelf<ObjectCreationExpressionSyntax>();
電球 UI のコード修正プログラムを登録します。 コード修正プログラムを登録すると、Roslyn は Visual Studio 電球 UI に自動的にプラグインします。 エンド ユーザーは、アナライザーが不適切な ImmutableArray<T>
コンストラクターの使用に波線を表示したときに、Ctrl+. (ピリオド) キーを使用できることが分かります。 コード修正プロバイダーは問題が発生したときにのみ実行されるため、探していたオブジェクト作成式があると仮定できます。 コンテキスト パラメーターから、次のコードをメソッドの末尾に追加することで、新しいコード修正 RegisterCodeFixAsync
登録できます。
context.RegisterCodeFix(
CodeAction.Create("Use ImmutableArray<T>.Empty",
c => ChangeToImmutableArrayEmpty(objectCreation,
context.Document,
c)),
context.Diagnostics[0]);
エディターのキャレットを識別子 CodeAction
に置き、Ctrl + . (ピリオド) キーを使って、この型の適切な using
ステートメントを追加する必要があります。
次に、エディターのキャレットを ChangeToImmutableArrayEmpty
識別子に配置し、Ctrl + をもう一度使用して、このメソッドスタブを生成します。
この最後に追加したコード スニペットは、検出された問題の種類の CodeAction
と診断 ID を渡すことによって、コード修正を登録します。 この例では、このコードで修正プログラムを提供する診断 ID は 1 つだけであるため、診断 ID 配列の最初の要素を渡すだけで済みます。 CodeAction
を作成するときに、電球 UI がコード修正の説明として使用するテキストを渡します。 CancellationToken を受け取り、新しい Document を返す関数も渡します。 新しいドキュメントには、ImmutableArray.Empty
を呼び出す修正プログラムが適用されたコードを含む新しい構文ツリーがあります。 このコード スニペットでは、objectCreation ノードとコンテキストの Document を閉じることができるように、ラムダを使用します。
新しい構文ツリーを構築します。 先ほどスタブを生成した ChangeToImmutableArrayEmpty
メソッドに、コード行 ImmutableArray<int>.Empty;
を入力します。 構文ビジュアライザー ツール ウィンドウをもう一度表示すると、この構文が SimpleMemberAccessExpression ノードであることがわかります。 これは、このメソッドで新しい Document を構築して返すために必要なものです。
ChangeToImmutableArrayEmpty
に対する最初の変更は、Task<Document>
する前に async
を追加することです。これは、メソッドを非同期にする必要があるとコード ジェネレーターが想定できないためです。
メソッドが次のように表示されるように、本文に次のコードを入力します。
private async Task<Document> ChangeToImmutableArrayEmpty(
ObjectCreationExpressionSyntax objectCreation, Document document,
CancellationToken c)
{
var generator = SyntaxGenerator.GetGenerator(document);
var memberAccess =
generator.MemberAccessExpression(objectCreation.Type, "Empty");
var oldRoot = await document.GetSyntaxRootAsync(c);
var newRoot = oldRoot.ReplaceNode(objectCreation, memberAccess);
return document.WithSyntaxRoot(newRoot);
}
エディターのキャレットを
このコードでは SyntaxGenerator
を使用します。これは、新しいコードを構築するための便利な型です。 コードの問題があるドキュメントのジェネレーターを取得した後、ChangeToImmutableArrayEmpty
MemberAccessExpression
を呼び出し、アクセスするメンバーを持つ型を渡し、メンバーの名前を文字列として渡します。
次に、メソッドはドキュメントのルートをフェッチします。これは一般的なケースでは任意の作業を伴う可能性があるため、コードはこの呼び出しを待機し、キャンセル トークンを渡します。 Roslyn コード モデルは、.NET 文字列の操作と同様に不変です。文字列を更新すると、新しい文字列オブジェクトが返されます。 ReplaceNode
を呼び出すと、新しいルート ノードが返されます。 構文ツリーのほとんどは共有されますが (不変であるため)、objectCreation
ノードは memberAccess
ノードと、構文ツリー ルートまでのすべての親ノードに置き換えられます。
コード修正を試す
F5 ImmutableArray<int>
の場所に電球が表示されます。 Ctrlキーを押してから+(ピリオド)を入力すると、コード修正が表示され、電球UIで自動生成されたコードの差分プレビューが表示されます。 Roslyn はこれを自動的に作成します。
Pro のヒント: Visual Studio の 2 番目のインスタンスを起動しても、コード修正で電球が表示されない場合は、Visual Studio コンポーネント キャッシュのクリアが必要になる場合があります。 キャッシュをクリアすると、Visual Studio でコンポーネントが再検査されるため、Visual Studio は最新のコンポーネントを取得する必要があります。 最初に、Visual Studio の 2 番目のインスタンスをシャットダウンします。 次に、Windows エクスプローラー
ビデオを話してコード プロジェクトを終了する
完成したコード はすべて、で確認できます。 DoNotUseImmutableArrayCollectionInitializer と
関連コンテンツ
- \\ビルド2015 カンファレンス トーク
- GitHubでコードを完了
- GitHub でいくつかの例を示し、3 種類のアナライザーにグループ化
- GitHub OSS サイトのその他のドキュメント
- FxCop ルールを GitHub で Roslyn アナライザーを使用して実装する