C#にはCodeDOMというコード生成用ライブラリがある。
CodeDOM
問題
生成できるコードはC#2.0の構文までしか対応していないと思われる。古すぎる……。
自動実装プロパティ不可
特にプロパティ自動実装形式にできないのが残念。10年以上前から要望はあるが、実装されていないっぽい。
- https://social.msdn.microsoft.com/Forums/vstudio/ja-JP/d1362ffd-7806-4bc0-9128-8606a7353e34/setgetcodedom?forum=vsgeneralja
- https://codeday.me/jp/qa/20190317/427380.html
以下のプロパティ作成コードをみると、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許容型なのに、default
はnull
を返すという矛盾した状態になってしまう。
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);
インデントしてくれるライタ
低レベルになってしまう。ファイルストリームに書き込む。このときインデントを数値で指定すると、その分だけインデントされて出力される。
所感
この辺の情報を踏まえて、次回はコードを書いてみる。
対象環境
- Raspbierry pi 3 Model B+
- Raspbian stretch 9.0 2018-11-13 ※
- bash 4.4.12(1)-release ※
- SQLite 3.29.0 ※
- C# dotnet 3.0.100 ※
$ uname -a Linux raspberrypi 4.19.42-v7+ #1218 SMP Tue May 14 00:48:17 BST 2019 armv7l GNU/Linux