「Code Contractsで頻繁に使うのに、スニペット用意されてないじゃん!」とお嘆きの声に答えまして、とりあえず的に作ったC#のやつがあるので置いておきます。
以下が、「Code Contractsで頻繁に使うのに、スニペット用意されてないじゃん!」の追加の俺々コードスニペットたちです。
まぁ、なんで標準的に用意されていないのか、なんとなくわかるような気もしますけどね。
ちなみに、やつけ的にテキストエディタで作ったものです。ご注意ください。
name | snippet | filename | explanation |
---|---|---|---|
EndContractBlock | cecb | contractendcontractblock.snippet | メソッドのコントラクトに if-then-throw の形式で実行前の状態のみが含まれる場合に、コントラクト セクションの終わりをマークします。 |
EnsuresOnThrow(TException)(Boolean) | ceot | contractensuresonthrow.snippet | 指定された例外および条件に基づいて、外側のメソッドまたはプロパティに実行後の状態のコントラクトを指定します。 |
Exists(T)(IEnumerable(T), Predicate(T)) | cexe | contractexistienumerablepredicate.snippet | ある要素のコレクション内の要素が関数内に存在するかどうかを判断します。 |
Exists(Int32, Int32, Predicate(Int32)) | cexi | contractexistintintpredicate.snippet | ある整数範囲内のすべての整数について指定したテストが true かどうかを判定します。 |
ForAll(T)(IEnumerable(T), Predicate(T)) | cfalle | contractforallienumerablepredicate.snippet | コレクション内のすべての要素が関数内に存在するかどうかを判断します。 |
ForAll(Int32, Int32, Predicate(Int32)) | cfalli | contractforallintintpredicate.snippet | 指定した範囲内のすべての整数について特定の状態が有効かどうかを判定します。 |
EndContractBlock
レガシーコード体質改善の際などを中心として、これはかなり活躍するはずです。その他の場合でも、Contractの明示的なエンドポイントとして積極的に使っていってもいいと思います。
contractendcontractblock.snippet
<?xml version="1.0" encoding="utf-8"?> <CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet"> <CodeSnippet Format="1.0.0"> <Header> <Title>Contract.EndContractBlock</Title> <Shortcut>cecb</Shortcut> <Description>Emits a 'Contract.EndContractBlock' clause</Description> <Author>zecl</Author> </Header> <Snippet> <Imports> <Import> <Namespace>System.Diagnostics.Contracts</Namespace> </Import> </Imports> <Declarations> <Object Editable="false"> <ToolTip>メソッドのコントラクトに if-then-throw の形式で実行前の状態のみが含まれる場合に、コントラクト セクションの終わりをマークします。</ToolTip> <Function> </Function> </Object> </Declarations> <Code Language="CSharp" Kind="any"><![CDATA[Contract.EndContractBlock();$end$]]></Code> </Snippet> </CodeSnippet> </CodeSnippets>
EnsuresOnThrow(TException)(Boolean)
奥さん、例外発生時の実行後の状態のコントラクトを指定できるんですってよ。ぶっちゃけこれ超重要だと思うんですが。
contractensuresonthrow.snippet
<?xml version="1.0" encoding="utf-8"?> <CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet"> <CodeSnippet Format="1.0.0"> <Header> <SnippetTypes> <SnippetType>Expansion</SnippetType> </SnippetTypes> <Title>Contract.EnsuresOnThrow<E></Title> <Shortcut>ceot</Shortcut> <Description>Emits a 'Contract.EnsuresOnThrow<Exc>' clause</Description> <Author>zecl</Author> </Header> <Snippet> <Imports> <Import> <Namespace>System.Diagnostics.Contracts</Namespace> </Import> </Imports> <Declarations> <Object Editable="true"> <ID>exception</ID> <ToolTip>実行後の状態のチェックを起動する例外の種類。</ToolTip> <Default>TException</Default> <Function> </Function> </Object> <Object Editable="true"> <ID>condition</ID> <ToolTip>テストする条件式。</ToolTip> <Default>false</Default> <Function> </Function> </Object> </Declarations> <Code Language="CSharp" Kind="method body"><![CDATA[Contract.EnsuresOnThrow<$exception$>($condition$);$end$]]></Code> </Snippet> </CodeSnippet> </CodeSnippets>
Exists(T)(IEnumerable(T), Predicate(T))
"LINQバンザイ"、"LINQ最高"のご時世ですから。こういうタイプの契約を指定したくなることもあると思うんです。思っちゃうんです。
contractexistienumerablepredicate.snippet
<?xml version="1.0" encoding="utf-8"?> <CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet"> <CodeSnippet Format="1.0.0"> <Header> <SnippetTypes> <SnippetType>Expansion</SnippetType> </SnippetTypes> <Title>Contract.Exists<T></Title> <Shortcut>cexe</Shortcut> <Description>Emits a 'Contract.Exists<T>' clause</Description> <Author>zecl</Author> </Header> <Snippet> <Imports> <Import> <Namespace>System.Diagnostics.Contracts</Namespace> </Import> </Imports> <Declarations> <Object Editable="true"> <ID>type</ID> <ToolTip>collection に格納されている型。</ToolTip> <Default>int</Default> <Function> </Function> </Object> <Object Editable="true"> <ID>collection</ID> <ToolTip>predicate に渡される型 T の要素が含まれているコレクション。</ToolTip> <Default>new int[] {}</Default> <Function> </Function> </Object> <Object Editable="true"> <ID>predicate</ID> <ToolTip>collection 内の要素を評価する関数。</ToolTip> <Default>x => true</Default> <Function> </Function> </Object> </Declarations> <Code Language="CSharp" Kind="method body"><![CDATA[Contract.Exists<$type$>($collection$, $predicate$);$end$]]></Code> </Snippet> </CodeSnippet> </CodeSnippets>
Exists(Int32, Int32, Predicate(Int32))
こっちもね。contractexistintintpredicate.snippet
<?xml version="1.0" encoding="utf-8"?> <CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet"> <CodeSnippet Format="1.0.0"> <Header> <SnippetTypes> <SnippetType>Expansion</SnippetType> </SnippetTypes> <Title>Contract.Exists</Title> <Shortcut>cexi</Shortcut> <Description>Emits a 'Contract.Exists' clause</Description> <Author>zecl</Author> </Header> <Snippet> <Imports> <Import> <Namespace>System.Diagnostics.Contracts</Namespace> </Import> </Imports> <Declarations> <Object Editable="true"> <ID>fromInclusive</ID> <ToolTip>predicate に渡す最初の整数。</ToolTip> <Default>0</Default> <Function> </Function> </Object> <Object Editable="true"> <ID>toExclusive</ID> <ToolTip>predicate に渡す最後の整数より 1 だけ大きい数。</ToolTip> <Default>1</Default> <Function> </Function> </Object> <Object Editable="true"> <ID>predicate</ID> <ToolTip>指定した範囲内の任意の整数値を評価する関数。</ToolTip> <Default>x => true</Default> <Function> </Function> </Object> </Declarations> <Code Language="CSharp" Kind="method body"><![CDATA[Contract.Exists($fromInclusive$, $toExclusive$, $predicate$);$end$]]></Code> </Snippet> </CodeSnippet> </CodeSnippets>
ForAll(T)(IEnumerable(T), Predicate(T))
そう、ループで回している最中の契約だって結びたいんです。Eiffelのバートランド・メイヤー大先生もそうおっしゃっております。あと、名著「達人プログラマー」にもいろいろ書いてあったような気がしますよ。
contractforallienumerablepredicate.snippet
<?xml version="1.0" encoding="utf-8"?> <CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet"> <CodeSnippet Format="1.0.0"> <Header> <SnippetTypes> <SnippetType>Expansion</SnippetType> </SnippetTypes> <Title>Contract.ForAll<T></Title> <Shortcut>cfalle</Shortcut> <Description>Emits a 'Contract.ForAll<T>' clause</Description> <Author>zecl</Author> </Header> <Snippet> <Imports> <Import> <Namespace>System.Diagnostics.Contracts</Namespace> </Import> </Imports> <Declarations> <Object Editable="true"> <ID>type</ID> <ToolTip>collection に格納されている型。</ToolTip> <Default>int</Default> <Function> </Function> </Object> <Object Editable="true"> <ID>collection</ID> <ToolTip>predicate に渡される型 T の要素が含まれているコレクション。</ToolTip> <Default>new int[] {}</Default> <Function> </Function> </Object> <Object Editable="true"> <ID>predicate</ID> <ToolTip>collection 内の要素を評価する関数。</ToolTip> <Default>x => true</Default> <Function> </Function> </Object> </Declarations> <Code Language="CSharp" Kind="method body"><![CDATA[Contract.ForAll<$type$>($collection$, $predicate$);$end$]]></Code> </Snippet> </CodeSnippet> </CodeSnippets>
ForAll(Int32, Int32, Predicate(Int32))
こっちもね。contractforallintintpredicate.snippet
<?xml version="1.0" encoding="utf-8"?> <CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet"> <CodeSnippet Format="1.0.0"> <Header> <SnippetTypes> <SnippetType>Expansion</SnippetType> </SnippetTypes> <Title>Contract.ForAll</Title> <Shortcut>cfalli</Shortcut> <Description>Emits a 'Contract.ForAll' clause</Description> <Author>zecl</Author> </Header> <Snippet> <Imports> <Import> <Namespace>System.Diagnostics.Contracts</Namespace> </Import> </Imports> <Declarations> <Object Editable="true"> <ID>fromInclusive</ID> <ToolTip>predicate に渡す最初の整数。</ToolTip> <Default>0</Default> <Function> </Function> </Object> <Object Editable="true"> <ID>toExclusive</ID> <ToolTip>predicate に渡す最後の整数より 1 だけ大きい数。</ToolTip> <Default>1</Default> <Function> </Function> </Object> <Object Editable="true"> <ID>predicate</ID> <ToolTip>指定した範囲内の任意の整数値を評価する関数。</ToolTip> <Default>x => true</Default> <Function> </Function> </Object> </Declarations> <Code Language="CSharp" Kind="method body"><![CDATA[Contract.ForAll($fromInclusive$, $toExclusive$, $predicate$);$end$]]></Code> </Snippet> </CodeSnippet> </CodeSnippets>
というわけで、クオリティはともかくとして月に1回は更新しようという自分ルール守った。うん。