やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

C#ソースコード雛形作成をC#でできないか調査する(CodeDOM)

 C#にはCodeDOMというコード生成用ライブラリがある。

CodeDOM

 C#にはCodeDOMというコード生成用ライブラリがある。

問題

 生成できるコードはC#2.0の構文までしか対応していないと思われる。古すぎる……。

自動実装プロパティ不可

 特にプロパティ自動実装形式にできないのが残念。10年以上前から要望はあるが、実装されていないっぽい。

 以下のプロパティ作成コードをみると、Widthプロパティが参照する名前にwidthValueというフィールドが設定されている。

 つまり、コード生成用コードを書くときは糖衣構文がやってくれた処理を明記せねばならない。なにそれクソ面倒……。

プロパティの書き方

2.0まで

private string name;
public string Name
{
    get { return name; };
    set { name = value; }
}

 CodeDomではこの書式のみ対応。でも、こんなコードは絶対に嫌だ。

3.0以降

 読書両用。

public string Name { get; set; }

 読取専用。

public string Name { get; private set; }

 書込専用。

public string Name { private get; set; }

 自動実装プロパティ。フィールドを宣言せずに済む。超嬉しい。なのにCodeDomでは使えない……。

6.0以降

 setを省略するとreadonlyフィールドを返すプロパティになる。getの省略は不可。

public string Name { get; }

 それに伴い、初期値をセットできるようになった。

public string Name { get; } = default;

 もしクラス内でセットしたいなら、今までどおりprivate set;を明記する。

public string Name { get; private set; }

8.0以降

 null許容型が使えるようになった。有効にするには.csprojに<Nullable>enable</Nullable>を追加する。このとき、型に?のない既存どおりの書き方をしたものは警告が出るようになる。

public string Name { get; } = default; // 警告

 以下のようにするとnull許容型になり、上記とは別の型になる。警告は消える。

public string? Name { get; } = default;

 null免除演算子!defaultの末尾につける。これで警告は回避できる。だが、string型は非null許容型なのに、defaultnullを返すという矛盾した状態になってしまう。

public string Name { get; } = default!;

 そこでコンストラクタにより初期化をする。

public string Name { get; };
public コンストラクタ(string name) => Name = name;

 面倒になったものだ。

どうやって実装するか?

CodeDomで再現する方法

CodeTypeDeclaration newType = new CodeTypeDeclaration("TestType"); 
CodeSnippetTypeMember snippet = new CodeSnippetTypeMember(); 
snippet.Comments.Add(new CodeCommentStatement("this is integer property", true)); 
snippet.Text="public int IntergerProperty { get; set; }"; 
newType.Members.Add(snippet); 

インデントしてくれるライタ

 低レベルになってしまう。ファイルストリームに書き込む。このときインデントを数値で指定すると、その分だけインデントされて出力される。

所感

 この辺の情報を踏まえて、次回はコードを書いてみる。

対象環境

$ uname -a
Linux raspberrypi 4.19.42-v7+ #1218 SMP Tue May 14 00:48:17 BST 2019 armv7l GNU/Linux