Archive for 4月 2014
Singleton
こないだ見かけた話題。
singletonといえば?
SingletonList
Roslynのコード中に、こんなメソッドがあるみたいです。
/// <summary>
/// Creates a singleton list of syntax nodes.
/// </summary>
/// <typeparam name=”TNode“>The specific type of the element nodes.</typeparam>
/// <param name=”node“>The single element node.</param>
/// <returns></returns>
public static SyntaxList<TNode> SingletonList<TNode>(TNode node) where TNode : SyntaxNode
{
return new SyntaxList<TNode>(node);
}
場所はここ。
http://roslyn.codeplex.com/SourceControl/latest#Src/Compilers/CSharp/Source/Syntax/SyntaxFactory.cs
Singletonパターン
プログラミングの分野では、singletonっていうと、プログラム稼働中にただ1つしかインスタンスがないもののことを指す場合が多いわけですが。singletonパターン(その、インスタンスの唯一性を保証するためのパターン)が有名なので。
ところが、上記のコードは見ての通り、メソッドを呼び出すたびに新しいインスタンスを作って返していると。それで、「どうしてsingletonじゃないのに名前にsingletonって入ってるの?私のsingletonの理解が間違ってる?」みたいな話が。
集合論のsingleton
まあそりゃ、そのsingletonじゃないから。
上記コードのsingletonは、集合論で使われる数学用語。日本語訳だと単集合になってるみたい。ただ1つの元からなる集合。
数学って、極力少ないルール(公理、証明不可能な最低限の決め事)を使ってより多くの結果を導けることが、理論の「よさ」の1つの指標になります。特に集合論は現代数学の基礎中の基礎なので、ものすごいシンプルなルールしか持っていません。例えば以下のような。
- 集合xとyの対 {x, y} を作れる
- 含まれる要素が全て等しいとき、2つの集合が等しいと判定する
- 自分自身を含む集合は認めない
ここで、1番目のルールから、同じ集合、xとxの対 {x, x} も作れます。ところが、2のルールを見ての通り、集合は含まれている要素の有無だけを見て等価判定するので、要素の重複を区別できません。結果的に、{x, x} と {x} は同じ集合ということになります。
で、x から {x} という集合を作れたわけですが、3のルールから、{x}、つまり、「xだけを含む集合」はxではないということになります。この、xから作った、xを1つだけ含む集合がsingletonになります。
上記コードはどう見てもsingleton(nodeを1つだけ含むSyntaxNodeを作った)なわけです。
+1
少々余談になりますが、この意味(集合論上の)singletonの利用場面を1つ。
集合論では、少ないルールから出発してる手前、ちょっとした操作をするのにも一工夫必要になったりします(動機としては逆で、ルールを減らすために工夫してる)。
例えば、自然数の構築。自然数を作るには「ある数よりも1つ大きい数が作れる」みたいなルールが必要になりますが、集合論的には以下のようにして「+1」を作ります。
- ある集合xと、そのsingleton {x}の和集合x∪{x}を作る
ちなみにこのためには、先ほどのルールに加えて、以下の2つのルール(公理)も必要。
- 要素を持たない集合{} が存在する(空集合)
- 2つの集合x, yの両方の元を持つ別の集合 x∪y が作れる(合併集合)
要素を持たない集合(空集合)を0扱いして、以下、
- 1 = 0∪{0} = {}∪{0} = {0}
- 2 = 1∪{1} = {0}∪{1} = {0, 1}
- 3 = 2∪{2} = {0, 1}∪{2} = {0, 1, 2}
- 4 = 3∪{3} = {0, 1, 2}∪{3} = {0, 1, 2, 3}
みたいな感じで「+1」していきます。
だからといって、singleton?
singletonなことはわかった。でも、その名前どうなの?
「singletonパターンと紛らわしいから」って理由もなくはないんですけども、どちらかというと、汎用性に欠けるから。
なんというか例えば、以下のようなメソッドもあるわけじゃないですか(この例はSystem.Concoleクラスからとってきたもの)。
public static void Write(string format, object arg0);
public static void Write(string format, object arg0, object arg1);
public static void Write(string format, object arg0, object arg1, object arg2);
public static void Write(string format, params object[] arg);
引数が1つだけのもの、2つだけのもの、3つのもの、そして、配列で任意の長さの引数を渡せるもの。これとの類推で行くなら、以下のような名前でもいいわけです。
public static SyntaxList<TNode> List<TNode>(TNode node) where TNode : SyntaxNode
public static SyntaxList<TNode> List<TNode>(TNode node1, TNode node2) where TNode : SyntaxNode
public static SyntaxList<TNode> List<TNode>(TNode node1, TNode node2, TNode node3) where TNode : SyntaxNode
public static SyntaxList<TNode> List<TNode>(IEnumerable<TNode> nodes) where TNode : SyntaxNode
(ちなみに、4 つ目、つまり、IEnumerableを受け取るやつは、実際にListっていうメソッドがSyntaxFactory.cs内にあります。)
1つ目にSingletonListなんて名前を付けてしまったら、2つ、3つとなるたびに、Singleton, Doubleton, Tripleton, … みたいに名前つけるんですかね?みたいなことになってしまいます(もっとも、今回のRoslynのコード上、2つ、3つの場合を使う要件はないんで、別にこれでいいんですけども。名前自体が違う方が、引数を間違える人的ミスは減りますし)。
結果
- いやいや、どう見てもsingletonだよ
- singletonなんだけど、singletonって名前はどうなの?
ソースコード共有と#if
いわゆるifdefコードの難しさ。
昨日、クロスプラットフォームな開発をしてる人から、「universal Windows apps の共有プロジェクトって、#if を正しく認識してるの?リネームとかのリファクタリング的な意味で」という疑問をいただいたので試してみた結果。
ダメでした。ええ、ダメでした(とりあえずConnectに登録済み)。
クロスプラットフォーム開発してて、どうしても#if/#elseするしかない場面ってごろごろあって、「動く」という意味では全然問題ないものの、こういうリファクタリングでいつも困るそうで。手元の環境で #if の対象になってない部分のコードで、どうしても修正ミスが残って、後から問題が発覚するという。
RyuJIT SIMD対応
なんか週明けてからもブログが。
//build/で出てた、RyuJIT CTP3のSIMD対応の話の詳細。あと、SIMD命令ってのが何なのかっていうそもそもの説明付き。
C# before/after
//build/ のセッション、やっとお目当てにあたりは見れたかなぁ。
「The Future of C#」のデモが、Roslyn使ったVisual Studio拡張とか次期C#の新機能紹介とかまとまっててよさげ。
で、このデモ中のコードが新機能紹介として優秀な感じだったので、before/after的に並べてみる。具体的にどういう文法なのかはこないだ書いたので今日は割愛。
(多少コードはいじってたり。いじった結果→ プロジェクト一式(ZIP圧縮))
左がC# 5.0、右が次期C#で書き直したもの。
Universal Windows Apps
ここ数日ブログに書いた話はCTP (Community Technology Preview: 要はアルファ版。リリース版は結構将来の話)なものばかりでしたが。
RC (Release Candidate: リリース間近。重大なバグフィックス除けばほぼそのままリリース)の話も1つ。
Visual Studio 2013 Update 2 RCを入れると、Windows Phone 8.1アプリの開発ができるようになります。
Windows Phone 8.1アプリは、以下で説明していくような意味でWindows 8.1アプリと“同一アプリ”として開発できて、この仕組みを「ユニバーサル アプリ」(universal Windows apps)って呼びます。
ユニバーサル アプリ
Visual Studio上で、(ユニバーサル アプリ)と付いたプロジェクト テンプレートを使って新規プロジェクトを作るか、もしくは、Windows 8.1アプリに対して「Windows Phone 8.1の追加」、Windows Phone 8.1アプリに対して「Windows 8.1の追加」という操作をすると、プロジェクトが以下のような状態になります。
この状態のアプリを「ユニバーサル アプリ」と言うみたい。
ちゃんと、JavaScript版もC++/CX版もあります。
開発者視点で言うとポイントが4つくらい。
- WinRTの互換性向上、Windows 8.1とWindows Phone 8.1でほぼ共通のAPI化
- 共有プロジェクト(.shproj)が作れるようになった
- PCLの利便性が向上
- Win8.1/WinPhone8.1アプリは、Windowsストア上で同一アプリとして扱われる
ほぼ共通のAPI
ユニバーサル アプリといいつつ、実際のところ、胆となるのはWindows 8.1アプリとWindows Phone 8.1アプリのAPI統合みたい。要するに、共通して使える.NET標準APIとWinRT APIが実用レベルに増えた。
やろうと思えばXAMLとかも完全コピペで(後述する共有プロジェクト使えば単一ソースコードで)作れそうな程度には共通っぽい。
個別にXAMLを書くモチベーションは、画面サイズの違いによる再デザインくらい。「Phone版は画面はみ出てもいいや」とか「ViewBox使って単に拡大して画面サイズ合わせればいいや」とかくらいの適当なので良ければ、ほんとうに単一ソースコードで開発できそう(それでストア審査通るかは別として)。
共有プロジェクト
新しいプロジェクト タイプとして、共有プロジェクトができたみたい。上記のスクリーンショットで言うところの、HubApp1.Sharedプロジェクト。
このプロジェクト中に追加したファイルは、Windows 8.1用プロジェクト(HubApp1.Windows)とWindows Phone 8.1用プロジェクト(HubApp1.WindowsPhone)の両方に含まれている扱いを受けるようです。PCL (Portable Class Library)と違って、ライブラリDLLができるとかではなく、ソースコードやリソースがプロジェクト内に含まれるものとしてそれぞれをビルドします。
各ファイルを「リンクとして追加」するのとかPCLとかと比べて何が嬉しいかというと、以下のような感じ。
- 画像リソースとかのアセットも含めて共有可能
- XAMLとかリソースのパスが狂って参照できなくなる問題もない
- #ifdefによる条件コンパイルなども利用可能
- 管理が楽。個別のプロジェクト側と共有プロジェクト側の間で、D&Dでファイルを移すだけで 個別⇔共有 の切り替え可能
この共有プロジェクトの仕組みを普通に使えるのは、現状ではユニバーサル アプリのみみたい。ただ、ユニバーサル アプリの.csprojファイルの中身を参考にして、自分で.csprojファイルを書き換えれば他のプロジェクトでもファイル共有くらいはできそう(IntelliSenseとかが正しく動く保証がないけども)。
PCLの利便性向上
- Visual Studio 2013 Express for Windows (無償版、Windowsストア アプリ開発用)からPCLプロジェクトを参照できるように
- クラス ライブラリ(単一環境用)プロジェクトとPCLプロジェクトを一本化
- ただし、現状Windowsストア用のみ
- 「.NET Framework 4.5」のみなPCLは作れないみたい
- つまり、PCLプロジェクトのターゲットを「Windows 8.1」のみ/「Windows Phone 8.1」のみに設定可能に
- 代わりに、ターゲットが「Windows 8.1」のみ/「Windows Phone 8.1」のみなプロジェクト テンプレートは廃止
- PCLプロジェクト内でWinRTを参照可能に
- プロジェクト テンプレートで「クラス ライブラリ(ユニバーサル アプリ用ポータブル)」を選ぶと、WinRTが参照されてる状態のPCLができる
- WinRT XAMLコントロールなんかもPCLとして作れるように
現状ではやたらと「Windowsストア用のみ」状態ですけども、「計画としては対応プラットフォームを広げていきたい」とのことらしいので今後に期待。
Windowsストア上では1つのアプリ扱い
上記スクリーンショットの通り、内部的には「2つのプロジェクトでソースコード共有」で、「パッケージ(appx)も2つ作られる」わけですが、これをWindowsストアに上げる際には1つのアプリとして扱ってもらえるそうです。
「1つ」ってのは、以下のような意味合い。
- 同じアプリIDが割り当てられる
- 課金の口が共通。有料アプリなら、片方で買えばもう片方でも使える
- ローミング(OneDrive経由のデータ同期)が共通
- プッシュ通知(Windows Notification Service)が共通
※
みんな、「※」と書いただけで「※ただし日本は除く」って意味にとってくれるのはどういうことなの。
Visual Studio 2013 Update 2 RCをインストールすると、Windows Phone 8.1のエミュレーターもついてくるわけですが。エミュレーターでアプリが動いても、実機が世の中に出回ってないことにはねぇ…
とりあえず、de:codeを期待して待っていればいいんでしょうか…
ちなみに、Visual Studio 2013 Update 2 RC自体は日本語対応済みです。各種プロジェクト テンプレート・項目テンプレートもちゃんと日本語。
//build/ .NET関連
//build/ のセッション動画・資料を眺め中。
あと、それ関連のブログとか。
.NET関連は、以下のセッションの資料の最後の方のまとめの表がなかなかによさげ。
↓それのコピペ。
Technology |
Info |
Download |
JIT “RyuJIT” |
||
SIMD |
||
.NET Compiler Platform (“Roslyn”) |
||
.NET support on Azure Mobile Services |
||
ASP.NET Updates in VS 2014 Update 2 |
||
Universal Windows apps |
||
.NET Native |
||
Xamarin |
||
.NET Foundation |
na |
|
Orleans |
以下、いくつか補足。
Roslynのソースコードを試してみるなら
C#チーム/VBチームのブログで手順説明あり。
このブログは、上半分がEnd-User Preview(Visual Studio拡張)の説明で、下半分がソースコードがらみ。
ソースコードがらみのは、gitリポジトリのcloneの仕方から懇切丁寧に説明してる(ただ、記事中でgitのURLがhttpになってるけども、httpsにしないとcloneできない)。Anders Hejlsbergが//build/ day 2 キーノートでやってたみたいな文字列リテラル構文の書き換え(≪≫をパースできるようにする)のサンプルの説明付き。
注意点として、RoslynのビルドがRoslyn自体を使ってること。End-User Previewを入れてないとビルドできない。あと、VSIX(Visual Studio拡張)パッケージにビルドされるので、Visual Studio 2013 SDKも必要。作られたVSIXパッケージをインストールすれば、自分で書き替えた独自C#拡張がVisual Studioから使える状態に。
RyuJITのSIMD対応を試してみるなら
MSDN SamplesにSIMD用のサンプルコードがあるのでこちらを参照。
こちらの注意点は、RyuJIT CTP3だけ入れてもダメで、レジストリを書き換えないとSIMD対応が有効にならないこと。サンプル中に、レジストリ書き換えのbat(enable-jit.bat)が入っているので、サンプルを試してみる前にこのbatを実行しておく。
↑これをやっておかないと、ビルドできるし正常動作するけども、SIMD使われなくてまったく速くならない。ただ単に、Vector2f型とかが普通の.NETコードとして実行されるだけ(試しに自作してみた自前Vector型と全く同じ性能だった)。
SIMD対応はまだ不安定で、すべての.NETプログラムが動く保証がないそうなので、試した後はレジストリを戻さないと危険で、そのためのbatもある(disable-jit.bat)。
C# vNext (Roslyn)での async/await の仕様変更
そういえば。昔、こんな話題が。
これの「Lift Your Way out of Garbage Collection」の節のあたりに書いてあること。大まかにいうと、
- 非同期メソッド内のローカル変数は全部フィールドに変更される
- それが原因で、オブジェクトの寿命が延びてGC性能を多少落とす
- 将来的に、このC#/VBコンパイラーの挙動は変更するかも
という内容。
今がその「将来」か?ということで、Roslynの新しいC#コンパイラーの生成結果をのぞいてみた。
元コード
以下のようなコードを、C# 5.0のコンパイラーと、Roslynの新コンパイラーでビルドして、その結果をIL Spyでのぞいてみる。
static async Task X()
{
var a = ReadInt();
var x = ReadInt();
Console.WriteLine(x);
await Task.Delay(1);
++a;
var y = ReadInt();
Console.WriteLine(y);
Console.WriteLine(a);
}
static int ReadInt()
{
return int.Parse(Console.ReadLine());
}
ちなみに、RoslynをインストールしちゃうとVisual Studioが新しいコンパイラーしか使わなくなるんで、コマンドラインで直にコンパイル。
コンパイラーは以下の場所を探せば見つかるはず。
- 現状のコンパイラー: Windowsフォルダーの下、Microsoft.NET\Framework64\v4.0.30319 (バージョン違いの場合、64 が付かなかったり v の後ろの数字が違う)にある csc.exe
- Roslynのコンパイラー: Visual Studio拡張のインストールフォルダー内を rcsc.exe で検索
- VS拡張は ユーザー名\AppData\Local\Microsoft\VisualStudio\12.0\Roslyn\Extensions に入ってる
実行ファイル名は rcsc.exe に変わっているものの、コンパイル オプションとかは今まで通りみたい。
結果
ちゃんと変更されてた。
(フィールド名とかは読めるように書き換えています。コンパイラーの生成するコードはもっと難読化されたようなひどい変数名。)
現状の何が問題かというと、awaitをまたがないものでも無関係に全部、ローカル変数がフィールド化されてたこと。
一方で、新コンパイラーでは、ちゃんとawaitをまたぐかどうかを判定して、またいでいるものだけをフィールド化。
このサンプルで言うと、変数 a だけがawaitをまたいでいて、x と y はまたいでいない。現コンパイラーだと a, x, y 全部フィールドになっていて、新コンパイラーだと a だけがフィールドになる。
変更の影響
まあ、実のところ破壊的変更になるわけですが。とはいえ、めったなことではこの変更の影響を受けないはず。
この変更の影響を受けるとすると、GCのタイミングに依存するようなコードを書いた場合(デストラクターを持っていて、かつ、デストラクターの実行順序によって挙動が変わるとか)。そんなコード書くことは普通ないので問題は出ないでしょう。
(というか、元のコードでもコンパイラーの最適化の有無で参照が消えたりするはずで、元々GCのタイミングに依存するようなコード書いたらまともに動かないはずですけども。)
.NET Compiler Platform (Roslyn) Preview
Roslynが1年以上ぶりに公開されました。
オープンソース化
おまけにオープンソース化(ライセンスは Apache License 2.0)のニュース付き。
ソースコードはページ内からのダウンロードもできるし、git cloneも可能
- git clone https://git01.codeplex.com/roslyn
Roslynの成果物
- End-User Preview
- Visual Studio上で、C#プロジェクトで使ってるコンパイラーとかリファクタリング機能がRoslyn版にさし変わる
- 後述するC# 6.0新機能(のうちのいくつか)も使えるようになる
- Roslyn SDK Project Template
- Roslynを使ったVisual Studio拡張を作るためのテンプレート集
- Roslyn Syntax Visualizer
- C#のソースコードのカーソルがある位置が、シンタックス ツリーのどこにあたるかを全部見れる
- ↓こんなの
- Microsoft.CodeAnalysisパッケージ
- 自分のプログラムから参照できるRoslynライブラリのNuGetパッケージ
- Install-Package Microsoft.CodeAnalysis
残念ながら、C#スクリプトがらみの、「C#スクリプトのアイテム テンプレート」とか「C# Interactiveウィンドウ」は現状ではないみたい(ロードマップにだけある)。
C#の新機能候補
今日公開されたバージョンのRoslyn(の新C#/VBコンパイラー)は、すでにいくつか、次期バージョンの来るべき機能が実装されてるみたい。
SDKとかと一緒に、「Upcoming Features in C#/VB」っていうドキュメントが入っているので、詳しくはそちらを参照。
ちなみに、「もっと多くの言語機能が計画としてはあるものの、未実装」とのこと(未実装分はドキュメントにはない)。
(去年出てた情報: The Future of C#。確かにいくつかはドキュメントにも実装にもない。)
以下、かいつまんで、というか、コード サンプルをいくつか(実際にRoslyn End-User Previewをインストールするとコンパイルできるコード)。
Primary Constructor
immutableなクラスが作りやすく。
class Point(int x, int y)
{
public int X { get; } = x;
public int Y { get; } = y;
}
要はF#的なコンストラクターの書き方。ちなみにこの書き方だと、パラメーターのxとかyは、初期化にしか使えない。
初期化以外でも使いたい場合には、以下のように、アクセス修飾子を付けて「Field paramters」って状態にする。
class Point(public int X, public int Y)
{
}
(フィールドをpublicにするのはあんまり推奨されないので、これはいい書き方ではないけども。)
Using static
Math. とか Expression. とか省略可能に。
using System.Math;
class Circle(public readonly double Radius)
{
public double GetArea { get { return Radius * Radius * PI; } }
}
Declaration expressions
式の途中で変数宣言可能に。「変数宣言式」(declaration expression)の名前通り、それ自体も式。
static void Main()
{
var num = int.TryParse("123", out var i) ? i : 0;
Get(out var x, out var y);
while ((var s = Console.ReadLine()) != null) Console.WriteLine(s);
}
static void Get(out int x, out int y)
{
x = 10;
y = 20;
}
Exception filters
(ILの仕様的には昔からあったんだけども、C#でも)例外のcatch句に条件付け可能に。
try
{
throw new Exception("b");
}
catch (Exception e) if (e.Message.StartsWith("a"))
{
Console.WriteLine("a");
}
catch (Exception e) if (e.Message.StartsWith("b"))
{
Console.WriteLine("b");
}
Binary literals
ドキュメントに「Try them out in VB」と書かれてる通り、実はC#には実装されてない。以下のように、2進数リテラルを書けるようにする予定。
var bits = 0b0010_1110;
var hex = 0x00_2E;
var dec = 1_234_567_890;
Indexed members and element initializers
オブジェクト初期化子にインデクサーを書けるように。
var data = new Dictionary<string, int>
{
["one"] = 1,
["two"] = 2,
};
これだけだとそんなにうれしくなくて、さらに、stringのキーに対しては以下のような書き方ができるように。
var data = new Dictionary<string, int>
{
$one = 1,
$two = 2,
};
Console.WriteLine(data.$one);
Console.WriteLine(data.$two);
つまるところ、JSON読み込みとかでは、dynamic使わなくても辞書のキー参照に対するシンタックス シュガーで十分じゃない?的な。
Await in catch and finally blocks
catch句、finally句にもawait演算子書けるように。
StreamWriter s = null;
try
{
s = new StreamWriter("data.txt");
await s.WriteAsync("some message");
}
catch (Exception e)
{
using (var errorLog = new StreamWriter("error.txt"))
await errorLog.WriteAsync(e.Message);
}
finally
{
if (s != null)
{
await s.FlushAsync();
s.Close();
}
}
例外catchしたときにログ書き出し(ファイルI/Oは非同期にしたい)とか、Disposeパターンを非同期にしたいとかいうときに困ることがなくなります。
Extension Add methods in collection initializers
コレクション初期化子で呼ばれるAddメソッドが拡張メソッドでもよくなりました。
using System.Collections.Generic;
class Person(string name, string address)
{
public string Name { get; } = name;
public string Address { get; } = address;
}
static class PersonExtensions
{
public static void Add(this IList<Person> list, string name, string address)
{
list.Add(new Person(name, address));
}
//↓のInitializerから、↑の拡張メソッドが呼ばれる
}
class Program
{
static void Main()
{
var list = new List<Person>
{
{ "name 1", "Shinjuku" },
{ "name 2", "Shinagawa" },
{ "name 3", "Chofu" },
};
}
}
.NET Native
.NET Nativeとかいうものが公開された模様。.NET言語(さしあたってはC#のみがサポート対象)からNativeコードを直接作る仕組み。
- 公式ページ: Microsoft .NET Native
- MSDN Library 内のヘルプ: http://msdn.microsoft.com/en-us/library/dn584397.aspx
去年の暮ぐらいから噂にはなっていたもの。//build/ の初日キーノートでは出てこなかった(初日は OS 関連。WP8.1とかの話題)ので公開明日かと思ったらもう。
概要
以下のようなもの。
- WP8が使ってるMDILに基いた技術
- クライアントデバイスには完全にネイティブ化した状態で配布
- クライアント上で余計な電力消費しないし、初回起動も早い
- 当面のターゲットはストアアプリのみ。ただし、ターゲットは今後広げていきたい
前にプロ生勉強会で話した通り(C#とILとネイティブと)、ManagedコードからNativeコードに変換するタイミングをどうするかってのは意外と難しい話なんですけども。
以下、.NET Nativeのヘルプを読んでみた感じ、その辺りをどうしてるかとか、その他疑問として出そうなところを補足。
クライアントデバイスに.NET Frameworkのインストールは?
不要。
実行に必要なものは全部ネイティブ化、静的リンク。
C#のネイティブコンパイラーが出来たの?
やってることはMSILの事前コンパイル。C#からだと、C#→MSIL→MDIL→ネイティブという流れに。
仕組み上、.NET言語なら何でもネイティブ化できるはずだけど、現状のVisual Studioのプロジェクトテンプレート的にはC#のみ提供(ストア アプリ的に利用者が一番多いものから対応)。
ガベコレは?
あり。
メモリは管理されたまま。Nativeだけど、Unmanagedではない。
.NET Nativeでビルドすると、実行ファイルにMRT.dllっていうDLLが同梱されて、その中にガベコレ用コードが入ってる。
バイナリのサイズは膨らまない?
使っていない部分は除外してからネイティブ化、静的リンクするので大丈夫。
ライブラリが更新されたときには?
当面ストアアプリ限定になってる理由の1つだと思うけど、ストアのサーバー上でクラウドコンパイル(Compile in the Cloud)する。依存先のライブラリが更新されたら自動でバイナリ更新。
将来どうなるかわからないけど、Windowsストアを介さないのであれば、バイナリ更新は開発者の責任ではないかと。(ライブラリが更新されることって、アプリの更新と比べるとかなり低頻度のはずなので、それで十分な場合が多いし。)
リフレクションは?
一番制約がかかるのはもちろんここ。前述の通り、使ってないコードは残さない方針なので、「リフレクションで使ってる」ってことをコンパイラーに教える必要がある。
経験則的な方法で、ある程度自動的にリフレクションで使っているクラスを判定してくれるらしい。自動判定できるのは、例えば、XAMLのデータバインディングで使った型とか、DataContractSerializerのコンストラクターにtypeof(T)で渡した型。
それ以外は、自分で「参照定義ファイル」を書かなきゃいけない(プロジェクトを.NET Native対応に変換すると、rd.xmlってファイルが追加されるので、これを書き換える)。DataContractSerializer以外の、サードパティ製シリアライザー(例えばJson.NETとか)を使う場合には、この参照定義ファイルへの記述が必要。
逆にいうと、参照定義ファイルさえ書けばリフレクション使い放題。dynamicも使える。
ジェネリックとか平気?
古いバージョンのMono AOTで問題になってたみたいな、値型のジェネリックが一部実行出来ない問題は起こらないみたい。
ここ数ヶ月、MSの.NETチームとXamarineが協業してたみたいだし、色々成果共有してるのかも。
使える.NET標準ライブラリは?
現状、ターゲットがストアアプリなのもあって、ベースは.NET Core(ストアアプリ向け.NETプロファイル)。
そこからさらに、いくつかのクラス/メソッドが使えない。例えば以下のようなものが使えない。
- DataAnnotations
- Microsoft.VisualBasic
- WCF
- DelegateのBeginInvoke/EndInvoke
- COM InteropでVARIANT
あと、DateTime.Parseでパースできる文字列に制限があるとか、そういう制限も。
結果、.NET Core以上に使えるクラス/メソッドが少ない「.NET Native」プロファイルができてる。
その他に制限とかは?
C#の言語的にも、ほとんど出くわさないような状況だと思うものの、いくつか制限あり。
- 構造体の最大サイズが1M Byte
- 3次元以上の多次元配列が使えない(jugged arrayなら使える)
- ポインター型の配列が使えない
コードの最適化は?
JITと違ってコンパイルに時間かけれるので、ガチガチの最適化コードにしてくれる。コンパイラーはC++のものとコードを共有してるらしい。
MSのC++コンパイラーとコードベース共通ってことは、auto-vectorizationとかもやってくれるはず。
(現状対象になっているストアアプリ以外)期待される分野は?
ゲームとか、.NET Micro Frameworkとか。
Windowsデスクトップもまだまだ大事なターゲットだけども、ライブラリの更新に自動追従しない辺りがつらいかも。
Xamarinと成果共有されてiOSとかAndroid向けバイナリも作れると夢広がる。
追記: 4/5(土)
以下のセッションの資料が公開されたので。
6ページ前後、「Compiler in the Cloud」の文字がやたらと強調されてる。やっぱり、ストア上だからネイティブ化しやすいのよねぇ(上記の「ライブラリが更新されたときは?」的な意味で)。
11ページ目、やっぱりauto-vectorization効いてるらしい。実に素敵。というか、さらに、auto-parallelizedとかいう文字まである。
13ページ目、FAQへのリンクあり: