Archive for 12月 2013
C#とILとネイティブと
プロ生でしゃべってきた。
- 12/21 プログラミング生放送勉強会 第27回@品川
- 【中継】プログラミング生放送勉強会 第27回@品川 (ニコ生。3:15 頃からが自分の発表)
スライド:
SkyDriveにもアップロード: C#とILとネイティブと
日程被ってなかったらグラニの新オフィスにも遊びに行ってみたかったんだけどもなぁとかも思いつつ。
まあ、時間の制限もあるのでかなり簡素化した例ですが、.NETのメタデータ辺りに焦点を当てた内容。
もうちょっとガッツリやれるなら、「じゃあ、C++みたいな言語だとどうしてるの」「pimplパターンとかを使う理由」「COM」みたいな話も入っててもよかったかもと思いつつ。
ニコ生での質問
そういや、帰宅後、ニコ生の録画を見てみたりもしてるんですが。生放送中は放映担当の人越しに1個だけニコ生コメントの質問に答えたりもしましたが、他にも妙な質問いくつかコメント流れてるw
いくつか回答。
- Q. 彼女いますか!
- てか、新婚です
- Q. なんで未確認飛行なんですか
- ++o++ みたいなののこと、おっさんはUFO演算子とか呼ぶの
- 古いCコンパイラーだと、++o++がコンパイル通るの(今の仕様では通らない)
- while(++*p++); とかだと意味のあるコードに一応なるの
- ちなみに、C#の発表があったときに、研究室(当時は学生)の同期が「じゃあ、次はこんな言語名とかいいんじゃない?」とかいう話をしてて、その中の一つが ++C++
- ++o++ みたいなののこと、おっさんはUFO演算子とか呼ぶの
- Q. 海賊版対策についてどう思われますか?
- (ILが逆コンパイルしやすいことに対する対策のことかな?)
- まあ、コアな部分はサーバー側に置くのがいまどきではないかと
- クライアント側も、難読化されたILを読もうとまでする人はそこまで多くないと思うものの
- Q. C#未経験用のおすすめの本
- 自分は仕様書とか読んじゃうタイプなので未経験者向けの本って言うとあんまりわからないのだけど…
- よく聞くのはオライリーのやつ?
- 自分が関わってるやつだと、中さん、猪股さん、山本さんとの共著の【速攻入門】C#プログラミングが一番売れてるっぽい
- Q. (C#のコンパイラの)改善内容は公開されてるんですか?
- (Roslynのことでいいのかな?)
- 大まかなデザイン ゴール(VSとの連携性を高めたいとか、既存コンパイラーのコード保守がそろそろきついとか)については開発者のブログにちらほら
- もっとフォーマルな資料は、まだ全然そろってない段階
- Q. 晩飯なににしますか?
- 懇親会で食べてたし。品川の「天狗」
- Q. ILサポートの言語中で、やっぱC#が一番ILの効率がいいですか?
- 実は、意味論的には(.NET以降の、つまり、VB7以降の)VBとC#って差がなくて、生成するILも大差ない
- ガチガチの最適化はJITがやるので、ILはどの言語でもそんなに差が出ないはず
- 何をもって効率がいいというかによるけども、例えば「関数型な書き方した方が効率がいい」みたいなアルゴリズムならF#の方が効率よかったりするかも
- Q. 今期のおすすめ深夜アニメを教えてください
- ニコ動でしかアニメを見ないので何が深夜かがまずわからなかったりするものの…
- 化物語?
- 白猫
The Future of C#
twitterで見かけた話題(1, 2)。ロンドンのイベントでMads(C#のプログラム マネージャー)がC#に追加するかもしれない(したいけど、まだ文法的に確定してない)機能について話したみたいですね。
- The Future of C#(イベントのページ)
- Channel9の掲示板での話題、同 別エントリー
早期プレビュー
C#ってこれまでのノリだと、コンパイラーとか仕様書までできた段階で情報を公開していたわけですけども、今回は「ご意見求む」なレベルでの情報公開。
MSDNブログとかChannel9でなくて、ヨーロッパ ローカルなイベントで初めて公にしたのも、ブログとかでまとめるような段階でない本当に早期プレビューなせいなのかも。
C# 言語チームの開発体制自体の変化を感じたり。
新文法(候補)
で、(twitter越しで見れる)スライド中の情報から読み取れる文法について。
primary constructor (コンストラクターの簡易文法)
F#ではおなじみな、簡易な文法でのコンストラクター生成ができるっぽい。
例えば現状のC#で immutable な型を作ろうとすると、以下のような感じになります。
public class Point { public int X { get; private set; } public int Y { get; private set; } public Point(int x, int y) { X = x; Y = y; } }
もしくは
public class Point { private int _x, _y; public int X { get { return _x; } } public int Y { get { return _y; } } public Point(int x, int y) { _x = x; _y = y; } }
いったい何か所に x とか y とか書かせるんだよ、という。
それが、以下のように書けるようになるっぽい。
public class Point(int x, int y) { public int X { get { return x; } } public int Y { get { return y; } } }
たぶん、(既存の)コンストラクターとフィールドの自動生成かと。
read only auto-properties (読み取り専用自動実装プロパティ)
上記の新しい簡易コンストラクター構文と組み合わせて便利そうなのが、readonly 自動実装プロパティ。以下のような構文みたい。
public class Point(int x, int y) { public int X { get; } = x; public int Y { get; } = y; }
たぶん、さっき書いたみたいなフィールドと、その初期化用コンストラクターの自動生成。結果できるコードは↓こういうの。
public class Point { private int _x, _y; public int X { get { return _x; } } public int Y { get { return _y; } } public Point(int x, int y) { _x = x; _y = y; } }
property expressions/method expressions(ラムダ式形式のプロパティ、メソッド定義)
今、匿名関数って、単文(式1個)か複文(ブロック持ち)かで2種類の書き方ができます。
Func<int, int> f1 = x => x * x; // 式1個 Func<int, int> f2 = x => { // ブロック持ち Console.WriteLine(x); return x * x; };
で、普通の(名前付きの)メソッドとかプロパティでも両方書けるようになりたいという話。{ return … } だけの式1個の実装書くのにいちいち return 書くのめんどくさかったわけで。
今の書き方:
public class Point { // 上記コードと被る部分は省略 public double Dist { get { return Math.Sqrt(X * X + Y * Y); } } public Point Move(int dx, int dy) { return new Point(X + dx, Y + dy); } }
新しい文法:
public class Point(int x, int y) { // 上記コードと被る部分は省略 public double Dist => Sqrt(X * X + Y * Y); public Point Move(int dx, int dy) => new Point(X + dx, Y + dy); }
static type using statements (静的メソッドの using)
Math.Sqrt みたいな、静的メソッドを、「クラス名.」の装飾なしで直接呼べるようになるみたいです。
今の書き方:
public class Point { // 上記コードと被る部分は省略 public double Dist { get { return Math.Sqrt(X * X + Y * Y); } } }
新しい文法:
using System.Math; public class Point { // 上記コードと被る部分は省略 public double Dist { get { return Sqrt(X * X + Y * Y); } } }
params IEnumerable
今のC#の文法だと、可変長引数は配列で受け取る(params T[] args)必要があったわけですが、IEnumerable で受け取れる(params IEnumerable<T> args)ようになるみたいです。
monadic null checking (null 伝搬メンバー アクセス)
以下のようなコード、結構よく書くわけですが。
if (points == null) return null; var first = points.FirstOrDefault(); if (first == null) return null; var x = first.X;
あるいは、式が短いうちは条件演算子なんかもよく使ったりするわけですが。
var x = points == null ? null : points.FirstOrDefault() == null ? null : (int?)points.FirstOrDefault().X;
null って割かし、
- (null 伝搬)引数に null を受け付けて、戻り値に null を返す
- (null 非許容)null 自体受け付けない。引数に null が来たら ArgumentNullException
の2択だったりするわけで、前者を選んだ場合にはこの手の null チェックがめんどくさいことこの上ない。
で、この null 伝搬用の演算子 ?. を追加しようという。
var x = points?.FirstOrDefault()?.X ?? -1;
constructor type parameter inference (コンストラクターでのジェネリック型引数推論)
ジェネリック メソッドの場合、引数の型から型引数を推論できて、明示的に Method<T>(x) とかの <T> の部分を書く必要はありません(引数から推論が効かない場合は除く)。
ところが、コンストラクターの場合は引数からの推論ができず、 <T> の部分の明示が必要でした。
これに対して、新たに、コンストラクターでも型引数推論が効くようになるようです。
これまで:
var t = new Tuple<int, string>(0, "abc");
もしくは、型引数推論のためだけに別途ファクトリー メソッドを作って:
var t = Tuple.Create(0, "abc");
新しい文法:
var t = new Tuple(0, "abc"); // これで、Tuple<int, string> が作られる
inline declarations (変数定義が式に)
C# 3.0以降、ローカル変数はたいてい var キーワードを使った型推論で定義できて便利なわけですが… それを阻害するのが out 引数。out 引数は var 使いにくい、メソッド チェインもしにくいで、極力使うなといわれるように。
int x; // 邪魔! if (int.TryParse(text, out x)) x …
で、これに対して、以下のような文法を追加するみたい。
if (int.TryParse(text, out var x)) x …
変数定義自体を式にしてるんだと思うので、たぶん、例えば以下のようなこともできるんじゃないかと。
while ((var line = stream.ReadLine()) != null) { line ... }
if ((var x = obj as Point) != null) x ...
just-do-it
まあ、C# 4.0 の dynamic とか 5.0 の async/await と違って、こまごまとした文法追加。でも、どれも確実に便利になりそうなものです。C# 3.0 の時にも大量に追加された、「関数型言語とか軽量言語方面ではよく見る文法」の輸入的なものが多いですね。
いくつかは、要望としてよく見るものです。これまで、async/await のような大きな機能を入れるために手を付けれずにいたもの。なので、今年の build であったインタビューなんかでは「just-do-it(とにかくやれ)的な要望がたまっている」なんて言葉も見られました。それを、「we just do it!」(やるよ!)という。
で、その前提には Roslyn の実装作業が落ち着いたってのもあるはず。Roslyn ができたことで、新文法の実装コストが下がって、機能追加がしやすくなったから、これまで難色を示していたような機能にも手が出せるようになったと(これも build のインタビューにて言ってた)。