Quantcast
Channel: ++C++; // 未確認飛行 C ブログ
Viewing all 482 articles
Browse latest View live

ピックアップRoslyn 1/9: structural typing

$
0
0

C#にstructural typing(構造的型付け)を入れようという案。

まあ、「何人かでちょっとディスカッションしたよ」というくらいの段階みたい。やりたいことの説明や、構文の案(3案ほど)が出ている程度(実装方法に関する言及あまりなし)。

以下、structural typingがどういうものなのかについて簡単に説明。

Goのインターフェイスがそうなんですが、明示的な実装を必要とせず、「同じシグネチャ(名前+引数一致)さえ持っていればなんでもOK」という方針で代入可能な型システムをstructural typingと言います。

Javaとか.NETのインターフェイスやクラスの継承・実装、C++のクラス継承なんかは、以下のように、明示的な参照・実装が必要になります。こういうのはnominative(指名的、任命的)な型付けといいます。

.NETのインターフェイス(nominative typing)

一方で、Goのインターフェイスは、(C#で提案されている案の1つを使って類似機能を書くと)以下のように、シグネチャだけ見て暗黙的に「実装されている」ことにしてくれます(これが、structural)。

structural typing

もちろん良し悪しあって、以下のような感じ

  1. nominativeな方が若干実行性能がいい
  2. ただ、structuralの方はほんの小さなコストで、結構大きな自由度が手に入る
  3. structuralの方は、実装クラス側が知らず知らずのうちに合わない構造に修正される可能性がある

3番目の「知らず知らずのうちに修正」が怖いので、Javaとか.NETとかみたいな動的リンクが基本のプログラミング言語ではstructuralのデメリットが大きいんですが。Goの場合は静的リンクだからインターフェイスをstructuralにできたというのもあるはず。

とはいえ、別にどっちか片方だけでないといけないということもないわけです。C#では、普通のインターフェイスはnominativeだけど、追加でstructuralな何かを加えて使い分けたってかまわないはず。「知らず知らずのうちに修正」問題をどう対処するかだけ決まればC#でもstructural typingの便利さを享受できるはずです。


ピックアップRoslyn 2/6

$
0
0

コンストラクター引数を元にオブジェクトの分解(deconstruction)

Proposal: Positional deconstruction based on existing constructors and properties #8415

パターン マッチングで、現在提案されている範囲では、is 演算子みたいな特殊なメソッドを1個追加してやらないと、o is Person("Alan", var last) みたいな感じのマッチングができません。

これだと、今後追加する型(特にレコード型)に対してなら使えるけども、既存の型には全く使えなくて困る。一方で、現状でも、以下のコードみたいに、コンストラクター引数とプロパティに1対1の関係があるようなクラスを書く人は多いわけで、この規約ベースでオブジェクトの分解をできないかという提案。

public class Person
{
  public Person(string firstName, string lastName) 
  { 
    FirstName = firstName; 
    LastName = lastName; 
  }
  public string FirstName { get; }
  public string LastName { get; }
}

確か自分もこのパターンでクラスを書いていることが多いんで、にこの機能が入れば、それらを1個1個レコード型に置き換えたりしなくてもパターン マッチングが使えて大変便利。

でも、引数のfirstNameとプロパティのFirstNameの対応関係を規約ベースでやるのは、C#の文化(規約を嫌う、識別子は大文字小文字を区別する)的には合わないんで悩ましい感じ。ついてるコメントも賛否両論です。

Swift 2.0

Swift 2.0でdeferとguardが入ったわけですが、先月、それはC#には適するかどうか、議論用のissueページが立ちました。

ついてるコメントからすると、賛否は半々くらいか、ちょっと否定が多いくらいかなぁ。個人的な予想では、採用されない気がする。

defer

try { 処理 } finally { 後始末 } の代わりに defer { 後始末 } 処理 と書くような構文。

    {
        SomeType thing = Whatever...;
        defer {
            thing.Free();
        }
        // some code code using thing
    }

メリットは以下のような感じ。

  • using 相当の機能を、IDisposable 実装していなくてもできる
  • try-finally と比べて、「処理」の部分がネスト深くならない
  • try句内と、finally句内の両方で使いたい変数をわざわざその外側で宣言する必要がない

ただ、以下のような問題も。

  • defer が複数並んでるとき、その実行順はどうすべき?
  • try-finally でできることに対してわざわざ新構文増やすの?
  • 1回り外側のブロックに対して影響を与えるような構文ってなかなか理解されにくい

guard

if (絶対満たすべき条件) ; else throw 例外; みたいなよくあるパターンに対して使う構文。絶対満たすべき条件だし、満たしてなかったら必ず例外を投げる(そこから先を絶対に実行しない)ことを保証するために、if じゃなくて guard を使おうというもの。

まあ、そういうものがほしいこともあるというのはわかるものの、コントラクトと被ってるし、そもそもguardの必要性を減らせそう(コンパイル時にチェック可能で、実行時に例外投げる必要がない)な構文もこれから増えるだろうし。

.NET Coreへの移植

$
0
0

twitterで流れてきてて、気になったやつ。

内容的には、

  • フィードバック募集中なのでお願いします
  • .NET Coreは今、ASP.NET、UWP、コンソール アプリに使えるけども、.NET Frameworkからの移植のモチベーションはそれぞれ何か
  • .NET Framework と .NET Coreの関係・差分
  • 意図して.NET Coreには取り込まなかったものがちらほらあるから注意
  • .NET Core化するかどうか、単純に時間的な不足で検討してないものもちらほら
    • 特にフィードバックほしいのはここ。ほしいかどうか、優先度付けしたい
  • 移植にあたってのコツ

みたいなの。

以下、さらっと概要。

何を移植するか

ASP.NET

移植する理由:

  • .NET Coreならクロスプラットフォーム。MacやLinuxで動く
  • マシン全体に対するインストールじゃないんで、デプロイが楽(管理者権限とかも不要でバージョン変えれる)

移植するとよい候補:

  • MVC/Web API使ったものなら移植しやすいのでお勧め

あまり移植に適してないもの:

  • WebFormsは .NET Coreに移植してないので、WebFormsを使っているものは以降大変。ほぼ再実装に
    • もちろん、そろそろWebForms自体をMVCとかに置き換えたいと思っているなら話は別

UWP

移植する理由:

  • (.NET Coreへの移植というか、既存GUIフレームワークからUWPへのという意味で)PC、tablet、phablet、phone、Xbox、IoTデバイスと、広範囲のデバイスで統一的なアプリ開発ができる

移植するとよい候補:

  • Windows 8/Windows Phone 8.1アプリは最初から.NET Core
    • .NET Coreの前身というか、いずれ.NET Coreが出ることを前提として設計されたというか、ほぼ Windows 8アプリ = .NET Core + Windows UIフレームワーク
  • Silverlightアプリも、開発モデルはUWPとかなり近い

あまり移植に適してないもの:

  • Win32なデスクトップ機能をフルに使ったWindows ForsmアプリやWPFアプリは
    • ただし、WPFアプリのXAMLを使った開発スタイルはUWPとかなり近いので多少楽

コンソール アプリ

移植する理由:

  • これも、クロスプラットフォーム対応
  • .NET Native (事前に必要な部分だけネイティブ化した単一実行ファイルを作ってしまう機能)を使いたい場合

移植するとよい候補/あまり移植に適してないもの:

  • 単純に依存しているライブラリが.NET Coreに対応してるかどうか次第
    • ASP.NETやUWPと比べるとハードル低いはず
  • 例えばCOMとか使いまくったWindowsとかOfficeの自動化アプリは移植できないだろうし移植の意味もなさそう

.NET Coreと.NET Framework

.NET Coreは、ある程度.NET Frameworkのサブセットになるように作られてるというか、Visual Studio 2015時点くらいまではそうなるようにある程度頑張ってたはず。でも、ずっとそうなるように維持するつもりはないみたい。現状でも.NET Core側だけにある機能がちらほらあるし、今後はまず.NET Core向けに機能実装されてくことになるはずだし、それが.NET Framework側にバックポーティングされる保証はない。

といっても、かなりの部分は.NET Core向けと.NET Framework (4以降)向けでコード共有できるはず。

差が生じる理由は大まかにいうと以下の3点に由来:

  1. NuGetベース
    • .NET Frameworkはシステム全体に対するインストールが必要
    • .NET CoreはNuGetパッケージ マネージャーを使ってモジュールごとにバージョン管理可能
    • なので、大体において、.NET Coreの方が新機能を早く使える
  2. きれいにレイヤー分け
    • .NET Frameworkではレイヤー分かれず低層から高層まで丸ごと含んでたようなライブラリが結構ある
    • .NET Coreではその辺りを整理して分割したものがある
  3. 問題ある技術の除外
    • .NET Framework 15年の歴史から、問題がはっきりしてて、新規実装の際には取り入れたくないものがある

変化の激しいもの: リフレクション

リフレクションは結構APIが変わっていて困るもの代表で。理由は:

  • レイヤー分けの問題: objectType に依存することで、System.Reflection過剰に参照されかねない
    • Typeには型識別(型の一致判定とか、型の名前を取得したりとか)だけ残す
    • 動的実行や動的コード生成に必要な情報はTypeInfoに分離
  • そもそもリフレクション非推奨
    • .NET Native (事前ネイティブ化)とは相性悪すぎる

.NET Coreには実装しないもの

AppDomain

理由: .NET Coreみたいな層でサポートするにはコストが高すぎる。.NET Nativeでは使えない

代替技術: コード分離(isolation)はプロセスとかコンテナーとかの技術使ってほしい。動的なDLL読み込みのためにはAssemblyLoadContextっていう新しいクラスがある

リモーティング

理由: RPC(remote procedure call)自体がいまいちと認識されてる。AppDomain間の通信みたいなものなので、非常に高コスト。

代替技術: プロセス間通信だったらpipeとかmemory mapped fileとかを使うべきだし、マシン間通信だったらHTTPとか使ったネットワーク ベースの技術使うべき。

バイナリ シリアライズ

理由: privateなデータまでアクセスしちゃうし、互換性を取る上で重荷でしかない。

代替技術: 要件によって最適なシリアライザーは変わるだろうけど、それを要件に合わせて選んでほしい。候補としては、data contract serializerXMLシリアライザーJSON.NETprotobuf-netなど

サンドボックス化

理由: これも.NET Coreみたいな層でサポートするにはコストが高すぎる。正しくサンドボックス化するのはかなり難しくて、信頼も置けない。

代替技術: OSレベルでのセキュリティ境界を使ってほしい。

移植も考えているもの

現状の.NET Coreにないものはもっといろいろあるものの、移植しないと決まったわけじゃなくて、単純に時間が足りないものもある。これに関しては、移植の必要性がどのくらいあるか、特にフィードバックがほしいみたい。

  • System.Data
  • System.DirectoryServices
  • System.Drawing
  • System.Transactions
  • System.Xml.XslSystem.Xml.Schema
  • System.Net.Mail
  • System.IO.Ports
  • System.Workflow
  • System.Xaml

移植にあたって

既存の.NET Framework向けのアセンブリがどのくらい移植しやすそうか解析するツールがあるみたい:

で移植の流れとしては、

  • とりあえず .NET Framework 4.6.1にしとくと.NET Coreとの差が少ない。
  • 元のコードは .NET Framework ターゲットのまま、このツールを掛けつつ修正してとか繰り返すのがおすすめ。
  • .NET Coreへの完全移行じゃなくて、Core/Framework両方で使うとかもあるだろうからその場合はShared SourceとかPCLとかを活用

とかそんな感じ。

Windows 10アプリ開発に関する近況 (Astoria開発中止とか)

$
0
0

以下のブログがちょっと話題になっていますが。

An Update on the Developer Opportunity and Windows 10

Windows 10アプリ開発に関する近況的な話で、Xamarinとか各種ブリッジ(他の環境向けアプリからの移植)とかの現状を説明しているんですが。

Xamarin買収の話と同時期に出したせいとか、ブログの内容がいまいちとか色々あり… なんか変な印象になってるなぁとか、ちょっと不安な感じ。文章読んでて受ける印象的に、これ、そんなに技術に詳しくない広報の人が、技術者から聞いた内容を元に書き起こしてて、微妙に正確じゃない表現になってるんじゃないかなぁとか思ったり(Windowsチームはそれをやらかしそう、という偏見もあり)。

Bridge for Android (コードネーム「Astoria」)の開発停止

この記事、「マイクロソフトはBridge for Android (Astoria)の開発停止を認める」とかいう話題にされてしまっていて。それはこのブログの本題じゃなかったと思うんだけどなぁ…

まあ、去年の11月にはそういう話が出ていたんですが、 確かに、ブログで明示的に停止した話が書かれたのは初めてなのかな… そのせいで、なんか騒動になっているみたいで。

ですが、 Xamarin買収のタイミングで変な文章を書いたので「AstoriaとXamarin、2つは必要ない」という主張だと誤認されたり、 Bridge for iOSとの関連の説明が下手なせいで「ブリッジ技術にAndroid向けとiOS向けの2つは必要ない」と取れる文章だったり、 なんか変な感じ(なので、これ、非技術者な広報担当者が書いてるなぁという印象です)。

クロス開発と、ブリッジと

そもそも、クロス開発と各種ブリッジは相補的というか、逆のことをやっているというか。

クロス開発は、これからスマホ向けアプリを作ろうとする人に、UWP (Windows 10 Mobile)も選択肢に入れてもらう(iOS、Android、Windows全部をターゲットにしてもらう)ためには何を使ってほしいかという話。マイクロソフトが提供する選択肢としては、

  • Visual C++ Cross-Platform Mobile
    • C++でクロス開発するためのプロジェクト テンプレートとかデバッガーとか
    • 今、Android開発に関してはJavaにも対応してたり
  • Apache Cordovaと、そのVisual Studio対応
    • JavaScriptでWeb的に(UIもHTMLで書いて)ネイティブ アプリ化する
  • Xamarin
    • Mono ベース/C# でクロス開発

とかがあったわけです。

一方、ブリッジは、特定環境向けに作られた既存のアプリをUWP化してもらうための技術。開発が続いてるのは、

  • Web Bridge (コードネーム Westminster)
    • Web技術をそのままUWP化
  • Win32/デスクトップ向け.NET移植 (コードネーム Centennial)
    • デスクトップ アプリをサンドボックス動作させるだけっぽい
  • Bridge for iOS (コードネーム Islandwood)
    • Objective-Cで書かれたiOS向けコードをビルドして、UWP化できる機能

など。

で、今回、開発停止が正式になったというのが、以下のAstroia

  • コードネーム Astoria
    • Windows 10にAndroid互換レイヤー(JVM + Android API)を載せて、エミュレーションしようという技術
    • ここが Bridge for iOSとの差。ソースコード レベルでの移植じゃなくて、バイナリをそのまま動かそうとしてた

Java for Android対応

一方で、今のVisual Studioって、JavaでのAndroidアプリ開発には実は対応していたり。

これ、しかもちょっと面白いのが、C++チームが保守してる(上記ブログはC++チームが書いたもの)という事実。

今、マイクロソフト内のC++チームが負ってる債務は「クロス開発」のようです。 その結果、Android開発はC++チームの範疇で、Java for Android対応もC++チームの債務。

という背景から、Androidからのブリッジも、Bridge for iOS (Objective-Cからのビルド)と同じく、JavaソースコードからUWPを作る機能であるべきなんじゃないかなぁという感じ。

で、実際、Astoriaの開発停止の話が出たのって、このJava support in Visual Studio for Androidが出たのと同時期だったりします。

結局のところAstoria開発停止の理由

実際のところは中の人に聞いてみないとわからないものの、僕が受けた印象としては、以下のような話だったんじゃないかなぁと。

  • Xamarinとの関連
    • 「Xamarin買収の話題をきっかけに、いったん現状報告しとくか」程度であって、Astoria開発停止とは完全に無関係
  • Bridge for iOS との関連
    • 本来いうべきこと: Bridge for iOS同様、ソースコードからのビルドであるべきではないか。互換レイヤー提供によるエミュレーションと、ソースコードからのビルドの2方式あるのは混乱の元
    • ブログの文面: Bridge for iOSに注力する。2つのブリッジ技術があるのは混乱の元
  • 実際あり得そうな本来のAstoria開発停止理由
    • Java support in Visual Studio for Android をベースに、Javaソースコード レベルでUWP化に対応するのが筋
    • ここが「計画としてはあるけどまだめどが立ってない、あるいは、//build/辺りでの発表目指してる」とかで今は何も言えない
      • 言えない(というか、できるかどうかもわかんない)ことをお茶を濁した結果がブログの微妙な文面

伝言ゲームで文面が変になったり、言えないことをお茶を濁して余計言っちゃいけない感じの文章になったり、まあ、割かしよくあることだと思います…

ピックアップRoslyn 3/1: position-to-propertyマッチ

$
0
0

久々にMads降臨(C# チームのLanguage Design Meetingの議事録投稿)。

3つの言語機能を紹介しているんですが、共通して「position-to-propertyマッチ」というのが必要になります。 このposition-to-propertyマッチを許す「主義」を採用することに決めたという報告です。

position-to-propertyマッチ

簡単に言うと、例えば以下のようなクラスがあったとき、

public class Person
{
    public string FirstName { get; }
    public string LastName { get; }

    public Person(string firstName, string lastName)
    {
        FirstName = firstName;
        LastName = lastName;
    }
}

コンストラクター第1引数のfirstNameとプロパティのFirstNameには1対1の対応があります。同様に第2に引数lastNameとプロパティLastNameもです。 こういう、1対1の関係を、(先頭の1文字の大小の差は無視して)名前をベースに調べて、

  • FirstNameというプロパティと、コンストラクターの第1引数を同一視する
  • LastNameというプロパティと、コンストラクターの第2引数を同一視する

というような、引数位置(position)とプロパティ(property)の間の同一視を用いようという意味合い。

結構これを認めるのはC#としてはチャレンジになります。「頭文字の大小を無視」も、「名前の一致を見て同一視」も、これまで結構避ける主義でした。

ただ、以下に紹介する機能を、既存の型に対しても使えるようにしようとすると、どうしてもこういう仕組みが必要になります。

3つの新機能

position-to-propertyマッチを使う3つの新機能は以下の通りです。

  • immutableオブジェクトに対するオブジェクト初期化子
  • with式
  • 位置指定のパターン(positional pattern)

immutableオブジェクトに対するオブジェクト初期化子

先ほど出したPersonクラスみたいなimmutableなオブジェクト(プロパティがget-onlyで、値の書き換え不能)を初期化したい場合、コンストラクター引数に値を渡す必要があります。でも、オブジェクト初期化子構文を使っての初期化を行いたいことがあります。なので、

new Person { FirstName = "Mickey", LastName = "Mouse" }

というコードを、

new Person("Mickey", "Mouse")

に置き換えようという機能を提供したい。

で、このためには、どのプロパティがどの引数に対応するか知る必要があります。

with 式

immutableなオブジェクトは、値の変更も面倒になります。書き換え不能なわけで、わざわざ、一部の値を変更したうえで、新しいオブジェクトを作る必要があります。この面倒を軽減するために、with式という構文が提案されています。

以下のような書き方で、

p with  { FirstName = "Minney" }

以下のようなコードを生成します。

new Person("Minney", p.LastName)

こちらも同様に、プロパティに対応する引数を知る必要があります。

位置指定のパターン

C# 7に向けて実装中のパターン マッチング機能で、以下のようなコードが書けます。

p is Person("Mickey", *)

これは、pの型がPersonかつ、FirstName"Mickey"ということを調べる式です。

第1引数がfirstNameなので、対応するプロパティFirstNameの値を調べます。

こういう書き方は位置指定のパターン(positional pattern、あるいは、position-based pattern)といって、コンストラクターの逆操作です。

p is Person("Mickey", *) ⇔ new Person("Mickey", "...")

一方、以下のようにプロパティ指定でのパターン(property pattern)もあって、こちらはオブジェクト初期化子の逆操作になります。

p is Person { FirstName is "Mickey" } ⇔ new Person { FirstName = "Mickey" }

そして再三になりますが、この位置指定のパターンにもposition-to-propertyマッチが必要になります。

もちろん、position-to-propertyマッチに頼らない明示的な挙動の上書きも用意する(GetValuesメソッドや、is演算子のオーバーロードなどが候補になっている)つもりだそうですが、既定の挙動としてはposition-to-propertyマッチを使いたいとのことです。

既存の型への新構文の適用

position-to-propertyマッチを認めるというのは、結構、C#としては主義の変更というか、大幅な妥協ではあります。 (当然、issueページのコメント欄は、結構な割合でネガティブなコメントが埋まっていたりします。)

最初は、レコード型という新しい構文を用意して、その構文で作ったクラスや構造体で、上記の3つの構文を使えるようにする(使うための特殊なメソッドを生成する)つもりで考えていました。

が、その場合、既存の型には上記の便利な構文が使えないことになります。そして、すでに世に出回っている多くのコードに対して逐一「レコード型で書き換えろ」なんて言えるはずもありません。

なのでこの妥協、この主義変更ということになります。 実際のところ、世に出ているコードの多くが、コンストラクター引数とプロパティの名前を(頭文字の大小除いて)同じにしていたりするので、 実用性を考えるとよい妥協しどころではあります。

ピックアップ Roslyn 3/3: タプル ベースのposition-to-propertyマッチ

$
0
0

一昨日のの補足。

先日は以下のようなLanguage Design Notesが出てたわけですが。

コンストラクター引数とプロパティの名前の一致を見て、何番目の引数がどのプロパティに対応するかを調べる(position-to-propertyマッチする)方針を使おうという話。 もちろんいろんな対案あった中で、今、こういう方針に傾いてるという話なんですが、そういう過程抜きに「名前の一致を見る」の話だけしたので多少炎上中。

ということで、対案の1つ、タプルを使ったパターンの話も公開されました。

以下のようなメソッドを用意することで、position-to-propertyマッチしようというもの。 拡張メソッドでもいいことにしておけば、既存のクラスの拡張もできます(ただし、その拡張メソッドを書くのは手動。大変めんどいはず)。

public class Person
{
  ...
  public (string FirstName, string LastName) GetValues() { ... }
  public Person With((string FirstName, string LastName) builder) { ... }
}

with式みたいなものの実現には、既存の言語構文だけでやるならいわゆる「ビルダー パターン」を使ったりします。 そのためにはビルダー用のクラスを1個余計に作らないと行けなくて、余計なメモリ アロケーションが発生したり、余計なクラスを書く手間が掛かったり。

でも、タプル型を使えば、タプルはmutableな構造体なので余計なアロケーションは起きない。 それに、新しいクラスの追加も必要なくて、手間は多少マシになる。 タプルは元々、引数位置と名前の対応関係を持っているので、黒魔術的な特殊処理なしでposition-to-propertyマッチできるはず、ということになります。

とはいえ、以下のように、悪い面もあります。

  • 既存の型に対してそのままでは使えない。GetValuesWithなどの追加(拡張メソッドでもいいけど、手動での追加)が必要
  • オブジェクトの分解(GetValues)やwith式(With)はインスタンス メソッドになるのでvirtualにできても、新規インスタンス作成ではできない
  • (レコード型などの新構文で)コンパイラーが自動生成するコードが増える
  • タプル型という、別の新構文に強く依存することになる(複雑度が増す)

というような話があっての、先日の「名前で解決」の流れになったという話です。

ピックアップRoslyn 3/18

$
0
0

C# 7に取り込む範囲、ある程度決まったみたい

作業リストが更新されてた。

前はあって今消えてるものは単に「7からは外す」という意味。 まだ最終決定でもないんで、ここからまた増減はあるはず。

個人的な印象としては、現状でもそこそこ動いているものだけ残してる感じ。 たぶん、「年に1回リリース」、つまり、今年中のC# 7リリースがかなり現実味ありそう。

ということで、まだちょっと検討が要りそうなものはリストから抜けました。 待ち遠しいけども先送られたのは「非同期シーケンス」と「非null参照型」あたりですかね。

レコード型の仕様書

レコード型の仕様書がやっとできてた。future ブランチにはマージ済み。

expression-bodied な set/get、コンストラクター

set, get 個別に、=> を使った短縮形のプロパティ定義を書けるようにしてほしいとか、そういう要望が前々から上がっていたわけですが。

C# 6の時にも検討されたものの、「要望があるのはわかるけど、そこまで需要高くないし後回し」扱いされていたものです。

それに対して、C# チームの外から pull request が来て、C# チーム的にも「それをベースに実装するか」という流れになっている模様。

サロゲートペア識別子対応

日本人的に、ほしければ「Add your reaction」で +1 だけでもつけといた方がよさそうなものが。

サロゲートペアになってる文字でも、文字カテゴリーが letter になってるんだったら識別子に使えるべきじゃないかという話。

要するに「𩸽」(ほっけ。U+29E3D)とかの話。

C# 的には、letter系のカテゴリーに含まれている文字を識別子に使えるという仕様になっています。 ただ、.NETが内部的に16ビット(UTF16)で文字列を持ってるせいで、サロゲートペアになってる文字はカテゴリーを正しく判定してもらえない。

要するに、以下のようなコードを実行すると、結果はSurrogateになります。

char.GetUnicodeCategory("𩸽"[0])

とはいえ、以下のように、charじゃなくてstringを受け付けて、サロゲートペアな文字でも使えるオーバーロードに書き直せばちゃんと判定できます。 𩸽の場合はOtherLetter。

char.GetUnicodeCategory("𩸽", 0)

ってことで、

  • C# 実装なRoslyn的に、実は判定自体はできる
  • でも、2文字見ないといけなくなってそれなりにコンパイラーに負担が掛かる
  • それで使えるようになる文字というと、日本語的には𩸽みたいなレアな文字
    • このissueページで言われてるのは「シュメール語の文字を使いたい」みたいな要望

という感じ。

それでも、この手の文字を識別子に使いたいですか?使いたいなら、reactionしておきましょう。

Visual Studio 2015 Update 2がRTM & Visual Studio "15" Preview

$
0
0

昨日は夜更かししていたわけですが。

なんか今回は「本来はWindowsのイベント」らしさがあり、ほんとにWindowsの話題ばっかり。 開発ツール系の話が初日キーノートに出てこないという。 内心「やべぇ、しゃべることねぇ」とかおびえながらのひな壇芸人やってました。 危うく、ただ池澤あやかさんに会いに行くだけのミーハーになるところでした。

開発ツール系は2日目の今晩のキーノートで話すんですかね。確かに最近そういう構成になってること多い。前の方にコンシューマー受けするもの、後ろの方に開発系。

そして、キーノートでまったく触れられないまま、さらっとMSDNブログで公開されるVisual Studio。

Visual Studio 2015 Update 2

そういえば、プレビュー版、RC版が出たときにあんまり取り上げてなかったなぁと。

C# に関連する新機能は4点ほど

  • ソースコードを選択 → 右クリックメニューの「Execute in Interactive」から、C# Interactiveにコードを送れる
  • Add Using (using ディレクティブの追加)に対するあいまいマッチング
  • アナライザーAPIの性能改善
  • 標準提供のリファクタリング機能にいくつかの新アクション

上の2つは簡単に触れておこうかと。

Execute in Interactive

ソースコードの1部分の実行結果を今その場で知りたいときに便利。

ではあるんですが、これ、プロジェクトのコンテキストを取り込んでくれない(そのプロジェクト内で自分で定義した型は使えないし、参照してるライブラリもCV# Interactiveからは参照されない)ので微妙に不便。標準ライブラリ内のクラスしか使えないんですよね。「Json.NETのシリアライズ結果の挙動を知りたい!」とかもできない。計画上はNuGetパッケージの参照とかはC# Interactiveウィンドウ内からできるようにしたいって話があった気がするので、まあ、今後に期待ですかね。

Add Using あいまいマッチング

「usingディレクティブってソースコードの上部にしか書けないからうざい。今まで使ってなかった名前空間の型を新たに使いたくなった場合、いちいちに上に移動するのがめんどくさい。」という不満にこたえる「Add Using」機能ですが、これまでだとクラス名を正確に打たないと「Add Using」できなくて、微妙に不便でした。

というのも、IntelliSenseであれば、

  • 全部小文字で打っても補完でCamelCaseなメンバーを見つけられる
  • 途中まで打てば補完で長い名前を打てる

という機能があって、もうさぼり癖がついてるわけです、C#開発者は。 それが、「Add Using」したければクラス名を正確に全部書けとか、無理。

挙動を見てる感じ、

  • 全部小文字で打っても認識
  • 文字が1・2文字まで間違ってる/足りてない状態でも認識
    • 単語の長さによるっぽい

という感じ。 streem(Stream)、dianostic(Diagnostics)とかそんなのがちゃんと補完されます。 スペルを正確に覚えるのが面倒なときに便利。 queueみたいな2文字違いどころじゃないレベルの単語が相手だと少々厳しいですが…

全部小文字で打って、Add Using

Visual Studio "15" Preview

"15"はもちろん内部バージョンのことです。Visual Studio 2015が"14"。つまり、次期バージョンのプレビュー。

これまでだと、マイクロソフトの製品って2・3年サイクルでリリースしてました。直近のC#でも、2010でC# 4→2012でC# 5→2015でC# 6です。 最近徐々にリリースサイクルを縮めたがっているわけですが、なので、今年中のリリースが期待されます。

あと、インストーラーが2つあります。今まで通り、isoファイルで丸ごとの提供があるインストーラーと、「lightweight」なインストーラー。

C# 的には、まあ、GitHubのRoslynリポジトリを眺めてると、futureブランチに結構C# 7の新機能がマージされだしておりまして、「おっ、ここまでは近々バイナリでのリリースがあるのかな」などと眺めておりました。

実際大体その通り。1・2週前のプルリクまではVS "15"に入った感じですね。

以下の機能が動きます。ただし、今、C#7の文法を試すにはちょっとしたトリック(条件コンパイルシンボルに __DEMO__ を追加する)が必要になります。

  • ローカル関数(nested local function)
  • パターン マッチング(pattern matching)の一部
  • ref戻り値/refローカル変数(ref returns/ref locals)
  • 2進数リテラル(binary digit)、数値セパレーター(digit separator)

(ちなみに、リリースノートに書かれてないやつも、GitHub上で実装っぽいものがあったものは一通り試しました。その結果、2進数リテラルが動いてることを確認。)

この3/31リリースのプレビュー版で動くC# 7コード、GitHubにサンプルを上げておきました。

DEMO 条件シンボル

今のところ、futureブランチにしかないような新文法は、コンパイラー オプションを追加しないと使えない状態になっています。 で、Visual Studio上からどうやってそのオプションを追加するの?という話なんですが… 追加できないです。対応追いついてないようで。

じゃあ、どうやって上記サンプルは動かしてるかというと、抜け道がありまして。 「プロジェクト設定で__DEMO__という名前の条件コンパイル シンボルを定義しておく」という、一時しのぎ感溢れる見事な対応。

__DEMO__ 条件シンボル

名前通り、デモで見せるときに使ったんでしょうね。

ローカル関数

↓こんなやつ。

private static void LocalFunctions()
{
    int F(int n) => n >= 1 ? n * F(n - 1) : 1;
    Console.WriteLine(F(5));
}

まあ、public void X()に対してprivate void XInternal()みたいなのを別途書くこと、たまにあったじゃないですか。 それが必要なくなります。

これまでも、ラムダ式を使えば似たようなことはできましたが、以下の点でローカル関数の方が有利になります。

  • 再帰呼び出しが素直に書ける
  • デリゲート変数への代入が省ける
  • ローカル変数のキャプチャがちょっと賢い
    • ラムダ式: クラスのフィールドに昇格する。ヒープのアロケーションが発生
    • ローカル関数: 構造体のフィールドにして、ref引数で関数に渡される。ヒープ除け

パターン マッチング(一部)

パターン マッチング自体は、最近Build Insiderに寄稿したんでそちらを参照していただくとして。

このうち、位置指定パターンだけは未実装。 次回の記事で書く予定ですが、位置指定パターンだけはちょっと実装が面倒とういうか、 レコード型やタプル型など、他の新機能も合わせて詳細を詰めないといけないので、少し実装が後回しになっています。

まあ、型パターンだけでも使えれば結構便利なはず。

ref戻り値

↓こんな感じ。

struct Buffer<T>
{
    public int BaseIndex { get; }

    private readonly T[] _array;

    public Buffer(int baseIndex, int count)
    {
        BaseIndex = baseIndex;
        _array = new T[count];
    }

    public ref T this[int index] => ref _array[index - BaseIndex];
}

まあ、ほとんどの開発者は直接は使わなさそうですかね。 パフォーマンス改善に期待できる機能です。 ライブラリ作者がこれを使うことでパフォーマンスが上がり、間接的には全ての開発者への恩恵が期待されます。 というか、C# コンパイラー自信のパフォーマンス改善が結構見込めそう。

これに限らず、パフォーマンス改善系の機能追加はちらほら追加されていきそうな雰囲気です。

2進数リテラル/数値セパレーター

↓これは大変わかりやすく。

var b = 0b1000_0001;
Console.WriteLine(b);

こいつはC# 6の頃から新機能候補に挙がってましたし、結構前から実装済みだったはず。CoreFxの方のソースコード見てたらそこらじゅうですでに使われてたり。 前からあるから、今回リリースノートに書き忘れたのかなぁとか思ったり。 「そんなに強い関心があるわけじゃないけど実装が簡単だから実装済みです」、「0bでいいのかとか_でいいのかとか議論の余地もあるし、もう少し寝かせるか」みたいな立ち位置のはず。

lightweightインストーラー

全部の機能はiso版のこれまで通りのインストーラーでないとまだ使えないらしいですが。 それとは別に、今後に期待がかかるlightweightインストーラーってのが提供されました。

これまでの「webインストーラー」と何が違うかというと、

  • 最小構成だと300MB程度でインストールできる
    • 必要な機能は必要に応じて拡張マネージャーで入れる
  • どうも、レジストリを汚さないみたい
    • 既存のVisual Studioを立ち上げっぱなしでもVS "15"をインストール可能
    • 1台に複数インストールとかもたぶんできる
      • プロジェクトごとに別の拡張入れた状態のVSを作るみたいなのもたぶん

という感じ。地味に、大きな変化だったり。


ピックアップRoslyn 4/10

$
0
0

「C# 7」に入る範囲がそろそろ決まってきた感じ。

C# Design Notes for Apr 6, 2016 (Tuples, Recursive patterns)

久々に言語デザインミーティングの議事録が。

タプル型と、再帰的なパターン(位置指定パターン・プロパティ パターン)の詳細がだいぶ決まってきたっぽい。

タプル型は↓こんな感じ。

  • メンバーの数と型が一致していたら、名前は無視して同一視する(代入可能)
    • box化・unboxしても同様の変換ルール適用可能
    • メンバーが int → long みたいな暗黙的型変換できる場合でも、タプル型の自動変換はいったんしないことにする(将来はわからない)
  • 無名タプルも作れる(メンバー名指定なし)
  • 匿名型の new { p.X, p.Y }みたいに、名前の射影(X, Yという名前を引き継ぐ)あり
  • タプル型に対する拡張メソッドも作れる
  • タプル型引数の規定値も指定できるようにしたいけど、そのためには何か新しい属性が必要になる(ので、いったん据え置きになりそう?)
  • 0-tuples, 1-tuplesも検討したい
    • それぞれ、C#チーム内ではnuples, wonples (null+tuple, one+tupleの造語?)と呼んでるみたい
    • nuplesは、要するに「ユニット型」。()で書き表せそう
    • wonplesが難しそう。(Type)(value)も現在のC#で有効な構文になっちゃってるんで
  • タプル型戻り値を、out引数みたいな感じで、メンバー名で代入可能にはしない。return使え

再帰的なパターンの方は、もしかしたら全部やC# 7ではやらないかも。段階的に便利にしていくのでもいいだろうし、後からの追加に耐えれるようにC# 7を作れそう、とのこと。

Language Feature Status

C# 7として出したいもの、だいぶ絞られてきたみたい。状況のまとめページができてます。

概ね、こないだのbuildでデモでプロトタイプが動いてたものに絞った感じ。リリース時期が大まかには決まってきたのかな?この絞り方(今ある程度動いてるものだけをまず出す)の感じからすると、Windows 10のレッドストーンと同時期?

Source Generators

メタプログラミングがらみ、ソースコード ジェネレーターのドキュメントができてた。

これはほんと一刻も早く試したい…

C# as a High-Performance Language

C# vNextのパフォーマンス改善系の提案まとめページが。

Build Insiderでやってる連載の次回のネタ、パフォーマンスにしようかなぁ。

Roslyn自体がパフォーマンス面に関して相当シビアだったり、ゲーム方面でC#が注目されてたり、.NET Coreがベンチマーク向上を頑張ってる真っ最中だったり、今、結構こういう機能が求められています。

ピックアップRoslyn 5/4

$
0
0

4月に紹介したLanguage Feature Status、だんだんはっきりとC# 7、VB 15に入りそうな範囲が結構絞られてきた感じ。

最近は、タプル型がらみに注力してる感じがします。

パターン マッチングも部分的に実装

これまで出てたアイディア全部を一気にC# 7に入れるんじゃなくて、将来的な拡張を阻害しないように気を付けつつ、部分的に実装しようという感じになってる様子。

上記リンクのうち、「Part 1 (targeting future)」になってる方がC# 7に入りそうなやつで、「Part 2 (to remain in features/patterns)」に入ってる方がそれより後のバージョンになりそうなもの。

要するに、C# 7としては、いったん、単純な型による分岐だけを実装するみたい。以下のものはその後の予定。

  • 再帰的なオブジェクト分解の構文
  • let ステートメント
  • match 式
  • throw 式

C# Design Notes (タプル型関連)

4月中にあったC# Designミーティングの議事録。タプル型関連の議題が多かったみたいです(あと、out varの話が少し)。以下のような内容。

  • ValueTuple以外の型
    • C#のタプル型の実装に使われるValueTuple構造体の他に、既存のTupleクラスとか、あと、KeyValuePairなんかも性質としてはタプルっぽい。これらを統一的に扱いたい
  • タプル型の分解(代入、宣言、パターン マッチング)用の構文案
    • (int x, int y) = Get();的なのか、(int, int) (x, y) = Get(); 的なのか、いくつか候補あり。今のところ前者が有力
  • (byte, short)から(int, int)みたいな、メンバー単位で暗黙の型変換がある場合の、タプル型間の変換
    • 認める方向で検討中。ただ、コンパイラーが頑張ることになるし、C# 6と7でオーバーロード解決ルールとかが変わっちゃう問題がある
  • (C#の構文糖衣としての)タプル型と、構造体のValueType
    • null許容型がint?でもNullable<int>でも使えるように、タプル型も(int, int)でもValueTuple<int, int>でも使えるようにしたい
  • パターン マッチングとの兼ね合い

ちなみに、そのValueTuple構造体ですが、ついにcorefxの方に入ったみたい。

(ちょっと前までは、roslynリポジトリ内でだけ実装してた)

非同期メソッドの戻り値を任意の型に

今、Taskクラスしか返せない非同期メソッドに、任意の型を返せるように拡張したいという話。

あと、非同期ストリーム(awaityieldを両方含めて、IObservableとかIAsyncEnumerableのような戻り値を返せるもの)の実装もまとめてディスカッション中。

これは、Language Feature Statusの「(C# 7.0 and VB 15) + 1」にすら並んでないんで、さらにもうちょっと先になりそうなんですかね。

ピックアップRoslyn 5/12

$
0
0

なんでも拡張

拡張メソッドは便利な構文なわけですが、インスタンス メソッドしか拡張できないのが残念なところです。拡張プロパティとかも作りたいことがあるし、静的な拡張(静的メソッドも既存のクラスに対して追加したように見える構文)もほしかったりします。という、なんでも拡張できる構文の案。

今のところ、以下のような構文で検討中。

extension class クラス名 : 拡張したい型
{
    // ここにメンバーは、拡張したい型の拡張メソッド、拡張プロパティなどになる
}

C# Design Notes (タプル型関連 再び)

前回C# Design Notes for Apr 12-22, 2016に引き続き、タプル型関連。

  • 分解
    • (x, y) = tuple; みたいなのを、tuple.Deconstruct(out x, out y); みたいなメソッド呼び出しとして解釈したい
    • タプル型専用の特別な構文にしないために、インスタンス or 拡張メソッドを通したい
    • ちょっと前までGetValueって名前を検討してたけど、一般的過ぎてすでに使われてそうなので、Deconstructメソッドにする
    • 要素の値を返すのはout引数にする。タプル型を分解するのにタプル型を返すわけにもいかないので
  • switchステートメントでの変換
    • 既存のswitchだとintとかstringしか受け付けないので、intとかへの暗黙的型変換できる型は変換結果で解釈されてた
    • 破壊的変更にならないようにするために、暗黙的型変換を定義した型は、今後も変換結果で解釈する
    • なので、そういう型(例えばintへの暗黙的型変換を持ったConst型)は case Const(int i): みたいなcaseにマッチしない(case 0:とかにはマッチする)
    • あんまり起きない状況だし、破壊的変更を避ける方を優先
  • タプル型間の変換
    • 「要素数が一致していて、各要素が暗黙的型変換できるなら、タプル型間でも暗黙的型変換できる」ってルールにするっぽい
  • タプル風のインスタンス生成
    • 任意の型に対して、左辺から型が推論できるなら、new (x, y)みたいな書き方でインスタンス生成できるようにする

最後の「タプル風インスタンス生成」はちょっと補足。

元々の発想は、「分解の構文をDeconstructメソッドを通すことで汎用化したんだし、構築の構文も汎用化すべき」というもの。タプル構築と、コンストラクター呼び出しを紐づけたいということになります。

が、例えば、その発想で行くと、以下のように、なんか直観にそぐわない「タプル型リテラルからの構築」ができてしまう。

Dictionary<int, string> d = (16, EqualityComparer<int>.Default); // さすがにこれは気持ち悪い

代わりと言ってはなんだけど、以下のような、newの後ろの型の省略を認めようという感じになってるみたい。

Point p = new (3, 4); // new Point(3, 4) と同じ
List<string> l1 = new (10); // 引数0個 or 1個でも大丈夫
List<int> l2 = new () { 3, 4, 5 }; // コレクション初期化子との併用もできるけど、() は省略できない

要するに、結局、左辺からの型推論みたいな構文を追加することになりそう。

【開催報告】 //build/ 振り返り勉強会

$
0
0

5/21(土)に勉強会を開いてました。 今回はまどすた(旧めとべや)との共同開催で、//build/の振り返りでした。

以下、当日資料の一覧です。

ルームA (サーバー部屋)

//build/ まとめ(サーバー編)

祝GA、 Service Fabric 概要

Bot FrameworkでBot入門

Introduction to Azure Functions

Bash on Ubuntu on Windows、ちょっとだけWindows Subsystem for Linux

C# 7

ルームB (クライアント部屋)

//build/ 2016現地で感じたクライアント開発の潮流

Holo World ~ はじめの一歩 ~

Build/Evolve 振り返り

デスクトップ アプリがこの先生きのこるには

デスクトップ アプリの生存戦略 (Desktop App Converter)

VR元年のゲーム開発

Cutting Edge!

2進数リテラルと数字区切り文字

$
0
0

C# 7思い出話

C# によるプログラミング入門に、ちらほらとC# 7の話題を書き始めたわけですが。

まあ、入門なんで仕様として固まったものだけを書いていくつもりです。ある程度固まりそうな段階まで書かないし、結局予定から漏れたものは修正したり。

一方で、その仕様が固まるまでにあった流れなんかも、ブログに残しといてもいいかなぁとか思ったり。

ってことで、「C# 7思い出話」なんていうカテゴリー付けて、ブログでも書いてみようというのが今回の話。 さしあたって、今、入門に書いたのが、

の2つなので、今日はこの2つ。

2進数リテラルと数字区切り文字

こういう機能。

var million = 1_000_000;
var abcd = 0b1010_1011_1100_1101; // 特に2進数リテラルで有用
var abcd2 = 0xab_cd;              // 16進数リテラルにも使える
var x = 1.123_456_789;            // 浮動小数点数リテラルにも使える

2進数リテラルと数字区切り文字の2つはセットですね。 2進数って普通に書いたらむちゃくちゃ大きな桁数になりますし。 そりゃ、区切らないと読めた代物じゃない。

この2つの機能、「C# 7」としては「気が付いたらいつの間にか実装があった」って感じです。 特に「実装したよ」アナウンスもなく、pull-requestも見かけず。

そもそも、「C# 7の最初の設計ミーティング」でちょこっと「ページ内検索してみたら確かに書かれてる」程度の地味な取り上げられ方してただけ。機能的にも小さなものなので、提案ページもすごく簡素。

それも当然でして、この機能はC# 6の頃からあったから。 要するに、「C# 6の頃から試験的な実装あったけど、結局C# 6には入れなった」というもの。 仕様的に何か問題があったわけでもなくて、単純に「優先度低、スケジュール的に後回し」。 という話が、今稼働してるGitHubのリポジトリじゃなくて、昔懐かしCodePlex時代にありました。

まあ、こういう、低コスト・低リターン機能は後回しになりがち。

実装するのは低コストと言っても、仕様的に問題ないかをよく考えたり、実際試してみる期間を設けるのはそれなりに大変です。 CodePlex上で、以下のようなディスカッションがあった記憶があります。

  • 区切り文字は _ でいいの?
  • 1010 1100みたいにスペースで区切らせてよ
    • それは字句解析的に面倒で、コストかかりすぎる
  • 8進数リテラルも入れてよ
    • あっても使わないだろ、実際
      • chmodで使うよ
    • C言語の0始まりは紛らわしいし、octalだからって0o (ゼロ、オー)も0とoが区別つきにくいし
  • そもそも、16進数リテラルの0xもなんなの、Xって。hexの3文字目って

簡単な機能であっても、なかなかめんどくさい感じの話に。

ピックアップRoslyn 5/29

$
0
0

拡張メンバー

Design Meetingで拡張メンバーの検討をしてたみたい。 (拡張メンバー = 初期検討段階で「extension everything」(なんでも拡張)って言ってたやつ。拡張メソッド以外に、プロパティとかも拡張できるようにする構文)

現状、以下のような感じ。

  • extension classってキーワードで、通常のクラスを継承したような構文で作る
    • 定義したメンバーは拡張メソッド同様、静的メソッド化される
    • プロパティは、「インデックス付きプロパティ」(ILレベルとかVBにはある。C#のレベルで使ってないだけ)に展開するのがよさそうだけど、現状のC#では認めてないものなのでちょっと悩ましい
  • インスタンス メンバー風の拡張だけじゃなくて、静的メソッドの拡張も足せる
  • コンストラクターも足せる
  • 演算子をどうするかは悩ましい
    • 四則演算とかはいいと思うんだけど
    • == とかが怪しい
  • Personクラスの拡張Enrolleeがあったとして、Personの通常のインスタンス メンバーと、拡張の方のメンバーを呼び分ける構文がほしい
    • 優先されるのは通常のインスタンス メンバー
    • たぶん((Emrollee)person).Supervisorみたいなキャスト構文でやる

コンパイラー組み込み

「時々C#にもインライン アセンブラーがほしい」問題に対して、 別解法の提案。

C#では書けないもの

まず、「ILを使えば書けるけど、C#では書けない」みたいなのの例。

  • CLRがやってるみたいなネイティブ コードとの相互運用をビルド時に静的に作ってしまおうと思うと、いくつかC#では書けない命令が必要
  • infoof(information ofの略。typeofと同じノリでMethodInfoとかを取る)相当の機能をライブラリでやろうと思うとldtoken命令が必要
  • スライスを作るのにC#では書けない機能が必要

インライン アセンブラーはやらない

  • 時々しかない要件のためにILインライン アセンブラーを実装するのはコストに見合わない
  • というか、混ぜるのよくない。C#コンパイラーとILアセンブラーは別ツールとして、別チームが個別開発すべき

別解法の提案

で、提案してるのが「コンパイラー組み込み」(compiler intrinsics: コンパイラーが内在して持ってる実装)。

いくつかのC++コンパイラーは、プログラマーがSSE命令とかAVX命令みたいな特殊な命令を使えるように、コンパイラー組み込みの特殊なメソッドを提供してたりします。 C#でもそういう特殊なメソッドを用意して、上記のような通常のC#では書けない場面に対処すればいいんじゃないかという提案を出してきています。

文法的にはexternメソッドを使うだけ。CompilerIntrinsic属性を付けることで、ネイティブDLL中のネイティブ メソッドを呼ぶ代わりに、コンパイラーが直接その場所にIL命令を出力するというもの。 これなら今から新文法について考える必要もないし、簡単に目的が達成できそう。

bool型やenum型のswitchの完備性

bool型にはtruefalseしかないはずなんだから、以下のdefault句は不要にできないかという話。ご意見求む状態。

bool b = ...;
switch (b)
{
    case true:
    case false:
        break;
    default:
        break; // warning: unreachable code?
}

これ、昔から要望としては頻出なんですが、できない理由もあります。ILは結構低級機能を提供しているので、bool型の変数を無理やり書き換えて、trueでもfalseでもない値を作れて、上記default句に来ちゃう場合があったり。 というか、C#でも、以下のような書き方でそういう値を作れます。

それに、後方互換性を考えると、既存のswitchには警告も出せないです。

という背景の中、今後導入予定のmatch式(switchの式バージョン)ではこういう普通はあり得ないdefault句に対する警告がほしいですか?という質問。

言語サポート付きのobsolete

今、obsolete (廃止したい、もう使ってほしくない)なメンバーにはObsolete属性を付けて対処しています。 でも、この属性ベースのやり方じゃなくて、C#の言語機能としてobsoleteキーワードが必要かもという話が。

シナリオ的には以下のようなもの。

// シナリオ 1:
int f(string s);                 // ライブラリv1がこいつを持ってる
int f(string s, bool b = false); // v2でこれに変えたい
// バイナリ互換性のためにf(string)は消せない
// でも、今後、オーバーロード解決時に、f("") で優先的に f(string, bool) の方を見てほしい(今は無理)

// シナリオ 2:
float g();  // ライブラリv1がこいつを持ってる
double g(); // v2でこれに変えたい
// バイナリ互換性のためにfloat g()は消せない
// でも、今後、double g()を使いたい(呼び分けどころか今はそもそも定義すら不可能)

これに対して、v1側にobsolete修飾子を付けることで、v2側の新メソッドの追加・オーバーロード解決できるようにしたいとのこと。

TryRoslyn

Roslynリポジトリの各ブランチの最新版でのコンパイルを、オンラインで試して見れるサイト作ってる人がいた。

C#チームの公式提供じゃないし、まだまだ作業途中みたいですけども。

  • Lucian (C#チームの中の人)が、自分のリポジトリでasync任意戻り値の試験実装してる
  • ashmind (TryRoslyn作ってる人)が、そのLucianの個人リポジトリのブランチをTryRoslynに追加してくれた
  • Lucian、早速利用

みたいな感じになってた。

参照戻り値と参照ローカル変数

$
0
0

C# 7の説明、1つ足しました。参照戻り値がらみ。

参照戻り値と参照ローカル変数

追加される構文自体は割とシンプルなんですが、活用できそうな場面まで含めて説明しようとするとなかなか骨が折れる感じの機能。

まず、メモリ管理の方法について(スタックとかヒープとか)知ってないとピンとこないですしね。

「別の何かを参照する」って考え方も、そこそこ素養を求める概念ですし。 C言語とかC++で「ポインターは難しい」とか言われるのも、同種の問題だと思います。

ということで、GitHub上のディスカッションでも、大体は、

  • 活用場面がよくわからない
  • (自分は)使わなさそうなのに、複雑性を増すのには反対
  • 構造体は immutable に作れってのが常識じゃないのか

なんて話がまずあって、それに対して、

  • メモリ管理の手法とか知らない人はそう言って、パフォーマンスをいとも簡単に落とすんだ
  • パフォーマンスを求めると、mutable な構造体を配列で持っとくしかない場面があるんだ

とかの返事が毎度ついてる感じ。

文法自体についての反対意見はあんまりなさそう。しいて言うなら、

  • 非同期メソッドとかイテレーターとかでも使いたいけど、Task<ref T>とかIEnumerable<ref T>は作れないよね?
  • ローカル変数の宣言で、var (変数の型推論)を使う場合ですらref varって書かないといけないのはちょっと面倒

みたいな話が出てるくらい。

まあ、なかなか活用しどころが想像しにくい機能ではあるんですが、C# チーム的には優先度結構高いでしょうね。 Build Insiderの方で書きましたけど、 今、パフォーマンスに対する要求がかなり上がってるので。 .NET Core関連のチームとか、C#チーム自身とかにとってはかなり有用な機能のはず。 多くのプログラマーにとって直接使うことがない機能であっても、 低レイヤーなライブラリとかツールとかの性能向上が見込めるので、間接的な恩恵はそこそこありそうな気がします。

6/6 追記:

この手のメモリ管理がらみのパフォーマンス改善の話に付いて回るのは、ガベージコレクションもかなり高性能になってて、もうガベコレに任せてても大体大丈夫なんじゃないかという議題。

確かに、MS製ガベコレって結構高性能なんですよね。それでもガベコレ除けをきっちりするとかなりのパフォーマンス改善したりしますが。 仮にまあ、ガベコレがもっともっと優秀になったとしても…

その優秀なガベコレがどこででも使えると思うなよ!

と思うわけです。 ガベコレのコードなんて、.NETのものなんてファイルサイズが1.2MB(GitHubに"we can't show files"って言われるやつ)、行数3700行を超える長大なC++コードです。どこまで手書きでどこまで機械生成かわからないなんて話もありますが、どちらにしたって、なかなか保守が大変そうな分量。 特定の1環境で保守するのはまだ成り立つんですが、全然スペックの違う異なる環境向けにそれぞれ提供とかにあると、なかなか大変そう。 要するに何が言いたいかというと、あんまりこういうレイヤーの改善に期待してると、新しいプラットフォームに移りづらくなるとかのリスクもあったり。

具体的に、最近自分はUnityでiOS/Android両対応のゲームを作ってるわけですけども、 どうも、ヒープ確保の性能がiOSとAndroidでだいぶ違うみたいで、同じコードを書いててもAndroidでだけパフォーマンスが出なかったりします。 (他にもパフォーマンス ネックの原因になってそうな場所は多いんですが、ヒープ確保もネックの1つなことは間違いなさそう。)

一般論としても、「ムーアの法則での発展を期待していたら、モバイルな時代が来ちゃってむしろ時代が巻き戻った」なんて言葉よく聞くわけでして。 今更ながらC#に参照戻り値みたいな「使う人を選ぶ」機能が入るのも、そういう時代背景があるんじゃないかなと思います。


C# 6, C# 7

$
0
0

最近、C#がらみの原稿仕事を依頼されたとき、よくある校正が「C# 6になってますけども、6.0ですよね?」。 回答は「いえ、C# 6が正式です」。

C#のバージョン番号、6以降は .0 を付けないのが正式っぽいんですよね。実は。

  • C# 1.0
  • C# 1.1 (#lineディレクティブと/** doc comment */が追加されただけ。1.1なのか1.2なのかも割かしよくわからず)
  • C# 2.0
  • C# 3.0
  • C# 4.0
  • C# 5.0
  • C# 6
  • C# 7

という感じ。

実質的に小数点以下使ってない(1.1とか存在感ない)し、要らないですよね。という感じ。

これに気づいたの、結構後になってからなんで、うちのC#によるプログラミング入門にも「C# 6.0」って表記が結構残ってたんですが、今しがた整理。ブログ以外からは6.0が消えたはず。

実はよくわからない

ただ、C# 7の次がC# 7.1とかになる可能性は0ではないです。「TypeScriptとか0.1刻みの細かいリリースしてるよね」みたいな話題もあるし、C#も1年1回リリースくらいのペースに速めようなんて話が出てますし。パターン マッチングの構文を、7で追加するものと、その先に回すものを分けたとかいうのもありますし。

.NET Frameworkも、「.NET 4」ってブランド名にしたら、その次からが「.NET 4.5」、「.NET 4.5.1」、「.NET 4.6」、…とかだったなんて話もあります。

あと、C#チームは現体制(GitHub上で公開MadsがPM)になってから、この手のアナウンスが手抜きなんですよね。気が付いたら「あれ?そうだったの?」みたいなことが割とちらほら。

単に、「6.0と6に何の差もないだろう」的な発想なのかも。例えば以下のページなんて、C# 1, C# 2, C# 3, ...表記。

ってことで、自分も全部C# 1, C# 2, C# 3, ...表記に変えたい気持ちありつつ。まあ、一応過去への遡及はしないことにします… 6以降だけ、.0を取る方針で。

おまけ: VB

Visual Basicのバージョンもなかなかよくわからないみたいですね。

C#は、言語のバージョンとIDEのバージョンを分けて表記してますけど、「Visual Basic」っていうIDE製品があった頃の名残で、言語とIDEの区別をしないみたい。その結果何が起こるかというと…

まあ、以下のページを見てください。

書かれてるのは以下の通り。

  • Visual Basic / Visual Studio .NET 2002 (内部バージョン7)
  • Visual Basic / Visual Studio .NET 2003 (7.1)
  • Visual Basic / Visual Studio .NET 2005 (8)
  • Visual Basic / Visual Studio .NET 2008 (9)
  • Visual Basic / Visual Studio .NET 2010 (10)
  • Visual Basic / Visual Studio .NET 2012 (11)
  • Visual Basic / Visual Studio .NET 2013 (12)
    • このとき、コンパイラーは全く更新してません
  • Visual Basic / Visual Studio .NET 2015 (14)
    • 13を嫌って、内部バージョン1つ飛ばして14

で、VBのバージョンとしては、Visual Studioの内部バージョンで(2002みたいな年号表記じゃなくて、7みたいなの)表します。 問題は、2013。VBのコンパイラーは一切変更してないのに、こいつのことをVB 12って言うみたいです。 しかもその後、13っていう忌み数を避けて内部バージョンを14にしたもんだから、VBもVB 14に。

dot.net にC#オンライン エディター

$
0
0

.NET Core、リリースされましたね。

まあ、その辺りの話は他の人に任せるとして。

自分が気になったのはこちら。

Scott Hanselmanのブログにこんな画像が

Scott Hanselmanの.NET Coreリリースに関するブログ記事に気になる画像がありまして。画像にリンクが貼ってあって、リンク先は

こちら。

ちょっと前に、「よくこのドメイン取れたな」、「マイクロソフトってURLにこだわってくれなくていつもダサいのに、これはほんとにうれしい」と話題になってたやつですね。 結局はhttps://www.microsoft.com/netに転送されたりはするんですが、まあ、http://dot.netがある、このURLでリンク貼れるってのが大事です。

で、このページをちょっと下にスクロールすると、こんなものが。

Starting coding

ウェブページ内でC#コード書いて試せる! いつからありましたっけ?

まあ、中身的には「Monaco」っぽいです。 Monacoを使って、チュートリアル コードをサイト内に埋め込んだり、「Run」ボタンを押して実行結果を出力したり。

これも、まあ、ずっとほしいほしい言い続けてたやつなわけですが。 Goなんかは公式サイト開いた瞬間「Try Go」なわけで。 同じものがC#にもほしいって言ってたら、ちゃんとできてた。 しいて言うなら、こんなちょっとスクロールしないと見えない位置に置くのはやめてほしいなぁという感じはあります。 このページはたびたび見たことあるけど、大体「DOWNLOADS」か「DOCUMENTATION」リンクに直行でスクロールしませんし。

しかも、チュートリアル ページのサンプル コードも、実行できるものは1個1個、このMonacoベースのオンライン エディターを立ち上げて実行できるみたいです。

チュートリアル ページのサンプル コード

これは大変よさげ。

「project.json辞めます」の意味

$
0
0

.NET CoreといいC#コンパイラーといいオープンソースになったおかげで常に最新の情報を拾えてありがたい限りなわけですが。 緩い段階のものが見えすぎて、いろいろ振り回されたりもします。

最近の話題というと、「project.json辞めます」騒動

これ、あんまり字面通り受け止めるとダメだと思うんですよね。 話の出どころは「ASP.NET Community Standup」の1コマ、5月10日放映分での会話らしいんですが。 こういう、会話中で出てきた言葉って、割かし不正確(にとられかねない緩い表現)なわけです。

ここでいう「project.json辞めます」の意味

.NET Coreは、当初、脱msbuildを目指していたわけです。.NET Coreにとっかかり始めた当時の発想としては、

  • msbuildとか、MS製のビルド ツールはC++、COM製で、クロスプラットフォーム化が大変
  • ASP.NET に対応できればいい
    • モダンなWebっぽいものを作りたい

というような感じだったはずです。

ところが今は、

  • msbuildが.NETでクロスプラットフォーム実装になってる
  • UWP、Xamarinなどなど、いろんなものに対応する必要が出てきた

と、状況が変わってる。

なので、実際のところは、「ASP.NET チーム主導で独自に作ってたビルド ツール辞めます」、「msbuild使います」という話になります。

で、「ASP.NET チーム主導で独自に作ってたビルド ツール」に名前がないもんだから、そいつが解釈するプロジェクト設定ファイルであるところの「project.json」を辞めるという言い回しをしてしまっているという状況。

もう1つのproject.json

.NET Coreのリリースがずるずると伸びてる間に、1年近く早く先にリリース段階に達した別プロダクトがあるわけです。UWPとかNuGet 3とか。

.NET Coreは標準ライブラリの参照でNuGetの仕組みに乗っかってるわけですが、 同じく、NuGetに乗っかりたかったのがUWP。 Windwos 10のリリースに合わせる必要があったので、2015年7月の段階でRTM。 そのために、NuGetも同時期にバージョン アップしました。

このとき、.NET Coreのproject.jsonのうち、パッケージ参照がらみの部分だけを抜き出して使うことになりました。 つまり、NuGet 3では、packages.configを辞めて、project.json形式を使うように。 ここで、project.jsonが2つに分岐したわけです。 この辺りは去年の12月にブログを書いてます。

そしてこちらのproject.jsonは、msbuild に組み込まれています。

先ほど言った通り、.NET Coreチームの言うところの「project.json辞めます」は、実際には「msbuild使います」の意味です。 つまるところ、NuGet側のproject.json (msbuild対応済み)は辞めるどころか、むしろ積極的に使われるようになる立場。

nuget.json?

で、パッケージ参照設定なのに名前が「project」なの?とかいう問題に至ります。 元々はprojectだったけども。その元々の方がお亡くなりになってしまい…

ってことで、NuGetが使っている方のproject.jsonはnuget.jsonにリネームしようみたいな話もあるみたい?

まあなんか、この「project.json辞めます」騒動のせいでもう、そこいら中から「project.json辞めたんじゃないの?」「UWPのやつどうなるの?」みたいな疑問の声が出まくってるんで、もう、リネーム必須な状況になってしまってるんじゃないかなぁ…という気がします。

project.json便利だったのに…

.NET Coreチームの言うproject.jsonは、.csprojほどファイルの衝突が起きなくて、ソースコードのバージョン管理的には大変ありがたかったです。

「project.json辞めます」、すなわち、「msbuild使います」というのは、結局、「.csprojに戻ります」という意味でもあります。 ありがたかった機能も一旦なくなるわけですが…

.NET Coreチーム曰く、「msbuild/.csprojの方を改善します」とのこと。csprojでも、「フォルダー中の.csは全部コンパイル対象」みたいなことをできるようにしたいみたいです。 てことで、「将来的に、msbuild/.csprojがもっと便利になる」と捉えるべき。

まとめ

緩い段階で出てきた話は字面通りに受け止めちゃダメというか。 今時は情報の出どころがものすごい緩いことが多いというか。 みんなタイトルだけ読んでわかった気になるんだから、緩い出どころを元にブログのタイトル付けちゃダメというか。

.NET Coreチームの言う、元々の意味のproject.jsonはどうやらなくなります。 ただし、その利便性をmsbuildに引き継ぎたいそうです。

「project.json辞めます」の本当の意味は「.NET Coreでもmsbuildを使います」です。 project.jsonでやろうとしていたことを、msbuildに取り込んでいきたいそうなので、「msbuildが便利になる」と考えるべきです。

また、NuGetの方のproject.jsonはすでに1年前からmsbuldに組み込み済みなので、なくならないどころか、むしろ今後積極的に使われるようになる側にいます。 ただし、nuget.jsonにリネームはするかも。

dotnetConf 2016 Japan

$
0
0

昨日はdotnetConf 2016 Japanでした。

あいにくの雨でキャンセル率高く、当初予想ほどの混雑には至りませんでしたが多くの方のお越しいただきました。 改めて御礼申し上げます。

以下、発表資料をまとめておきます。

dotnetConf 2016 Japan 開催にあたって ~ .NET の今と未来

デモ用ソースコード: https://github.com/chack411/dotnetConfjp

.NET Standard

Xamarinの新しい話とMonoの深い話

関連:

MVVM Done Right with Xamarin.Forms and Prism

.NET Core on RHEL

関連: .NET Core on RHEL リンク集 (RTM 1.0 時点)

ASP.NET Core

関連: dotnetConf 2016 Japan で ASP.NET Core 1.0 について話してきました

.NET Core/VS/VSCode他ツール類

ローカル関数

$
0
0

ちょっと間が空いたんで「C# 7思い出話」タグでなんか書いてたことを忘れかかっていたりはしますが。

C# 7のページにローカル関数の話を足しました

これで、現状で仕様が結構安定してるやつは全部なんですよねぇ。type switch辺りはそろそろ書いてもよさそうなくらい作業進んでは来てますが。タプル型とかはもうちょっと先かなぁ(自分の執筆ペースを考えるとたぶんちょうどいいくらいに安定しそうな気も)。

ローカル関数

これは本文にも書いちゃってるんですけど、要望として多いのは、ローカル関数がほしいというよりも、匿名関数の改良だったんですよね。

などなど。

そこに来て、ローカル関数ほしい?って話を出したところ、この手の匿名関数に対する問題が、ローカル関数なら結構解決するんじゃないか的な話にどんどんなっていって。数か月後には(正式に機能追加の提案に至る](https://github.com/dotnet/roslyn/issues/2930)。

まあ、元々、C# Scripting/Interactive由来っぽい感じはあったんですが。 スクリプト環境だと、常にメソッド内部にいるかのような文法になる(トップレベルにステートメントを書ける)んで、 そこにメソッドを書くのは、実際のところローカル関数を作るのと大差ない感じになります。 たぶん、今まで全然入れてくれなかった機能が急に出てきたのはこれのせいじゃないかなぁとか思います。

Viewing all 482 articles
Browse latest View live