<?xml version="1.0" encoding="UTF-8" ?>

<rss version="2.0">
	<channel>
		<title>++C++; // 未確認飛行 C ブログ</title>
		<link>http://ufcpp.net/blog/</link>
		<description><![CDATA[ ++C++; // 未確認飛行 C のブログです。C# を中心に随時更新しています。 ]]></description>
		<pubDate>Sat, 07 Mar 2026 22:46:21 +0900</pubDate>
		<lastBuildDate>Fri, 17 Apr 2026 04:44:15 +0900</lastBuildDate>
		<language>ja</language>
		<copyright>Copyright Nobuyuki Iwanaga since 2000</copyright>

			<item>
				<title>「マクロ欲しい」→「Source Generator 使え」→「むずい」→「ほら、作ったよ」</title>
				<link>http://ufcpp.net/blog/2026/3/sourcegeneratordemo/</link>
				<description><![CDATA[ <p>少し前に C# 言語仕様のディスカッションで、こんな提案が立ちました。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/discussions/10010">Compile-Time Inline Macros</a></li>
</ul>
<p>この手の提案は、ほぼ同様のものがたびたび出てきました。
そして毎回かなり高い確率で、「Source Generator を使ってくれ」が結論になります。</p>
<p>それでも同様の提案が繰り返し出るのは、つまりそれだけ Source Generator に心理的ハードルがある、というです。</p>
<h2>い　つ　も　の</h2>
<p>毎度おおむね、話の流れはこうです:</p>
<ol>
<li>「マクロ欲しい」</li>
<li>「Source Generator 使えば？」</li>
<li>「いや、あれ大変。プロジェクト分かれるのがつらい。同じプロジェクトにテンプレートを書きたい」</li>
<li>「属性ベースの Source Generator を最初に 1 個だけ作れば、あとは使い回せるよ」</li>
<li>「簡単って言うなら、実物あるんですか？」</li>
</ol>
<p>で、だいたいこうなった辺りで横やりを入れたくなります。</p>
<p>「<strong>じゃあ、今作ったわ</strong>。」</p>
<p>実際、過去にもそういう流れで作ったものがあります。
確か以下の2つとかもそういう出自。</p>
<ul>
<li><a href="https://github.com/ufcpp/BitFieldGenerator">BitFieldGenerator</a></li>
<li><a href="https://github.com/ufcpp/StringLiteralGenerator">StringLiteralGenerator</a></li>
</ul>
<h2>そして再び。今回は気合入れ気味</h2>
<p>まあ久しぶりに恒例行事参加いたしまして。
今回、気が付いたらちょっと気合入り気味。
その結果がこれです:</p>
<ul>
<li><a href="https://github.com/ufcpp/SourceGeneratorDemo">SourceGeneratorDemo</a></li>
</ul>
<p>目的が目的なのでこんな名前。特定の目的の Source Generator を作りたいとか広めたいということではなく、また同様の提案が出たときに「あるよ」と即出しするためのリポジトリ。</p>
<p>当然ながら英語でないと目的を果たせず、これまでだったらソースコードだけ書いてそこから説明文を書くのが面倒で一切何も書かなかったりするんですが。
最近の Copilot の進化に感謝しつつの readme 付き。</p>
<p>「雑に書いて雑に使える」を目標にしているのでほんとに最低限実装を目指しまして、
NuGet パッケージなし(パッケージ化する設定一切入れず、ProjectReference での利用を想定)。
Visual Studio のプロジェクト テンプレートの「Analyzer with Code Fix (.NET Standard)」が作るようなごてごてとしたコードは一切使わず、<a href="https://github.com/ufcpp/SourceGeneratorDemo/tree/main/Starter">数ファイルのテンプレ</a>をコピペする想定。</p>
<h2>マクロ的 Source Generator</h2>
<p>そして今回は特に、
「属性ベースの Source Generator を最初に 1 個だけ作って、あとは使い回し」を実装しまして。</p>
<ul>
<li><a href="https://github.com/ufcpp/SourceGeneratorDemo/blob/main/AttributeTemplate/README.md">AttributeTemplateGenerator</a></li>
</ul>
<p>(ちなみに、今回のこの<a href="https://github.com/dotnet/csharplang/discussions/10010#discussioncomment-15924116">ディスカッションに同じく居合わせて</a>、同じくこれをモチベーションにしたっぽい方がいらっしゃったり: 「<a href="https://zenn.dev/sator_imaging/articles/0ac6bf76bafe2a">C# でマクロを使う</a>」)</p>
<p>こちらのやつは、属性中に<a href="https://ufcpp.net/study/csharp/st_string.html#string-interpolation">文字列補間</a>を書くことでマクロとして機能する Source Generator です。
例えばよくある <code>INotifyPropertyChanged</code> 実装用のマクロを書くなら以下のような感じ。</p>
<p>まず、クラス自体に <code>INotifyPropertyChanged</code> インターフェイス実装を用意するマクロ:</p>
<pre class="source" title="クラス用マクロ属性">
[<span class="type">AttributeUsage</span>(<span class="type">AttributeTargets</span><span class="operator">.</span>Class)]
<span class="reserved">class</span> <span class="type">NotifyClassAttribute</span>() : <span class="type">TemplateAttribute</span>(
    <span class="static"><span class="method">Global</span></span>(<span class="string">&quot;using System.ComponentModel;&quot;</span>),
    <span class="static"><span class="method">Parent</span></span>(<span class="string">$&quot;</span><span class="string">partial class </span>{<span class="constant"><span class="static">Name</span></span>}<span class="string"> : INotifyPropertyChanged;</span><span class="string">&quot;</span>),
<span class="string">&quot;&quot;&quot;
    public event PropertyChangedEventHandler? PropertyChanged;
    
    protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
    {
        PropertyChanged?.Invoke(this, e);
    }
    
    protected bool SetProperty&lt;T&gt;(ref T storage, T value, PropertyChangedEventArgs e)
    {
        if (global::System.Collections.Generic.EqualityComparer&lt;T&gt;.Default.Equals(storage, value))
        {
            return false;
        }
        storage = value;
        OnPropertyChanged(e);
        return true;
    }
&quot;&quot;&quot;</span>
    );
</pre>
<p>次にプロパティ用:</p>
<pre class="source" title="プロパティ用マクロ属性">
[<span class="type">AttributeUsage</span>(<span class="type">AttributeTargets</span><span class="operator">.</span>Property)]
<span class="reserved">class</span> <span class="type">NotifyPropertyAttribute</span>() : <span class="type">TemplateAttribute</span>(
<span class="string">$&quot;&quot;&quot;
</span><span class="string">    get =&gt; field;
    set =&gt; SetProperty(ref field, value, </span>{<span class="static"><span class="constant">Name</span></span>}<span class="string">PropertyChangedEventArgs);</span><span class="string">
&quot;&quot;&quot;</span>,
<span class="static"><span class="method">Parent</span></span>(<span class="string">$&quot;&quot;&quot;
</span><span class="string">    private static readonly System.ComponentModel.PropertyChangedEventArgs </span>{<span class="constant"><span class="static">Name</span></span>}<span class="string">PropertyChangedEventArgs = new(nameof(</span>{<span class="static"><span class="constant">Name</span></span>}<span class="string">));</span><span class="string">
&quot;&quot;&quot;</span>)
    );
</pre>
<p></pre></p>
<p>で、これの利用側コード:</p>
<pre class="source" title="マクロ利用者コードの例">
<span class="reserved">using</span> AttributeTemplateGenerator;

<span class="reserved">namespace</span> Examples;

[<span class="type">NotifyClass</span>]
<span class="reserved">partial</span> <span class="reserved">class</span> <span class="type">NotifyPropertyChangedExample</span>
{
    [<span class="type">NotifyProperty</span>]
    <span class="reserved">public</span> <span class="reserved">partial</span> <span class="reserved">int</span> <span class="property">Integer</span> { <span class="reserved">get</span>; <span class="reserved">set</span>; }

    [<span class="type">NotifyProperty</span>]
    <span class="reserved">public</span> <span class="reserved">partial</span> <span class="reserved">string</span><span class="operator">?</span> <span class="property">Str</span> { <span class="reserved">get</span>; <span class="reserved">set</span>; }

    [<span class="type">NotifyProperty</span>]
    <span class="reserved">public</span> <span class="reserved">partial</span> <span class="type struct">TimeOnly</span> <span class="property">Time</span> { <span class="reserved">get</span>; <span class="reserved">set</span>; }

    [<span class="type">NotifyProperty</span>]
    <span class="reserved">public</span> <span class="reserved">partial</span> <span class="type struct">DateOnly</span><span class="operator">?</span> <span class="property">Date</span> { <span class="reserved">get</span>; <span class="reserved">set</span>; }

    [<span class="type">NotifyProperty</span>]
    <span class="reserved">public</span> <span class="reserved">partial</span> (<span class="reserved">int</span>, <span class="reserved">string</span><span class="operator">?</span>, <span class="type struct">DateTimeOffset</span>) <span class="property">Tuple</span> { <span class="reserved">get</span>; <span class="reserved">set</span>; }

    [<span class="type">NotifyProperty</span>]
    <span class="reserved">public</span> <span class="reserved">partial</span> <span class="type">List</span>&lt;<span class="reserved">int</span>&gt; <span class="property">List</span> { <span class="reserved">get</span>; <span class="reserved">set</span>; }
}
</pre>
<p>「デモ用だし雑に」とか思いながら作り始めたんですけど、
その先 Copilot に向かって「これもやろう」とか言ってみたら思った以上にしっかり作ってくれたというのもあり。</p>
<h2>やった感想</h2>
<p>Source Generator を雑に書いて雑に使うの、さすがに昔よりもだいぶ楽になってますねぇ。
昔は Source Generator 側を書き換えたあとの、利用側プロジェクトへの反映性とかかなり悪かったんですけども、
今はもうビルド1回するだけで即時反映になってたりで。</p>
<p>AI コーディング大流行の昨今、(Source Generator みたいに) 学習ソースが少なそうなものはきついのかなぁとかうっすら思いながら書き始めたんですが、
試してみたら全然余裕でちゃんとしたコードが出てきてびっくりしたりも。
ソリューション内に他の例がある状態からとはいえ、<a href="https://github.com/ufcpp/SourceGeneratorDemo/blob/main/DependencyProperty/Generators/NotifyPropertyChangedGenerator.cs">このコード</a>とか 100% Copilot (Claude Sonnet 4.5)製。
「DependencyProperty に INotifyPropertyChanged 実装の例も足しましょう」とかです。</p>
<p>あと、おそらく割かし最近の話なんですが、 Visual Studio (for Windows)の Analyzer 実行プロセス(Source Generator もこれの中で動いてる)が .NET 8 になっていまして、もう .NET Standard 2.0 (.NET Framework 相当)にとらわれる必要もないかも。</p>
<ul>
<li><a href="https://github.com/ufcpp/SourceGeneratorDemo/tree/main/Net8.0">.NET 8 Source Generators</a></li>
</ul>
<p>まあそれでも .NET 8 なんですけども(ちなみに、 VS Code のやつは普通に .NET 10 で動いてる)。</p>
<p>AttributeTemplateGenerator だけ高機能、かつ、多少の実用性あるのでこいつだけ独立させた方がいいのかなぁとか NuGet パッケージ公開した方がいいのかなぁとかも思いつつ。</p>
 ]]></description>
				<pubDate>Sat, 07 Mar 2026 22:46:21 +0900</pubDate>
			</item>
			<item>
				<title>C# 14 の破壊的変更点(First-class Span)</title>
				<link>http://ufcpp.net/blog/2025/10/first-class-span-breaking-change/</link>
				<description><![CDATA[ <p>C# 14 で導入された <a href="https://ufcpp.net/study/csharp/resource/span/#first-class-span">First-class Span</a> は破壊的変更を伴っています。</p>
<p>例えば標準ライブラリの範囲内の拡張メソッド呼び出しでも以下のような差が生じます。</p>
<pre class="source" title="C# 14 にすると挙動が変わる拡張メソッド呼び出しの例">
<span class="reserved">int</span>[] <span class="variable">array</span> <span class="operator">=</span> [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>];

<span class="comment">// C# 13 まで: System.Linq.Enumerable.Contains (IEnumerable 引数) が呼ばれる</span>
<span class="comment">// C# 14 から: System.MemoryExtensions.Contains (ReadOnlySpan 引数) が呼ばれる</span>
<span class="static"><span class="type">Console</span></span><span class="operator">.</span><span class="method"><span class="static">WriteLine</span></span>(<span class="variable">array</span><span class="operator">.</span><span class="method">Contains</span>(<span class="number">2</span>));
</pre>
<p>ほとんどの場合、「パフォーマンスが上がるだけで得られる結果は同じ」な実装ばかりなのでそんなに問題にはならないだろうということで、
「許容できる範囲内」・「破壊的変更を受け入れるメリットの方が大きい」という判定を受けています。
公式の<a href="https://learn.microsoft.com/ja-jp/dotnet/core/compatibility/core-libraries/10.0/csharp-overload-resolution">.NET 10 での破壊的変更に関するドキュメント</a>では、
「式ツリーで使っていた場合に問題が起きうる」くらいしか書かれていません。</p>
<p>ただ、これのせいで問題を起こしそうだった拡張メソッドとして <code>Reverse</code> があったりします。</p>
<pre class="source" title="Reverse は危うかった">
<span class="reserved">int</span>[] <span class="variable">array</span> <span class="operator">=</span> [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>];

<span class="comment">// C# 13 まで: Enumerable.Reverse だったから問題なし。</span>
<span class="comment">// C# 14 から: MemoryExtensions.Reverse を呼んじゃいそう…</span>
<span class="control">foreach</span> (<span class="reserved">var</span> <span class="variable">x</span> <span class="control">in</span> <span class="error" title="CS1579"><span class="variable">array</span><span class="operator">.</span><span class="method">Reverse</span>()</span>)
{
}

<span class="comment">// デモ用に同じシグネチャの拡張メソッドをローカル実装。</span>
<span class="reserved">static</span> <span class="reserved">class</span> <span class="static"><span class="type">A</span></span>
{
    <span class="comment">// System.Linq.Enumerable にあるのは「新しい IEnumerable インスタンスを作って返す」タイプ。</span>
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="type">IEnumerable</span>&lt;<span class="type param">TSource</span>&gt; <span class="method"><span class="static">Reverse</span></span>&lt;<span class="type param">TSource</span>&gt;(<span class="reserved">this</span> <span class="type">IEnumerable</span>&lt;<span class="type param">TSource</span>&gt; <span class="variable local">source</span>) <span class="operator">=&gt;</span> <span class="reserved">null</span><span class="operator">!</span>;

    <span class="comment">// MemoryExtensions にあるのは「Span に対する自己書き換え」タイプ。</span>
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">Reverse</span></span>&lt;<span class="type param">T</span>&gt;(<span class="reserved">this</span> <span class="type struct">Span</span>&lt;<span class="type param">T</span>&gt; <span class="variable local">span</span>) { }
}
</pre>
<p>ちなみに、この問題は「<a href="https://learn.microsoft.com/ja-jp/dotnet/api/system.linq.enumerable.reverse?view=net-10.0#system-linq-enumerable-reverse-1(-0())"><code>TSource[]</code> 引数の <code>Reverse</code></a> を足す」という方法で解決しています。
<code>Span&lt;T&gt;</code> (first-class とはいえ型変換を挟む)よりも <code>T[]</code> (無変換)の方が優先度が高いので、
<code>array.Reverse()</code> は <code>Reverse(T[])</code> が優先的に呼ばれます。</p>
<p>ここまではあくまで「標準ライブラリの範囲内で」の話。
「自作の LINQ もどき」とかを持っているともう少しいろいろと問題を踏みます。
というか、自分が踏んだという話…
それを2つほど紹介。</p>
<h2>Where(Span)</h2>
<p>1個目は以下のような <code>Where</code> メソッドです。</p>
<pre class="source" title="Span 自己書き換え Where">
<span class="reserved">static</span> <span class="reserved">class</span> <span class="static"><span class="type">InPlaceLinq</span></span>
{
    <span class="comment">// Reverse の例と同様、「Span 相手は自己書き換えでいいだろ」的なメソッド。</span>
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="type struct">Span</span>&lt;<span class="type param">T</span>&gt; <span class="method"><span class="static">Where</span></span>&lt;<span class="type param">T</span>&gt;(<span class="reserved">this</span> <span class="type struct">Span</span>&lt;<span class="type param">T</span>&gt; <span class="variable local">span</span>, <span class="type">Func</span>&lt;<span class="type param">T</span>, <span class="reserved">bool</span>&gt; <span class="variable local">predicate</span>)
    {
        <span class="reserved">int</span> <span class="variable">count</span> <span class="operator">=</span> <span class="number">0</span>;
        <span class="control">for</span> (<span class="reserved">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; <span class="variable">i</span> <span class="operator">&lt;</span> <span class="variable local">span</span><span class="operator">.</span><span class="property">Length</span>; <span class="variable">i</span><span class="operator">++</span>)
        {
            <span class="control">if</span> (<span class="variable local">predicate</span>(<span class="variable local">span</span>[<span class="variable">i</span>]))
            {
                <span class="variable local">span</span>[<span class="variable">count</span><span class="operator">++</span>] <span class="operator">=</span> <span class="variable local">span</span>[<span class="variable">i</span>];
            }
        }
        <span class="control">return</span> <span class="variable local">span</span>[..<span class="variable">count</span>];
    }
}
</pre>
<p>先ほどの <code>Reverse</code> の例同様、自己書き換え。</p>
<p>自己書き換えな時点で用途はかなり限定的で、
本来は以下のような利用を想定しています。</p>
<pre class="source" title="本来の「自己書き換え Where」利用">
<span class="reserved">struct</span> <span class="type struct">SomeItem</span>
{
    <span class="reserved">public</span> <span class="reserved">bool</span> <span class="property">Flag</span> { <span class="reserved">get</span>; }
}

<span class="reserved">class</span> <span class="type">SomeRepository</span>
{
    <span class="reserved">public</span> <span class="type struct">SomeItem</span>[] <span class="method">Filter</span>(<span class="type">Func</span>&lt;<span class="type struct">SomeItem</span>, <span class="reserved">bool</span>&gt; <span class="variable local">predicate</span>)
    {
        <span class="comment">// 個数の上限がある程度わかってる &amp; 小さいので stackalloc でバッファー確保。</span>
        <span class="type struct">Span</span>&lt;<span class="type struct">SomeItem</span>&gt; <span class="variable">buffer</span> <span class="operator">=</span> <span class="reserved">stackalloc</span> <span class="type struct">SomeItem</span>[<span class="number">32</span>];

        <span class="comment">// 一覧を取る時点では Where 出来ず一度バッファーに書き込みが必要なメソッドを呼ぶ。</span>
        <span class="reserved">var</span> <span class="variable">written</span> <span class="operator">=</span> <span class="method">GetItems</span>(<span class="variable">buffer</span>);

        <span class="comment">// 最終的には ToArray して返す。</span>
        <span class="control">return</span> [.. <span class="variable">buffer</span>[..<span class="variable">written</span>]<span class="operator">.</span><span class="method">Where</span>(<span class="variable local">predicate</span>)];
    }

    <span class="reserved">private</span> <span class="reserved">int</span> <span class="method">GetItems</span>(<span class="type struct">Span</span>&lt;<span class="type struct">SomeItem</span>&gt; <span class="variable local">destination</span>)
    {
        <span class="comment">// 本来は以下の類のコード</span>
        <span class="comment">// destination[count++] = ...</span>
        <span class="comment">// return count;</span>
        <span class="control">return</span> <span class="number">0</span>;
    }
}
</pre>
<p>ところが、first-class Span が入ったことで、配列に対して <code>Enumerable.Where</code> よりも優先度が高くなってしまい…
意図しないところで呼ばれてしまうことに…</p>
<pre class="source" title="意図せず「自己書き換え Where」の方が呼ばれてしまった例">
<span class="reserved">int</span>[] <span class="variable">array</span> <span class="operator">=</span> [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>];

<span class="comment">// C# 13 まで: System.Linq.Enumerable.Where が呼ばれる。</span>
<span class="comment">// C# 14 から: InPlaceLinq.Where が呼ばれる。自己書き換え…</span>
<span class="reserved">var</span> <span class="variable">result</span> <span class="operator">=</span> <span class="variable">array</span><span class="operator">.</span><span class="method">Where</span>(<span class="variable local">x</span> <span class="operator">=&gt;</span> <span class="variable local">x</span> <span class="operator">%</span> <span class="number">2</span> <span class="operator">==</span> <span class="number">0</span>);

<span class="static"><span class="type">Console</span></span><span class="operator">.</span><span class="static"><span class="method">WriteLine</span></span>(<span class="string">&quot;result&quot;</span>);
<span class="control">foreach</span> (<span class="reserved">var</span> <span class="variable">x</span> <span class="control">in</span> <span class="variable">result</span>)
{
    <span class="type"><span class="static">Console</span></span><span class="operator">.</span><span class="static"><span class="method">WriteLine</span></span>(<span class="variable">x</span>);
}

<span class="comment">// C# 14 だと自己書き換えやっちゃってるんで当然…</span>
<span class="type"><span class="static">Console</span></span><span class="operator">.</span><span class="method"><span class="static">WriteLine</span></span>(<span class="string">&quot;array&quot;</span>);
<span class="control">foreach</span> (<span class="reserved">var</span> <span class="variable">x</span> <span class="control">in</span> <span class="variable">array</span>)
{
    <span class="static"><span class="type">Console</span></span><span class="operator">.</span><span class="static"><span class="method">WriteLine</span></span>(<span class="variable">x</span>); <span class="comment">// 2, 4, 3, 4 になっちゃう。</span>
}
</pre>
<p>この例の特に厳しいところは、コンパイル エラーにはならずに実行できてしまうものの、
実行結果が破滅的に意図しない挙動になるところです…</p>
<p>一応、<code>Reverse</code> の例同様、<code>Where(TSource[], Func&lt;TSource, bool&gt;)</code> オーバーロードを足して <code>Enumerable.Where</code> に流すようにしてしまえば解決できるはずです。</p>
<p>また、自己書き換えな拡張メソッドが非破壊なものと同名なのが問題だったという反省もあり、
メソッド名を変更してしまうべきとう気もします。
(実際、この路線で修正。<code>WhereInPlace</code> というあえての長ったらしい名前に変更。)</p>
<h2>Index(ReadOnlySpan)</h2>
<p>もう1個は以下のような <code>Index</code> メソッド。</p>
<pre class="source" title="">
<span class="reserved">static</span> <span class="reserved">class</span> <span class="static"><span class="type">SpanExtensions</span></span>
{
    <span class="comment">// 要は「Span 相手にも Enumerable.Index みたいなものが欲しい」。</span>
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="type struct">IndexEnumerable</span>&lt;<span class="type param">T</span>&gt; <span class="static"><span class="method">Index</span></span>&lt;<span class="type param">T</span>&gt;(<span class="reserved">this</span> <span class="type struct">ReadOnlySpan</span>&lt;<span class="type param">T</span>&gt; <span class="variable local">span</span>) <span class="operator">=&gt;</span> <span class="reserved">new</span>(<span class="variable local">span</span>);

    <span class="reserved">public</span> <span class="reserved">readonly</span> <span class="reserved">ref</span> <span class="reserved">struct</span> <span class="type struct">IndexEnumerable</span>&lt;<span class="type param">T</span>&gt;(<span class="type struct">ReadOnlySpan</span>&lt;<span class="type param">T</span>&gt; <span class="variable local">span</span>)
    {
        <span class="reserved">private</span> <span class="reserved">readonly</span> <span class="type struct">ReadOnlySpan</span>&lt;<span class="type param">T</span>&gt; <span class="field">_span</span> <span class="operator">=</span> <span class="variable local">span</span>;
        <span class="reserved">public</span> <span class="type struct">IndexEnumerator</span>&lt;<span class="type param">T</span>&gt; <span class="method">GetEnumerator</span>() <span class="operator">=&gt;</span> <span class="reserved">new</span>(<span class="field">_span</span>);
    }

    <span class="reserved">public</span> <span class="reserved">ref</span> <span class="reserved">struct</span> <span class="type struct">IndexEnumerator</span>&lt;<span class="type param">T</span>&gt;(<span class="type struct">ReadOnlySpan</span>&lt;<span class="type param">T</span>&gt; <span class="variable local">span</span>)
    {
        <span class="reserved">private</span> <span class="reserved">readonly</span> <span class="type struct">ReadOnlySpan</span>&lt;<span class="type param">T</span>&gt; <span class="field">_span</span> <span class="operator">=</span> <span class="variable local">span</span>;
        <span class="reserved">private</span> <span class="reserved">int</span> <span class="field">_index</span> <span class="operator">=</span> <span class="operator">-</span><span class="number">1</span>;
        <span class="reserved">public</span> <span class="reserved">bool</span> <span class="method">MoveNext</span>() <span class="operator">=&gt;</span> <span class="operator">++</span><span class="field">_index</span> <span class="operator">&lt;</span> <span class="field">_span</span><span class="operator">.</span><span class="property">Length</span>;
        <span class="reserved">public</span> <span class="reserved">readonly</span> (<span class="reserved">int</span> Index, <span class="type param">T</span> Item) <span class="property">Current</span> <span class="operator">=&gt;</span> (<span class="field">_index</span>, <span class="field">_span</span>[<span class="field">_index</span>]);
    }
}
</pre>
<p>こちらは <code>Enumerable.Index(this IEnumerable&lt;T&gt;)</code> と同じ挙動を <code>ReadOnlySpan&lt;T&gt;</code> 引数で実装したものです。</p>
<p>まあ、<code>Span</code>/<code>ReadOnlySpan</code> を使いたいくらいパフォーマンスを気にする場面なら <code>for (var i = 0; i &lt; span.Length; ++i)</code> を使えという話はありつつも…</p>
<p>同じ挙動なので、配列に対して呼ばれても問題ないはずでめでたしめでたし(?)</p>
<pre class="source" title="">
<span class="reserved">int</span>[] <span class="variable">array</span> <span class="operator">=</span> [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>];

<span class="comment">// C# 13 まで: System.Linq.Enumerable.Index が呼ばれる。</span>
<span class="comment">// C# 14 から: 自作の SpanExtensions.Index が呼ばれる。</span>
<span class="comment">//</span>
<span class="comment">// 挙動は同じなので特に問題ない。</span>
<span class="comment">// むしろパフォーマンス上がるのではないかと。</span>
<span class="control">foreach</span> (<span class="reserved">var</span> (<span class="variable">index</span>, <span class="variable">item</span>) <span class="control">in</span> <span class="variable">array</span><span class="operator">.</span><span class="method">Index</span>())
{
    <span class="type"><span class="static">Console</span></span><span class="operator">.</span><span class="static"><span class="method">WriteLine</span></span>(<span class="string">$&quot;</span>{<span class="variable">index</span>}<span class="string">: </span>{<span class="variable">item</span>}<span class="string">&quot;</span>);
}
</pre>
<p>問題は <code>IndexEnumerable</code> が <code>ref struct</code> な点で、
<code>foreach</code> 中に <code>yield</code> や <code>await</code> があるとエラーになります。</p>
<pre class="source" title="">
<span class="reserved">int</span>[] <span class="variable">array</span> <span class="operator">=</span> [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>];

<span class="comment">// C# 14 で 自作の SpanExtensions.Index が呼ばれようになると…</span>
<span class="error" title="CS4007"><span class="control">foreach</span> (<span class="reserved">var</span> (<span class="variable">index</span>, <span class="variable">item</span>) <span class="control">in</span> <span class="variable">array</span><span class="operator">.</span><span class="method">Index</span>())</span>
{
    <span class="comment">// さっきとの差は await を含んでることだけ。</span>
    <span class="control">await</span> <span class="type">Task</span><span class="operator">.</span><span class="method"><span class="static">Delay</span></span>(<span class="number">1</span>);
    <span class="type"><span class="static">Console</span></span><span class="operator">.</span><span class="static"><span class="method">WriteLine</span></span>(<span class="string">$&quot;</span>{<span class="variable">index</span>}<span class="string">: </span>{<span class="variable">item</span>}<span class="string">&quot;</span>);
}
</pre>
<p>「 'SpanExtensions.IndexEnumerator&lt;int&gt;' 型のインスタンスは、'await' または 'yield' 境界を越えて保持することはできません。」というコンパイル エラーが出るはずです。</p>
<p>これはまあ、ほとんどの場合は <code>Index(ReadOnlySpan)</code> が呼ばれた方が好ましい中、
少数の <code>yield</code>/<code>await</code> を含むケースでだけ問題になるので、
コンパイル エラーが出た場所を <code>Enumerable.Index</code> (拡張メソッドをやめて静的メソッド呼び)に書き換えるなどで対処しました。
(それか、名前空間の内側に <code>using static System.Linq.Enumerable;</code> を書いて <code>Enumerable.Index</code> の優先度を上げるという手もあります。)</p>
<p>あとこれも一応、配列用のオーバーロード追加でも問題解消するはずです。</p>
 ]]></description>
				<pubDate>Wed, 22 Oct 2025 21:33:30 +0900</pubDate>
			</item>
			<item>
				<title>ファイナライザー</title>
				<link>http://ufcpp.net/blog/2025/5/ファイナライザー/</link>
				<description><![CDATA[ <p>以下の <code>~Class1</code> のこと、（C# の言語機能名として)なんと呼びますか？</p>
<pre class="source" title="~Class1">
<span class="reserved">class</span> <span class="type">Class1</span>
{
    <span class="reserved">public</span> <span class="type">Class1</span>() { }
    <span class="operator">~</span><span class="type">Class1</span>() { }
}
</pre>
<p>すごく今更ながら、8年くらい前からこれの呼び名が変わってたらしいというのを最近気づいたという話になります。</p>
<p>ちなみに結果だけ言うと、旧称がデストラクター(destructor)、今はファイナライザー(finalizer)です。</p>
<h2>他の言語とかの話</h2>
<p>C# がかつてこいつのことをデストラクターと読んでいたのは C++ 由来です。
ただ…</p>
<ul>
<li>
文法は確かに同じで、C++ も <code>~Class1</code> な文法がある
<ul>
<li>これのことをデストラクターと呼ぶ</li>
<li>ただし、挙動は C# のものと違っていて、呼ばれるタイミングは「変数のスコープを抜けるとき」</li>
</ul>
</li>
<li>
C# は文法こそ同じなものの、実際にはそれはファイナライザーだった
<ul>
<li>Java の <code>finalize</code> メソッド(ファイナライザーって呼ばれてる)と同じ挙動</li>
<li>GC 回収されるタイミングで呼ばれる</li>
<li>C# もコンパイル結果的には <code>object.Finalize</code> メソッドのオーバーロードとして実装</li>
<li><code>GC.SuppressFinalize</code> って名前のメソッドもある</li>
<li>.NET の仕様書上も呼び名はファイナライザー</li>
</ul>
</li>
</ul>
<p>文法だけ同じな C++ 由来の名前(デストラクター)で、意味合いとしては違うもの(ファイナライザー)という地雷。</p>
<p>しかも、「.NET の仕様書はファイナライザーと呼んでいるものを、C# のレベルではデストラクターと呼んでいた」という2個目の地雷。</p>
<h2>Deconstruct との兼ね合い</h2>
<p>さかのぼること2016年末、うちのブログでも書いてましたね、これの話。</p>
<ul>
<li><a href="https://ufcpp.net/blog/2016/12/tipsdeconstruct/">小ネタ 「deconstruct」という単語</a></li>
</ul>
<p>ここにある通り、発端は C# 7 の頃(20217年3月頃正式リリース)に導入した<a href="https://ufcpp.net/study/csharp/cheatsheet/ap_ver7/#deconstruction">分解</a>構文でして。
「Deconstruct って英単語は微妙じゃない？」という話から派生して、
「誰だよ、<code>~Class1</code> のことをデストラクターって言ったの」という話題にまで及びまして。</p>
<p>このブログの最後で「デストラクターって呼び名は微妙なので変えることも視野に入ってるみたい」と書いていますが、
実際、その後変更されたみたいですね。
Microsoft Learn (前記のブログの時代は MSDN だったもの)の文章の大元になってる <a href="https://github.com/dotnet/docs/tree/main/docs">dotnet/docs</a> リポジトリを見てみた感じ、
割と早い段階から finalizer に置き換わっていました。</p>
<h2>ということで直します</h2>
<p>前述のブログの話があったので長いこと自分も口頭ではファイナライザーって呼んでたりはしたんですが。
Learn が案外ちゃんとドキュメントの修正を早期に入れていたことには気づいておらず。
気が付いたら8年くらい放置してましたね…</p>
<p>うちのサイトも長らく放置で各所にデストラクターと書いたままなんで、直します…
(すぐにやるとは言っていない。)</p>
 ]]></description>
				<pubDate>Sat, 17 May 2025 17:19:14 +0900</pubDate>
			</item>
			<item>
				<title>文字列リテラルを data セクションに UTF-8 で書き込む案</title>
				<link>http://ufcpp.net/blog/2025/1/data-section-string/</link>
				<description><![CDATA[ <p>ここ数回のブログ(
<a href="https://ufcpp.net/blog/2025/1/field-keyword/">その1</a>、
<a href="https://ufcpp.net/blog/2025/1/first-class-span/">その2</a>、
<a href="https://ufcpp.net/blog/2025/1/nameof-unbound-generic-types/">その3</a>
)、<a href="https://github.com/dotnet/roslyn/blob/main/docs/Language%20Feature%20Status.md">Language Feature Status</a> に最近かかった更新のうち、すでに実装されたものの紹介をしていたわけですが。</p>
<p>「その <a href="https://github.com/dotnet/roslyn/blob/main/docs/Language%20Feature%20Status.md">Language Feature Status</a> を見てると、何やら見慣れないものもちらほら増えてない？」みたいな話題も出ておりまして、今回からその辺りに触れていきたいと思います。</p>
<p>今日は「String literals in data section as UTF8」というやつを。</p>
<h2>概要</h2>
<p>普通にやると、C# の文字列リテラルや定数はアセンブリ(exe や dll)中の UserString セクションというところに UTF-16 で記録されます。
今回取り上げる話は、オプション追加で、特定の条件を満たす文字列は data セクションというところに UTF-8 で記録できるようにしたいという話です。</p>
<p>おおむね、例えば以下のコードを、</p>
<pre class="source" title="なんか長い文字列リテラルを持ってるコード例">
<span class="reserved">string</span> <span class="variable">s</span> <span class="operator">=</span> <span class="string">&quot;Some very very long looo...ooong string!!!!!&quot;</span>;
</pre>
<p>特定条件下では以下のようなコード扱いでコンパイルするというもの。</p>
<pre class="source" title="なんか u8 リテラルみたいな状態で記録して、デコードして使いたい">
<span class="reserved">string</span> <span class="variable">s</span> <span class="operator">=</span> System<span class="operator">.</span>Text<span class="operator">.</span><span class="type">Encoding</span><span class="operator">.</span><span class="property"><span class="static">UTF8</span></span><span class="operator">.</span><span class="method">GetString</span>(
    <span class="string">&quot;Some very very long looo...ooong string!!!!!&quot;</span><span class="reserved">u8</span>
    );
<span class="comment">// ※ 実際にはこの GetString 結果を静的にキャッシュ</span>
</pre>
<p>ちなみにこれから説明していきますが、一番の目的は「data セクションに書くこと」で、
UTF-8 化(その結果、dll サイズが大体縮む)は副産物だそうです。</p>
<h2>24ビット制限</h2>
<p>PE ファイル(.NET の exe とか dll のファイル形式)中のメタデータの仕様上の問題なんですが、
C# の文字列リテラルって合計サイズで24ビット長(約 1,600万バイト、800万文字(以下 8M と表記))を超えれないそうです。</p>
<p>どうも理屈としては、</p>
<ul>
<li>文字列リテラルは UserString セクションというところに書き込む</li>
<li>UserString セクション中の文字列を表すハンドル値は4バイト</li>
<li>そのうち1バイトは「テーブル番号」</li>
<li>残り3バイト(24ビット)が「文字列の先頭までのオフセット(バイト数)」</li>
<li>文字列の合計長が 16M バイト(8M 文字)を超えると、その次の文字列のオフセットが24ビットを超えてオーバーフロー</li>
</ul>
<p>とのこと。</p>
<p>なので、これを超えると C# コンパイラーも <a href="https://github.com/dotnet/roslyn/blob/b7e891b8a884be1519a709edc7121140c5a1fac2/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs#L1338">CS8103</a> エラーを出すんですって。</p>
<p>しかも「8M を超えたその次の文字列リテラルがあるとダメ」というのが曲者で、
「一番最後のファイルの、一番後ろのメソッド中の、一番最後の文字列リテラルがでかい」という状況だと合計サイズ 8M 超でもコンパイルできちゃうそうです(最後の1個だけはセーフ)。
その状況で、「それより後ろに1個、短かろうが別の文字列リテラルが増えた」となると突然にアウト。</p>
<h2>制限超過</h2>
<p>まあ、8M 文字よ？
原稿用紙2万枚(日本人にしか通じない単位)。
太宰治の「人間失格」が8万文字くらいっぽいので、それ100冊分。
皆様方、「1プロジェクトでそんなの超えるやついるの？」と疑うかと思われます。</p>
<p>そう疑う方はぜひ、「CS8103」で Web 検索してみてください。
案外たくさん踏んでるやついる…</p>
<p>特によく出てくる話だと、<a href="https://learn.microsoft.com/ja-jp/aspnet/core/mvc/views/razor?view=aspnetcore-9.0">razor ファイル</a>がビルド時に文字列化されて、UserString セクションに書き込まれるせいっぽいです。
でかい ASP.NET プロジェクトだとそこそこ 8M を超えてしまうとか。
(まあこれに関しては ASP.NET 側が「<a href="https://github.com/dotnet/aspnetcore/issues/50788">.razor, .cshtml が生成する文字列、u8 リテラルに変えたら？</a>」とか言われたりもしますが。)</p>
<p>他にも、「大量の SQL を文字列で埋め込んでる」とか「元々あったでかい CSV ファイルの中身を文字列リテラルで埋め込んだら起きた」とか、
中々に「ほー、それで 8M 行っちゃったかー」と関心()するようなコメントも多数。</p>
<h2>data セクションと UTF-8 リテラル</h2>
<p>ところで、C# 11 のときに <a href="https://ufcpp.net/study/csharp/cheatsheet/ap_ver11/#utf8-literal">UTF-8 リテラル</a>というものを導入したわけですが、こいつは単なる定数バイト列にコンパイルされます。
で、定数バイト列は data セクションってところに記録されるそうです。</p>
<p>そして、data セクション(というか、UserString セクション以外のもの大体)は<a href="https://github.com/dotnet/roslyn/issues/9852">制限サイズが29ビット</a>だそうで。
UserString よりも5ビット多く、32倍！ 256M！</p>
<p>しかも、問題を起こしがちなのが .razor とかということは、
多くの部分がマークアップとかスクリプトですからね。
大体 ASCII 文字。
ASCII 文字は、UTF-8 だと1バイト、UTF-16 だと2バイト。
つまり、UTF-8 にするとそれだけで半分のサイズ。
さらに倍(合わせて64倍)の文字数を記録できるはず！512M！</p>
<p>64倍程度の差でどのくらい「突然 CS8103 が出た！」という「バグ報告」(自称)が減るでしょうか…
ムーアの法則的に言うと10年くらいの延命にはなりますかね。</p>
<p>まあ、 .NET ができた当初、
こんなさらっと 8M 文字超えてくるような使われ方も、
バイナリデータ用のセクションに UTF-8 を書き込んで使うやり方も全く想像してなかったでしょうね…</p>
<h2>コンパイラー オプションでやってみる</h2>
<p>という話の流れで最初の話題になります。
「1回、試しに C# コンパイラー側でやってみる？」と。
長い文字列を見たら u8 リテラル化して、読み込み時に <code>UTF8.GetString</code> を挟む実装。</p>
<ul>
<li>提案文書: <a href="https://github.com/dotnet/roslyn/pull/76139">Add spec for the data section string literals feature #76139</a></li>
<li>実験的実装: <a href="https://github.com/dotnet/roslyn/pull/76036">Emit opted-in string literals into data section as UTF8 #76036</a></li>
</ul>
<p>これ、あくまで「C# コンパイラー実装」の話であって、
C# 言語の文法上は何一つ影響がないので Roslyn 側にしか作業はありません。
(<a href="https://github.com/dotnet/csharplang/">csharplang</a> 上に関連項目なし。)</p>
<p>そして、まあ、問題起こすのの大部分が ASP.NET だし、
先ほどちょっと触れていますが <a href="https://github.com/dotnet/aspnetcore/issues/50788">ASP.NET 側がコード生成方針変えろという話</a>もあるので、
本当に C# コンパイラー側でやる価値があるのかどうかがちょっと自信なさげな感じではあります。</p>
<p>なのでとりあえず experimental。
「いったん merge されたものが世に出荷された上で、やっぱり取りやめになって消える」みたいなことがあり得る状態なのでご注意ください。</p>
<p>軽く現状の仕様を紹介しておくと以下のような感じ。</p>
<ul>
<li>UTF8 リテラルでやってることを流用するので実装はそんなに難しくはない</li>
<li>
feature フラグ (<code>/feature</code> オプションに渡すフラグ名)として <code>experimental-data-section-string-literals</code> を用意
<ul>
<li><code>experimental-data-section-string-literals=20</code> みたいに最後に「閾値の文字数」を渡す</li>
<li>この文字数を超えた文字列リテラルだけが対象 (<code>=0</code> と書けばすべての文字列リテラルが対象)</li>
</ul>
</li>
<li>
パフォーマンスはそこまで悪くならない予想(多少は不利)
<ul>
<li>静的にキャッシュするので <code>GetString</code> は初回のみ</li>
<li>しかも最近、<code>UTF8.GetString</code> のパフォーマンスは JIT 最適化かかってる</li>
<li><code>ldstr</code> (定数文字列のロード)と <code>ldsfld</code> (キャッシュした静的フィールドのロード)の命令自体はそんなにパフォーマンス差がない</li>
<li>ただ、定数文字列は文字列専用のヒープに書き込まれたり、JIT 時最適化はかかりやすくて、そこは <code>GetString</code> を挟むのが不利</li>
<li>静的キャッシュを持つための匿名型が作られるので、型ロードのコストはかかる</li>
</ul>
</li>
</ul>
<h2>まとめ</h2>
<p>というか感想。
「そんなやついるんだ」からの、「そんな対処するんだ」。</p>
<p>まあ「副作用として UTF-8 化すると文字列データのサイズがほぼ半分」の方が結構ありがたい可能性があります。
dll のバイナリサイズが問題になることもちらほらありますしね。
UTF-8 だと日本語なんかは逆にサイズが増えるんですが、
案外、プログラム中に埋め込んでる文字列リテラルは ASCII なもので
(razor 同様マークアップだったりとか、URL だったりとか、ハッシュ値の base64 だったりとか)。</p>
 ]]></description>
				<pubDate>Sun, 12 Jan 2025 00:16:03 +0900</pubDate>
			</item>
			<item>
				<title>nameof(T&lt;&gt;)</title>
				<link>http://ufcpp.net/blog/2025/1/nameof-unbound-generic-types/</link>
				<description><![CDATA[ <p>「Rosly の <a href="https://github.com/dotnet/roslyn/blob/main/docs/Language%20Feature%20Status.md">Language Feature Status</a> に並んでいるもののうち、すでに preview 提供済みのものシリーズ第3段。</p>
<ul>
<li>field キーワード</li>
<li>First-class Span</li>
<li>nameof(T&lt;&gt;) ← 今日はこれ</li>
</ul>
<p>すでに今、<a href="https://ufcpp.net/study/csharp/cheatsheet/langversionoption/#langversion">LangVersion</a> に <code>preview</code> を指定すれば利用可能です。</p>
<p>今日は最後の1個の <code>nameof(T&lt;&gt;)</code> の話です。
当初「3つまとめて1ブログにする予定」だった原因。
こいつだけ対して書くことがなく…</p>
<h3><a id="unbound-generic-nameof">nameof(T&lt;&gt;)</a></h3>
<p>今日のやつは Visual Studio 17.13.0 Preview 2 (.NET 9 の正式リリースの次のアプデ)で merge 済みです。
<a href="https://github.com/dotnet/csharplang/blob/main/proposals/unbound-generic-types-in-nameof.md"><code>nameof</code> 演算子の中に unbound な型を書けるようになりました</a>。
unbound (未束縛)というのは、<code>List&lt;&gt;</code> みたいに、型実引数を渡してなくて(<code>&lt;&gt;</code> の中に何も書かず)、具体的な型が決定していない状態のジェネリック型のことを言います。</p>
<p>例えば以下のような感じ。</p>
<pre class="source" title="nameof の中に unbound な型を書けるように">
<span class="reserved">var</span> <span class="variable">name</span> <span class="operator">=</span> <span class="reserved">nameof</span>(<span class="type">List</span>&lt;&gt;<span class="operator">.</span><span class="type struct">Count</span>);

<span class="type"><span class="static">Console</span></span><span class="operator">.</span><span class="static"><span class="method">WriteLine</span></span>(<span class="variable">name</span>); <span class="comment">// Count</span>
</pre>
<p>元々、<code>nameof(T&lt;int&gt;)</code> とか書いても、結果の文字列は <code>T</code> だけで、型引数は何にも影響しません。
メンバー参照でも、<code>nameof(T.X)</code> でも <code>nameof(T&lt;int&gt;.X)</code> でも <code>nameof(T&lt;string&gt;.X)</code> でも、得られる文字列は <code>X</code> です。
つまり、<code>nameof</code> に取って型引数は全くの無意味でした。</p>
<p>それでもこれまでは unbound な型は掛けず、何か適当なダミーの型実引数を渡す必要がありました。
上記の例であれば、適当に <code>object</code> なり <code>int</code> なりを渡して、
<code>nameof(List&lt;int&gt;.Count)</code> とか書いていました。</p>
<p><code>typeof</code> の場合は <code>typeof(T&lt;&gt;)</code> (unbound な型の <code>Type</code> 型インスタンスが取れる)とか書けるわけで、
<code>nameof</code> でも <code>nameof(T&lt;&gt;)</code> と書けてもいいじゃないかと前々から言われていました。</p>
<p>まあ、別に特に問題があってできなかったわけではなくて「それなりに実装コストがかかるから後回し」みたいな感じで放置されていただけです。
<code>typeof(T&lt;&gt;)</code> と共通のコードでできそうに見えるかもしれませんが、
<code>typeof(T&lt;&gt;)</code> の方では <code>typeof(T&lt;&gt;.X)</code> とメンバー参照することはないので、
<code>nameof</code> では「似て非なるものの再実装」が必要とのことです。</p>
<pre class="source" title="似て非なる nameof と typeof">
<span class="comment">// unbound でメンバー参照(特にインスタンス メンバーの参照)をするのは nameof だけ。</span>
<span class="reserved">var</span> <span class="variable"><span class="warning" title="CS0219">name</span></span> <span class="operator">=</span> <span class="reserved">nameof</span>(<span class="type">List</span>&lt;&gt;<span class="operator">.</span><span class="property">Count</span>);

<span class="comment">// 入れ子の型なら参照することはあるけども、</span>
<span class="type">List</span>&lt;<span class="reserved">int</span>&gt;<span class="operator">.</span><span class="type struct">Enumerator</span> <span class="variable"><span class="warning" title="CS0219">e1</span></span> <span class="operator">=</span> <span class="reserved">default</span>;

<span class="comment">// unbound はあり得ない。</span>
<span class="error" title="CS7003"><span class="type">List</span>&lt;&gt;</span><span class="operator">.</span><span class="type struct">Enumerator</span> <span class="variable"><span class="warning" title="CS0219">e2</span></span> <span class="operator">=</span> <span class="reserved">default</span>;

<span class="comment">// まして、インスタンス メンバー参照はあり得ない。</span>
<span class="reserved">_</span> <span class="operator">=</span> <span class="error" title="CS0120"><span class="error" title="CS0305"><span class="type">List</span>&lt;&gt;</span><span class="operator">.</span><span class="property">Count</span></span>;

<span class="comment">// 入れ子の型は unboud な typeof ができるけど、</span>
<span class="reserved">var</span> <span class="variable">t1</span> <span class="operator">=</span> <span class="reserved">typeof</span>(<span class="type">List</span>&lt;&gt;<span class="operator">.</span><span class="type struct">Enumerator</span>);

<span class="comment">// メンバー参照はあり得ない。</span>
<span class="reserved">var</span> <span class="variable">m1</span> <span class="operator">=</span> <span class="reserved">typeof</span>(<span class="type">List</span>&lt;&gt;<span class="operator">.</span><span class="error" title="CS0426"><span class="property">Count</span></span>);
</pre>
<p>一応、「理由なく掛かっていた制限を取り払った」以上の意味もありまして、
これまでは「型制約の関係でどうやっても <code>nameof</code> を使いにくい」という場面がありえました。
一例として、以下のような場面があり得ます。</p>
<pre class="source" title="型制約のせいで nameof が使いにくくなる例">
<span class="reserved">var</span> <span class="variable"><span class="warning" title="CS0219">name1</span></span> <span class="operator">=</span> <span class="reserved">nameof</span>(<span class="type">A</span>&lt;<span class="type">_</span>&gt;); <span class="comment">// これは書けるけど、</span>
<span class="reserved">var</span> <span class="variable"><span class="warning" title="CS0219">name2</span></span> <span class="operator">=</span> <span class="reserved">nameof</span>(<span class="type">B</span>&lt;<span class="error" title="CS0453"><span class="type">_</span></span>&gt;); <span class="comment">// これは書けない。</span>


<span class="comment">// 「無意味な nameof 型引数のためのダミーはこの型を使う」みたいな規約でやってたとして…</span>
<span class="comment">// 型制約によっては規約を守れない。</span>
<span class="reserved">class</span> <span class="type">_</span>;

<span class="reserved">class</span> <span class="type">A</span>&lt;<span class="type param">T</span>&gt; <span class="reserved">where</span> <span class="type param">T</span> : <span class="reserved">class</span>;
<span class="reserved">class</span> <span class="type">B</span>&lt;<span class="type param">T</span>&gt; <span class="reserved">where</span> <span class="type param">T</span> : <span class="reserved">struct</span>;
</pre>
<p>この例はまだ「規約が守れない」程度の話ですが、
型制約が複雑になるにつれ、「そもそも <code>nameof</code> が使えない」みたいなことも起こりえるそうです。</p>
<p>とうことで、優先度は低くて放置はされていたものの、ようやく unbound な <code>nameof(T&lt;&gt;)</code> を認める実装が merge されました。</p>
<h2>おまけ: typeof がらみを定数扱いする特殊処理</h2>
<p>おまけでもう1個似たような話。</p>
<p><code>nameof</code> から取れる名前はかなり限られています。
<code>nameof(T&lt;Arg1, Arg2, Arg3&gt;)</code> から取れるのは <code>T</code> だけですし、
<code>nameof(A.B.C.D&lt;E, F&gt;.G)</code> から取れるのは <code>G</code> だけです。</p>
<p>これに対して、</p>
<ul>
<li>フルネームを取りたい</li>
<li>型引数も含めて取りたい</li>
</ul>
<p>みたいなこともなくはないらしく。
一時は <a href="https://github.com/dotnet/csharplang/discussions/701"><code>fullnameof</code></a> みたいな提案も出たことがあるくらいです。</p>
<p>これに対する解決案として、<code>typeof</code> で取った <code>Type</code> 型のプロパティ <code>Name</code> と <code>FullName</code> を特殊処理で定数扱いしてはどうか？というものも一瞬提案されたりしてました。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/8505">typeof string constants #8505</a></li>
</ul>
<p>まあ、余りにもニッチで役立つ場面が少なすぎるということでリジェクトされて終わりましたが…</p>
 ]]></description>
				<pubDate>Sun, 05 Jan 2025 11:20:36 +0900</pubDate>
			</item>
			<item>
				<title>First-class な Span 型</title>
				<link>http://ufcpp.net/blog/2025/1/first-class-span/</link>
				<description><![CDATA[ <p>「Rosly の <a href="https://github.com/dotnet/roslyn/blob/main/docs/Language%20Feature%20Status.md">Language Feature Status</a> に並んでいるもののうち、すでに preview 提供済みのものシリーズ第2段。</p>
<ul>
<li>field キーワード</li>
<li>First-class Span ← 今日はこれ</li>
<li>nameof(T&lt;&gt;)</li>
</ul>
<p>すでに今、<a href="https://ufcpp.net/study/csharp/cheatsheet/langversionoption/#langversion">LangVersion</a> に <code>preview</code> を指定すれば利用可能です。</p>
<p>今日は First-class Span。
(<a href="https://ufcpp.net/blog/2024/2/first-class-span/">これも昔1回取り上げてるんですが</a>、案外書くことあり。)</p>
<h3><a id="first-class-span">First-class Span</a></h3>
<p>C# 7.2 の頃に <code>Span&lt;T&gt;</code> や <code>ReadOnlySpan&lt;T&gt;</code> が導入されて以来、
これらの型を使った高パフォーマンスな API がたくさん提供されています。
また、<a href="https://ufcpp.net/study/csharp/datatype/collection-expression/#priority">C# 12 で入ったコレクション式</a>や、
<a href="https://ufcpp.net/study/csharp/sp_params.html#params-collections">C# 13 で入った <code>params</code> コレクション</a>では、
<code>T[]</code> や <code>IEnumerable&lt;T&gt;</code> よりも <code>Span&lt;T&gt;</code> や <code>ReadOnlySpan&lt;T&gt;</code> を優先的に選ぶように特別な処理が入っています。
この例からもわかるように、今や <code>Span&lt;T&gt;</code> や <code>ReadOnlySpan&lt;T&gt;</code> が重要な地位を占めています。</p>
<p>ところが、コレクション式などの一部の文脈を除いて、
<code>Span&lt;T&gt;</code> や <code>ReadOnlySpan&lt;T&gt;</code> は「ただの構造体」で、
配列からの型変換も「<code>Span&lt;T&gt;</code> や <code>ReadOnlySpan&lt;T&gt;</code> 構造体に定義されたユーザー定義型変換」です。
C# 言語組み込みの型変換と比べて、ユーザー定義型変換は1段下扱いで、色々な不便があります。</p>
<p>そこで、<a href="https://github.com/dotnet/csharplang/blob/main/proposals/first-class-span-types.md"><code>Span&lt;T&gt;</code> や <code>ReadOnlySpan&lt;T&gt;</code> を言語組み込み(= first-class、一級市民)にしたい</a>という提案があって、
これもすでに実装があり、
Visual Studio 17.13.0 Preview 1 (.NET 9 の正式リリースと同時)で merge 済みです。</p>
<p>わかりやすいのは拡張メソッドの呼び出しで、
ユーザー定義型変換を挟む拡張メソッド呼び出しはできません。
例えば、以下のコードは C# 13 でコンパイル エラーだったものが、preview ではコンパイルできるようになっています。</p>
<pre class="source" title="配列に対して Span や ReadOnlySpan の拡張メソッドは呼べない">
<span class="comment">// 拡張メソッドの呼び出しはユーザー定義の型変換を見ない。</span>
<span class="comment">// Span の特別扱いがないと拡張メソッドは呼べない。</span>
<span class="reserved">new</span> <span class="reserved">int</span>[<span class="number">1</span>]<span class="operator">.</span><span class="method">M</span>();

<span class="reserved">static</span> <span class="reserved">class</span> <span class="type"><span class="static">Ex</span></span>
{
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="static"><span class="method">M</span></span>&lt;<span class="type param">T</span>&gt;(<span class="reserved">this</span> <span class="type struct">Span</span>&lt;<span class="type param">T</span>&gt; <span class="variable local">_</span>) { }
}
</pre>
<p>また、
「<code>Span&lt;T&gt;</code> や <code>ReadOnlySpan&lt;T&gt;</code> 引数を使った方がパフォーマンスがいいのでこちらを呼んでほしい」という要望があるんですが、
これまでは <code>IEnumerable&lt;T&gt;</code> なオーバーロードがあるとそっちが優先されるという問題もありました。</p>
<pre class="source" title="IEnumerable よりも Span/ReadOnlySpan を優先する特別扱い">
<span class="comment">// ユーザー定義の型変換よりも、「派生・実装クラスだから変換可能」の方が優先度が高い。</span>
<span class="static"><span class="type">Ex</span></span><span class="operator">.</span><span class="method"><span class="static">M</span></span>(<span class="reserved">new</span> <span class="reserved">int</span>[<span class="number">1</span>]);

<span class="reserved">static</span> <span class="reserved">class</span> <span class="type"><span class="static">Ex</span></span>
{
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="static"><span class="method">M</span></span>&lt;<span class="type param">T</span>&gt;(<span class="reserved">this</span> <span class="type">IEnumerable</span>&lt;<span class="type param">T</span>&gt; <span class="variable local">_</span>) { } <span class="comment">// C# 13 ではこっち。</span>
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="static"><span class="method">M</span></span>&lt;<span class="type param">T</span>&gt;(<span class="reserved">this</span> <span class="type struct">ReadOnlySpan</span>&lt;<span class="type param">T</span>&gt; <span class="variable local">_</span>) { } <span class="comment">// preview ではこっち。Span の特別扱いがないとこっちは呼んでもらえない。</span>
}
</pre>
<p>また、ユーザー定義の型変換では「型引数の<a href="https://ufcpp.net/study/csharp/sp4_variance.html#variance">共変性</a>」を表現できないという問題があります。
<code>ReadOnlySpan&lt;string&gt;</code> を <code>ReadOnlySpan&lt;object&gt;</code> に代入できてもいいはずなのに、
これが C# 13 まではできませんでしたが、preview にすると受け付けます。</p>
<pre class="source" title="ReadOnlySpan の共変性">
<span class="type struct">ReadOnlySpan</span>&lt;<span class="reserved">string</span>&gt; <span class="variable">s</span> <span class="operator">=</span> [];
<span class="type struct">ReadOnlySpan</span>&lt;<span class="reserved">object</span>&gt; <span class="variable">span</span> <span class="operator">=</span> <span class="variable">s</span>; <span class="comment">// C# 13 ではエラー。</span>
</pre>
<p>ちなみに、<code>Span&lt;T&gt;</code> と <code>ReadOnlySpan&lt;T&gt;</code> の両方のオーバーロードがある場合、
<code>ReadOnlySpan&lt;T&gt;</code> の方が優先されます。</p>
<pre class="source" title="ReadOnlySpan 優先">
<span class="reserved">string</span>[] <span class="variable">s</span> <span class="operator">=</span> [];

<span class="comment">// ReadOnlySpan の方が優先。</span>
<span class="variable">s</span><span class="operator">.</span><span class="method">M</span>();

<span class="reserved">static</span> <span class="reserved">class</span> <span class="type"><span class="static">Ex</span></span>
{
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">M</span></span>&lt;<span class="type param">T</span>&gt;(<span class="reserved">this</span> <span class="type struct">Span</span>&lt;<span class="type param">T</span>&gt; <span class="variable local">_</span>) { }
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">M</span></span>&lt;<span class="type param">T</span>&gt;(<span class="reserved">this</span> <span class="type struct">ReadOnlySpan</span>&lt;<span class="type param">T</span>&gt; <span class="variable local">_</span>) { }
}
</pre>
<p>target-typed で生成される型自体が変わるコレクション式と違って、
一度配列を作っちゃってるので <code>ReadOnlySpan&lt;T&gt;</code> を優先しても別にパフォーマンス的なメリットは少ないんですけども。
じゃあどうしてこういう仕様にしたかというと…
こうしておかないとまた「<a href="https://ufcpp.net/blog/2022/11/covariantarrayincident/">配列の共変性の地雷</a>を踏むから」とのこと。</p>
<pre class="source" title="配列の共変性は結構な地雷">
<span class="reserved">string</span>[] <span class="variable">s</span> <span class="operator">=</span> [];
<span class="reserved">object</span>[] <span class="variable">o</span> <span class="operator">=</span> <span class="variable">s</span>; <span class="comment">// C# の配列は共変。</span>

<span class="comment">// Span を優先するとこれが例外を起こしちゃう。</span>
<span class="comment">// ReadOnlySpan&lt;object&gt; x = s; は合法。</span>
<span class="comment">// Span&lt;object&gt; x = s; は実行時例外。</span>
<span class="variable">o</span><span class="operator">.</span><span class="method">M</span>(); <span class="comment">// ReadOnlySpan&lt;object&gt; を優先しないとここで例外が出る。</span>

<span class="reserved">static</span> <span class="reserved">class</span> <span class="static"><span class="type">Ex</span></span>
{
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="static"><span class="method">M</span></span>(<span class="reserved">this</span> <span class="type struct">Span</span>&lt;<span class="reserved">object</span>&gt; <span class="variable local">_</span>) { }
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="static"><span class="method">M</span></span>(<span class="reserved">this</span> <span class="type struct">ReadOnlySpan</span>&lt;<span class="reserved">object</span>&gt; <span class="variable local">_</span>) { }
}
</pre>
<p>以上、とりあえず、C# 14 (現状 <code>LangVersion</code> preview)では <code>Span&lt;T&gt;</code>、<code>ReadOnlySpan&lt;T&gt;</code> が特別扱いされて、オーバーロードの解決順位が変わります。
おおむね便利な方向に変わるはずですが、もしかすると何らかの問題を起こす可能性もあります。
もしも「<code>Span&lt;T&gt;</code> オーバーロードを呼ばれるとまずい」みたいなことがあれば、<a href="https://ufcpp.net/study/csharp/cheatsheet/ap_ver13/#overload-resolution-priority"><code>OverloadResolutionPriority</code></a>とかでの対処を考えてみてください。</p>
 ]]></description>
				<pubDate>Fri, 03 Jan 2025 21:01:48 +0900</pubDate>
			</item>
			<item>
				<title>field キーワード</title>
				<link>http://ufcpp.net/blog/2025/1/field-keyword/</link>
				<description><![CDATA[ <p>「Rosly の <a href="https://github.com/dotnet/roslyn/blob/main/docs/Language%20Feature%20Status.md">Language Feature Status</a> にこの1・2か月で結構更新かかったね」という話題もたびたびあり、その辺りの話を。</p>
<p>Language Feature Status に並んでいるもののうち、いくつかは preview として現時点でもうすでに取り込まれています。</p>
<ul>
<li>field キーワード ← 今日はこれ</li>
<li>First-class Span</li>
<li>nameof(T&lt;&gt;)</li>
</ul>
<p>今(執筆時、Visual Studio 17.13.0 Preview 2.1)の時点でも、
<a href="https://ufcpp.net/study/csharp/cheatsheet/langversionoption/#langversion">LangVersion</a> に <code>preview</code> を指定すれば利用可能です。</p>
<p>最初は3つまとめて1ブログにしようかと思ってたんですが、
案外長くなったので個別に。
今日は field キーワードの話になります。
(<a href="https://ufcpp.net/blog/2023/1/semi-auto-property/">昔のブログ</a>を参照して「やっと入ったよ」だけ書いて終わりかと思ったら案外新規に書くことがあり。)</p>
<h3><a id="field">field キーワード</a></h3>
<p>プロパティ内において <a href="https://github.com/dotnet/csharplang/blob/main/proposals/field-keyword.md"><code>field</code> をキーワード扱い</a>して、
「プロパティのバッキング フィールドを表す変数」にしようという案があって、
今は機能名としても「field キーワード」と呼ばれています。</p>
<pre class="source" title="field キーワード">
<span class="reserved">class</span> <span class="type">A</span>(<span class="reserved">int</span> <span class="variable local">x</span>)
{
    <span class="comment">// (既存の)自動プロパティ。</span>
    <span class="reserved">public</span> <span class="reserved">int</span> <span class="property">X1</span> { <span class="reserved">get</span>; <span class="reserved">set</span>; }

    <span class="comment">// X1 と同じ意味になる「field キーワード持ち」のプロパティ。</span>
    <span class="reserved">public</span> <span class="reserved">int</span> <span class="property">X2</span>
    {
        <span class="reserved">get</span> <span class="operator">=&gt;</span> <span class="reserved">field</span>;
        <span class="reserved">set</span> <span class="operator">=&gt;</span> <span class="reserved">field</span> <span class="operator">=</span> <span class="reserved">value</span>;
    }

    <span class="comment">// 片方を自動、片方を field 持ちにもできる。</span>
    <span class="reserved">public</span> <span class="reserved">int</span> <span class="property">X3</span>
    {
        <span class="reserved">get</span>; <span class="comment">// 自動。</span>
        <span class="reserved">set</span> <span class="operator">=&gt;</span> <span class="reserved">field</span> <span class="operator">=</span> <span class="reserved">value</span>; <span class="comment">// field 持ち。</span>
    }

    <span class="comment">// 自動プロパティでできたことは一通りこっちでもできる。</span>
    <span class="comment">// (イニシャライザーも持てたり、get-only とか init とかも。)</span>
    <span class="comment">// (というか、扱いは完全に自動プロパティと同じ。)</span>
    <span class="reserved">public</span> <span class="reserved">int</span> <span class="property">X4</span> { <span class="reserved">get</span> <span class="operator">=&gt;</span> <span class="reserved">field</span>; } <span class="operator">=</span> <span class="variable local">x</span>;

    <span class="comment">// get 省略形の =&gt; 内でも field が使える。</span>
    <span class="comment">// int X5 { get; } と全く同じ。(コンストラクターで初期化可能。)</span>
    <span class="reserved">public</span> <span class="reserved">int</span> <span class="property">X5</span> <span class="operator">=&gt;</span> <span class="reserved">field</span>;
}
</pre>
<p><a href="https://ufcpp.net/blog/2023/1/semi-auto-property/">2年前にすでに「場合によっては C# 11 に入っていたかも」と言っていたもの</a>がようやく C# 14 で入ります。
当時は「半自動プロパティ」(semi-auto properties)とか呼んでいましたが、
結局「field キーワード」で行こうという感じになっているみたいです。</p>
<p>Visual Studio 17.12 Preview 3 / .NET 9 RC 2 の頃にはすでに merge されています。
つまり、C# 13 正式リリース(.NET 9)よりも前に、
すでに C# 14 の preview 機能が取り込まれている状態。
結構長いこと検討していて実装もあるものの、いくつか懸念があって延びに延びていて、
ようやく preview として世に出すことに。</p>
<p>懸念の1つは、これが「そこそこありえる」頻度の破壊的変更になることです。
「<code>field</code> という名前のフィールドがあって、<code>this.</code> は付けずに、プロパティの中で参照している」という状況が破壊的変更になります。
(「そこまで多くはないけど、まあそういう人も一定数いる」レベル。)</p>
<pre class="source" title="field キーワードにはそこそこありえる破壊的変更">
<span class="reserved">class</span> <span class="type">A</span>
{
    <span class="reserved">int</span> <span class="field">field</span>;

    <span class="reserved">public</span> <span class="reserved">int</span> <span class="property">Field</span>
    {
        <span class="comment">// C# 13 まで: field フィールドの参照。</span>
        <span class="comment">// C# 14 から: field キーワード。</span>
        <span class="comment">//             field フィールドはノータッチになる。</span>
        <span class="comment">//             field フィールドを参照したければ @field とか this.field にする。</span>
        <span class="reserved">get</span> <span class="operator">=&gt;</span> <span class="field">field</span>;
        <span class="reserved">set</span> <span class="operator">=&gt;</span> <span class="field">field</span> <span class="operator">=</span> <span class="reserved">value</span>;
    }
}
</pre>
<p>このコードは一応、C# 14 では警告になる予定です。
「<code>field</code> キーワードが <code>field</code> フィールドを隠してるけども意図通りか？」と怒られて、<code>@field</code> への書き換えを推奨されます。
もしかすると、今年のうち(C# 13 の間)に、「今のうちから <code>@field</code> に書き換えておいてくれ」アナライザーが提供されるかもしれません。</p>
<p>ちなみに、プロパティ内において、<code>field</code> は完全にキーワードになっています。
当初は「既存のコードを壊さない限りにキーワード扱いする」みたいな努力をするかどうかという話もあったんですが、複雑すぎるので断念しています。
例えば、<code>field</code> という名前のローカル変数があったとしてもキーワード扱いです。</p>
<pre class="source" title="ローカル変数があっても field はキーワード扱い">
<span class="reserved">class</span> <span class="type">A</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> <span class="property">X</span>
    {
        <span class="reserved">get</span>
        {
            <span class="reserved">var</span> <span class="variable"><span class="warning" title="CS0219">field</span></span> <span class="operator">=</span> <span class="number">1</span>;
            <span class="control">return</span> <span class="reserved"><span class="warning" title="CS9258">field</span></span>; <span class="comment">// これは field キーワード。フィールドの場合と同じく警告あり。</span>
        }
    }
}
</pre>
<p><code>nameof(field)</code> もエラーになります。
<code>nameof(int)</code> とかがエラーなのと同じ。</p>
<pre class="source" title="nameof(field) はダメ">
<span class="reserved">class</span> <span class="type">A</span>
{
    <span class="reserved">public</span> <span class="reserved">string</span> <span class="property"><span class="warning" title="CS9264">X</span></span>
    {
        <span class="reserved">get</span> <span class="operator">=&gt;</span> <span class="reserved">nameof</span>(<span class="reserved"><span class="error" title="CS8081">field</span></span>); <span class="comment">// ダメ。</span>
    }
}
</pre>
<p>(余談で、<a href="https://ufcpp.net/blog/2024/2/value-as-context-keyword/"><code>value</code> もキーワードに変えちゃうか</a>という話もあったんですが、これは没になりました。)</p>
<p>これと関連して、以下のようなコードを書くと、タプル要素名のやつだけエラーを起こします。</p>
<pre class="source" title="タプル要素名とか、匿名型のプロパティとか">
<span class="reserved">class</span> <span class="type">A</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> <span class="property">X</span>
    {
        <span class="reserved">get</span>
        {
            <span class="reserved">var</span> <span class="variable">x</span> <span class="operator">=</span> (<span class="reserved">field</span><span class="error" title="CS1002"><span class="error" title="CS1513"><span class="error" title="CS1026">:</span></span></span> <span class="number">1</span><span class="error" title="CS1002"><span class="error" title="CS1513">,</span></span> <span class="number">2</span><span class="error" title="CS1002"><span class="error" title="CS1513">)</span></span>; <span class="comment">// タプル要素名 (これだけコンパイル エラー)</span>
            <span class="reserved">var</span> <span class="variable">y</span> <span class="operator">=</span> <span class="reserved">new</span> { <span class="property">field</span> <span class="operator">=</span> <span class="number">1</span> }; <span class="comment">// 匿名型のプロパティ</span>
            <span class="reserved">var</span> <span class="variable">z</span> <span class="operator">=</span> <span class="reserved">new</span> <span class="type">Foo</span>() { <span class="field">field</span> <span class="operator">=</span> <span class="number">1</span> }; <span class="comment">// オブジェクト初期化子でのフィールド/プロパティ参照</span>
            <span class="control">if</span> (<span class="variable">y</span> <span class="reserved">is</span> { <span class="property">field</span>: <span class="number">1</span> }) { } <span class="comment">// プロパティ パターンでのフィールド/プロパティ参照</span>

            <span class="control">return</span> <span class="reserved">field</span>;
        }
    }

    <span class="reserved">class</span> <span class="type">Foo</span>
    {
        <span class="reserved">public</span> <span class="reserved">int</span> <span class="field">field</span>;
    }
}
</pre>
<p>最後にもう1つ、<a href="https://ufcpp.net/study/csharp/resource/nullablereferencetype/">null 許容参照型</a>のフロー解析の問題があります。
プロパティが <code>T</code> のとき、そのバッキング フィールド(<code>field</code> キーワードの実体)は <code>T</code> であるべきか、<code>T?</code> であるべきか。</p>
<p>例えば以下のような <code>??=</code> を使った遅延初期化コードはよく書くと思います。</p>
<pre class="source" title="??= で遅延初期化">
<span class="reserved">class</span> <span class="type">A</span>(<span class="type">Type</span> <span class="variable local">type</span>)
{
    <span class="comment">// Type.Name のキャッシュ。</span>
    <span class="reserved">public</span> <span class="reserved">string</span> <span class="property"><span class="warning" title="CS9264">Name</span></span>
    {
        <span class="comment">// 遅延初期化にしたいので field ??= で代入。</span>
        <span class="reserved">get</span> <span class="operator">=&gt;</span> <span class="reserved">field</span> <span class="operator">??=</span> <span class="variable local">type</span><span class="operator">.</span><span class="property">Name</span>;
    }
}
</pre>
<p>現状(Visual Studio 17.13.0 Preview 2.1 時点)、「プロパティが <code>T</code> なら <code>field</code> も <code>T</code>」です。
この例の場合、<code>string</code> (not null)。
「not null なフィールドがあるのに、コンストラクターで初期化していない」という警告が出ます。</p>
<p><a href="https://github.com/dotnet/csharplang/blob/main/proposals/field-keyword.md#nullability">解決策</a>は検討さいれているんですが、短期的には <code>MaybeNull</code> 属性を使って回避してくれと言われています。</p>
<pre class="source" title="当面、MaybeNull で回避">
<span class="reserved">using</span> System<span class="operator">.</span>Diagnostics<span class="operator">.</span>CodeAnalysis;

<span class="reserved">class</span> <span class="type">A</span>(<span class="type">Type</span> <span class="variable local">type</span>)
{
    [<span class="reserved">field</span>: <span class="type">MaybeNull</span>] <span class="comment">// この属性によって、field が string? 扱いになる。</span>
    <span class="reserved">public</span> <span class="reserved">string</span> <span class="property">Name</span>
    {
        <span class="reserved">get</span> <span class="operator">=&gt;</span> <span class="reserved">field</span> <span class="operator">??=</span> <span class="variable local">type</span><span class="operator">.</span><span class="property">Name</span>;
    }
}
</pre>
<p>上記<a href="https://github.com/dotnet/csharplang/blob/main/proposals/field-keyword.md#nullability">解決策</a>が間に合うなら、
「いったん <code>field</code> が <code>T?</code> と仮定してフロー解析して nullable 警告を起こすかどうか」をみてバッキング フィールドが <code>T</code> か <code>T?</code> かを決定するとのこと。
これが入れば <code>MaybeNull</code> を付ける前のコードでも警告が出なくなる予定です。</p>
 ]]></description>
				<pubDate>Thu, 02 Jan 2025 22:47:21 +0900</pubDate>
			</item>
			<item>
				<title>UTF8 か Utf8 か</title>
				<link>http://ufcpp.net/blog/2025/1/pascalcase/</link>
				<description><![CDATA[ <p>今日は C# 配信をやっててちょくちょく話題になるやつの話。</p>
<pre class="source" title="Utf8? UTF8?">
<span class="reserved">using</span> System<span class="operator">.</span>Text;
<span class="reserved">using</span> System<span class="operator">.</span>Text<span class="operator">.</span>Unicode;

<span class="reserved">var</span> <span class="variable">buffer</span> <span class="operator">=</span> (<span class="reserved">stackalloc</span> <span class="reserved">byte</span>[<span class="number">3</span>]);
<span class="static"><span class="type">Utf8</span></span><span class="operator">.</span><span class="method"><span class="static">FromUtf16</span></span>(<span class="string">&quot;abc&quot;</span>, <span class="variable">buffer</span>, <span class="reserved">out</span> <span class="reserved">var</span> <span class="variable">r</span>, <span class="reserved">out</span> <span class="reserved">var</span> <span class="variable">w</span>);
<span class="type">Encoding</span><span class="operator">.</span><span class="static"><span class="property">UTF8</span></span><span class="operator">.</span><span class="method">GetString</span>(<span class="variable">buffer</span>[..<span class="variable">w</span>]);
</pre>
<p><code>Utf8</code> なの？
<code>UTF8</code> なの？</p>
<p>(昔1回同じ話題でブログ書いた気がしつつ、最近もまた話題に出たので。)</p>
<h2>.NET の命名ガイドライン</h2>
<p>.NET には命名規約に関するガイドラインがありまして、以下の場所にドキュメントとして残っています。</p>
<ul>
<li><a href="https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/capitalization-conventions#capitalization-rules-for-identifiers">Capitalization Rules for Identifiers</a></li>
</ul>
<p>おおむね以下のようなルール。</p>
<ul>
<li>
クラス名などは PacalCase を使ってください
<ul>
<li>(2文字よりも長い) 頭文字略語も同様です</li>
<li>2文字の頭文字略語(two-letter acronyms)は例外で、全て大文字</li>
</ul>
</li>
</ul>
<p>つまるところ、
<code>Utf8</code> か <code>UTF8</code> なら、前者の <code>Utf8</code> が正解。</p>
<p>ちなみに、 <code>Encoding.UTF8</code> に何か崇高な理由があるわけではなく、
単純に「初期はルールが徹底されてなかった。すまん。」という懺悔あり。</p>
<p>3文字略語で他に変なのがないかはちょっと検索してみたんですけども、<code>UTF8</code> 以外、自分には見つけられず。
ただ、何せ <code>Encoding.UTF8</code> の利用頻度が高く、どうしても目立ってしまいます。</p>
<h2>特殊ルールやめてほしい問題</h2>
<p>例外であるところの「2文字の略語」に該当するのは例えば以下のような名前。</p>
<ul>
<li><a href="https://learn.microsoft.com/ja-jp/dotnet/api/system.io?view=net-8.0"><code>IO</code></a> 名前空間</li>
<li><a href="https://learn.microsoft.com/ja-jp/dotnet/api/system.gc?view=net-8.0"><code>GC</code></a> クラス</li>
<li><code>IL</code> (<a href="https://learn.microsoft.com/ja-jp/dotnet/api/system.reflection.emit.ilgenerator?view=net-8.0"><code>ILGenerator</code></a> クラスとか)</li>
</ul>
<p>個人的な意見としては、正直、こんな特殊ルールはない方がよかったんじゃないかなぁと思っています。
「<code>System.IO</code> で懺悔案件やらかしちゃったのをあとからつじつま合わせの特殊ルール足しただろ」とか陰口言われてるのも見たことがあります
(個人的にはこれに1票)。</p>
<p><code>System.Io</code>、<code>System.Gc</code> は確かになんか字面の違和感すごいですし、<code>Il</code> (L が小文字)の視認性の悪さもすごいんですけど、特殊ルールが招く混乱よりはだいぶマシというお気持ち。</p>
<p>↓とか結構キモいと思うんですよねぇ。</p>
<ul>
<li><a href="https://learn.microsoft.com/ja-jp/dotnet/api/system.runtime.intrinsics.x86.avx512bw?view=net-8.0"><code>Avx512BW</code></a> (AVX-512 の byte and word 命令)</li>
<li><a href="https://learn.microsoft.com/ja-jp/dotnet/api/system.runtime.intrinsics.x86.avx512vbmi?view=net-8.0"><code>Avx512Vbmi</code></a> (同、Vector Byte Manipulation Instructions)</li>
</ul>
<p>ルール上は確かに、 BW は全部大文字で、VBMI は先頭だけ大文字なんですけども…</p>
<p>.NET Runtime の中の人もしばしば混乱していまして、
public なものにこそあまりないものの、internal/private なものだとときどき「2文字略語だけど2文字目が小文字」があります。</p>
<ul>
<li><a href="https://github.com/dotnet/runtime/blob/6045e29bbefa63b58ccd5502f057ae452f3c83af/src/libraries/System.Private.CoreLib/src/System/Number.DiyFp.cs#L18"><code>DiyFp</code></a> (floating point)</li>
<li><a href="https://github.com/dotnet/runtime/blob/511d26611c051c56e546404ea616c220cc78817c/src/libraries/Common/src/Interop/Windows/Interop.Libraries.cs#L25"><code>NtDll</code></a> (Windows NT の NT。New Technology?)</li>
</ul>
<p>他に、「.NET Runtime 内のもの(<a href="https://learn.microsoft.com/ja-jp/dotnet/api/system.dbnull?view=net-8.0"><code>DBNull</code></a>)は DB だけど、ASP.NET チームが書いてるもの(<a href="https://learn.microsoft.com/ja-jp/dotnet/api/system.data.entity.dbcontext?view=entity-framework-6.2.0"><code>DbContext</code></a>)は Db」なんて事案も。
ASP.NET チームは「しがらみはリセット」路線で、やっぱ特殊ルールを快く思ってないんでしょうね。</p>
<h3>ID? OK?</h3>
<p><a href="https://learn.microsoft.com/ja-jp/dotnet/api/system.platformid?view=net-8.0"><code>PlatformID</code></a>…</p>
<p>こいつだけが「2文字とも大文字の ID」です。
<a href="https://learn.microsoft.com/ja-jp/dotnet/api/system.threading.thread.managedthreadid?view=net-8.0#system-threading-thread-managedthreadid"><code>ManagedThreadId</code></a>とか<a href="https://learn.microsoft.com/ja-jp/dotnet/api/system.diagnostics.tracing.eventattribute.eventid?view=net-8.0#system-diagnostics-tracing-eventattribute-eventid"><code>EventId</code></a>とかは Id。
これも懺悔案件でしょうね。<code>PlatformID</code> は最初期からある enum なので。</p>
<p>何だったら、ドキュメントには↓とか書かれてますからね。<code>ID</code> を <code>Id</code> に渡す。</p>
<blockquote>
<p><code>PlatformID</code> の列挙型メンバーの整数値を SignTool.exe の <code>PlatformId</code> 引数に渡せる</p>
</blockquote>
<p>しかし、id とは一体何なのか…</p>
<ul>
<li>identity の略？ → ガイドライン的には「略語は使うな」なので、Identity と書くべき</li>
<li>id という英単語(元は identity だったとしても、もう id のスペルで普及)？ → 略語ではないので Id と書くべき</li>
<li>
identity document (本人確認書類)の略？ → なら ID
<ul>
<li><code>PlatformID</code> がこの意味とは考えにくい…</li>
</ul>
</li>
</ul>
<p>他に、OK もぶれがちで、
<a href="https://learn.microsoft.com/ja-jp/dotnet/api/system.windows.messageboxresult?view=windowsdesktop-8.0"><code>OK</code></a>も<a href="https://learn.microsoft.com/ja-jp/dotnet/api/microsoft.aspnetcore.mvc.controllerbase.ok?view=aspnetcore-9.0"><code>Ok</code></a>もあります(これも、後者は ASP.NET)。</p>
<p>ok とは一体何なのか…</p>
<ul>
<li>元々 all correct がなまったスラングの oll korrect の略らしい → OK</li>
<li>が、語源ももうあいまいで ok という英単語化してる → Ok</li>
<li>なんなら okay というスペルも定着してる → Okay (略すな危険)</li>
</ul>
<p>この辺りで悩むことになるのも「2文字略語は特別」とかやっちゃったからで、
この特殊ルールがなければ迷うことなく Id, Ok なんですけども。</p>
<h2>まとめ</h2>
<p>ガイドライン上、<code>Utf8</code> が正しくて、<code>UTF8</code> は過去のしがらみです。
ガイドラインは以下の通り。</p>
<ul>
<li>3文字以上の場合は略語も含め、PascalCase</li>
<li>2文字の略語だけ例外で IO とか GC とか全部大文字</li>
</ul>
<p>ただ、2文字略語の特殊ルールも割と過去のしがらみ感があって、
ASP.NET とかは2文字の略語も含めて PascalCase を採用しているみたいです。</p>
 ]]></description>
				<pubDate>Wed, 01 Jan 2025 18:52:45 +0900</pubDate>
			</item>
			<item>
				<title>(没) 数学準拠な剰余演算子</title>
				<link>http://ufcpp.net/blog/2024/12/euclidean-mod/</link>
				<description><![CDATA[ <p><a href="https://ufcpp.net/blog/2024/12/u8-string-interpolation/">こないだ</a>につづき、C# 言語機能としては没ネタ。
最終的な結論が「ライブラリでやれ」 → 「.NET 10 でメソッド追加を検討」です。</p>
<h2><a id="mod-usecase">剰余の利用例</a></h2>
<p>剰余演算(C# だと <code>%</code> 演算子)の用途として、
「配列の範囲内に収めるために <code>index % array.Length</code> する」とかがあると思います。
例えば以下のような感じ。</p>
<pre class="source" title="配列のインデックスを i % Length">
<span class="reserved">var</span> <span class="variable">table</span> <span class="operator">=</span> <span class="reserved">new</span> <span class="type struct">Table</span>([<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>]);

<span class="control">for</span> (<span class="reserved">var</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; <span class="variable">i</span> <span class="operator">&lt;</span> <span class="number">5</span>; <span class="variable">i</span><span class="operator">++</span>)
    <span class="type"><span class="static">Console</span></span><span class="operator">.</span><span class="static"><span class="method">WriteLine</span></span>(<span class="variable">table</span><span class="operator">.</span><span class="method">Next</span>());

<span class="comment">// 引数で受け取った配列の中身を1個ずつ返す。</span>
<span class="reserved">struct</span> <span class="type struct">Table</span>(<span class="reserved">int</span>[] <span class="variable local">values</span>)
{
    <span class="reserved">private</span> <span class="reserved">int</span> <span class="field">_index</span>;

    <span class="reserved">public</span> <span class="reserved">int</span> <span class="method">Next</span>()
    {
        <span class="reserved">var</span> <span class="variable">i</span> <span class="operator">=</span> <span class="field">_index</span>;
        <span class="reserved">var</span> <span class="variable">x</span> <span class="operator">=</span> <span class="variable local">values</span>[<span class="variable">i</span>];
        <span class="field">_index</span> <span class="operator">=</span> (<span class="variable">i</span> <span class="operator">+</span> <span class="number">1</span>) <span class="operator">%</span> <span class="variable local">values</span><span class="operator">.</span><span class="property">Length</span>; <span class="comment">// % Length することで範囲内に収める。 </span>
        <span class="control">return</span> <span class="variable">x</span>;
    }
}
</pre>
<p>この状態なら、単純に +1 でやっていて、 <code>i</code> が常に0以上なので特に問題は起きません。</p>
<p>で、これにちょこっと、「ステップ幅」みたいなのを足したとします。
インデックスを何個飛ばしするか。</p>
<pre class="source" title="(i + 1) % Length を (i + step) % Length に変更">
<span class="reserved">var</span> <span class="variable">table</span> <span class="operator">=</span> <span class="reserved">new</span> <span class="type struct">Table</span>([<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>], <span class="number">3</span>);

<span class="comment">// 3個飛ばしにしたので 1, 4, 2, 5, 3 と出力される。</span>
<span class="control">for</span> (<span class="reserved">var</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; <span class="variable">i</span> <span class="operator">&lt;</span> <span class="number">5</span>; <span class="variable">i</span><span class="operator">++</span>)
    <span class="static"><span class="type">Console</span></span><span class="operator">.</span><span class="static"><span class="method">WriteLine</span></span>(<span class="variable">table</span><span class="operator">.</span><span class="method">Next</span>());

<span class="reserved">struct</span> <span class="type struct">Table</span>(<span class="reserved">int</span>[] <span class="variable local">values</span>, <span class="reserved">int</span> <span class="variable local">step</span>)
{
    <span class="reserved">private</span> <span class="reserved">int</span> <span class="field">_index</span>;

    <span class="reserved">public</span> <span class="reserved">int</span> <span class="method">Next</span>()
    {
        <span class="reserved">var</span> <span class="variable">i</span> <span class="operator">=</span> <span class="field">_index</span>;
        <span class="reserved">var</span> <span class="variable">x</span> <span class="operator">=</span> <span class="variable local">values</span>[<span class="variable">i</span>];
        <span class="field">_index</span> <span class="operator">=</span> (<span class="variable">i</span> <span class="operator">+</span> <span class="variable local">step</span>) <span class="operator">%</span> <span class="variable local">values</span><span class="operator">.</span><span class="property">Length</span>; <span class="comment">// +1 を +step に変更。 </span>
        <span class="control">return</span> <span class="variable">x</span>;
    }
}
</pre>
<p>そしてうっかり、<code>step</code> を負にして <code>IndexOutOfRange</code>…</p>
<pre class="source" title="負のステップ">
<span class="reserved">var</span> <span class="variable">table</span> <span class="operator">=</span> <span class="reserved">new</span> <span class="type struct">Table</span>([<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>], <span class="operator">-</span><span class="number">1</span>);

<span class="comment">// IndexOutOfRange で止まる。</span>
<span class="control">for</span> (<span class="reserved">var</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; <span class="variable">i</span> <span class="operator">&lt;</span> <span class="number">5</span>; <span class="variable">i</span><span class="operator">++</span>)
    <span class="static"><span class="type">Console</span></span><span class="operator">.</span><span class="static"><span class="method">WriteLine</span></span>(<span class="variable">table</span><span class="operator">.</span><span class="method">Next</span>());

<span class="reserved">struct</span> <span class="type struct">Table</span>(<span class="reserved">int</span>[] <span class="variable local">values</span>, <span class="reserved">int</span> <span class="variable local">step</span>)
{
    <span class="reserved">private</span> <span class="reserved">int</span> <span class="field">_index</span>;

    <span class="reserved">public</span> <span class="reserved">int</span> <span class="method">Next</span>()
    {
        <span class="reserved">var</span> <span class="variable">i</span> <span class="operator">=</span> <span class="field">_index</span>;
        <span class="reserved">var</span> <span class="variable">x</span> <span class="operator">=</span> <span class="variable local">values</span>[<span class="variable">i</span>];
        <span class="field">_index</span> <span class="operator">=</span> (<span class="variable">i</span> <span class="operator">+</span> <span class="variable local">step</span>) <span class="operator">%</span> <span class="variable local">values</span><span class="operator">.</span><span class="property">Length</span>; <span class="comment">// 負 % 正 の結果は負です。 </span>
        <span class="control">return</span> <span class="variable">x</span>;
    }
}
</pre>
<p>「負 % 正」の結果は負になるので、<code>values[i]</code> が例外を起こすようになります。</p>
<p>何か多少気持ち悪いですよね。
この類の <code>(i + step) % Length</code> って、
意味的には「配列の末尾を超えたら先頭に戻る」なわけです。
だったら逆に、「配列の先頭を超えたら末尾に戻る」もあってもいいわけで。
この例(<code>Length</code> が5)でいうと、<code>values[0]</code> の次は <code>values[4]</code> に行ってほしい。</p>
<h2><a id="divrem-sign">剰余の符号</a></h2>
<p>前節みたいな動作になるのは、「大体の CPU の剰余命令がそういう実装だから」です。
C# を始めとして、そこそこパフォーマンスを気にするプログラミング言語では、だいたい「ハードウェア的に一番速い奴を選ぶ」な方針になります。</p>
<p>そもそも、整数の剰余自体、ちょっと定義がぶれていまして。
「以下の条件を満たす」というところまではほとんどの環境で合意が得られてる感じではあるんですが:</p>
<blockquote>
<p>a を n で割った商(quotient )を q、余り(remainder )を r として、</p>
<ul>
<li>a = nq + r</li>
<li>|r| &lt; |n|</li>
</ul>
</blockquote>
<p>商 q は (実数で計算した場合の) a ÷ n に近い整数ではあるんですが、丸め方によって値が1ずれます。
その結果、余り r の符号も変わります。</p>
<p>例えば、以下のコードで得られる <code>q</code> と <code>r</code> はどの丸め方でも必ず <code>a == n * q + r</code>、<code>Abs(r) &lt; Abs(n)</code> の条件を満たします。</p>
<pre class="source" title="丸め方の違いでバリエーションがある商と余り">
<span class="comment">// 一度 double で計算して、商の丸め方式をいろいろ変えてみる。</span>
<span class="comment">// 余りは常に r = a - q * n で計算。</span>
<span class="reserved">static</span> (<span class="reserved">int</span> q, <span class="reserved">int</span> r) <span class="method"><span class="static">DivRem</span></span>(<span class="reserved">int</span> <span class="variable local">a</span>, <span class="reserved">int</span> <span class="variable local">n</span>, <span class="type">MidpointRounding</span> <span class="variable local">mode</span>)
{
    <span class="reserved">var</span> <span class="variable">q</span> <span class="operator">=</span> (<span class="reserved">int</span>)<span class="static"><span class="type">Math</span></span><span class="operator">.</span><span class="static"><span class="method">Round</span></span>((<span class="reserved">double</span>)<span class="variable local">a</span> <span class="operator">/</span> <span class="variable local">n</span>, <span class="variable local">mode</span>);
    <span class="reserved">var</span> <span class="variable">r</span> <span class="operator">=</span> <span class="variable local">a</span> <span class="operator">-</span> <span class="variable">q</span> <span class="operator">*</span> <span class="variable local">n</span>;
    <span class="control">return</span> (<span class="variable">q</span>, <span class="variable">r</span>);
}
</pre>
<p>一応、これでどういう結果が得られるかも例示しておきます:</p>
<pre class="source" title="DivRem の実行例">
<span class="method"><span class="static">ShowDivRem</span></span>(<span class="number">5</span>, <span class="number">3</span>);
<span class="method"><span class="static">ShowDivRem</span></span>(<span class="operator">-</span><span class="number">5</span>, <span class="number">3</span>);
<span class="method"><span class="static">ShowDivRem</span></span>(<span class="number">5</span>, <span class="operator">-</span><span class="number">3</span>);
<span class="method"><span class="static">ShowDivRem</span></span>(<span class="operator">-</span><span class="number">5</span>, <span class="operator">-</span><span class="number">3</span>);

<span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">ShowDivRem</span></span>(<span class="reserved">int</span> <span class="variable local">x</span>, <span class="reserved">int</span> <span class="variable local">y</span>)
{
    <span class="static"><span class="type">Console</span></span><span class="operator">.</span><span class="method"><span class="static">WriteLine</span></span>(<span class="string">$&quot;</span><span class="string">DivRem(</span>{<span class="variable local">x</span>}<span class="string">, </span>{<span class="variable local">y</span>}<span class="string">)</span><span class="string">&quot;</span>);
    <span class="type"><span class="static">Console</span></span><span class="operator">.</span><span class="static"><span class="method">WriteLine</span></span>(<span class="string">$&quot;</span><span class="string">  to 0  </span>{<span class="method"><span class="static">DivRem</span></span>(<span class="variable local">x</span>, <span class="variable local">y</span>, <span class="type">MidpointRounding</span><span class="operator">.</span>ToZero)}<span class="string">&quot;</span>);
    <span class="type"><span class="static">Console</span></span><span class="operator">.</span><span class="static"><span class="method">WriteLine</span></span>(<span class="string">$&quot;</span><span class="string">  floor </span>{<span class="method"><span class="static">DivRem</span></span>(<span class="variable local">x</span>, <span class="variable local">y</span>, <span class="type">MidpointRounding</span><span class="operator">.</span>ToNegativeInfinity)}<span class="string">&quot;</span>);
    <span class="static"><span class="type">Console</span></span><span class="operator">.</span><span class="method"><span class="static">WriteLine</span></span>(<span class="string">$&quot;</span><span class="string">  ceil  </span>{<span class="method"><span class="static">DivRem</span></span>(<span class="variable local">x</span>, <span class="variable local">y</span>, <span class="type">MidpointRounding</span><span class="operator">.</span>ToPositiveInfinity)}<span class="string">&quot;</span>);
    <span class="static"><span class="type">Console</span></span><span class="operator">.</span><span class="static"><span class="method">WriteLine</span></span>(<span class="string">$&quot;</span><span class="string">  away  </span>{<span class="method"><span class="static">DivRem</span></span>(<span class="variable local">x</span>, <span class="variable local">y</span>, <span class="type">MidpointRounding</span><span class="operator">.</span>AwayFromZero)}<span class="string">&quot;</span>);
}
</pre>
<pre class="console" title="DivRem の実行例">
DivRem(5, 3)
  to 0  (1, 2)
  floor (1, 2)
  ceil  (2, -1)
  away  (2, -1)
DivRem(-5, 3)
  to 0  (-1, -2)
  floor (-2, 1)
  ceil  (-1, -2)
  away  (-2, 1)
DivRem(5, -3)
  to 0  (-1, 2)
  floor (-2, -1)
  ceil  (-1, 2)
  away  (-2, -1)
DivRem(-5, -3)
  to 0  (1, -2)
  floor (1, -2)
  ceil  (2, 1)
  away  (2, 1)
</pre>
<p>C# の整数の <code>/</code> と <code>%</code> (= 大体の CPU の剰余命令の結果)は、この例でいうと <code>ToZero</code> と同じです。
例を見ての通り、余り <code>r</code>の符号は被除数 <code>a</code> と一致します。</p>
<p>一方、<a href="#mod-usecase">前節</a>みたいなものを含め、アルゴリズム的に使いやすいのは <code>ToNegativeInfinity</code> (floor)かもしれません。
正負反転のタイミングで不連続がないのと、r が正負問わず 0～n の範囲に収まるので。</p>
<p>ちなみに、数学では<a href="https://ja.wikipedia.org/wiki/%E9%99%A4%E6%B3%95%E3%81%AE%E5%8E%9F%E7%90%86">ユークリッド除法</a>を根拠として、</p>
<ul>
<li>余り r が常に正になるようにする</li>
<li>それに合わせて q を (a - r) ÷ n で計算</li>
</ul>
<p>とすることが多いそうです。</p>
<h2><a id="euclidean-mod-operator">没案: %% 演算子</a></h2>
<p>「<a href="#divrem-sign">いろんな剰余があり得る</a>」という話をしたところで、
<a href="#mod-usecase">最初の例</a>に戻りましょう。
最初の例では、要するに「<code>(i + step) % Length</code> の結果は正が良かったな」という話になります。</p>
<p>ということで出てきたのが以下の提案。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/7599">Proposal: New operator %% for canonical Modulus operations #7599</a></li>
</ul>
<p>ここでいう canonical (聖典・規範に準ずる)というのは、「数学の定義に準ずる」みたいな意味で言っていて、
前節の「ユークリッド除法を根拠にした、余り r を常に正する」方式です。
この定義の余りを返す演算子として <code>%%</code> 演算子を足すのはどうかという案。</p>
<p>結果的にリジェクトされてるんですけども、理由はまあ、前節の説明の後だとわかりやすいですね。
以下のようなことを考えた時、本当に演算子として追加するのが望ましいのかどうかというと微妙。</p>
<ul>
<li>
剰余にもいろいろある
<ul>
<li>例えば今の場合、<code>Length</code> が正なことはわかっているので、<code>ToNegativeInfinity</code> 丸めでもいい</li>
</ul>
</li>
<li>
商と余りはセットで考えないとダメ
<ul>
<li><code>%%</code> と対になる除算も必要？</li>
</ul>
</li>
</ul>
<p>まあ、言語組み込みの演算子ではなく、
ライブラリ提供のメソッドでやるべきでしょうね。
以下の方法で上記の問題は解決できるので。</p>
<ul>
<li><code>Divide</code>、<code>Remainder</code>、<code>DivRem</code> メソッドをセットで提供</li>
<li>丸め方式は引数で明示</li>
</ul>
<h2><a id="divrem-rounding">DivRem メソッド</a></h2>
<p>ということで、dotnet/runtime 側に以下の提案が出ています。</p>
<ul>
<li><a href="https://github.com/dotnet/runtime/issues/93568">Provide support for alternative rounding modes for division and remainder of division. #93568</a></li>
</ul>
<p>現状の案では以下のようなメソッドの追加になります。</p>
<pre class="source" title="丸め方式指定付きの DivRem">
<span class="reserved">namespace</span> System<span class="operator">.</span>Numerics;

<span class="reserved">public</span> <span class="reserved">enum</span> <span class="type">DivisionRounding</span>
{
    Truncate <span class="operator">=</span> <span class="number">0</span>,        <span class="comment">// Towards Zero</span>
    Floor <span class="operator">=</span> <span class="number">1</span>,           <span class="comment">// Towards -Infinity</span>
    Ceiling <span class="operator">=</span> <span class="number">2</span>,         <span class="comment">// Towards +Infinity</span>
    AwayFromZero <span class="operator">=</span> <span class="number">3</span>,    <span class="comment">// Away from Zero</span>
    Euclidean <span class="operator">=</span> <span class="number">4</span>,       <span class="comment">// floor(x / abs(n)) * sign(n)</span>
}

<span class="reserved">public</span> <span class="reserved">partial</span> <span class="reserved">interface</span> <span class="type">IBinaryInteger</span>&lt;<span class="type param">TSelf</span>&gt;
{
    <span class="reserved">static</span> <span class="reserved">virtual</span> <span class="type param">TSelf</span> <span class="method"><span class="static">Divide</span></span>(<span class="type param">TSelf</span> <span class="variable local">left</span>, <span class="type param">TSelf</span> <span class="variable local">right</span>, <span class="type">DivisionRounding</span> <span class="variable local">mode</span>);
    <span class="reserved">static</span> <span class="reserved">virtual</span> (<span class="type param">TSelf</span> Quotient, <span class="type param">TSelf</span> Remainder) <span class="method"><span class="static">DivRem</span></span>(<span class="type param">TSelf</span> <span class="variable local">left</span>, <span class="type param">TSelf</span> <span class="variable local">right</span>, <span class="type">DivisionRounding</span> <span class="variable local">mode</span>);
    <span class="reserved">static</span> <span class="reserved">virtual</span> <span class="type param">TSelf</span> <span class="static"><span class="method">Remainder</span></span>(<span class="type param">TSelf</span> <span class="variable local">left</span>, <span class="type param">TSelf</span> <span class="variable local">right</span>, <span class="type">DivisionRounding</span> <span class="variable local">mode</span>);
}
</pre>
<p>おそらくこれらは .NET 10 で入ります。
(デザイン レビューで承認済みで、すでに<a href="https://github.com/dotnet/runtime/pull/104589">実装作業も始まって Pull Request が出ている</a>状態。)</p>
 ]]></description>
				<pubDate>Wed, 25 Dec 2024 21:02:17 +0900</pubDate>
			</item>
			<item>
				<title>(没) UTF-8 文字列補間</title>
				<link>http://ufcpp.net/blog/2024/12/u8-string-interpolation/</link>
				<description><![CDATA[ <p>今日のは、C# 言語機能としては否決されたものの、ほぼ同等のものがライブラリと JIT 時最適化で実現されたという話になります。</p>
<p>ちなみに今日のこの話は .NET 8 の頃の話で、「そういえば去年書いてなかった」ネタになります。</p>
<h2>UTF-8 リテラルがあるなら</h2>
<p>C# 11 で <a href="https://ufcpp.net/study/csharp/st_string.html?p=3#utf8-literal">UTF-8 リテラル</a>が入って、
C# プログラム中に UTF-8 なバイト列を <code>ReadOnlySpan&lt;byte&gt;</code> で直接埋め込めるようになりました。</p>
<pre class="source" title="UTF-8 リテラル">
<span class="type struct">ReadOnlySpan</span>&lt;<span class="reserved">byte</span>&gt; <span class="variable">hex</span> <span class="operator">=</span> <span class="string">&quot;0123456789ABCDEF&quot;</span><span class="reserved">u8</span>;
</pre>
<p><a href="https://ufcpp.net/study/csharp/st_string.html?p=3#history">割かし何度も書いてたりはしますが</a>、
もう今となっては世の中の多くの文字列が UTF-8 でやり取りされています。
.NET の <code>string</code> が UTF-16 ベースなので、UTF-16 ⇔ UTF-8 の変換がそれなりのコストになっていたりします。</p>
<p>そこで、いろんなものを直接 UTF-8 で書き込んだりするようになりました。
今、 .NET のプリミティブ型にも <a href="https://learn.microsoft.com/ja-jp/dotnet/api/system.iutf8spanformattable"><code>IUtf8SpanFormattable</code> インターフェイス</a>とかが実装されていて、UTF-8 文字列化を直接できるようになっています。</p>
<p>そうなると欲しくなるのが UTF-8 に直接書き込める<a href="https://ufcpp.net/study/csharp/st_string.html#string-interpolation">文字列補間</a>。
以下のようなことをできるといいなぁという要望があります。</p>
<pre class="source" title="(提案) UTF-8 リテラルの延長で、UTF-8 文字列補間が欲しい">
<span class="reserved">static</span> <span class="reserved">byte</span>[] <span class="static"><span class="method">Format</span></span>(<span class="reserved">int</span> <span class="variable local">x</span>, <span class="reserved">int</span> <span class="variable local">y</span>) <span class="operator">=&gt;</span> <span class="string">$&quot;</span><span class="string">(X: </span>{<span class="variable local">x</span>:<span class="string">X2</span>}<span class="string">, Y: </span>{<span class="variable local">y</span>:<span class="string">X2</span>}<span class="string">)&quot;</span><span class="reserved">u8</span></span>;
</pre>
<p>要は、文字列補間の <code>$&quot;&quot;</code> にも <code>u8</code> を付けて、直接 UTF-8 を書き込むというもの。</p>
<p>この提案、一瞬本気で検討はされてたんですけども:</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/7072">[Proposal]: u8 string interpolation #7072</a></li>
</ul>
<p>結論がどうなったかというと、「普通の文字列補間を使って、パフォーマンスを落とさずに UTF-8 補間できるように JIT 最適化したからいいや」という感じで、C# 言語機能は不要ということになりました。</p>
<h2>Utf8.TryWrite</h2>
<p>前節の UTF-8 文字列補間(案)に類することをやるために、 .NET 8 移行、以下のような書き方ができます。</p>
<pre class="source" title="Utf8.TryWrite で UTF-8 文字列補間">
<span class="reserved">using</span> System<span class="operator">.</span>Text<span class="operator">.</span>Unicode;

<span class="reserved">static</span> <span class="reserved">byte</span>[] <span class="static"><span class="method">Format</span></span>(<span class="reserved">int</span> <span class="variable local">x</span>, <span class="reserved">int</span> <span class="variable local">y</span>)
{
    <span class="reserved">var</span> <span class="variable">temp</span> <span class="operator">=</span> (<span class="reserved">stackalloc</span> <span class="reserved">byte</span>[<span class="number">64</span>]);

    <span class="static"><span class="type">Utf8</span></span><span class="operator">.</span><span class="static"><span class="method">TryWrite</span></span>(<span class="variable">temp</span>, <span class="string">$&quot;</span><span class="string">(X: </span>{<span class="variable local">x</span>:<span class="string">X2</span>}<span class="string">, Y: </span>{<span class="variable local">y</span>:<span class="string">X2</span>}<span class="string">)&quot;</span>, <span class="reserved">out</span> <span class="reserved">var</span> <span class="variable">written</span>);

    <span class="control">return</span> <span class="variable">temp</span>[..<span class="variable">written</span>]<span class="operator">.</span><span class="method">ToArray</span>();
}
</pre>
<p><code>Utf8</code> クラスの <code>TryWrite</code> メソッドを使って直接 UTF-8 なバイト列を作れます。</p>
<p>ただ、文字列補間の部分は普通の <code>$&quot;&quot;</code> で書きます。
そして、この文字列補間の展開結果は以下の通り。</p>
<pre class="source" title="Utf8.TryWrite 中の文字列補間の展開結果">
<span class="reserved">using</span> System<span class="operator">.</span>Text<span class="operator">.</span>Unicode;

<span class="reserved">static</span> <span class="reserved">byte</span>[] <span class="method"><span class="static">Format</span></span>(<span class="reserved">int</span> <span class="variable local">x</span>, <span class="reserved">int</span> <span class="variable local">y</span>)
{
    <span class="reserved">var</span> <span class="variable">temp</span> <span class="operator">=</span> (<span class="reserved">stackalloc</span> <span class="reserved">byte</span>[<span class="number">64</span>]);

    <span class="type"><span class="static">Utf8</span></span><span class="operator">.</span><span class="type struct">TryWriteInterpolatedStringHandler</span> <span class="variable">handler</span> <span class="operator">=</span> <span class="reserved">new</span>(<span class="number">9</span>, <span class="number">2</span>, <span class="variable">temp</span>, <span class="reserved">out</span> <span class="reserved">var</span> <span class="variable">shouldAppend</span>);

    <span class="control">if</span> (<span class="variable">shouldAppend</span>
        <span class="operator">&amp;&amp;</span> <span class="variable">handler</span><span class="operator">.</span><span class="method">AppendLiteral</span>(<span class="string">&quot;X: &quot;</span>)
        <span class="operator">&amp;&amp;</span> <span class="variable">handler</span><span class="operator">.</span><span class="method">AppendFormatted</span>(<span class="variable local">x</span>, <span class="string">&quot;X2&quot;</span>)
        <span class="operator">&amp;&amp;</span> <span class="variable">handler</span><span class="operator">.</span><span class="method">AppendLiteral</span>(<span class="string">&quot;, Y: &quot;</span>)
        )  <span class="variable">handler</span><span class="operator">.</span><span class="method">AppendFormatted</span>(<span class="variable local">y</span>, <span class="string">&quot;X2&quot;</span>);

    <span class="static"><span class="type">Utf8</span></span><span class="operator">.</span><span class="static"><span class="method">TryWrite</span></span>(<span class="variable">temp</span>, <span class="reserved">ref</span> <span class="variable">handler</span>, <span class="reserved">out</span> <span class="reserved">var</span> <span class="variable">written</span>);

    <span class="control">return</span> <span class="variable">temp</span>[..<span class="variable">written</span>]<span class="operator">.</span><span class="method">ToArray</span>();
}
</pre>
<h2>定数文字列の最適化</h2>
<p>前節、UTF-8 補間に、普通の文字列補間構文を使っているため、
<code>AppendLiteral(&quot;X: &quot;)</code> とかで、普通の文字列リテラル(UTF-16)が発生しています。
当然ここで「そんなことしたら UTF-16 から UTF-8 への変換コストが発生したりするんじゃないか？」という話になるんですが、
そこが今日の本題。
.NET 8 移行、定数文字列の最適化がものすごい進んだみたいでして。
結果、この変換コストはほとんど発生しないそうです。</p>
<p><code>AppendLiteral</code> の中身はこんな感じ:</p>
<ul>
<li><a href="https://github.com/dotnet/runtime/blob/4695f3f0e2fcfdd94602a21d6ef0670fc85f6d2a/src/libraries/System.Private.CoreLib/src/System/Text/Unicode/Utf8.cs#L399C25-L419">Utf8.cs#L399C25-L419</a></li>
</ul>
<p>内部的に <code>ReadUtf8</code> ってのを呼んでるんですけども、これはこちら:</p>
<ul>
<li><a href="https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/Text/UTF8Encoding.Sealed.cs#L158-L171">UTF8Encoding.Sealed.cs#L158-L171</a></li>
</ul>
<p>説明文に、</p>
<blockquote>
<p>Same as Encoding.UTF8.TryGetBytes, except with refs, returning the number of bytes written (or -1 if the operation fails), and optimized for a constant input.</p>
</blockquote>
<p>(<code>Encoding.UTF8.TryGetBytes</code> とほとんど一緒で、違いは、ref を使っていて書き込んだバイト数を返すのと、<strong>定数入力に対して最適化される</strong>。)</p>
<p>と書かれていますし、<code>Intrinsic</code> 属性が付いています。
この属性が付いているメソッドは「JIT が特別な最適化したものに置き換える」というマーカーでして、
定数文字列の UTF-16 → UTF-8 変換は JIT がやっちゃいます。
この最適化の Pull Request は以下の通り:</p>
<ul>
<li><a href="https://github.com/dotnet/runtime/pull/85328">JIT: Intrinsify UTF16-&gt;UTF8 conversion for string literals (Encoding.UTF8.TryGetBytes) #85328</a></li>
</ul>
<p>これのおかげで、
<code>AppendLiteral(&quot;X: &quot;)</code> のコストがほぼ <code>AppendLiteral(&quot;X: &quot;u8)</code> (みたいな <code>ReadOnlySpan&lt;byte&gt;</code> 引数オーバーロードを足すの)と同レベルになるそうで。</p>
<h2>$&quot;&quot;u8 要る？</h2>
<p>そこで本題に戻りまして、UTF-8 文字列補間用の構文、すなわち、<code>$&quot;&quot;u8</code> みたいなものは必要かどうか。</p>
<p>ここまでで説明したように、<code>Utf8.TryWrite(temp, $&quot;(X: {x:X2}, Y: {y:X2})&quot;, out var written);</code> みたいに普通の文字列補間(C# のコンパイル結果的には UTF-16)で書いても、JIT 時最適化で UTF-16 から UTF-8 の変換コストがかなり低コストになっています。</p>
<p>この事実を踏まえて、<a href="https://github.com/dotnet/csharplang/blob/227c84c027dee993934d39800aaa6ba8331ea1ea/meetings/2023/LDM-2023-10-16.md#u8-string-interpolation">改めて C# コンパイラー チーム内で検討した結果</a>、
backlog (未処理・未完成品、C# チーム用語的には「よっぽど斬新なアイディアが出てこない限りやらない」)行きになりました。</p>
<p>まあ、確かに、<code>Utf8.TryWrite</code> で事足りた感じはあります。</p>
 ]]></description>
				<pubDate>Thu, 19 Dec 2024 22:13:12 +0900</pubDate>
			</item>
			<item>
				<title>.NET 9 の破壊的変更の1つを踏んだ話</title>
				<link>http://ufcpp.net/blog/2024/12/satulating-float-to-int/</link>
				<description><![CDATA[ <p>かなりのレアケースを踏んだので酒の肴程度にその話を。</p>
<h2>破壊的変更の内容: 浮動小数点数 → 整数の飽和変換</h2>
<p>破壊的変更の告知ページ:</p>
<ul>
<li><a href="https://learn.microsoft.com/ja-jp/dotnet/core/compatibility/jit/9.0/fp-to-integer">Floating point-to-integer conversions are saturating</a></li>
</ul>
<p>最小再現コードは以下の通り。</p>
<pre class="source" title=".NET 8 と 9 で挙動が違うコードの例">
<span class="reserved">var</span> <span class="variable">x</span> <span class="operator">=</span> <span class="reserved">int</span><span class="operator">.</span><span class="static"><span class="constant">MaxValue</span></span>;
<span class="reserved">var</span> <span class="variable">y</span> <span class="operator">=</span> (<span class="reserved">float</span>)<span class="variable">x</span>;
<span class="reserved">var</span> <span class="variable">z</span> <span class="operator">=</span> (<span class="reserved">int</span>)<span class="variable">y</span>;
<span class="type"><span class="static">Console</span></span><span class="operator">.</span><span class="static"><span class="method">WriteLine</span></span>(<span class="variable">z</span>);
</pre>
<p><code>z</code> の値は、
.NET 8 では <code>-2147483648</code> (<code>int.MinValue</code>) になって、
.NET 9 では <code>2147483647</code> (<code>int.MaxValue</code>) になります。</p>
<p>(注意: <code>float</code> の精度の問題で、<code>y</code> の値は <code>int.MaxValue</code> よりも大きい扱いを受けていそうです。
<code>double</code> では2行目を <code>var y = (double)x + 1;</code> にすると再現。)</p>
<p><code>int</code> の範囲に収まらない <code>float</code> の値を <code>int</code> に変換した時の挙動が変わりました。</p>
<ul>
<li>古い挙動: <code>x &lt; int.MinValue</code> もしくは <code>x &gt; int.MaxValue</code> のとき、<code>(int)x</code> は <code>int.MinValue</code> になる</li>
<li>新しい挙動: <code>x &lt; int.MinValue</code> のとき <code>(int)x</code> は <code>int.MinValue</code>、<code>x &gt; int.MaxnValue</code> のとき <code>(int)x</code> は <code>int.MaxValue</code></li>
</ul>
<p>どう見ても新しい挙動の方が自然…</p>
<h2>破壊的変更をした理由</h2>
<p>変な挙動であっても、変更するメリットがそれなりにないと破壊的変更が認められることはほとんどありません。</p>
<p>今回の場合何があったのかというと、AVX512 命令を使いたかったということみたいです。</p>
<ul>
<li><a href="https://github.com/dotnet/runtime/pull/97529">Scalar/Packed conversions for floating point to integer #97529</a></li>
</ul>
<p>AVX512 には <code>double</code>, <code>float</code> を <code>int</code>, <code>uint</code> とかに変換するための vfixupimmsd などの命令があるそうで。
ハードウェア命令を持っているんなら、ソフトウェア計算するよりもこの命令を使った方がパフォーマンスがよくなります。
当然、積極的に活用したいんですが、どうも、この命令の挙動が前節の「新しい挙動」になるみたいです。</p>
<p>「AVX512 命令が使える場合だけ挙動が変わる」みたいなことになるとかえってまずいので、だったら、
AVX512 が使えないとき向けのソフトウェア実装の挙動も改めて、
破壊的変更の告知を出してしまおうという流れに。</p>
<h2>破壊的変更の踏み方</h2>
<p>「<code>int.MaxValue</code> を超える値を <code>int</code> に変換して使う」とか普通はやらないし、
「こんなの影響する人いないでしょ」と高を括っていたものの…</p>
<p>自社のコードに .NET 8 から 9 に変更したら永久ループを起こすコードがありました。
すごく簡素化して書くと以下のようなコードがあったせい。</p>
<pre class="source" title="飽和変換の仕様変更が永久ループになる例">
<span class="comment">// .NET 9 でだけ永久ループ…</span>
<span class="static"><span class="method">M</span></span>((<span class="reserved">int</span>)<span class="type"><span class="static">Math</span></span><span class="operator">.</span><span class="static"><span class="method">Floor</span></span>(<span class="reserved">float</span><span class="operator">.</span><span class="constant"><span class="static">MaxValue</span></span>), (<span class="reserved">int</span>)<span class="static"><span class="type">Math</span></span><span class="operator">.</span><span class="static"><span class="method">Floor</span></span>(<span class="reserved">float</span><span class="operator">.</span><span class="static"><span class="constant">MaxValue</span></span>));

<span class="type"><span class="static">Console</span></span><span class="operator">.</span><span class="static"><span class="method">WriteLine</span></span>(<span class="string">&quot;done.&quot;</span>);

<span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">M</span></span>(<span class="reserved">int</span> <span class="variable local">x</span>, <span class="reserved">int</span> <span class="variable local">y</span>)
{
    <span class="comment">// y が int.MaxValue だと、i++ がオーバーフローして永久ループになる。</span>
    <span class="control">for</span> (<span class="reserved">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="variable local">x</span>; <span class="variable">i</span> <span class="operator">&lt;=</span> <span class="variable local">y</span>; <span class="variable">i</span><span class="operator">++</span>) ;
}
</pre>
<p>.NET 8 では、<code>M</code> の引数に渡る値は <code>int.MinValue</code> でした。
それが、.NET 9 になると <code>int.MaxValue</code> に変わります。</p>
<p>で、以下のコードは「<code>for</code> の中を1回だけ実行」になりますが、</p>
<pre class="source" title="&lt;= MinVavlue">
<span class="control">for</span> (<span class="reserved">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="reserved">int</span><span class="operator">.</span><span class="static"><span class="constant">MinValue</span></span>; <span class="variable">i</span> <span class="operator">&lt;=</span> <span class="reserved">int</span><span class="operator">.</span><span class="constant"><span class="static">MinValue</span></span>; <span class="variable">i</span><span class="operator">++</span>) ;
</pre>
<p>以下のコードは永久ループです。</p>
<pre class="source" title="&lt;= MaxVavlue">
<span class="comment">// i++ がオーバーフローするので i &lt;= int.MaxValue が false になることはない。</span>
<span class="control">for</span> (<span class="reserved">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="reserved">int</span><span class="operator">.</span><span class="static"><span class="constant">MaxValue</span></span>; <span class="variable">i</span> <span class="operator">&lt;=</span> <span class="reserved">int</span><span class="operator">.</span><span class="constant"><span class="static">MaxValue</span></span>; <span class="variable">i</span><span class="operator">++</span>) ;
</pre>
<p>背景としては以下のような感じ。</p>
<ul>
<li><code>record struct Point(float X, float Y)</code> で座標管理している</li>
<li>「無効な座標」が必要になったものの、工数的に <code>Point?</code> に書き換える余裕はなかった</li>
<li>「すごく遠い座標」を与えてみて、テストプレイしてみたところ所望の動作になったので、<code>float.MaxValue</code> の座標に飛ばしてた</li>
<li>経路探索ロジックが、パフォーマンスのため、内部的に整数で計算していた</li>
<li><code>for (int i = x; i &lt;= y; i++)</code> に <code>(int)float.MaxValue</code> が来る</li>
<li><code>for</code> は、<code>i</code> が <code>int.MinValue</code> だったら何も起きないようなコードだった(ループ内を1回通ってたけども特に問題は起きなかった)</li>
</ul>
<p>だいぶレアな不幸が重なった感じ…</p>
<p>以下の条件が重ならないと起きないですからね。</p>
<ul>
<li><code>float.MaxValue</code> (<code>int.MaxValue</code> を超える値)を特殊な意味に使っちゃった</li>
<li><code>&lt;=</code> でループしてる</li>
<li><code>int.MinValue</code> のときにはたまたま問題を起こさないコードだった</li>
</ul>
<p>問題を特定できた時、かなりびっくりしました。</p>
 ]]></description>
				<pubDate>Wed, 18 Dec 2024 21:09:06 +0900</pubDate>
			</item>
			<item>
				<title>ref/ref struct 変数を非同期メソッド中で使えるように</title>
				<link>http://ufcpp.net/blog/2024/4/ref-in-async/</link>
				<description><![CDATA[ <p><a href="https://ufcpp.net/blog/2024/4/lock-class/">前回の <code>Lock</code> クラスの話</a>を見てから、とりあえず以下のコードを見てほしい。</p>
<pre class="source" title="非同期メソッド中でエラーに">
<span class="reserved">using</span> System<span class="operator">.</span>Runtime<span class="operator">.</span>Versioning;

[<span class="reserved">module</span>: <span class="type">RequiresPreviewFeatures</span>]

<span class="reserved">class</span> <span class="type">MultiThreadCode</span>
{
    <span class="reserved">private</span> <span class="reserved">static</span> <span class="reserved">readonly</span> <span class="reserved">object</span> <span class="field"><span class="static">_syncObj</span></span> <span class="operator">=</span> <span class="reserved">new</span>();
    <span class="reserved">private</span> <span class="reserved">static</span> <span class="reserved">readonly</span> <span class="type">Lock</span> <span class="field"><span class="static">_syncLock</span></span> <span class="operator">=</span> <span class="reserved">new</span>();

    <span class="reserved">public</span> <span class="reserved">static</span> <span class="type">IEnumerable</span>&lt;<span class="reserved">object</span><span class="operator">?</span>&gt; <span class="method"><span class="static">MIterator</span></span>()
    {
        <span class="reserved">lock</span> (<span class="field"><span class="static">_syncObj</span></span>) { } <span class="comment">// 旧来 lock。</span>
        <span class="reserved">lock</span> (<span class="field"><span class="static">_syncLock</span></span>) { } <span class="comment">// 新しい lock (VS 17.10p2 以降)。</span>

        <span class="control">yield</span> <span class="control">return</span> <span class="reserved">null</span>;
    }

    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">async</span> <span class="type struct">ValueTask</span> <span class="method"><span class="static">MAsync</span></span>()
    {
        <span class="reserved">lock</span> (<span class="static"><span class="field">_syncObj</span></span>) { }
        <span class="reserved">lock</span> (<span class="static"><span class="error" title="CS9217"><span class="field">_syncLock</span></span></span>) { } <span class="comment">// これだけダメ(VS 17.10p2 以降)。</span>

        <span class="reserved">await</span> <span class="type">Task</span><span class="operator">.</span><span class="method"><span class="static">Yield</span></span>();
    }
}
</pre>
<p>おそらく C# 13 正式リリースまでには直ると思うんですが、
どうしてこうなるのかと、どう対処する予定なのかという話になります。</p>
<p>ちなみに、単に <code>Lock</code> クラスに対して特殊処理をするという話ではなく、
もう少し汎用に「非同期メソッド中で ref ローカル変数を使えるようにする」という対処になります。</p>
<h2>lock の展開</h2>
<p>[前回の話]で、今回関係するのは、<code>Lock</code> インスタンスに対する <code>lock</code> ステートメントが <code>using (x.EnterScope())</code> み化けるという点。
で、さらにいうと、<code>using</code> は以下のように展開されます。</p>
<pre class="source" title="lock → using → try-finally">
<span class="reserved">class</span> <span class="type">MultiThreadCode</span>
{
    <span class="reserved">private</span> <span class="reserved">static</span> <span class="reserved">readonly</span> <span class="type">Lock</span> <span class="field"><span class="static">_syncLock</span></span> <span class="operator">=</span> <span class="reserved">new</span>();

    <span class="comment">// 元コード。</span>
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="static"><span class="method">A</span></span>()
    {
        <span class="reserved">lock</span> (<span class="field"><span class="static">_syncLock</span></span>) { }
    }

    <span class="comment">// lock → using。</span>
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">B</span></span>()
    {
        <span class="reserved">using</span> (<span class="static"><span class="field">_syncLock</span></span><span class="operator">.</span><span class="method">EnterScope</span>()) { }
    }

    <span class="comment">// using → try-finally。</span>
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="static"><span class="method">C</span></span>()
    {
        <span class="type">Lock</span><span class="operator">.</span><span class="type struct">Scope</span> <span class="variable">scope</span> <span class="operator">=</span> <span class="field"><span class="static">_syncLock</span></span><span class="operator">.</span><span class="method">EnterScope</span>();
        <span class="control">try</span>
        {
        }
        <span class="control">finally</span>
        {
            <span class="variable">scope</span><span class="operator">.</span><span class="method">Dispose</span>();
        }
    }
}
</pre>
<p>ここで、<code>Lock.Scope</code> は <a href="https://ufcpp.net/study/csharp/resource/refstruct/">ref struct</a> になっています。
これが先ほどのコードで非同期メソッド中の <code>lock (_syncLock)</code> がエラーになる原因です。
問題の本質としては以下のようなコードと同じ。</p>
<pre class="source" title="非同期メソッド中では ref struct を使えない">
<span class="reserved">class</span> <span class="type">A</span>
{
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="type">IEnumerable</span>&lt;<span class="reserved">object</span><span class="operator">?</span>&gt; <span class="method"><span class="static">MIterator</span></span>()
    {
        <span class="comment">// イテレーター中では ref strcut を使える。</span>
        <span class="comment">// (ただし、yield をまたがない場合のみ。)</span>
        <span class="type struct">Span</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">span</span> <span class="operator">=</span> <span class="reserved">stackalloc</span> <span class="reserved">int</span>[<span class="number">1</span>];

        <span class="control">yield</span> <span class="control">return</span> <span class="reserved">null</span>;
    }

    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">async</span> <span class="type struct">ValueTask</span> <span class="method"><span class="static">MAsync</span></span>()
    {
        <span class="comment">// こちらはダメ。</span>
        <span class="error" title="CS4012"><span class="type struct">Span</span>&lt;<span class="reserved">int</span>&gt;</span> <span class="variable">span</span> <span class="operator">=</span> <span class="reserved">stackalloc</span> <span class="reserved">int</span>[<span class="number">1</span>];

        <span class="reserved">await</span> <span class="type">Task</span><span class="operator">.</span><span class="method"><span class="static">Yield</span></span>();
    }
}
</pre>
<p>イテレーターと非同期メソッドって、仕組みがかなり似ていて、「イテレーターでできて非同期メソッドでできない」ということは原理的にはあまりないんですが。
実際、上記の挙動は単に実装都合で、コストさえかければ「非同期メソッド中でも ref struct のローカル変数を書けるようにする」というのは可能です。</p>
<h2>イテレーターの中断と再開</h2>
<p>「<a href="https://ufcpp.net/study/csharp/sp2_iterator.html#complied">イテレーターのコンパイル結果</a>」辺りで書いてるんですが、
イテレーターは「中断と再開」をするようなコードが生成されます。</p>
<p>例えば以下のようなコードを書いたとき、</p>
<pre class="source" title="イテレーターの例">
<span class="control">foreach</span> (<span class="reserved">var</span> <span class="variable">x</span> <span class="control">in</span> <span class="method">M</span>())
{
    <span class="type"><span class="static">Console</span></span><span class="operator">.</span><span class="method"><span class="static">WriteLine</span></span>(<span class="variable">x</span>);
}

<span class="type">IEnumerable</span>&lt;<span class="reserved">int</span>&gt; <span class="method">M</span>()
{
    <span class="reserved">var</span> <span class="variable">x</span> <span class="operator">=</span> <span class="number">1</span>;
    <span class="control">yield</span> <span class="control">return</span> <span class="variable">x</span> <span class="operator">*</span> <span class="variable">x</span>;

    <span class="comment">// 式は適当。</span>
    <span class="comment">// ここで重要なのは、y は yield をまたがないということ。</span>
    <span class="reserved">var</span> <span class="variable">y</span> <span class="operator">=</span> <span class="operator">++</span><span class="variable">x</span> <span class="operator">*</span> <span class="variable">x</span>;
    <span class="variable">y</span> <span class="operator">*=</span> <span class="variable">y</span>;

    <span class="control">yield</span> <span class="control">return</span> <span class="variable">y</span>;

    <span class="comment">// 同、z は yield をまたがない。</span>
    <span class="reserved">var</span> <span class="variable">z</span> <span class="operator">=</span> <span class="operator">++</span><span class="variable">x</span>;
    <span class="variable">z</span> <span class="operator">*=</span> (<span class="number">2</span> <span class="operator">*</span> <span class="variable">x</span> <span class="operator">+</span> <span class="number">1</span>);

    <span class="control">yield</span> <span class="control">return</span> <span class="variable">z</span>;
}
</pre>
<p>おおむね、以下のようなクラスが生成されます。
(簡単化のためちょこっとさぼっています。要点のみ。)</p>
<pre class="source" title="上記イテレーターの解釈結果">
<span class="reserved">var</span> <span class="variable">e</span> <span class="operator">=</span> <span class="reserved">new</span> <span class="type">MImpl</span>();
<span class="control">while</span> (<span class="variable">e</span><span class="operator">.</span><span class="method">MoveNext</span>())
{
    <span class="type"><span class="static">Console</span></span><span class="operator">.</span><span class="method"><span class="static">WriteLine</span></span>(<span class="variable">e</span><span class="operator">.</span><span class="property">Current</span>);
}

<span class="reserved">class</span> <span class="type">MImpl</span>
{
    <span class="reserved">private</span> <span class="reserved">int</span> <span class="field">_i</span> <span class="operator">=</span> <span class="number">0</span>;
    <span class="reserved">private</span> <span class="reserved">int</span> <span class="field">_x</span> <span class="operator">=</span> <span class="number">1</span>;

    <span class="reserved">public</span> <span class="reserved">int</span> <span class="property">Current</span> { <span class="reserved">get</span>; <span class="reserved">private</span> <span class="reserved">set</span>; }

    <span class="reserved">public</span> <span class="reserved">bool</span> <span class="method">MoveNext</span>()
    {
        <span class="control">if</span> (<span class="field">_i</span> <span class="operator">==</span> <span class="number">0</span>)
        {
            <span class="property">Current</span> <span class="operator">=</span> <span class="field">_x</span> <span class="operator">*</span> <span class="field">_x</span>;
        }
        <span class="control">else</span> <span class="control">if</span> (<span class="field">_i</span> <span class="operator">==</span> <span class="number">1</span>)
        {
            <span class="reserved">var</span> <span class="variable">y</span> <span class="operator">=</span> <span class="operator">++</span><span class="field">_x</span> <span class="operator">*</span> <span class="field">_x</span>;
            <span class="variable">y</span> <span class="operator">*=</span> <span class="variable">y</span>;
            <span class="property">Current</span> <span class="operator">=</span> <span class="variable">y</span>;
        }
        <span class="control">else</span> <span class="control">if</span> (<span class="field">_i</span> <span class="operator">==</span> <span class="number">2</span>)
        {
            <span class="reserved">var</span> <span class="variable">z</span> <span class="operator">=</span> <span class="operator">++</span><span class="field">_x</span>;
            <span class="variable">z</span> <span class="operator">*=</span> (<span class="number">2</span> <span class="operator">*</span> <span class="field">_x</span> <span class="operator">+</span> <span class="number">1</span>);
            <span class="property">Current</span> <span class="operator">=</span> <span class="variable">z</span>;
        }
        <span class="control">else</span>
        {
            <span class="control">return</span> <span class="reserved">false</span>;
        }

        <span class="field">_i</span><span class="operator">++</span>;
        <span class="control">return</span> <span class="reserved">true</span>;
    }
}
</pre>
<p>ここで重要なのは以下の点。</p>
<ul>
<li><code>yield</code> をまたいで使う変数はフィールドに昇格する</li>
<li>そうでないものはローカル変数のまま</li>
</ul>
<p>つまり、「<code>yield</code> さえまたがなければ、ローカル変数に制限を掛ける必要はない」ということになります。
ここではイテレーターで話しましたが、非同期メソッドもほぼ同様で、
「<code>await</code> さえまたがなければ、ローカル変数に制限を掛ける必要はない」といえたりします。</p>
<p>ただまあ、これはあくまで「原理的には」という話であって、じゃあ、現在の実装がどうなっているかというと…
C# 12 時点では以下のような感じ。</p>
<pre class="source" title="C# 12 時点での、ref/ref struct のイテレーター/非同期メソッド中での挙動">
<span class="reserved">class</span> <span class="type">A</span>
{
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">M</span></span>()
    {
        <span class="type struct">RefStruct</span> <span class="variable">rs</span> <span class="operator">=</span> <span class="reserved">new</span>();

        <span class="reserved">using</span> (<span class="variable">rs</span>) { }
        <span class="control">foreach</span> (<span class="reserved">var</span> <span class="variable">_</span> <span class="control">in</span> <span class="variable">rs</span>) ;

        <span class="reserved">int</span> <span class="variable">x</span> <span class="operator">=</span> <span class="number">1</span>;
        <span class="reserved">ref</span> <span class="reserved">int</span> <span class="variable">r</span> <span class="operator">=</span> <span class="reserved">ref</span> <span class="variable">x</span>;
    }

    <span class="reserved">public</span> <span class="reserved">static</span> <span class="type">IEnumerable</span>&lt;<span class="reserved">object</span><span class="operator">?</span>&gt; <span class="method"><span class="static">MIterator</span></span>()
    {
        <span class="type struct">RefStruct</span> <span class="variable">rs</span> <span class="operator">=</span> <span class="reserved">new</span>();

        <span class="reserved">using</span> (<span class="variable">rs</span>) { }
        <span class="error" title="CS8344"><span class="control">foreach</span></span> (<span class="reserved">var</span> <span class="variable">_</span> <span class="control">in</span> <span class="variable">rs</span>) ; <span class="comment">// ダメ。</span>

        <span class="reserved">int</span> <span class="variable">x</span> <span class="operator">=</span> <span class="number">1</span>;
        <span class="reserved">ref</span> <span class="reserved">int</span> <span class="error" title="CS8176"><span class="variable">r</span></span> <span class="operator">=</span> <span class="reserved">ref</span> <span class="variable">x</span>; <span class="comment">// ダメ。</span>

        <span class="control">yield</span> <span class="control">return</span> <span class="reserved">null</span>;
    }

    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">async</span> <span class="type struct">ValueTask</span> <span class="static"><span class="method">MAsync</span></span>()
    {
        <span class="type struct"><span class="error" title="CS4012">RefStruct</span></span> <span class="variable">rs</span> <span class="operator">=</span> <span class="reserved">new</span>(); <span class="comment">// 非同期メソッドだとこの時点でダメ。</span>

        <span class="reserved">using</span> (<span class="variable"><span class="error" title="CS9104">rs</span></span>) { } <span class="comment">// ダメ。</span>
        <span class="control"><span class="error" title="CS8344">foreach</span></span> (<span class="reserved">var</span> <span class="variable">_</span> <span class="control">in</span> <span class="variable">rs</span>) ; <span class="comment">// ダメ。</span>

        <span class="reserved">int</span> <span class="variable">x</span> <span class="operator">=</span> <span class="number">1</span>;
        <span class="reserved">ref</span> <span class="reserved">int</span> <span class="error" title="CS8177"><span class="variable">r</span></span> <span class="operator">=</span> <span class="reserved">ref</span> <span class="variable">x</span>; <span class="comment">// ダメ。</span>

        <span class="reserved">await</span> <span class="type">Task</span><span class="operator">.</span><span class="static"><span class="method">Yield</span></span>();
    }
}

<span class="reserved">ref</span> <span class="reserved">struct</span> <span class="type struct">RefStruct</span>
{
    <span class="reserved">public</span> <span class="reserved">void</span> <span class="method">Dispose</span>() { }

    <span class="reserved">public</span> <span class="type struct">RefStruct</span> <span class="method">GetEnumerator</span>() <span class="operator">=&gt;</span> <span class="reserved">this</span>;
    <span class="reserved">public</span> <span class="reserved">int</span> <span class="property">Current</span> <span class="operator">=&gt;</span> <span class="number">0</span>;
    <span class="reserved">public</span> <span class="reserved">bool</span> <span class="method">MoveNext</span>() <span class="operator">=&gt;</span> <span class="reserved">false</span>;
}
</pre>
<p>どれも、「ref struct のローカル変数が認められるのであれば書けてもいいはずのコード」になります。
ところが、大丈夫なものとコンパイル エラーになるものがまちまち。</p>
<h2>ref/ref struct 変数を非同期メソッド中で使えるように</h2>
<p>まあ既知の問題ではあったんですが。
これまで、需要がそこまでないからか、ずっと放置されていました。
ところが、今回「<code>Lock</code> クラスに対する <code>lock</code> ステートメント」問題が出たからか、急に対処することになったみたいです。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/pull/7994">Add proposal for &quot;ref and unsafe in iterators and async&quot; #7994</a></li>
</ul>
<p>先ほどの、以下のようなコード、すべて「<code>yield</code>/<code>await</code> さえまたがなければ認める」ということになりそうです。</p>
<pre class="source" title="C# 12 時点での、ref/ref struct のイテレーター/非同期メソッド中での挙動">
<span class="type struct">RefStruct</span> <span class="variable">rs</span> <span class="operator">=</span> <span class="reserved">new</span>();

<span class="reserved">using</span> (<span class="variable">rs</span>) { }
<span class="control">foreach</span> (<span class="reserved">var</span> <span class="variable">_</span> <span class="control">in</span> <span class="variable">rs</span>) ;

<span class="reserved">int</span> <span class="variable">x</span> <span class="operator">=</span> <span class="number">1</span>;
<span class="reserved">ref</span> <span class="reserved">int</span> <span class="variable">r</span> <span class="operator">=</span> <span class="reserved">ref</span> <span class="variable">x</span>;
</pre>
<ul>
<li>ref ローカル変数</li>
<li>
ref struct のローカル変数
<ul>
<li>ref struct に対する <code>using</code> ステートメント</li>
<li>ref struct に対する <code>foreach</code> ステートメント</li>
</ul>
</li>
</ul>
<p>付随して、同じく「<code>yield</code>/<code>await</code> さえまたがなければ認める」という条件で、
<a href="https://ufcpp.net/study/csharp/sp_unsafe.html#unsafe"><code>unsafe</code> ブロック</a>も認めるそうです。</p>
<h3>lock 中の yield</h3>
<p>逆に、「これまで書けちゃっていたけども、実はまずかった」というものに警告を出そうという話もあります。
それが「<code>lock</code> ステートメント中の <code>yield</code>」です。</p>
<pre class="source" title="まずそうなコード: lock 中の yield">
<span class="reserved">class</span> <span class="type">MultiThreadCode</span>
{
    <span class="reserved">private</span> <span class="reserved">static</span> <span class="reserved">readonly</span> <span class="reserved">object</span> <span class="static"><span class="field">_syncObj</span></span> <span class="operator">=</span> <span class="reserved">new</span>();

    <span class="reserved">public</span> <span class="reserved">static</span> <span class="type">IEnumerable</span>&lt;<span class="reserved">object</span><span class="operator">?</span>&gt; <span class="method"><span class="static">MIterator</span></span>()
    {
        <span class="reserved">lock</span> (<span class="field"><span class="static">_syncObj</span></span>)
        {
            <span class="comment">// これが書けちゃう。使い方によってはまずい。</span>
            <span class="control">yield</span> <span class="control">return</span> <span class="reserved">null</span>;
        }
    }

    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">async</span> <span class="type struct">ValueTask</span> <span class="method"><span class="static">MAsync</span></span>()
    {
        <span class="reserved">lock</span> (<span class="field"><span class="static">_syncObj</span></span>)
        {
            <span class="comment">// 非同期メソッドの場合、コンパイル エラーになるので大丈夫。</span>
            <span class="error" title="CS1996"><span class="reserved">await</span> <span class="type">Task</span><span class="operator">.</span><span class="method"><span class="static">Yield</span></span>()</span>;
        }
    }
}
</pre>
<p>.NET の実装では、
「ロックの開始と終了(内部的には <code>Monitor.Enter</code> と <code>Monitor.Exit</code>)は同じスレッドでやらないといけない」という制限がありまして。
非同期メソッドの方はわかりやすく「<code>await</code> をまたぐと別スレッド」感があるのでコンパイルの時点でエラーにしています。</p>
<p>で、イテレーターの方も使い方によっては「<code>yield</code> をまたぐと別スレッドになることがある」という意味では危険で、
例えば、以下のようなコードを書くと実行時に <code>SynchronizationLockException</code> 例外が出ます。</p>
<pre class="source" title="lock 中 yield で例外を起こす例">
<span class="reserved">object</span> <span class="variable">syncObj</span> <span class="operator">=</span> <span class="reserved">new</span>();

<span class="type">IEnumerable</span>&lt;<span class="reserved">object</span><span class="operator">?</span>&gt; <span class="method">M</span>()
{
    <span class="reserved">lock</span> (<span class="variable">syncObj</span>)
    {
        <span class="comment">// これが書けちゃう。使い方によってはまずい。</span>
        <span class="control">yield</span> <span class="control">return</span> <span class="reserved">null</span>;
    }
}

<span class="control">foreach</span> (<span class="reserved">var</span> <span class="variable">_</span> <span class="control">in</span> <span class="method">M</span>())
{
    <span class="comment">// M 内に非同期コードがなくても、利用側が非同期だった時点でアウト。</span>
    <span class="reserved">await</span> <span class="type">Task</span><span class="operator">.</span><span class="method"><span class="static">Yield</span></span>();
}
</pre>
<p>ということで、この「<code>lock</code> 中での <code>yield</code>」も警告を足すことになりそうです。
(いきなりエラーにすると破壊的変更になるのでとりあえず警告。
何バージョンかかけてエラーに変更する可能性はあり。)</p>
<p>(※ 「スレッドをまたいだ <code>lock</code> を書けるようにする」みたいなことはしません。)</p>
 ]]></description>
				<pubDate>Thu, 04 Apr 2024 23:30:21 +0900</pubDate>
			</item>
			<item>
				<title>Lock クラス</title>
				<link>http://ufcpp.net/blog/2024/4/lock-class/</link>
				<description><![CDATA[ <p>今日は、
.NET 9 で <a href="https://learn.microsoft.com/ja-jp/dotnet/api/system.threading.lock"><code>Lock</code> クラス</a>というのが入る予定で、
それに伴って C# コンパイラーにも対応が必要そうという話。</p>
<p>一応雰囲気的には C# 13 に入りそう。</p>
<h2>任意のオブジェクトを lock</h2>
<p>C# は<strong>なぜか</strong>任意のオブジェクト インスタンスを使って排他制御ができます。
ロックを掛けるために以下のようなコードを書くことになります。</p>
<pre class="source" title="ロック用のオブジェクトをわざわざ用意">
<span class="reserved">class</span> <span class="type">MultiThreadCode</span>
{
    <span class="reserved">private</span> <span class="reserved">readonly</span> <span class="reserved">object</span> <span class="field">_syncObj</span> <span class="operator">=</span> <span class="reserved">new</span> <span class="reserved">object</span>();

    <span class="reserved">public</span> <span class="reserved">void</span> <span class="method">Run</span>()
    {
        <span class="reserved">lock</span> (<span class="field">_syncObj</span>)
        {
            <span class="comment">// いろんなスレッドから同時に呼ばれるコード。</span>
        }
    }
}
</pre>
<p>Java からの習慣(= 1995年頃の発想)ですかね。
Java の <code>synchronized</code> ブロックも同じ仕様のはず。</p>
<p>本来の思想としては「<code>lock()</code> の <code>()</code> 内には同時に操作されるとまずいリソースを書く」という感じのはず。
そういわれると、<code>lock (任意のオブジェクト)</code> に正当性があるように感じます。</p>
<pre class="source" title="lock (任意オブジェクト) の本来の意図">
<span class="reserved">class</span> <span class="type">Resource</span>;

<span class="reserved">class</span> <span class="type">MultiThreadCode</span>
{
    <span class="reserved">private</span> <span class="reserved">readonly</span> <span class="type">Resource</span> <span class="field">_someResource</span> <span class="operator">=</span> <span class="reserved">new</span>();

    <span class="reserved">public</span> <span class="reserved">void</span> <span class="method">Run</span>()
    {
        <span class="reserved">lock</span> (<span class="field">_someResource</span>)
        {
            <span class="comment">// _someResource に対する操作をする。</span>
            <span class="comment">// _someResource を同時に操作されると困るんだから、「_someResource を lock」。</span>
        }
    }
}
</pre>
<p>ですがまあ、実際のところこんなにきれいに <code>lock (x) { x に対する操作 }</code> になることはなく、
大体は先ほどのように「<code>lock</code> のためだけに1個追加で <code>object _syncObj</code> みたいなフィールドを用意」みたいなことになります。</p>
<p>これがめんどくさく…
とはいえ、面倒だからといって以下のようなことは<strong>してはいけない</strong>とされています。</p>
<pre class="source" title="ダメ！絶対！">
<span class="reserved">class</span> <span class="type">MultiThreadCode</span>
{
    <span class="reserved">public</span> <span class="reserved">void</span> <span class="method">Run</span>()
    {
        <span class="comment">// ✖</span>
        <span class="comment">// 任意のオブジェクトでロックできるということは、this でも行ける！</span>
        <span class="reserved">lock</span> (<span class="reserved">this</span>)
        {
            <span class="comment">// いろんなスレッドから同時に呼ばれるコード。</span>
        }
    }

    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">StaticRun</span></span>()
    {
        <span class="comment">// ✖</span>
        <span class="comment">// 静的メソッド内では this がない…</span>
        <span class="comment">// そうだ、Type 型もオブジェクトじゃん！</span>
        <span class="reserved">lock</span> (<span class="reserved">typeof</span>(<span class="type">MultiThreadCode</span>))
        {
            <span class="comment">// いろんなスレッドから同時に呼ばれるコード。</span>
        }
    }
}
</pre>
<p>「外に漏れるインスタンスでロックを取ってはいけない」というお作法があるからです。
以下のようなコードを書かれる可能性があって困ります。</p>
<pre class="source" title="ダメな lock の例">
<span class="reserved">var</span> <span class="variable">x</span> <span class="operator">=</span> <span class="reserved">new</span> <span class="type">MultiThreadCode</span>();

<span class="comment">// ここの lock と、MultiThreadCode.Run 内の lock (this) が同じオブジェクトをロックする。</span>
<span class="comment">// 意図しない挙動のはず。</span>
<span class="reserved">lock</span> (<span class="variable">x</span>)
{
}

<span class="reserved">class</span> <span class="type">MultiThreadCode</span>
{
    <span class="reserved">public</span> <span class="reserved">void</span> <span class="method">Run</span>()
    {
        <span class="reserved">lock</span> (<span class="reserved">this</span>)
        {
            <span class="comment">// いろんなスレッドから同時に呼ばれるコード。</span>
        }
    }
}
</pre>
<p>さらにいうと、外に漏れてダメなら以下のようなコードもダメになると。</p>
<pre class="source" title="これもダメ">
<span class="reserved">var</span> <span class="variable">x</span> <span class="operator">=</span> <span class="reserved">new</span> <span class="type">MultiThreadCode</span>();

<span class="comment">// ここの lock と、MultiThreadCode.Run 内の lock (_items) が同じオブジェクトをロックする。</span>
<span class="reserved">lock</span> (<span class="variable">x</span><span class="operator">.</span><span class="property">Items</span>)
{
}

<span class="reserved">class</span> <span class="type">MultiThreadCode</span>
{
    <span class="comment">// private だから一見外に漏れてない。</span>
    <span class="reserved">private</span> <span class="reserved">readonly</span> <span class="type">List</span>&lt;<span class="reserved">int</span>&gt; <span class="field">_items</span> <span class="operator">=</span> [];

    <span class="reserved">public</span> <span class="reserved">void</span> <span class="method">Run</span>()
    {
        <span class="reserved">lock</span> (<span class="field">_items</span>)
        {
            <span class="comment">// _items に Add/Remove とかしたり。</span>
        }
    }

    <span class="comment">// List としては公開していないものの、</span>
    <span class="comment">// インスタンス自体は _items そのままなので…</span>
    <span class="reserved">public</span> <span class="type">IEnumerable</span>&lt;<span class="reserved">int</span>&gt; <span class="property">Items</span> <span class="operator">=&gt;</span> <span class="field">_items</span>;
}
</pre>
<p>なのでまあ、元の話の戻りますが、結局は「<code>_items</code> とは別に
<code>object _syncObj = new();</code> を用意」みたいなことになります。</p>
<h2>.NET のオブジェクト ヘッダー</h2>
<p>「任意のオブジェクトに対して <code>lock</code> を掛けれるという仕様は意外とオーバーヘッドが大きい」という話題があったりします。
なので、「ロック専用のクラスがあった方がいい」という話も。</p>
<ul>
<li><a href="https://github.com/dotnet/runtime/issues/34812">Add first class System.Threading.Lock type</a></li>
</ul>
<p>ここにこんな説明があります:</p>
<blockquote>
<p>Locking on any class has overhead from the dual role of the syncblock as both lock field and hashcode et al.</p>
<p>(任意のクラスに対するロック操作は、ロック用の値とハッシュ値とか、syncblock に複数の役割を持たせていることによるオーバーヘッドを持つ。)</p>
</blockquote>
<p>syncblock が何かという話は以下の英語の記事がわかりやすそう。</p>
<ul>
<li><a href="https://mycodingplace.wordpress.com/2018/01/10/object-header-get-complicated/">Object header get complicated</a></li>
</ul>
<p>ここの図を見ての通り、27ビット目の値によって、下位ビットをハッシュ値として使うか、ロック用に使うか分岐させています。</p>
<p>ところがまあ、<a href="https://github.com/dotnet/runtime/issues/34800">これのせいで分岐予測をミスりまくって、結構ペナルティ</a>になるみたいです。
言われてみればそりゃそう。
<code>GetHashCode</code> と <code>lock</code> だったら <code>GetHashCode</code> の方が圧倒的に利用頻度高いでしょうから。
いざ <code>lock</code> しようとすると分岐予測当たらないのもしょうがなく。</p>
<p>(あと、<code>lock</code> 中のオブジェクトに対して override してない <code>object.GetHashCode</code> を呼ぶと遅くなります。)</p>
<p>で、ここで、前節の「どうせロック専用のインスタンスを作ることが多い」話と合わせると、
「だったらロック専用の <code>Lock</code> クラスを作って <code>private readonly Lock _syncObj = new();</code> しようよ」ということになったりします。</p>
<h2>System.Threading.Lock クラス</h2>
<p>ということで、 .NET 9 では <code>Lock</code> クラス(<code>System.Threading</code> 名前空間)を追加するみたいです。
現状 (.NET 9 Preview 1 とか Preview 2 時点)では、
プレビュー扱いで <code>RequiresPreviewFeatures</code> 属性が付いていますが、
一応今でも実装が入っています。</p>
<p>C# の <code>lock</code> ステートメントをどうするかはいったん置いておいて(後述)、
以下のような使い方を想定しているクラスです。</p>
<pre class="source" title="Lock クラス導入">
<span class="reserved">using</span> System<span class="operator">.</span>Runtime<span class="operator">.</span>Versioning;

<span class="comment">// 今のペースなら、.NET 9 正式リリースまでには外れる気はする。</span>
[<span class="reserved">module</span>: <span class="type">RequiresPreviewFeatures</span>]

<span class="reserved">class</span> <span class="type">MultiThreadCode</span>
{
    <span class="reserved">private</span> <span class="reserved">readonly</span> <span class="type">Lock</span> <span class="field">_syncObj</span> <span class="operator">=</span> <span class="reserved">new</span>();

    <span class="reserved">public</span> <span class="reserved">void</span> <span class="method">Run</span>()
    {
        <span class="comment">// C# コンパイラーに手を入れないとしたらこんな使い方に。</span>
        <span class="comment">// lock じゃなくて using。</span>
        <span class="reserved">using</span> (<span class="field">_syncObj</span><span class="operator">.</span><span class="method">EnterScope</span>())
        {
            <span class="comment">// いろんなスレッドから同時に呼ばれるコード。</span>
        }
    }
}
</pre>
<p><code>Lock</code> クラスが何をやっているかというと、おおむね「<code>lock</code> が内部で使っている C++ コード(<a href="https://github.com/dotnet/runtime/blob/e5cf6905f6065b45f32f8780fe9645969e836ecf/src/coreclr/vm/syncblk.h#L157"><code>AwareLock</code></a>)を <a href="https://github.com/dotnet/runtime/pull/87672">C# に移植</a>」です。
本当に、「オブジェクト ヘッダーの syncblock を使うのが高コスト」を避けるためのクラスという感じです。</p>
<h2>lock ステートメントで Lock インスタンス</h2>
<p>ここで問題になるのが、じゃあ、<code>Lock</code> インスタンスに対して <code>lock</code> ステートメントを使うとどうなるの？というお話。
「<code>Lock</code> の時には <code>lock (x)</code> じゃなくて <code>using (x.EnterScope())</code> にしようね」とか言われても割と困るかと思います。
知らなきゃ確実に <code>lock (x)</code> と書くでしょうし、
知ってたって <code>lock (x)</code> をやらかす自信があります。</p>
<p>なので、C# 言語のレベルでも何らかの対処は必要だろうという話になります。
(おそらくその辺りが <code>RequiresPreviewFeatures</code> 属性付きになっている理由。)</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/blob/main/proposals/lock-object.md"><code>Lock</code> object</a></li>
</ul>
<p>検討段階では「<code>lock (x)</code> すると警告を出すみたいなのだけでもいいかもしれない」なんて話もありましたが、
まあ、「<code>lock (x)</code> と書いたらコンパイラーが <code>using (x.EnterScope())</code> に置き換える」路線で行くことになりました。</p>
<p>この実装、 Visual Studio 17.10.0 Preview 2.0 (<a href="https://github.com/ufcpp-live/UfcppLiveAgenda/issues/88">3週間くらい前</a>)の時点で入ってるみたいです。
以下のコードを書いて、ILSpy とかでコンパイル結果の中身を覗くと <code>using (_syncObj.EnterScope())</code> に置き換わっています。</p>
<pre class="source" title="Lock インスタンスに対する lock ステートメント">
<span class="reserved">class</span> <span class="type">MultiThreadCode</span>
{
    <span class="reserved">private</span> <span class="reserved">readonly</span> <span class="type">Lock</span> <span class="field">_syncObj</span> <span class="operator">=</span> <span class="reserved">new</span>();

    <span class="reserved">public</span> <span class="reserved">void</span> <span class="method">Run</span>()
    {
        <span class="comment">// C# コンパイラーが特殊対応することになったので、lock で OK に。</span>
        <span class="reserved">lock</span> (<span class="field">_syncObj</span>)
        {
            <span class="comment">// いろんなスレッドから同時に呼ばれるコード。</span>
        }
    }
}
</pre>
<p>ちなみに、現状は <code>Lock</code> クラス専用です。
珍しくパターン ベースでなく、<code>Lock</code> でないと認識せず。
まあ、需要がないんでしょうね。</p>
<pre class="source" title="Lock 専用なので、自作はできず">
<span class="comment">// これは現状、既存の lock (Monitor.TryEnter を使ったコード)になる。 </span>
<span class="reserved">lock</span> (<span class="reserved">new</span> <span class="type">MyLock</span>())
{
}

<span class="comment">// System.Threading.Lock と同じパターンのメソッド持ちの自作クラス。</span>
<span class="reserved">class</span> <span class="type">MyLock</span>
{
    <span class="reserved">public</span> <span class="type struct">Scope</span> <span class="method">EnterScope</span>() <span class="operator">=&gt;</span> <span class="reserved">default</span>;

    <span class="reserved">public</span> <span class="reserved">ref</span> <span class="reserved">struct</span> <span class="type struct">Scope</span>
    {
        <span class="reserved">public</span> <span class="reserved">void</span> <span class="method">Dispose</span>() { }
    }
}
</pre> ]]></description>
				<pubDate>Thu, 04 Apr 2024 00:22:28 +0900</pubDate>
			</item>
			<item>
				<title>Extensions (拡張型)</title>
				<link>http://ufcpp.net/blog/2024/3/extensions/</link>
				<description><![CDATA[ <p>C# 3.0 から<a href="https://ufcpp.net/study/csharp/sp3_extension.html">拡張メソッド</a>が使えるわけですが、
もうちょっといろんな「拡張」をしたいという話が前々からあります。
例えば以下のような要求。</p>
<ul>
<li>既存の型に静的メンバーも足したい</li>
<li>プロパティや演算子も足したい</li>
<li>インターフェイスの後付けもしたい</li>
</ul>
<p>今では Extensions とか呼ばれていまして、以下の issue でトラッキング中。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/discussions/164">Exploration: Shapes and Extensions #164</a></li>
</ul>
<p>ここからさかのぼって、かつては Extension everything とか呼ばれていたり、
個別に「インターフェイスを実装したい」「演算子を拡張したい」など個別の issue がありました。</p>
<ul>
<li>
<a href="https://github.com/dotnet/roslyn/issues/11159">Extension Everything</a>
<ul>
<li><a href="https://github.com/dotnet/roslyn/issues/3357">Extension classes with Interfaces</a></li>
<li><a href="https://github.com/dotnet/roslyn/issues/4945">Extension operators</a></li>
</ul>
</li>
</ul>
<p>2015年(<a href="https://github.com/dotnet/roslyn">Roslyn</a> が GitHub での公開に切り替わった年)にはすでにそんな話が出ています。</p>
<p>結構大きな機能なのでしり込みしていたみたいですが、
去年くらいから Working Group (この機能の追加を推進するメンバーを割り当てて、定期的にミーティング)を設けて作業を始めました。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/tree/3cd77d5664281f6df4785a35d4b778c88ec3aa98/meetings/working-groups/roles">Extensions がらみの議事録</a></li>
</ul>
<p>うちのブログでも去年、1度取り上げています。</p>
<ul>
<li><a href="https://ufcpp.net/blog/2023/3/extensions/">【C# 12 候補】 Extensions</a></li>
</ul>
<p>もう9年も経ってしまい、C# 12 でも入らなかったわけですが、
ついに今年、C# 13 には一部入りそう(インターフェイスの後付けだけは無理そう)な雰囲気になっています。</p>
<p>最近の話題のうちいくつかを取り上げると、以下のような話が出ています。</p>
<ul>
<li>
<a href="https://github.com/dotnet/csharplang/blob/3cd77d5664281f6df4785a35d4b778c88ec3aa98/meetings/working-groups/roles/extensions-2024-01-25.md#scope-and-priorities-for-c13">段階的に実装していく</a>
<ul>
<li>静的メンバー → インスタンス メンバー → 継承のサポート (C# 13 でやれそうなのはここまで) → インターフェイスの後付け</li>
</ul>
</li>
<li>
<a href="https://github.com/dotnet/csharplang/issues/7771">普通の構造体でラッパー型を作って、利用時に Unsafe.As で変換してメンバーを呼ぶ</a>
<ul>
<li>型消去な実装</li>
</ul>
</li>
<li><a href="https://github.com/dotnet/csharplang/blob/7a3990a2bec382871de3a0615746d274ae924b6b/proposals/extension-interfaces.md">インターフェイス実装は大変そう</a></li>
<li>
<a href="https://github.com/dotnet/csharplang/blob/main/meetings/2024/LDM-2024-02-28.md">メンバーのルックアップ</a>
<ul>
<li>クラスの継承時の挙動に準ずる</li>
<li>旧拡張メソッドと新 Extensions は優先度をつけない(どちらにも同名メソッドがあった場合、コンパイル エラーにする)案が今のところ優勢</li>
</ul>
</li>
</ul>
<h2>extension 構文</h2>
<p>ということで、改めて Extensions の話を。
今、以下のような構文を足そうとしています。</p>
<pre class="source" title="extension 構文">
<span class="comment">// 拡張の構文例。</span>
<span class="reserved">implicit</span> <span class="reserved">extension</span> <span class="type">SomeExtension</span> <span class="reserved">for</span> <span class="type">SomeClass</span> : <span class="type">IEquatable</span>&lt;<span class="type">SomeExtension</span>&gt;
{
    <span class="comment">// 追加したいメンバーを書く。</span>

    <span class="comment">// 1. 静的メンバーも書ける。</span>
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">int</span> <span class="property"><span class="static">Y</span></span> <span class="operator">=&gt;</span> <span class="property"><span class="static">X</span></span> <span class="operator">*</span> <span class="property"><span class="static">X</span></span>;

    <span class="comment">// 2. メソッド以外も書ける。</span>
    <span class="reserved">public</span> <span class="reserved">int</span> <span class="property">Property</span>
    {
        <span class="reserved">get</span> <span class="operator">=&gt;</span> <span class="method">GetValue</span>();
        <span class="reserved">set</span> <span class="operator">=&gt;</span> <span class="method">SetValue</span>(<span class="reserved">value</span>);
    }

    <span class="reserved">public</span> <span class="reserved">int</span> <span class="reserved">this</span>[<span class="reserved">int</span> <span class="variable local">index</span>] <span class="operator">=&gt;</span> <span class="method">GetValue</span>(<span class="variable local">index</span>);

    <span class="comment">// 3. インターフェイスの実装を持てる。</span>
    <span class="reserved">public</span> <span class="reserved">bool</span> <span class="method">Equals</span>(<span class="type">SomeExtension</span><span class="operator">?</span> <span class="variable local">other</span>) <span class="operator">=&gt;</span> <span class="property">Property</span> <span class="operator">==</span> <span class="variable local">other</span><span class="operator">?</span><span class="operator">.</span><span class="property">Property</span>;
}

<span class="comment">// 拡張の対象の例。</span>
<span class="reserved">class</span> <span class="type">SomeClass</span>
{
    <span class="comment">// (中身は適当。)</span>
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">int</span> <span class="field"><span class="static">X</span></span> <span class="operator">=</span> <span class="number">123</span>;

    <span class="reserved">private</span> <span class="reserved">int</span> <span class="field">_value</span>;

    <span class="reserved">public</span> <span class="reserved">int</span> <span class="method">GetValue</span>() <span class="operator">=&gt;</span> <span class="field">_value</span>;
    <span class="reserved">public</span> <span class="reserved">void</span> <span class="method">SetValue</span>(<span class="reserved">int</span> <span class="variable local">value</span>) <span class="operator">=&gt;</span> <span class="field">_value</span> <span class="operator">=</span> <span class="variable local">value</span>;
    <span class="reserved">public</span> <span class="reserved">int</span> <span class="method">GetValue</span>(<span class="reserved">int</span> <span class="variable local">index</span>) <span class="operator">=&gt;</span> <span class="field">_value</span> <span class="operator">*</span> <span class="variable local">index</span>;
}
</pre>
<p>ちなみに、「インターフェイスの実装を持つ」には少し難題があって、
C# 13 時点では入らない可能性がかなり高いです。</p>
<h2>普通の構造体 + Unsafe.As</h2>
<p>拡張はラッパー構造体を使った実装になりそうです。
一時期は以下のような ref struct を使った実装になりそうだったんですが、
この案は結局没になりました。</p>
<pre class="source" title="ref struct 案">
<span class="reserved">var</span> <span class="variable">value</span> <span class="operator">=</span> <span class="reserved">new</span> <span class="type struct">SomeStruct</span>();
<span class="reserved">var</span> <span class="variable">extension</span> <span class="operator">=</span> <span class="reserved">new</span> <span class="type struct">SomeExtension</span>(<span class="reserved">ref</span> <span class="variable">value</span>);

<span class="comment">// 拡張プロパティを呼び出す。</span>
<span class="variable">extension</span><span class="operator">.</span><span class="property">Property</span> <span class="operator">=</span> <span class="number">123</span>;

<span class="comment">// ちゃんと元インスタンスに値が反映。</span>
<span class="static"><span class="type">Console</span></span><span class="operator">.</span><span class="static"><span class="method">WriteLine</span></span>(<span class="variable">value</span><span class="operator">.</span><span class="method">GetValue</span>());

<span class="reserved">ref</span> <span class="reserved">struct</span> <span class="type struct">SomeExtension</span>(<span class="reserved">ref</span> <span class="type struct">SomeStruct</span> <span class="variable local">@this</span>)
{
    <span class="reserved">ref</span> <span class="type struct">SomeStruct</span> <span class="field">@this</span> <span class="operator">=</span> <span class="reserved">ref</span> <span class="variable local">@this</span>;

    <span class="reserved">public</span> <span class="reserved">int</span> <span class="property">Property</span>
    {
        <span class="reserved">get</span> <span class="operator">=&gt;</span> <span class="field">@this</span><span class="operator">.</span><span class="method">GetValue</span>(); <span class="comment">// ref で持ってるので、引数でもらった構造体に書き換えが反映される。</span>
        <span class="reserved">set</span> <span class="operator">=&gt;</span> <span class="field">@this</span><span class="operator">.</span><span class="method">SetValue</span>(<span class="reserved">value</span>);
    }
}

<span class="comment">// デモ用に構造体に変更。</span>
<span class="reserved">struct</span> <span class="type struct">SomeStruct</span>
{
    <span class="reserved">private</span> <span class="reserved">int</span> <span class="field">_value</span>;

    <span class="reserved">public</span> <span class="reserved">int</span> <span class="method">GetValue</span>() <span class="operator">=&gt;</span> <span class="field">_value</span>;
    <span class="reserved">public</span> <span class="reserved">void</span> <span class="method">SetValue</span>(<span class="reserved">int</span> <span class="variable local">value</span>) <span class="operator">=&gt;</span> <span class="field">_value</span> <span class="operator">=</span> <span class="variable local">value</span>;
    <span class="reserved">public</span> <span class="reserved">int</span> <span class="method">GetValue</span>(<span class="reserved">int</span> <span class="variable local">index</span>) <span class="operator">=&gt;</span> <span class="field">_value</span> <span class="operator">*</span> <span class="variable local">index</span>;
}
</pre>
<p>この案に変わって、普通の構造体 + Unsafe.As を使う路線で考えているそうです。</p>
<pre class="source" title="Unsafe.As 案">
<span class="reserved">using</span> System<span class="operator">.</span>Runtime<span class="operator">.</span>CompilerServices;

<span class="reserved">var</span> <span class="variable">value</span> <span class="operator">=</span> <span class="reserved">new</span> <span class="type struct">SomeStruct</span>();

<span class="comment">// Unsafe.As を使って、value 値が入っているの場所を無理やり SomeExtension で解釈。</span>
<span class="reserved">ref</span> <span class="reserved">var</span> <span class="variable">extension</span> <span class="operator">=</span> <span class="reserved">ref</span> <span class="type"><span class="static">Unsafe</span></span><span class="operator">.</span><span class="static"><span class="method">As</span></span>&lt;<span class="type struct">SomeStruct</span>, <span class="type struct">SomeExtension</span>&gt;(<span class="reserved">ref</span> <span class="variable">value</span>);

<span class="comment">// 拡張プロパティを呼び出す。</span>
<span class="variable">extension</span><span class="operator">.</span><span class="property">Property</span> <span class="operator">=</span> <span class="number">123</span>;

<span class="comment">// extension の参照先が value なので、ちゃんと value が書き変わる。</span>
<span class="type"><span class="static">Console</span></span><span class="operator">.</span><span class="method"><span class="static">WriteLine</span></span>(<span class="variable">value</span><span class="operator">.</span><span class="method">GetValue</span>());

<span class="comment">// 普通の構造体。</span>
<span class="reserved">struct</span> <span class="type struct">SomeExtension</span>
{
    <span class="reserved">private</span> <span class="type struct">SomeStruct</span> <span class="field">@this</span>;

    <span class="reserved">public</span> <span class="reserved">int</span> <span class="property">Property</span>
    {
        <span class="reserved">get</span> <span class="operator">=&gt;</span> <span class="field">@this</span><span class="operator">.</span><span class="method">GetValue</span>();
        <span class="reserved">set</span> <span class="operator">=&gt;</span> <span class="field">@this</span><span class="operator">.</span><span class="method">SetValue</span>(<span class="reserved">value</span>);
    }
}

<span class="comment">// SomeStruct は先ほどと同じ。</span>
</pre>
<h2>型消去</h2>
<p>Extensions は普通の型と同じように使えたりします。
(特に、<code>explicit</code> を付けた Extensions はむしろ「型を明示しないと使えない」状態になります。)
なのでこれを拡張型(extension types)と呼んだりもします。</p>
<p>で、前節の通り Extensions のコンパイル結果はラッパー構造体だったりするわけですが、
このラッパー構造体への変換(Unsafe.As)はあくまでメンバー参照のタイミングで行われます。
メソッドの引数などに拡張型を書くと、実際には「元の型 + 属性」(いわゆる「型消去」方式)になる予定です。
例えば、以下のようなメソッドを書いたとして、</p>
<pre class="source" title="拡張型を引数に書く例">
<span class="reserved">static</span> <span class="reserved">int</span> <span class="static"><span class="method">Sum</span></span>(<span class="type struct">SomeExtension</span> <span class="variable local">a</span>, <span class="type">List</span>&lt;<span class="type struct">SomeExtension</span>&gt; <span class="variable local">b</span>)
{
    <span class="reserved">var</span> <span class="variable">sum</span> <span class="operator">=</span> <span class="variable local">a</span><span class="operator">.</span><span class="property">Property</span>;
    <span class="control">foreach</span> (<span class="reserved">var</span> <span class="variable">x</span> <span class="control">in</span> <span class="variable local">b</span>) <span class="variable">sum</span> <span class="operator">+=</span> <span class="variable">x</span><span class="operator">.</span><span class="property">Property</span>;
    <span class="control">return</span> <span class="variable">sum</span>;
}
</pre>
<p>以下のような類のコードに置き換わる予定です。</p>
<pre class="source" title="拡張型を引数に書く例の展開結果">
<span class="reserved">static</span> <span class="reserved">int</span> <span class="static"><span class="method">Sum</span></span>(
    <span class="comment">// SomeExtension は属性の中にしか残らない。</span>
    <span class="comment">// 元の、 SomeStruct に置き換わる。</span>
    [<span class="type">Extension</span>(<span class="reserved">typeof</span>(<span class="type struct">SomeExtension</span>))] <span class="type struct">SomeStruct</span> <span class="variable local">a</span>,
    [<span class="type">Extension</span>(<span class="reserved">typeof</span>(<span class="type struct">SomeExtension</span>))] <span class="type">List</span>&lt;<span class="type struct">SomeStruct</span>&gt; <span class="variable local">b</span>)
{
    <span class="comment">// メンバーアクセスするところで Unsafe.As</span>
    <span class="reserved">var</span> <span class="variable">sum</span> <span class="operator">=</span> <span class="type"><span class="static">Unsafe</span></span><span class="operator">.</span><span class="method"><span class="static">As</span></span>&lt;<span class="type struct">SomeStruct</span>, <span class="type struct">SomeExtension</span>&gt;(<span class="reserved">ref</span> <span class="variable local">a</span>)<span class="operator">.</span><span class="property">Property</span>;
    <span class="control">foreach</span> (<span class="reserved">var</span> <span class="variable">x</span> <span class="control">in</span> <span class="variable local">b</span>) <span class="variable">sum</span> <span class="operator">+=</span> <span class="static"><span class="type">Unsafe</span></span><span class="operator">.</span><span class="method"><span class="static">As</span></span>&lt;<span class="type struct">SomeStruct</span>, <span class="type struct">SomeExtension</span>&gt;(<span class="reserved">ref</span> <span class="static"><span class="type">Unsafe</span></span><span class="operator">.</span><span class="static"><span class="method">AsRef</span></span>(<span class="reserved">in</span> <span class="variable">x</span>))<span class="operator">.</span><span class="property">Property</span>;
    <span class="control">return</span> <span class="variable">sum</span>;
}
</pre>
<p><a href="https://ufcpp.net/study/csharp/sp4_variance.html">変性</a>を持っていない <code>List&lt;T&gt;</code> で、
<code>List&lt;SomeStruct&gt;</code> を <code>List&lt;SomeExtension&gt;</code> に変換する手段は通常全くありません。
型消去で <code>List&lt;SomeExtension&gt;</code> が <code>List&lt;SomeStruct&gt;</code> に置き換わることで、
<code>List&lt;SomeStruct&gt;</code> 型の変数を <code>List&lt;SomeExtension&gt;</code> 型の引数に渡せるようになっています。</p>
<h2>メンバーのルックアップ(継承)</h2>
<p>拡張型は元となる型との間には、クラスの継承関係と似た関係が成り立ちます。
なので、メンバーのルックアップのルールも「クラスの継承に準ずる」で行きたいそうです。
例えば、派生クラスから基底クラスのメンバーを何の修飾もなしで(<code>this.</code> とか <code>base.</code> が必須ではなく)参照できるように、
拡張型から元となる型のメンバーも修飾なしで参照できます。</p>
<p>おさらい的に、「継承があるときのルックアップ」の例をいくつか紹介しておきます。
(拡張型中で元となる型と同名のメンバーを書くとこれに準ずることになると思われます。)</p>
<p>近い側優先:</p>
<pre class="source" title="基底クラスと同名のメンバー参照">
<span class="reserved">class</span> <span class="type">Base</span>
{
    <span class="reserved">public</span> <span class="reserved">void</span> <span class="method">M</span>(<span class="reserved">int</span> <span class="variable local">x</span>) { }
}

<span class="reserved">class</span> <span class="type">Derived</span> : <span class="type">Base</span>
{
    <span class="reserved">public</span> <span class="reserved">new</span> <span class="reserved">void</span> <span class="method">M</span>(<span class="reserved">int</span> <span class="variable local">x</span>) { }

    <span class="reserved">public</span> <span class="reserved">void</span> <span class="method">M</span>()
    {
        <span class="comment">// 近い側優先なので、Derived.M が呼ばれる。</span>
        <span class="method">M</span>(<span class="number">1</span>);
    }
}
</pre>
<p>もうちょっとわかりにくい例:</p>
<pre class="source" title="基底クラスと同名で、引数の型が違うメンバー参照">
<span class="reserved">class</span> <span class="type">Base</span>
{
    <span class="reserved">public</span> <span class="reserved">void</span> <span class="method">M</span>(<span class="reserved">int</span> <span class="variable local">x</span>) { }
}

<span class="reserved">class</span> <span class="type">Derived</span> : <span class="type">Base</span>
{
    <span class="reserved">public</span> <span class="reserved">new</span> <span class="reserved">void</span> <span class="method"><span class="warning" title="CS0109">M</span></span>(<span class="reserved">object</span> <span class="variable local">x</span>) { }

    <span class="reserved">public</span> <span class="reserved">void</span> <span class="method">M</span>()
    {
        <span class="comment">// わかりにくいけども、Derived.M(object) の方が呼ばれる。</span>
        <span class="comment">// 引数の型を考えると Base.M(int) が呼ばれそうに見えるけども、そうはならない。</span>
        <span class="comment">// (「元々はなかったけど後から Base の方に M(int) が追加された」みたいな状況で破壊的変更にならないようにするため。)</span>
        <span class="method">M</span>(<span class="number">1</span>);
    }
}
</pre>
<h2>メンバーのルックアップ(拡張同士)</h2>
<p>あと、既存の拡張メソッドには以下のような優先度があります。</p>
<pre class="source" title="インスタンス メソッド優先">
<span class="reserved">namespace</span> Ex1
{
    <span class="reserved">static</span> <span class="reserved">class</span> <span class="type"><span class="static">AExtension</span></span>
    {
        <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="static"><span class="method">M</span></span>(<span class="reserved">this</span> App1<span class="operator">.</span><span class="type">A</span> <span class="variable local">_</span>) <span class="operator">=&gt;</span> <span class="type"><span class="static">Console</span></span><span class="operator">.</span><span class="static"><span class="method">WriteLine</span></span>(<span class="string">&quot;Extension in Ex1&quot;</span>);
    }
}

<span class="reserved">namespace</span> App1
{
    <span class="reserved">class</span> <span class="type">A</span>
    {
        <span class="reserved">public</span> <span class="reserved">void</span> <span class="method">M</span>() <span class="operator">=&gt;</span> <span class="static"><span class="type">Console</span></span><span class="operator">.</span><span class="static"><span class="method">WriteLine</span></span>(<span class="string">&quot;Instance&quot;</span>);
    }

    <span class="reserved">class</span> <span class="type">Program</span>
    {
        <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">Main</span></span>()
        {
            <span class="comment">// インスタンス メソッド優先。</span>
            <span class="reserved">new</span> <span class="type">A</span>()<span class="operator">.</span><span class="method">M</span>(); <span class="comment">// Instance</span>
        }
    }
}
</pre>
<pre class="source" title="同じ名前空間内の拡張メソッド優先">
<span class="reserved">namespace</span> Ex1
{
    <span class="reserved">static</span> <span class="reserved">class</span> <span class="static"><span class="type">AExtension</span></span>
    {
        <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">M</span></span>(<span class="reserved">this</span> App1<span class="operator">.</span><span class="type">A</span> <span class="variable local">_</span>) <span class="operator">=&gt;</span> <span class="static"><span class="type">Console</span></span><span class="operator">.</span><span class="static"><span class="method">WriteLine</span></span>(<span class="string">&quot;Extension in Ex1&quot;</span>);
    }
}

<span class="reserved">namespace</span> App1
{
    <span class="reserved">class</span> <span class="type">A</span>;

    <span class="reserved">static</span> <span class="reserved">class</span> <span class="type"><span class="static">AExtension</span></span>
    {
        <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="static"><span class="method">M</span></span>(<span class="reserved">this</span> <span class="type">A</span> <span class="variable local">_</span>) <span class="operator">=&gt;</span> <span class="static"><span class="type">Console</span></span><span class="operator">.</span><span class="method"><span class="static">WriteLine</span></span>(<span class="string">&quot;Extension in App1&quot;</span>);
    }

    <span class="reserved">class</span> <span class="type">Program</span>
    {
        <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="static"><span class="method">Main</span></span>()
        {
            <span class="comment">// 同じ名前空間内の拡張メソッド優先。</span>
            <span class="reserved">new</span> <span class="type">A</span>()<span class="operator">.</span><span class="method">M</span>(); <span class="comment">// in App1</span>
        }
    }
}
</pre>
<pre class="source" title="内側で using した方優先">
<span class="reserved">using</span> Ex1;

<span class="reserved">namespace</span> Ex1
{
    <span class="reserved">static</span> <span class="reserved">class</span> <span class="static"><span class="type">AExtension</span></span>
    {
        <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">M</span></span>(<span class="reserved">this</span> App1<span class="operator">.</span><span class="type">A</span> <span class="variable local">_</span>) <span class="operator">=&gt;</span> <span class="static"><span class="type">Console</span></span><span class="operator">.</span><span class="method"><span class="static">WriteLine</span></span>(<span class="string">&quot;Extension in Ex1&quot;</span>);
    }
}

<span class="reserved">namespace</span> Ex2
{
    <span class="reserved">static</span> <span class="reserved">class</span> <span class="static"><span class="type">AExtension</span></span>
    {
        <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="static"><span class="method">M</span></span>(<span class="reserved">this</span> App1<span class="operator">.</span><span class="type">A</span> <span class="variable local">_</span>) <span class="operator">=&gt;</span> <span class="static"><span class="type">Console</span></span><span class="operator">.</span><span class="method"><span class="static">WriteLine</span></span>(<span class="string">&quot;Extension in Ex1&quot;</span>);
    }
}

<span class="reserved">namespace</span> App1
{
    <span class="reserved">using</span> Ex2;

    <span class="reserved">class</span> <span class="type">A</span>;

    <span class="reserved">class</span> <span class="type">Program</span>
    {
        <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="static"><span class="method">Main</span></span>()
        {
            <span class="comment">// 内側で using した方優先。</span>
            <span class="reserved">new</span> <span class="type">A</span>()<span class="operator">.</span><span class="method">M</span>(); <span class="comment">// in Ex2</span>
        }
    }
}
</pre>
<pre class="source" title="優劣がない場合はコンパイル エラー">
<span class="reserved">namespace</span> Ex1
{
    <span class="reserved">static</span> <span class="reserved">class</span> <span class="type"><span class="static">AExtension</span></span>
    {
        <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="static"><span class="method">M</span></span>(<span class="reserved">this</span> App1<span class="operator">.</span><span class="type">A</span> <span class="variable local">_</span>) <span class="operator">=&gt;</span> <span class="static"><span class="type">Console</span></span><span class="operator">.</span><span class="method"><span class="static">WriteLine</span></span>(<span class="string">&quot;Extension in Ex1&quot;</span>);
    }
}

<span class="reserved">namespace</span> Ex2
{
    <span class="reserved">static</span> <span class="reserved">class</span> <span class="type"><span class="static">AExtension</span></span>
    {
        <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">M</span></span>(<span class="reserved">this</span> App1<span class="operator">.</span><span class="type">A</span> <span class="variable local">_</span>) <span class="operator">=&gt;</span> <span class="type"><span class="static">Console</span></span><span class="operator">.</span><span class="method"><span class="static">WriteLine</span></span>(<span class="string">&quot;Extension in Ex1&quot;</span>);
    }
}

<span class="reserved">namespace</span> App1
{
    <span class="reserved">using</span> Ex1;
    <span class="reserved">using</span> Ex2;

    <span class="reserved">class</span> <span class="type">A</span>;

    <span class="reserved">class</span> <span class="type">Program</span>
    {
        <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">Main</span></span>()
        {
            <span class="comment">// 優劣がない場合はコンパイル エラー。</span>
            <span class="reserved">new</span> <span class="type">A</span>()<span class="operator">.</span><span class="method"><span class="error" title="CS0121">M</span></span>();
        }
    }
}
</pre>
<p>新しい拡張型でも同様のルールになると思われます。</p>
<p>一方で、旧「拡張メソッド」と新「拡張型」に優劣をつけるかという議題もありますが、
現状は「優劣つけない」という方向で検討されています。
というか、新旧混在した時点でコンパイル エラーにしようかという話もあるみたいです。</p>
<pre class="source" title="優劣がない場合はコンパイル エラー">
<span class="reserved">namespace</span> Ex1
{
    <span class="reserved">static</span> <span class="reserved">class</span> <span class="type"><span class="static">AExtension</span></span>
    {
        <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="static"><span class="method">M</span></span>(<span class="reserved">this</span> App1<span class="operator">.</span><span class="type">A</span> <span class="variable local">_</span>) <span class="operator">=&gt;</span> <span class="static"><span class="type">Console</span></span><span class="operator">.</span><span class="method"><span class="static">WriteLine</span></span>(<span class="string">&quot;old extension method&quot;</span>);
    }
}

<span class="reserved">namespace</span> Ex2
{
    <span class="reserved">implicit</span> <span class="reserved">extension</span> <span class="type"><span class="static">AExtension</span></span> <span class="reserved">for</span> <span class="type">A</span>
    {
        <span class="reserved">public</span> <span class="reserved">void</span> <span class="method">M</span>() <span class="operator">=&gt;</span> <span class="type"><span class="static">Console</span></span><span class="operator">.</span><span class="method"><span class="static">WriteLine</span></span>(<span class="string">&quot;new extension type&quot;</span>);
    }
}

<span class="reserved">namespace</span> App1
{
    <span class="reserved">using</span> Ex1; <span class="comment">// これが外にあってもエラーにする案もあり</span>
    <span class="reserved">using</span> Ex2;

    <span class="reserved">class</span> <span class="type">A</span>;

    <span class="reserved">class</span> <span class="type">Program</span>
    {
        <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">Main</span></span>()
        {
            <span class="comment">// 優劣を付けない(コンパイル エラーになる)。</span>
            <span class="comment">// 何なら新旧混在している時点でコンパイル エラーにする可能性濃厚。</span>
            <span class="reserved">new</span> <span class="type">A</span>()<span class="operator">.</span><span class="method"><span class="error" title="CS0121">M</span></span>();
        }
    }
}
</pre>
<h2>インターフェイス実装</h2>
<p>ここまでの話は割かし C# 13 で入りそうな話なんですが、
最後に1つ、13では入らなさそうなのがインターフェイス実装の後付けです。</p>
<p>これまでの話どおり、ラッパー構造体を作る方針で少し考えてみましょう。</p>
<p>インターフェイス実装に関する部分だけ残して、以下のようにしたとします。</p>
<pre class="source" title="拡張型でインターフェイス実装">
<span class="reserved">var</span> <span class="variable">value</span> <span class="operator">=</span> <span class="reserved">new</span> <span class="type">SomeClass</span> { <span class="field">Value</span> <span class="operator">=</span> <span class="number">1</span> };
<span class="type struct">SomeExtension</span> <span class="variable">extension</span> <span class="operator">=</span> <span class="variable">value</span>;

<span class="variable">extension</span><span class="operator">.</span><span class="method">Equals</span>(<span class="reserved">new</span> <span class="type">SomeClass</span> { <span class="field">Value</span> <span class="operator">=</span> <span class="number">1</span> });

<span class="reserved">explicit</span> <span class="reserved">extension</span> <span class="type">SomeExtension</span> <span class="reserved">for</span> <span class="type">SomeClass</span> : <span class="type">IEquatable</span>&lt;<span class="type">SomeExtension</span>&gt;
{
    <span class="reserved">public</span> <span class="reserved">bool</span> <span class="method">Equals</span>(<span class="type">SomeExtension</span><span class="operator">?</span> <span class="variable local">other</span>) <span class="operator">=&gt;</span> <span class="field">Value</span> <span class="operator">==</span> <span class="variable local">other</span><span class="operator">?</span><span class="operator">.</span><span class="field">Value</span>;
}

<span class="reserved">class</span> <span class="type">SomeClass</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> <span class="field">Value</span>;
}
</pre>
<p>ラッパー構造体で展開するとしたら以下のようになります。</p>
<pre class="source" title="ラッパー構造体で展開">
<span class="reserved">using</span> System<span class="operator">.</span>Runtime<span class="operator">.</span>CompilerServices;

<span class="reserved">var</span> <span class="variable">value</span> <span class="operator">=</span> <span class="reserved">new</span> <span class="type">SomeClass</span> { <span class="field">Value</span> <span class="operator">=</span> <span class="number">1</span> };
<span class="reserved">ref</span> <span class="reserved">var</span> <span class="variable">extension</span> <span class="operator">=</span> <span class="reserved">ref</span> <span class="type"><span class="static">Unsafe</span></span><span class="operator">.</span><span class="method"><span class="static">As</span></span>&lt;<span class="type">SomeClass</span>, <span class="type struct">SomeExtension</span>&gt;(<span class="reserved">ref</span> <span class="variable">value</span>);

<span class="reserved">var</span> <span class="variable">temp</span> <span class="operator">=</span> <span class="reserved">new</span> <span class="type">SomeClass</span> { <span class="field">Value</span> <span class="operator">=</span> <span class="number">1</span> };

<span class="comment">// こういう風に直接インターフェイス メンバーを呼ぶ分には特に問題なさげ。</span>
<span class="variable">extension</span><span class="operator">.</span><span class="method">Equals</span>(<span class="static"><span class="type">Unsafe</span></span><span class="operator">.</span><span class="static"><span class="method">As</span></span>&lt;<span class="type">SomeClass</span>, <span class="type struct">SomeExtension</span>&gt;(<span class="reserved">ref</span> <span class="variable">temp</span>));

<span class="reserved">struct</span> <span class="type struct">SomeExtension</span> : <span class="type">IEquatable</span>&lt;<span class="type struct">SomeExtension</span>&gt;
{
    <span class="reserved">private</span> <span class="type">SomeClass</span> <span class="field">Value</span>;
    <span class="reserved">public</span> <span class="reserved">bool</span> <span class="method">Equals</span>(<span class="type struct">SomeExtension</span> <span class="variable local">other</span>) <span class="operator">=&gt;</span> <span class="field">Value</span><span class="operator">.</span><span class="field">Value</span> <span class="operator">==</span> <span class="variable local">other</span><span class="operator">.</span><span class="field">Value</span><span class="operator">?</span><span class="operator">.</span><span class="field">Value</span>;
}

<span class="reserved">class</span> <span class="type">SomeClass</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> <span class="field">Value</span>;
}
</pre>
<p>この例はインターフェイス実装しているといっても、そもそもメンバーを直接呼んでいるので問題がないだけです。
問題は以下の状況。</p>
<ul>
<li>インターフェイス型や <code>object</code> 型の変数で受けてボックス化する場合</li>
<li>ジェネリック メソッドに渡す場合</li>
</ul>
<p>まず、インターフェイス型の変数で受けてみましょう。
<code>ReferenceEquals</code> や <code>is</code> 判定であまり期待通りとは言えない挙動を起こします。</p>
<pre class="source" title="インターフェイス型の変数で受けてみる">
<span class="reserved">using</span> System<span class="operator">.</span>Runtime<span class="operator">.</span>CompilerServices;

<span class="reserved">var</span> <span class="variable">value</span> <span class="operator">=</span> <span class="reserved">new</span> <span class="type">SomeClass</span> { <span class="field">Value</span> <span class="operator">=</span> <span class="number">1</span> };
<span class="reserved">ref</span> <span class="reserved">var</span> <span class="variable">extension</span> <span class="operator">=</span> <span class="reserved">ref</span> <span class="static"><span class="type">Unsafe</span></span><span class="operator">.</span><span class="method"><span class="static">As</span></span>&lt;<span class="type">SomeClass</span>, <span class="type struct">SomeExtension</span>&gt;(<span class="reserved">ref</span> <span class="variable">value</span>);

<span class="comment">// インターフェイスに渡そうとすると、この実装だとボックス化が発生。</span>
<span class="type">IEquatable</span>&lt;<span class="type struct">SomeExtension</span>&gt; <span class="variable">boxedExtension</span> <span class="operator">=</span> <span class="variable">extension</span>;

<span class="comment">// インスタンスが一致しなくなる。</span>
<span class="type"><span class="static">Console</span></span><span class="operator">.</span><span class="static"><span class="method">WriteLine</span></span>(<span class="static"><span class="method">ReferenceEquals</span></span>(<span class="variable">value</span>, <span class="variable">boxedExtension</span>)); <span class="comment">// false</span>

<span class="comment">// ダウンキャストが失敗する。</span>
<span class="type"><span class="static">Console</span></span><span class="operator">.</span><span class="static"><span class="method">WriteLine</span></span>(<span class="variable">boxedExtension</span> <span class="reserved">is</span> <span class="type">SomeClass</span>); <span class="comment">// false</span>
</pre>
<p>ジェネリク メソッドでは、以下のように、元の型と拡張型の両方の型情報を使う必要がでてきます。</p>
<pre class="source" title="ジェネリク メソッドに拡張型を渡す">
<span class="reserved">var</span> <span class="variable">value</span> <span class="operator">=</span> <span class="reserved">new</span> <span class="type">SomeClass</span> { <span class="field">Value</span> <span class="operator">=</span> <span class="number">1</span> };
<span class="type">List</span>&lt;<span class="type">SomeClass</span>&gt; <span class="variable">list</span> <span class="operator">=</span> [<span class="reserved">new</span>() { <span class="field">Value</span> <span class="operator">=</span> <span class="number">2</span> }, <span class="reserved">new</span>() { <span class="field">Value</span> <span class="operator">=</span> <span class="number">1</span> }, <span class="reserved">new</span>() { <span class="field">Value</span> <span class="operator">=</span> <span class="number">0</span> }];

<span class="comment">// SomeClass のままだと IEquatable 制約を満たさなくて呼べない。</span>
<span class="reserved">var</span> <span class="variable">i1</span> <span class="operator">=</span> <span class="method"><span class="static">IndexOf</span></span><span class="operator">&lt;</span><span class="error" title="CS0119"><span class="type">SomeClass</span></span><span class="operator">&gt;&gt;</span>(<span class="variable">list</span>, <span class="variable">value</span>);

<span class="comment">// これなら呼べるようになるはず。</span>
<span class="comment">// ただ、list は List&lt;SomeClass&gt; なので、やっぱり型消去が必要。</span>
<span class="comment">// 型引数が暗黙的に SomeClass と SomeExtension の2つに増えるような処理が必要。</span>
<span class="reserved">var</span> <span class="variable">i2</span> <span class="operator">=</span> <span class="static"><span class="method">IndexOf</span></span>&lt;<span class="type struct">SomeExtension</span>&gt;(<span class="variable"><span class="error" title="CS1503">list</span></span>, <span class="error" title="CS1503"><span class="variable">value</span></span>);

<span class="reserved">static</span> <span class="reserved">int</span> <span class="method"><span class="static">IndexOf</span></span>&lt;<span class="type param">T</span>&gt;(<span class="type">List</span>&lt;<span class="type param">T</span>&gt; <span class="variable local">list</span>, <span class="type param">T</span> <span class="variable local">value</span>)
    <span class="reserved">where</span> <span class="type param">T</span> : <span class="type">IEquatable</span>&lt;<span class="type param">T</span>&gt;
{
    <span class="comment">// 今の型システムだと T が通常の型か拡張型かを知るすべはなく、Unsafe.As 展開ができない。</span>
    <span class="control">for</span> (<span class="reserved">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; <span class="variable">i</span> <span class="operator">&lt;</span> <span class="variable local">list</span><span class="operator">.</span><span class="property">Count</span>; <span class="variable">i</span><span class="operator">++</span>)
        <span class="control">if</span> (<span class="variable local">list</span>[<span class="variable">i</span>]<span class="operator">.</span><span class="method">Equals</span>(<span class="variable local">value</span>))
            <span class="control">return</span> <span class="variable">i</span>;
    <span class="control">return</span> <span class="operator">-</span><span class="number">1</span>;
}
</pre>
<p>いずれも、C# コンパイラー上のトリックでは問題を解消できなさそうで、
.NET ランタイムの型システムに手を入れる必要が出てきそうです。
型システムに手を入れるとなると結構大ごとなので、C# 13 で実現する見込みは残念ながらほぼありません。</p>
 ]]></description>
				<pubDate>Wed, 20 Mar 2024 19:51:16 +0900</pubDate>
			</item>
			<item>
				<title>C# 13 でのコレクション式 - ディクショナリ式</title>
				<link>http://ufcpp.net/blog/2024/3/dictionary-expressions/</link>
				<description><![CDATA[ <p>C# 13でのコレクション式関連、量が多いのでちょっとずつ取り上げシリーズ。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/7913">[Proposal]: Collection Expressions Next (C#13 and beyond)</a></li>
</ul>
<p>今日はディクショナリ式の話を。</p>
<ul>
<li>ディクショナリ式 ← 今日はこれ</li>
<li>自然な型</li>
<li>インラインなコレクション式</li>
<li>コレクションに対する拡張メソッド</li>
<li>現状でコレクション式に対応してない型</li>
<li>非ジェネリックなコレクションのサポート</li>
<li><a href="https://ufcpp.net/blog/2024/3/colexpr13-relax-restriction/">制限の緩和</a></li>
</ul>
<h2>ディクショナリ式</h2>
<p>C# 12 でコレクション式が入りましたが、<code>Dictionary&lt;TKey, TValue&gt;</code> などのディクショナリ系の型に対しては使えませんでした。</p>
<pre class="source" title="ディクショナリに対するコレクション式">
<span class="comment">// C# 12 でも空っぽのディクショナリは作れるのに…</span>
<span class="type">Dictionary</span>&lt;<span class="reserved">string</span>, <span class="reserved">int</span>&gt; <span class="variable">d</span> <span class="operator">=</span> [];

<span class="comment">// 要素があるものは書く手段がない(以下はいずれもエラー)。</span>
<span class="comment">// スケジュールの都合で意図的に「C# 13 でやる」計画。</span>

<span class="comment">// KeyValuePair とかタプルも受け付けず。</span>
<span class="type">Dictionary</span>&lt;<span class="reserved">string</span>, <span class="reserved">int</span>&gt; <span class="variable">d1</span> <span class="operator">=</span> <span class="error" title="CS9215">[<span class="static"><span class="type">KeyValuePair</span></span><span class="operator">.</span><span class="method"><span class="static">Create</span></span>(<span class="string">&quot;&quot;</span>, <span class="number">1</span>)]</span>;
<span class="type">Dictionary</span>&lt;<span class="reserved">string</span>, <span class="reserved">int</span>&gt; <span class="variable">d2</span> <span class="operator">=</span> <span class="error" title="CS9215">[<span class="error" title="CS0029">(<span class="string">&quot;&quot;</span>, <span class="number">1</span>)</span>]</span>;

<span class="comment">// コレクション初期化子/オブジェクト初期化子みたいな構文も受け付けず。</span>
<span class="type">Dictionary</span>&lt;<span class="reserved">string</span>, <span class="reserved">int</span>&gt; <span class="variable">d3</span> <span class="operator">=</span> [<span class="error" title="CS1001">{</span><span class="string">&quot;&quot;</span>, <span class="number">1</span><span class="error" title="CS1022"><span class="error" title="CS1003"><span class="error" title="CS1002">}</span></span></span><span class="error" title="CS1022">]</span>;
<span class="type">Dictionary</span>&lt;<span class="reserved">string</span>, <span class="reserved">int</span>&gt; <span class="variable">d4</span> <span class="operator">=</span> [<span class="error" title="CS0131">[<span class="string">&quot;&quot;</span>]</span> <span class="operator">=</span> <span class="number">1</span>];
</pre>
<p>C# 12 時点で<a href="https://ufcpp.net/study/csharp/datatype/collection-expression/">コレクション式</a>に対する背景と同じく、
ディクショナリについても以下の需要が見込まれます。</p>
<ul>
<li>簡素に書きたい</li>
<li>いろいろな種類のディクショナリ系の型に対して共通で使える構文にしたい</li>
<li>特に、既存のコレクション初期化子では使えない immutable な型にも対応したい</li>
</ul>
<p>まあ、
GitHub を軽くクロールしてみて利用頻度を調べると、
リストや配列と比べたらディクショナリの利用率は10%くらいらしいです。
とはいえ、10%もそこそこ大きな数字。
C# 12 時点では後回しになりましたが、13候補としては有力です。</p>
<p>提案ドキュメント、関連デザインミーティング等:</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/7822">[Proposal]: Dictionary expressions #7822</a></li>
<li><a href="https://github.com/dotnet/csharplang/blob/main/proposals/dictionary-expressions.md">Dictionary Expressions</a></li>
<li><a href="https://github.com/dotnet/csharplang/blob/main/meetings/2024/LDM-2024-03-11.md">C# Language Design Meeting for March 11th, 2024</a></li>
</ul>
<p>まあ検討が始まったばかりなので、まだまだ結論の出ていない検討事項も多数。
とりあえず今日は3月11日のミーティング議事録をベースにした話を書こうかと思います。</p>
<h2>構文の候補</h2>
<p>まだ構文をどうするかも決定ではないんですが、現状の最有力候補は <code>[key: value]</code> みたいな書き方です。</p>
<pre class="source" title="ディクショナリ式の候補文法">
<span class="comment">// 「ディクショナリ式」の最有力候補の文法:</span>
<span class="type">Dictionary</span>&lt;<span class="reserved">string</span>, <span class="reserved">int</span>&gt; <span class="variable">d</span> <span class="operator">=</span> [
    <span class="string">&quot;one&quot;</span>: <span class="number">1</span>,
    <span class="string">&quot;two&quot;</span>: <span class="number">2</span>,
    ];
</pre>
<p>もちろん、「JavaScript では <code>{}</code> を使うけども」みたいな別案もあるんですが、
まあ、C# 12 のコレクション式に合わせて <code>[]</code> になると思われます。</p>
<p>ちなみに、最初期には「<code>[]</code> の外でも <code>key: value</code> で <code>KeyValuePair</code> を作れるようにするべきか？」みたいな見当もありましたが、
現状それには否定的で、 <code>[]</code> の中限定の構文になりそうです。</p>
<pre class="source" title="没案">
<span class="comment">// 没案「KeyValuePair 式」。</span>
<span class="type struct">KeyValuePair</span>&lt;<span class="reserved">string</span>, <span class="reserved">int</span>&gt; <span class="variable">kvp</span> <span class="operator">=</span> <span class="string">&quot;one&quot;</span>: <span class="number">1</span>;
</pre>
<h2>検討事項1: KeyValuePair を並べる</h2>
<p>ディクショナリ式中では、<code>key: value</code> みたいな形式のみを受け付けるか、それとも、<code>KeyValuePair</code> であれば直接書けるようにするかという話があります。</p>
<pre class="source" title="KeyValuePair を直接書けるようにする案">
<span class="comment">// key: value のみ。これは問題ない。</span>
<span class="type">Dictionary</span>&lt;<span class="reserved">string</span>, <span class="reserved">int</span>&gt; <span class="variable">d</span> <span class="operator">=</span> [<span class="string">&quot;one&quot;</span>: <span class="number">1</span>];

<span class="reserved">var</span> <span class="variable">kvp</span> <span class="operator">=</span> <span class="type"><span class="static">KeyValuePair</span></span><span class="operator">.</span><span class="method"><span class="static">Create</span></span>(<span class="string">&quot;two&quot;</span>, <span class="number">2</span>);

<span class="comment">// KeyValuePair をいちいち展開する必要はあるかどうか。</span>
<span class="type">Dictionary</span>&lt;<span class="reserved">string</span>, <span class="reserved">int</span>&gt; <span class="variable">d1</span> <span class="operator">=</span> [<span class="string">&quot;one&quot;</span>: <span class="number">1</span>,</span></span> <span class="variable">kvp</span><span class="operator">.</span><span class="property">Key</span>: <span class="variable">kvp</span><span class="operator">.</span><span class="property">Value</span>];

<span class="comment">// こう書きたい需要はある。</span>
<span class="type">Dictionary</span>&lt;<span class="reserved">string</span>, <span class="reserved">int</span>&gt; <span class="variable">d2</span> <span class="operator">=</span> [<span class="string">&quot;one&quot;</span>: <span class="number">1</span>, <span class="variable">kvp</span>];
</pre>
<p><code>[&quot;one&quot;: 1, kvp]</code> と書けるようにする案には肯定的な人が多く、承認されそうです。</p>
<h2>検討事項2: KeyValuePair のリストを Spread する</h2>
<p>検討事項1と似たような話ですが、<code>IEnumerable&lt;KeyValuePair&lt;TKey, TValue&gt;&gt;</code> とかをディクショナリ式中に含められるかという話もあります。</p>
<pre class="source" title="ディクショナリ式中で KeyValuePair のリストを Spread">
<span class="reserved">var</span> <span class="variable">kvps</span> <span class="operator">=</span> <span class="reserved">new</span>[] { <span class="static"><span class="type">KeyValuePair</span></span><span class="operator">.</span><span class="static"><span class="method">Create</span></span>(<span class="string">&quot;two&quot;</span>, <span class="number">2</span>) };

<span class="comment">// .. で展開すると KeyValuePair になるわけで、</span>
<span class="comment">// KeyValuePair を認めるのなら、 ..(KeyValuePair のリスト) も認めたい。</span>
<span class="type">Dictionary</span>&lt;<span class="reserved">string</span>, <span class="reserved">int</span>&gt; <span class="variable">d1</span> <span class="operator">=</span> [..<span class="variable">kvps</span>];

<span class="comment">// 混在も需要あり。</span>
<span class="type">Dictionary</span>&lt;<span class="reserved">string</span>, <span class="reserved">int</span>&gt; <span class="variable">d2</span> <span class="operator">=</span> [<span class="string">&quot;one&quot;</span>: <span class="number">1</span>, ..><span class="variable">kvps</span>];

<span class="comment">// 特に、「複数のディクショナリのマージ」みたいな用途で以下のように書きたい。</span>
<span class="reserved">var</span> <span class="variable">kvps1</span> <span class="operator">=</span> <span class="reserved">new</span>[] { <span class="type"><span class="static">KeyValuePair</span></span><span class="operator">.</span><span class="static"><span class="method">Create</span></span>(<span class="string">&quot;three&quot;</span>, <span class="number">3</span>) };
<span class="type">Dictionary</span>&lt;<span class="reserved">string</span>, <span class="reserved">int</span>&gt; <span class="variable">d3</span> <span class="operator">=</span> [..<span class="variable">kvps</span>, ..<span class="variable">kvps1</span>];
</pre>
<p>これも認める方向で検討されています。</p>
<h2>検討事項3: ディクショナリじゃなくて KeyValuePair のリスト</h2>
<p><code>[]</code> 中の <code>key: value</code> は「<code>KeyValuePair</code> を作るための簡易記法」みたいなものになっているわけですが、
だったら以下のような「ディクショナリじゃないただのコレクションに対して使えるか」という話が出てきます。</p>
<pre class="source" title="KeyValuePair のリストに対してディクショナリ式">
<span class="comment">// 「ディクショナリ式」の最有力候補の文法:</span>
<span class="type">List</span>&lt;<span class="type">KeyValuePair</span>&lt;<span class="reserved">string</span>, <span class="reserved">int</span>&gt;&gt; <span class="variable">d</span> <span class="operator">=</span> [
    <span class="string">&quot;one&quot;</span>: <span class="number">1</span>,
    <span class="string">&quot;two&quot;</span>: <span class="number">2</span>,
    ];
</pre>
<p>これも需要がそれなりにありそうです。
.NET の BCL とか、 Roslyn 中のコードでもオプションとかをディクショナリではなくて <code>IEnumerable&lt;KeyValuePair&lt;TKey, TValue&gt;&gt;</code> 引数で受け取っているものがそれなりにあるそうで。</p>
<p>それに、先ほどの <code>Dictionary&lt;string, int&gt; d3 = [..kvps, ..kvps1];</code> みたいなもので、マージ元になる <code>kvps</code> などはディクショナリではなくて <code>KeyValuePair</code> のリストということは十分ありそうな話です。</p>
<p>ということで、これも承認されそうです。</p>
<h2>検討事項4: KeyValuePair 以外の要素は認められるか</h2>
<p><code>Dictionary&lt;TValue, TKey&gt;</code> とかでは要素の列挙などに <code>KeyValuePair&lt;TValue, TKey&gt;</code> を使うことが多いですが、
ディクショナリ式を作るにあたって <code>KeyValuePair</code> だけに絞るか、それとも他の型も使えるようにするかという問題もあります。</p>
<p>例えば、タプル導入時にも、<code>(TKey key, TValue value)</code> はほぼ <code>KeyValuePair&lt;TKey, TValue&gt;</code> と同等」みたいなことを言われています。
割かし最近 BCL に追加された <a href="https://learn.microsoft.com/ja-jp/dotnet/api/system.collections.generic.priorityqueue-2"><code>PriorityQueue</code></a> なんかは、<code>(TElement Element, TPriority Priority)</code> で要素とその優先度の列挙をします。
<a href="https://learn.microsoft.com/ja-jp/dotnet/api/system.linq.enumerable.zip?view=net-8.0#system-linq-enumerable-zip-2(system-collections-generic-ienumerable((-0))-system-collections-generic-ienumerable((-1)))"><code>Zip</code></a> なんかも <code>(TFirst First, TSecond Second)</code> で結果を列挙します。
こういうものを直接 <code>[]</code> の中で <code>..</code> で展開したかったりはします。</p>
<p>あとは、<code>KeyValuePair</code> を特別扱いするとしても、暗黙の型変換を認めるかどうか。</p>
<pre class="source" title="">
<span class="reserved">struct</span> <span class="type struct">Pair</span>&lt;<span class="type param">X</span>, <span class="type param">Y</span>&gt;(<span class="type param">X</span> <span class="variable local"><span class="warning" title="CS9113">x</span></span>, <span class="type param">Y</span> <span class="variable local"><span class="warning" title="CS9113">y</span></span>)
{
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">implicit</span> <span class="reserved">operator</span> <span class="type struct">KeyValuePair</span>&lt;<span class="type param">X</span>, <span class="type param">Y</span>&gt;(<span class="type struct">Pair</span>&lt;<span class="type param">X</span>, <span class="type param">Y</span>&gt; <span class="variable local">pair</span>) <span class="operator">=&gt;</span> </span>..<span class="operator">.;
}

<span class="type">Dictionary</span>&lt;<span class="reserved">string</span>, <span class="reserved">int</span>&gt; <span class="variable">d</span> <span class="operator">=</span> 
[
    <span class="reserved">new</span> <span class="type struct">Pair</span>(<span class="string">&quot;one&quot;</span>, <span class="number">1</span>),
    .. <span class="reserved">new</span>[] { <span class="reserved">new</span> <span class="type struct">Pair</span>(<span class="string">&quot;two&quot;</span>, <span class="number">2</span>) }
];
</pre>
<p>これについては結論はまだ出ていないみたいです。</p>
<h2>検討事項5: Add か、インデクサーか</h2>
<p>まず、ディクショナリ式ではキーの重複を認めるかどうかという話があります。
例えば、<code>ToDictionary</code> なんかでは、キーが重複していると例外を出します。</p>
<pre class="source" title="ToDictionary はキーの重複ダメ">
<span class="reserved">var</span> <span class="variable">d</span> <span class="operator">=</span> <span class="reserved">new</span>[] { (<span class="number">1</span>, <span class="number">10</span>), (<span class="number">1</span>, <span class="number">20</span>) }
    <span class="operator">.</span><span class="method">ToDictionary</span>(<span class="variable local">x</span> <span class="operator">=&gt;</span> <span class="variable local">x</span><span class="operator">.</span><span class="field">Item1</span>); <span class="comment">// ArgumentException</span>
</pre>
<p>が、まあ、前述の2個のディクショナリをマージするようなケースでは重複を認める方がよかったりします。
オプション指定とかだと「デフォルト設定と、ユーザーごとの設定をマージ、後で追加した方を優先」みたいな使い方を結構しますし。</p>
<p>ただ、「重複を認めるかどうか」という観点だと、結局は「ターゲットにする型によって挙動が違う」ということになります。
例えば、以下のような感じ。</p>
<ul>
<li><code>Dictionary&lt;TKey, TValue&gt;</code> の <code>Add</code> は重複を認めていない</li>
<li><code>ImmutableDictionary&lt;TKey, TValue&gt;</code> の <code>Add</code> は上書き(上書きした新しいインスタンスを作って返す)</li>
<li><code>FrozenDictionary&lt;TKey, TValue&gt;</code> の <code>Add</code> (<code>ICollection</code> インターフェイス越しに呼べちゃう) は <code>NotSupported</code> 例外を出す</li>
</ul>
<p>なので結局は「どういう動作にするか」は決めれなくて、「<code>Add</code> とインデクサーのどちらを使うか」という話になります。</p>
<pre class="source" title="ディクショナリ式の初期化はどちらにすべきか">
<span class="comment">// Add で初期化。</span>
<span class="type">Dictionary</span>&lt;<span class="reserved">string</span>, <span class="reserved">int</span>&gt; <span class="variable">d1</span> <span class="operator">=</span> <span class="reserved">new</span>();
<span class="variable">d1</span><span class="operator">.</span><span class="method">Add</span>(<span class="string">&quot;a&quot;</span>, <span class="number">1</span>);
<span class="variable">d1</span><span class="operator">.</span><span class="method">Add</span>(<span class="string">&quot;b&quot;</span>, <span class="number">2</span>);

<span class="comment">// インデクサで初期化。</span>
<span class="type">Dictionary</span>&lt;<span class="reserved">string</span>, <span class="reserved">int</span>&gt; <span class="variable">d2</span> <span class="operator">=</span> <span class="reserved">new</span>();
<span class="variable">d2</span>[<span class="string">&quot;a&quot;</span>] <span class="operator">=</span> <span class="number">1</span>;
<span class="variable">d2</span>[<span class="string">&quot;b&quot;</span>] <span class="operator">=</span> <span class="number">2</span>;
</pre>
<p>ちなみにこれらは、現状のコレクション初期化子・オブジェクト初期化子を使うと以下のように書けるやつです。</p>
<pre class="source" title="Dictionary に対するコレクション初期化子・オブジェクト初期化子">
<span class="comment">// Add での初期化になるコレクション初期化子。</span>
<span class="type">Dictionary</span>&lt;<span class="reserved">string</span>, <span class="reserved">int</span>&gt; <span class="variable">d1</span> <span class="operator">=</span> <span class="reserved">new</span>()
{
    { <span class="string">&quot;a&quot;</span>, <span class="number">1</span> },
    { <span class="string">&quot;b&quot;</span>, <span class="number">2</span> }
};

<span class="comment">// インデクサでの初期化になるオブジェクト初期化子。</span>
<span class="type">Dictionary</span>&lt;<span class="reserved">string</span>, <span class="reserved">int</span>&gt; <span class="variable">d2</span> <span class="operator">=</span> <span class="reserved">new</span>()
{
    [<span class="string">&quot;a&quot;</span>] <span class="operator">=</span> <span class="number">1</span>,
    [<span class="string">&quot;b&quot;</span>] <span class="operator">=</span> <span class="number">2</span>
};
</pre>
<p><code>[&quot;a&quot;: 1, &quot;b&quot;: 2]</code> はどちらになるかという話なわけですが、
現状はインデクサー案が有力みたいです。
コレクション初期化子(<code>Add</code> になる)と食い違うという懸念もありますが、
インデクサーの方が都合がよさどうという判断になっています。
例えば先ほど例に挙げた <code>[..defaultSettings, ..userSettings]</code> みたいなケースで重複を認めている方がよさそうで、
<code>Dictionary&lt;TKey, TValue&gt;</code> の場合は「<code>Add</code> は重複不可、インデクサーは可」ですし。</p>
 ]]></description>
				<pubDate>Sat, 16 Mar 2024 18:17:03 +0900</pubDate>
			</item>
			<item>
				<title>C# 13 でのコレクション式 - 制限の緩和の話</title>
				<link>http://ufcpp.net/blog/2024/3/colexpr13-relax-restriction/</link>
				<description><![CDATA[ <h2>C# 13 でのコレクション式 - 制限の緩和の話</h2>
<p>C# 12 で<a href="https://ufcpp.net/study/csharp/cheatsheet/ap_ver12/#collection-expression">コレクション式</a>が入ったわけですが、
スケジュールの都合で「C# 12 後に改めて検討する」ということになった機能がたくさんあります。
C# 12 リリース(2023/11)直後から再検討が始まっていて、先月にはある程度まとまった計画が出ています。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/7913">[Proposal]: Collection Expressions Next (C#13 and beyond)</a></li>
</ul>
<p>量が多いのでちょっとずつ取り上げ…</p>
<ul>
<li>ディクショナリ式</li>
<li>自然な型</li>
<li>インラインなコレクション式</li>
<li>コレクションに対する拡張メソッド</li>
<li>現状でコレクション式に対応してない型</li>
<li>非ジェネリックなコレクションのサポート</li>
<li>制限の緩和 ← 今日はこれ</li>
</ul>
<h2>制限の緩和</h2>
<p>今、コレクション式の要素の型は <code>IEnumerable&lt;T&gt;</code> の <code>T</code> で判定しています。</p>
<pre class="source" title="iteration type を元に型判定してる">
<span class="reserved">using</span> System<span class="operator">.</span>Collections;

<span class="control">foreach</span> (<span class="reserved">var</span> <span class="variable">x</span> <span class="control">in</span> <span class="reserved">new</span> <span class="type">A</span>()) ; <span class="comment">// この x は int</span>

<span class="comment">// Add(int) だけあればよさそうに見えるのに、</span>
<span class="comment">// 実際には IEnumerable&lt;int&gt; をみて「int のコレクション」と判断してる。</span>
<span class="type">A</span> <span class="variable">a</span> <span class="operator">=</span> [<span class="number">1</span>];

<span class="comment">// foreach すると int を列挙する型。</span>
<span class="reserved">class</span> <span class="type">A</span> : <span class="type">IEnumerable</span>&lt;<span class="reserved">int</span>&gt;
{
    <span class="type">IEnumerator</span>&lt;<span class="reserved">int</span>&gt; <span class="type">IEnumerable</span>&lt;<span class="reserved">int</span>&gt;<span class="operator">.</span><span class="method">GetEnumerator</span>() <span class="operator">=&gt;</span> <span class="control">throw</span> <span class="reserved">new</span> <span class="type">NotImplementedException</span>();
    <span class="type">IEnumerator</span> <span class="type">IEnumerable</span><span class="operator">.</span><span class="method">GetEnumerator</span>() <span class="operator">=&gt;</span> <span class="control">throw</span> <span class="reserved">new</span> <span class="type">NotImplementedException</span>();
    <span class="reserved">public</span> <span class="reserved">void</span> <span class="method">Add</span>(<span class="reserved">int</span> <span class="variable local">x</span>) { }
}
</pre>
<pre class="source" title="インターフェイス実装を消したらエラー">
<span class="comment">// foreach はインターフェイスがなくても GetEnumerator っていう名前のメソッドさえ持っていれば OK なのに。</span>
<span class="control">foreach</span> (<span class="reserved">var</span> <span class="variable">x</span> <span class="control">in</span> <span class="reserved">new</span> <span class="type">A</span>()) { }

<span class="comment">// これはダメになる。</span>
<span class="type">A</span> <span class="variable">a</span> <span class="operator">=</span> <span class="error" title="CS9174">[<span class="number">1</span>]</span>;

<span class="comment">// インターフェイスを削るとコレクション式で使えなくなる。</span>
<span class="reserved">class</span> <span class="type">A</span>
{
    <span class="reserved">public</span> <span class="type">IEnumerator</span>&lt;<span class="reserved">int</span>&gt; <span class="method">GetEnumerator</span>() <span class="operator">=&gt;</span> <span class="control">throw</span> <span class="reserved">new</span> <span class="type">NotImplementedException</span>();
    <span class="reserved">public</span> <span class="reserved">void</span> <span class="method">Add</span>(<span class="reserved">int</span> <span class="variable local">x</span>) { }
}
</pre>
<pre class="source" title="コレクション初期化子は使えるのに…">
<span class="reserved">using</span> System<span class="operator">.</span>Collections;

<span class="comment">// foreach なんとか OK。</span>
<span class="comment">// non-generic な GetEnumerator が呼ばれてるので object を介してるけど…</span>
<span class="control">foreach</span> (<span class="reserved">int</span> <span class="variable">x</span> <span class="control">in</span> <span class="reserved">new</span> <span class="type">A</span>()) { }

<span class="comment">// 旧来のコレクション初期化子は使えるのに…</span>
<span class="type">A</span> <span class="variable">a1</span> <span class="operator">=</span> <span class="reserved">new</span>() { <span class="number">1</span> };

<span class="comment">// コレクション式はダメになる。</span>
<span class="type">A</span> <span class="variable">a2</span> <span class="operator">=</span> <span class="error" title="CS9215"><span class="error" title="CS1503">[<span class="number">1</span>]</span></span>;

<span class="comment">// non-generic インターフェイスに変えると？</span>
<span class="reserved">class</span> <span class="type">A</span> : <span class="type">IEnumerable</span>
{
    <span class="reserved">public</span> <span class="type">IEnumerator</span> <span class="method">GetEnumerator</span>() <span class="operator">=&gt;</span> <span class="control">throw</span> <span class="reserved">new</span> <span class="type">NotImplementedException</span>();
    <span class="reserved">public</span> <span class="reserved">void</span> <span class="method">Add</span>(<span class="reserved">int</span> <span class="variable local">x</span>) { }
}
</pre>
<p>ちなみに、この「<code>IEnumerable&lt;T&gt;</code> の <code>T</code>」以外は受け付けなかったりします。
これも、コレクション初期化子時代はできたこと。</p>
<pre class="source" title="コレクション初期化子は使えるのに… (再)">
<span class="reserved">using</span> System<span class="operator">.</span>Collections;

<span class="comment">// 旧来のコレクション初期化子は string を受け付けるのに…</span>
<span class="type">A</span> <span class="variable">a1</span> <span class="operator">=</span> <span class="reserved">new</span>() { <span class="number">1</span>, <span class="string">&quot;2&quot;</span> };

<span class="comment">// コレクション式はダメになる。</span>
<span class="type">A</span> <span class="variable">a2</span> <span class="operator">=</span> [<span class="number">1</span>, <span class="string"><span class="error" title="CS0029">&quot;2&quot;</span></span>];

<span class="comment">// Add だけは string 受付。</span>
<span class="reserved">class</span> <span class="type">A</span> : <span class="type">IEnumerable</span>&lt;<span class="reserved">int</span>&gt;
{
    <span class="reserved">public</span> <span class="reserved">void</span> <span class="method">Add</span>(<span class="reserved">int</span> <span class="variable local">x</span>) { }
    <span class="reserved">public</span> <span class="reserved">void</span> <span class="method">Add</span>(<span class="reserved">string</span> <span class="variable local">x</span>) { }

    <span class="type">IEnumerator</span>&lt;<span class="reserved">int</span>&gt; <span class="type">IEnumerable</span>&lt;<span class="reserved">int</span>&gt;<span class="operator">.</span><span class="method">GetEnumerator</span>() <span class="operator">=&gt;</span> <span class="control">throw</span> <span class="reserved">new</span> <span class="type">NotImplementedException</span>();
    <span class="type">IEnumerator</span> <span class="type">IEnumerable</span><span class="operator">.</span><span class="method">GetEnumerator</span>() <span class="operator">=&gt;</span> <span class="control">throw</span> <span class="reserved">new</span> <span class="type">NotImplementedException</span>();
}
</pre>
<p>これが、非ジェネリックな <code>IEnumerable</code> を使うと object のみ受け付けるようになるみたいです。
しかもこれ、 Visual Studio 17.10 以前であれば受け付けていたコードがコンパイル エラーになるというひと悶着あり。</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/issues/72098">False positive for CS1503 with MSBuild 17.10, but not dotnet build #72098</a></li>
</ul>
<pre class="source" title="">
<span class="reserved">using</span> System<span class="operator">.</span>Collections;

<span class="comment">// 旧来のコレクション初期化子は string を受け付けるのに…</span>
<span class="type">A</span> <span class="variable">a1</span> <span class="operator">=</span> <span class="reserved">new</span>() { <span class="number">1</span>, <span class="string">&quot;2&quot;</span> };

<span class="comment">// これ、ちょっと前まで受け付けていたらしい。</span>
<span class="comment">// Visual Studio 17.10 Preview 1 だとエラー。</span>
<span class="type">A</span> <span class="variable">a2</span> <span class="operator">=</span> <span class="error" title="CS9215"><span class="error" title="CS1503">[<span class="number">1</span>, <span class="string">&quot;2&quot;</span>]</span></span>;

<span class="comment">// non-generic なインターフェイスを実装。</span>
<span class="reserved">class</span> <span class="type">A</span> : <span class="type">IEnumerable</span>
{
    <span class="reserved">public</span> <span class="reserved">void</span> <span class="method">Add</span>(<span class="reserved">int</span> <span class="variable local">x</span>) { }
    <span class="reserved">public</span> <span class="reserved">void</span> <span class="method">Add</span>(<span class="reserved">string</span> <span class="variable local">x</span>) { }

    <span class="type">IEnumerator</span> <span class="type">IEnumerable</span><span class="operator">.</span><span class="method">GetEnumerator</span>() <span class="operator">=&gt;</span> <span class="control">throw</span> <span class="reserved">new</span> <span class="type">NotImplementedException</span>();
}
</pre>
<p><a href="https://github.com/dotnet/roslyn/blob/main/docs/compilers/CSharp/Compiler%20Breaking%20Changes%20-%20DotNet%208.md#collection-expression-target-type-must-have-constructor-and-add-method">意図した破壊的変更</a> (たぶん、<a href="https://github.com/dotnet/csharplang/discussions/7832">1/8 の LDM での決定</a>)だそうですが、
本当にこの変更をしてよかったのかどうか。
こういう非ジェネリック <code>IEnumerable</code> だけ実装して、<code>Add</code> でちゃんとした型を指定しているクラス、
WPF とか WinForms には結構あって、それが突然コンパイルできなくなったものでちょっとした混乱が起きています。</p>
<p>ちなみに、この変更の理由は、こうしておかないと <a href="https://ufcpp.net/blog/2024/3/params-collections/"><code>params</code> コレクション</a>を使った時のオーバーロード解決のコストが高くなるからだそうです。
制限を緩めるとして、もしかしたら「コレクション式では使えるけども <code>params</code> コレクションでは使えない」みたいな状況が増えるかもしれません。</p>
<p>一方、そもそもとして <code>IEnumerable</code> 実装は必要なのかという問題が。
何せ、コレクションを作る時点では <code>GetEnumerator</code> は要らず、<code>CollectionBuilder</code> 属性で指定した <code>Create</code> メソッドだけあれば事足ります。
例えば、型によっては「別のコレクションを作るための足掛かりにするもので、直接列挙はしない」みたいなものがあります。
(実際、Roslyn チーム自身が1件そういう問題を踏んだりしています: <a href="https://github.com/dotnet/roslyn/blob/026c96327b02c5ce4d3208f821e02d2ffa825312/src/Compilers/Test/Utilities/CSharp/CSharpTestSource.cs#L22">CSharpTestSource</a>。<code>SyntaxTree[]</code> を作るために使っていて、この型自体からの列挙はしない)。</p>
<p>ということで、<code>CollectionBuilder</code> 属性指定のコレクション型の場合、
<code>Create</code> メソッドの引数の <code>ReadOnlySpan&lt;T&gt;</code> から要素の型を決めようという提案が出ています。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/7744">Open issue: relax requirement that type be enumerable to participate in collection expressions #7744</a></li>
</ul>
 ]]></description>
				<pubDate>Sat, 09 Mar 2024 21:31:10 +0900</pubDate>
			</item>
			<item>
				<title>IList とかを IReadOnlyList とかから派生させたい</title>
				<link>http://ufcpp.net/blog/2024/3/ilist-inherites-from-ireadonlylist/</link>
				<description><![CDATA[ <p>.NET が長らく抱えている「なぜ <code>IList&lt;T&gt;</code> は <code>IReadOnlyList&lt;T&gt;</code> ではないのか」問題、 .NET 9 で解消するかもしれないみたい。</p>
<p>ちなみに、問題を抱えるに至った原因は <code>IReadOnlyList&lt;T&gt;</code> が後付けということです。
1から作り直すのであれば、誰がどう考えても <code>IList&lt;T&gt;</code> は <code>IReadOnlyList&lt;T&gt;</code> から派生させるのが自然です。
それがかえって、<code>IReadOnlyList&lt;T&gt;</code> 導入以降に .NET 利用を始めた人に混乱を招いているというのが現状になります。</p>
<h2>当初設計: インターフェイスは増やしすぎない</h2>
<p>インターフェイスを増やすというのは、
型情報で DLL サイズが増えるとか、
実行時にインターフェイスを検索するコストが増えるとか、
多少なりともコストを生じます。</p>
<p>一方で、.NET Framework の最初のβ版が出たのは2000年ごろ、正式版で2002年なわけですが、
この頃は read-only であることの重要性が過小評価されていたと思います。
なので、重要でない(と当時は思われていた)ものにコストは掛けたくないという話に。</p>
<p>(この辺りのことは「<a target="_blank" href="https://www.amazon.co.jp/dp/4296080040?&amp;_encoding=UTF8&amp;tag=cunflc-22&amp;linkCode=ur2&amp;linkId=c74d95cede34616d4c468ff921d42544&amp;camp=247&amp;creative=1211">.NETのクラスライブラリ設計</a>」で触れられていたりします。
ちなみにこの本、要は「.NET の初期設計に関する懺悔本」です。)</p>
<p>そこで当時の設計としては「read-only / writeable なインターフェイスを1個用意して、<code>IsReadOnly</code> プロパティで書き込み出来るかどうかを調べる」という作りでした。</p>
<pre class="source" title="read-only かどうかはプロパティで調べる">
<span class="reserved">namespace</span> System<span class="operator">.</span>Collections;

<span class="reserved">public</span> <span class="reserved">interface</span> <span class="type">IList</span> : <span class="type">ICollection</span>, <span class="type">IEnumerable</span>
{
    <span class="reserved">object</span> <span class="reserved">this</span>[<span class="reserved">int</span> <span class="variable local">index</span>] { <span class="reserved">get</span>; <span class="reserved">set</span>; }
    <span class="reserved">bool</span> <span class="property">IsReadOnly</span> { <span class="reserved">get</span>; } <span class="comment">// ← これ</span>
    <span class="reserved">void</span> <span class="method">Add</span>(<span class="reserved">object</span> <span class="variable local">value</span>);
    <span class="comment">// 以下略</span>
}
</pre>
<p>.NET Framework 2.0 (2005年)に<a href="https://ufcpp.net/study/csharp/sp2_generics.html">ジェネリクス</a>が導入されてもまだこの思想は引き継がれます。
まあ、旧来インターフェイスとジェネリック インターフェイスで思想が違うのも混乱しそうですし。</p>
<pre class="source" title="ジェネリック ICollection でも IsReadOnly プロパティ">
<span class="reserved">namespace</span> System<span class="operator">.</span>Collections<span class="operator">.</span>Generic;

<span class="reserved">public</span> <span class="reserved">interface</span> <span class="type">ICollection</span>&lt;<span class="type param">T</span>&gt; : <span class="type">IEnumerable</span>&lt;<span class="type param">T</span>&gt;, <span class="type">IEnumerable</span>
{
    <span class="reserved">int</span> <span class="property">Count</span> { <span class="reserved">get</span>; }
    <span class="reserved">bool</span> <span class="property">IsReadOnly</span> { <span class="reserved">get</span>; } <span class="comment">// ← これ</span>
    <span class="reserved">void</span> <span class="method">Add</span>(<span class="type param">T</span> <span class="variable local">value</span>);
    <span class="comment">// 以下略</span>
}
</pre>
<p>問題になり始めたのは C# 4.0 (2010年)で共変性を得てからでして。
読み書き両方できてしまう <code>IList&lt;T&gt;</code> や <code>ICollection&lt;T&gt;</code> では、以下のような共変な代入ができません。</p>
<pre class="source" title="書き込みがあると共変にできない">
<span class="type">IList</span>&lt;<span class="reserved">string</span>&gt; <span class="variable">str</span> <span class="operator">=</span> <span class="reserved">new</span> <span class="type">List</span>&lt;<span class="reserved">string</span>&gt;();
<span class="type">IList</span>&lt;<span class="reserved">object</span>&gt; <span class="variable">obj</span> <span class="operator">=</span> <span class="variable"><span class="error" title="CS0266">str</span></span>; <span class="comment">// ダメ。</span>

<span class="comment">// そりゃ、こういうコード書かれたらまずいので当然。</span>
<span class="variable">obj</span><span class="operator">.</span><span class="method">Add</span>(<span class="number">1</span>);
</pre>
<p>そこで .NET Framework 4.5 (2012年)では read-only 系のインターフェイスが導入されます。</p>
<pre class="source" title="read-only 系インターフェイスは共変">
<span class="type">IReadOnlyList</span>&lt;<span class="reserved">string</span>&gt; <span class="variable">str</span> <span class="operator">=</span> <span class="reserved">new</span> <span class="type">List</span>&lt;<span class="reserved">string</span>&gt; { <span class="string">&quot;abc&quot;</span> };
<span class="type">IReadOnlyList</span>&lt;<span class="reserved">object</span>&gt; <span class="variable">obj</span> <span class="operator">=</span> <span class="variable">str</span>; <span class="comment">// read-only なら共変。</span>

<span class="comment">// obj.Add(1); とか書かれる心配がない。</span>
<span class="comment">// 読むだけなら安全。</span>
<span class="static"><span class="type">Console</span></span><span class="operator">.</span><span class="method"><span class="static">WriteLine</span></span>(<span class="variable">obj</span>[<span class="number">0</span>]);
</pre>
<h2>インターフェイスへの親インターフェイスの追加・メンバー移動は破壊的変更</h2>
<p>2012年に追加された read-only 系インターフェイスですが、元々あったインターフェイスとは独立しています。
残念ながら「<code>IList&lt;T&gt;</code> は <code>IReadOnlyList&lt;T&gt;</code> ではない」という状態。</p>
<pre class="source" title="残念ながら完全に別インターフェイス">
<span class="reserved">namespace</span> System<span class="operator">.</span>Collections<span class="operator">.</span>Generic;

<span class="reserved">public</span> <span class="reserved">interface</span> <span class="type">IReadOnlyCollection</span>&lt;<span class="reserved">out</span> <span class="type param">T</span>&gt; : <span class="type">IEnumerable</span>&lt;<span class="type param">T</span>&gt;
{
    <span class="reserved">int</span> <span class="property">Count</span> { <span class="reserved">get</span>; }
}

<span class="reserved">public</span> <span class="reserved">interface</span> <span class="type">ICollection</span>&lt;<span class="type param">T</span>&gt; : <span class="type">IEnumerable</span>&lt;<span class="type param">T</span>&gt;
{
    <span class="comment">// IReadOnlyCollection とは独立に Count を持つ。</span>
    <span class="reserved">int</span> <span class="property">Count</span> { <span class="reserved">get</span>; }
    <span class="comment">// 以下略</span>
}

<span class="reserved">public</span> <span class="reserved">interface</span> <span class="type">IReadOnlyList</span>&lt;<span class="reserved">out</span> <span class="type param">T</span>&gt; : <span class="type">IReadOnlyCollection</span>&lt;<span class="type param">T</span>&gt;
{
    <span class="type param">T</span> <span class="reserved">this</span>[<span class="reserved">int</span> <span class="variable local">index</span>] { <span class="reserved">get</span>; }
}

<span class="reserved">public</span> <span class="reserved">interface</span> <span class="type">IList</span>&lt;<span class="type param">T</span>&gt; : <span class="type">ICollection</span>&lt;<span class="type param">T</span>&gt;
{
    <span class="comment">// IReadOnlyList とは独立に this[int] を持つ。</span>
    <span class="type param">T</span> <span class="reserved">this</span>[<span class="reserved">int</span> <span class="variable local">index</span>] { <span class="reserved">get</span>; <span class="reserved">set</span>; }
    <span class="comment">// 以下略</span>
}
</pre>
<p>普通に考えて、1から作るのであれば以下のようにします。</p>
<pre class="source" title="1からやり直せるならどう考えても ICollection : IReadOnlyCollection">
<span class="reserved">namespace</span> System<span class="operator">.</span>Collections<span class="operator">.</span>Generic;

<span class="reserved">public</span> <span class="reserved">interface</span> <span class="type">IReadOnlyCollection</span>&lt;<span class="reserved">out</span> <span class="type param">T</span>&gt; : <span class="type">IEnumerable</span>&lt;<span class="type param">T</span>&gt;
{
    <span class="reserved">int</span> <span class="property">Count</span> { <span class="reserved">get</span>; }
}

<span class="reserved">public</span> <span class="reserved">interface</span> <span class="type">ICollection</span>&lt;<span class="type param">T</span>&gt; : <span class="type">IReadOnlyCollection</span>&lt;<span class="type param">T</span>&gt; 
{
    <span class="comment">// 以下略</span>
}
</pre>
<p>ところが、後付けでこういうことをするのは破壊的変更になります。</p>
<p>例えば以下のようなコードがあったとします。</p>
<pre class="source" title="バージョン1">
<span class="comment">// バージョン1</span>

<span class="comment">// corelib.dll</span>
<span class="reserved">interface</span> <span class="type">ICollection</span>
{
    <span class="reserved">int</span> <span class="property">Count</span> { <span class="reserved">get</span>; }
}

<span class="comment">// corelib とは別のプロジェクトで、別の開発者が保守</span>
<span class="comment">// mylib.dll</span>
<span class="reserved">class</span> <span class="type">C</span> : <span class="type">ICollection</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> <span class="property">Count</span> <span class="operator">=&gt;</span> <span class="number">0</span>;
}
</pre>
<p>ここに <code>IReadOnlyCollection</code> を「理想的な状態」で導入したくて <code>Count</code> を移動させると mylib を壊します。</p>
<pre class="source" title="Count を IReadOnlyCollection">
<span class="comment">// バージョン2</span>

<span class="comment">// corelib.dll</span>
<span class="reserved">interface</span> <span class="type">IReadOnlyCollection</span>
{
    <span class="reserved">int</span> <span class="property">Count</span> { <span class="reserved">get</span>; }
}

<span class="reserved">interface</span> <span class="type">ICollection</span> : <span class="type">IReadOnlyCollection</span>
{
    <span class="comment">// Count は IReadOnlyCollection に移した。</span>
}

<span class="comment">// corelib とは別のプロジェクトで、別の開発者が保守</span>
<span class="comment">// mylib.dll</span>
<span class="reserved">class</span> <span class="type">C</span> : <span class="type">ICollection</span>
{
    <span class="comment">// 再コンパイルするなら平気。</span>
    <span class="comment">// ただ、古い dll のまま使うと「IReadOnlyCollection.Count がない」と怒られる。</span>
    <span class="comment">// 再コンパイルするまでは C が持ってるのは ICollection.Count。</span>
    <span class="reserved">public</span> <span class="reserved">int</span> <span class="property">Count</span> <span class="operator">=&gt;</span> <span class="number">0</span>;
}
</pre>
<p>ということでインターフェイスを独立。
これなら「再コンパイルするまでは <code>C</code> は <code>IReadOnlyCollection</code> にはならない」というだけなので、
DLL のロードに失敗したりはしません。</p>
<pre class="source" title="機能がダブるけどもこれで妥協">
<span class="comment">// corelib.dll</span>
<span class="reserved">interface</span> <span class="type">IReadOnlyCollection</span>
{
    <span class="reserved">int</span> <span class="property">Count</span> { <span class="reserved">get</span>; }
}

<span class="reserved">interface</span> <span class="type">ICollection</span>
{
    <span class="reserved">int</span> <span class="property">Count</span> { <span class="reserved">get</span>; } <span class="comment">// IReadOnlyCollection と機能がダブってるけど許して</span>
}

<span class="comment">// corelib とは別のプロジェクトで、別の開発者が保守</span>
<span class="comment">// mylib.dll</span>
<span class="reserved">class</span> <span class="type">C</span> : <span class="type">ICollection</span>, <span class="type">IReadOnlyCollection</span> <span class="comment">// 2個とも実装</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> <span class="property">Count</span> <span class="operator">=&gt;</span> <span class="number">0</span>;
}
</pre>
<p>これが .NET のコレクション系インターフェイスの現状になります。</p>
<h2>インターフェイス メソッドのデフォルト実装</h2>
<p>.NET Core 3.0 (2019年)に<a href="https://ufcpp.net/study/csharp/cheatsheet/ap_ver8/#default-imeplementation-of-interface">デフォルト実装</a>というものが導入されて、インターフェイスへのメンバー追加での破壊的変更を避けれるようになりました。</p>
<p>この機能を使えば先ほどの「既存クラスが <code>IReadOnlyCollection.Count</code> を実装していない」問題は解消できます。
(親インターフェイスの追加は、「メンバー追加」の一種なのでデフォルト実装で対処できます。)</p>
<pre class="source" title="デフォルト実装で解決">
<span class="comment">// corelib.dll</span>
<span class="reserved">interface</span> <span class="type">IReadOnlyCollection</span>
{
    <span class="reserved">int</span> <span class="property">Count</span> { <span class="reserved">get</span>; }
}

<span class="reserved">interface</span> <span class="type">ICollection</span> : <span class="type">IReadOnlyCollection</span>
{
    <span class="reserved">new</span> <span class="reserved">int</span> <span class="property">Count</span> { <span class="reserved">get</span>; } <span class="comment">// IReadOnlyCollection.Count とは別の Count にはなっちゃう。</span>

    <span class="comment">// IReadOnlyCollection のことを知らない既存クラスのために、</span>
    <span class="comment">// 既存クラスに代わって ICollection 内で IReadOnlyCollection.Count を実装。</span>
    <span class="reserved">int</span> <span class="type">IReadOnlyCollection</span><span class="operator">.</span><span class="property">Count</span> <span class="operator">=&gt;</span> <span class="property">Count</span>;
}

<span class="comment">// corelib とは別のプロジェクトで、別の開発者が保守</span>
<span class="comment">// mylib.dll</span>
<span class="reserved">class</span> <span class="type">C</span> : <span class="type">ICollection</span>
{
    <span class="comment">// 再コンパイルするまではあくまで ICollection.Count。</span>
    <span class="comment">// それでも、ICollection 側で IReadOnlyCollection.Count を実装してくれているので平気。</span>
    <span class="comment">//</span>
    <span class="comment">// ちなみに、再コンパイルするとこの Count をもって</span>
    <span class="comment">// ICollection.Count と IReadOnlyCollection.Count の両方を実装。</span>
    <span class="reserved">public</span> <span class="reserved">int</span> <span class="property">Count</span> <span class="operator">=&gt;</span> <span class="number">0</span>;
}
</pre>
<p>ということで、インターフェイスのデフォルト実装の導入後、
ついに <code>ICollection&lt;T&gt;</code> が <code>IReadOnlyCollection&lt;T&gt;</code> 派生に、
<code>IList&lt;T&gt;</code> が <code>IReadOnlyList&lt;T&gt;</code> 派生にできるのではないかと多くの期待が寄せられています。
実際、2019年に提案あり:</p>
<ul>
<li><a href="https://github.com/dotnet/runtime/issues/31001">Make mutable generic collection interfaces implement read-only collection interfaces
</a></li>
</ul>
<p>ただ、厳密にはこれも破壊的変更を起こす可能性はあったりします。
というのも、デフォルト実装には「ダイアモンド継承」問題というものがあります。
以下のような感じで、「分かれ道からの合流がある継承」をやると問題を起こすことがあります。</p>
<pre class="source" title="ダイアモンド継承問題">
<span class="reserved">interface</span> <span class="type">IA</span>
{
    <span class="reserved">int</span> <span class="method">M</span>();
}

<span class="reserved">interface</span> <span class="type">IB</span> : <span class="type">IA</span>
{
    <span class="reserved">int</span> <span class="type">IA</span><span class="operator">.</span><span class="method">M</span>() <span class="operator">=&gt;</span> <span class="number">1</span>; <span class="comment">// デフォルト実装持ち</span>
}

<span class="reserved">interface</span> <span class="type">IC</span> : <span class="type">IA</span>
{
    <span class="reserved">int</span> <span class="type">IA</span><span class="operator">.</span><span class="method">M</span>() <span class="operator">=&gt;</span> <span class="number">2</span>; <span class="comment">// デフォルト実装持ち</span>
}

<span class="comment">// IA.M の実装をデフォルト実装に頼るとして、</span>
<span class="comment">// IB の実装と IC の実装のどちらを使えばいいか不明瞭。</span>
<span class="reserved">class</span> <span class="type">C</span> : <span class="type"><span class="error" title="CS8705">IB</span></span>, <span class="type">IC</span>
{
}
</pre>
<p>まあ、前述の <code>ICollection</code> に「分かれ道」はないので誰しもがこの問題を踏むわけではないんですが。
1段自作のインターフェイスとかを挟んでいると問題を踏む可能性が出てきます。
例えば以下のような感じ。</p>
<pre class="source" title="IReadOnlyCollection.Count でダイアモンド継承問題を踏む例">
<span class="comment">// corelib とは別のプロジェクトで、別の開発者が保守</span>
<span class="comment">// anotherlib.dll</span>
<span class="reserved">interface</span> <span class="type">ICustomReadonlyList</span> : <span class="type">IReadOnlyCollection</span>
{
    <span class="comment">// 何らかのデフォルト実装持ち</span>
    <span class="reserved">int</span> <span class="type">IReadOnlyCollection</span><span class="operator">.</span><span class="property">Count</span> <span class="operator">=&gt;</span> <span class="number">0</span>;
}

<span class="comment">// corelib とも anotherlib とも別のプロジェクトで、別の開発者が保守</span>
<span class="comment">// mylib.dll</span>
<span class="reserved">class</span> <span class="type">C</span> : <span class="type"><span class="error" title="CS8705">ICollection</span></span>, <span class="type">ICustomReadonlyList</span>
{
    <span class="comment">// ICollection 更新前: </span>
    <span class="comment">//   ICollection.Count は明示的に実装</span>
    <span class="comment">//   IReadOnlyCollection.Count は ICustomReadonlyList 側のデフォルト実装を使用</span>
    <span class="comment">//</span>
    <span class="comment">// ICollection 更新後: </span>
    <span class="comment">//   ICollection.Count は明示してるから平気</span>
    <span class="comment">//   IReadOnlyCollection.Count は ICustomReadonlyList と ICollection のどちらのデフォルト実装を使えばいいかわからない</span>
    <span class="comment">//   (ソースコードも修正しないと再コンパイルも失敗)</span>
    <span class="reserved">int</span> <span class="type">ICollection</span><span class="operator">.</span><span class="property">Count</span> <span class="operator">=&gt;</span> <span class="number">1</span>;
}
</pre>
<p>この辺りの懸念もあって、しばらく塩漬けが続きます。</p>
<h2>ついに動きが</h2>
<p>そして時は流れること4年、ついに動きが。
.NET 9 でこの作業をやろうという検討に入ったみたいです。</p>
<ul>
<li>
<a href="https://github.com/dotnet/runtime/issues/31001#issuecomment-1811013088">API レビューをやった報告コメント</a>
<ul>
<li>実験を試みる準備が整った</li>
</ul>
</li>
<li>
<a href="https://github.com/dotnet/runtime/issues/31001#issuecomment-1813159725">.NET チームのプロダクト マネージャーのコメント</a>
<ul>
<li>指摘されている破壊的変更はレアケースで、考えを変えるものではないと思う</li>
<li>どの程度の破壊的変更になるか(許容できる範囲かどうか)、.NET 9 の初期に実験してみるのは十分妥当</li>
</ul>
</li>
<li><a href="https://github.com/dotnet/runtime/pull/95830">修正 Pull Request</a></li>
</ul>
 ]]></description>
				<pubDate>Sun, 03 Mar 2024 00:18:50 +0900</pubDate>
			</item>
			<item>
				<title>params コレクション</title>
				<link>http://ufcpp.net/blog/2024/3/params-collections/</link>
				<description><![CDATA[ <p><a href="https://ufcpp.net/blog/2023/2/params-ros/">ほぼ1年ぶり</a>の <a href="https://ufcpp.net/study/csharp/sp_params.html#params">params</a> の話。</p>
<p>params を配列以外のコレクションに対して使えるようにするという話ですが、
雰囲気的に C# 13 でついに 入りそうです。
なので、最近そこそこ高頻度で Language Design Meeting の議題に上がっています。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/7700">Params Collection</a></li>
<li>
C# Language Design Meeting
<ul>
<li><a href="https://github.com/dotnet/csharplang/blob/main/meetings/2023/LDM-2023-11-15.md#params-improvements">November 15th, 2023</a></li>
<li><a href="https://github.com/dotnet/csharplang/blob/main/meetings/2024/LDM-2024-01-29.md#params-collections">January 29th, 2024</a></li>
<li><a href="https://github.com/dotnet/csharplang/blob/main/meetings/2024/LDM-2024-01-31.md#params-collections-evaluation-orders">January 31st, 2024</a></li>
<li><a href="https://github.com/dotnet/csharplang/blob/main/meetings/2024/LDM-2024-02-21.md#params-collections">February 21st, 2024</a></li>
</ul>
</li>
</ul>
<p>まあ、割かしもう詳細を詰めている感じの話題が多めですね。</p>
<h2>params ‘コレクション’</h2>
<p>去年には「<code>ReadOnlySpan&lt;T&gt;</code> 以外需要低め」、「他は<a href="https://ufcpp.net/study/csharp/cheatsheet/ap_ver12/#collection-expression">コレクション式</a>を使って <code>M([a, b, c])</code> でいいのでは」などという話も出ていましたが。
コレクション式を実装した今改めて検討して、
むしろ「コレクション式とそろえるのがいいのではないか」という感じに変わったみたいです。</p>
<pre class="source" title="params コレクション(案)">
<span class="comment">// ReadOnlySpan を優先するようになる予定。</span>
<span class="type">C</span><span class="operator">.</span><span class="method"><span class="static">M</span></span>(<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>);

<span class="reserved">class</span> <span class="type">C</span>
{
    <span class="comment">// 今でも書ける。</span>
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">M</span></span>(<span class="reserved">params</span> <span class="reserved">int</span>[] <span class="variable local">_</span>) { }

    <span class="comment">// 新規に書けるようになる予定。</span>
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">M</span></span>(<span class="reserved"><span class="error" title="CS0225">params</span></span> <span class="type">List</span>&lt;<span class="reserved">int</span>&gt; <span class="variable local">_</span>) { }
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">M</span></span>(<span class="reserved"><span class="error" title="CS0225">params</span></span> <span class="type struct">ReadOnlySpan</span>&lt;<span class="reserved">int</span>&gt; <span class="variable local">_</span>) { }
}
</pre>
<h2>params ‘ref struct’</h2>
<p>params に配列以外の型を認めたいという話の前提には、パフォーマンスを改善したいという要求があります。
なので、<code>Span</code> や <code>ReadOnlySpan</code> をはじめとした <a href="https://ufcpp.net/study/csharp/resource/refstruct/">ref struct</a> を使いたいです(ref struct 自体がパフォーマンス改善のために導入された概念)。</p>
<p>で、ref struct にはスコープの概念があって、引数や変数を <a href="https://ufcpp.net/study/csharp/resource/refstruct/#scoped"><code>scoped</code></a> で修飾するかどうかでちょっと挙動が変わります。</p>
<pre class="source" title="scoped の有無">
<span class="static"><span class="method">M</span></span>(<span class="reserved">true</span>);

<span class="reserved">static</span> <span class="type struct">S</span> <span class="method"><span class="static">M</span></span>(<span class="reserved">bool</span> <span class="variable local">b</span>)
{
    <span class="control">if</span>(<span class="variable local">b</span>)
    {
        <span class="comment">// [] が作る Span が S に伝搬してて、外に漏らせないので return に渡すとエラー。</span>
        <span class="control">return</span> <span class="error" title="CS8347"><span class="type">C</span><span class="operator">.</span><span class="static"><span class="method">Unscoped</span></span>(<span class="error" title="CS9203">[<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>]</span>)</span>;
    }
    <span class="control">else</span>
    {
        <span class="comment">// こちらは Span が伝搬しないので return できる。</span>
        <span class="control">return</span> <span class="type">C</span><span class="operator">.</span><span class="static"><span class="method">Scoped</span></span>([<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>]);
    }
}

<span class="reserved">class</span> <span class="type">C</span>
{
    <span class="comment">// span の寿命が S に伝搬する。</span>
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="type struct">S</span> <span class="static"><span class="method">Unscoped</span></span>(<span class="type struct">Span</span>&lt;<span class="reserved">int</span>&gt; <span class="variable local">span</span>) <span class="operator">=&gt;</span> <span class="reserved">new</span>(<span class="variable local">span</span>);

    <span class="comment">// span の寿命を外に漏らさない。</span>
    <span class="comment">// なので、S に直接伝搬できない。</span>
    <span class="comment">// new(span.ToArray()) とかする必要がある。</span>
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="type struct">S</span> <span class="static"><span class="method">Scoped</span></span>(<span class="reserved">scoped</span> <span class="type struct">Span</span>&lt;<span class="reserved">int</span>&gt; <span class="variable local">span</span>) <span class="operator">=&gt;</span> <span class="error" title="CS8347"><span class="reserved">new</span>(<span class="error" title="CS8352"><span class="variable local">span</span></span>)</span>;
}

<span class="reserved">readonly</span> <span class="reserved">ref</span> <span class="reserved">struct</span> <span class="type struct">S</span>(<span class="type struct">Span</span>&lt;<span class="reserved">int</span>&gt; <span class="variable local">span</span>)
{
    <span class="reserved">public</span> <span class="reserved">readonly</span> <span class="type struct">Span</span>&lt;<span class="reserved">int</span>&gt; <span class="field">Span</span> <span class="operator">=</span> <span class="variable local">span</span>;
}
</pre>
<p>で、ここに params をつけれるようになった場合にどうするかという話になります。</p>
<p>まあ、現状出ている用途を考えると「scoped じゃない params を必要とする場面はなく、scoped な params を必要とする場面はある」とのことで、「params が付いている時点で暗黙的に scoped にする」という判断になりそうです。</p>
<p>こうなるともう1つ問題が、オーバーライドをどうするかという話があるみたいです。
というのも、params 配列の場合、実はオーバーライド側には params 修飾を付けなくてもいいそうで。</p>
<pre class="source" title="params 配列のオーバーライドには params 修飾不要">
<span class="reserved">class</span> <span class="type">Base</span>
{
    <span class="reserved">public</span> <span class="reserved">virtual</span> <span class="reserved">void</span> <span class="method">M</span>(<span class="reserved">params</span> <span class="reserved">int</span>[] <span class="variable local">x</span>) { }
}

<span class="reserved">class</span> <span class="type">Derived</span> : <span class="type">Base</span>
{
    <span class="comment">// params 配列の場合、派生側で params を付けなくても別にいい。</span>
    <span class="reserved">public</span> <span class="reserved">override</span> <span class="reserved">void</span> <span class="method">M</span>(<span class="reserved">int</span>[] <span class="variable local">x</span>) { }
}
</pre>
<p>ところがまあ、「params ref strcut は暗黙的に scoped」みたいな暗黙の挙動があるので、
「何もつけてないのになぜか scoped」みたいな挙動は避けたいでしょう。
なので、この場合は「オーバーライド側にも params を必須にしたい」とのこと。</p>
<p>(けど、<a href="https://github.com/dotnet/csharplang/blob/main/meetings/2024/LDM-2024-02-21.md#params-and-scoped-across-overrides">LDM に挙げられている例</a>を見るに、戻り値があるときにだけこれを求められていそう…)</p>
<h2>オーバーロード解決</h2>
<p>現在の params (配列の <code>params T[]</code>)とコレクション式は、ちょっとオーバーロード解決の仕組みが違います。
なので、「params の部分を <code>[]</code> で覆っても同じ結果になる」というのは<strong>成り立たない</strong>ことになります。
例えば以下のようなもの。</p>
<pre class="source" title="params と []">
<span class="type">C</span><span class="operator">.</span><span class="method"><span class="error" title="CS0121"><span class="static">M</span></span></span>([<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>]); <span class="comment">// こちらは解決できなくてエラーに。</span>
<span class="type">C</span><span class="operator">.</span><span class="method"><span class="static">M</span></span>(<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>); <span class="comment">// こちらは int[] 側に解決。</span>

<span class="reserved">class</span> <span class="type">C</span>
{
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">M</span></span>(<span class="reserved">params</span> <span class="reserved">int</span>[] <span class="variable local">_</span>) { }
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">M</span></span>(<span class="reserved">params</span> <span class="reserved">long</span>[] <span class="variable local">_</span>) { }
}
</pre>
<p>で、params コレクションに関してですが、「既存の params 配列に沿う」案で行くみたいです。</p>
<h2>引数の評価順</h2>
<p>引数に副作用のある式を渡さない限り問題になることは少ないので忘れがちですが、
引数をどういう順で評価するかは決めておかないと混乱のもとです。
C# は基本的に「呼び出し側で並べた順」で、例えば名前付き引数を使うと順序を変えることができたりします。</p>
<pre class="source" title="引数の評価は並べた順">
<span class="method"><span class="static">Test</span></span>(<span class="static"><span class="method">GetA</span></span>(), <span class="static"><span class="method">GetB</span></span>()); <span class="comment">// A → B</span>
<span class="method"><span class="static">Test</span></span>(<span class="variable local">b</span>: <span class="static"><span class="method">GetB</span></span>(), <span class="variable local">a</span>: <span class="static"><span class="method">GetA</span></span>()); <span class="comment">// B → A</span>

<span class="reserved">static</span> <span class="reserved">void</span> <span class="static"><span class="method">Test</span></span>(<span class="reserved">int</span> <span class="variable local">a</span>, <span class="reserved">int</span> <span class="variable local">b</span>) { }

<span class="reserved">static</span> <span class="reserved">int</span> <span class="method"><span class="static">GetA</span></span>() { <span class="static"><span class="type">Console</span></span><span class="operator">.</span><span class="method"><span class="static">WriteLine</span></span>(<span class="string">&quot;A&quot;</span>); <span class="control">return</span> <span class="number">0</span>; }
<span class="reserved">static</span> <span class="reserved">int</span> <span class="static"><span class="method">GetB</span></span>() { <span class="static"><span class="type">Console</span></span><span class="operator">.</span><span class="method"><span class="static">WriteLine</span></span>(<span class="string">&quot;B&quot;</span>); <span class="control">return</span> <span class="number">0</span>; }
</pre>
<p>で、名前付き引数を使うと params 引数の場所も末尾以外に移せたり。</p>
<pre class="source" title="params 引数を真ん中に。GetC の評価順も真ん中に">
<span class="static"><span class="method">Test</span></span>(<span class="variable local">b</span>: <span class="static"><span class="method">GetB</span></span>(), <span class="variable local">c</span>: <span class="method"><span class="static">GetC</span></span>(), <span class="variable local">a</span>: <span class="method"><span class="static">GetA</span></span>()); <span class="comment">// B → C → A</span>

<span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">Test</span></span>(<span class="reserved">int</span> <span class="variable local">a</span>, <span class="reserved">int</span> <span class="variable local">b</span>, <span class="reserved">params</span> <span class="reserved">int</span>[] <span class="variable local">c</span>) { }

<span class="reserved">static</span> <span class="reserved">int</span> <span class="method"><span class="static">GetA</span></span>() { <span class="type"><span class="static">Console</span></span><span class="operator">.</span><span class="method"><span class="static">WriteLine</span></span>(<span class="string">&quot;A&quot;</span>); <span class="control">return</span> <span class="number">0</span>; }
<span class="reserved">static</span> <span class="reserved">int</span> <span class="static"><span class="method">GetB</span></span>() { <span class="static"><span class="type">Console</span></span><span class="operator">.</span><span class="static"><span class="method">WriteLine</span></span>(<span class="string">&quot;B&quot;</span>); <span class="control">return</span> <span class="number">0</span>; }
<span class="reserved">static</span> <span class="reserved">int</span> <span class="method"><span class="static">GetC</span></span>() { <span class="static"><span class="type">Console</span></span><span class="operator">.</span><span class="method"><span class="static">WriteLine</span></span>(<span class="string">&quot;C&quot;</span>); <span class="control">return</span> <span class="number">0</span>; }
</pre>
<p>ちなみにこの時、<code>params int[] c</code> のための配列は、<code>Test</code> を呼ぶ直前になるそうです。
ということで、展開結果は以下のような感じ。</p>
<pre class="source" title="先ほどのコードの展開結果">
<span class="reserved">var</span> <span class="variable">b</span> <span class="operator">=</span> <span class="static"><span class="method">GetB</span></span>();
<span class="reserved">var</span> <span class="variable">c</span> <span class="operator">=</span> <span class="static"><span class="method">GetC</span></span>();
<span class="reserved">var</span> <span class="variable">a</span> <span class="operator">=</span> <span class="static"><span class="method">GetA</span></span>();
<span class="reserved">var</span> <span class="variable">paramsC</span> <span class="operator">=</span> <span class="reserved">new</span>[] { <span class="variable">c</span> };
<span class="static"><span class="method">Test</span></span>(<span class="variable">a</span>, <span class="variable">b</span>, <span class="variable">paramsC</span>);
</pre>
<p>ところが、params コレクションとなるとどうなるべきかという話になります。
コレクションのインスタンスはいつ作られるべきなのか。</p>
<pre class="source" title="params を自作の型に変更">
<span class="method"><span class="static">Test</span></span>(<span class="variable local">b</span>: <span class="static"><span class="method">GetB</span></span>(), <span class="variable local">c</span>: <span class="method"><span class="static">GetC</span></span>(), <span class="variable local">a</span>: <span class="static"><span class="method">GetA</span></span>());

<span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">Test</span></span>(<span class="reserved">int</span> <span class="variable local">a</span>, <span class="reserved">int</span> <span class="variable local">b</span>, <span class="reserved">params</span> <span class="type">MyCollection</span> <span class="variable local">c</span>) { }

<span class="reserved">static</span> <span class="reserved">int</span> <span class="method"><span class="static">GetA</span></span>() { <span class="type"><span class="static">Console</span></span><span class="operator">.</span><span class="static"><span class="method">WriteLine</span></span>(<span class="string">&quot;A&quot;</span>); <span class="control">return</span> <span class="number">0</span>; }
<span class="reserved">static</span> <span class="reserved">int</span> <span class="static"><span class="method">GetB</span></span>() { <span class="type"><span class="static">Console</span></span><span class="operator">.</span><span class="static"><span class="method">WriteLine</span></span>(<span class="string">&quot;B&quot;</span>); <span class="control">return</span> <span class="number">0</span>; }
<span class="reserved">static</span> <span class="reserved">int</span> <span class="static"><span class="method">GetC</span></span>() { <span class="type"><span class="static">Console</span></span><span class="operator">.</span><span class="static"><span class="method">WriteLine</span></span>(<span class="string">&quot;C&quot;</span>); <span class="control">return</span> <span class="number">0</span>; }

<span class="reserved">class</span> <span class="type">MyCollection</span> : <span class="type">IEnumerable</span>&lt;<span class="reserved">int</span>&gt;
{
    <span class="reserved">public</span> <span class="type">MyCollection</span>() { <span class="type"><span class="static">Console</span></span><span class="operator">.</span><span class="method"><span class="static">WriteLine</span></span>(<span class="string">&quot;MyCollection Construcotr&quot;</span>); }
    <span class="reserved">public</span> <span class="reserved">void</span> <span class="method">Add</span>(<span class="reserved">int</span> <span class="variable local">_</span>) { }
    <span class="reserved">public</span> <span class="type">IEnumerator</span>&lt;<span class="reserved">int</span>&gt; <span class="method">GetEnumerator</span>() <span class="operator">=&gt;</span> <span class="control">throw</span> <span class="reserved">new</span> <span class="type">NotImplementedException</span>();
    System<span class="operator">.</span>Collections<span class="operator">.</span><span class="type">IEnumerator</span> System<span class="operator">.</span>Collections<span class="operator">.</span><span class="type">IEnumerable</span><span class="operator">.</span><span class="method">GetEnumerator</span>() <span class="operator">=&gt;</span> <span class="control">throw</span> <span class="reserved">new</span> <span class="type">NotImplementedException</span>();
}
</pre>
<p>こんな副作用の起こし方をするコードはめったに書かないでしょうけども、
&quot;MyCollection Construcotr&quot; はいつ表示されるべきでしょう？</p>
<p>とりあえず現状は、B → MyCollection → C → A の順で考えているそうです。
引数 <code>c:</code> の場所で生成。<code>GetC</code> を呼ぶよりも前。
要するに、以下のように展開したいんでしょうね。</p>
<pre class="source" title="params 部分の展開の例">
<span class="reserved">var</span> <span class="variable">b</span> <span class="operator">=</span> <span class="static"><span class="method">GetB</span></span>();
<span class="reserved">var</span> <span class="variable">a</span> <span class="operator">=</span> <span class="method"><span class="static">GetA</span></span>();
<span class="reserved">var</span> <span class="variable">paramsC</span> <span class="operator">=</span> <span class="reserved">new</span> <span class="type">MyCollection</span>();
<span class="variable">paramsC</span><span class="operator">.</span><span class="method">Add</span>(<span class="method"><span class="static">GetC</span></span>());
<span class="method"><span class="static">Test</span></span>(<span class="variable">a</span>, <span class="variable">b</span>, <span class="variable">paramsC</span>);
</pre>
<h2>メタデータ</h2>
<p>今ある params 配列のコンパイル結果には <code>System.ParamArrayAttribute</code> が付きます。
で、C# 13 で考えている params コレクションでも、別にこの属性を使いまわすこともできるそうです。</p>
<p>ただ1点懸念は、C# 以外のコンパイラーが誤動作しないかどうか。
新しい属性であれば「未対応なので無視」でいいわけですが、
既存の属性を使いまわすと「<code>ParamArray</code> 属性が付いているのであれば配列でないとダメ」というコンパイル エラーを起こす可能性が高いです。</p>
<p>ということで、新しい params コレクションについては新しい属性として <code>System.Runtime.CompilerServices.ParamCollectionAttribute</code> を用意するそうです。</p>
 ]]></description>
				<pubDate>Sat, 02 Mar 2024 17:44:41 +0900</pubDate>
			</item>
			<item>
				<title>ラムダ式の引数で、型名を省略して ref, out などだけを指定</title>
				<link>http://ufcpp.net/blog/2024/2/ref-out-lambda-params/</link>
				<description><![CDATA[ <p>ラムダ式で、<code>ref</code> 引数などに対して <code>ref x =&gt; { }</code> みたいに書けるようにしたいという話が出ています。</p>
<h2>ラムダ式での ref 引数、out 引数</h2>
<p>ラムダ式は、状況が許すなら、<code>x =&gt; { }</code> などといったように非常に簡素に書けます。
ところが、<a href="https://ufcpp.net/study/csharp/sp_ref.html#sec-byref"><code>ref</code></a> や <a href="https://ufcpp.net/study/csharp/sp_ref.html#out"><code>out</code></a> が絡むとそうもいかなくて、型推論が効く状況でも型名を省略できません。</p>
<pre class="source" title="ref, out などが絡むと型名の省略ができない">
<span class="comment">// 通常、ラムダ式は型推論が効く限り、引数の型を省略できる。</span>
<span class="type">Action</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">a</span> <span class="operator">=</span> <span class="variable local">x</span> <span class="operator">=&gt;</span> { };

<span class="comment">// ところが ref, out などの修飾が付いた引数は省略不可。</span>

<span class="comment">// これなら OK。</span>
<span class="type">RefAction</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">r</span> <span class="operator">=</span> (<span class="reserved">ref</span> <span class="reserved">int</span> <span class="variable local">x</span>) <span class="operator">=&gt;</span> { };
<span class="type">OutFunc</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">o</span> <span class="operator">=</span> (<span class="reserved">out</span> <span class="reserved">int</span> <span class="variable local">x</span>) <span class="operator">=&gt;</span> <span class="variable local">x</span> <span class="operator">=</span> <span class="number">1</span>;

<span class="comment">// ダメ。CS1676 エラー。</span>
<span class="type">RefAction</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">r1</span> <span class="operator">=</span> <span class="error" title="CS1676"><span class="variable local">x</span></span> <span class="operator">=&gt;</span> { };
<span class="type">OutFunc</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">o1</span> <span class="operator">=</span> <span class="variable local"><span class="error" title="CS1676">x</span></span> <span class="operator">=&gt;</span> <span class="variable local">x</span> <span class="operator">=</span> <span class="number">1</span>;

<span class="reserved">delegate</span> <span class="reserved">void</span> <span class="type">RefAction</span>&lt;<span class="type param">T</span>&gt;(<span class="reserved">ref</span> <span class="type param">T</span> <span class="variable local">arg</span>);
<span class="reserved">delegate</span> <span class="reserved">void</span> <span class="type">OutFunc</span>&lt;<span class="type param">T</span>&gt;(<span class="reserved">out</span> <span class="type param">T</span> <span class="variable local">arg</span>);
</pre>
<p>特に、「他にも引数が多かったり、他の引数のどれかに型名が長くて書きたくない引数がある」みたいな状況では相当に不便です。</p>
<pre class="source" title="引数が多くて型の省略したい…">
<span class="comment">// 全部の引数に型の明示が必要。</span>
<span class="type">ManyParams</span> <span class="variable">a</span> <span class="operator">=</span> (<span class="reserved">int</span> <span class="variable local">x</span>, <span class="reserved">int</span> <span class="variable local">y</span>, <span class="reserved">int</span> <span class="variable local">z</span>, <span class="reserved">ref</span> <span class="reserved">int</span> <span class="variable local">r</span>) <span class="operator">=&gt;</span> { };

<span class="comment">// r の型は省略できない。</span>
<span class="type">ManyParams</span> <span class="variable">a1</span> <span class="operator">=</span> (<span class="variable local">x</span>, <span class="variable local">y</span>, <span class="variable local">z</span>, <span class="error" title="CS1676"><span class="variable local">r</span></span>) <span class="operator">=&gt;</span> { };

<span class="comment">// 「部分的に型を明示」というのも書けない。</span>
<span class="type">ManyParams</span> <span class="variable">a2</span> <span class="operator">=</span> (<span class="variable local">x</span>, <span class="variable local">y</span>, <span class="variable local">z</span>, <span class="reserved">ref</span> <span class="reserved"><span class="error" title="CS0748">int</span></span> <span class="variable local"><span class="error" title="CS1676">r</span></span>) <span class="operator">=&gt;</span> { };

<span class="reserved">delegate</span> <span class="reserved">void</span> <span class="type">ManyParams</span>(<span class="reserved">int</span> <span class="variable local">x</span>, <span class="reserved">int</span> <span class="variable local">y</span>, <span class="reserved">int</span> <span class="variable local">z</span>, <span class="reserved">ref</span> <span class="reserved">int</span> <span class="variable local">r</span>);
</pre>
<pre class="source" title="型名が長くて省略したい…">
<span class="comment">// 全部の引数に型の明示が必要。</span>
<span class="type">LongTypeName</span> <span class="variable">a</span> <span class="operator">=</span> (<span class="type">IReadOnlyDictionary</span>&lt;(<span class="reserved">int</span> x, <span class="reserved">int</span> y), <span class="type">List</span>&lt;<span class="reserved">string</span>[,]&gt;&gt; <span class="variable local">x</span>, <span class="reserved">ref</span> <span class="reserved">int</span> <span class="variable local">r</span>) <span class="operator">=&gt;</span> { };

<span class="comment">// r の型は省略できない。</span>
<span class="type">LongTypeName</span> <span class="variable">a1</span> <span class="operator">=</span> (<span class="variable local">x</span>, <span class="variable local"><span class="error" title="CS1676">r</span></span>) <span class="operator">=&gt;</span> { };

<span class="comment">// 「部分的に型を明示」というのも書けない。</span>
<span class="type">LongTypeName</span> <span class="variable">a2</span> <span class="operator">=</span> (<span class="variable local">x</span>, <span class="reserved">ref</span> <span class="reserved"><span class="error" title="CS0748">int</span></span> <span class="variable local"><span class="error" title="CS1676">r</span></span>) <span class="operator">=&gt;</span> { };

<span class="reserved">delegate</span> <span class="reserved">void</span> <span class="type">LongTypeName</span>(<span class="type">IReadOnlyDictionary</span>&lt;(<span class="reserved">int</span> x, <span class="reserved">int</span> y), <span class="type">List</span>&lt;<span class="reserved">string</span>[,]&gt;&gt; <span class="variable local">x</span>, <span class="reserved">ref</span> <span class="reserved">int</span> <span class="variable local">r</span>);
</pre>
<p>これに対して、<code>ref x =&gt; { }</code> みたいな書き方は認めてもいいんじゃない？という話があります。</p>
<pre class="source" title="ref x, out x なら型名省略できてもいいのでは？">
<span class="comment">// 現状ダメ。でも、これくらいはできてもいいのでは？</span>
<span class="type">RefAction</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">r</span> <span class="operator">=</span> (<span class="reserved">ref</span> <span class="error" title="CS0246">x</span><span class="error" title="CS1001">)</span> <span class="operator">=&gt;</span> { };
<span class="type">OutFunc</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">o</span> <span class="operator">=</span> (<span class="reserved">out</span> <span class="error" title="CS0246">x</span><span class="error" title="CS1001">)</span> <span class="operator">=&gt;</span> <span class="error" title="CS0177">x <span class="operator">=</span> <span class="number">1</span></span>;
<span class="type">ManyParams</span> <span class="variable">m</span> <span class="operator">=</span> (<span class="variable local">x</span>, <span class="variable local">y</span>, <span class="variable local">z</span>, <span class="reserved">ref</span> <span class="error" title="CS0118"><span class="variable">r</span></span>) <span class="operator">=&gt;</span> { };
<span class="type">LongTypeName</span> <span class="variable">l</span> <span class="operator">=</span> (<span class="variable local">x</span>, <span class="reserved">ref</span> <span class="variable"><span class="error" title="CS0118">r</span></span>) <span class="operator">=&gt;</span> { };

<span class="reserved">delegate</span> <span class="reserved">void</span> <span class="type">RefAction</span>&lt;<span class="type param">T</span>&gt;(<span class="reserved">ref</span> <span class="type param">T</span> <span class="variable local">arg</span>);
<span class="reserved">delegate</span> <span class="reserved">void</span> <span class="type">OutFunc</span>&lt;<span class="type param">T</span>&gt;(<span class="reserved">out</span> <span class="type param">T</span> <span class="variable local">arg</span>);
<span class="reserved">delegate</span> <span class="reserved">void</span> <span class="type">ManyParams</span>(<span class="reserved">int</span> <span class="variable local">x</span>, <span class="reserved">int</span> <span class="variable local">y</span>, <span class="reserved">int</span> <span class="variable local">z</span>, <span class="reserved">ref</span> <span class="reserved">int</span> <span class="variable local">r</span>);
<span class="reserved">delegate</span> <span class="reserved">void</span> <span class="type">LongTypeName</span>(<span class="type">IReadOnlyDictionary</span>&lt;(<span class="reserved">int</span> x, <span class="reserved">int</span> y), <span class="type">List</span>&lt;<span class="reserved">string</span>[,]&gt;&gt; <span class="variable local">x</span>, <span class="reserved">ref</span> <span class="reserved">int</span> <span class="variable local">r</span>);
</pre>
<h2>コミュニティ提案</h2>
<p>実際アイディア自体は2015年くらいからずっとあります。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/338">Declaration of ref/out parameters in lambdas without typename #338</a></li>
</ul>
<p><code>ref</code> 引数ラムダ式とか自体が使用頻度低めなのでそれほど優先度はついておらず、
ずっと「Any Time」(C# チーム自らはやらず、「コミュニティ貢献お待ちしております」状態)でした。</p>
<p>これに対して、去年くらいに実際、コミュニティからの提案ドキュメントが上がっていました。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/blob/main/proposals/ref-out-lambda-params.md">Declaration of lambda parameters with modifiers without type name</a></li>
</ul>
<p><a href="https://github.com/dotnet/csharplang/commits/main/proposals/ref-out-lambda-params.md">履歴</a>)を見るに、2023年7～8月くらいにコミュニティから提案されていて、C# 12 作業中は進捗なし。
今月に入ってから C# チームの中の人が引き取って検討を始めていそうな感じですね。</p>
<p>そして<a href="https://github.com/dotnet/csharplang/blob/main/meetings/2024/LDM-2024-02-21.md">数日前の Language Design Meeting</a> で議題に。
とりあえず提案は承認されたみたいです。</p>
<h2>その他検討事項</h2>
<p>Desing Meeting では対案も2点ほど検討されたんですがそちらはリジェクト。
元の提案の方向で受け付けるみたいです。</p>
<p>対案その1は、<code>x =&gt; { }</code> だけで <code>ref</code>/<code>out</code> も「推論」してもいいのでは？という案。
ただ、C# の <code>ref</code> 引数、<code>out</code> 引数は、呼び出し元にも <code>ref</code>/<code>out</code> の明示を求めるくらいなので、さすがに <code>x =&gt; { }</code> というような書き方はちょっと C# 的には違和感があります(なのでリジェクト)。</p>
<pre class="source" title="呼び出し元にも ref/out の明示が必須">
<span class="type">RefAction</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">r</span> <span class="operator">=</span> (<span class="reserved">ref</span> <span class="reserved">int</span> <span class="variable local">x</span>) <span class="operator">=&gt;</span> { };
<span class="type">OutFunc</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">o</span> <span class="operator">=</span> (<span class="reserved">out</span> <span class="reserved">int</span> <span class="variable local">x</span>) <span class="operator">=&gt;</span> <span class="variable local">x</span> <span class="operator">=</span> <span class="number">1</span>;

<span class="comment">// ref, out 引数は呼び出し側にも ref, out を書く必要があるくらい明示を求められる。</span>
<span class="comment">// 呼び出し先で書き変わるのは明示されないと怖い。</span>
<span class="reserved">int</span> <span class="variable">local</span>;
<span class="variable">o</span>(<span class="reserved">out</span> <span class="variable">local</span>);
<span class="variable">r</span>(<span class="reserved">ref</span> <span class="variable">local</span>);

<span class="comment">// なのでラムダ式側でも ref, out は書かないと違和感。</span>
<span class="comment">// 以下のような書き方は今後も乗り気ではない。</span>
<span class="type">RefAction</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">r1</span> <span class="operator">=</span> <span class="variable local"><span class="error" title="CS1676">x</span></span> <span class="operator">=&gt;</span> { };
<span class="type">OutFunc</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">o1</span> <span class="operator">=</span> <span class="variable local"><span class="error" title="CS1676">x</span></span> <span class="operator">=&gt;</span> <span class="variable local">x</span> <span class="operator">=</span> <span class="number">1</span>;

<span class="reserved">delegate</span> <span class="reserved">void</span> <span class="type">RefAction</span>&lt;<span class="type param">T</span>&gt;(<span class="reserved">ref</span> <span class="type param">T</span> <span class="variable local">arg</span>);
<span class="reserved">delegate</span> <span class="reserved">void</span> <span class="type">OutFunc</span>&lt;<span class="type param">T</span>&gt;(<span class="reserved">out</span> <span class="type param">T</span> <span class="variable local">arg</span>);
</pre>
<p>対案その2は前述の <code>ManyParams</code> とか <code>LongTypeName</code> とかの例で書いたような、「引数の一部分の型名を省略、一部分を明示」です。
ただ、これは「<code>r</code> に指定した型から <code>x</code> の型を推論」みたいな別の要望が加わるだろうことと、
それをやると<a href="https://ufcpp.net/blog/2024/2/partial-inference/">部分型推論</a>の話と同様、
推論を頑張ろうとすると指数的なコンパイル時間になってしまう可能性があってちょっと怖いそうです(なのでリジェクト、やるとしても部分型推論と一緒に)。</p>
<pre class="source" title="ラムダ式引数の部分型指定は型推論が複雑になりそう">
<span class="comment">// ラムダ式引数の部分型指定 + 型引数の推論。</span>
<span class="comment">// 結構推論機構が複雑になるはず。</span>
<span class="reserved">static</span> <span class="type">ManyParams</span>&lt;<span class="type param">T</span>&gt; <span class="method"><span class="warning" title="CS8321"><span class="static">Create</span></span></span>&lt;<span class="type param">T</span>&gt;(<span class="type">ManyParams</span>&lt;<span class="type param">T</span>&gt; <span class="variable local">a</span>) <span class="operator">=&gt;</span> <span class="variable local">a</span>;
<span class="reserved">var</span> <span class="variable">a1</span> <span class="operator">=</span> <span class="static"><span class="method"><span class="error" title="CS0411">Create</span></span></span>((<span class="variable local">x</span>, <span class="variable local">y</span>, <span class="variable local">z</span>, <span class="reserved">ref</span> <span class="error" title="CS0748"><span class="reserved">int</span></span> <span class="variable local">r</span>) <span class="operator">=&gt;</span> { });

<span class="reserved">delegate</span> <span class="reserved">void</span> <span class="type">ManyParams</span>&lt;<span class="type param">T</span>&gt;(<span class="type param">T</span> <span class="variable local">x</span>, <span class="type param">T</span> <span class="variable local">y</span>, <span class="type param">T</span> <span class="variable local">z</span>, <span class="reserved">ref</span> <span class="type param">T</span> <span class="variable local">r</span>);
</pre>
<p>あと、元の提案に残っていた「属性や、引数のデフォルト値はどうしよう？」という未解決の議題についても「大変そうなわりに需要がない」ということで、やらないことになりそうです。</p>
<pre class="source" title="属性やデフォルト値が付いているときの型省略">
<span class="reserved">using</span> System<span class="operator">.</span>Diagnostics<span class="operator">.</span>CodeAnalysis;

<span class="comment">// C# 10 と 12 で、こんな感じで属性を付けたりデフォルト値を指定できるようになった。</span>
<span class="type">Func</span>&lt;<span class="reserved">string</span>, <span class="reserved">int</span>&gt; <span class="variable">f</span> <span class="operator">=</span> <span class="warning" title="CS8622">([<span class="type">MaybeNull</span>] <span class="reserved">string</span> <span class="variable local"><span class="warning" title="CS9099">s</span></span> <span class="operator">=</span> <span class="warning" title="CS8625"><span class="reserved">null</span></span>) <span class="operator">=&gt;</span></span> <span class="variable local">s</span><span class="operator">?</span><span class="operator">.</span><span class="property">Length</span> <span class="operator">??</span> <span class="number">0</span>;

<span class="comment">// これに対して型名省略したい？</span>
<span class="comment">// (そんなに需要なさそうな割に、これを実装するのは大変そう。)</span>
<span class="type">Func</span>&lt;<span class="reserved">string</span>, <span class="reserved">int</span>&gt; <span class="variable">f1</span> <span class="operator">=</span> <span class="warning" title="CS8622">([<span class="type">MaybeNull</span>] <span class="variable local"><span class="error" title="CS9098">s</span></span> <span class="operator">=</span> <span class="reserved">null</span>) <span class="operator">=&gt;</span></span> <span class="variable local">s</span><span class="operator">?</span><span class="operator">.</span><span class="property">Length</span> <span class="operator">??</span> <span class="number">0</span>;
</pre> ]]></description>
				<pubDate>Sun, 25 Feb 2024 22:53:14 +0900</pubDate>
			</item>
			<item>
				<title>field, value を文脈キーワード化</title>
				<link>http://ufcpp.net/blog/2024/2/value-as-context-keyword/</link>
				<description><![CDATA[ <p>C# 13 向けに検討されている機能の一つに、
「半自動プロパティ」とか「field キーワード」と呼ばれているものがあります。
元々は C# 12 向けに考えられていて、去年、うちのブログでも書いているやつです。</p>
<ul>
<li><a href="https://ufcpp.net/blog/2023/1/semi-auto-property/">【C# 12 候補】半自動プロパティ</a></li>
</ul>
<p>簡単におさらいすると、
プロパティの <code>get</code>/<code>set</code> アクセサー内で、<code>field</code> を使って
<a href="https://ufcpp.net/study/csharp/oo_property.html#auto">バッキング フィールド</a>(自動プロパティの値を保存するためにコンパイラーが生成するフィールド)に明示的にアクセスするというものです。</p>
<pre class="source" title="半自動プロパティ案">
<span class="reserved">class</span> <span class="type">A</span>
{
    <span class="comment">// 手動プロパティ (manual property)</span>
    <span class="comment">// (と、自前で用意したフィールド)。</span>
    <span class="comment">// こういう、プロパティからほぼ素通しで値を記録しているフィールドを「バッキング フィールド」(backing field)という。</span>
    <span class="reserved">private</span> <span class="reserved">int</span> <span class="field">_x</span>;
    <span class="reserved">public</span> <span class="reserved">int</span> <span class="property">X</span> { <span class="reserved">get</span> <span class="operator">=&gt;</span> <span class="field">_x</span>; <span class="reserved">set</span> <span class="operator">=&gt;</span> <span class="field">_x</span> <span class="operator">=</span> <span class="reserved">value</span>; }

    <span class="comment">// 自動プロパティ (auto-property)。</span>
    <span class="comment">// 前述の X とほぼ一緒。</span>
    <span class="comment">// バッキング フィールドの自動生成。</span>
    <span class="reserved">public</span> <span class="reserved">int</span> <span class="property">Y</span> { <span class="reserved">get</span>; <span class="reserved">set</span>; }

    <span class="comment">// 【C# 12 候補(改め、13 候補)】 半自動プロパティ (semi-auto-property)。</span>
    <span class="comment">// バッキング フィールドは自動生成。</span>
    <span class="comment">// 全自動の方と違って、バッキング フィールドの使い方は自由にできる。</span>
    <span class="comment">// field キーワードでバッキング フィールドを読み書き。</span>
    <span class="reserved">public</span> <span class="reserved">int</span> <span class="property">Z</span> { <span class="reserved">get</span> <span class="operator">=&gt;</span> <span class="reserved">field</span>; <span class="reserved">set</span> <span class="operator">=&gt;</span> <span class="reserved">field</span> <span class="operator">=</span> <span class="reserved">value</span>; }
}
</pre>
<p>C# 12 時点では「これを破壊的変更なしで実装するのは大変」ということで見送りになりまして、
その結果検討されていたのが先日書いたブログの話。</p>
<ul>
<li><a href="https://ufcpp.net/blog/2024/2/breaking-changes/">C# での破壊的変更の今後の扱い (続報)</a></li>
</ul>
<p>ここで、「<code>field</code> の扱いで破壊的変更があるんだったら、<code>value</code> についても…」
という話が出ています。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/7964">[Proposal]: Field and value as contextual keywords #7964</a></li>
</ul>
<p>というのも、<code>value</code> (プロパティの <code>set</code> 内でだけ特別な意味を持つ)はちょっと C# 的には珍しく、
キーワードではなくて「暗黙に定義された引数」で、ちょっと浮いた挙動をします。</p>
<p>1つ目、<a href="https://ufcpp.net/study/csharp/st_variable.html#identifier"><code>@</code> で「脱キーワード化」</a>ができない。</p>
<pre class="source" title="キーワードじゃないので…">
<span class="reserved">class</span> <span class="type">A</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> <span class="property">X</span>
    {
        <span class="reserved">set</span>
        {
            <span class="comment">// value は @ を付けてもダメ。</span>
            <span class="comment">// 扱いが「暗黙定義された引数」なので、@value もその引数を指す。</span>
            <span class="reserved">var</span> <span class="variable"><span class="warning" title="CS0219"><span class="error" title="CS0136">@value</span></span></span> <span class="operator">=</span> <span class="number">1</span>;

            <span class="comment">// 普通、キーワードだったら @ を付けることで識別子に使える。</span>
            <span class="reserved">var</span> <span class="variable">@this</span> <span class="operator">=</span> <span class="number">2</span>;
        }
    }
}
</pre>
<p>2つ目、<a href="https://ufcpp.net/study/csharp/st_string.html#nameof-operator"><code>nameof</code></a>。</p>
<pre class="source" title="nameof が使える">
<span class="reserved">class</span> <span class="type">A</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> <span class="property">X</span>
    {
        <span class="reserved">set</span>
        {
            <span class="comment">// 逆に、引数扱いゆえに nameof が使える。</span>
            <span class="reserved">var</span> <span class="variable">n1</span> <span class="operator">=</span> <span class="reserved">nameof</span>(<span class="reserved">value</span>);

            <span class="comment">// キーワードには nameof は使えない。</span>
            <span class="reserved">var</span> <span class="variable">n2</span> <span class="operator">=</span> <span class="reserved">nameof</span>(<span class="reserved"><span class="error" title="CS8081">this</span></span>);
        }
    }
}
</pre>
<p>3つ目、外側の識別子の参照。</p>
<pre class="source" title="外にある「value フィールド」の参照ができない">
<span class="reserved">class</span> <span class="type">A</span>
{
    <span class="reserved">int</span> <span class="field">value</span>;
    <span class="reserved">int</span> <span class="field">@this</span>;

    <span class="reserved">public</span> <span class="reserved">int</span> <span class="property">X</span>
    {
        <span class="reserved">set</span>
        {
            <span class="comment">// 外にある「value フィールド」すら、@value では参照できない。</span>
            <span class="comment">// 暗黙の引数の方になる(@ を付けるだけ無駄)。</span>
            <span class="comment">// (ちなみに、 this.value = 1; と書けばフィールド参照になる。)</span>
            <span class="reserved">@value</span> <span class="operator">=</span> <span class="number">1</span>;

            <span class="comment">// キーワードの場合は @this で外のフィールド参照になる。</span>
            <span class="field">@this</span> <span class="operator">=</span> <span class="number">2</span>;
        }
    }
}
</pre>
<p><code>field</code> を足すことで軽微ながら破壊的変更が出るんなら、
<code>value</code> に軽微な破壊的変更がかかってもいいのではということで、
もうこの際 <code>value</code> もキーワード(<code>set</code> 内限定なので、<a href="https://ufcpp.net/study/csharp/ap_reserved.html#context">文脈キーワード</a>)してもいいのではという話になります。
どういう影響があるかというと、先ほどの例からわかる通りで、</p>
<ul>
<li>
<code>var @value = 1;</code> みたいなのが書けるようになる
<ul>
<li>これは、できないことができるようにあるので破壊的ではない</li>
</ul>
</li>
<li>
<code>nameof(value)</code> が書けなくなる
<ul>
<li>こう書いていた人が多数派とは思えない</li>
<li>※追記: <code>if (value is null) throw new ArgumentNullException(nameof(value));</code> って書く人それなりにいる説あり</li>
</ul>
</li>
<li>
<code>@value = 1;</code> みたいなのが暗黙的引数の上書きから、外のフィールドの上書きに変わる
<ul>
<li>単に <code>value = 1;</code> でよかったわけで、もともと変</li>
</ul>
</li>
</ul>
<p>となります。</p>
<p>ちなみに、<code>field</code> は「暗黙の引数扱い」でも「文脈キーワード扱い」でもどちらにしろ破壊的変更になります。
「文脈キーワード扱い」の方が自然っぽいんですが、
そうなるとこの「<code>value</code> と何か挙動が違う」が気になるという懸念がありまして。
そこで出た対案が「<code>value</code> も文脈キーワードに変更」という感じかと思います。</p>
 ]]></description>
				<pubDate>Sat, 24 Feb 2024 22:20:18 +0900</pubDate>
			</item>
			<item>
				<title>オーバーロード解決優先度</title>
				<link>http://ufcpp.net/blog/2024/2/overload-resolution-priority/</link>
				<description><![CDATA[ <p>今日は「負の遺産整理で消したいけども消せないメソッド対処」の話。
紆余曲折合って、現状、<code>OverloadResolutionPriority</code> 属性でオーバーロード解決に優先度をつけて、
優先度の高いものだけを見るようにするという案になっています。</p>
<p>最近のわかりやすい例だと、「パフォーマンス改善のために配列引数を <code>ReadOnlySpan</code> 引数に変えたい」というのをやりたいとします。</p>
<p>元々、配列引数で作っていたとして、</p>
<pre class="source" title="元コード">
<span class="reserved">int</span>[] <span class="variable">x</span> <span class="operator">=</span> [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>];

<span class="type">C</span><span class="operator">.</span><span class="static"><span class="method">M</span></span>(<span class="variable">x</span>);

<span class="comment">// 元コード。</span>
<span class="reserved">public</span> <span class="reserved">class</span> <span class="type">C</span>
{
    <span class="comment">// これの引数を変えたい。</span>
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="static"><span class="method">M</span></span>(<span class="reserved">int</span>[] <span class="variable local">x</span>) { }
}
</pre>
<p>暗黙的型変換があるものであれば、多少型を変えても「再コンパイルすれば大丈夫」という状態になることはあります。</p>
<pre class="source" title="再コンパイルすれば大丈夫なこともある">
<span class="reserved">int</span>[] <span class="variable">x</span> <span class="operator">=</span> [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>];

<span class="comment">// int[] → ReadOnlySpan&lt;int&gt; の変更は、再コンパイルするならエラーにならず移行可能。</span>
<span class="type">C</span><span class="operator">.</span><span class="static"><span class="method">M</span></span>(<span class="variable">x</span>);

<span class="comment">// 変更後コード。</span>
<span class="reserved">public</span> <span class="reserved">class</span> <span class="type">C</span>
{
    <span class="comment">// 引数、変えちゃった。</span>
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">M</span></span>(<span class="type struct">ReadOnlySpan</span>&lt;<span class="reserved">int</span>&gt; <span class="variable local">x</span>) { }
}
</pre>
<p>ただ、「再コンパイル必須」というのは、
末端のアプリならともかく、ライブラリとかプラグインとかにとってはきついです。
過去にコンパイル済みバイナリの形でライブラリ参照すると、
先ほどの例は「<code>M(int[])</code> が見つからない」という実行時例外を起こします。</p>
<p>なので、現実的には「メソッドは追加する一方」になりがちなんですが、
非推奨にしたい古いメソッドによって利便性が損なわれることが多々あります。</p>
<pre class="source" title="メソッドは追加する一方になりがち">
<span class="reserved">int</span>[] <span class="variable">x</span> <span class="operator">=</span> [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>];

<span class="comment">// 普通に書くと int[] の方に行っちゃう。</span>
<span class="comment">// パフォーマンスを理由に ReadOnlySpan&lt;int&gt; オーバーロードを足したのに無意味。</span>
<span class="type">C</span><span class="operator">.</span><span class="static"><span class="method">M</span></span>(<span class="variable">x</span>);

<span class="comment">// 変更後コード。</span>
<span class="reserved">public</span> <span class="reserved">class</span> <span class="type">C</span>
{
    <span class="comment">// 元のメソッドは残しつつ、</span>
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">M</span></span>(<span class="reserved">int</span>[] <span class="variable local">x</span>) { }
    <span class="comment">// オーバーロードを追加。</span>
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="static"><span class="method">M</span></span>(<span class="type struct">ReadOnlySpan</span>&lt;<span class="reserved">int</span>&gt; <span class="variable local">x</span>) { }
}
</pre>
<p>非推奨にしたいものには <code>Obsolete</code> 属性を付けるという手段はありますが、
<code>Obsolete</code> 属性を付けたところでオーバーロード解決候補には残ってしまうのがかなり邪魔です。</p>
<pre class="source" title="Obsolete でもオーバーロード解決候補になっちゃう">
<span class="reserved">int</span>[] <span class="variable">x</span> <span class="operator">=</span> [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>];

<span class="comment">// C# コンパイラーは Obsolete 属性が付いたメソッドも普通にオーバーロード解決候補にしちゃう。</span>
<span class="comment">// ReadOnlySpan&lt;int&gt; の方を呼んでほしくてやってるのに、</span>
<span class="comment">// 実際は int[] が選ばれたうえで警告が出るだけになる。</span>
<span class="warning" title="CS0618"><span class="type">C</span><span class="operator">.</span><span class="static"><span class="method">M</span></span>(<span class="variable">x</span>)</span>;

<span class="comment">// 変更後コード。</span>
<span class="reserved">public</span> <span class="reserved">class</span> <span class="type">C</span>
{
    <span class="comment">// 古い方には Obsolete 属性を付ける。</span>
    [<span class="type">Obsolete</span>(<span class="string">&quot;Use M(ReadOnlySpan&lt;int&gt; x) instead.&quot;</span>)]
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="static"><span class="method">M</span></span>(<span class="reserved">int</span>[] <span class="variable local">x</span>) { }

    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="static"><span class="method">M</span></span>(<span class="type struct">ReadOnlySpan</span>&lt;<span class="reserved">int</span>&gt; <span class="variable local">x</span>) { }
}
</pre>
<p>ということで、「バイナリ互換性のために残すけども、コンパイル時のオーバーロード解決候補には残さない」
(過去にコンパイルした DLL からは見えてるけども、ソースコードの再コンパイル時には見えない)
という状態を作りたいという要望があります。
これを「binary compat only」とか呼んでいます。</p>
<p>最初に思いつく案としては、<code>Obsolete</code> 属性に手を入れる方法。</p>
<pre class="source" title="Obsolete 属性修正案">
<span class="reserved">public</span> <span class="reserved">class</span> <span class="type">C</span>
{
    <span class="comment">// 最初に思いつく案として、Obsolete 属性を修正。</span>
    [<span class="type">Obsolete</span>(<span class="string">&quot;Use M(ReadOnlySpan&lt;int&gt; x) instead.&quot;</span>, <span class="type">ObsoleteLevel</span><span class="operator">.</span>BinaryCompatOnly)]
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">M</span></span>(<span class="reserved">int</span>[] <span class="variable local">x</span>) { }

    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="static"><span class="method">M</span></span>(<span class="type struct">ReadOnlySpan</span>&lt;<span class="reserved">int</span>&gt; <span class="variable local">x</span>) { }
}
</pre>
<p>ただ、既存の <code>Obsolete</code> 属性に手を入れる案だと、例えば netstarndard2.0 向けライブラリとか、
ターゲットフレームワーク古いライブラリに対して使えなくなります。
なので新しい属性を足さざるを得ず。</p>
<p>当初案はまんま <code>BinaryCompatOnly</code> 属性でした。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/pull/7707">Add proposal for BinaryCompatOnlyAttribute</a></li>
</ul>
<pre class="source" title="BinaryCompatOnly 案">
<span class="reserved">int</span>[] <span class="variable">x</span> <span class="operator">=</span> [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>];

<span class="comment">// ReadOnlySpan&lt;int&gt; の方が選ばれるようになる予定。</span>
<span class="type">C</span><span class="operator">.</span><span class="static"><span class="method">M</span></span>(<span class="variable">x</span>);

<span class="reserved">public</span> <span class="reserved">class</span> <span class="type">C</span>
{
    <span class="comment">// 新属性で「オーバーロード解決候補から外す」指定。</span>
    [<span class="type">BinaryCompatOnly</span>]
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">M</span></span>(<span class="reserved">int</span>[] <span class="variable local">x</span>) { }

    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">M</span></span>(<span class="type struct">ReadOnlySpan</span>&lt;<span class="reserved">int</span>&gt; <span class="variable local">x</span>) { }
}

<span class="reserved">public</span> <span class="reserved">class</span> <span class="type">BinaryCompatOnlyAttribute</span> : <span class="type">Attribute</span>;
</pre>
<p>ところが、じゃあ、「完全に候補から外す」だけでいいのかというと、そうでもなくて困ったみたいです。
例えば、インターフェイスの実装とかはどうするの？ということになりました。</p>
<pre class="source" title="「完全に候補から外す」だけでいいのかどうか問題">
<span class="reserved">public</span> <span class="reserved">interface</span> <span class="type">I</span>
{
    <span class="comment">// 新属性で「オーバーロード解決候補から外す」指定。</span>
    [<span class="type">BinaryCompatOnly</span>]
    <span class="reserved">void</span> <span class="method">M</span>(<span class="reserved">int</span>[] <span class="variable local">x</span>);

    <span class="comment">// 新規追加メソッド。</span>
    <span class="reserved">void</span> <span class="method">M</span>(<span class="type struct">ReadOnlySpan</span>&lt;<span class="reserved">int</span>&gt; <span class="variable local">x</span>);
}

<span class="reserved">public</span> <span class="reserved">class</span> <span class="type">C</span> : <span class="type">I</span>
{
    <span class="comment">// BinaryCompatOnly = コンパイル時には見えない</span>
    <span class="comment">// なわけで、 I.M(int[]) も「見えない」 = 実装できないのが正しい？</span>
    <span class="comment">//</span>
    <span class="comment">// こっちの M(int[]) にも BinaryCompatOnly 属性を付けることを義務付ける？</span>
    <span class="reserved">public</span> <span class="reserved">void</span> <span class="method">M</span>(<span class="reserved">int</span>[] <span class="variable local">x</span>) { }

    <span class="reserved">public</span> <span class="reserved">void</span> <span class="method">M</span>(<span class="type struct">ReadOnlySpan</span>&lt;<span class="reserved">int</span>&gt; <span class="variable local">x</span>) { }
}

<span class="reserved">public</span> <span class="reserved">class</span> <span class="type">BinaryCompatOnlyAttribute</span> : <span class="type">Attribute</span>;
</pre>
<p>そこで最終的に、</p>
<ul>
<li>
オーバーロード解決に優先度をつけれるようにする
<ul>
<li>何も指定がないときを 0 として、数字が大きいほど優先度を上げ、小さいほど下げる</li>
</ul>
</li>
<li>優先度が一番高いものだけを候補にする</li>
</ul>
<p>という案に修正されました。
属性名は <code>OverloadResolutionPriority</code>。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/pull/7906">Add proposal for overload resolution priority</a></li>
</ul>
<pre class="source" title="オーバーロード解決の優先度指定">
<span class="reserved">int</span>[] <span class="variable">x</span> <span class="operator">=</span> [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>];

<span class="comment">// ReadOnlySpan&lt;int&gt; の方が選ばれるようになる予定。</span>
<span class="type">C</span><span class="operator">.</span><span class="static"><span class="method">M</span></span>(<span class="variable">x</span>);

<span class="reserved">public</span> <span class="reserved">class</span> <span class="type">C</span>
{
    <span class="comment">// 優先度を上げたければ priority の数字を増やす。</span>
    [<span class="type">OverloadResolutionPriority</span>(<span class="number">1</span>)]
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="static"><span class="method">M</span></span>(<span class="type struct">ReadOnlySpan</span>&lt;<span class="reserved">int</span>&gt; <span class="variable local">x</span>) { }

    <span class="comment">// 逆にこっちに priority = -1 とかを与えて優先度を下げるとかでも OK。</span>
    [<span class="type">OverloadResolutionPriority</span>(<span class="number">-1</span>)]
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="static"><span class="method">M</span></span>(<span class="reserved">int</span>[] <span class="variable local">x</span>) { }
}

<span class="reserved">public</span> <span class="reserved">class</span> <span class="type">OverloadResolutionPriorityAttribute</span>(<span class="reserved">int</span> <span class="variable local">priority</span>) : <span class="type">Attribute</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> <span class="property">Priority</span> { <span class="reserved">get</span>; } <span class="operator">=</span> <span class="variable local">priority</span>;
}
</pre>
<p>これなら先ほどのインターフェイスの例みたいな「見なくなりすぎる」問題は回避。
「高優先度のものが見つからなければ単に古い方を見に行く」みたいな挙動になります</p>
<p>まあ、具体化するには検討すべき項目はまだまだあるでしょうが
(例えば優先度は int で何でも受け付けるのでいいか？とか)、
方向性としては、C# チームも強く支持するし、
BCL 側もこれが入れば大々的に使いたい意向ありとのこと。</p>
 ]]></description>
				<pubDate>Sun, 18 Feb 2024 17:56:51 +0900</pubDate>
			</item>
			<item>
				<title>ジェネリック型引数の部分型推論</title>
				<link>http://ufcpp.net/blog/2024/2/partial-inference/</link>
				<description><![CDATA[ <p>C# のジェネリック型引数の推論を賢くしたいという話は、issue として記録されている分に限っても5年くらい前からあります。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/1349">Champion: &quot;Partial Type Inference&quot;</a></li>
</ul>
<p>現状の C# の型推論は割と &quot;All or Nothing&quot; で、
<code>new()</code> みたいに型全体の省略はできても、<code>new List&lt;&gt;()</code> みたいな「一部分だけ省略」ができません。</p>
<pre class="source" title="部分的な型の推論">
<span class="comment">// 型全体の推論は可能。</span>
<span class="comment">// 左辺から型が決定されて、new() は new List&lt;int&gt;() と解釈される。</span>
<span class="type">List</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">x1</span> <span class="operator">=</span> <span class="reserved">new</span>();

<span class="comment">// 一方、型引数だけの省略というのができない。</span>
<span class="type">List</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">x2</span> <span class="operator">=</span> <span class="reserved">new</span> <span class="error" title="CS7003"><span class="type">List</span>&lt;&gt;</span>(); <span class="comment">// 要は Java のダイヤモンド演算子みたいなのとか、</span>
<span class="type">List</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">x3</span> <span class="operator">=</span> <span class="reserved">new</span> <span class="type">List</span>&lt;<span class="error" title="CS0246">_</span>&gt;(); <span class="comment">// あるいは「ここは推論して」を表すキーワードを用意したい。</span>

<span class="comment">// 特にこういう「部分推論」ができないと困るのは以下のような場面。</span>
<span class="type">IList</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">x4</span> <span class="operator">=</span> <span class="reserved">new</span> <span class="type">List</span>&lt;<span class="error" title="CS0246">_</span>&gt;(); <span class="comment">// 左辺がインターフェイス、右辺が具象型なので new() とは書けない。</span>
</pre>
<p>この issue はずいぶん前から「Champion」(C# チーム内の誰かが興味を持って推進している状態)にはなっていたんですが、しばらく動きはありませんでした。</p>
<p>それが去年くらいから動きあり。
具体的な提案が出ました。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/pull/7582">Add proposal for partial type inference #7582</a></li>
</ul>
<p>現状有力な案は「推論したいところに <code>_</code> を入れる」文法です。
先日の「<a href="https://ufcpp.net/blog/2024/2/breaking-changes/">C# での破壊的変更の今後の扱い</a>」の話とも関連していますね。
discard と同じく <code>_</code> を利用するとなると、<code>class _ { }</code> が邪魔なので。</p>
<p>そして最近これが Language Design Meeting でも取り上げられたみたいです。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/blob/main/meetings/2024/LDM-2024-02-07.md">C# Language Design Meeting for February 7th, 2024</a></li>
</ul>
<p>これによれば以下のような感じ。</p>
<ul>
<li>コミュニティ貢献。作者は修士論文として取り組んでいるらしい</li>
<li>
C# チームも乗り気でサポート中
<ul>
<li>特に、「型推論が面倒だからインターフェイス使わない」(<code>IEnumerable&lt;T&gt;</code> じゃなくて <code>List&lt;T&gt;</code> を使う方を好む)みたいな問題を減らせる点を評価</li>
</ul>
</li>
<li>
出ている提案はパフォーマンスも考慮していて、「コンパイル時間が指数的に爆発する」みたいな問題は避けれそう
<ul>
<li>いくつか制限することで、(型推論アルゴリズムとして有名な) Hindley-Milner ほど複雑にはならず、指数的な処理は避けれる</li>
</ul>
</li>
<li>
ポリシーとして「<code>var</code> は使わない」とか「型が明白な場合にのみ <code>var</code> を使う」みたいなことがあり、現在の <code>var</code> と同じく部分型推論にもその手のアナライザー提供の可能性あり
<ul>
<li>ただ、部分型推論にとって「型が明白」とはどういうものかは要検討</li>
</ul>
</li>
<li>C# 13 には入らなさそう(原文 &quot;not going to&quot; なので結構な確度で入らない)なものの、取り組みには前向き</li>
</ul>
 ]]></description>
				<pubDate>Sat, 17 Feb 2024 15:43:51 +0900</pubDate>
			</item>
			<item>
				<title>ファーストクラスな Span 型</title>
				<link>http://ufcpp.net/blog/2024/2/first-class-span/</link>
				<description><![CDATA[ <p>今日は「<code>Span&lt;T&gt;</code>、<code>ReadOnlySpan&lt;T&gt;</code> をコンパイラーで特別扱いしたい」という話。</p>
<p>C# 7.2 の頃、<a href="https://ufcpp.net/study/csharp/resource/span/"><code>Span&lt;T&gt;</code> 型</a>が追加されて、
安全性を損なわずに unsafe コード並みにパフォーマンスのよいコードが書けるようになりました。
それ以来、.NET の標準ライブラリでもいろんな場面で<code>Span&lt;T&gt;</code> 型が活用されています。</p>
<p>いまや結構重要なポジションを担う型なわけですが、
現状の扱いはあくまで「普通の構造体の1つ」です。
そのため微妙にオーバーロード解決とかで困り気味。</p>
<p>例えば直近では、C# 12 でコレクション式を導入するにあたって「<a href="https://ufcpp.net/study/csharp/datatype/collection-expression/#priority">普通にやってたら使い勝手が悪いので <code>Span</code> を特別扱い</a>」みたいなことをやっています。</p>
<pre class="source" title="コレクション式の Span 特別対応">
<span class="comment">// 普通にやると IEnumerable と Span の優先度はつかなくてコンパイルエラー。</span>
<span class="type">EnumerableVsSpan</span><span class="operator">.</span><span class="method"><span class="error" title="CS0121"><span class="static">M</span></span></span>(<span class="reserved">new</span> <span class="reserved">int</span>[<span class="number">5</span>]);

<span class="comment">// コレクション式は Span を優先する。</span>
<span class="type">EnumerableVsSpan</span><span class="operator">.</span><span class="method"><span class="static">M</span></span>([<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>]);

<span class="comment">// Span を優先しちゃう(パフォーマンス的に好ましくない)。</span>
<span class="type">SpanVsReadOnlySpan</span><span class="operator">.</span><span class="method"><span class="static">M</span></span>(<span class="reserved">new</span> <span class="reserved">int</span>[<span class="number">5</span>]);

<span class="comment">// ReadOnlySpan を優先するよう特別扱い。</span>
<span class="type">SpanVsReadOnlySpan</span><span class="operator">.</span><span class="method"><span class="static">M</span></span>([<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>]);

<span class="reserved">class</span> <span class="type">EnumerableVsSpan</span>
{
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">M</span></span>(<span class="type">IEnumerable</span>&lt;<span class="reserved">int</span>&gt; <span class="variable local">_</span>) { }
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="static"><span class="method">M</span></span>(<span class="type struct">Span</span>&lt;<span class="reserved">int</span>&gt; <span class="variable local">_</span>) { }
}

<span class="reserved">class</span> <span class="type">SpanVsReadOnlySpan</span>
{
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">M</span></span>(<span class="type struct">ReadOnlySpan</span>&lt;<span class="reserved">int</span>&gt; <span class="variable local">_</span>) { }
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">M</span></span>(<span class="type struct">Span</span>&lt;<span class="reserved">int</span>&gt; <span class="variable local">_</span>) { }
}
</pre>
<p>また、いわゆる共変性の辺りが微妙だったりします。
以下のように、コンパイルできてほしくないのに実行時エラーになるのが1件、
コンパイルできてほしいのにできないのが1件。</p>
<pre class="source" title="ReadOnlySpan の共変性">
<span class="reserved">var</span> <span class="variable">strArray</span> <span class="operator">=</span> <span class="reserved">new</span> <span class="reserved">string</span>[<span class="number">5</span>];

<span class="comment">// 行ける。 Span に implicit operator が定義されているので。</span>
<span class="type struct">Span</span>&lt;<span class="reserved">string</span>&gt; <span class="variable">strSpan</span> <span class="operator">=</span> <span class="variable">strArray</span>;

<span class="comment">// なぜか行ける…</span>
<span class="comment">// 配列に共変性(object[] objArray = strArray; が合法という負の遺産)があるせい。</span>
<span class="comment">// が、実行時例外起こす。</span>
<span class="type struct">Span</span>&lt;<span class="reserved">object</span>&gt; <span class="variable">objSpan</span> <span class="operator">=</span> <span class="variable">strArray</span>;

<span class="comment">// 行ける。</span>
<span class="type struct">ReadOnlySpan</span>&lt;<span class="reserved">string</span>&gt; <span class="variable">strRos1</span> <span class="operator">=</span> <span class="variable">strArray</span>;
<span class="type struct">ReadOnlySpan</span>&lt;<span class="reserved">string</span>&gt; <span class="variable">strRos2</span> <span class="operator">=</span> <span class="variable">strSpan</span>;

<span class="comment">// これも行ける。</span>
<span class="type struct">ReadOnlySpan</span>&lt;<span class="reserved">object</span>&gt; <span class="variable">objRos1</span> <span class="operator">=</span> <span class="variable">objSpan</span>;
<span class="type struct">ReadOnlySpan</span>&lt;<span class="reserved">object</span>&gt; <span class="variable">objRos2</span> <span class="operator">=</span> <span class="variable">strArray</span>;

<span class="comment">// ダメ…</span>
<span class="comment">// (できても問題ないけど、ReadOnlySpan を特別扱いしないとコンパイラーにはそれがわからない。)</span>
<span class="type struct">ReadOnlySpan</span>&lt;<span class="reserved">object</span>&gt; <span class="variable">objRos3</span> <span class="operator">=</span> <span class="variable"><span class="error" title="CS0029">strSpan</span></span>;
</pre>
<p>ということで、まあ、
「<code>Span&lt;T&gt;</code>、<code>ReadOnlySpan&lt;T&gt;</code> をコンパイラーで特別扱いしたい」という話になります。</p>
<ul>
<li>ドキュメント追加の PR: <a href="https://github.com/dotnet/csharplang/pull/7904">Add first-class span types proposal</a></li>
<li>トラッキング issue: <a href="https://github.com/dotnet/csharplang/issues/7905">[Proposal]: First-Class Span Types</a></li>
</ul>
<p>「配列から <code>IEnumerable&lt;T&gt;</code> への変換」とかが元からそうなんで、その辺りに並べて <code>Span&lt;T&gt;</code>、<code>ReadOnlySpan&lt;T&gt;</code> がらみの仕様を入れるとのこと。</p>
<p>提案は<a href="https://github.com/dotnet/csharplang/blob/main/meetings/2024/LDM-2024-02-05.md">2月5日の Language Design Meeting であっさり了承されてる</a>し、
割かしコレクション式の取り組みからの流れっぽい感じもするので C# 13 に入りそうな感じがしますね。
懸念として、ちょっとした(めったに起こらなさそうな)破壊的変更があり得るので、
そのリスクがどう評価されるか次第。</p>
 ]]></description>
				<pubDate>Tue, 13 Feb 2024 23:12:43 +0900</pubDate>
			</item>
			<item>
				<title>インターセプター</title>
				<link>http://ufcpp.net/blog/2024/2/interceptors/</link>
				<description><![CDATA[ <p>「最近動きがあったもの」ブログをいくつか書いてて、
「<a href="https://ufcpp.net/blog/2024/2/breaking-changes/">続報</a>」みたいなものも書いてるわけですが。</p>
<p>今日のも「まあ、去年から動く実装すでにあるんだけど」という意味では続報なものの、
今日のインターセプターはあまりうちのサイトで取り上げておらず、初めて説明を書く話。
(<a href="https://github.com/ufcpp/UfcppSample/issues/456">ライブ配信</a>では時々話に出てるんですが。)</p>
<h2>インターセプター</h2>
<p>今日話すインターセプターは、まあ、<a href="https://ufcpp.net/study/csharp/misc/analyzer-generator/">Source Generator</a>向けの機能です。</p>
<p>既存の Source Generator でも、
クラスを丸ごと生成するとか、メソッドの中身を生成とかはできます。</p>
<p>.NET が標準で提供しているやつだと <code>GeneratedRegex</code> とか。
partial メソッドに属性を付けて、メソッドの中身をコード生成しています。</p>
<pre class="source" title="GeneratedRegex">
<span class="reserved">partial</span> <span class="reserved">class</span> <span class="type">Reg</span>
{
    <span class="comment">// この属性を付けた partial メソッドに対して、</span>
    <span class="comment">// Sytem.Text.RegularExpressions.Generator でコード生成してる。</span>
    [<span class="type">GeneratedRegex</span>(<span class="string">@&quot;\d+&quot;</span>)]
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">partial</span> <span class="type">Regex</span> <span class="method"><span class="static">Digits</span></span>();
}
</pre>
<p>これで困るのは、<strong>メソッドの呼び出し箇所ごとに違う実装をコード生成したい場合</strong>です。</p>
<p>一例として以下のようなコードを考えます。
要は「const string を <code>Parse</code> するならコンパイル時に全部やっちゃえるのでは」という話。</p>
<pre class="source" title="呼び出し箇所ごとに別コード生成したいものの例">
<span class="reserved">using</span> <span class="reserved">static</span> System<span class="operator">.</span><span class="static"><span class="type">Console</span></span>;

<span class="comment">// const string の Parse はコンパイル時にできるのでは。</span>
<span class="static"><span class="method">WriteLine</span></span>(<span class="reserved">int</span><span class="operator">.</span><span class="method"><span class="static">Parse</span></span>(<span class="string">&quot;123&quot;</span>));
<span class="static"><span class="method">WriteLine</span></span>(<span class="reserved">int</span><span class="operator">.</span><span class="static"><span class="method">Parse</span></span>(<span class="string">&quot;456&quot;</span>));

<span class="comment">// こういうのは無理として。</span>
<span class="static"><span class="method">WriteLine</span></span>(<span class="reserved">int</span><span class="operator">.</span><span class="method"><span class="static">Parse</span></span>(<span class="method"><span class="static">ReadLine</span></span>()<span class="operator">!</span>));
</pre>
<p>int だと「最初から <code>123</code> と書け」と言われればそれまでなので役に立ちませんが、
例えば <a href="https://learn.microsoft.com/ja-jp/dotnet/api/system.numerics.biginteger"><code>BigInteger</code></a> とかなら意味がありそうです。</p>
<p>こういう場合に、メソッド呼び出し箇所を乗っ取って別のメソッドに差し替えてしまう仕組みを検討中で、
それがインターセプター(interceptor: 妨害者、途中で奪う・捕まえるもの)です。
C# 12 時点でプレビュー機能として実装されていて、後述するオプションを設定すると現在でも動かすことができます
(提案ドキュメント: <a href="https://github.com/dotnet/roslyn/blob/main/docs/features/interceptors.md">Interceptors</a>)。</p>
<p>現在の実装をベースに話すと、
先ほどのコードが F:/src/ConsoleApp1/ConsoleApp1/Program.cs というパスのファイルに書かれているものとして、
以下のようなコードを作ります(Source Generator で作ること前提)。</p>
<pre class="source" title="インターセプターの例">
<span class="reserved">using</span> System<span class="operator">.</span>Runtime<span class="operator">.</span>CompilerServices;

<span class="reserved">namespace</span> ConsoleApp1
{
    <span class="reserved">static</span> <span class="reserved">class</span> <span class="type"><span class="static">Interceptors</span></span>
    {
        [<span class="type">InterceptsLocation</span>(<span class="string">&quot;F:/src/ConsoleApp1/ConsoleApp1/Program.cs&quot;</span>, <span class="number">4</span>, <span class="number">15</span>)]
        <span class="reserved">internal</span> <span class="reserved">static</span> <span class="reserved">int</span> <span class="static"><span class="method">Parse123</span></span>(<span class="reserved">string</span> <span class="variable local">_</span>) <span class="operator">=&gt;</span> <span class="number">123</span>;

        [<span class="type">InterceptsLocation</span>(<span class="string">&quot;F:/src/ConsoleApp1/ConsoleApp1/Program.cs&quot;</span>, <span class="number">5</span>, <span class="number">15</span>)]
        <span class="reserved">internal</span> <span class="reserved">static</span> <span class="reserved">int</span> <span class="static"><span class="method">Parse456</span></span>(<span class="reserved">string</span> <span class="variable local">_</span>) <span class="operator">=&gt;</span> <span class="number">456</span>;
    }
}

<span class="reserved">namespace</span> System<span class="operator">.</span>Runtime<span class="operator">.</span>CompilerServices
{
    [<span class="type">AttributeUsage</span>(<span class="type">AttributeTargets</span><span class="operator">.</span>Method, <span class="property">AllowMultiple</span> <span class="operator">=</span> <span class="reserved">true</span>)]
    <span class="reserved">file</span> <span class="reserved">sealed</span> <span class="reserved">class</span> <span class="type">InterceptsLocationAttribute</span> : <span class="type">Attribute</span>
    {
        <span class="reserved">public</span> <span class="type">InterceptsLocationAttribute</span>(<span class="reserved">string</span> <span class="variable local">filePath</span>, <span class="reserved">int</span> <span class="variable local">line</span>, <span class="reserved">int</span> <span class="variable local">column</span>) { }
    }
}
</pre>
<p><code>InterceptsLocation</code> 属性が付いたメソッドで、属性で指定したファイル・行・列にあるメソッド呼び出しを乗っ取ります。</p>
<p>この例の場合、</p>
<ul>
<li><code>(&quot;略/Program.cs&quot;, 4, 15)</code> → <code>int.Parse(&quot;123&quot;)</code> の場所 → ここを <code>Parse123</code> で乗っ取る</li>
<li><code>(&quot;略/Program.cs&quot;, 5, 15)</code> → <code>int.Parse(&quot;456&quot;)</code> の場所 → ここを <code>Parse456</code> で乗っ取る</li>
</ul>
<p>という挙動。
その結果、Program.cs の内容は以下のものに置き換わったものとしてコンパイルされます。</p>
<pre class="source" title="インターセプターの適用結果">
<span class="reserved">using</span> <span class="reserved">static</span> System<span class="operator">.</span><span class="static"><span class="type">Console</span></span>;

<span class="comment">// const string の Parse はコンパイル時にできるのでは。</span>
<span class="static"><span class="method">WriteLine</span></span>(<span class="type">Interceptors</span><span class="operator">.</span><span class="method"><span class="static">Parse123</span></span>(<span class="string">&quot;123&quot;</span>));
<span class="static"><span class="method">WriteLine</span></span>(<span class="type">Interceptors</span><span class="operator">.</span><span class="static"><span class="method">Parse456</span></span>(<span class="string">&quot;456&quot;</span>));

<span class="comment">// こういうのは無理として。</span>
<span class="static"><span class="method">WriteLine</span></span>(<span class="reserved">int</span><span class="operator">.</span><span class="method"><span class="static">Parse</span></span>(<span class="method"><span class="static">ReadLine</span></span>()<span class="operator">!</span>));
</pre>
<p>ちなみに、ファイル指定がフルパスなのが気持ち悪すぎていまいち取り上げる気になれず、今までブログ化していなかったり。
後述しますが、フルパスだと困るであろうことは課題として認識されていて、C# 13 正式リリースまでには対処が入ると思います。</p>
<h2>プレビュー オプション</h2>
<p>インターセプターは「早めに動くものを提供して、ASP.​NET チーム辺りで実際に使ってもらってフィードバックをもらいたい」という意図で、かなり早い段階でプレビュー機能としてリリースされています。
当然作ってる側も自信をもってリリースしているわけがなく、
大幅に変更がかかる可能性があります。</p>
<p>(ちなみに、実際に試してもらってるコードはここ: <a href="https://github.com/dotnet/aspnetcore/tree/c52a7abf3a8a08213dea461c7d97f421b9d862e6/src/Http/Http.Extensions/gen">Http.Extensions</a>)</p>
<p>そんな感じの早期プレビューなのと、
先ほどの例の <code>int.Parse</code> みたいな何の変哲もない普通のメソッドを乗っ取れる仕組みが結構怖いので、
オプション指定しないとコンパイルできません。</p>
<p>当初は csproj に <code>&lt;Features&gt;InterceptorsPreview&lt;Features&gt;</code> というタグを入れておけば使える仕様でした。
単に「LangVersion preview」ではなくて、フィーチャースイッチを明示。</p>
<p>が、その後、「もっと制限をかけたい」ということになったみたいで、
<code>&lt;InterceptorsPreviewNamespaces&gt;ConsoleApp1&lt;/InterceptorsPreviewNamespaces&gt;</code> みたいに、
「特定の名前空間にあるインターセプターのみを認める」というオプションの書き方に変わりました。
(コンパイラーがインターセプターを検索するコストを減らすためだそうです。
今は <code>InterceptorsPreviewNamespaces</code> という名前なものの、
プレビューが外れたら <code>InterceptorsNamespaces</code> にする予定。)</p>
<h2>現在の open issue</h2>
<p>ということで、最近あった検討内容:</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/pull/7835">Interceptors open issues for C# 13</a></li>
</ul>
<h3>相対パス化</h3>
<p>一番はやっぱり「フルパス問題」。</p>
<p>Source Generator はそれなりに重たい処理になることがあって、
コンパイルのたびに何度も走ってほしくないということがあります。
そういう場合ように、Source Generator の実行結果をファイル システムに書きこんじゃって、
手書きのコードと一緒にコミットしてしまうという運用も考えられます
(<a href="https://learn.microsoft.com/ja-jp/dotnet/csharp/roslyn-sdk/source-generators-overview"><code>EmitCompilerGeneratedFiles</code> オプション</a>でできます)。</p>
<p>フルパスはこのオプションを使うと一発で破綻します。
自分の手元では F:/src/ConsoleApp1 かもしれないものの、
Git とかで他人と共有すると、他の人のパスは F:/users/UserName/repos/ConsoleApp1 とかだったりします。
都度コード生成するなら問題ありませんが、コミットしようとするとパスの差で困ります。</p>
<p>なので、<code>InterceptsLocation</code> 属性に渡すパスは相対パスにできるようになると思います。
とはいえ、以下のような課題あり。</p>
<ul>
<li>
「インターセプトする側とされる側の保存先が別ドライブにある」みたいな場合、相対パス指定できない
<ul>
<li>元からあるファイルシステムの問題で、<code>#line</code> ディレクティブとかでも同様の制限あり</li>
</ul>
</li>
<li>
Source Generator が生成するファイルのパスがわからないと「そこからインターセプトされる側」の相対パスがわからない
<ul>
<li>Source Generator の生成結果の出力先パスを相対パス フレンドリーな場所に変更するつもりあり</li>
</ul>
</li>
</ul>
<h3>location specifier</h3>
<p>もしくは、ファイル パスに依存すること自体をやめて、何らかの抽象的な「location specifier (場所指定子)」を受け付ける仕組みを用意するという案も出ています。
まずは <code>InterceptsLocation</code> 属性に以下のコンストラクター追加。</p>
<pre class="source" title="locationSpecifier 引数のコンストラクター">
<span class="reserved">namespace</span> System<span class="operator">.</span>Runtime<span class="operator">.</span>CompilerServices;

[<span class="type">AttributeUsage</span>(<span class="type">AttributeTargets</span><span class="operator">.</span>Method, <span class="property">AllowMultiple</span> <span class="operator">=</span> <span class="reserved">true</span>)]
<span class="reserved">sealed</span> <span class="reserved">class</span> <span class="type">InterceptsLocationAttribute</span> : <span class="type">Attribute</span>
{
    <span class="reserved">public</span> <span class="type">InterceptsLocationAttribute</span>(<span class="reserved">string</span> <span class="variable local">filePath</span>, <span class="reserved">int</span> <span class="variable local">line</span>, <span class="reserved">int</span> <span class="variable local">column</span>) { }
    <em><span class="reserved">public</span> <span class="type">InterceptsLocationAttribute</span>(<span class="reserved">string</span> <span class="variable local">locationSpecifier</span>) { }</em>
}
</pre>
<p>一例として以下のように、何らかの書式で「ソースコードの場所」がわかる文字列を指定。</p>
<pre class="source" title="locationSpecifier 指定のインターセプター">
<span class="reserved">class</span> <span class="type">Interceptors</span>
{
    [<span class="type">InterceptsLocation</span>(<span class="string">&quot;v1:../../src/MyFile.cs(12,34)&quot;</span>)]
    <span class="reserved">public</span> <span class="reserved">void</span> <span class="method">Interceptor</span>() { }
}
</pre>
<p>独特な書式を覚えるのは大変でしょうが、
幸い、インターセプターは Source Generator 用の機能なわけで、
Source Generator 作者向けに location specifier を取得できる API を同時に提供するつもりだそうです
(なので独特な書式を覚える必要はないはず)。</p>
<pre class="source" title="location specifier を取得できる API の追加">
<span class="reserved">namespace</span> Microsoft<span class="operator">.</span>CodeAnalysis;

<span class="reserved">public</span> <span class="reserved">readonly</span> <span class="reserved">struct</span> <span class="type struct">SourceProductionContext</span>
{
    <span class="reserved">public</span> <span class="reserved">void</span> <span class="method">AddSource</span>(<span class="reserved">string</span> <span class="variable local">hintName</span>, <span class="reserved">string</span> <span class="variable local">source</span>);
    <em><span class="reserved">public</span> <span class="reserved">string</span> <span class="method">GetInterceptsLocationSpecifier</span>(<span class="type">InvocationExpressionSyntax</span> <span class="variable local">intercepted</span>, <span class="reserved">string</span> <span class="variable local">interceptorFileHintName</span>);</em>
}
</pre>
<p>Roslyn の構文木ノードを受け取って、
そこに相当する specifier を返してもらって、
この specifier をそのまま <code>InterceptsLocation</code> 属性に出力する想定です。</p>
<h3>もっと先の話</h3>
<p>「たぶん C# 13 より後」と分類されている課題もいくつか。</p>
<ul>
<li>
プロパティとかコンストラクターもインターセプトしたい
<ul>
<li><a href="https://learn.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.unsafeaccessorattribute"><code>UnsafeAccessor</code></a> と書き方そろえるかも</li>
</ul>
</li>
<li>
インターセプトする側とされる側で完全にシグネチャが同じでないとダメなのを緩和したい
<ul>
<li>「<code>Delegate</code> を <code>Func&lt;T&gt;</code> に変える」みたいなことはできていいはず</li>
</ul>
</li>
</ul>
 ]]></description>
				<pubDate>Sun, 11 Feb 2024 18:49:49 +0900</pubDate>
			</item>
			<item>
				<title>ref 構造体のインターフェイス実装 / 型引数での使用</title>
				<link>http://ufcpp.net/blog/2024/2/ref-struct-interface/</link>
				<description><![CDATA[ <p><a href="https://ufcpp.net/study/csharp/resource/refstruct/">ref 構造体</a>で説明しているように、
<a href="https://ufcpp.net/study/csharp/resource/span/"><code>Span&lt;T&gt;</code></a> 型など一部の型は「スタック上にないといけない」という強い制約があります。</p>
<p>この制約を守るため、これまで、ref 構造体は</p>
<ul>
<li>インターフェイスを実装できなかった</li>
<li>ジェネリック型引数に使えなかった</li>
</ul>
<p>という制限が掛かっていました。</p>
<p>C# 13 では、この制限を緩和するため、
ジェネリック型引数に「<code>allows ref struct</code>」という「アンチ制約」を追加する予定です。</p>
<p>こういう案自体は <a href="https://ufcpp.net/study/csharp/resource/refstruct/#ref-field">ref フィールド</a>が追加された C# 11 (2022年)の頃から温められてはいたんですが、
いよいよ C# 13 で本格的に取り組むみたいです。
.NET 8/C# 12 がリリースされた後くらいからちらほら提案ドキュメントの更新あり。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/pull/7769">Add draft for demonstrating ref-struct-constraint soundness</a></li>
<li><a href="https://github.com/dotnet/csharplang/pull/7865">Update ref struct interfaces based on LDM discussions</a></li>
<li><a href="https://github.com/dotnet/csharplang/pull/7911">ref struct interfaces updates</a></li>
</ul>
<p>ちなみに、ランタイム側はその2022年頃に対応すでに入っているみたいです。</p>
<ul>
<li><a href="https://github.com/dotnet/runtime/pull/67129">Design to support ByRefLike types in Generics</a></li>
<li><a href="https://github.com/dotnet/runtime/pull/67783">Support ByRefLike types as Generic parameters</a></li>
</ul>
<h2>ref 構造体の制限緩和の要求</h2>
<p>わかりやすい例でいうと、<code>Span&lt;T&gt;</code> は <code>IEnumerable&lt;T&gt;</code> であってほしいというものです。
C# 12 時点だと、以下のような2重実装を余儀なくされています。</p>
<pre class="source" title="C# 12 時点では IEnumerable と Span の2重実装が必須">
<span class="type">List</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">list</span> <span class="operator">=</span> [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>];
<span class="type struct">ReadOnlySpan</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">span</span> <span class="operator">=</span> [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>];

<span class="type"><span class="static">Console</span></span><span class="operator">.</span><span class="static"><span class="method">WriteLine</span></span>(<span class="static"><span class="type">MyMath</span></span><span class="operator">.</span><span class="static"><span class="method">Sum</span></span>(<span class="variable">list</span>));
<span class="static"><span class="type">Console</span></span><span class="operator">.</span><span class="method"><span class="static">WriteLine</span></span>(<span class="type"><span class="static">MyMath</span></span><span class="operator">.</span><span class="static"><span class="method">Sum</span></span>(<span class="variable">span</span>));

<span class="reserved">static</span> <span class="reserved">class</span> <span class="static"><span class="type">MyMath</span></span>
{
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">int</span> <span class="method"><span class="static">Sum</span></span>(<span class="type">IEnumerable</span>&lt;<span class="reserved">int</span>&gt; <span class="variable local">numbers</span>)
    {
        <span class="reserved">var</span> <span class="variable">sum</span> <span class="operator">=</span> <span class="number">0</span>;
        <span class="control">foreach</span> (<span class="reserved">var</span> <span class="variable">x</span> <span class="control">in</span> <span class="variable local">numbers</span>) <span class="variable">sum</span><span class="operator">+=</span> <span class="variable">x</span>;
        <span class="control">return</span> <span class="variable">sum</span>;
    }

    <span class="comment">// メソッドの中身全く同じ。</span>
    <span class="comment">// Span/ReadOnlySpan が IEnumerable じゃないので別メソッドでの実装が必須。</span>
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">int</span> <span class="static"><span class="method">Sum</span></span>(<span class="type struct">ReadOnlySpan</span>&lt;<span class="reserved">int</span>&gt; <span class="variable local">numbers</span>)
    {
        <span class="comment">// 実装的に、numbers をボックス化したり、ref フィールドを外に漏らしたりもしてない。</span>
        <span class="comment">// IEnumerable に対する実装をそのまま使って何も問題ない。</span>
        <span class="reserved">var</span> <span class="variable">sum</span> <span class="operator">=</span> <span class="number">0</span>;
        <span class="control">foreach</span> (<span class="reserved">var</span> <span class="variable">x</span> <span class="control">in</span> <span class="variable local">numbers</span>) <span class="variable">sum</span> <span class="operator">+=</span> <span class="variable">x</span>;
        <span class="control">return</span> <span class="variable">sum</span>;
    }
}
</pre>
<p>ref 構造体にインターフェイス実装を持たせること自体はそこまで問題ではありません。
問題は、以下のように、「インターフェイス型の変数に直接代入してしまうとボックス化を起こしてまずい」という点です。</p>
<pre class="source" title="Span をインターフェイス型変数に代入しちゃダメ">
<span class="type struct">Span</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">span</span> <span class="operator">=</span> [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>];

<span class="comment">// たとえ、Span が IEnumerable&lt;T&gt; を実装していたとしても、</span>
<span class="comment">// 以下のようなコードを書くとこの時点でボックス化が起きる。</span>
<span class="comment">// span がヒープに漏れてしまうのでまずい。</span>
<span class="type">IEnumerable</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">e</span> <span class="operator">=</span> <span class="variable"><span class="error" title="CS0029">span</span></span>;
</pre>
<p>じゃあどうすべきかというと、ジェネリクスを介します。</p>
<pre class="source" title="ジェネリクスを介すればいい">
<span class="type struct">Span</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">span</span> <span class="operator">=</span> [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>];

<span class="comment">// ジェネリクスを介すれば、ボックス化を起こさずにインターフェイスのメンバーを呼べる。</span>
<span class="comment">// (前述の問題はクリア。)</span>
<span class="reserved">static</span> <span class="type param">T</span> <span class="method"><span class="static">Sum</span></span>&lt;<span class="type param">T</span>, <span class="type param">TEnumerable</span>&gt;(<span class="type param">TEnumerable</span> <span class="variable local">list</span>)
    <span class="reserved">where</span> <span class="type param">TEnumerable</span> : <span class="type">IEnumerable</span>&lt;<span class="type param">T</span>&gt;
{
    <span class="comment">// 省略</span>
    <span class="control">return</span> <span class="reserved">default</span><span class="operator">!</span>; <span class="comment">// 仮</span>
}

<span class="comment">// なので残る問題はこっち。</span>
<span class="comment">// ref 構造体を型引数に渡したい。</span>
<span class="error" title="CS0306"><span class="static"><span class="method">Sum</span></span>&lt;<span class="reserved">int</span>, <span class="type struct">Span</span>&lt;<span class="reserved">int</span>&gt;&gt;</span>(<span class="variable">span</span>);
</pre>
<p>ということで次節で説明する「アンチ制約」が必要になります。</p>
<h2>アンチ制約</h2>
<p>ジェネリック型制約(<code>where T :</code> みたいなやつ)は、普通、制限を掛けることで、</p>
<ul>
<li>メソッド内で <code>T</code>に対して できること(呼べるメソッドとか)が増える</li>
<li>その代わり、呼び出し側で <code>T</code> に対して渡せる型が減る</li>
</ul>
<p>というものになります。</p>
<pre class="source" title="型制約">
<span class="comment">// 制限なし。</span>
<span class="reserved">static</span> <span class="reserved">void</span> <span class="static"><span class="method">M1</span></span>&lt;<span class="type param">T</span>&gt;() { }

<span class="comment">// 何の型でも渡せる。</span>
<span class="static"><span class="method">M1</span></span>&lt;<span class="reserved">int</span>&gt;();
<span class="static"><span class="method">M1</span></span>&lt;<span class="reserved">string</span>&gt;();
<span class="static"><span class="method">M1</span></span>&lt;<span class="reserved">object</span>&gt;();

<span class="comment">// 制限あり。</span>
<span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">M2</span></span>&lt;<span class="type param">T</span>&gt;() <span class="reserved">where</span> <span class="type param">T</span>:<span class="type">ISpanParsable</span>&lt;<span class="type param">T</span>&gt;
{
    <span class="comment">// 呼べるメソッドが増える。</span>
    <span class="type param">T</span> <span class="variable">value</span> <span class="operator">=</span> <span class="type param">T</span><span class="operator">.</span><span class="method"><span class="static">Parse</span></span>(<span class="string">&quot;123&quot;</span>, <span class="reserved">null</span>);
}

<span class="comment">// 渡せる型が減る。</span>
<span class="static"><span class="method">M2</span></span>&lt;<span class="reserved">int</span>&gt;();
<span class="method"><span class="static">M2</span></span>&lt;<span class="reserved">string</span>&gt;();
<span class="error" title="CS0311"><span class="method"><span class="static">M2</span></span>&lt;<span class="reserved">object</span>&gt;</span>(); <span class="comment">// コンパイルエラー。</span>
</pre>
<p>ところが今回、「ref 構造体を渡せるようにしたい」という逆の要件なので、「制約」ではなく「アンチ制約(制約の撤回)」が必要になります。</p>
<p><a href="https://ufcpp.net/blog/2022/2/ref-generic-arguments/">2年くらい前のブログ</a>でちょこっと触れていますが、
逆のことをするのに <code>where T : ref struct</code> とは書かせたくないようで、ちょっと別文法を模索していました。
当初案だと <code>allow T : ref struct</code> とかも検討されていたんですが、
結局は <code>where T : allows ref struct</code> (where はそのまま。制約の前に allows)になりそうです。</p>
<pre class="source" title="">
<span class="comment">// allows で制限を緩める。</span>
<span class="reserved">static</span> <span class="reserved">void</span> <span class="static"><span class="method">M3</span></span>&lt;<span class="type param">T</span>&gt;(<span class="type param">T</span> <span class="variable local">x</span>)
    <span class="reserved">where</span> <span class="type param">T</span> : <span class="reserved">allows</span> <span class="reserved">ref</span> <span class="reserved">struct</span> <span class="comment">// アンチ制約。</span>
{
    <span class="comment">// メソッド内でできることが減る。</span>
    <span class="reserved">object</span> <span class="variable">obj</span> <span class="operator">=</span> <span class="variable local">x</span>; <span class="comment">// box 化ダメ。エラーにする予定。</span>
}

<span class="comment">// 渡せる型が増える。</span>
<span class="static"><span class="method">M3</span></span>&lt;<span class="reserved">int</span>&gt;();
<span class="static"><span class="method">M3</span></span>&lt;<span class="reserved">string</span>&gt;();
<span class="static"><span class="method">M3</span></span>&lt;<span class="reserved">object</span>&gt;();
<span class="static"><span class="method">M3</span></span>&lt;<span class="type struct">Span</span>&lt;<span class="reserved">int</span>&gt;&gt;(); <span class="comment">// allows ref struct がないと呼べない。</span>
</pre>
<p>ちなみに、<code>where T : IDisposable, allows ref struct</code> みたいに、制約とアンチ制約は並べて書けます。</p>
 ]]></description>
				<pubDate>Sun, 11 Feb 2024 11:53:20 +0900</pubDate>
			</item>
			<item>
				<title>C# での破壊的変更の今後の扱い (続報)</title>
				<link>http://ufcpp.net/blog/2024/2/breaking-changes/</link>
				<description><![CDATA[ <p><a href="https://ufcpp.net/blog/2023/3/csharp-breaking-change/">去年の3月にブログに書いた</a>ものの続報。</p>
<p>C# でも限定的に破壊的変更を許していこうかという話だったわけですが、
ちょっと具体化しました。</p>
<p>ある機能を実現するにあたって破壊的変更の原則と進め方についての話をしています。</p>
<h2>破壊的変更の候補</h2>
<p>C# 13 で導入したい <code>field</code> アクセス(自動プロパティのバッキングフィールドにアクセスするための <code>field</code> キーワード)と、
これまでに破壊的変更を避けるためにちょっと変な設計になっている <code>var</code> (型推論変数宣言)、<code>_</code> (discard)が検討の対象になっています。</p>
<h2>破壊的変更を認める基準</h2>
<ol>
<li>あくまで控えめな破壊的変更で、エンドユーザーに明確なメリットがある</li>
<li>破壊的変更を踏むようなコードは割かしレア</li>
<li>破壊的変更を起こす予定のコードはどういう理由でどこが問題で、どう直せばいいかが明確に示せる</li>
<li>破壊的変更を避けられるよう、完全に自動で、簡単で、堅牢で、局所的な code-fix が提供できる</li>
</ol>
<h3>field の場合</h3>
<p><code>field</code> アクセスは以下のような話。</p>
<pre class="source" title="field アクセス">
<span class="reserved">class</span> <span class="type">こういうのを</span>
{
    <span class="reserved">private</span> <span class="reserved">int</span> <span class="field">_x</span>;
    <span class="reserved">public</span> <span class="reserved">int</span> <span class="property">X</span>
    {
        <span class="reserved">get</span> <span class="operator">=&gt;</span> <span class="field">_x</span>; <span class="reserved">set</span> <span class="operator">=&gt;</span> <span class="field">_x</span> <span class="operator">=</span> <span class="reserved">int</span><span class="operator">.</span><span class="static"><span class="method">Min</span></span>(<span class="reserved">value</span>, <span class="number">0</span>);
    }
}

<span class="reserved">class</span> <span class="type">こう書きたい</span> <span class="comment">// C# 13 候補</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> <span class="property">X</span>
    {
        <span class="reserved">get</span> <span class="operator">=&gt;</span> <span class="reserved">field</span>; <span class="reserved">set</span> <span class="operator">=&gt;</span> <span class="reserved">field</span> <span class="operator">=</span> <span class="reserved">int</span><span class="operator">.</span><span class="method"><span class="static">Min</span></span>(<span class="reserved">value</span>, <span class="number">0</span>);
    }
}

<span class="reserved">class</span> <span class="type">こういうコードで困る</span>
{
    <span class="reserved">private</span> <span class="reserved">int</span> <span class="field">field</span>;
    <span class="comment">// ↑「このフィールドがないときだけ field をキーワード扱いする」みたいなことすると使い勝手が悪くなる。</span>

    <span class="reserved">public</span> <span class="reserved">int</span> <span class="property">X</span>
    {
        <span class="reserved">get</span> <span class="operator">=&gt;</span> <span class="field">field</span>; <span class="reserved">set</span> <span class="operator">=&gt;</span> <span class="field">field</span> <span class="operator">=</span> <span class="reserved">int</span><span class="operator">.</span><span class="static"><span class="method">Min</span></span>(<span class="reserved">value</span>, <span class="number">0</span>);
    }
}
</pre>
<p>これは以下のように、前述の基準を満たします。</p>
<ol>
<li><code>field</code> アクセスが欲しいという要望は多い。「<code>field</code> フィールドがないときだけ」とやると構文が複雑になるし、使い勝手も悪くなる</li>
<li>「<code>field</code> という名前のフィールド」はなくはないだろうけども多くはないし、問題になるのはプロパティのアクセサー内だけ</li>
<li>「<code>field</code> が将来キーワードになる」(から使うな)という明確な説明ができる</li>
<li>型名や <code>this</code> を付けて <code>A.field</code> とか <code>this.field</code> と書くように変えればいい</li>
</ol>
<h3>var の場合</h3>
<p><a href="https://ufcpp.net/study/csharp/ap_ver3.html#functional">C# 3.0 の頃からある <code>var</code></a>ですが、
有名な話、「<code>class var { }</code> とかいう型をどこかに書いておけば、型推論の <code>var</code> を阻害できる」という問題があります。</p>
<pre class="source" title="var">
<span class="comment">// 普通は型推論の var になるはず。</span>
<span class="reserved">var</span> <span class="variable">x</span> <span class="operator">=</span> <span class="number">1</span>;

<span class="comment">// が、こういうことをすると var x の意味が変わってしまう。</span>
<span class="reserved">class</span> <span class="type"><span class="warning" title="CS8981">var</span></span>
{
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">implicit</span> <span class="reserved">operator</span> <span class="type">var</span>(<span class="reserved">int</span> <span class="variable local">_</span>) <span class="operator">=&gt;</span> <span class="number">0</span>;
}
</pre>
<p>嫌がらせでしかないんですが、
昔は「型推論とか怖いから嫌がらせしてやれ」と言っちゃう人が実際いたとか…</p>
<p>今でも「型推論は嫌」ということをもう人はいるとは思いますが、
その場合も今は<a href="https://learn.microsoft.com/ja-jp/dotnet/fundamentals/code-analysis/overview">ソースコード分析</a>の設定を変えて警告なりエラーにできるようになっているので「<code>class var { }</code>」みたいな変なことをする必要はありません。</p>
<p>なので、もう今となってはこれも破壊的変更してでも「<code>var</code> は常に型推論」にしてしまっていいのではないかという話になります。</p>
<p>これについての前述の基準:</p>
<ol>
<li>「<code>class var { }</code>みたいなものは実用的じゃない。その割に <code>var</code> を常にキーワード扱いできないのは構文ハイライトとかで結構困る</li>
<li>嫌がらせ以外で「<code>class var { }</code>」を書く人もいない</li>
<li>「<code>var</code> という名前の型は作るな」と説明できる</li>
<li>もしどうしても「<code>var</code> 型」を作りたければ <code>@var</code> と書けばいい</li>
</ol>
<h3>_ の場合</h3>
<p><a href="https://ufcpp.net/study/csharp/cheatsheet/ap_ver7/#discard">C# 7 で discard が導入された</a>わけですが、
これも「<code>_</code> を普通に変数として使っていないときに限り、<code>_</code> が discard の意味になる」という挙動になっています。</p>
<pre class="source" title="_ (discard)">
<span class="reserved">void</span> <span class="method">m1</span>(<span class="reserved">int</span> <span class="variable local">i</span>, <span class="reserved">string</span> <span class="variable local">s</span>)
{
    <span class="comment">// これはいずれも discard。</span>
    (<span class="reserved">_</span>, <span class="reserved">string</span> <span class="reserved">_</span>) <span class="operator">=</span> (<span class="variable local">i</span>, <span class="variable local">s</span>);
    <span class="reserved">int</span><span class="operator">.</span><span class="method"><span class="static">TryParse</span></span>(<span class="variable local">s</span>, <span class="reserved">out</span> <span class="reserved">_</span>);
}

<span class="reserved">void</span> <span class="method">m2</span>(<span class="reserved">int</span> <span class="variable local">i</span>, <span class="reserved">string</span> <span class="variable local">s</span>)
{
    <span class="reserved">var</span> <span class="variable">_</span> <span class="operator">=</span> <span class="variable local">i</span>; <span class="comment">// これがあるせいで…</span>

    (<span class="variable">_</span>, <span class="reserved">string</span> <span class="reserved">_</span>) <span class="operator">=</span> (<span class="variable local">i</span>, <span class="variable local">s</span>); <span class="comment">// ここの1個目の _ は変数。</span>
    <span class="reserved">int</span><span class="operator">.</span><span class="method"><span class="static">TryParse</span></span>(<span class="variable local">s</span>, <span class="reserved">out</span> <span class="variable">_</span>); <span class="comment">// ここの _ は変数。</span>
}

<span class="reserved">void</span> <span class="method">m3</span>(<span class="reserved">int</span> <span class="variable local">i</span>, <span class="reserved">string</span> <span class="variable local">s</span>)
{
    <span class="reserved">var</span> <span class="variable">_</span> <span class="operator">=</span> <span class="variable local">i</span>;
    <span class="reserved">var</span> <span class="variable"><span class="error" title="CS0128">_</span></span> <span class="operator">=</span> <span class="variable local">s</span>; <span class="comment">// これは「同じ名前の変数がすでにある」エラー。</span>

    (<span class="variable">_</span>, <span class="reserved">string</span> <span class="reserved">_</span>) <span class="operator">=</span> (<span class="variable local">i</span>, <span class="variable local">s</span>);
    <span class="reserved">int</span><span class="operator">.</span><span class="static"><span class="method">TryParse</span></span>(<span class="variable local">s</span>, <span class="reserved">out</span> <span class="variable">_</span>);
}
</pre>
<p>これについての前述の基準:</p>
<ol>
<li>今のままだといつ <code>_</code> が discard になるかわかりにくすぎる</li>
<li>元々 <code>_</code> を変数・引数として使っていた人も、「値を特に読まない」(なのでほんとは discard にしたい)という意味でこの名前を使うことが多い</li>
<li>「<code>_</code> が常に discard の意味になる」と説明できる</li>
<li><code>@_</code> と書けば「<code>_</code> という名前の変数」を書ける</li>
</ol>
<h2>破壊的変更の影響を軽減</h2>
<p>破壊的変更に対応しやすくするため、
C# <em>N</em> に対応したコンパイラーを使ったとき、
まだ C# <em>N - 1</em> 以下だった場合に警告と code-fix を提供したいとのこと。</p>
<p>現在、<code>LangVersion</code> を明示しなかった場合、
.NET SDK が「<code>TargetFramework</code> に応じた言語バージョンを自動選択する」という挙動になっています。</p>
<p>なので、例えば以下のような流れで比較的安全にバージョンアップができます。</p>
<ul>
<li>.NET 9 SDK をインストールすると C# 13 対応コンパイラーになる</li>
<li>この時点で既存のプロジェクトは <code>net8.0</code> とかがターゲットになっているはずで、C# 12 が選ばれる</li>
<li>「C# 13 対応コンパイラーで C# 12 を利用」状態なので、<code>field</code> に関する警告が出る</li>
<li>警告を直してから <code>net9.0</code> ターゲットに上げると安全にバージョンアップができる</li>
</ul>
<p>ただ、この手の警告の追加自体が破壊的変更
(警告は必ず取る方針であったり、なんなら WarnAsError オプションでエラーにできる)なので、
年に1回のメジャーバージョンアップ時以外には警告追加しないとのこと。</p>
<p>C# のバージョンアップを予定していない人向けに警告抑止の手段の提供や、
もしかしたら「先送りはするけどいつかバージョンアップしたい」人向けに「30日だけ警告を止める」みたいな手段を提供するのがいいかもしれないという話も出ています。</p>
<h3>LangVersion latest, preview</h3>
<p><a href="https://ufcpp.net/study/csharp/cheatsheet/langversionoption/#langversion">LangVersion</a> latest にすると、
常に C# コンパイラーが対応している最新の C# バージョンになります。
こうなると先ほどの「C# <em>N</em> 対応コンパイラーで C# <em>N - 1</em>」という状態が起きなくなるので、
「言語バージョンアップ前に破壊的変更を修正」ということができません。
なので、latest は今後非推奨にして、使っていたら警告を出すことを検討しているそうです。</p>
<p>一方で、LangVersion preview はわかってて使っている人柱向けですし、
プレビュー提供している言語機能は普通にリリースまでに破壊的変更がかかることもあって、
元から破壊的変更は覚悟の上で使っているはずです。
なので、preview に対しては特に問題視はしないそうです。</p>
 ]]></description>
				<pubDate>Sat, 10 Feb 2024 19:55:38 +0900</pubDate>
			</item>
			<item>
				<title>オブジェクト初期化子中の ^ 演算子</title>
				<link>http://ufcpp.net/blog/2024/2/hat-operator-in-object-initializer/</link>
				<description><![CDATA[ <p>今日の C# 話はちょこっとした修正の話になります。
これまで <code>new C { [^1] = 1 };</code> がコンパイル通らなかったみたいで、これが最近修正されました。</p>
<p>(Visual Studio 17.9 Preview 3 (1月17日リリース済み)の時点で実装されていました。
気づいてはいたけども、小さすぎてブログにするかどうか迷ってるうちに3週間ほど経過。)</p>
<p>以下のコードで示すような修正内容です。</p>
<pre class="source" title="オブジェクト初期化子中の ^ 演算子">
<span class="comment">// これがコンパイル エラーを起こす。</span>
<span class="comment">// (Visual Studio 17.9 Preview 3 以降を使うとコンパイルできるようになった。)</span>
<span class="reserved">var</span> <span class="variable">c</span> <span class="operator">=</span> <span class="reserved">new</span> <span class="type">C</span> { [<span class="operator">^</span><span class="number">1</span>] <span class="operator">=</span> <span class="number">1</span> };

<span class="comment">// これなら昔からコンパイル通る。</span>
<span class="comment">// (オブジェクト初期化子はこれと同じコードに展開されるはずなのに。)</span>
<span class="variable">c</span>[<span class="operator">^</span><span class="number">1</span>] <span class="operator">=</span> <span class="number">1</span>;

<span class="reserved">class</span> <span class="type">C</span>
{
    <span class="comment">// インデクサーと Length さえ持っていれば c[^i] と書けるようになる。</span>
    <span class="comment">// c[c.Length - i] 扱い。</span>
    <span class="reserved">public</span> <span class="reserved">int</span> <span class="property">Length</span> <span class="operator">=&gt;</span> <span class="number">1</span>;
    <span class="reserved">public</span> <span class="reserved">int</span> <span class="reserved">this</span>[<span class="reserved">int</span> <span class="variable local">i</span>] { <span class="reserved">get</span> <span class="operator">=&gt;</span> <span class="variable local">i</span>; <span class="reserved">set</span> { } }
}
</pre>
<p>まあ、<code>^</code> を導入した時にオブジェクト初期化子は考慮漏れしてたんですかね。</p>
<p>こんなのでも一応悩むポイントはありまして。
1つは、例えば入れ子で <code>new C() { [^1] = { [2] = 42, [3] = 43 } }</code> とか書いたとき、</p>
<pre class="source" title="2度 Length を評価">
<span class="comment">// 2行に分かれる = Length - 1 の計算が2度走る。</span>
<span class="reserved">var</span> <span class="variable">c</span> <span class="operator">=</span> <span class="reserved">new</span> <span class="type">C</span>();
<span class="variable">c</span>[<span class="operator">^</span><span class="number">1</span>][<span class="number">2</span>] <span class="operator">=</span> <span class="number">42</span>;
<span class="variable">c</span>[<span class="operator">^</span><span class="number">1</span>][<span class="number">3</span>] <span class="operator">=</span> <span class="number">43</span>;
</pre>
<p>か</p>
<pre class="source" title="^i をキャッシュして Length は1回限り評価">
<span class="comment">// ^ の結果をキャッシュする。</span>
<span class="reserved">var</span> <span class="variable">c</span> <span class="operator">=</span> <span class="reserved">new</span> <span class="type">C</span>();
<span class="reserved">var</span> <span class="variable">cachedIndexArgument</span> <span class="operator">=</span> <span class="operator">^</span><span class="number">1</span>;
<span class="variable">c</span>[<span class="variable">cachedIndexArgument</span>][<span class="number">2</span>] <span class="operator">=</span> <span class="number">42</span>;
<span class="variable">c</span>[<span class="variable">cachedIndexArgument</span>][<span class="number">3</span>] <span class="operator">=</span> <span class="number">43</span>;
</pre>
<p>か、どちらがいいかという問題。</p>
<p>もう1つ、<code>new C() { [^1] = { } }</code> みたいに入れ子の部分が空っぽの場合、<code>Length</code> を評価する必要はあるかどうかとかも。</p>
<p>「<code>Length</code> が副作用を持っている」とか「<code>c[^1]</code> が副作用で <code>Length</code> を書き換える」みたいな変なことをしているとこの辺りの結果が変わるわけで。</p>
<p>結局、以下のような選択をしたそうです。</p>
<ul>
<li>前者は、「<code>^</code> の結果をキャッシュする」の方を選択</li>
<li>後者は、<code>[^1] = { }</code> の時は評価しない(<code>Length - 1</code> の計算自体せず、<code>Length</code> の getter は呼ばない) を選択</li>
</ul>
<h2>おまけ: ちょっと予告</h2>
<p>あと、ちょこっと次回以降の予告。</p>
<p>しばらくブログ化していませんでしが C# 13 向けの作業がちらほら。
特に、2月に入ったくらいからアクティブで、結構検討が進んでいるみたいです。</p>
<p>最近見かけている話題を見出しだけ出しておくと以下の通り。</p>
<ul>
<li>コレクション式の改善</li>
<li>ジェネリクスで ref struct を使えるように</li>
<li>Extensions</li>
<li>ジェネリクスの部分型推論 <code>_</code></li>
<li>partial プロパティ</li>
<li>破壊的変更がらみ</li>
</ul>
<p>しばらくネタをため込んでしまったために大量に…
一気に書くと大変なので、次回以降、1個ずつブログにしようかと思います。</p>
 ]]></description>
				<pubDate>Thu, 08 Feb 2024 21:36:47 +0900</pubDate>
			</item>
			<item>
				<title>\e (エスケープ文字のエスケープ シーケンス)</title>
				<link>http://ufcpp.net/blog/2023/12/escape-escape/</link>
				<description><![CDATA[ <p>先々月書いた「<a href="https://ufcpp.net/blog/2023/10/triage2023/">C# 13 向けトリアージ</a>」で紹介してた C# 13 候補の1つ、「<code>\e</code> エスケープ シーケンス」が早々に実装されてたという話です。</p>
<p><a href="https://www.youtube.com/watch?v=1w-E4QgmAdg">.NET 8 正式リリース記念</a>の配信ではちょこっと触れてたんですが、そういえばブログには書いてなかったので紹介。</p>
<h2><a id="escape-character">エスケープ文字</a></h2>
<p>キーボードで打てないような文字や、画面に表示されない文字を入力したりするために、
「<code>\n</code> と書いたら改行(U+000A, new line, line feed)に置き換える」みたいな仕様があり、これをエスケープ シーケンス(escape sequence, 回避用の一連の文字列)と言います。</p>
<p>C# をはじめ、C 言語の影響を受けて作られた言語の多くは <code>\</code> (reverse solidus, 逆スラッシュ)で始まる文字列によってエスケープします。
プログラミング言語だと他には <code>`</code> (逆引用符、グレイブ アクセント, grave accent)とかを使うものがあったりしますが、
要は、利用頻度があまりない文字をエスケープ シーケンスの開始文字にすることが多いです。</p>
<p>一方で、ASCII コードには古よりずっと、<a href="https://ja.wikipedia.org/wiki/%E3%82%A8%E3%82%B9%E3%82%B1%E3%83%BC%E3%83%97%E6%96%87%E5%AD%97#ASCII%E3%82%A8%E3%82%B9%E3%82%B1%E3%83%BC%E3%83%97%E6%96%87%E5%AD%97">エスケープ文字</a>(U+001B, escape character)というものがあります。
名前通りエスケープ シーケンスの開始文字として使われるもので、
多くのターミナル アプリがこのエスケープ文字を使ったシーケンスに対応しています。
<a href="https://en.wikipedia.org/wiki/ANSI_escape_code">ANSI (American National Standards Institute) によって策定された標準仕様</a>があって、大体のターミナルはこの仕様に基づいた実装を持っています。
(この仕様は ANSI X3.64 というそうです。)</p>
<p>例えば C# で以下のようなコードを書いて実行すると、たいていの環境で赤い文字が表示されるはずです。</p>
<pre class="source" title="ANSI X3.64 を使って文字色を変える例">
<span class="type"><span class="static">Console</span></span><span class="operator">.</span><span class="method"><span class="static">WriteLine</span></span>(<span class="string">&quot;\u001b[31mred text&quot;</span>);
</pre>
<p><code>\u001b</code> がエスケープ文字(以下、ESC と表記)で、ESC + <code>[31m</code> という文字列を Console に書き込むとそれ以降の文字色が変わります。</p>
<h2><a id="escape-escape">エスケープのエスケープ</a></h2>
<p>そして C# 13 候補として、このエスケープ文字(U+001B)に対する C# のエスケープ シーケンスとして、<code>\e</code> が提案・承認されました。</p>
<p>C# 12 以前でも <code>\x</code> + 16進数2桁とか、<code>\u</code> + 16進数4桁とか、 <code>\U</code> + 16進数8桁とか、
任意の文字コードを直接打ち込むエスケープ手段があったので、別にそれほどなくて困るものでもなかったりはします。
以下のコードの <code>\x1b</code>, <code>\u001b</code>, <code>\U0000001b</code> はいずれもエスケープ文字です。</p>
<pre class="source" title="\x, \u, \U">
<span class="static"><span class="type">Console</span></span><span class="operator">.</span><span class="static"><span class="method">WriteLine</span></span>(<span class="string">&quot;\x1b[31mred text&quot;</span>);
<span class="type"><span class="static">Console</span></span><span class="operator">.</span><span class="method"><span class="static">WriteLine</span></span>(<span class="string">&quot;\u001b[4munderlined text&quot;</span>);
<span class="type"><span class="static">Console</span></span><span class="operator">.</span><span class="method"><span class="static">WriteLine</span></span>(<span class="string">&quot;\U0000001b[0mreset style&quot;</span>);
</pre>
<p>古からある仕様ですが、
長らく C# の主戦場だった Windows では
「文字のスタイル変更は <code>Console.ForegroundColor</code> などの API 経由で行ってほしい」
みたいな感じで、あまり ANSI X3.64 を利用する文化ではありませんでした。</p>
<p>しかし最近は Linux 上での C# 利用も増え、
Windows も<a href="https://apps.microsoft.com/detail/9N0DX20HK701?hl=ja-jp&amp;gl=JP">今時っぽい新しいターミナル</a>を搭載するようになり、
ANSI X3.64 を積極的に使いたいという要望がちらほら増えてきました。</p>
<p>また、
Windows Terminal が新しくなった今となっては、
<code>Console.ForegroundColor</code> などの .NET の API を使って操作できるものよりも、
ANSI X3.64 でやれることの方が多くなっていたりします。</p>
<p>そこで出てきたのが<a href="https://github.com/dotnet/csharplang/issues/7400"> <code>\e</code> でエスケープ文字を表せるようにしてほしい</a>という要望。</p>
<h2><a id="proposal">\e 提案の検討</a></h2>
<p>この提案で得られるメリットや、かかるコストを考えてみましょう。</p>
<p>まずメリットの方。
前節で書いた通り、エスケープ文字を使いたいことはちらほらないこともなく、「あれば便利かも」とは思います。
とはいえ、毎回自分で ANSI X3.64 を書くかと言われると微妙。
「31番が赤」とかいちいち覚えないですからね。
C# でも、ANSI X3.64 出力用のライブラリを提供してくれている方がいらっしゃいます: <a href="https://github.com/Cysharp/Kokuban">Kokuban</a> (安定の Cysharp)。</p>
<p>また、元から <code>\x1b</code> と書けたわけで、「<code>\e</code> と書けるようになって楽かどうか」と言われるとたった2文字の短縮です。
もちろん、「エスケープ文字の文字コードは何だったっけ？」というのを覚えるよりは「エスケープの頭文字をとって <code>e</code>」というのの方が覚えやすそうではあります。</p>
<p>コストに関しては、エスケープ シーケンスの解析用の <code>switch</code> ステートメントに1個 <code>case</code> を追加するだけです。
以下のたった3行の追加。</p>
<pre class="source" title="\e 対応のためのコード">
    <span class="control">case</span> <span class="string">'e'</span>:
        <span class="variable">ch</span> <span class="operator">=</span> <span class="string">'\u001b'</span>;
        <span class="control">break</span>;
</pre>
<p>「C# 12 以下では使えない」みたいな判定を足すとしてもさらに追加で +3 行。
テストとかを足しても数百行程度の修正になります。
ここの <code>case</code> 1個くらいならコンパイル実行時のコストもほとんどなし。</p>
<p>要するに、割かし毒にも薬にもならない、低コスト低リターンな提案ということになります。</p>
<p>なので、<a href="https://github.com/dotnet/csharplang/discussions/7603">C# チームによる判定</a>は「Any Time」。
この「Any Time」は、</p>
<ul>
<li>自分たちで実装の労力は割かない</li>
<li>コミュニティによる Pull Request が来た場合は受け付ける</li>
</ul>
<p>みたいな温度感です。</p>
<h2><a id="implemented">そして実装</a></h2>
<p>「Any Time」のわりにもうすでに実装されたものがあるわけですが。
以下のコード、Visual Studio 17.9 Preview 1 (11月15日にリリース) で動きます。</p>
<pre class="source" title="\e エスケープ、もう動いてる">
<span class="static"><span class="type">Console</span></span><span class="operator">.</span><span class="static"><span class="method">WriteLine</span></span>(<span class="string">&quot;\e[31mred text&quot;</span>);
<span class="type"><span class="static">Console</span></span><span class="operator">.</span><span class="method"><span class="static">WriteLine</span></span>(<span class="string">&quot;\e[4munderlined text&quot;</span>);
<span class="type"><span class="static">Console</span></span><span class="operator">.</span><span class="method"><span class="static">WriteLine</span></span>(<span class="string">&quot;\e[0mreset style&quot;</span>);
</pre>
<p><img src="/media/1217/escapeescape.png" alt="\e もう動いてる" /></p>
<p>普通、コミュニティ実装だとそこそこ時間がかかるんですけどね。
何せ、「専業でやっているわけじゃない外部の人のコードのレビュー」みたいなプロセスを経るので。</p>
<p><code>\e</code> に関しては、</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/7400#issuecomment-1765078956">10月17日に「Any Time」で承認</a></li>
<li><a href="https://github.com/dotnet/roslyn/pull/70497">10月21日に Pull Request 出る</a></li>
<li>10月24日に Pull Request が通る</li>
<li><a href="https://github.com/dotnet/roslyn/issues/70634">10月31日に main ブランチに merge</a></li>
</ul>
<p>という感じ。
「Any Time」とは…</p>
<p>Pull Request を作った方、C# チームの人ですしね。
定時後とかにさらっとやっちゃった感じかなぁと。
<a href="https://github.com/dotnet/roslyn/pull/23984">ホリデーの飛行機の中で embedded language を実装しちゃうような人</a>なので。</p>
<p>ということで、「.NET 9 のプレビュー版もまだ出てないのにもう C# 13 候補機能の1つが実装されてリリースされてる」という面白状況に。</p>
 ]]></description>
				<pubDate>Tue, 05 Dec 2023 22:42:39 +0900</pubDate>
			</item>
			<item>
				<title>C# 13 向けトリアージ</title>
				<link>http://ufcpp.net/blog/2023/10/triage2023/</link>
				<description><![CDATA[ <p>.NET 8 も RC 2 な段階になって、ここから GA までの間に仕様が変わるということはほとんどなくなってきました。
となると、話題はもうその次。来年向け(C# 13 / .NET 9 ターゲット)の話が出てきます。
C# Design Meeting でも、13向けのトリアージがちらほら始まりました。</p>
<p>とりあえず現状、2件。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/discussions/7587">LDM Notes for October 9th, 2023</a></li>
<li><a href="https://github.com/dotnet/csharplang/discussions/7603">LDM Notes for October 16th, 2023</a></li>
</ul>
<p>以下のようなものがトリアージされました。</p>
<h2>10/9 議事録</h2>
<h3>ReadOnlySpan initialization from static data 5295</h3>
<p><a href="https://github.com/dotnet/csharplang/issues/5295">#5295</a></p>
<p>C# 7.2 辺りから、以下のような「配列のアロケーションを消す」最適化が掛かります。</p>
<pre class="source" title="配列が消える">
<span class="comment">// 定数だけで構成された byte 配列は最適化で消える。</span>
<span class="comment">// new ReadOnlySpan&lt;byte&gt;(静的データのポインター, 4) みたいなコードに展開される。</span>
<span class="type struct">ReadOnlySpan</span>&lt;<span class="reserved">byte</span>&gt; <span class="variable">data1</span> <span class="operator">=</span> <span class="reserved">new</span> <span class="reserved">byte</span>[] { <span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span> };

<span class="comment">// .NET 7 までは byte, sbyte のみだったけど、 .NET 8 からはそれ以外の整数にも最適化がかかるように。</span>
<span class="type struct">ReadOnlySpan</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">data2</span> <span class="operator">=</span> <span class="reserved">new</span> <span class="reserved">int</span>[] { <span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span> };
</pre>
<p>けども、見た目はどう見ても配列を作っているので、たびたび「この配列を new するのもったいなくない？」という突っ込みが入りがちです。</p>
<p>そこで、以下のような「ReadOnlySpan の初期化構文が欲しい」という話がありました。</p>
<pre class="source" title="Span 初期化構文(案)">
<span class="type struct">ReadOnlySpan</span>&lt;<span class="reserved">byte</span>&gt; <span class="variable">data1</span> <span class="operator">=</span> { <span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span> };

<span class="type struct">ReadOnlySpan</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">data2</span> <span class="operator">=</span> { <span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span> };
</pre>
<p>ですが、C# 12 で入る予定の<a href="https://ufcpp.net/blog/2023/1/collection-literal/">コレクション式</a>がこれを兼ねるので、この <code>{}</code> を使った書き方はリジェクトになりました。</p>
<h3>Embedded Language Indicators for raw string literals 6247</h3>
<p><a href="https://github.com/dotnet/csharplang/issues/6247">#6247</a></p>
<pre class="source" title="インジケーター案">
<span class="comment">// こんな風に、raw string の先頭行に「文字列リテラルの中身が何か」を示すインジケーターを書きたいという案。</span>
<span class="reserved">var</span> <span class="variable">y</span> <span class="operator">=</span> <span class="string">&quot;&quot;&quot;regex
    \s+
    &quot;&quot;&quot;</span>;

<span class="comment">// ちなみに今も、以下のように「文字列リテラル直前のコメントに lang = を付ける」という手段でインジケーターを書ける。</span>
<span class="comment">// Visual Studio はこれを認識して色付けしたり補間したりしてくれる。</span>

<span class="comment">// lang=regex</span>
<span class="reserved">var</span> <span class="variable">y</span> <span class="operator">=</span> <span class="string">&quot;&quot;&quot;
    \s+
    &quot;&quot;&quot;</span>;
</pre>
<p>優先度付くほど強いモチベーションがなさげ。
Backlog (過去ログ行き)。</p>
<h3>list-patterns on enumerables</h3>
<p><a href="https://github.com/dotnet/csharplang/issues/6574">#6574</a></p>
<p><code>IEnumerable</code> に対して <code>x is []</code> とか書けるようにしたいというやつ。</p>
<p>時間がなくて12でも入らなかっただけ。
Working set (作業中)。</p>
<h3>Make generated <code>Program</code>` for top-level statements public by default</h3>
<p><a href="https://github.com/dotnet/csharplang/issues/6769">#6769</a></p>
<p><a href="https://ufcpp.net/study/csharp/cheatsheet/ap_ver9/#top-level-statements">トップ レベル ステートメント</a>から生成される Program クラスを public にしたいという話。</p>
<p>一番のモチベはテストだけど。
テスト関連、もっと広く要件調査必要。</p>
<h3>CallerCharacterNumberAttribute</h3>
<p><a href="https://github.com/dotnet/csharplang/issues/3992">#3992</a></p>
<p><a href="https://ufcpp.net/study/csharp/ap_ver5.html#CallerInfo">Caller Info 属性</a>に追加で「ソースコードの何列目か」を取れるものを足したいという話。
(今、CallerLineNumber で行番号は取れるけども、列を取る手段がない。)</p>
<p><a href="https://github.com/ufcpp/UfcppSample/issues/456">Interceptor</a>と一環としてやる。</p>
<h3>Add private and namespace accessibility modifiers for top-level types</h3>
<p><a href="https://github.com/dotnet/csharplang/issues/6794">#6794</a></p>
<p>「同一の名前空間内限定でアクセスできる」というアクセスレベルの新設。
<a href="https://ufcpp.net/study/csharp/cheatsheet/ap_ver11/#file-local">file</a> は狭すぎるし、<a href="https://ufcpp.net/study/csharp/oo_conceal.html#protected-internal">internal</a> は広すぎる。</p>
<p>やる気になってるっぽい(Working set)。</p>
<h3>Require await to apply nullable postconditions to task-returning calls</h3>
<p><a href="https://github.com/dotnet/csharplang/issues/6888">#6888</a></p>
<p>非同期メソッドが絡んだ時に <code>MemberNotNull</code>` とかがちゃんと働かない問題。</p>
<p>作業中。もらったフィードバックに対処が必要。</p>
<h3>is expression evaluating const expression should be considered constant</h3>
<p><a href="https://github.com/dotnet/csharplang/issues/6926">#6926</a></p>
<pre class="source" title="const is expression">
<span class="reserved">const</span> <span class="reserved">int</span> <span class="constant"><span class="static">x</span></span> <span class="operator">=</span> <span class="number">123</span>;
<span class="reserved">const</span> <span class="reserved">bool</span> <span class="static"><span class="constant">y</span></span> <span class="operator">=</span> <span class="constant">x</span> <span class="operator">==</span> <span class="number">0</span>; <span class="comment">// これは OK。const 同士に対する式の結果は const。</span>
<span class="reserved">const</span> <span class="reserved">bool</span> <span class="static"><span class="constant">z</span></span> <span class="operator">=</span> <span class="error" title="CS0133"><span class="constant">x</span> <span class="reserved">is</span> <span class="number">0</span></span>; <span class="comment">// 今ダメ。 == が行けるんなら is も行けていいんじゃない？</span>
</pre>
<p>Any time (C# チーム内ではやらないけど、コミュニティ貢献受付はできる)。
実際、<a href="https://github.com/dotnet/csharplang/pull/7589">コミュニティ実装が始まってそう</a>。</p>
<h2>10/16 議事録</h2>
<h3>Breaking change warnings</h3>
<p><a href="https://github.com/dotnet/csharplang/issues/7189">#7189</a></p>
<p>「C# 14 で破壊的変更になる予定だから注意してね」警告みたいなやつを C# 13 以下に対して出そうかという話。
(主に、field キーワード導入がモチベ。)</p>
<p>これについて書いたブログ: <a href="https://ufcpp.net/blog/2023/3/csharp-breaking-change/">C# での破壊的変更の今後の扱い(案)</a></p>
<p>普通に作業中。
10/9 のミーティングでは取り上げ忘れてただけ。
Working set。</p>
<h3>Determine natural type of method group by looking scope-by-scope</h3>
<p><a href="https://github.com/dotnet/csharplang/issues/7364">#7364</a></p>
<p><a href="https://github.com/dotnet/csharplang/issues/7429">#7429</a> との重複扱いで close。</p>
<h3>u8 string interpolation</h3>
<p><a href="https://github.com/dotnet/csharplang/issues/7072">#7072</a></p>
<p><code>$&quot;直接 UTF-8 で書き込まれる文字列補間 {x} {y}&quot;u8</code> (u8 接尾辞) みたいなのが欲しいという話は上がってたんだけど。</p>
<p>.NET 8 の並々ならぬ努力の結果、JIT 最適化がだいぶ賢くなった。</p>
<pre class="source" title=".NET 8 の Utf8.TryWrite は UTF-16 → UTF-8 変換がほぼノーコスト">
<span class="reserved">using</span> System<span class="operator">.</span>Text<span class="operator">.</span>Unicode;

<span class="reserved">int</span> <span class="variable">x</span> <span class="operator">=</span> <span class="number">123</span>;
<span class="reserved">int</span> <span class="variable">y</span> <span class="operator">=</span> <span class="number">456</span>;
<span class="type struct">Span</span>&lt;<span class="reserved">byte</span>&gt; <span class="variable">dest</span> <span class="operator">=</span> <span class="reserved">stackalloc</span> <span class="reserved">byte</span>[<span class="number">100</span>];

<span class="static"><span class="type">Utf8</span></span><span class="operator">.</span><span class="method"><span class="static">TryWrite</span></span>(<span class="variable">dest</span>, <span class="string">$&quot;</span><span class="string">UTF-8 補間 </span>{<span class="variable">x</span>}<span class="string"> </span>{<span class="variable">y</span>}<span class="string">&quot;</span>, <span class="reserved">out</span> <span class="reserved">var</span> <span class="variable">written</span>);
<span class="comment">// ↑ 普通の(UTF-16 な)文字列補間だけど、JIT の努力によって UTF-16 → UTF-8 への変換がほぼノーコストに最適化される。</span>
</pre>
<p>その結果、 <code>$&quot;&quot;u8</code> の要求減った。
Backlog 行き。</p>
<h3>Lock statement pattern</h3>
<p><a href="https://github.com/dotnet/csharplang/issues/7104">#7104</a></p>
<p><code>lock (obj)</code> もパターンベースにしたいという話。</p>
<p>.NET の「任意の object を lock に使える」、「オブジェクトヘッダーに lock 用の syncblock って領域を持ってる」という仕様、オーバーヘッドが大きいので、ちゃんと <a href="https://github.com/dotnet/runtime/issues/34812"><code>Lock</code>` 型</a>みたいなのを用意してそれを使って lock したい。</p>
<p>この <code>Lock</code> 型インスタンスに対して <code>lock (_lock)</code> されたときに、syncblock 使わず、パターンベースで <code>Lock.TryEnter</code> が呼ばれるようにしたい。</p>
<p>.NET 9 マイルストーンで Working set に。</p>
<h3>String/Character escape sequence \e as a short-hand for \u001b ()</h3>
<p><a href="https://github.com/dotnet/csharplang/issues/7400">#7400</a></p>
<p>エスケープ文字(U+001B)に対するエスケープシーケンス <code>\e</code> を導入したい。</p>
<p>Any time に(今、<a href="https://github.com/dotnet/csharplang/issues/7400#issuecomment-1765085640">提案者に対してコミュニティ実装するか聞いてる</a>ところ)。</p>
<h3>New operator %% for canonical Modulus operations</h3>
<p><a href="https://github.com/dotnet/csharplang/issues/7599">#7599</a></p>
<p>C# の <code>%</code> 演算子 (というか、大体の CPU の div rem 命令) は、オペランドの符号によっては 0～n-1 にならない。
それに対して、<code>array[x % array.Length]</code> みたいな用途では 0～n-1 になってほしい。</p>
<p>という、需要はあるものの、C# 言語組み込みでやるべきかどうかは疑問。
div rem にはいろいろ種類があるんで、メソッド名とかメソッド引数で「どの div か」を明示すべきという話に支持が集まってる。</p>
<p>なので C# としてはやらない(likely never)。</p>
<p>代わりにライブラリ追加の提案が runtime の方で進みそう (<a href="https://github.com/dotnet/runtime/issues/93568">#93568</a>)。
↓提案内容。</p>
<pre class="source" title="">
<span class="reserved">namespace</span> System<span class="operator">.</span>Numerics;

<span class="reserved">public</span> <span class="reserved">enum</span> <span class="type">DivisionRounding</span>
{
    Truncate <span class="operator">=</span> <span class="number">0</span>,        <span class="comment">// Towards Zero</span>
    Floor <span class="operator">=</span> <span class="number">1</span>,           <span class="comment">// Towards -Infinity</span>
    Ceiling <span class="operator">=</span> <span class="number">2</span>,         <span class="comment">// Towards +Infinity</span>
    AwayFromZero <span class="operator">=</span> <span class="number">3</span>,    <span class="comment">// Away from Zero</span>
    Euclidean <span class="operator">=</span> <span class="number">4</span>,       <span class="comment">// floor(x / abs(n)) * sign(n)</span>
}

<span class="reserved">public</span> <span class="reserved">partial</span> <span class="reserved">interface</span> <span class="type">IBinaryInteger</span>&lt;<span class="type param">TSelf</span>&gt;
{
    <span class="comment">// Existing:</span>
    <span class="reserved">static</span> <span class="reserved">virtual</span> (<span class="type param">TSelf</span> Quotient, <span class="type param">TSelf</span> Remainder) <span class="method"><span class="static">DivRem</span></span>(<span class="type param">TSelf</span> <span class="variable local">left</span>, <span class="type param">TSelf</span> <span class="variable local">right</span>);

    <span class="comment">// Proposed:</span>
    <span class="reserved">static</span> <span class="reserved">virtual</span> <span class="type param">TSelf</span> <span class="static"><span class="method">Divide</span></span>(<span class="type param">TSelf</span> <span class="variable local">left</span>, <span class="type param">TSelf</span> <span class="variable local">right</span>, <span class="type">DivisionRounding</span> <span class="variable local">mode</span>);
    <span class="reserved">static</span> <span class="reserved">virtual</span> (<span class="type param">TSelf</span> Quotient, <span class="type param">TSelf</span> Remainder) <span class="static"><span class="method">DivRem</span></span>(<span class="type param">TSelf</span> <span class="variable local">left</span>, <span class="type param">TSelf</span> <span class="variable local">right</span>, <span class="type">DivisionRounding</span> <span class="variable local">mode</span>);
    <span class="reserved">static</span> <span class="reserved">virtual</span> <span class="type param">TSelf</span> <span class="method"><span class="static">Remainder</span></span>(<span class="type param">TSelf</span> <span class="variable local">left</span>, <span class="type param">TSelf</span> <span class="variable local">right</span>, <span class="type">DivisionRounding</span> <span class="variable local">mode</span>);
}
</pre> ]]></description>
				<pubDate>Wed, 18 Oct 2023 21:14:51 +0900</pubDate>
			</item>
			<item>
				<title>Length-based switch dispatch</title>
				<link>http://ufcpp.net/blog/2023/8/lengthbasedswitch/</link>
				<description><![CDATA[ <p>「そういやブログに書いてなかった」ネタ。
<a href="https://github.com/dotnet/roslyn/pull/66081">Pull Request</a> が通った
プレビュー版(Visual Studio 16.6 Preview 1)でよければ今年の2月頃から使えてた話です。</p>
<p>文字列に対する <code>switch</code> に新しい最適化手法が導入されました。</p>
<h2><a id="traditional-switch">元々の switch のコスト</a></h2>
<p>例として以下のような <code>switch</code> を考えます。</p>
<pre class="source" title="文字列に対する switch の例">
<span class="reserved">static</span> <span class="reserved">int</span> <span class="method"><span class="static">StringSwitch</span></span>(<span class="reserved">string</span> <span class="variable local">s</span>) <span class="operator">=&gt;</span> <span class="variable local">s</span> <span class="control">switch</span>
{
    <span class="string">&quot;abc&quot;</span> <span class="operator">=&gt;</span> <span class="number">0</span>,
    <span class="string">&quot;def&quot;</span> <span class="operator">=&gt;</span> <span class="number">1</span>,
    <span class="string">&quot;ghi&quot;</span> <span class="operator">=&gt;</span> <span class="number">2</span>,
    <span class="string">&quot;01234a&quot;</span> <span class="operator">=&gt;</span> <span class="number">3</span>,
    <span class="string">&quot;01234b&quot;</span> <span class="operator">=&gt;</span> <span class="number">4</span>,
    <span class="string">&quot;01234c&quot;</span> <span class="operator">=&gt;</span> <span class="number">5</span>,
    <span class="string">&quot;aaaaaaaa&quot;</span> <span class="operator">=&gt;</span> <span class="number">6</span>,
    <span class="reserved">_</span> <span class="operator">=&gt;</span> <span class="operator">-</span><span class="number">1</span>,
};
</pre>
<p>C# コンパイラー的には、</p>
<ul>
<li><code>case</code> 少なければ単に上から順に <code>if (s == &quot;...&quot;)</code> を並べる</li>
<li>多ければ IL の switch 命令を出力</li>
</ul>
<p>みたいな処理をしていました。</p>
<p>ちなみに、IL の switch 命令は、</p>
<ol>
<li>各 <code>case</code> 文字列に対応するハッシュ値を事前計算</li>
<li><code>s.GetHashCode()</code> で <code>switch</code> する</li>
</ol>
<p>みたいなコードを生成するそうです。</p>
<p><code>if (s == &quot;...&quot;)</code> を並べる方式はワーストケースでは多数の <code>==</code> 比較がかかりますし、
文字列に対する <code>GetHashCode</code> の計算は意外と重たい処理です。</p>
<h2><a id="length-based-switch">新手法 switch</a></h2>
<p>Visual Studio 17.6 (Roslyn 4.6) 以降では、<code>case</code> の数が中程度のとき、
以下のような分岐をかけるようになりました
(<a href="https://ja.wikipedia.org/wiki/%E3%83%88%E3%83%A9%E3%82%A4_(%E3%83%87%E3%83%BC%E3%82%BF%E6%A7%8B%E9%80%A0)">Trie木</a>的発想の簡易アルゴリズム)。</p>
<ol>
<li>文字列長でまず分岐</li>
<li>どこか1文字だけを使って <code>char</code> で <code>switch</code></li>
<li>その後に <code>string</code> の <code>==</code> 判定</li>
</ol>
<p>Length-based switch dispatch (文字列長ベースの switch 分配)というそうです。</p>
<p>先ほどの例の <code>switch</code> だと、おおむね以下のような感じの分岐に置き換わります。
(実際はもうちょっと goto だらけのコードになりますが、
見やすさ優先で変更。)</p>
<pre class="source" title="length-based switch の例">
<span class="static"><span class="method">StringSwitch</span></span>(<span class="string">&quot;&quot;</span>);

<span class="reserved">static</span> <span class="reserved">int</span> <span class="method"><span class="static">StringSwitch</span></span>(<span class="reserved">string</span> <span class="variable local">s</span>) <span class="operator">=&gt;</span> <span class="variable local">s</span><span class="operator">.</span><span class="property">Length</span> <span class="control">switch</span>
{
    <span class="number">3</span> <span class="operator">=&gt;</span> <span class="variable local">s</span>[<span class="number">0</span>] <span class="control">switch</span>
    {
        <span class="string">'a'</span> <span class="operator">=&gt;</span> <span class="variable local">s</span> <span class="operator">==</span> <span class="string">&quot;abc&quot;</span> <span class="operator">?</span> <span class="number">0</span> <span class="operator">:</span> <span class="operator">-</span><span class="number">1</span>,
        <span class="string">'d'</span> <span class="operator">=&gt;</span> <span class="variable local">s</span> <span class="operator">==</span> <span class="string">&quot;def&quot;</span> <span class="operator">?</span> <span class="number">1</span> <span class="operator">:</span> <span class="operator">-</span><span class="number">1</span>,
        <span class="string">'g'</span> <span class="operator">=&gt;</span> <span class="variable local">s</span> <span class="operator">==</span> <span class="string">&quot;ghi&quot;</span> <span class="operator">?</span> <span class="number">2</span> <span class="operator">:</span> <span class="operator">-</span><span class="number">1</span>,
        <span class="reserved">_</span> <span class="operator">=&gt;</span> <span class="operator">-</span><span class="number">1</span>,
    },
    <span class="number">6</span> <span class="operator">=&gt;</span> <span class="variable local">s</span>[<span class="number">5</span>] <span class="control">switch</span>
    {
        <span class="string">'a'</span> <span class="operator">=&gt;</span> <span class="variable local">s</span> <span class="operator">==</span> <span class="string">&quot;01234a&quot;</span> <span class="operator">?</span> <span class="number">3</span> <span class="operator">:</span> <span class="operator">-</span><span class="number">1</span>,
        <span class="string">'b'</span> <span class="operator">=&gt;</span> <span class="variable local">s</span> <span class="operator">==</span> <span class="string">&quot;01234b&quot;</span> <span class="operator">?</span> <span class="number">4</span> <span class="operator">:</span> <span class="operator">-</span><span class="number">1</span>,
        <span class="string">'c'</span> <span class="operator">=&gt;</span> <span class="variable local">s</span> <span class="operator">==</span> <span class="string">&quot;01234c&quot;</span> <span class="operator">?</span> <span class="number">5</span> <span class="operator">:</span> <span class="operator">-</span><span class="number">1</span>,
        <span class="reserved">_</span> <span class="operator">=&gt;</span> <span class="operator">-</span><span class="number">1</span>,
    },
    <span class="number">8</span> <span class="operator">=&gt;</span> <span class="variable local">s</span> <span class="operator">==</span> <span class="string">&quot;aaaaaaaa&quot;</span> <span class="operator">?</span> <span class="number">6</span> <span class="operator">:</span> <span class="operator">-</span><span class="number">1</span>,
    <span class="reserved">_</span> <span class="operator">=&gt;</span> <span class="operator">-</span><span class="number">1</span>,
};
</pre>
<p>これで、どの <code>case</code> にも当たらないときには「長さ比較 + 1文字比較」で終わり、
当たった時でもそれに加えて少数の文字列 <code>==</code> になります。</p>
<p>例えば .NET の中の人が <a href="https://github.com/dotnet/roslyn/issues/56374">HTTP の content type 用の分岐で測った</a>感じだと、
5～10倍くらい速いみたいです。</p>
 ]]></description>
				<pubDate>Thu, 03 Aug 2023 22:36:41 +0900</pubDate>
			</item>
			<item>
				<title>モジュール初期化子が呼ばれる順</title>
				<link>http://ufcpp.net/blog/2023/6/init-order/</link>
				<description><![CDATA[ <p><a href="https://ufcpp.net/blog/2023/6/ca-specify-culture/">前回のブログ</a>に続き、
<a href="https://www.youtube.com/watch?v=M5weHOCzJ6E">先日の C# 配信</a>で出てたネタ。</p>
<p>まあ、今回のは知ったところで誰が助かるということもないようなトリビア的な話です。</p>
<h2>後だし優先で上書き</h2>
<p>その C# 配信内で、
「<a href="https://github.com/ufcpp-live/UfcppLiveAgenda/issues/73#issuecomment-1595764176"><code>CultureInfo.DefaultThreadCurrentCulture</code> を上書きすれば対処はできるけども</a>」
みたいな話が出まして。</p>
<p>ただ、まあ、こういう「グローバルに影響がある静的プロパティの書き換え」は決してお行儀はよくないじゃないですか。
誰でも、いつでも上書き可能。
すぐに競合しかねません。</p>
<p>例えばここで出した
<code>DefaultThreadCurrentCulture</code> だと、
人それぞれ、以下のようなバラバラの主張が混ざったとします。</p>
<ul>
<li>常に <code>InvariantCulture</code> にしたい</li>
<li>常に ja-jp カルチャーにしたい</li>
<li>基本、<code>InvariantCulture</code> でいいものの、日付の書式だけは <code>MM-dd-yyyy</code> が許せないので上書きする</li>
</ul>
<p>そしてしかも、これを「ソース ジェネレーターとかを使って裏でこっそり書き換えておきたい」とかやったときに、誰の主張が通ってしまうでしょうという問題。</p>
<pre class="source" title="一体どの主張が通ってしまうのか">
<span class="reserved">using</span> System<span class="operator">.</span>Globalization;
<span class="reserved">using</span> System<span class="operator">.</span>Runtime<span class="operator">.</span>CompilerServices;

<span class="comment">// file: A.cs</span>
<span class="reserved">class</span> <span class="type">Aさんの主張</span>
{
    [<span class="type">ModuleInitializer</span>]
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">Init</span></span>()
    {
        <span class="type">CultureInfo</span><span class="operator">.</span><span class="property"><span class="static">DefaultThreadCurrentCulture</span></span> <span class="operator">=</span> <span class="type">CultureInfo</span><span class="operator">.</span><span class="property"><span class="static">InvariantCulture</span></span>;
    }
}

<span class="comment">// file: B.cs</span>
<span class="reserved">class</span> <span class="type">Bさんの主張</span>
{
    [<span class="type">ModuleInitializer</span>]
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">Init</span></span>()
    {
        <span class="type">CultureInfo</span><span class="operator">.</span><span class="property"><span class="static">DefaultThreadCurrentCulture</span></span> <span class="operator">=</span> <span class="reserved">new</span> <span class="type">CultureInfo</span>(<span class="string">&quot;ja-JP&quot;</span>);
    }
}

<span class="comment">// file: C.cs</span>
<span class="reserved">class</span> <span class="type">Cさんの主張</span>
{
    [<span class="type">ModuleInitializer</span>]
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="static"><span class="method">Init</span></span>()
    {
        <span class="reserved">var</span> <span class="variable">c</span> <span class="operator">=</span> (<span class="type">CultureInfo</span>)<span class="type">CultureInfo</span><span class="operator">.</span><span class="property"><span class="static">InvariantCulture</span></span><span class="operator">.</span><span class="method">Clone</span>();
        <span class="variable">c</span><span class="operator">.</span><span class="property">DateTimeFormat</span><span class="operator">.</span><span class="property">LongDatePattern</span> <span class="operator">=</span> <span class="string">&quot;yyyy'-'MM'-'dd&quot;</span>;
        <span class="variable">c</span><span class="operator">.</span><span class="property">DateTimeFormat</span><span class="operator">.</span><span class="property">LongTimePattern</span> <span class="operator">=</span> <span class="string">&quot;HH':'mm':'ss&quot;</span>;
        <span class="variable">c</span><span class="operator">.</span><span class="property">DateTimeFormat</span><span class="operator">.</span><span class="property">MonthDayPattern</span> <span class="operator">=</span> <span class="string">&quot;MM'-'dd&quot;</span>;
        <span class="variable">c</span><span class="operator">.</span><span class="property">DateTimeFormat</span><span class="operator">.</span><span class="property">YearMonthPattern</span> <span class="operator">=</span> <span class="string">&quot;yyyy'-'MM&quot;</span>;
        <span class="variable">c</span><span class="operator">.</span><span class="property">DateTimeFormat</span><span class="operator">.</span><span class="property">ShortDatePattern</span> <span class="operator">=</span> <span class="string">&quot;yyyy'-'MM'-'dd&quot;</span>;
        <span class="variable">c</span><span class="operator">.</span><span class="property">DateTimeFormat</span><span class="operator">.</span><span class="property">ShortTimePattern</span> <span class="operator">=</span> <span class="string">&quot;HH':'mm':'ss&quot;</span>;
        <span class="type">CultureInfo</span><span class="operator">.</span><span class="property"><span class="static">DefaultThreadCurrentCulture</span></span> <span class="operator">=</span> <span class="variable">c</span>;
    }
}
</pre>
<p>そしてこの話題から、「後だし優先といわれても、
じゃあ、<a href="https://ufcpp.net/study/csharp/oop/moduleinitializer/">モジュール初期化子</a>の実行順序は決まっているの？」という話題になります。</p>
<h2>呼び出し順序</h2>
<p>「<a href="https://ufcpp.net/study/csharp/oop/moduleinitializer/#module-initializer-impl">モジュール初期化子の実装方法</a>」のところで書いてるんですが、
C# 的に「1つのモジュールに複数のモジュール初期化子がある」とき、
コンパイル結果的には「本当のモジュール初期化子は1つで、その中で複数のメソッドを呼ぶ」みたいな実装になっています。
問題はこの「複数のメソッド呼び出し」がどういう順序で並ぶか。</p>
<p>C# の仕様書上は「reserved, but deterministic order」
(詳細は明言せず将来変更の余地を残す、ただし決定論的な順序)
となっているみたいです。
こういう場合、同じ環境(同じツールの同じバージョン)でコンパイルする限りは、
同じソースコードからは同じ実行ファイルができます。
その一方で、環境が変わると結果が変わる可能性あり。</p>
<p>ここでは現時点での実装がどうなっているかという話もしておきましょう。</p>
<h3>同じファイルの中</h3>
<p>まずは同じファイルの中に複数のモジュール初期化子を書いた場合。
これはまあ結構単純で、上から順番です。</p>
<p>メタデータ的に、同じ名前空間内のクラスは書いた順に並ぶし、
クラスのメンバーも書いた順に並びます。
モジュール初期化子はその順で呼ばれます。</p>
<p>例えば以下のようなコードを1つのファイルに書いた場合、</p>
<pre class="source" title="複数のモジュール初期化子を1ファイルに並べる例">
<span class="reserved">using</span> System<span class="operator">.</span>Runtime<span class="operator">.</span>CompilerServices;

<span class="reserved">class</span> <span class="type">Z</span>
{
    [<span class="type">ModuleInitializer</span>]
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="static"><span class="method">Init1</span></span>() { }

    [<span class="type">ModuleInitializer</span>]
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">Init2</span></span>() { }
}

<span class="reserved">class</span> <span class="type">Y</span>
{
    [<span class="type">ModuleInitializer</span>]
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="static"><span class="method">Init2</span></span>() { }

    [<span class="type">ModuleInitializer</span>]
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="static"><span class="method">Init1</span></span>() { }
}

<span class="reserved">class</span> <span class="type">A</span>
{
    [<span class="type">ModuleInitializer</span>]
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="static"><span class="method">Init</span></span>() { }
}
</pre>
<p>呼ばれるのは <code>Z.Init1</code>, <code>Z.Init2</code>, <code>Y.Init2</code>, <code>Y.Init1</code>, <code>A.Init</code> の順です。</p>
<h3>ファイルが分かれている場合</h3>
<p>問題は複数のファイルが分かれている場合。</p>
<p><a href="https://github.com/ufcpp/UfcppSample/tree/master/Demo/2023/MemberOrder">調べた感じ</a>、
<code>&lt;Compile&gt;</code> タグの手書きで順序を明示することもできるけども、
<code>*.cs</code> 指定にした場合はビルド ツール依存
(MSBuild.exe と dotnet build で微妙に結果に差あり)
みたいです。</p>
<p>とはいえ、まあ、おおむね、ファイル名でソートしているみたいです。
補足として、</p>
<ul>
<li>
Ordinal 比較でソート
<ul>
<li>安心してください、カルチャーには依存しません</li>
<li>a と b の間に À が来たりしません。文字コード順</li>
</ul>
</li>
<li>MSBuild.exe は UTF-16 比較、dotnet build は UTF-8 比較してそう</li>
</ul>
<p>となります。</p>
<p>例えば以下のような2つのファイルを同じプロジェクトに含めた場合、</p>
<pre class="source" title="A.cs に書く">
<span class="comment">// このコードを A.cs に書く</span>
<span class="reserved">using</span> System<span class="operator">.</span>Runtime<span class="operator">.</span>CompilerServices;

<span class="reserved">class</span> <span class="type">Z</span>
{
    [<span class="type">ModuleInitializer</span>]
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">Init</span></span>() { }
}
</pre>
<pre class="source" title="Z.cs に書く">
<span class="comment">// このコードを Z.cs に書く</span>
<span class="reserved">using</span> System<span class="operator">.</span>Runtime<span class="operator">.</span>CompilerServices;

<span class="reserved">class</span> <span class="type">A</span>
{
    [<span class="type">ModuleInitializer</span>]
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="static"><span class="method">Init</span></span>() { }
}
</pre>
<p>(型名とファイル名が逆なことに注意。)</p>
<p>呼ばれるのは <code>Z.Init</code>, <code>A.Init</code> の順です。</p>
<h3>一番最後に並ぶもの</h3>
<p>ここで「後だし優先」の話に戻ります。</p>
<p>これまでに話した仕様に沿って、極力「後だし」になるためにやれそうな工夫としては、</p>
<ul>
<li>文字コード的に後ろの方の文字、例えば半角カナとかのファイル名を付ける</li>
<li><code>&lt;Compile Include=&quot;&quot;/&gt;</code>タグを明示的に後ろの方に書く</li>
<li>.targets ファイル(.csproj の末尾に import されるファイル)に <code>&lt;Compile&gt;</code> タグを書く</li>
</ul>
<p>とかですかね。</p>
<p>まあ、モジュール初期化子の実行順序に依存するようなコードを書くのは邪悪なのであんまりおすすめはしませんが。</p>
 ]]></description>
				<pubDate>Sat, 24 Jun 2023 21:57:33 +0900</pubDate>
			</item>
			<item>
				<title>.NET の文字列比較でカルチャー未指定を検知する</title>
				<link>http://ufcpp.net/blog/2023/6/ca-specify-culture/</link>
				<description><![CDATA[ <p><a href="https://www.youtube.com/watch?v=M5weHOCzJ6E">先日の C# 配信</a>で、
「これはブログに書いておくと助かる人がいるんじゃないか」と言われたものをブログ化。</p>
<h2>背景: カルチャー依存問題再び</h2>
<p>うちのブログでも何回か書いてるんですが、 .NET の文字列比較は、カルチャー依存比較するものと Ordinal (文字コード通り)比較するものが混在していて、なかなかにやばいです。</p>
<ul>
<li><a href="https://ufcpp.net/blog/2021/8/invariantculture/">.NET のカルチャー依存 API 問題</a></li>
<li><a href="https://ufcpp.net/blog/2023/3/string-order/">忘れがちなカルチャー依存問題</a></li>
</ul>
<p><a href="https://gist.github.com/ufcpp/071785157dfb8402af27b443427f8b90">例えば以下のようなやつ</a>。</p>
<pre class="source" title="正気とは思えない ContaisKey">
<span class="reserved">using</span> <span class="reserved">static</span> System<span class="operator">.</span><span class="static"><span class="type">Console</span></span>;

<span class="comment">// 正規化すると同じ文字になる、文字コード的には別の文字。</span>
<span class="reserved">var</span> <span class="variable">s1</span> <span class="operator">=</span> <span class="string">&quot;a\u0301&quot;</span>; <span class="comment">// á = a + ́</span>
<span class="reserved">var</span> <span class="variable">s2</span> <span class="operator">=</span> <span class="string">&quot;\u00e1&quot;</span>; <span class="comment">// á</span>

<span class="comment">// これは false。Ordinal 比較。</span>
<span class="method"><span class="static">WriteLine</span></span>(<span class="reserved">new</span> <span class="type">Dictionary</span>&lt;<span class="reserved">string</span>, <span class="reserved">int</span>&gt; { { <span class="variable">s1</span>, <span class="number">0</span> } }<span class="operator">.</span><span class="method">ContainsKey</span>(<span class="variable">s2</span>));

<span class="comment">// これは true。CurrentCulture 比較。</span>
<span class="method"><span class="static">WriteLine</span></span>(<span class="reserved">new</span> <span class="type">SortedDictionary</span>&lt;<span class="reserved">string</span>, <span class="reserved">int</span>&gt; { { <span class="variable">s1</span>, <span class="number">0</span> } }<span class="operator">.</span><span class="method">ContainsKey</span>(<span class="variable">s2</span>));
</pre>
<p>なんでこんなことになるかというと、</p>
<ul>
<li>
<code>Dictionary</code> は <code>EqualityComparer</code> 依存
<ul>
<li><code>EqualityComparer</code> は <code>Ordinal</code> 比較</li>
<li><code>Ordinal</code> 比較だと、文字コード的に別の文字は一致しない</li>
</ul>
</li>
<li>
<code>SortedDictionary</code> は <code>Comparer</code> 依存
<ul>
<li><code>Comparer</code> は <code>CurrentCulture</code> 比較</li>
<li><code>CurrentCulture</code> 比較だと、たいていのカルチャーで <code>a\u0301</code> と <code>\u00e1</code> を同一視</li>
</ul>
</li>
</ul>
<p>という仕組み。</p>
<p>やばい。</p>
<p>前述のブログで一応の解決策として、
<a href="https://learn.microsoft.com/ja-jp/dotnet/core/runtime-config/globalization">InvariantGlobalization</a> モード指定してしまうという案も書いたんですが、
このモード変更は影響範囲が結構大きいので、
保守しているコードベースがでかいとなかなか踏み切れない方も多いと思います。</p>
<h2>コード解析</h2>
<p>このカルチャー依存文字列比較問題は .NET の中の人も把握していて、
.NET 5 の頃にいろいろと対策をしました。
その対策の1つに、<a href="https://learn.microsoft.com/ja-jp/dotnet/fundamentals/code-analysis/overview?tabs=net-7">NetAnalyzers</a> の提供があります。</p>
<p>NetAnalyzers は要するに、「.NET SDK 付属の公式コード解析」です。
例えば Visual Studio からなら、Dependencis → Analyzers → Microsoft.CodeAnalysis.NetAnalysers のところで確認できます。</p>
<p><img src="/media/1216/netanalyzers.png" alt="Visual Studio の Solution Exprorer で NetAnalyzers の内容を確認" /></p>
<p>この中で、カルチャー依存 API 対策になっているのは以下の項目。</p>
<ul>
<li>CA1304: Specify CultureInfo</li>
<li>CA1305: Specify IFormatProvider</li>
<li>CA1307: Specify StringComparison for clarity</li>
<li>CA1310: Specify StringComparison for correctness</li>
</ul>
<p>こいつら、デフォルトでは Silent なんですよね…
(Silent = 何も表示しない。エラーや警告はおろか、サジェストのアイコンすら出ない。)</p>
<p>カルチャー依存 API のやばさのわりに Silent。
まあ、 .NET Framework 1.0 から .NET 5 までの十数年、ずっとそうでしたからね…</p>
<p>ということで、このコード解析の警告・エラー レベルを上げてしまった方がいいかもしれません。
.editorconfig に以下のような行を足せばエラーにできます。</p>
<pre class="source">
<span class="type">[*.cs]</span>
<span class="reserved">dotnet_diagnostic.CA1304.severity</span> = error
<span class="reserved">dotnet_diagnostic.CA1305.severity</span> = error
<span class="reserved">dotnet_diagnostic.CA1307.severity</span> = error
<span class="reserved">dotnet_diagnostic.CA1310.severity</span> = error
</pre>
<p>例えば以下のようなメソッドを警告にできます。</p>
<pre class="source" title="">
<span class="reserved">using</span> System<span class="operator">.</span>Resources;

<span class="reserved">static</span> <span class="reserved">string</span><span class="operator">?</span> <span class="method"><span class="static">M</span></span>(<span class="type">ResourceManager</span> <span class="variable local">m</span>) <span class="operator">=&gt;</span> <span class="error" title="CA1304"><span class="variable local">m</span><span class="operator">.</span><span class="method">GetString</span>(<span class="string">&quot;&quot;</span>)</span>; <span class="comment">// CA1304</span>
<span class="error" title="CA1305"><span class="type struct">DateTime</span><span class="operator">.</span><span class="property"><span class="static">Now</span></span><span class="operator">.</span><span class="method">ToString</span>()</span>; <span class="comment">// CA1305</span>
<span class="error" title="CA1307"><span class="string">&quot;&quot;</span><span class="operator">.</span><span class="method">IndexOf</span>(<span class="string">' '</span>)</span>; <span class="comment">// CA1307</span>
<span class="error" title="CA1310"><span class="string">&quot;abc&quot;</span><span class="operator">.</span><span class="method">StartsWith</span>(<span class="string">&quot;abc&quot;</span>)</span>; <span class="comment">// CA1310</span>
</pre> ]]></description>
				<pubDate>Tue, 20 Jun 2023 22:11:29 +0900</pubDate>
			</item>
			<item>
				<title>忘れがちなカルチャー依存問題</title>
				<link>http://ufcpp.net/blog/2023/3/string-order/</link>
				<description><![CDATA[ <p>今日は、「<a href="https://github.com/dotnet/runtime/blob/main/docs/design/features/globalization-invariant-mode.md">Globalization Invariant Mode</a>」に変更したら、意外と忘れがちなところで差が出たみたいな話。</p>
<h2>Globalization Invariant Mode</h2>
<p><a href="https://ufcpp.net/blog/2021/8/invariantculture/">以前に1回ブログに書いてる</a>んですが、 .NET の文字列 API にはカルチャー依存なものが多くて、
例えば <code>1.2.ToString()</code> すらカルチャー依存です。
大陸ヨーロッパだと小数点を <code>,</code> にすることが多く、そのあたりの OS でこの <code>ToString</code> を実行すると <code>&quot;1,2&quot;</code> になります。</p>
<p>一方で、カルチャーごとの書式情報みたいなのは結構データ量が多いので、
WebAssembly みたいなフットプリントを小さくしたい環境では「そのデータを除外したい」要件があったりします。</p>
<p>そこで導入されたのが<a href="https://github.com/dotnet/runtime/blob/main/docs/design/features/globalization-invariant-mode.md">Globalization Invariant Mode</a>。
<code>CultureInfo.CurrentCulture</code> を呼んでも、<code>InvariantCulture</code> が返ってくるというモードです。
<code>1.2.ToString()</code> も常に <code>&quot;1.2&quot;</code> に。</p>
<h2>文字列比較</h2>
<p>日本 (<code>ja-JP</code> カルチャー)の場合、<code>InvariantCulture</code> (実質 <code>en-US</code> カルチャー)との差は日付がらみ(米国は <code>MM/dd/yyyy</code>)くらいなので、
大した影響もないはず(フォーマット未指定で日付系の型を <code>ToString</code> することがあんまりない)なので早々に Globalization Invariant Mode を有効化しようとしたところ、
<code>Order</code>/<code>OrderBy</code> が影響を受けていました。</p>
<p><a href="https://github.com/dotnet/runtime/blob/main/docs/design/features/globalization-invariant-mode.md">Globalization Invariant Mode の解説</a>をよく見てみれば原因は明白で、</p>
<blockquote>
<p>String operations like Compare, IndexOf and LastIndexOf are always performed as ordinal and not linguistic operations regardless of the string comparing options passed to the APIs.</p>
<p>文字列操作、例えば Compare, IndexOf, LastIndesOf などは常に ordinal で実行され、言語的な操作はしません。文字列比較のオプションに何を渡しても関係なく。</p>
</blockquote>
<p>とのこと。</p>
<p><code>CurrentCulture</code> が <code>InvariantCulture</code> に化ける他に、
文字列比較が常に ordinal (文字コード順)になるそうです。</p>
<p>例えば以下のようなコードを実行すると、</p>
<pre class="source" title="Order がカルチャー依存">
<span class="type"><span class="static">Console</span></span><span class="operator">.</span><span class="property"><span class="static">OutputEncoding</span></span> <span class="operator">=</span> System<span class="operator">.</span>Text<span class="operator">.</span><span class="type">Encoding</span><span class="operator">.</span><span class="property"><span class="static">UTF8</span></span>;

<span class="comment">// InvariantGlobalization true のときはこの行が例外になるのでコメントアウトして実行。</span>
<span class="type">Thread</span><span class="operator">.</span><span class="static"><span class="property">CurrentThread</span></span><span class="operator">.</span><span class="property">CurrentCulture</span> <span class="operator">=</span> <span class="reserved">new</span> System<span class="operator">.</span>Globalization<span class="operator">.</span><span class="type">CultureInfo</span>(<span class="string">&quot;tr-TR&quot;</span>);

<span class="reserved">var</span> <span class="variable">data</span> <span class="operator">=</span> <span class="reserved">new</span>[]
{
    <span class="comment">// だいたいのカルチャーで、大文字・小文字、アクセント記号違いの文字が並ぶようにソートされる。</span>
    <span class="string">&quot;a&quot;</span>,
    <span class="string">&quot;A&quot;</span>,
    <span class="string">&quot;b&quot;</span>,
    <span class="string">&quot;B&quot;</span>,
    <span class="string">&quot;À&quot;</span>,
    <span class="comment">// トルコ語の時に順序変わるやつ</span>
    <span class="string">&quot;i&quot;</span>,
    <span class="string">&quot;I&quot;</span>,
    <span class="string">&quot;ı&quot;</span>,
    <span class="string">&quot;İ&quot;</span>,
};

<span class="reserved">var</span> <span class="variable">@default</span> <span class="operator">=</span> <span class="variable">data</span><span class="operator">.</span><span class="method">Order</span>()<span class="operator">.</span><span class="method">ToArray</span>(); <span class="comment">// 実行結果を見ればわかるものの、未指定は CurrentCulture。</span>
<span class="reserved">var</span> <span class="variable">current</span> <span class="operator">=</span> <span class="variable">data</span><span class="operator">.</span><span class="method">Order</span>(<span class="type">StringComparer</span><span class="operator">.</span><span class="static"><span class="property">CurrentCulture</span></span>)<span class="operator">.</span><span class="method">ToArray</span>();
<span class="reserved">var</span> <span class="variable">invariant</span> <span class="operator">=</span> <span class="variable">data</span><span class="operator">.</span><span class="method">Order</span>(<span class="type">StringComparer</span><span class="operator">.</span><span class="property"><span class="static">InvariantCulture</span></span>)<span class="operator">.</span><span class="method">ToArray</span>();
<span class="reserved">var</span> <span class="variable">ordinal</span> <span class="operator">=</span> <span class="variable">data</span><span class="operator">.</span><span class="method">Order</span>(<span class="type">StringComparer</span><span class="operator">.</span><span class="static"><span class="property">Ordinal</span></span>)<span class="operator">.</span><span class="method">ToArray</span>();

<span class="control">for</span> (<span class="reserved">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; <span class="variable">i</span> <span class="operator">&lt;</span> <span class="variable">@default</span><span class="operator">.</span><span class="property">Length</span>; <span class="variable">i</span><span class="operator">++</span>)
{
    <span class="static"><span class="type">Console</span></span><span class="operator">.</span><span class="static"><span class="method">WriteLine</span></span>(<span class="string">$&quot;</span>{<span class="variable">@default</span>[<span class="variable">i</span>]}<span class="string"> </span>{<span class="variable">current</span>[<span class="variable">i</span>]}<span class="string"> </span>{<span class="variable">invariant</span>[<span class="variable">i</span>]}<span class="string"> </span>{<span class="variable">ordinal</span>[<span class="variable">i</span>]}<span class="string">&quot;</span>);
}
</pre>
<p>InvariantGlobalization が false なら以下のような結果になります。
無指定が <code>CurrentCulture</code> と一緒。
<code>CurrentCulture</code> と <code>InvariantCulture</code> では一部の並びに変化がありますが、
「大文字・小文字が並ぶ」くらいはどのカルチャーでも共通です。</p>
<pre class="console">
a a a A
A A A B
À À À I
b b b a
B B B b
ı ı i i
I I I À
i i İ İ
İ İ ı ı
</pre>
<p>そして、InvariantGlobalization を true 以下のような結果に変化します。
無指定と <code>CurrentCulture</code> の列だけが変わるかと思いきや、
<code>InvariantCulture</code> の列も含めて全部が <code>Ordinal</code> とそろいます。
完全に文字コード順なので、ASCII アルファベットは大文字が先で、小文字がまとめて後ろに。
<code>À</code> は non-ASCII の文字なのでさらに後ろ。</p>
<pre class="console">
A A A A
B B B B
I I I I
a a a a
b b b b
i i i i
À À À À
İ İ İ İ
ı ı ı ı
</pre>
<p>ちなみに、日本語でもひらがな・カタカナの並びが変わります。
(カルチャーあり: あ、ア、い、イ。
Ordinal: あ、い、ア、イ。)</p>
<h2>実は遅い Order()</h2>
<p>カルチャー依存のテーブルを引いて順序を決めるのと、
単に文字コードの数値を見てソートするのとではどちらが高速か明白です。</p>
<p><code>Order</code>/<code>OrderBy</code> もカルチャー依存ということは…
ベンチマークを取ってみましょう…</p>
<pre class="source" title="Order のベンチマーク取ってみる">
<span class="reserved">using</span> BenchmarkDotNet<span class="operator">.</span>Attributes;
<span class="reserved">using</span> BenchmarkDotNet<span class="operator">.</span>Running;

<span class="static"><span class="type">BenchmarkRunner</span></span><span class="operator">.</span><span class="static"><span class="method">Run</span></span>&lt;<span class="type">StringCompareBenchmark</span>&gt;();

<span class="reserved">public</span> <span class="reserved">class</span> <span class="type">StringCompareBenchmark</span>
{
    <span class="reserved">private</span> <span class="reserved">static</span> <span class="reserved">readonly</span> <span class="reserved">string</span>[] <span class="field"><span class="static">_data</span></span> <span class="operator">=</span> <span class="string">&quot;&quot;&quot;
        Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
        &quot;&quot;&quot;</span><span class="operator">.</span><span class="method">Split</span>(<span class="string">' '</span>);

    [<span class="type">Benchmark</span>]
    <span class="reserved">public</span> <span class="reserved">string</span>[] <span class="method">Order</span>() <span class="operator">=&gt;</span> <span class="static"><span class="field">_data</span></span><span class="operator">.</span><span class="method">Order</span>()<span class="operator">.</span><span class="method">ToArray</span>();

    [<span class="type">Benchmark</span>]
    <span class="reserved">public</span> <span class="reserved">string</span>[] <span class="method">OrderCurrent</span>() <span class="operator">=&gt;</span> <span class="static"><span class="field">_data</span></span><span class="operator">.</span><span class="method">Order</span>(<span class="type">StringComparer</span><span class="operator">.</span><span class="static"><span class="property">CurrentCulture</span></span>)<span class="operator">.</span><span class="method">ToArray</span>();

    [<span class="type">Benchmark</span>]
    <span class="reserved">public</span> <span class="reserved">string</span>[] <span class="method">OrderInvariant</span>() <span class="operator">=&gt;</span> <span class="field"><span class="static">_data</span></span><span class="operator">.</span><span class="method">Order</span>(<span class="type">StringComparer</span><span class="operator">.</span><span class="property"><span class="static">InvariantCulture</span></span>)<span class="operator">.</span><span class="method">ToArray</span>();

    [<span class="type">Benchmark</span>]
    <span class="reserved">public</span> <span class="reserved">string</span>[] <span class="method">OrderOrdinal</span>() <span class="operator">=&gt;</span> <span class="field"><span class="static">_data</span></span><span class="operator">.</span><span class="method">Order</span>(<span class="type">StringComparer</span><span class="operator">.</span><span class="static"><span class="property">Ordinal</span></span>)<span class="operator">.</span><span class="method">ToArray</span>();
}
</pre>
<p>結果、うちの環境だと以下のような感じでした。</p>
<table>
<thead>
<tr>
	<th>Method</th>
	<th align="right">Mean</th>
	<th align="right">Error</th>
	<th align="right">StdDev</th>
</tr>
</thead>
<tbody>
<tr>
	<td>Order</td>
	<td align="right">8.348 us</td>
	<td align="right">0.0778 us</td>
	<td align="right">0.0727 us</td>
</tr>
<tr>
	<td>OrderCurrent</td>
	<td align="right">8.399 us</td>
	<td align="right">0.0313 us</td>
	<td align="right">0.0277 us</td>
</tr>
<tr>
	<td>OrderInvariant</td>
	<td align="right">8.453 us</td>
	<td align="right">0.0569 us</td>
	<td align="right">0.0532 us</td>
</tr>
<tr>
	<td>OrderOrdinal</td>
	<td align="right">2.593 us</td>
	<td align="right">0.0125 us</td>
	<td align="right">0.0111 us</td>
</tr>
</tbody>
</table>
<p>Ordinal 指定すると3倍以上速くなります。</p>
<p>ちなみに、自分の用途ではどこで何度実行しようと同じ順になりさえすればよくて、
順序は a A b B でも A B a b でもどちらでもよかったので、
もっと早くから Ordinal 指定しておくべき事案でした。</p>
 ]]></description>
				<pubDate>Sat, 18 Mar 2023 17:35:11 +0900</pubDate>
			</item>
			<item>
				<title>C# での破壊的変更の今後の扱い(案)</title>
				<link>http://ufcpp.net/blog/2023/3/csharp-breaking-change/</link>
				<description><![CDATA[ <p>C# は、進化していくにあたって、破壊的変更を極力起こさないようにかなり気を使っているプログラミング言語です。
細かい話をすると破壊的変更も皆無ではないんですが、
破壊的変更を認める(認めてでも追加したい新機能を実装する)ハードルは結構高めです。</p>
<p>そんな C# ですが、ちょっとそのハードルの基準を緩められないかというような話が出ています。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/discussions/7033">Dealing with limited breaking changes in C#</a></li>
<li><a href="https://github.com/dotnet/csharplang/blob/main/meetings/2023/LDM-2023-03-08.md#limited-breaking-changes-in-c">その後の Design Meeting 議事録</a></li>
</ul>
<h2>補足: 影響範囲と、影響力の軽減</h2>
<p>補足として、
ハードルを緩めるといっても本当にちょっとです。
C# チームは、「GitHub の public リポジトリを検索して、実際に影響を受けたコードを探す」とかやって既存のコードに対する影響を評価してたりするんですが、</p>
<ul>
<li>これまで: 単体テストとかでわざと変なコードを書いているものを除いて、ほぼ影響皆無なら OK</li>
<li>提案: それほど多くはないものの、無視できると言えるほど皆無ではないものでも OK にしたい</li>
</ul>
<p>みたいな感じ。</p>
<p>代わりといってはなんですが、影響を受ける人への負担を最小限にするために、以下のような仕組みを提供するのはどうか？という提案になっています。</p>
<ul>
<li>言語バージョンを最新のものにアップグレードすると影響を受けるコードを識別する</li>
<li>そういうコードに対して診断メッセージを出して、破壊的変更があることを知らせる</li>
<li>自動コード修正機能で、破壊的変更を受けないようなコードへの書き換えを提供する</li>
<li>早い段階でこれらの診断・コード修正を提供する</li>
</ul>
<h2>これまでの破壊的変更の例</h2>
<p><a href="https://github.com/dotnet/csharplang/discussions/7033">件の discussion</a>で触れられているわけではないですが、
補足的に、
これまでの「ほぼ影響皆無」な破壊的について紹介しておきましょう。
細かく言うともっといろいろとあるんですが、結構大きめのもののみ抜粋。</p>
<h3>ジェネリクスの &lt;&gt;</h3>
<p>C# のジェネリクスは C# 2.0 からの導入なわけで、それ以前には <code>M&lt;T&gt;()</code> みたいな <code>&lt;&gt;</code> の用法はありませんでした。
ここで、多少工夫すると、C# 1.0 の頃でも合法そうな <code>&lt;&gt;</code> が書けます。
例えばこんな感じ:</p>
<pre class="source" title="&lt;&gt;">
X(A&lt;B, C&gt;(D));
</pre>
<ul>
<li>C# 1.0 の解釈: 2引数のメソッド <code>X</code> があって、式 <code>A&lt;B</code> と <code>C&gt;(D)</code> が引数</li>
<li>C# 2.0 の解釈: 1引数のメソッド <code>X</code> と、引数1つで型引数2つのメソッド <code>A</code> がある</li>
</ul>
<p>色が付くと多少わかりやすいですかね。</p>
<pre class="source" title="&lt;&gt; 1.0 VS 2.0">
<span class="comment">// C# 1.0 解釈</span>
<span class="method">X</span>(<span class="variable">A</span> &lt; <span class="variable">B</span>, <span class="variable">C</span> &gt; (<span class="variable">D</span>));

<span class="comment">// C# 2.0 解釈</span>
<span class="method">X</span>(<span class="method">A</span>&lt;<span class="type">B</span>, <span class="type">C</span>&gt;(<span class="variable">D</span>));
</pre>
<p>まあ、狙わないと踏めないですね。
C# 2.0 当時に踏んだ人はいないんじゃないでしょうか。
実際僕も確か、C# 5.0 辺りの時に「かつてこんなのあったけども誰も気にしなかったよ」的な話題で知りました。</p>
<h3>foreach 変数のキャプチャ</h3>
<p>割かしちゃんとアナウンスがあった破壊的変更でいうと、C# 5.0 のときの <a href="https://ufcpp.net/study/csharp/ap_ver5.html#foreach"><code>foreach</code> の仕様変更</a>があります。
詳細はリンク先を見てもらうとして、
簡単に言うと以下のコードの実行結果が C# 4.0 以前と 5.0 以降で変わります。</p>
<pre class="source" title="C# 5.0 の foreach の仕様変更">
<span class="reserved">var</span> <span class="variable">data</span> <span class="operator">=</span> <span class="reserved">new</span>[] { <span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span> };

<span class="type">Action</span> <span class="variable">a</span> <span class="operator">=</span> <span class="reserved">null</span>;

<span class="control">foreach</span> (<span class="reserved">var</span> <span class="variable">x</span> <span class="control">in</span> <span class="variable">data</span>)
{
    <span class="variable">a</span> <span class="operator">+=</span> () <span class="operator">=&gt;</span> <span class="type"><span class="static">Console</span></span><span class="operator">.</span><span class="method"><span class="static">WriteLine</span></span>(<span class="variable">x</span>);
}

<span class="variable">a</span>();
</pre>
<p><code>x</code> のスコープが <code>foreach</code> の内側か外側かが変わっていて、
単一の変数 <code>x</code> が全てのループで共有されるか、ループごとに違う変数扱いになるかが変わります。
結果的に、(C# 4.0 以前)「5つの5が表示される」か(C# 5.0 以降)「1, 2, 3, 4, 5 が表示される」かという結構大きな差になります。</p>
<p>まあ、4.0以前の挙動の方をバグだと思う人もいたくらいです。
このコードを書いてみて5が5つ表示されたら、まあ、コードを書き換えますよね、普通。
なので、破壊的変更の影響を受ける人はほぼ皆無でした。</p>
<p>この当時はまだ「GitHub にあるコードをクロールして調べる」みたいな手段がなかったので、
C# チーム的には恐る恐る破壊的変更をリリースしていました。
ですが、まあ、結果的には「心配しすぎだった」と言われているくらい、不平不満の声はなかったはずです。
繰り返しになりますが、バグ修正とすら思われているレベルです。</p>
<h3>record, required, scoped, file</h3>
<p>C# 9.0 で<a href="https://ufcpp.net/study/csharp/cheatsheet/ap_ver9/#record"><code>record</code></a>が、
C# 11.0 で<a href="https://ufcpp.net/study/csharp/cheatsheet/ap_ver11/#required"><code>required</code></a>、<a href="https://ufcpp.net/study/csharp/resource/refstruct/#scoped"><code>scoped</code></a>、<a href="https://ufcpp.net/study/csharp/cheatsheet/ap_ver11/#file-local"><code>file</code></a>が新たにキーワードになりました。</p>
<p>ただ、幸い、これらは(当然、<a href="https://ufcpp.net/study/csharp/ap_compatibility.html#contextual-keyword">文脈キーワード</a>で)「型名として使おうとする時だけまずい」という仕様になっています。</p>
<pre class="source" title="record の破壊的変更の影響は型名に対してのみ">
<span class="reserved">class</span> <span class="type">A</span>
{
    <span class="comment">// 全然平気。</span>
    <span class="reserved">int</span> <span class="field">record</span>;
    <span class="reserved">void</span> <span class="method">M</span>(<span class="reserved">int</span> <span class="variable local">record</span>) { }
    <span class="reserved">int</span> <span class="method">M</span>()
    {
        <span class="reserved">int</span> <span class="variable">record</span> <span class="operator">=</span> <span class="number">0</span>;
        <span class="control">return</span> <span class="variable">record</span>;
    }

    <span class="comment">// これがダメ。</span>
    <span class="comment">// 以前:  record という名前のクラスのフィールド x</span>
    <span class="comment">// C# 11: x という名前のレコード型宣言</span>
    <span class="reserved">record</span> <span class="type"><span class="warning" title="CS8981">x</span></span>;
}

<span class="reserved">class</span> <span class="type"><span class="warning" title="CS8860">record</span></span> { }
</pre>
<p>幸い、C# では「型名は大文字始まりにする」という文化が浸透していて、わざわざこの規約に反する型名を使う人もほとんどいません。</p>
<p>昔ならそれでも破壊的変更はしり込みしたんでしょうが、
今回は「GitHub にあるコードをクロールして調べる」が有効に機能したようです。
調べた結果、デモやテストでわざと変な名前をつけている人を除いて、問題を起こしそうなコードは見当たらなかったそうです。</p>
<p>実際、C# 9.0 リリース後にこれで困ったという人は見かけません。
それもあってか、C# 11.0 では、<a href="https://ufcpp.net/study/csharp/cheatsheet/ap_ver11/#CS9029">そもそも <code>required</code>、<code>scoped</code>、<code>file</code> という名前の型宣言自体エラーに</a>しました。
結構な破壊的変更ですが、これで困ったという人は、僕の知る限りは見かけたことはありません。</p>
<p>(1個だけ、native interop で、native 側に <code>file</code> という構造体がいて、
それに合わせて「C# でも意図的に小文字始まりの <code>file</code> を使う」みたいな判断をしていたコードは見たことがあります。それは <code>struct @file {}</code> と書けば解決。)</p>
<h2>今懸念される新機能: 半自動プロパティ</h2>
<p>今何で困っているかというと、1月にブログに書いた<a href="https://ufcpp.net/blog/2023/1/semi-auto-property/">半自動プロパティ</a>です。
<code>field</code> キーワードの追加。</p>
<pre class="source" title="手動、(全)自動、半自動プロパティ">
<span class="reserved">class</span> <span class="type">A</span>
{
    <span class="comment">// 手動プロパティ (manual property)</span>
    <span class="comment">// (と、自前で用意したフィールド)。</span>
    <span class="comment">// こういう、プロパティからほぼ素通しで値を記録しているフィールドを「バッキング フィールド」(backing field)という。</span>
    <span class="reserved">private</span> <span class="reserved">int</span> <span class="field">_x</span>;
    <span class="reserved">public</span> <span class="reserved">int</span> <span class="property">X</span> { <span class="reserved">get</span> <span class="operator">=&gt;</span> <span class="field">_x</span>; <span class="reserved">set</span> <span class="operator">=&gt;</span> <span class="field">_x</span> <span class="operator">=</span> <span class="reserved">value</span>; }

    <span class="comment">// 自動プロパティ (auto-property)。</span>
    <span class="comment">// 前述の X とほぼ一緒。</span>
    <span class="comment">// バッキング フィールドの自動生成。</span>
    <span class="reserved">public</span> <span class="reserved">int</span> <span class="property">Y</span> { <span class="reserved">get</span>; <span class="reserved">set</span>; }

    <span class="comment">// 【C# 12 候補】 半自動プロパティ (semi-auto-property)。</span>
    <span class="comment">// バッキング フィールドは自動生成。</span>
    <span class="comment">// 全自動の方と違って、バッキング フィールドの使い方は自由にできる。</span>
    <span class="comment">// field キーワードでバッキング フィールドを読み書き。</span>
    <span class="reserved">public</span> <span class="reserved">int</span> <span class="property">Z</span> { <span class="reserved">get</span> <span class="operator">=&gt;</span> <span class="reserved"><em>field</em></span>; <span class="reserved">set</span> <span class="operator">=&gt;</span> <span class="reserved"><em>field</em></span> <span class="operator">=</span> <span class="reserved">value</span>; }
}
</pre>
<p><code>record</code> とかと違ってこれが危ないのは、「<code>field</code> という名前のフィールドがいたらアウト」という、割かしありそうなラインなせいです。
以下のコード、半自動プロパティが実装される前後で意味が変わる可能性が大きくなっています。
(回避できなくもないものの、コストが高すぎてできれば破壊的変更を認める方向で進めたい。)</p>
<pre class="source" title="半自動プロパティで壊れる予定のコード">
<span class="reserved">class</span> <span class="type">A</span>
{
    <span class="reserved">private</span> <span class="reserved">int</span> <span class="field">field</span>;

    <span class="reserved">public</span> <span class="reserved">int</span> <span class="property">Property</span>
    {
        <span class="reserved">get</span> <span class="operator">=&gt;</span> <span class="field">field</span>;
        <span class="reserved">set</span> <span class="operator">=&gt;</span> <span class="field">field</span> <span class="operator">=</span> <span class="reserved">value</span>;
    }
}
</pre>
<p>これはGitHubで調べたら、いるらしいです。
まあ、いそうですよね。</p>
<p>ただ、そんなに多くもない。
安直な <code>field</code> という名前のフィールドがそこまで多くないというのもありますが、
C# のコーディング規約上の派閥的な話もあります。
フィールドの命名規約として「<code>_</code> を付ける派」は影響を受けません。</p>
<pre class="source" title="_ 派">
<span class="reserved">class</span> <span class="type">A</span>
{
    <span class="reserved">private</span> <span class="reserved">int</span> <span class="field">_field</span>; <span class="comment">// _ 派。影響を受けない。</span>

    <span class="reserved">public</span> <span class="reserved">int</span> <span class="property">Property</span>
    {
        <span class="reserved">get</span> <span class="operator">=&gt;</span> <span class="field">_field</span>;
        <span class="reserved">set</span> <span class="operator">=&gt;</span> <span class="field">_field</span> <span class="operator">=</span> <span class="reserved">value</span>;
    }
}
</pre>
<p>「インスタンス メンバーには常に <code>this.</code> を付ける派」も影響を受けません。</p>
<pre class="source" title="this. 派">
<span class="reserved">class</span> <span class="type">A</span>
{
    <span class="reserved">private</span> <span class="reserved">int</span> <span class="field">field</span>;

    <span class="reserved">public</span> <span class="reserved">int</span> <span class="property">Property</span>
    {
        <span class="comment">// this. 派。影響を受けない。</span>
        <span class="reserved">get</span> <span class="operator">=&gt;</span> <span class="reserved">this</span><span class="operator">.</span><span class="field">field</span>;
        <span class="reserved">set</span> <span class="operator">=&gt;</span> <span class="reserved">this</span><span class="operator">.</span><span class="field">field</span> <span class="operator">=</span> <span class="reserved">value</span>;
    }
}
</pre>
<p>C# は結構「<code>private</code> なところのコーディング規約は口うるさく言わない」みたいなところがあるので、フィールドに関しては <code>_field</code>、<code>this.field</code>、<code>field</code> の3つとも結構います。</p>
<p>さて、このラインの「大した影響ではないものの、無視できるほどは皆無じゃない」をどう扱いましょうか。
というのが現在の課題。</p>
<h2>さかのぼって</h2>
<p>「<code>field</code> フィールド」程度の破壊的変更を認めたいのであれば、
過去のさかのぼれば、同程度の以下の影響範囲だけどもちょっと特殊対応して破壊的変更を避けたものがあります。</p>
<ul>
<li><code>var</code>: <code>var</code> という名前の型がないときに限りキーワード扱い</li>
<li><code>dynamic</code>: <code>dynamic</code> という名前の型がないときに限りキーワード扱い</li>
<li><code>_</code>: 1つも変数参照がないときに限り <a href="https://ufcpp.net/study/csharp/cheatsheet/ap_ver7/#discard">discard</a> 扱い</li>
</ul>
<p>特に前2者なんて、<code>required</code> や <code>scopde</code> が型名として使えなくなった今、かなり不自然ですよね。</p>
<p>かつては「型推論の <code>var</code> を使わせないために、わざと <code>class var {}</code> を定義しておく」という嫌がらせのような規約を定めてしまう人も一部いたそうですが。
今では「そんなことやるのは推奨されていない」で一蹴していいと思います。</p>
<h2>改めて、破壊的変更の影響軽減</h2>
<p>とりあえず差し当たっては「<code>field</code> フィールド」問題、もしかするとさらに踏み込んで「<code>var</code> 型」問題を、今後、破壊的変更を認める方向で進めることになるかもしれません。</p>
<p>さすがにサイレントに行うには大きすぎる破壊的変更なので、以下のように進めたいとのこと。</p>
<ul>
<li>
コンパイラーを最新にした場合、言語バージョンを更新しなくても(TargetFramework を最新にしなくても)、「最新の C# で破壊的変更になる」旨を警告する
<ul>
<li>言語バージョンを上げるつもりのない人向けに、抑止オプションも提供する</li>
</ul>
</li>
<li>
自動コード修正を提供して、早期に修正してもらう
<ul>
<li>半自動プロパティの例でいうと <code>field</code> を <code>this.field</code> に自動的に置き換える</li>
</ul>
</li>
<li>このコード修正は IDE 上でも、コマンドラインでの実行もできるようにする</li>
</ul>
<p><a href="https://github.com/dotnet/csharplang/discussions/7033">discussion</a> での反応は「賛成多数」(👍100 対 👎4)。
むしろ、「他の言語はもっと破壊的変更してるだろ。やっちゃえ」発言も目立ちます。
ただ、この discussion に参加しに来る人はその時点で「積極的な人」のはずなので、
もう少しいろんな方面の調査は必要かと思われます。</p>
<p>また、1つ disucussion 内で挙げられた懸念として、
「StackOverflow とかからコピペしてくるコード問題」があります。
コード片のコピペの場合、「どのバージョンのコピーを、どのバージョンのコンパイラーにペーストするか」がわからないので、「事前に警告して、事前にコード修正をかけてもらう」戦略がやりにくいです。
(こういう問題も、<a href="https://ufcpp.net/study/csharp/cheatsheet/ap_ver9/#top-level-statements">top-level statemsnt</a>ですでに経験済み。)</p>
 ]]></description>
				<pubDate>Sat, 11 Mar 2023 23:49:16 +0900</pubDate>
			</item>
			<item>
				<title>【C# 12 候補】 Extensions</title>
				<link>http://ufcpp.net/blog/2023/3/extensions/</link>
				<description><![CDATA[ <p>今日は「拡張」(拡張メソッド的なものの改良)の話。
(今日のこれは、C# 12 で全て実装されるかどうか怪しく、
一部 13 以降になる可能性も結構高いです。)</p>
<ul>
<li>提案ドキュメント: <a href="https://github.com/dotnet/csharplang/blob/main/proposals/extensions.md">Extension types</a></li>
<li>
Working Group 議事録
<ul>
<li><a href="https://github.com/dotnet/csharplang/blob/main/meetings/working-groups/roles/roles-2022-11-10.md">2022/11/10</a></li>
<li><a href="https://github.com/dotnet/csharplang/blob/main/meetings/working-groups/roles/roles-2023-01-23.md">2023/1/23</a></li>
<li><a href="https://github.com/dotnet/csharplang/blob/main/meetings/working-groups/roles/roles-2023-01-25.md">2023/1/25</a></li>
<li><a href="https://github.com/dotnet/csharplang/blob/main/meetings/working-groups/roles/roles-2023-02-15.md">2023/2/15</a></li>
</ul>
</li>
</ul>
<p>結構昔から、</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/issues/11159">Extension everything</a>: 拡張メソッドと同じような仕組みでプロパティ、インデクサー、演算子などを「拡張」したい</li>
<li><a href="https://github.com/dotnet/csharplang/blob/main/meetings/2022/LDM-2022-09-26.md#roles--extensions">Roles</a>: 「拡張」をある種の「型」扱いしたい</li>
</ul>
<p>みたいな案があったんですが、結局、この Roles をベースに、Extensions とか Extension types という名称で実装が進みそうです。</p>
<p>原案で「Roles/Extensions」と呼ばれていたものは、「Explicit /Implicit extensions」となります。</p>
<h2>extension キーワード</h2>
<p>提案されている現状の文法では、新たに <code>extension</code> キーワードを使った「型定義」できるようにするみたいです。</p>
<p>例えば、<code>int</code> に対する「拡張」を書くのなら、以下のような書き方をします。</p>
<pre class="source" title="int に対する extension">
<span class="reserved">implicit</span> <span class="reserved">extension</span> <span class="type">Ex</span> <span class="reserved">for</span> <span class="reserved">int</span>
{
}
</pre>
<h3>なんでも拡張</h3>
<p>現状の<a href="https://ufcpp.net/study/csharp/sp3_extension.html">拡張メソッド</a>の仕様では、名前通り、メソッドしか定義できません。
プロパティなどを「拡張」したいという要望は長らくあるんですが、
今の拡張メソッドの文法がプロパティなどに向いていなさ過ぎて、導入できずにいます。
また、静的メンバーにも対応していません。</p>
<pre class="source" title="プロパティに向かない文法、静的メンバーにも未対応">
<span class="reserved">static</span> <span class="reserved">class</span> <span class="type"><span class="static">Extensions</span></span>
{
    <span class="comment">// x.Method() と呼べる。</span>
    <span class="comment">// 第1引数を特別扱いしてる都合上…</span>
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="static"><span class="method">Method</span></span>(<span class="reserved">this</span> <span class="reserved">int</span> <span class="variable local">x</span>) { }

    <span class="comment">// 引数のないプロパティとか、</span>
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">int</span> <span class="static"><span class="property"><span class="error" title="CS0548">Property</span></span></span> { }

    <span class="comment">// インデクサーはどうするか悩ましい。</span>
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">int</span> <span class="error" title="CS0720"><span class="error" title="CS0548"><span class="error" title="CS0106"><span class="reserved">this</span></span></span></span>[<span class="reserved">int</span> <span class="variable local">index</span>] { }

    <span class="comment">// 元が static なものを拡張する手段もない。</span>
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">int</span> <span class="reserved">operator</span> <span class="error" title="CS1534"><span class="error" title="CS0715"><span class="error" title="CS0161"><span class="operator">+</span></span></span></span>() { }
}
</pre>
<p><code>extension</code> を使った定義では、インスタンス フィールドと<a href="https://ufcpp.net/study/csharp/oo_property.html#auto">自動プロパティ</a>・<a href="https://ufcpp.net/study/csharp/sp_event.html#auto-event">自動イベント</a>(暗黙的にフィールドが必要)を除いて、どのメンバーでも使えます。</p>
<pre class="source" title="プロパティやインデクサー、静的メンバーにも対応">
<span class="reserved">implicit</span> <span class="reserved">extension</span> <span class="type">Ex</span> <span class="reserved">for</span> <span class="reserved">int</span>
{
    <span class="reserved">public</span> <span class="reserved">void</span> <span class="method">Method</span>() { }
    <span class="reserved">public</span> <span class="reserved">int</span> <span class="property">Property</span> => <span class="reserved">this</span>;
    <span class="reserved">public</span> <span class="reserved">int</span> <span class="reserved">this</span>[<span class="reserved">int</span> <span class="variable">index</span>] => <span class="variable">index</span>;

    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">StaticMethod</span></span>() { }
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="type">Ex</span> <span class="reserved">operator</span>+ (<span class="type">Ex</span> <span class="variable">x</span>) => <span class="variable">x</span>;
}
</pre>
<p>ちなみに、インターフェイスも実装できる予定です。
既存の(第3者が作っていて自分では手を入れられない)型にインターフェイスを後挿しできます。</p>
<pre class="source" title="拡張インターフェイス実装">
<span class="reserved">implicit</span> <span class="reserved">extension</span> <span class="type">Ex</span> <span class="reserved">for</span> <span class="reserved">bool</span> : <span class="type">IFormattable</span>
{
    <span class="reserved">public</span> <span class="reserved">void</span> <span class="method">ToString</span>(<span class="reserved">string</span>? <span class="variable">format</span>, <span class="type">IFormatProvider</span>? <span class="variable">formatProvider</span>) =&gt; <span class="reserved">this</span> ? <span class="string">"true"</span> : <span class="string">"false"</span>;
}
</pre>
<p>これで、以下のような呼び出しができるようになる予定です。</p>
<pre class="source" title="拡張定義したプロパティ、インデクサー、静的メソッドを呼び出し">
<span class="reserved">int</span> <span class="variable">x</span> <span class="operator">=</span> <span class="number">0</span>;

<span class="variable">x</span><span class="operator">.</span><span class="method">Method</span>();
<span class="reserved">_</span> <span class="operator">=</span> <span class="variable">x</span><span class="operator">.</span><span class="property">Property</span>;
<span class="reserved">_</span> <span class="operator">=</span> <span class="variable">x</span>[<span class="number">1</span>];
<span class="reserved">int</span><span class="operator">.</span><span class="method"><span class="static">StaticMethod</span></span>();

<span class="type">IFormattable</span> f = <span class="reserved">true</span>;
</pre>
<h3>拡張「型」</h3>
<p>既存の拡張メソッドでも起こるんですが、
複数の拡張があるとき、同名のメソッドが被ってどちらを呼ぶべきか解決できない時があります。</p>
<pre class="source" title="名前被りで解決できない拡張メソッド">
<span class="reserved">int</span> <span class="variable">x</span> <span class="operator">=</span> <span class="number">0</span>;

<span class="comment">// 2つ同名のメソッドがあって優先度解決できないのでコンパイル エラー。</span>
<span class="variable">x</span><span class="operator">.</span><span class="method"><span class="error" title="CS0121">Method</span></span>();

<span class="comment">// 解決するためには途端に「普通の静的メソッド」呼びに戻る。</span>
<span class="static"><span class="type">Ex1</span></span><span class="operator">.</span><span class="method"><span class="static">Method</span></span>(<span class="variable">x</span>);
<span class="type"><span class="static">Ex2</span></span><span class="operator">.</span><span class="static"><span class="method">Method</span></span>(<span class="variable">x</span>);

<span class="reserved">static</span> <span class="reserved">class</span> <span class="type"><span class="static">Ex1</span></span>
{
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="static"><span class="method">Method</span></span>(<span class="reserved">this</span> <span class="reserved">int</span> <span class="variable local">x</span>) { }
}

<span class="reserved">static</span> <span class="reserved">class</span> <span class="static"><span class="type">Ex2</span></span>
{
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">Method</span></span>(<span class="reserved">this</span> <span class="reserved">int</span> <span class="variable local">x</span>) { }
}
</pre>
<p>また、拡張メソッドは元々あるインスタンス メソッドよりも優先度が低いので、
同名のメソッドで「上書き」することもできません。</p>
<pre class="source" title="拡張メソッドでは同名インスタンス メソッドの上書きはできない">
<span class="reserved">int</span> <span class="variable">x</span> <span class="operator">=</span> <span class="number">0</span>;

<span class="comment">// インスタンス メソッドの方が優先度が高く、この書き方で Ex1.ToString は呼べない。</span>
<span class="variable">x</span><span class="operator">.</span><span class="method">ToString</span>();

<span class="comment">// 「普通の静的メソッド」呼びで一応解決は可能。</span>
<span class="type"><span class="static">Ex1</span></span><span class="operator">.</span><span class="static"><span class="method">ToString</span></span>(<span class="variable">x</span>);

<span class="reserved">static</span> <span class="reserved">class</span> <span class="type"><span class="static">Ex1</span></span>
{
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">ToString</span></span>(<span class="reserved">this</span> <span class="reserved">int</span> <span class="variable local">x</span>) <span class="operator">=&gt;</span> <span class="variable local">x</span><span class="operator">.</span><span class="method">ToString</span>(<span class="string">&quot;X2&quot;</span>);
}
</pre>
<p>これらの例の通り、
名前被り時の解決方法は「普通の静的メソッドとして呼ぶ」という手段です。</p>
<p>一方、<code>extension</code> では、以下のように、キャスト的な文法で解決します。</p>
<pre class="source" title="キャストで拡張を使う">
<span class="reserved">int</span> <span class="variable">x</span> <span class="operator">=</span> <span class="number">0</span>;

<span class="comment">// 「暗黙」にやろうとすると、extension を使ったやり方でも解決不能・元々あるメソッド優先。</span>
<span class="variable">x</span><span class="operator">.</span><span class="method">Method</span>();   <span class="comment">// これは解決不能。</span>
<span class="variable">x</span><span class="operator">.</span><span class="method">ToString</span>(); <span class="comment">// これは int.ToString が呼ばれる。</span>

<span class="comment">// キャスト構文で解決可能。</span>
((<span class="type">Ex1</span>)<span class="variable">x</span>)<span class="operator">.</span><span class="method">Method</span>();   <span class="comment">// Ex1.Method。</span>
((<span class="type">Ex2</span>)<span class="variable">x</span>)<span class="operator">.</span><span class="method">Method</span>();   <span class="comment">// Ex2.Method。</span>
((<span class="type">Ex2</span>)<span class="variable">x</span>)<span class="operator">.</span><span class="method">ToString</span>(); <span class="comment">// Ex1.ToString。</span>

<span class="comment">// 「拡張型」の変数で1度受けるのでも解決可能。</span>
<span class="comment">// この場合は int のメソッドよりも extension のメソッドの方が優先。</span>
<span class="type">Ex1</span> <span class="variable">ex</span> <span class="operator">=</span> <span class="variable">x</span>;
<span class="variable">ex</span><span class="operator">.</span><span class="method">Method</span>();
<span class="variable">ex</span><span class="operator">.</span><span class="method">ToString</span>();

<span class="reserved">implicit</span> <span class="reserved">extension</span> <span class="type">Ex1</span> <span class="reserved">for</span> <span class="reserved">int</span>
{
    <span class="reserved">public</span> <span class="reserved">void</span> <span class="method">Method</span>(<span class="reserved">this</span> <span class="reserved">int</span> <span class="variable local">x</span>) { }
    <span class="reserved">public</span> <span class="reserved">void</span> <span class="method">ToString</span>(<span class="reserved">this</span> <span class="reserved">int</span> <span class="variable local">x</span>) <span class="operator">=&gt;</span> <span class="variable local">x</span><span class="operator">.</span><span class="method">ToString</span>(<span class="string">&quot;X2&quot;</span>);
}

<span class="reserved">implicit</span> <span class="reserved">extension</span> <span class="type">Ex2</span> <span class="reserved">for</span> <span class="reserved">int</span>
{
    <span class="reserved">public</span> <span class="reserved">void</span> <span class="method">Method</span>(<span class="reserved">this</span> <span class="reserved">int</span> <span class="variable local">x</span>) { }
}
</pre>
<h3>実際に型として使える</h3>
<p><code>Ex1 ex</code> みたいな変数を定義できることからもわかる通り、
<code>extension</code> は普通に「型」という扱いです。
なので、拡張型 (extension types)と呼びます。</p>
<p>変数だけではなく、引数、型引数などにも使えます。</p>
<pre class="source" title="拡張型引数">
<span class="reserved">using</span> System<span class="operator">.</span>Collections;

<span class="reserved">int</span> <span class="variable">x</span> <span class="operator">=</span> <span class="number">0</span>;

<span class="comment">// int → Ex1 の暗黙の変換。</span>
<span class="method"><span class="static">M1</span></span>(<span class="variable">x</span>);

<span class="comment">// IEnumerable&lt;int&gt; → IEnumerable&lt;Ex1&gt; の暗黙の変換。</span>
<span class="static"><span class="method">M2</span></span>(<span class="reserved">new</span>[] { <span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span> });

<span class="comment">// 引数に拡張型を使う。</span>
<span class="reserved">static</span> <span class="reserved">void</span> <span class="static"><span class="method">M1</span></span>(<span class="type">Ex1</span> <span class="variable local">x</span>) <span class="operator">=&gt;</span> <span class="static"><span class="type">Console</span></span><span class="operator">.</span><span class="static"><span class="method">WriteLine</span></span>(<span class="variable local">x</span>);

<span class="comment">// 型引数に拡張型を使う。</span>
<span class="reserved">static</span> <span class="reserved">void</span> <span class="static"><span class="method">M2</span></span>(<span class="type">IEnumerable</span>&lt;<span class="type">Ex1</span>&gt; <span class="variable local">x</span>)
{
    <span class="control">foreach</span> (<span class="reserved">var</span> <span class="variable">item</span> <span class="control">in</span> <span class="variable local">x</span>) <span class="static"><span class="type">Console</span></span><span class="operator">.</span><span class="static"><span class="method">WriteLine</span></span>(<span class="variable">item</span>);
}

<span class="reserved">implicit</span> <span class="reserved">extension</span> <span class="type">Ex1</span> <span class="reserved">for</span> <span class="reserved">int</span>
{
}
</pre>
<h3>explicit extension</h3>
<p>これまで説明なしで <code>implicit extension</code> という書き方をしてきましたが、
そこから察していただける通り、<code>explicit extension</code> もあります。
名前通り型の明示が必須になって、
<code>int</code> などの元の型のままでメンバーを呼ぶことができなくなります。</p>
<pre class="source" title="explicit exntension">
<span class="comment">// (implicit なら呼べるけど) explicit extension では呼べない。</span>
<span class="number">1</span>.<span class="method">Method</span>();
<span class="reserved">int</span>.<span class="method"><span class="static">StaticMethod</span></span>();

<span class="comment">// こんな風に、型を明示して呼ぶ想定。</span>
<span class="type">Ex</span> <span class="variable">ex</span> <span class="operator">=</span> <span class="number">1</span>;
<span class="variable">ex</span><span class="operator">.</span><span class="method">Method</span>();
<span class="type">Ex</span>.<span class="method"><span class="static">StaticMethod</span></span>();

<span class="reserved"><em>explicit</em></span> <span class="reserved">extension</span> <span class="type">Ex</span> <span class="reserved">for</span> <span class="reserved">int</span>
{
    <span class="reserved">public</span> <span class="reserved">void</span> <span class="method">Method</span>() { }
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">StaticMethod</span></span>() { }
}
</pre>
<p>「<code>1.Method()</code> みたな呼び方ができないものが『extension』なのか？」みたいな話はあります。
なので、元々は role, view, shape (同じデータの別の役割・見え方・輪郭)みたいな言葉を使おうかという話も出ていました。
ただ、変に用語を増やすよりは、「暗黙的拡張」、「明示的拡張」と呼び分ける方がいいのではないかということになって、こちらにも <code>extension</code> を使おうという流れになっています。</p>
<p>ちなみに、同じ型に対する別の extension はお互い型変換させるつもりはないそうです。</p>
<pre class="source" title="2つの異なる explicit exntension">
<span class="comment">// 基となる型から extension への変換は暗黙 OK。</span>
<span class="type">Ex1</span> <span class="variable">ex1</span> = 1;
<span class="type">Ex2</span> <span class="variable">ex2</span> = 2;

<span class="comment">// extension 同士の変換はダメ。</span>
<span class="type">Ex2</span> <span class="variable">ex3</span> = <span class="variable">ex1</span>;

<span class="reserved">explicit</span> <span class="reserved">extension</span> <span class="type">Ex1</span> <span class="reserved">for</span> <span class="reserved">int</span> { }
<span class="reserved">explicit</span> <span class="reserved">extension</span> <span class="type">Ex2</span> <span class="reserved">for</span> <span class="reserved">int</span> { }
</pre>
<p>要は、strong-typedef 的なものに使えます。
(この辺りが「それは extension なのか？」と言われるゆえんです。
拡張するメンバーが一切なくても使い道があります。)</p>
<h3>細かい文法話</h3>
<p>extension は別の extension からの派生もOKで、
多重継承も認めるそうです。</p>
<p>インターフェイス実装もできるわけで、
<code>:</code> の後ろには他の extension とインターフェイスが並びます。
例えば以下のような感じ。
(<code>T</code> は通常の型、<code>I</code> 始まりのものがインターフェイス、<code>X</code> 始まりのものが extension。)</p>
<pre class="source" title="extension 定義(文法まとめ)">
<span class="reserved">implicit</span> <span class="reserved">extension</span> <span class="type">X</span> <span class="reserved">for</span> <span class="type">T</span> : <span class="type">XA</span>, <span class="type">XB</span>, <span class="type">IA</span>, <span class="type">IB</span>
{
}
</pre>
<p>ちなみに、ここでいう <code>T</code> (<code>for</code> の後ろの型)のことを「基になる型」(underlying type: 根底にある型、基礎となる型)と言います。
(C# 的には、<code>enum</code> なんかの <code>enum E : int { }</code> とかの <code>int</code> の部分も underlying type と言います。Microsoft の和訳では undelying type = 基になる型。)</p>
<p>クラスの場合は基底クラスとインターフェイスをあまり区別せず、<code>class Derived : Base, IA, IB</code> と書ける(ただし、基底クラスは先頭である必要あり)わけですが、
extension の場合は <code>for</code> を使って <code>:</code> とは分ける方向で考えているみたいです。
基底型をいくつも持てるし、ただでさえ基底型とインターフェイスの混在があるのに、さらに基になる型 <code>T</code> も並べた時に、「同じ <code>:</code> を使って、一番先頭という縛りを設ける」というのはいささか不安だったそうです。
特に、<code>partial</code> を認めるつもりなので、その場合に「一番先頭」があやふやになるのを懸念したみたいです。</p>
<pre class="source" title="partial extension">
<span class="reserved">implicit</span> <span class="reserved">partial</span> <span class="reserved">extension</span> <span class="type">X</span> <span class="reserved">for</span> <span class="type">T</span> : <span class="type">XA</span>, <span class="type">IA</span>
{
}

<span class="reserved">implicit</span> <span class="reserved">partial</span> <span class="reserved">extension</span> <span class="type">X</span> : <span class="type">XB</span>, <span class="type">IB</span>
{
}
</pre>
<p>また、既存の拡張メソッドがトップレベルの型での定義以外を認めていないのに対して、
新しい extension は入れ子を認めるそうです。</p>
<pre class="source" title="partial extension">
<span class="reserved">using</span> <span class="reserved">static</span> <span class="type">Ex</span>;
<span class="reserved">using</span> <span class="reserved">static</span> <span class="type">C</span>;

<span class="comment">// ちゃんと呼べる。</span>
1.<span class="method">M1</span>();
2.<span class="method">M2</span>();

<span class="reserved">implicit</span> <span class="reserved">extension</span> <span class="type">Ex</span> <span class="reserved">for</span> <span class="type">T</span>
{
    <span class="reserved">implicit</span> <span class="reserved">extension</span> <span class="type">NextedEx</span> <span class="reserved">for</span> <span class="reserved">int</span>
    {
        <span class="reserved">void</span> <span class="method">M1</span>() { }
    }
}

<span class="reserved">class</span> <span class="type">C</span>
{
    <span class="reserved">implicit</span> <span class="reserved">extension</span> <span class="type">NextedEx</span> <span class="reserved">for</span> <span class="reserved">int</span>
    {
        <span class="reserved">void</span> <span class="method">M2</span>() { }
    }
}
</pre>
<p>さらに、ジェネリックにもできるそうです。</p>
<pre class="source" title="generic extension">
<span class="reserved">implicit</span> <span class="reserved">extension</span> <span class="type">X</span>&lt;<span class="type">T</span>&gt; <span class="reserved">for</span> <span class="type">T</span> : <span class="type">XA</span>, <span class="type">IA</span>
    <span class="reserved">where</span> <span class="type">T</span> : <span class="type">IT</span>
{
}
</pre>
<p>派生 extension を作る際には、
基となる型の条件を強める方向でなら、基となる型の変更もできるみたいです。</p>
<pre class="source" title="基となる型の変更">
<span class="reserved">implicit</span> <span class="reserved">extension</span> <span class="type">XBase</span> <span class="reserved">for</span> <span class="type">IEnumerable</span>&lt;<span class="reserved">object</span>&gt;
{
}

<span class="comment">// IEnumerable&lt;object&gt; から IEnumerable&lt;string&gt; への変更はOK。</span>
<span class="comment">// (逆だとダメ。)</span>
<span class="reserved">implicit</span> <span class="reserved">extension</span> <span class="type">XDerived1</span> <span class="reserved">for</span> <span class="type">IEnumerable</span>&lt;<span class="reserved">string</span>&gt; : <span class="type">XBase</span>
{
}

<span class="comment">// ちなみに、基となる型に変更がないなら for は省略可。</span>
<span class="reserved">implicit</span> <span class="reserved">extension</span> <span class="type">XDerived2</span> : <span class="type">XBase</span>
{
}
</pre>
<h2>実装方法</h2>
<p>現状、文法面をどうするかが議論の中心で、
あんまり実装方法に関する決定はないみたいなんですが、
案として挙がっているのは以下のような方向性です。</p>
<p>例えば、前述の(以下に再掲) extension に対して、</p>
<pre class="source" title="前述の extension">
<span class="reserved">implicit</span> <span class="reserved">extension</span> <span class="type">Ex</span> <span class="reserved">for</span> <span class="reserved">int</span>
{
    <span class="reserved">public</span> <span class="reserved">void</span> <span class="method">Method</span>() { }
    <span class="reserved">public</span> <span class="reserved">int</span> <span class="property">Property</span> => <span class="reserved">int</span>;
    <span class="reserved">public</span> <span class="reserved">int</span> <span class="reserved">this</span>[<span class="reserved">int</span> <span class="variable">index</span>] => <span class="variable">index</span>;

    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">StaticMethod</span></span>() { }
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="type">Ex</span> <span class="reserved">operator</span>+ (<span class="type">Ex</span> <span class="variable">x</span>) => <span class="variable">x</span>;
}
</pre>
<p>以下のようなラッパー構造体を作るのはどうかという案になっています。</p>
<pre class="source" title="">
<span class="reserved">ref</span> <span class="reserved">struct</span> <span class="type struct">Ex</span>
{
    <span class="reserved">private</span> <span class="reserved">ref</span> <span class="reserved">int</span> <span class="field">@this</span>;
    <span class="reserved">public</span> <span class="type struct">Ex</span>(<span class="reserved">ref</span> <span class="reserved">int</span> <span class="variable local">@this</span>) <span class="operator">=&gt;</span> <span class="reserved">this</span><span class="operator">.</span><span class="field">@this</span> <span class="operator">=</span> <span class="reserved">ref</span> <span class="variable local">@this</span>;

    <span class="reserved">public</span> <span class="reserved">void</span> <span class="method">Method</span>() { }
    <span class="reserved">public</span> <span class="reserved">int</span> <span class="property">Property</span> <span class="operator">=&gt;</span> <span class="field">@this</span>;
    <span class="reserved">public</span> <span class="reserved">int</span> <span class="reserved">this</span>[<span class="reserved">int</span> <span class="variable local">index</span>] <span class="operator">=&gt;</span> <span class="variable local">index</span>;

    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">StaticMethod</span></span>() { }
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="type struct">Ex</span> <span class="reserved">operator</span> <span class="operator">+</span>(<span class="type struct">Ex</span> <span class="variable local">x</span>) <span class="operator">=&gt;</span> <span class="variable local">x</span>;
}
</pre>
<p><a href="https://ufcpp.net/study/csharp/resource/refstruct/">ref 構造体</a>、<a href="https://ufcpp.net/study/csharp/resource/refstruct/#ref-field">ref フィールド</a>を使う想定なので、
別途以下のような機能(C# 11 時点で認められていない)が必要になります。</p>
<ul>
<li>ref 構造体の ref フィールドを持てるようにする</li>
<li>ref 構造体をジェネリック型引数にする</li>
<li>ref 構造体でインターフェイスを実装する</li>
</ul>
<pre class="source" title="C# 11 で無理なものの、extension の実装に欲しいもの">
<span class="comment">// 現状、ref 構造体はインターフェイス実装を持てない。</span>
<span class="reserved">ref</span> <span class="reserved">struct</span> <span class="type struct">S</span> : <span class="error" title="CS0535"><span class="error" title="CS0535"><span class="error" title="CS8343"><span class="type">IEnumerable</span>&lt;<span class="reserved">int</span>&gt;</span></span></span>
{
    <span class="comment">// 現状、ref 構造体の ref フィールドはダメ。</span>
    <span class="error" title="CS9050"><span class="reserved">ref</span> <span class="type struct">S</span></span> <span class="warning" title="CS0169"><span class="field"><span class="error" title="CS0523">_refS</span></span></span>;

    <span class="comment">// 現状、ref 構造体を型引数に渡せない。</span>
    <span class="type">IEnumerable</span>&lt;<span class="type struct">S</span>&gt; <span class="method"><span class="error" title="CS0306">GetItems</span></span>()
    {
        <span class="control">yield</span> <span class="control">return</span> <span class="reserved">default</span>;
    }
}
</pre>
<h2>実装フェーズ</h2>
<p>冒頭に「C# 12 で全て実装されるかどうか怪しい」という話をしましたが、
具体的には以下のような3つのフェーズに分かれています。</p>
<ol>
<li>静的メンバーの拡張だけ認める</li>
<li>インスタンス メンバーも認める</li>
<li>インターフェイス実装を認める</li>
</ol>
<p>前節で説明したように、ref フィールドを使った実装にする可能性が濃厚なわけで、
これら3フェーズは要するに、</p>
<ul>
<li>静的メンバー: 現状でもできる</li>
<li>インスタンス メンバー: ref 構造体の ref フィールドを認めた上でやりたい</li>
<li>インターフェイス実装: ref 構造体のインターフェイス実装を認めた上でやりたい</li>
</ul>
<p>という区分だったりします。</p>
<p>1と2を分けるのは少々気持ち悪いので実際にはこの2つは同時に提供されるかもしれませんが、
実装都合でいうと結構な難易度の隔たりがあるそうです。</p>
<p>ちなみに、「<a href="https://github.com/dotnet/csharplang/discussions/2505">静的メソッドの拡張をしたい、既存の型に静的メソッドを追加したい</a>」という要望もそれなりに昔からあるので、
1だけ先行実装というのもそこまで不自然でもないかもしれません。</p>
 ]]></description>
				<pubDate>Sun, 05 Mar 2023 22:39:12 +0900</pubDate>
			</item>
			<item>
				<title>【C# 12 候補】params Span、改め、params ReadOnlySpan</title>
				<link>http://ufcpp.net/blog/2023/2/params-ros/</link>
				<description><![CDATA[ <p>今回は <a href="https://ufcpp.net/study/csharp/sp_params.html#params">params</a> の話。</p>
<ul>
<li>
Working Group 議事録
<ul>
<li><a href="https://github.com/dotnet/csharplang/blob/main/meetings/working-groups/params-improvements/PI-2022-10-25.md">2022/10/25</a></li>
<li><a href="https://github.com/dotnet/csharplang/blob/main/meetings/working-groups/params-improvements/PI-2022-11-03.md">2022/11/3</a></li>
</ul>
</li>
</ul>
<p>params の改善話は紆余曲折ありまして。
<a href="https://ufcpp.net/blog/2022/2/params-span/">去年の時点では <code>params Span&lt;T&gt;</code> で検討されていました</a>。
ちょこっとだけマイナーチェンジされまして、現在は <code>params ReadOnlySpan&lt;T&gt;</code> です。</p>
<h2>いろんな型で params 案(没)</h2>
<p>現在の C# の params (可変長引数)は、<code>params T[]</code> (引数の型は配列)しか書けません。
これに対して、任意のコレクション型を使って、<code>params List&lt;T&gt;</code> とか <code>params IEnumerable&lt;T&gt;</code> とか書きたいという要望が長らくありました。</p>
<pre class="source" title="過去の params 改善案">
<span class="comment">// (あくまでも過去の案)</span>
<span class="method"><span class="static">M1</span></span>(<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>);
<span class="method"><span class="static">M2</span></span>(<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>);
<span class="static"><span class="method">M3</span></span>(<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>);

<span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">M1</span></span>(<span class="reserved">params</span> <span class="type">IEnumerable</span>&lt;<span class="reserved">int</span>&gt; <span class="variable local">items</span>) { }
<span class="reserved">static</span> <span class="reserved">void</span> <span class="static"><span class="method">M2</span></span>(<span class="reserved">params</span> <span class="type">List</span>&lt;<span class="reserved">int</span>&gt; <span class="variable local">items</span>) { }
<span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">M3</span></span>(<span class="reserved">params</span> <span class="type struct">Span</span>&lt;<span class="reserved">int</span>&gt; <span class="variable local">items</span>) { }
</pre>
<p>「この類の何かを書きたい」という要望は今でもあるんですが、
ただ、ここにきて<a href="https://ufcpp.net/blog/2023/1/collection-literal/">コレクション リテラル</a>という提案が出ています。
コレクション リテラルがあれば、別に params がなくても以下のように書くことができます。</p>
<pre class="source" title="コレクション リテラルがあれば別にいいのでは…">
<span class="comment">// 呼び出し側をコレクション リテラルにしてしまう。</span>
<span class="comment">// 元の params 案との差は [] の2文字だけ。</span>
<span class="method"><span class="static">M1</span></span>([<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>]);
<span class="method"><span class="static">M2</span></span>([<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>]);
<span class="static"><span class="method">M3</span></span>([<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>]);

<span class="comment">// params で任意のコレクションを扱うのはやめちゃう。</span>
<span class="reserved">static</span> <span class="reserved">void</span> <span class="static"><span class="method">M1</span></span>(<span class="type">IEnumerable</span>&lt;<span class="reserved">int</span>&gt; <span class="variable local">items</span>) { }
<span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">M2</span></span>(<span class="type">List</span>&lt;<span class="reserved">int</span>&gt; <span class="variable local">items</span>) { }
<span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">M3</span></span>(<span class="type struct">Span</span>&lt;<span class="reserved">int</span>&gt; <span class="variable local">items</span>) { }
</pre>
<p><code>[]</code> の2文字程度ならさぼらず書いてもいいんじゃないかという感じがします。
なので、「params の汎用化」という目的においてはもう別にやらなくてもいいんじゃないかという雰囲気になっています。</p>
<h2>params ReadOnlySpan</h2>
<p>「params の汎用化」が没り気味な一方で、
「既存の <code>params T[]</code> 利用個所のパフォーマンスを改善したい」という要件は残っています。
そこで出てくるのが <code>params ReadOnlySpan&lt;T&gt;</code> になります。</p>
<p>すなわち、</p>
<ul>
<li>params に使えそうな中で一番パフォーマンス的に有利な <code>ReadOnlySpan</code> だけを残す</li>
<li>
既存の <code>params T[]</code> よりも、<code>params ReadOnlySpan&lt;T&gt;</code> の方がオーバーロード解決優先順位を上にする
<ul>
<li>既存のメソッドに <code>params ReadOnlySpan&lt;T&gt;</code> なオーバーロードを足せば、利用側は再コンパイルするだけでパフォーマンス改善になる</li>
</ul>
</li>
</ul>
<p>という方針で進めるようです。</p>
<p>ちなみに、<code>params ReadOnlySpan&lt;T&gt;</code> で定義した引数は常に <a href="https://ufcpp.net/study/csharp/resource/refstruct/#scoped">scoped</a> みたいです。
ReadOnly で受け取っているので書き換えできず、scoped なのでメソッドの外には漏らせません。
その結果、呼び出し側で <code>M(a, b, c)</code> みたいな書き方から「<code>a</code>, <code>b</code>, <code>c</code> を含む <code>ReadOnlySpan</code>」を作るときの最適化がしやすくなっています
(DLL のデータ領域を直接参照したり、複数回呼び出されるときに同じバッファーを使いまわしたり)。</p>
<h2>固定長バッファー</h2>
<p>以下のようなコードを書いたとき、</p>
<pre class="source" title="params ReadOnlySpan">
<span class="method"><span class="static">M</span></span>(<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>);
<span class="method"><span class="static">M</span></span>(<span class="string">"a"</span>, <span class="string">"b"</span>, <span class="string">"c"</span>);

<span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">M</span></span>&lt;<span class="type">T</span>&gt;(<span class="reserved">params</span> <span class="type struct">ReadOnlySpan</span>&lt;<span class="type">T</span>&gt; <span class="variable local">items</span>) { }
</pre>
<p>概念的には、以下のように「スタック割り当て」をしたいです。</p>
<pre class="source" title="">
<span class="comment">// int の場合はこれで問題ない。</span>
<span class="type struct">ReadOnlySpan</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">temp1</span> <span class="operator">=</span> <span class="reserved">stackalloc</span>[] { <span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span> };
<span class="method"><span class="static">M</span></span>(<span class="variable">temp1</span>);

<span class="comment">// 現状、参照型の stackalloc はできないので、何らかの対処が必要。</span>
<span class="type struct">ReadOnlySpan</span>&lt;<span class="reserved">string</span>&gt; <span class="variable">temp2</span> <span class="operator">=</span> <span class="error" title="CS0208"><span class="reserved">stackalloc</span>[] { <span class="string">&quot;a&quot;</span>, <span class="string">&quot;b&quot;</span>, <span class="string">&quot;c&quot;</span> }</span>;
<span class="static"><span class="method">M</span></span>(<span class="variable">temp2</span>);

<span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">M</span></span>&lt;<span class="type">T</span>&gt;(<span class="reserved">params</span> <span class="type struct">ReadOnlySpan</span>&lt;<span class="type">T</span>&gt; <span class="variable local">items</span>) { }
</pre>
<p>そこで、参照型にも使えるスタック割り当て手段を必要とするわけですが。
<a href="https://ufcpp.net/blog/2022/2/params-span/">去年の時点で</a>、
「<a href="https://github.com/dotnet/runtime/pull/60428">Experiment with 'Unsafe.StackAlloc<T>'</a>」とか「<a href="https://github.com/dotnet/runtime/pull/60519">[hackathon] ValueArray</a>」みたいなプロトタイプもあったんですが、あんまり筋はよくなかったようで没っています。</p>
<p>そして現状、「特殊な属性を1個用意して、それをつけると .NET ランタイムが特殊対応して固定長バッファーを生成する」みたいな案で進んでいるようです。</p>
<ul>
<li><a href="https://github.com/dotnet/runtime/issues/61135">[API Proposal]: InlineArrayAttribute #61135</a></li>
</ul>
<p>ちなみに、<code>params ReadOnlySpan&lt;T&gt;</code> と <code>ReadOnlySpan&lt;T&gt;</code> に対する<a href="https://ufcpp.net/blog/2023/1/collection-literal/">コレクション リテラル</a>は同じ戦略をとるそうで
(やることは同じなので2重実装は避ける)、
「params の改善」と「コレクション リテラル」は2つ合わせて同時に進めるということになりました。</p>
 ]]></description>
				<pubDate>Sun, 12 Feb 2023 15:41:58 +0900</pubDate>
			</item>
			<item>
				<title>【C# 12 候補】コレクション リテラル</title>
				<link>http://ufcpp.net/blog/2023/1/collection-literal/</link>
				<description><![CDATA[ <p>今回はコレクション リテラルの話。</p>
<p>・提案 issue: <a href="https://github.com/dotnet/csharplang/issues/5354">[Proposal]: Collection literals #5354</a></p>
<p>今日の話も、提案自体は<a href="https://ufcpp.net/blog/2021/12/collection-literal/">去年から結構前向きに検討されてたもの</a>です。
リスト パターンの実装の過程で出てきた案で、元から「C# 11 には間に合わないかも」みたいな空気感だったもの。
昨年11月に C# 11 が世に出た後、改めて進捗が出始めたので、今日はその辺りの話になります。</p>
<p>ちなみに、<a href="https://github.com/dotnet/roslyn/blob/main/docs/Language%20Feature%20Status.md">Language Feature Status</a> で、<a href="https://github.com/dotnet/roslyn/commit/0e17a88c3b34f7c7f995c5e29207d2bfe0095fb9">最近 &quot;C# Next&quot; の欄に並びました</a>。
実装もちらほら始まっているので、割かし C# 12 入りが有望だと思います。</p>
<h2>コレクション リテラルおさらい</h2>
<p><a href="https://ufcpp.net/blog/2021/12/collection-literal/">去年</a>から大体決まってそうなところをおさらい。</p>
<p>文法的には <code>[]</code> を使う案が有力です。</p>
<pre class="source" title="[] リテラル案">
<span class="reserved">using</span> System<span class="operator">.</span>Collections<span class="operator">.</span>Immutable;

<span class="comment">// いろんなコレクション型に対して共通して使える。</span>
<span class="reserved">int</span>[] <span class="variable">array</span> <span class="operator">=</span> [<span class="number">1, 2, 3</span>];
<span class="type struct">Span</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">span</span> = [<span class="number">1, 2, 3</span>];
<span class="type">List</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">list</span> = [<span class="number">1, 2, 3</span>];
<span class="type struct">ImmutableArray</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">immutable</span> = [<span class="number">1, 2, 3</span>];
</pre>
<p>また、同時に、いわゆる &quot;spread&quot; と呼ばれる操作も導入されます。</p>
<pre class="source" title="コレクションの spread">
<span class="comment">// いろんなコレクション型に対して共通して使える。</span>
<span class="reserved">int</span>[] <span class="variable">a</span> <span class="operator">=</span> [<span class="number">1</span>, <span class="number">2</span>];
<span class="reserved">int</span>[] <span class="variable">b</span> <span class="operator">=</span> [<span class="number">3</span>, <span class="number">4</span>];

<span class="comment">// これだと、2重配列の [ [1, 2], [3, 4] ] になる。</span>
<span class="reserved">int</span>[][] <span class="variable">nested</span> <span class="operator">=</span> [<span class="variable">a</span>, <span class="variable">b</span>];

<span class="comment">// これが &quot;spread&quot;。各コレクションを展開して、concat 的な操作をする。</span>
<span class="comment">// [ 1, 2, 3, 4] になる。</span>
<span class="reserved">int</span>[] <span class="variable">spread</span> <span class="operator">=</span> [..<span class="variable">a</span>, ..<span class="variable">b</span>];

<span class="comment">// もちろん混在もあり得る。</span>
<span class="comment">// [ [1, 2], 3, 4] になる。</span>
<span class="reserved">object</span>[] <span class="variable">spread</span> <span class="operator">=</span> [<span class="variable">a</span>, ..<span class="variable">b</span>];
</pre>
<p>導入の動機は以下のようなものです。</p>
<ul>
<li>
現在だと <code>new T[] { ... }</code>, <code>new T { ... }</code>, <code>stackalloc T[] { ... }</code>, <code>T.Create(...)</code> みたいにバラバラな書き方になるものを簡潔な書き方に統一する
<ul>
<li>特に、<a href="https://ufcpp.net/blog/2022/12/stackalloc-natural-type/"><code>stackalloc</code></a> みたいな不自然な構文の必要性を減らす</li>
</ul>
</li>
<li><a href="https://ufcpp.net/study/csharp/datatype/patterns/?p=2#list">リスト パターン</a>と対称な構文を用意する</li>
<li>
コレクション初期化周りのパフォーマンス改善
<ul>
<li>現状書くとすると <code>a.Concat(b).Append(c).ToArray()</code> は書くのが煩雑な上にパフォーマンスが悪い</li>
<li><a href="https://ufcpp.net/blog/2022/2/span-optimization/">ReadOnlySpan 最適化</a>みたいな知らないとまず書けない最適化を減らしたい</li>
</ul>
</li>
<li>
型推論フレンドリーにしたい
<ul>
<li><a href="https://ufcpp.net/blog/2022/11/covariantarrayincident/">現在の事故例</a></li>
</ul>
</li>
</ul>
<h2>その後</h2>
<p>最近の C# チームは、有望そうな機能ごとに、その機能を専門に検討する「Working Group」という単位を作って作業をしています。
コレクション リテラルにも Working Group があって、2回ほど Working Group 内でのミーティング議事録が公開されています。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/blob/main/meetings/working-groups/collection-literals/CL-2022-10-06.md">Collection literals working group meeting for October 6th, 2022</a></li>
<li><a href="https://github.com/dotnet/csharplang/blob/main/meetings/working-groups/collection-literals/CL-2022-10-14.md">Collection literals working group meeting for October 14th, 2022</a></li>
<li><a href="https://github.com/dotnet/csharplang/blob/main/meetings/working-groups/collection-literals/CL-2022-10-21.md">Collection literals working group meeting for October 21st, 2022</a></li>
</ul>
<p>以下、これらの議事録から<a href="https://ufcpp.net/blog/2021/12/collection-literal/">去年</a>からの進捗を拾って列挙していこうかと思います。</p>
<ul>
<li>
自然な型 (<code>var x = [a];</code> のときの <code>x</code> の型)は <code>List&lt;T&gt;</code> がよさそう
<ul>
<li><code>var a = [x]; a.Add(y);</code> ってやりたい</li>
<li><code>let</code> (readonly local) が入るんなら、<code>let x = [a];</code> の自然な型は <code>ImmutableArray&lt;T&gt;</code> がよさげ。Swift がそう</li>
</ul>
</li>
<li>
アロケーションを減らせるように、長さが既知なら <code>new List&lt;T&gt;(length)</code> みたいに capacity を渡せるようにしたい
<ul>
<li><code>IEnumerable&lt;T&gt;</code> に対しても、<code>Enumerable.TryGetNonEnumeratedCount</code> を使って事前に長さをとれないか試みる</li>
</ul>
</li>
<li>当初予定では <code>var x = new(length); x.Init(buffer);</code> みたいなコード生成のつもりでいたけども、このメソッドは <code>Init</code> よりも <code>Construct</code> という名前の方がいいかも</li>
<li>長さが未知の <code>[..enumarable]</code> を <code>ImmutableArray&lt;T&gt;</code> みたいな <code>Add</code> が使えない型に対しても使えるようにしたい</li>
<li>lazy な enumerable に対して <code>[..a, ..b]</code> するとき、これも lazy であってほしいと望む人もいそうだけど、たぶん、(即時評価で)新しいコレクション作る</li>
<li>
新しい文法がが「一番パフォーマンスいい」状態にはしたい
<ul>
<li>(<code>ImmutableArray&lt;T&gt;</code> に対する <code>[..enumerableOfT]</code> は <code>ImmutableArray.CreateRange&lt;T&gt;</code> よりも遅くなってはいけない。)</li>
</ul>
</li>
<li><code>[..a]</code> は <code>a</code> のクローン手段として使えていい</li>
<li><code>[]</code> は <code>null</code> と同様に、「どんな型のコレクションにでも代入できる特殊なリテラル」であるべき</li>
<li><code>var list = cond ? [str] : [obj];</code> の型はどう決める？ target-typed? それか、common-base-type?</li>
<li>
一緒に Dictionary リテラルもやる。最有力候補は <code>[key:value]</code>という書き方
<ul>
<li><code>key:value</code> の部分で <code>KeyValuePair&lt;TKey, TValue&gt;</code> なリテラルになりそう</li>
<li><code>List&lt;T&gt;</code>, <code>Dictionary&lt;TKey, TValue&gt;</code>, <code>KeyValuePair&lt;TKey, TValue&gt;</code> の3つの型は first-class になりそう</li>
</ul>
</li>
</ul>
<h3>Dictionary リテラル</h3>
<p>特に、Dictionary リテラルの話は<a href="https://ufcpp.net/blog/2021/12/collection-literal/">去年</a>はまだなかったですかね、確か。
候補となる文法は以下のようなもの。
(このうち、<code>[key: value]</code> が有力。<code>[ [key] = value ]</code> もありかも。)</p>
<pre class="source" title="Dictionary リテラルの文法候補">
<span class="reserved">var</span> <span class="variable">dict1 <span class="operator">=</span> { <span class="string">&quot;key1&quot;</span></span>: <span class="string">&quot;value1&quot;</span>, <span class="string">&quot;key2&quot;</span>: <span class="string">&quot;value2&quot;</span> };
<span class="reserved">var</span> <span class="variable">dict2</span> <span class="operator">=</span> [<span class="string">&quot;key1&quot;</span>: <span class="string">&quot;value1&quot;</span>, <span class="string">&quot;key2&quot;</span>: <span class="string">&quot;value2&quot;</span> ];
<span class="reserved">var</span> <span class="variable">dict3</span> <span class="operator">=</span> [ [<span class="string">&quot;key1&quot;</span>] <span class="operator">=</span> <span class="string">&quot;value1&quot;</span>, [<span class="string">&quot;key2&quot;</span>] <span class="operator">=</span> <span class="string">&quot;value2&quot;</span> ];
<span class="reserved">var</span> <span class="variable">dict4</span> <span class="operator">=</span> [<span class="string">&quot;key1&quot;</span> <span class="operator">=&gt;</span> <span class="string">&quot;value1&quot;</span>, <span class="string">&quot;key2&quot;</span> <span class="operator">=&gt;</span> <span class="string">&quot;value2&quot;</span>];
</pre>
<p>Dictionary リテラルをやるのであれば、一緒に「Dictionary パターン」もやりたいそうです。</p>
<pre class="source" title="Dictionary パターンの文法候補">
<span class="reserved">var</span> <span class="variable">dict</span> = [ <span class="string">"key1"</span>: <span class="string">"value1"</span>, <span class="string">"key2"</span>: <span class="string">"value2"</span> ];

<span class="reserved">if</span> (<span class="variable">dict</span> <span class="reserved">is</span> [ <span class="string">"key1"</span>: <span class="reserved">var</span> <span class="variable">value</span> ])
{
}
</pre>
<p><code>[key: value]</code> の場合には <code>x.Add(new(key, value))</code> (もしくは前述の <code>Construct</code>)扱いで、
<code>[ [key] = value ]</code> の場合には <code>x[key] = value</code> 扱いという区別で両方認める可能性もあります。
この場合、「パターン」の方も、以下のような別パターンを考えます。</p>
<pre class="source" title="Dictionary パターンの文法候補">
<span class="reserved">var</span> <span class="variable">dict</span> = [ [<span class="string">"key1"</span>] = <span class="string">"value1"</span>, [<span class="string">"key2"</span>] = <span class="string">"value2"</span> ];

<span class="reserved">if</span> (<span class="variable">dict</span> <span class="reserved">is</span> [ [<span class="string">"key1"</span>]: <span class="reserved">var</span> <span class="variable">value</span> ])
{
}
</pre>
<p>他に、以下のような話あり。</p>
<ul>
<li>spread の併用で <code>[..dict, prop: a]</code> とか書くのも OK</li>
<li>Swift は <code>[:]</code> で空辞書リテラル作れる。C# もやる？</li>
<li><code>init void Init(KeyValuePair&lt;TKey, TValue&gt;[] values)</code> で実装</li>
<li>コレクション インデクサー(<code>List&lt;string&gt; list = [0: &quot;first&quot;, 1: &quot;second&quot;];</code> みたいなの)も認める？</li>
<li>Dictionary 2個連結した <code>[..dict1, ..dict2]</code> は Dictionary であるべき</li>
</ul>
 ]]></description>
				<pubDate>Sun, 29 Jan 2023 16:24:10 +0900</pubDate>
			</item>
			<item>
				<title>using alias を任意の型に対応</title>
				<link>http://ufcpp.net/blog/2023/1/using-alias-any-types/</link>
				<description><![CDATA[ <p>今日は using alias の話。</p>
<ul>
<li>提案: <a href="https://github.com/dotnet/csharplang/blob/main/proposals/using-alias-types.md">Allow using alias directive to reference any kind of Type</a></li>
</ul>
<p>これはちらほら実装が始まっているので近々触れるものが出てくるんじゃないでしょうか。</p>
<h2>既存の using ディレクティブ</h2>
<p>using alias は、using ディレクティブを書くときに <code>using T = System.DateOnly;</code> みたいに書いて、以後は <code>T</code> だけで型名を参照できるやつ。
現状何が問題かというと…</p>
<p>まず、以下のコードであれば現状でもコンパイルできるんですが…</p>
<pre class="source" title="現状の C# でも書ける using alias">
<span class="reserved">using</span> <span class="type">List</span> <span class="operator">=</span> System<span class="operator">.</span>Collections<span class="operator">.</span>Generic<span class="operator">.</span><span class="type">List</span>&lt;<span class="reserved">int</span>&gt;;
<span class="reserved">using</span> <span class="type">ListA</span> <span class="operator">=</span> System<span class="operator">.</span>Collections<span class="operator">.</span>Generic<span class="operator">.</span><span class="type">List</span>&lt;<span class="reserved">int</span>[]&gt;;
<span class="reserved">using</span> <span class="type">ListN</span> <span class="operator">=</span> System<span class="operator">.</span>Collections<span class="operator">.</span>Generic<span class="operator">.</span><span class="type">List</span>&lt;<span class="reserved">int</span><span class="operator">?</span>&gt;;
<span class="reserved">using</span> <span class="type">ListT</span> <span class="operator">=</span> System<span class="operator">.</span>Collections<span class="operator">.</span>Generic<span class="operator">.</span><span class="type">List</span>&lt;(<span class="reserved">int</span>, <span class="reserved">int</span>)&gt;;
</pre>
<p>そのくせ以下のコードはコンパイルできません。</p>
<pre class="source" title="現状ではコンパイルできない using alias">
<span class="reserved">using</span> <span class="type">Primitive</span> <span class="operator">=</span>  <span class="reserved"><span class="error" title="CS1001">int</span></span>;
<span class="reserved">using</span> <span class="type">Array</span> <span class="operator">=</span> <span class="reserved"><span class="error" title="CS1001"><span class="error" title="CS1002">int</span></span></span>[<span class="error" title="CS0116">]</span>;
<span class="reserved">using</span> <span class="type">Nullable</span> <span class="operator">=</span> <span class="error" title="CS1002"><span class="reserved">int</span></span><span class="error" title="CS0116"><span class="operator">?</span></span>;
<span class="reserved">using</span> <span class="type">Tuple</span> <span class="operator">=</span> <span class="error" title="CS1002">(</span><span class="reserved"><span class="error" title="CS1525">int</span></span>, <span class="reserved"><span class="error" title="CS1525">int</span></span>);
</pre>
<p>要するに、ジェネリック型引数なら制限がほとんどないのに、トップレベルの時にだけ、以下のものを書けないという制限がありました。</p>
<ul>
<li><code>int</code> みたいにキーワードを使ったプリミティブ型 (⇔ <code>System.Int32</code> なら書ける)</li>
<li>null 許容型 (<code>T?</code>) (⇔ <code>System.Nullable&lt;T&gt;</code> なら書ける)</li>
<li>タプル (<code>(T1, T2)</code>) (⇔ <code>System.ValueTuple&lt;T1, T2&gt;</code> なら書ける)</li>
<li>配列 (<code>T[]</code>)</li>
</ul>
<p>まあさすがにいい加減これを認めようという話になっています。</p>
<p>一番需要があるのはタプルですかね。
あと、最近では<a href="https://github.com/ufcpp/UfcppSample/issues/347">関数ポインター</a>なんかも <code>delegate*&lt;int, int, void&gt;</code> みたいな感じで名前が長くなりがちなので、これに対しても使いたいみたいです。</p>
<h2>微修正</h2>
<p><code>int</code> とか <code>int?</code> とかに対応するだけなら大した変更は要らないみたいです。
<a href="https://github.com/dotnet/csharplang/blob/main/proposals/using-alias-types.md">構文的には1行書き変わるだけ</a>。</p>
<pre>
using_alias_directive
-    : 'using' identifier '=' namespace_or_type_name ';'
+    : 'using' identifier '=' (namespace_name | type) ';'
    ;
</pre>
<p>たぶん、「元々 using 専用に特殊処理していたけども、普通の型名参照と同じものに置き換える」みたいな感じでしょうか。</p>
<p>これは…
もっと早くから対応してくれててもよかった疑惑が…</p>
<h2>トップレベルの null 許容参照型</h2>
<p>参照型に対しては、トップレベルでは <code>?</code> をつけれないようにするみたいです。
まあ、今でも、<code>typeof(string)</code> は書けても <code>typeof(string?)</code> とは書けないので、
それと同じです。</p>
<pre class="source" title="トップレベルの NRT">
<span class="reserved">using</span> <span class="type">List</span> <span class="operator">=</span> System<span class="operator">.</span>Collections<span class="operator">.</span>Generic<span class="operator">.</span><span class="type">List</span>&lt;<span class="reserved">string</span><span class="operator">?</span>&gt;; <span class="comment">// これは OK。</span>
<span class="reserved">using</span> <span class="type">S</span> <span class="operator">=</span> <span class="error"><span class="reserved">string</span><span class="operator">?</span></span>; <span class="comment">// これはダメ。</span>
</pre>
<h2>ポインター</h2>
<p>要望として関数ポインターのエイリアスを作りたいわけですが。
<a href="https://ufcpp.net/study/csharp/sp_unsafe.html">unsafe</a> なものを単に
<code>using T = int*;</code> とか書いていいのかどうかという議題がありました。</p>
<p>これに対しては結局、<code>using unsafe</code> という構文を導入するみたいです。</p>
<pre class="source" title="using unsafe">
<span class="reserved">using</span> <span class="reserved">unsafe</span> <span class="type">T</span> <span class="operator">=</span> <span class="reserved">int</span><span class="operator">*</span>;
<span class="reserved">using</span> <span class="reserved">unsafe</span> <span class="type">F</span> <span class="operator">=</span> <span class="reserved">delegate</span><span class="operator">*</span>&lt;<span class="reserved">int</span>, <span class="reserved">int</span>, <span class="reserved">void</span>&gt;;
</pre>
<h2>今後の課題: 型引数</h2>
<p><a href="https://github.com/dotnet/csharplang/issues/1239">エイリアスをジェネリックにして型引数を持たせたい</a>という話もあります。
以下のような、エイリアスの右辺にも <code>&lt;T&gt;</code> を付けたいというやつ。</p>
<pre class="source" title="エイリアスに &lt;T&gt; を付けたい">
<span class="reserved">using</span> <span class="type">List</span>&lt;<span class="type">T</span>&gt; <span class="operator">=</span> System<span class="operator">.</span>Collections<span class="operator">.</span>Generic<span class="operator">.</span><span class="type">List</span>&lt;<span class="type">T</span>&gt;;
</pre>
<p>これはこれで要望はあって、Backlog (すぐに手を付けるほどの優先度にはない)とはいえ、
Champion (C# チームの担当がついてる状態)にはなっています。</p>
<p>ただ、これの対応は「微修正」では済まないので、
C# 12 マイルストーンからは外れるみたいです。</p>
 ]]></description>
				<pubDate>Wed, 18 Jan 2023 22:07:04 +0900</pubDate>
			</item>
			<item>
				<title>【C# 12 候補】半自動プロパティ</title>
				<link>http://ufcpp.net/blog/2023/1/semi-auto-property/</link>
				<description><![CDATA[ <p>今日は半自動プロパティの話。</p>
<ul>
<li>提案 issue: <a href="https://github.com/dotnet/csharplang/issues/140">Proposal: Semi-Auto-Properties; field keyword #140</a></li>
</ul>
<p><a href="https://ufcpp.net/blog/2021/12/semi-auto-property/">約1年前にも書いてる</a>通り、場合によっては C# 11 で入っていたかもしれないものです。</p>
<p>需要はそれなりに高いんですが、
案外課題があって結局スケジュール的に11からははずれ、「その後どうなったの？」とか思われていそうな機能です。
(12候補としては結構有力。)</p>
<p>半自動プロパティの話自体は<a href="https://ufcpp.net/blog/2021/12/semi-auto-property/">去年度</a>にしているので、
今日書くのはその「課題」をつらつらと。</p>
<h2>半自動プロパティ概要</h2>
<p>去年の繰り返しになるので概要のみ。
要は、手動で書く通常のプロパティ(以下、手動プロパティ)と自動プロパティの中間で、
バッキング フィールドのアクセスに <code>field</code> というキーワードを使おうというものです。</p>
<pre class="source" title="手動、(全)自動、半自動プロパティ">
<span class="reserved">class</span> <span class="type">A</span>
{
    <span class="comment">// 手動プロパティ (manual property)</span>
    <span class="comment">// (と、自前で用意したフィールド)。</span>
    <span class="comment">// こういう、プロパティからほぼ素通しで値を記録しているフィールドを「バッキング フィールド」(backing field)という。</span>
    <span class="reserved">private</span> <span class="reserved">int</span> <span class="field">_x</span>;
    <span class="reserved">public</span> <span class="reserved">int</span> <span class="property">X</span> { <span class="reserved">get</span> <span class="operator">=&gt;</span> <span class="field">_x</span>; <span class="reserved">set</span> <span class="operator">=&gt;</span> <span class="field">_x</span> <span class="operator">=</span> <span class="reserved">value</span>; }

    <span class="comment">// 自動プロパティ (auto-property)。</span>
    <span class="comment">// 前述の X とほぼ一緒。</span>
    <span class="comment">// バッキング フィールドの自動生成。</span>
    <span class="reserved">public</span> <span class="reserved">int</span> <span class="property">Y</span> { <span class="reserved">get</span>; <span class="reserved">set</span>; }

    <span class="comment">// 【C# 12 候補】 半自動プロパティ (semi-auto-property)。</span>
    <span class="comment">// バッキング フィールドは自動生成。</span>
    <span class="comment">// 全自動の方と違って、バッキング フィールドの使い方は自由にできる。</span>
    <span class="comment">// field キーワードでバッキング フィールドを読み書き。</span>
    <span class="reserved">public</span> <span class="reserved">int</span> <span class="property">Z</span> { <span class="reserved">get</span> <span class="operator">=&gt;</span> <span class="reserved"><em>field</em></span>; <span class="reserved">set</span> <span class="operator">=&gt;</span> <span class="reserved"><em>field</em></span> <span class="operator">=</span> <span class="reserved">value</span>; }
}
</pre>
<h2>field の “キーワード性”</h2>
<p>半自動プロパティに類する提案は他にもありつつも、
現状はとりあえず「<code>field</code> キーワード」案で話が進んでいます。
キーワード追加。</p>
<p>ところが、この世に出ている C# コードの中には「<code>field</code> という名前のフィールドや変数」がそれなりにあって(オープンソースになっているコードとかを検索すると相当量出てくるそうで)、さすがに「<code>field</code> を文脈抜きに無条件にキーワード扱い」とかやるのは、破壊的変更としては許容できるレベルを超えていて、現実的ではないです。
<code>field</code> という単語は、最近提案されている新機能の中では断トツで(<code>record</code> や <code>required</code> すら霞むくらい)影響力が大きいかもしれません。</p>
<p>一方で、文脈キーワードの仕様はなかなかに複雑になりがちで、
今、<a href="https://ufcpp.net/blog/2021/2/lexicalkeywords/">ちょっと単純化したいという話もあるくらい</a>です。
そんな中、半自動プロパティでは早速苦戦しそうな雰囲気。</p>
<p>半自動プロパティの <code>field</code> は、極限まで突き詰めて「有効な時だけキーワード扱い」をやろうとすると <code>var</code> とか <code>record</code> とかよりもだいぶ難しいみたいです。
一例として挙がっているのは以下のようなコード。</p>
<pre class="source" title="field の有効性の循環">
<span class="reserved">unsafe</span> <span class="reserved">struct</span> <span class="type struct">S</span>
{
    <span class="reserved">object</span> <span class="property">Prop</span>
    {
        <span class="reserved">get</span>
        {
            <span class="type struct">S</span> <span class="variable">s</span> <span class="operator">=</span> <span class="reserved">new</span>();

            <span class="comment">// このステートメントは「構造体 S が unmanaged のときだけ有効」</span>
            <span class="comment">// 言い換えると、「構造体 S が参照型のフィールドを持たないときだけ有効」</span>
            <span class="comment">// (C# 11 からは警告のみになったものの、元々はエラー。)</span>
            <span class="reserved">var</span> <span class="variable">ptr</span> <span class="operator">=</span> <span class="operator">&amp;</span><span class="variable">s</span>;

            <span class="comment">// field が「S とは無関係な定数とか」だと &amp;s が有効。</span>
            <span class="comment">// ところが、field がキーワードで、バッキング フィールドが自動的に作られると &amp;s が無効になる。</span>
            <span class="comment">// 「&amp;s が無効にならないようにこれは認めない」みたいなことまでやるのは解析が「循環」してしまう。</span>
            <span class="control">return</span> field;
        }
    }
}
</pre>
<p>なのであんまり正確にやるのはやめておいた方がいいとして、
簡素化した案でいうと以下のようなものがあります。</p>
<ul>
<li>セマンティクスを見るのは「<code>field</code> という名前のクラスと、<code>field</code> という名前のフィールドがあるかどうか」だけ</li>
<li>あとは、構文的にだけ解析して、「スコープ内に <code>field</code> という名前の識別子がいるかどうか」で判定</li>
</ul>
<p>簡素化するために「スコープを無視して解析」みたいな案もあるみたいなんですが、
結局は、以下のように「スコープも考慮に入れる」、「内側のスコープやローカル関数でのシャドーイングは認める」という予定だそうです。</p>
<pre class="source" title="field キーワード/識別子のスコープ">
<span class="reserved">object</span> <span class="property">Prop</span>
{
    <span class="reserved">get</span>
    {
        {
            <span class="comment">// この field は {} 内でだけ有効。</span>
            <span class="reserved">int</span> <span class="variable">field</span> <span class="operator">=</span> <span class="number">1</span>;
        }

        <span class="comment">// このフィールドは m の内側でだけ有効。</span>
        <span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">m</span></span>(<span class="reserved">int</span> <span class="variable local">field</span>) { } 

        <span class="comment">// {} とかローカル関数の外側には &quot;field&quot; がいないので、</span>
        <span class="comment">// ここの field はキーワード。</span>
        <span class="control">return</span> <span class="reserved">field</span>;
    }
}
</pre>
<p>というのも、同スコープ内の解析に限っても、それなりに解析が大変そうな文法がいくつかあって、「労力は変わらない」とのこと。</p>
<pre class="source" title="field のキーワード性の解析が大変そうなやつら">
<span class="reserved">class</span> <span class="type">C</span>
{
    <span class="reserved">int</span> <span class="property">Prop</span>
    {
        <span class="reserved">get</span>
        {
            <span class="reserved">var</span> <span class="variable">x</span> <span class="operator">=</span> (<span class="field">field</span>: <span class="number">1</span>, <span class="number">2</span>); <span class="comment">// タプル要素名</span>
            <span class="reserved">var</span> <span class="variable">y</span> <span class="operator">=</span> <span class="reserved">new</span> { <span class="property">field</span> <span class="operator">=</span> <span class="number">1</span> }; <span class="comment">// 匿名型のプロパティ</span>
            <span class="reserved">var</span> <span class="variable">z</span> <span class="operator">=</span> <span class="reserved">new</span> <span class="type">Foo</span>() { <span class="field">field</span> <span class="operator">=</span> <span class="number">1</span> }; <span class="comment">// オブジェクト初期化子でのフィールド/プロパティ参照</span>
            <span class="control">if</span> (<span class="variable">x</span> <span class="reserved">is</span> { <span class="field">field</span>: <span class="number">1</span> }) { } <span class="comment">// プロパティ パターンでのフィールド/プロパティ参照</span>

            <span class="comment">// 上記の field はいずれも、field という名前の変数が新たに導入されたりはしない。</span>
            <span class="comment">// このスコープ内に &quot;field&quot; はいないので、ここの field はキーワードでいいはず。</span>
            <span class="control">return</span> <span class="reserved">field</span>;
        }
    }
}

<span class="reserved">class</span> <span class="type">Foo</span> { <span class="reserved">public</span> <span class="reserved">int</span> <span class="field">field</span>; }
</pre>
<h2>初期化子の挙動</h2>
<p>C# の構造体には「すべてのフィールドを初期化しきるまで関数メンバー(メソッドやプロパティ)を呼べない」という仕様がありました。
(ただし、<a href="https://ufcpp.net/study/csharp/cheatsheet/ap_ver11/#auto-default">C# 11 で緩和されました</a>。)</p>
<pre class="source" title="すべてのフィールドの初期化が必須">
<span class="reserved">struct</span> <span class="type struct">S</span>
{
    <span class="reserved">int</span> <span class="field">_x</span>;

    <span class="reserved">public</span> <span class="reserved">void</span> <span class="method">M</span>() { }

    <span class="reserved">public</span> <span class="type struct">S</span>()
    {
        <span class="comment">// C# 10 まではコンパイル エラーになってた。</span>
        <span class="method"><span class="error" title="CS0188">M</span></span>(); <span class="comment">// _x の初期化より前</span>
        <span class="field">_x</span> <span class="operator">=</span> <span class="number">0</span>;
    }
}
</pre>
<p>そんな中、C# 6 で<a href="https://ufcpp.net/study/csharp/ap_ver6.html#getter-only"> get-only プロパティ</a>の導入とともに、
「<a href="https://ufcpp.net/study/csharp/ap_ver6.html?p=2#struct-property-init">コンストラクター内での自動プロパティへの代入は、それのバッキング フィールドへの直接代入への最適化を認める</a>」という仕様も入っています。</p>
<pre class="source" title="バッキング フィールドへの代入に展開">
<span class="reserved">struct</span> <span class="type struct">Point</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> <span class="property">X</span> { <span class="reserved">get</span>; <span class="reserved">private</span> <span class="reserved">set</span>; }

    <span class="reserved">public</span> <span class="type struct">Point</span>(<span class="reserved">int</span> <span class="variable local">x</span>)
    {
        <span class="comment">// C# 5.0まではエラーに。</span>
        <span class="property">X</span> <span class="operator">=</span> <span class="variable local">x</span>;

        <span class="comment">// これを認めるために、X = x の部分は「Xのバッキングフィールド = x」に展開される。</span>
    }
}
</pre>
<p>その流れで、プロパティ初期化子も「バッキング フィールドへの代入に展開」されます。
例えば以下のようなコードを書いたとします。</p>
<pre class="source" title="プロパティ初期化子">
<span class="reserved">struct</span> <span class="type struct">S</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> <span class="property">X</span> { <span class="reserved">get</span>; <span class="reserved">private</span> <span class="reserved">set</span>; } <span class="operator">=</span> <span class="number">1</span>;
    <span class="reserved">public</span> <span class="type struct">S</span>() { }
}

<span class="reserved">record</span> <span class="reserved">struct</span> <span class="type struct">R</span>(<span class="reserved">int</span> <span class="variable local">X</span>)
{
    <span class="reserved">public</span> <span class="reserved">int</span> <span class="property">X</span> { <span class="reserved">get</span>; <span class="reserved">private</span> <span class="reserved">set</span>; } <span class="operator">=</span> <span class="variable local">X</span>;
}
</pre>
<p>このコードは、以下のようなコードとほぼ同じ挙動になります。</p>
<pre class="source" title="バッキング フィールドへの代入に展開">
<span class="reserved">struct</span> <span class="type struct">S</span>
{
    <span class="reserved">private</span> <span class="reserved">int</span> <span class="field">_x</span>;
    <span class="reserved">public</span> <span class="reserved">int</span> <span class="property">X</span> { <span class="reserved">get</span> <span class="operator">=&gt;</span> <span class="field">_x</span>; <span class="reserved">private</span> <span class="reserved">set</span> <span class="operator">=&gt;</span> <span class="field">_x</span> <span class="operator">=</span> <span class="reserved">value</span>; }
    <span class="reserved">public</span> <span class="type struct">S</span>()
    {
        <span class="field">_x</span> <span class="operator">=</span> <span class="number">1</span>; <span class="comment">// X = 1 ではなくて、_x = 1</span>
    }
}

<span class="reserved">struct</span> <span class="type struct">R</span>
{
    <span class="reserved">private</span> <span class="reserved">int</span> <span class="field">_x</span>;
    <span class="reserved">public</span> <span class="reserved">int</span> <span class="property">X</span> { <span class="reserved">get</span> <span class="operator">=&gt;</span> <span class="field">_x</span>; <span class="reserved">private</span> <span class="reserved">set</span> <span class="operator">=&gt;</span> <span class="field">_x</span> <span class="operator">=</span> <span class="reserved">value</span>; }

    <span class="reserved">public</span> <span class="type struct">R</span>(<span class="reserved">int</span> <span class="variable local">X</span>)
    {
        <span class="field">_x</span> <span class="operator">=</span> <span class="variable local">X</span>; <span class="comment">// this.X = X ではなくて、_x = 1</span>
    }
}
</pre>
<p>という背景の中、半自動プロパティの場合はどうしようかという問題があります。
例えば以下のようなコードを認めたいんですが、
じゃあ、初期化時に <code>OnXChanged</code> は呼ばれるのかどうか。</p>
<pre class="source" title="半自動プロパティのプロパティ初期化子">
<span class="reserved">struct</span> <span class="type struct">S</span>
{
    <span class="comment">// 流れ的にはこういうプロパティ初期化子も認めたい。</span>
    <span class="reserved">public</span> <span class="reserved">int</span> <span class="property">X</span>
    {
        <span class="reserved">get</span> <span class="operator">=&gt;</span> <span class="reserved">field</span>;
        <span class="reserved">private</span> <span class="reserved">set</span>
        {
            <span class="reserved">field</span> <span class="operator">=</span> <span class="reserved">value</span>;
            <span class="method">OnXChanged</span>();
        }
    } <span class="operator">=</span> <span class="number">1</span>;

    <span class="reserved">public</span> <span class="type struct">S</span>() { }

    <span class="reserved">public</span> <span class="reserved">void</span> <span class="method">OnXChanged</span>()
    {
        <span class="type"><span class="static">Console</span></span><span class="operator">.</span><span class="static"><span class="method">WriteLine</span></span>(<span class="string">&quot;何か副作用起こす&quot;</span>);
    }
}
</pre>
<p>C# 11 での変更前は「自動プロパティと同様にせざるを得ない」と言われていました。
つまるところ、プロパティ初期化子はバッキング フィールドへの直代入に展開されて、
結果的に、<code>OnXChanged</code> は呼ばれないということになります。</p>
<p>C# 11 でこの要件は必然ではなくなったわけですが、
それでも「自動プロパティと同様」の仕様(<code>OnXChanged</code> は呼ばれない)になりそうな雰囲気です。</p>
<h2>override</h2>
<p>override したときの挙動をどうしようかという問題もあります。
というのも、例えば以下のコードを考えます。</p>
<pre class="source" title="自動プロパティの override">
<span class="reserved">class</span> <span class="type">Base</span>
{
    <span class="comment">// 自動プロパティなので、バッキング フィールドが作られる。</span>
    <span class="reserved">public</span> <span class="reserved">virtual</span> <span class="reserved">int</span> <span class="property">Prop</span> { <span class="reserved">get</span>; <span class="reserved">set</span>; }
}

<span class="reserved">class</span> <span class="type">Derived</span> : <span class="type">Base</span>
{
    <span class="comment">// override してる時点で Base.Prop とは別物。</span>
    <span class="comment">// それをまた自動プロパティにすると、Base.Prop のものとは別に追加でバッキング フィールドができる。</span>
    <span class="reserved">public</span> <span class="reserved">override</span> <span class="reserved">int</span> <span class="property">Prop</span> { <span class="reserved">get</span>; <span class="reserved">set</span>; }
}
</pre>
<p>自動プロパティの作るバッキング フィールドは <code>Base</code> と <code>Derived</code> で独立しています。
さらに、virtual なプロパティは「<code>get</code> だけ override」みたいなことができます。</p>
<pre class="source" title="get だけ override">
<span class="reserved">var</span> <span class="variable">x</span> <span class="operator">=</span> <span class="reserved">new</span> <span class="type">Derived</span> { <span class="property">Prop</span> <span class="operator">=</span> <span class="number">2</span> }; <span class="comment">// set は base.Prop のものがそのまま呼ばれる。</span>
<span class="static"><span class="type">Console</span></span><span class="operator">.</span><span class="static"><span class="method">WriteLine</span></span>(<span class="variable">x</span><span class="operator">.</span><span class="property">Prop</span>);        <span class="comment">// get は Derived.Prop が呼ばれて、4 になる。</span>

<span class="reserved">class</span> <span class="type">Base</span>
{
    <span class="reserved">public</span> <span class="reserved">virtual</span> <span class="reserved">int</span> <span class="property">Prop</span> { <span class="reserved">get</span>; <span class="reserved">set</span>; }
}

<span class="reserved">class</span> <span class="type">Derived</span> : <span class="type">Base</span>
{
    <span class="comment">// get だけ override して、base のものの二乗を返す。</span>
    <span class="reserved">public</span> <span class="reserved">override</span> <span class="reserved">int</span> <span class="property">Prop</span> { <span class="reserved">get</span> <span class="operator">=&gt;</span> <span class="reserved">base</span><span class="operator">.</span><span class="property">Prop</span> <span class="operator">*</span> <span class="reserved">base</span><span class="operator">.</span><span class="property">Prop</span>; }
}
</pre>
<p>そんな中、半自動プロパティでの override はどうしよう？という話になります。</p>
<pre class="source" title="半自動プロパティでの override">
<span class="reserved">var</span> <span class="variable">x</span> <span class="operator">=</span> <span class="reserved">new</span> <span class="type">Derived</span> { <span class="property">Prop</span> <span class="operator">=</span> <span class="number">2</span> };
<span class="static"><span class="type">Console</span></span><span class="operator">.</span><span class="method"><span class="static">WriteLine</span></span>(<span class="variable">x</span><span class="operator">.</span><span class="property">Prop</span>);

<span class="reserved">class</span> <span class="type">Base</span>
{
    <span class="reserved">public</span> <span class="reserved">virtual</span> <span class="reserved">int</span> <span class="property">Prop</span> { <span class="reserved">get</span>; <span class="reserved">set</span>; }
}

<span class="reserved">class</span> <span class="type">Derived</span> : <span class="type">Base</span>
{
    <span class="comment">// get だけ override して(全)自動プロパティというのはできない。</span>
    <span class="comment">// じゃあ、get だけ &quot;半&quot;自動プロパティは？</span>
    <span class="comment">// これは Base.Prop とは別のバッキング フィールドになる？</span>
    <span class="reserved">public</span> <span class="reserved">override</span> <span class="reserved">int</span> <span class="property">Prop</span> { <span class="reserved">get</span> <span class="operator">=&gt;</span> <span class="reserved">field</span> <span class="operator">*</span> <span class="reserved">field</span>; }
}
</pre>
<p>これはさすがにどう転んでもわかりにくいので、
いっそのこと、「半自動プロパティでの override はすべてのアクセサー(get/set 両方)の override が必須」とするそうです。</p>
<h2>nullability</h2>
<p>半自動プロパティの導入の動機の1つに遅延初期化、
すなわち、以下のようなコードを書きたいというものがあります。</p>
<pre class="source" title="遅延初期化目的の半自動プロパティ">
<span class="reserved">public</span> <span class="reserved">class</span> <span class="type">LazyInit</span>
{
    <span class="reserved">public</span> <span class="reserved">string</span> <span class="property">Value</span> <span class="operator">=&gt;</span> <span class="reserved">field</span> <span class="operator">??=</span> <span class="method"><span class="static">ComputeValue</span></span>();
    <span class="reserved">private</span> <span class="reserved">static</span> <span class="reserved">string</span> <span class="method"><span class="static">ComputeValue</span></span>() { <span class="comment">/*...*/</span> }
}
</pre>
<p>この用途の場合、バッキング フィールドの型は <code>string?</code> であるべきなんですよね。</p>
<p>ところが、現状は「半自動プロパティから作られるバッキング フィールドの型はプロパティの型と同じ」という仕様なので、<code>string</code> になります。</p>
<p>参照型に関しては元から <a href="https://ufcpp.net/study/csharp/resource/nullablereferencetype/"><code>?</code> の有無はフロー解析</a>の差だけなのでそこまで問題ではないんですが、
値型の場合は困ります。</p>
<pre class="source" title="">
<span class="reserved">public</span> <span class="reserved">class</span> <span class="type">LazyInit</span>
{
    <span class="comment">// field も int なので、 ?? が意味をなさない。</span>
    <span class="reserved">public</span> <span class="reserved">int</span> <span class="property">Value</span> <span class="operator">=&gt;</span> <span class="reserved">field</span> <span class="operator">??=</span> <span class="method"><span class="static">ComputeValue</span></span>();
    <span class="reserved">private</span> <span class="reserved">static</span> <span class="reserved">int</span> <span class="method"><span class="static">ComputeValue</span></span>() { <span class="comment">/*...*/</span> }
}
</pre>
<p>これは、「<code>field</code> キーワード」路線でやる以上は解決しようがなさそうで、
それとは別に「<a href="https://github.com/dotnet/csharplang/issues/133">プロパティ スコープ フィールド</a>」(半自動プロパティと同じ要件に対する別案)が必要かもしれません。
とはいえ、とりあえず「<code>field</code> キーワード」優先で、
プロパティ スコープ フィールドはやるとしてもその後ということになっています。</p>
 ]]></description>
				<pubDate>Mon, 16 Jan 2023 22:15:04 +0900</pubDate>
			</item>
			<item>
				<title>【C# 12 候補】IEnumerable 向けリスト パターン</title>
				<link>http://ufcpp.net/blog/2023/1/list-pattern-enumerable/</link>
				<description><![CDATA[ <p>C# vNext (12 候補)紹介シリーズ。</p>
<p>今日はリスト パターンがらみ。</p>
<p>提案ドキュメント:</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/blob/main/proposals/list-patterns-enumerables.md">List patterns on enumerables</a> (この当時から、リスト パターンの文法には結構変更あり)</li>
<li><a href="https://github.com/dotnet/csharplang/blob/main/meetings/2022/LDM-2022-10-19.md">直近の Language Design Meeting ノート</a></li>
</ul>
<h2>C# 11 のときの話</h2>
<p><a href="https://ufcpp.net/study/csharp/cheatsheet/ap_ver11/#list">C# 11 でリスト パターン</a>が入りました。</p>
<p><code>is []</code> みたいに、<code>[]</code> を使って配列とか <code>List&lt;T&gt;</code> に対するパターン マッチを行います。
ただ、C# 11 時点では、</p>
<ul>
<li>countable: <code>Length</code> もしくは <code>Count</code> で長さを取れる</li>
<li>indexable: <code>[int index]</code> (整数引数のインデクサー)で i 番目の要素を取れる</li>
<li>sliceable: <code>[Range range]</code> や <code>Slice(int start, int length)</code> でスライスを作れる</li>
</ul>
<p>みたいな割と厳し目な条件を満たす型に対してだけリスト パターンを使えました。
以下の例ではリスト パターンとその展開結果をコメントに書いていますが、
見ての通り、 <code>Length</code> や <code>[]</code> を使ったコードと等価です。</p>
<pre class="source" title="リスト パターンの展開例">
<span class="reserved">using</span> <span class="reserved">static</span> System<span class="operator">.</span><span class="type"><span class="static">Console</span></span>;

<span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">m</span></span>(<span class="reserved">int</span>[] <span class="variable local">x</span>)
{
    <span class="method"><span class="static">WriteLine</span></span>(<span class="variable local">x</span> <span class="reserved">is</span> []); <span class="comment">// x.Length == 0</span>
    <span class="static"><span class="method">WriteLine</span></span>(<span class="variable local">x</span> <span class="reserved">is</span> [<span class="number">1</span>]); <span class="comment">// x.Length == 1 &amp;&amp; x[0] == 1</span>
    <span class="static"><span class="method">WriteLine</span></span>(<span class="variable local">x</span> <span class="reserved">is</span> [<span class="number">1</span>, ..]); <span class="comment">// x.Length &gt;= 1 &amp;&amp; x[0] == 1</span>
    <span class="static"><span class="method">WriteLine</span></span>(<span class="variable local">x</span> <span class="reserved">is</span> [<span class="reserved">_</span>, .. <span class="reserved">var</span> y]); <span class="comment">// y = x[1..]</span>
    <span class="static"><span class="method">WriteLine</span></span>(<span class="variable local">x</span> <span class="reserved">is</span> [<span class="reserved">_</span>, .. <span class="reserved">var</span> z, <span class="reserved">_</span>, <span class="reserved">_</span>]); <span class="comment">// y = x[1..^2]</span>
}
</pre>
<h2>対 IEnumerable</h2>
<p>提案当初(コミュニティ提案だったりします)では、
リスト パターンは <code>IEnumerable</code> に対しても使える提案がありました。
別にリジェクトされたわけでもないんですが、countable, indexable, sliceable に対するものと比べると課題が多いので「後回し」にされています。</p>
<p>まあ、元々提案にあったものなので、引き続き検討しようかという感じで C# vNext 候補です。
元々の提案では、何らかのヘルパー クラスを間に挟んで、
<code>x is [0, 1, ..]</code> みたいなコードを以下のような感じで展開することを考えています。</p>
<pre class="source" title="IEnumerable に対するリスト パターンの展開例">
<span class="reserved">var</span> <span class="variable">helper</span> <span class="operator">=</span> <span class="reserved">new</span> <span class="type">ListPatternHelper</span>(<span class="variable">x</span>, <span class="number">2</span>, <span class="number">0</span>);

<span class="variable">helper</span><span class="operator">.</span><span class="method">TryGetStartElement</span>(<span class="variable local">index</span>: <span class="number">0</span>, <span class="reserved">out</span> <span class="reserved">var</span> <span class="variable">element0</span>) <span class="operator">&amp;&amp;</span> <span class="variable">element0</span> <span class="reserved">is</span> <span class="number">0</span> <span class="operator">&amp;&amp;</span>
<span class="variable">helper</span><span class="operator">.</span><span class="method">TryGetStartElement</span>(<span class="number">1</span>, <span class="reserved">out</span> <span class="reserved">var</span> <span class="variable">element1</span>) <span class="operator">&amp;&amp;</span> <span class="variable">element1</span> <span class="reserved">is</span> <span class="number">1</span>
</pre>
<h2>課題</h2>
<p>リスト パターンを <code>IEnumerable</code> でも使えるようにしようとすると、スライスが絡むときが難しそうです。
例えば、 <code>x is [0, 1]</code> だとそんなに問題はなくて、
「最初の2個分 <code>MoveNext</code> → <code>Current</code> するだけ」になるんですが。
一方で <code>x is [.., 1]</code> だと、 LINQ でいうところの <code>Last</code> になるわけで、
LINQ でもそうなんですけども、無限シーケンスで困ります。</p>
<pre class="source" title="">
<span class="comment">// 普通、無限シーケンスは Take(有限の値) とかで一部分だけ取り出して使う。</span>
<span class="reserved">var</span> <span class="variable">x</span> <span class="operator">=</span> <span class="method"><span class="static">m</span></span>()<span class="operator">.</span><span class="method">Take</span>(<span class="number">100</span>);

<span class="comment">// 無限なものの Last があるわけなく、永久ループになる。まずい。</span>
<span class="reserved">var</span> <span class="variable">y</span> <span class="operator">=</span> <span class="static"><span class="method">m</span></span>()<span class="operator">.</span><span class="method">Last</span>();

<span class="reserved">static</span> <span class="type">IEnumerable</span>&lt;<span class="reserved">int</span>&gt; <span class="method"><span class="static">m</span></span>()
{
    <span class="reserved">var</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>;
    <span class="control">while</span> (<span class="reserved">true</span>) <span class="control">yield</span> <span class="control">return</span> <span class="variable">i</span><span class="operator">++</span>; <span class="comment">// whiel(true) なので永久に途切れない</span>
}
</pre>
<p>この辺りを中心に、<a href="https://github.com/dotnet/csharplang/blob/main/meetings/2022/LDM-2022-10-19.md">LDM</a>で検討:</p>
<h3>スライスの後ろにパターンがある場合</h3>
<p>前述のように <code>x is [.., 1, 2]</code> とかになっているパターンをどうするか:</p>
<ul>
<li>
展開結果がちょっと複雑
<ul>
<li>→ 手書きするよりはコンパイラーに頑張ってもらう方がマシ</li>
</ul>
</li>
<li>
無限シーケンスとかみたいに footgun (勢い余って自分の足を打ち抜いちゃいそうな道具)になりそう
<ul>
<li>→ 元から。LINQ もそうだし、なんだったら .NET Framework 1.0 の頃からこの手の footgun はある</li>
</ul>
</li>
<li>
LINQ よりもパフォーマンスが落ちる可能性
<ul>
<li>LINQ to Object の場合、内部的に <code>is IList</code> 分岐とかで「indexable ならそれ前提のコードを使う」みたいな最適化をしてる</li>
<li>この問題は大きいと思っている。「パターンを使うとパフォーマンスが悪くなる」という状況は避けたい</li>
<li><code>IEnumerable</code> 向けリスト パターンでもその手の最適化がかかるようにしないといけない</li>
</ul>
</li>
</ul>
<p>まあとりあえず、最初の実装としては <code>x is [1, 2, ..]</code> みたいな「スライスの前」だけを認めて、
<code>x is [.., 1, 2]</code> みたいな「スライスの後」は後々改めて検討するのでもいいかも見たいな雰囲気です。</p>
<p>「スライスの後」の方は、
結局は、「最初に紹介した <code>ListPatternHelper</code> みたいなヘルパー クラスの中で、LINQ と比べてパフォーマンス悪化させないような最適化がかかってほしい」ということになるんですが、「BCL チームと連携して作る」とのこと。</p>
<h2>.. 部分をキャプチャ</h2>
<p>リスト パターンでは、<code>x is [1, 2, ..var y]</code> みたいに書いて、<code>y = x[2..]</code> みたいなスライスをキャプチャすることもできます。
とうことで、「スライスをキャプチャ」は、「<a href="https://ufcpp.net/study/csharp/data/dataranges/#indexer">配列とかリストのスライス</a>」と密接に紐づいています。</p>
<p>で、このスライスなんですが、推奨としては「<code>Slice</code> メソッドの戻り値は元の型と同じにするべき」ということになっています。
配列であれば <code>x[i..j]</code> の結果も配列、
<code>List&lt;T&gt;</code> であれば <code>x[i..j]</code> の結果も <code>List&lt;T&gt;</code>、
<code>Span&lt;T&gt;</code> であれば <code>x[i..j]</code> の結果も <code>Span&lt;T&gt;</code> ということです。</p>
<p>(その結果、配列や <code>List&lt;T&gt;</code> に対して <code>[..]</code> を使うとコピーが発生してパフォーマンスはそんなによくないですが、「型が同じ」の方が驚きは少ないだろう、パフォーマンスが必要なら <code>Span</code> を使えばいいだろうということになっています。)</p>
<p>ところが、<code>IEnumerable</code> の場合、スライスを具体的に何の型にすればいいのかが決まらないので困ると。</p>
<p>これも結局、「よいヘルパー クラスができてから改めて考える」みたいな空気感で終わっています。</p>
 ]]></description>
				<pubDate>Sat, 14 Jan 2023 16:21:28 +0900</pubDate>
			</item>
			<item>
				<title>【C# 12 候補】ラムダ式のデフォルト引数と params 引数</title>
				<link>http://ufcpp.net/blog/2023/1/lambda-default/</link>
				<description><![CDATA[ <p>そろそろ、C# vNext 候補で上がってるものをちらほら紹介していこうかと。</p>
<p>今日は割かし確度高そうなものとして、ラムダ式がらみの話。
ラムダ式でもデフォルト引数と params への対応を考えているそうです。</p>
<p>提案ドキュメント:</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/blob/main/proposals/lambda-method-group-defaults.md">Optional and parameter array parameters for lambdas and method groups</a></li>
</ul>
<p>※追記: 後から気づきましたが、この機能は Visual Studio 17.5 Preview 2 (2022年12月中旬)の時点ですでに使えてたっぽいです。
(未確認。少なくとも Preview 3 (2023年1月中旬) では使えます。<a href="https://ufcpp.net/study/csharp/cheatsheet/langversionoption/#langversion">LangVersion</a> preview 必要。)</p>
<h2>C# 10 のときの話</h2>
<p><a href="https://ufcpp.net/study/csharp/cheatsheet/ap_ver10/#lambda-improvement">C# 10 のときにラムダ式の改善</a>がいくつか入りました。
以下のように、Web アプリがシンプルに書けるようになります。</p>
<pre class="source" title="C# 10 のラムダ式の改善">
<span class="reserved">var</span> <span class="variable">builder</span> <span class="operator">=</span> <span class="type">WebApplication</span><span class="operator">.</span><span class="static"><span class="method">CreateBuilder</span></span>(<span class="reserved">args</span>);
<span class="reserved">var</span> <span class="variable">app</span> <span class="operator">=</span> <span class="variable">builder</span><span class="operator">.</span><span class="method">Build</span>();

<span class="comment">// MapGet の引数は System.Delegate 型。</span>
<span class="comment">// Delegate に対してラムダ式が使える。</span>
<span class="comment">// 自然な型決定が働いて、この場合は Func&lt;string&gt; になる。</span>
<span class="variable">app</span><span class="operator">.</span><span class="method">MapGet</span>(<span class="string">&quot;/&quot;</span>, () <span class="operator">=&gt;</span> <span class="string">&quot;Hello World!&quot;</span>);

<span class="variable">app</span><span class="operator">.</span><span class="method">Run</span>();
</pre>
<p>この機能の延長で、</p>
<ul>
<li>ラムダ式の引数にデフォルト値を与えられるように</li>
<li>ラムダ式の引数を params にできるように</li>
</ul>
<p>の2つが追加で提案されています。</p>
<h2>これまでのラムダ式の引数</h2>
<p>C# 9 までの状態だと、
ラムダ式にデフォルト引数/params 引数が書けても役に立ちませんでした。</p>
<p>メソッドを使った例で説明すると、
以下のように、デフォルト引数/params 引数はデリゲート化する際に一切紛失します。</p>
<pre class="source" title="デフォルト引数/params 引数はデリゲート化すると紛失">
<span class="static"><span class="method">m</span></span>();

<span class="comment">// m() と呼べるのに、 Action には代入できない。</span>
<span class="type">Action</span> <span class="variable">a1</span> <span class="operator">=</span> <span class="static"><span class="error" title="CS0123"><span class="method">m</span></span></span>;

<span class="comment">// Action&lt;int, int[]&gt; には代入できるけど、</span>
<span class="type">Action</span>&lt;<span class="reserved">int</span>, <span class="reserved">int</span>[]&gt; <span class="variable">a2</span> <span class="operator">=</span> <span class="method"><span class="static">m</span></span>;

<span class="comment">// Action&lt;int, int[]&gt; 越しには () では呼べない。</span>
<span class="variable"><span class="error" title="CS7036">a2</span></span>();

<span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">m</span></span>(<span class="reserved">int</span> <span class="variable local">x</span> <span class="operator">=</span> <span class="number">1</span>, <span class="reserved">params</span> <span class="reserved">int</span>[] <span class="variable local">y</span>) { }
</pre>
<p>デリゲートに代入して使うことが前提のラムダ式では、
そもそもデフォルト引数/params 引数を書けても全く役に立たないということになります。</p>
<p>そんな中、<a href="https://ufcpp.net/study/csharp/functional/fun_localfunctions/#lambda-csharp10">C# 10 ではラムダ式への属性指定ができるようになった</a>わけですが、静的な型情報からは消えるという意味ではこの属性も同様だったりします。
ただ、属性は、静的な情報としては紛失したとしても、
リフレクションを使って属性を取る前提であれば意味があります。</p>
<pre class="source" title="リフレクションで取る情報としては意味があり、ラムダ式に属性を付ける意義はある">
<span class="reserved">using</span> System<span class="operator">.</span>Reflection;
<span class="reserved">using</span> Microsoft<span class="operator">.</span>AspNetCore<span class="operator">.</span>Mvc;

<span class="comment">// f の型 (Func&lt;string, string&gt;) に FromBody 属性が反映されるわけではな。</span>
<span class="type">Func</span>&lt;<span class="reserved">string</span>, <span class="reserved">string</span>&gt; <span class="variable">f</span> <span class="operator">=</span> ([<span class="type">FromBody</span>] <span class="reserved">string</span> <span class="variable local">name</span>) <span class="operator">=&gt;</span> <span class="string">&quot;Hello World!&quot;</span>;

<span class="comment">// リフレクションで MethodInfo から引数や戻り値を取れば、それについてる属性を調べられる。</span>
<span class="reserved">var</span> <span class="variable">p</span> <span class="operator">=</span> <span class="variable">f</span><span class="operator">.</span><span class="property">Method</span><span class="operator">.</span><span class="method">GetParameters</span>()[<span class="number">0</span>];

<span class="control">foreach</span> (<span class="reserved">var</span> <span class="variable">a</span> <span class="control">in</span> <span class="variable">p</span><span class="operator">.</span><span class="method">GetCustomAttributes</span>())
{
    <span class="comment">// FromBodyAttribute</span>
    <span class="type"><span class="static">Console</span></span><span class="operator">.</span><span class="static"><span class="method">WriteLine</span></span>(<span class="variable">a</span><span class="operator">.</span><span class="method">GetType</span>()<span class="operator">.</span><span class="property">Name</span>);
}

</pre>
<p>「リフレクションで」というのであれば、
デフォルト引数と params 引数も同様のはずです。</p>
<pre class="source" title="リフレクションでデフォルト引数/params 引数を調べる例">
<span class="reserved">using</span> System<span class="operator">.</span>Reflection;
<span class="reserved">using</span> System<span class="operator">.</span>Runtime<span class="operator">.</span>InteropServices;

<span class="type">Delegate</span> <span class="variable">f</span> <span class="operator">=</span> <span class="type">C</span><span class="operator">.</span><span class="static"><span class="method">M</span></span>;

<span class="control">foreach</span> (<span class="reserved">var</span> <span class="variable">p</span> <span class="control">in</span> <span class="variable">f</span><span class="operator">.</span><span class="property">Method</span><span class="operator">.</span><span class="method">GetParameters</span>())
{
    <span class="type"><span class="static">Console</span></span><span class="operator">.</span><span class="static"><span class="method">WriteLine</span></span>(<span class="variable">p</span><span class="operator">.</span><span class="property">Name</span>);
    <span class="static"><span class="type">Console</span></span><span class="operator">.</span><span class="static"><span class="method">WriteLine</span></span>(<span class="variable">p</span><span class="operator">.</span><span class="method">GetCustomAttribute</span>&lt;<span class="type">OptionalAttribute</span>&gt;());   <span class="comment">// x のときに取れる</span>
    <span class="static"><span class="type">Console</span></span><span class="operator">.</span><span class="method"><span class="static">WriteLine</span></span>(<span class="variable">p</span><span class="operator">.</span><span class="method">GetCustomAttribute</span>&lt;<span class="type">ParamArrayAttribute</span>&gt;()); <span class="comment">// y のときに取れる</span>
}

<span class="reserved">class</span> <span class="type">C</span>
{
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">M</span></span>(<span class="reserved">int</span> <span class="variable local">x</span> <span class="operator">=</span> <span class="number">1</span>, <span class="reserved">params</span> <span class="reserved">int</span>[] <span class="variable local">y</span>) { }
}
</pre>
<h2>ラムダ式のデフォルト引数/params 引数を認める</h2>
<p>ということで、C# 10 の時に属性を認めたのと同じく、
ラムダ式のデフォルト引数/params 引数を認めたいという話になりました。</p>
<p>そこから、もう1歩進めた提案もあって、
自然な型決定で、デフォルト引数/params 引数付きのデリゲートを作るという話もあります。</p>
<pre class="source" title="ラムダ式のデフォルト引数/params 引数">
<span class="reserved">static</span> <span class="reserved">void</span> <span class="static"><span class="method">m</span></span>(<span class="reserved">int</span> <span class="variable local">x</span> <span class="operator">=</span> <span class="number">1</span>, <span class="reserved">params</span> <span class="reserved">int</span>[] <span class="variable local">y</span>) { }

<span class="comment">// 今までだったら Action&lt;int, int[]&gt; になってた。</span>
<span class="comment">// これを、 delegate void Anonymous(int x = 1, params int[] y) で生成したい。</span>
<span class="reserved">var</span> <span class="variable">f</span> <span class="operator">=</span> <span class="static"><span class="method">m</span></span>;

<span class="comment">// 今まででも、↓なら呼べる。</span>
<span class="variable">f</span>(<span class="number">1</span>, <span class="reserved">new</span>[] { <span class="number">2</span> });

<span class="method"><span class="static">m</span></span>(<span class="number">1</span>, <span class="number">2</span>);
<span class="method"><span class="static">m</span></span>(<span class="variable local">x</span>: <span class="number">1</span>);
<span class="method"><span class="static">m</span></span>(<span class="variable local">y</span>: <span class="number">2</span>);

<span class="comment">// ↓はこれまではダメで、C# 12 でできるようにしたい。</span>
<span class="variable">f</span>(<span class="number">1</span>, <span class="number"><span class="error" title="CS1503">2</span></span>);
<span class="variable">f</span>(<span class="error" title="CS1746">x</span>: <span class="number">1</span>);
<span class="variable">f</span>(<span class="error" title="CS1746">y</span>: <span class="number">2</span>);

<span class="type"><span class="static">Console</span></span><span class="operator">.</span><span class="static"><span class="method">WriteLine</span></span>(<span class="variable">f</span><span class="operator">.</span><span class="method">GetType</span>());
</pre>
<p>割かし実装も進んでいるはずなので、これは近いうちにプレビューが来ると思われます。</p>
 ]]></description>
				<pubDate>Wed, 11 Jan 2023 22:10:34 +0900</pubDate>
			</item>
			<item>
				<title>JSON とかの中身確認ツール</title>
				<link>http://ufcpp.net/blog/2022/12/binarytool/</link>
				<description><![CDATA[ <p>今日は、「主に自分が使う用ツールを Blazor WebAssembly で作って Static Web Apps に置いたよ」系の話を一応ブログ化。</p>
<ul>
<li><a href="https://github.com/ufcpp/StaticWebApps/tree/main/BlazorWasm/BinaryTool">ソースコード</a></li>
<li><a href="https://ambitious-plant-0ea3d5100.2.azurestaticapps.net/">Static Web App</a></li>
</ul>
<div>
<iframe width="1409" height="794" src="https://www.youtube.com/embed/_oi53peGbnw" title="Binary Tool" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div>
<p>よくある「JSON とかのデータの中身を確認するツール」です。</p>
<p>しばらく、JSON と MessagePack の読み書きをするコードを書いてて、
デバッグがしんどくなって作ったのがこのツール。</p>
<p>いろんな形式を同時に扱うことがニッチ需要なのであんまり自分の需要にあったツールがなかったんですよね。なら、まあ、自作。</p>
<p><a href="https://youtu.be/_f6UA3Vs3Kc?t=5935">こないだの C# 配信</a> で、UTF-8 とか MessagePack バイナリとかを手打ちで入力してたら <a href="https://twitter.com/xin9le">@xin9le</a>, <a href="https://twitter.com/okazuki">@okazuki</a> 両氏にドン引きされたやつ。</p>
<h2>バイナリ読み込み (Parser)</h2>
<p>UTF-8 を <code>ReadOnlySpan&lt;byte&gt;</code> のまま扱ってて、
ブレイクポイントを仕掛けてデバッガーで中身を覗くとかやってると、
「97, 98, 99」みたいな数値列しか見れないことが多く。</p>
<p>デバッガーからコピペするとその数値が <code>&quot;97, 98, 99&quot;</code> みたいな文字列としてコピーされてしまったりするので、それをバイナリに戻す処理を入れています。</p>
<p>せっかくなので、</p>
<ul>
<li>10進数コンマ区切り <code>97,98,99</code></li>
<li>10進数スペース区切り <code>97 98 99</code></li>
<li>16進数コンマ区切り <code>61,62,63</code></li>
<li>16進数スペース区切り <code>61 62 63</code></li>
<li>16進数区切りなし <code>616263</code></li>
<li>UTF-8 文字列 <code>abc</code></li>
<li>Base64エンコードされた文字列 <code>YWJj</code></li>
<li>C# 風 <code>0b0110_0001, 0x62, 99</code></li>
<li>上記の中からある程度自動判定</li>
</ul>
<p>とかを読めるようにしています。</p>
<h2>文字列化 (Formatter)</h2>
<p>読み込んだバイナリを表示する形式も選択式に。
UTF-8 だったらそれをデコードした文字列を見たいことがほとんどですし、
バイナリなら16進数を並べたもの辺りが使い勝手がいいと思います。</p>
<p>その他、「デバッグで使いたいけども、いちいちファイルとかから読むの面倒で、C# コード中に生で埋め込みたい」みたいな時のために、<code>new byte[] { 0x61, 0x62, 0x63 }</code> みたいな書式にする機能も持たせています。</p>
<h2>デシリアライズ結果の可視化 (DOM)</h2>
<p>用途が「JSON とかの中身確認」だったのでその機能を持っています。</p>
<p><code>json
{&quot;abc&quot;:0,&quot;ABC&quot;:[null,false,true]}</code></p>
<p>みたいなデータを、</p>
<ul>
<li>abc: 0</li>
<li>
ABC:
<ul>
<li>0: null</li>
<li>1: false</li>
<li>2: true</li>
</ul>
</li>
</ul>
<p>みたいな <code>&lt;li&gt;</code> タグにして表示します。</p>
<p>とりあえず JSON と MessagePack に対応。
Protocol Buffers と YAML くらいには対応してもいいかも。</p>
<p>自動判定というか、「エラーなくデシリアライズできた最初の1個を選択」みたいな処理も入れています。
(いかにも「自分用ツール」らしく、エラー処理が甘いんで結構フリーズするんですが…)</p>
<h2>再シリアライズ (Writer)</h2>
<p>再度シリアライズして、改めて Formatter にかける処理も入っています。</p>
<p>「MessagePack なバイナリを、JSON な UTF-8 で表示」みたいなことやると結構デバッグがはかどりまして。</p>
 ]]></description>
				<pubDate>Fri, 30 Dec 2022 16:34:58 +0900</pubDate>
			</item>
			<item>
				<title>必ず、かの邪知暴虐の T4 を除かねばならぬと決意した</title>
				<link>http://ufcpp.net/blog/2022/12/no-more-t4/</link>
				<description><![CDATA[ <p>個人的に、前々から「<a href="https://learn.microsoft.com/ja-jp/visualstudio/modeling/code-generation-and-t4-text-templates">T4</a> は将来性が見えなさ過ぎてもう使うのやめたい」と言い続けていたわけですが、
最近ようやく自分が保守している T4 を全部別の手段で書き換えたので、
今日はそれの話。</p>
<h2><a id="t4">T4 (Text Template Transformation Toolkit)</a></h2>
<p>テキスト テンプレートというと、ひな形的なテキストを簡易な文法で生成するようなものです。</p>
<p>例えば、</p>
<pre class="source">
public static bool TryParse(this string s, out {{T}} x) =&gt; {{T}}.TryParse(s, out x);
</pre>
<p>みたいな文字列の、<code>{{T}}</code> のところに <code>bool</code>, <code>byte</code>, <code>int</code>, <code>double</code> を与えて、</p>
<pre class="source">
public static bool TryParse(this string s, out bool x) =&gt; bool.TryParse(s, out x);
public static bool TryParse(this string s, out byte x) =&gt; byte.TryParse(s, out x);
public static bool TryParse(this string s, out int x) =&gt; int.TryParse(s, out x);
public static bool TryParse(this string s, out double x) =&gt; double.TryParse(s, out x);
</pre>
<p>とかを生成したいことがたまにあります。</p>
<p>今書いたみたいに4種・4行程度なら手書きでも全然かまわないんですが、
<code>sbyte</code>, <code>short</code>, <code>ushort</code>, ... と増やしていくとテキスト テンプレートに頼りたくなります。</p>
<p>C# でテキスト テンプレートというと、
<a href="https://learn.microsoft.com/ja-jp/visualstudio/modeling/code-generation-and-t4-text-templates">T4</a> (Text Template Transfomration Toolkit)が有名ではあります。</p>
<p>T4 を使うと、上記の <code>Parse</code> は以下のように書けます。</p>
<pre class="source">
&lt;#
var types = new[] { "bool", "byte", "int", "double" };

foreach (var t in types)
{
#&gt;
    public static bool TryParse(string s, out &lt;#= t #&gt; x) =&gt; &lt;#= t #&gt;.TryParse(s, out x);
&lt;#
}
#&gt;
</pre>
<h2><a id="t4-now">T4 の今</a></h2>
<p>元々 Entity Framework が内部で使っていたツールを公にしてしまったものですよね、確か。
今となっては本当に「してしまった」みたいな言い方にした方がいいと僕は本気で思っているんですけども。
どうも、.NET の中の人も、Entity Framework チーム以外あんまり乗り気で使っている風には見えず。
真面目に使う気があるのなら今時もうちょっと改良されててもよさそうなものなのに、
ちょっと塩漬け感があります。</p>
<p>例えば以下のような問題あり。</p>
<ul>
<li>
Visual Studio でしか動かず、しかも、手作業で .tt ファイルを開いて保存したタイミングでしかテキスト生成が走らない
<ul>
<li>今時あれば、<a href="https://ufcpp.net/study/csharp/misc/analyzer-generator/">Roslyn Source Generator</a> 化すれば dotnet build でテキスト生成できるのにやってない</li>
<li>Git とかで管理するなら、生成結果のテキストもコミットする運用になる</li>
</ul>
</li>
<li>
Visual Studio 自体の表示言語に生成結果が依存する
<ul>
<li>編集して保存した人の表示言語によって生成結果が変わる</li>
<li>無駄に差分が出て、Git とかの差分が悲惨</li>
</ul>
</li>
<li>
csproj 内にいろいろとゴミが残る
<ul>
<li><a href="https://github.com/ufcpp/UfcppSample/blob/master/Demo/2022/NoMoreT4/ClassLibrary1/ClassLibrary1.csproj#L11"><code>&lt;Service Include=&quot;{508349b6-6b84-4df5-91f0-309beebad82d}&quot; /&gt;</code></a> とか</li>
<li><a href="https://github.com/ufcpp/UfcppSample/blob/master/Demo/2022/NoMoreT4/ClassLibrary1/ClassLibrary1.csproj#L10"><code>System.CodeDom</code> の参照</a>とか</li>
<li><a href="https://github.com/ufcpp/UfcppSample/blob/master/Demo/2022/NoMoreT4/ClassLibrary1/ClassLibrary1.csproj#L14-L24"><code>&lt;None Update=&quot;T4Generator.tt&quot;&gt;</code> みたいなの</a>とか</li>
</ul>
</li>
</ul>
<p>さらに、中間的に作られる「テキスト生成するための generator クラス」がまたかなり悲惨だったりします。</p>
<p>一例: <a href="https://github.com/ufcpp/UfcppSample/blob/master/Demo/2022/NoMoreT4/ClassLibrary1/T4Generator.tt">元 tt ファイル</a> → <a href="https://github.com/ufcpp/UfcppSample/blob/master/Demo/2022/NoMoreT4/ClassLibrary1/T4Generator.cs">生成される generator クラス</a></p>
<p>例えば、元 tt ファイルで <code>&lt;#= t #&gt;</code> みたいになっているところは
generator 内では <code>ToStringWithCulture(t)</code> みたいに展開されるんですが、
この <code>ToStringWithCulture</code> の中身は以下のようになっています。</p>
<pre class="source" title="T4 が生成する ToStringWithCulture メソッド">
<span class="reserved">public</span> <span class="reserved">string</span> <span class="method">ToStringWithCulture</span>(<span class="reserved">object</span> <span class="variable local">objectToConvert</span>)
{
    <span class="control">if</span> ((<span class="variable local">objectToConvert</span> <span class="operator">==</span> <span class="reserved">null</span>))
    {
        <span class="control">throw</span> <span class="reserved">new</span> <span class="reserved">global</span><span class="operator">::</span>System<span class="operator">.</span><span class="type">ArgumentNullException</span>(<span class="string">&quot;objectToConvert&quot;</span>);
    }
    System<span class="operator">.</span><span class="type">Type</span> <span class="variable">t</span> <span class="operator">=</span> <span class="variable local">objectToConvert</span><span class="operator">.</span><span class="method">GetType</span>();
    System<span class="operator">.</span>Reflection<span class="operator">.</span><span class="type">MethodInfo</span> <span class="variable">method</span> <span class="operator">=</span> <span class="variable">t</span><span class="operator">.</span><span class="method">GetMethod</span>(<span class="string">&quot;ToString&quot;</span>, <span class="reserved">new</span> System<span class="operator">.</span><span class="type">Type</span>[] {
                <span class="reserved">typeof</span>(System<span class="operator">.</span><span class="type">IFormatProvider</span>)});
    <span class="control">if</span> ((<span class="variable">method</span> == <span class="reserved">null</span>))
    {
        <span class="control">return</span> <span class="variable local">objectToConvert</span><span class="operator">.</span><span class="method">ToString</span>();
    }
    <span class="control">else</span>
    {
        <span class="control">return</span> ((<span class="reserved">string</span>)(<span class="variable">method</span><span class="operator">.</span><span class="method">Invoke</span>(<span class="variable local">objectToConvert</span>, <span class="reserved">new</span> <span class="reserved">object</span>[] {
                    <span class="reserved">this</span><span class="operator">.</span>formatProviderField })));
    }
}
</pre>
<p>任意の型に対してカルチャー(<code>IFromatProvider</code>)指定するためだけにリフレクション。
しかも、<code>MethodInfo</code> のキャッシュもせず、毎回律義に <code>GetMethod</code>。
さらに、常に <code>object</code> 引数で受け取っているので、<code>int</code> (おそらく最多で渡される)とかだと都度<a href="https://ufcpp.net/study/csharp/RmBoxing.html">ボックス化</a>。</p>
<p>T4 が作られた当初ならしょうがなかったのかもしれないですけどねぇ。
今なら、単に <a href="https://learn.microsoft.com/ja-jp/dotnet/api/system.string.create#system-string-create(system-iformatprovider-system-runtime-compilerservices-defaultinterpolatedstringhandler@)"><code>string.Create</code></a>とか<a href="https://learn.microsoft.com/ja-jp/dotnet/api/system.text.stringbuilder.append#system-text-stringbuilder-append(system-iformatprovider-system-text-stringbuilder-appendinterpolatedstringhandler@)">StringBuilder.Append</a>でカルチャー指定もできるのに。
というか、むしろ、<a href="https://ufcpp.net/blog/2021/8/invariantculture/">カルチャー依存やめろ、誰得</a>。</p>
<p>ちなみに、T4 生成の generator クラスと、自前で<a href="https://ufcpp.net/study/csharp/st_string.html#string-interpolation">文字列補間</a>を使って書いた generator でベンチマークを比べると、一例として以下のテーブルくらいの差が出ます。</p>
<table>
<thead>
<tr>
	<th>Method</th>
	<th align="right">Mean</th>
	<th align="right">Error</th>
	<th align="right">StdDev</th>
</tr>
</thead>
<tbody>
<tr>
	<td>T4</td>
	<td align="right">19,247.7 ns</td>
	<td align="right">74.46 ns</td>
	<td align="right">69.65 ns</td>
</tr>
<tr>
	<td>Interpolation</td>
	<td align="right">330.6 ns</td>
	<td align="right">5.94 ns</td>
	<td align="right">5.55 ns</td>
</tr>
</tbody>
</table>
<p>2桁差。
2倍ではなく、<em>2桁</em>。
マイクロ秒とナノ秒の補助単位違いレベル。</p>
<p>という感じで、T4、
さすがに中身がグダグダすぎ、かつ、近代化される気配がまるっきり皆無でつらいかなと思います。
テンプレートの文法とかはそこまでおかしくもないんですけどね。
さすがにもう使っていられないかなと…</p>
<h2><a id="no-more-t4">脱 T4</a></h2>
<p>ということで脱 T4 の話。</p>
<p>ただ、T4 の用途は2種類ありまして、それぞれ代替手段が異なります。</p>
<ul>
<li>TextTemplatingFilePreprocessor: 上記でいう「generator を作る」ところまでやるモード</li>
<li>TextTemplatingFileGenerator: さらにその generator を実行して、最終結果を直接生成するモード</li>
</ul>
<h3><a id="file-preprocessor">TextTemplatingFilePreprocessor</a></h3>
<p>「generator を作るところまで」の方。</p>
<p>TextTemplatingFilePreprocessor な T4 はもう本当に存在意義がないですね。
先ほどすでに「文字列補間で自前で」とかやっていますが、
文字列補間で十分です。</p>
<p>特に、<a href="https://ufcpp.net/study/csharp/st_string.html#csharp10-improvement">C# 10 で文字列補間のパフォーマンスが劇的に向上</a>していますし、
C# 11 で入った<a href="https://ufcpp.net/study/csharp/st_string.html?p=2#raw-string">生文字列リテラル</a>によってテンプレートも書きやすくなっています。
本校冒頭で書いたテンプレートなら、普通に以下のように書けます。</p>
<pre class="source" title="文字列補間でテンプレート">
<span class="reserved">using</span> System<span class="operator">.</span>Text;

<span class="reserved">var</span> <span class="variable">s</span> <span class="operator">=</span> <span class="reserved">new</span> <span class="type">StringBuilder</span>();

<span class="control">foreach</span> (<span class="reserved">var</span> <span class="variable">t</span> <span class="control">in</span> <span class="reserved">new</span>[] { <span class="string">&quot;bool&quot;</span>, <span class="string">&quot;byte&quot;</span>, <span class="string">&quot;int&quot;</span>, <span class="string">&quot;double&quot;</span> })
{
    <span class="variable">s</span><span class="operator">.</span><span class="method">Append</span>(<span class="string">$$&quot;&quot;&quot;
</span><span class="string">            public static bool TryParse(string s, out </span>{{<span class="variable">t</span>}}<span class="string"> x) =&gt; </span>{{<span class="variable">t</span>}}<span class="string">.TryParse(s, out x);
</span><span class="string">
        &quot;&quot;&quot;</span>);
}
</pre>
<p>(カルチャー指定が必要なら <code>Append</code> メソッドの第1引数を追加。)</p>
<p>テキスト テンプレートとしては結構冗長ですけども、まあ、許容範囲で、
「素の C# だけで書けてる」ということを考慮すると十分満足の行くコードじゃないかと思います。</p>
<p>T4 からの移行も割かし簡単で、
<a href="https://gist.github.com/ufcpp/2262fe3f607974b68b849b5b47a4dc32">こんな感じのコード</a>で置換を掛けるだけで行けます。</p>
<ul>
<li><code>&lt;#=</code> ～ <code>#&gt;</code> を、<code>{{</code> ～ <code>}}</code> に置換</li>
<li><code>#&gt;</code> を <code>s.Append($$&quot;&quot;&quot;</code> に置換</li>
<li><code>&lt;#</code> を <code>&quot;&quot;&quot;);</code> に置換</li>
</ul>
<p>(これだと不足もあるんですが、あとは手での書き換えでもなんとかなるレベル。)</p>
<h3><a id="file-generator">TextTemplatingFileGenerator</a></h3>
<p>「generator を実行までして最終結果を直接得る」の方。</p>
<p>こっちはさすがに素の C# ではできないんですが。
ビルド時に何かしらのテキストを生成するものというと、最近だと Roslyn Source Generator です。</p>
<p>T4 も、テンプレートの文法自体に不満はそこまでないので、Source Generator 実装に置き換わっていたらそれを普通に使うんですけどね…
ここ数年定期的に「誰か T4 を Source Generator 実装しなおしてないかな」とか検索したりしてたんですが…
いないですね。一向に。</p>
<p>そして、「ないので自分で作ろう」ってなったときに、なかなかきれいな T4 エンジン ライブラリが見つからず。
「だったらもっと楽に使えそうな別のテンプレート エンジンを使いたい」となりまして。
結局、Source Generator で一番使いやすそうだったのが scriban でした。</p>
<ul>
<li><a href="https://github.com/scriban/scriban">scriban</a></li>
</ul>
<p>ということで作ったのがこれです:</p>
<ul>
<li><a href="https://github.com/ufcpp/ScribanSourceGenerator">ScribanSourceGenerator</a></li>
<li><a href="https://github.com/ufcpp/UfcppSample/tree/master/Demo/2022/NoMoreT4/FileGenerator">利用例</a></li>
</ul>
<p>例えば以下のような拡張子 .scriban のファイルを置くか、</p>
<pre class="source">
static class Extensions
{
{{
for $t in ["bool","byte","int","double"]
~}}
    public static bool TryParse(this string s, out {{$t}} x) =&gt; {{$t}}.TryParse(s, out x);
{{ end }}
}
</pre>
<p>以下のようにクラスに属性を付けてコード生成できます。</p>
<pre class="source" title="">
<span class="reserved">namespace</span> FileGenerator;

[ScribanSourceGeneretor<span class="operator">.</span><span class="type">ClassMember</span>(<span class="string">&quot;&quot;&quot;
    {{
    for $t in [&quot;bool&quot;,&quot;byte&quot;,&quot;int&quot;,&quot;double&quot;]
    ~}}
        public static bool TryParse(this string s, out {{$t}} x) =&gt; {{$t}}.TryParse(s, out x);
    {{ end }}
    &quot;&quot;&quot;</span>)]
<span class="reserved">internal</span> <span class="reserved">static</span> <span class="reserved">partial</span> <span class="reserved">class</span> <span class="type"><span class="static">Extensions</span></span>
{
}
</pre> ]]></description>
				<pubDate>Tue, 20 Dec 2022 22:39:14 +0900</pubDate>
			</item>
			<item>
				<title>Unsafe クラスの敗北 (関数ポインター)</title>
				<link>http://ufcpp.net/blog/2022/12/unsafer-unsafe/</link>
				<description><![CDATA[ <p><a href="https://gist.github.com/ufcpp">Gist</a> に書き捨ててたコードの供養ブログ シリーズ、
今日のは特に人を選ぶやつ。</p>
<p>今日は C# 9 で入った <a href="https://ufcpp.net/study/csharp/cheatsheet/ap_ver9#function-pointer">関数ポインター</a> がらみの話です。</p>
<h2><a id="unsafe-class">Unsafe クラス</a></h2>
<p>C# の unsafe 機能、例えばポインターとかは、なかなか制限がきついです。
そのため、「実は .NET の型システム的にはできる」というものでも、
C# で書くことはできないことが結構あります。</p>
<p>それに対して、
.NET Core 以降、
<a href="https://learn.microsoft.com/ja-jp/dotnet/api/system.runtime.compilerservices.unsafe?view=net-7.0"><code>Unsafe</code></a> (<code>System.Runtime.CompilerServices</code> 名前空間)とかいう名前からして unsafe なクラスがあって、
内部的に IL を使ったり、
runtime intrinsics (JIT コンパイラーの特別扱い)で実装したりして、
元々 C# では書けなかったようなコードを、普通の C# で書けるようにしました。</p>
<p>この <code>Unsafe</code> クラスは、
<a href="https://ufcpp.net/study/csharp/sp_unsafe.html">unsafe コンテキスト</a>なしで、
普通の unsafe コードよりもよっぽど unsafe なことができちゃうという意味で良くも悪くも凶悪です。</p>
<p>ということで、皆様ご存じの通り<sup><a href="#as-you-all-known">※</a></sup>、
<code>Unsafe</code> クラスを使えば C# でも C++ 的な遊びがいろいろと楽しめます。</p>
<pre class="source" title="Unsafe.As">
<span class="reserved">using</span> System<span class="operator">.</span>Runtime<span class="operator">.</span>CompilerServices;

<span class="reserved">var</span> <span class="variable">a</span> <span class="operator">=</span> <span class="reserved">new</span> <span class="type struct">A</span>(<span class="number">123</span>);

<span class="comment">// readonly struct なので、↓はエラー。</span>
<span class="comment">//a.Value = 999;</span>

<span class="comment">// Unsafe.As を使えば、</span>
<span class="comment">// C++ でいう reinterpret_cast 的に何でもかんでも変換可能。</span>
<span class="comment">// (メモリレイアウトが想定通りかは利用者の自己責任。)</span>
<span class="reserved">ref</span> <span class="reserved">var</span> <span class="variable">x</span> <span class="operator">=</span> <span class="reserved">ref</span> <span class="static"><span class="type">Unsafe</span></span><span class="operator">.</span><span class="method"><span class="static">As</span></span>&lt;<span class="type struct">A</span>, <span class="reserved">int</span>&gt;(<span class="reserved">ref</span> <span class="variable">a</span>);
<span class="variable">x</span> <span class="operator">=</span> <span class="number">999</span>;

<span class="comment">// a.Value が 999 に書き変わってる。</span>
<span class="comment">// A { Value = 999 }</span>
<span class="static"><span class="type">Console</span></span><span class="operator">.</span><span class="method"><span class="static">WriteLine</span></span>(<span class="variable">a</span>);

<span class="reserved">readonly</span> <span class="reserved">record</span> <span class="reserved">struct</span> <span class="type struct">A</span>(<span class="reserved">int</span> <span class="variable local">Value</span>);
</pre>
<p><sup><a id="as-you-all-known">※</a></sup>どの方面に向かって「皆」と言っているのかは不明。</p>
<p><code>Unsafe</code> クラスを使ったこの手の処理、
誤用すると盛大にクラッシュさせれるくらい安全性皆無になるので利用には注意が必要ですが、
パフォーマンス改善につながることが多くて、
一部界隈では結構多用されます。</p>
<h2><a id="ref-struct">ref struct の制限</a></h2>
<p>ところが、<code>Unsafe</code> クラスでもできないことがありまして。
というか、<code>Unsafe</code> クラスはおろか、現状では<a href="https://ufcpp.net/study/csharp/sp_unsafe.html#pointer">ポインター</a>を使っても解決できないものがありまして。</p>
<p>というのも、<a href="https://ufcpp.net/study/csharp/resource/refstruct/">ref struct</a>はジェネリック型引数にもできないし、ポインターにもできません。</p>
<p>なので、先ほどと同じノリで ref struct に対して <code>Unsafe.As</code> (とか、それ相当の unsafe コード)を書こうとしてもうまくいきません。</p>
<pre class="source" title="Span には Unsafe.As が使えない">
<span class="reserved">using</span> System<span class="operator">.</span>Runtime<span class="operator">.</span>CompilerServices;

<span class="reserved">var</span> <span class="variable">span</span> <span class="operator">=</span> (<span class="reserved">stackalloc</span> <span class="reserved">int</span>[] { <span class="number">0xDE</span>, <span class="number">0xAD</span>, <span class="number">0xBE</span>, <span class="number">0xEF</span> });
<span class="reserved">var</span> <span class="variable">a</span> <span class="operator">=</span> <span class="reserved">new</span> <span class="type struct">A</span>(<span class="variable">span</span>);

<span class="reserved">var</span> <span class="variable">spanFromA</span> <span class="operator">=</span> <span class="type"><span class="static">Unsafe</span></span><span class="operator">.</span><span class="error" title="CS0306"><span class="error" title="CS0306"><span class="static"><span class="method">As</span></span>&lt;<span class="type struct">A</span>, <span class="type struct">Span</span>&lt;<span class="reserved">int</span>&gt;&gt;</span></span>(<span class="reserved">ref</span> <span class="variable">a</span>);

<span class="reserved">ref</span> <span class="reserved">struct</span> <span class="type struct">A</span>
{
    <span class="comment">// private なので通常、この _span を取り出す方法ない。</span>
    <span class="comment">// なんならリフレクションを使っても無理。</span>
    <span class="reserved">private</span> <span class="type struct">Span</span>&lt;<span class="reserved">int</span>&gt; <span class="field">_span</span>;
    <span class="reserved">public</span> <span class="type struct">A</span>(<span class="type struct">Span</span>&lt;<span class="reserved">int</span>&gt; <span class="variable local">span</span>) <span class="operator">=&gt;</span> <span class="field">_span</span> <span class="operator">=</span> <span class="variable local">span</span>; 
}
</pre>
<h2><a id="function-pointer">関数ポインター</a></h2>
<p>そんな時には<a href="https://ufcpp.net/study/csharp/cheatsheet/ap_ver9#function-pointer">関数ポインター</a>を使えばいいらしいですよ。</p>
<p>C# 9 で入った関数ポインター、
<code>delegate*&lt;T1, T2, ...&gt;</code> みたいな、ジェネリクスに似た記法を使う割に、
この <code>T1</code> とか <code>T2</code> のところには <code>ref</code> も書けるし ref struct も書けるしで、相当自由みたいです。</p>
<p>要するに、<code>Span&lt;T&gt;</code> (ref struct)に対して、
<code>Span&lt;T&gt;*</code> (直接その型のポインター)は書けないし、
<code>Unsafe.As&lt;A, Span&lt;T&gt;&gt;</code> (型引数)も書けませんが、
<code>delegate*&lt;ref A, ref Span&lt;T&gt;&gt;</code> (関数ポインターの引数)なら書けます。</p>
<p>これを使えば、以下のように、ref struct に対しても <code>Unsafe.As</code> 的なことができるようになったりします。</p>
<pre class="source" title="関数ポインターは制限がゆるくて、現状これでしかできないことができちゃう">
<span class="reserved">var</span> <span class="variable">span</span> <span class="operator">=</span> (<span class="reserved">stackalloc</span> <span class="reserved">int</span>[] { <span class="number">0xDE</span>, <span class="number">0xAD</span>, <span class="number">0xBE</span>, <span class="number">0xEF</span> });
<span class="reserved">var</span> <span class="variable">a</span> <span class="operator">=</span> <span class="reserved">new</span> <span class="type struct">A</span>(<span class="variable">span</span>);

<span class="reserved">unsafe</span>
{
    <span class="comment">// function pointer の引数なら ref RefStruct も行ける。</span>
    <span class="reserved">var</span> <span class="variable">f</span> <span class="operator">=</span> (<span class="reserved">delegate</span><span class="operator">*</span>&lt;<span class="reserved">ref</span> <span class="type struct">A</span>, <span class="reserved">ref</span> <span class="type struct">Span</span>&lt;<span class="reserved">int</span>&gt;&gt;)(<span class="reserved">delegate</span><span class="operator">*</span>&lt;<span class="reserved">nint</span>, <span class="reserved">nint</span>&gt;)<span class="operator">&amp;</span><span class="method"><span class="static">id</span></span>;

    <span class="comment">// 晴れて A の中から _span を抜き出し。</span>
    <span class="reserved">var</span> <span class="variable">spanFromA</span> <span class="operator">=</span> <span class="variable">f</span>(<span class="reserved">ref</span> <span class="variable">a</span>);

    <span class="comment">// span と同じ内容。</span>
    <span class="control">foreach</span> (<span class="reserved">var</span> <span class="variable">x</span> <span class="control">in</span> <span class="variable">spanFromA</span>) <span class="type"><span class="static">Console</span></span><span class="operator">.</span><span class="method"><span class="static">Write</span></span>(<span class="string">$&quot;</span>{<span class="variable">x</span>:<span class="string">X2</span>}<span class="string">&quot;</span>);
    <span class="static"><span class="type">Console</span></span><span class="operator">.</span><span class="static"><span class="method">WriteLine</span></span>();

    <span class="comment">// span が書き変わる。</span>
    <span class="variable">spanFromA</span>[<span class="number">0</span>] <span class="operator">=</span> <span class="number">1</span>;
    <span class="variable">spanFromA</span>[<span class="number">1</span>] <span class="operator">=</span> <span class="number">2</span>;
    <span class="variable">spanFromA</span>[<span class="number">2</span>] <span class="operator">=</span> <span class="number">3</span>;
    <span class="variable">spanFromA</span>[<span class="number">3</span>] <span class="operator">=</span> <span class="number">4</span>;
}

<span class="comment">// 上書きされた 01020304。</span>
<span class="control">foreach</span> (<span class="reserved">var</span> <span class="variable">x</span> <span class="control">in</span> <span class="variable">span</span>) <span class="type"><span class="static">Console</span></span><span class="operator">.</span><span class="static"><span class="method">Write</span></span>(<span class="string">$&quot;</span>{<span class="variable">x</span>:<span class="string">X2</span>}<span class="string">&quot;</span>);
<span class="type"><span class="static">Console</span></span><span class="operator">.</span><span class="method"><span class="static">WriteLine</span></span>();

<span class="comment">// nint 素通しメソッド。</span>
<span class="comment">// nint = unsafe コンテキスト内なら任意のポインター、任意の ref T を通せる。</span>
<span class="reserved">static</span> <span class="reserved">nint</span> <span class="method"><span class="static">id</span></span>(<span class="reserved">nint</span> <span class="variable local">x</span>) <span class="operator">=&gt;</span> <span class="variable local">x</span>;

<span class="reserved">ref</span> <span class="reserved">struct</span> <span class="type struct">A</span>
{
    <span class="comment">// private なので通常、この _span を取り出す方法ない。</span>
    <span class="comment">// なんならリフレクションを使っても無理。</span>
    <span class="reserved">private</span> <span class="type struct">Span</span>&lt;<span class="reserved">int</span>&gt; <span class="field">_span</span>;
    <span class="reserved">public</span> <span class="type struct">A</span>(<span class="type struct">Span</span>&lt;<span class="reserved">int</span>&gt; <span class="variable local">span</span>) <span class="operator">=&gt;</span> <span class="field">_span</span> <span class="operator">=</span> <span class="variable local">span</span>;
}
</pre>
<p>native interop でしか使い道がないと思っていた関数ポインター、
こんなところで「これでしかできないこと」があるとは…</p>
 ]]></description>
				<pubDate>Sun, 18 Dec 2022 22:11:56 +0900</pubDate>
			</item>
			<item>
				<title>未使用ジェネリック型引数で TypeLoadException が起こる問題</title>
				<link>http://ufcpp.net/blog/2022/12/unused-generic-type-parameter/</link>
				<description><![CDATA[ <p>今日は C# の構造体がらみで、
できそうでできない、
できてもいいはずだけど直されない、
コンパイルまでは通るのに実行時にエラーになってしまう制限の話。</p>
<p>※(2023/8/3追記) .NET 8 で直るそうです。</p>
<h2>入れ子の構造体</h2>
<p>C# で、構造体の中にその構造体自身のフィールドを持つことはできません。
レイアウトの決定が無限再帰を起こすので、これはダメで当然。</p>
<pre class="source" title="構造体の入れ子はダメ">
<span class="reserved">struct</span> <span class="type struct">S</span> { <span class="type struct">S</span> <span class="field"><span class="error" title="CS0523">_nested</span></span>; }
</pre>
<p>これはそもそもコンパイル エラーになります。
当然。</p>
<h2>使ってないジェネリック型引数でも TypeLoadExcpetion</h2>
<p>問題は以下のような場合。
現在の C# (というか .NET の型システム)では、以下のような型はコンパイルはできるものの、実行してみようとすると実行時例外を起こします。
(構造体 <code>S</code> のメンバーに初めて触れた瞬間に <code>TypeLoadException</code> が飛ぶ。)</p>
<pre class="source" title="疑惑の判定">
<span class="reserved">struct</span> <span class="type struct">S</span> { <span class="type struct">Empty</span>&lt;<span class="type struct">S</span>&gt; <span class="field">_empty</span>; }
<span class="reserved">struct</span> <span class="type struct">Empty</span>&lt;<span class="type param">T</span>&gt; { }
</pre>
<p><code>Empty&lt;T&gt;</code> の側が <code>T</code> のフィールドを持っていないので
(というか空っぽなので、<code>T</code> が何かによらずサイズ1で固定)、
レイアウト決定で無限再帰は起こさないはずです。
実際、これは、</p>
<ul>
<li>原理的にはできてもいい</li>
<li>C# は禁止していない</li>
<li>CLI (.NET のランタイム仕様)でも禁止は名言されていない</li>
<li>現在の .NET のランタイムの実装が過剰防衛している</li>
</ul>
<p>という状態。
<a href="https://github.com/dotnet/runtime/issues/6924">C# コンパイラー チームの人がそれを指摘する issue</a> も立っていたりします。</p>
<h3>実用例</h3>
<p>まあ、<code>Empty</code> みたいな無意味なコードは誰も書かないとしても、
例えば、以下のようなシナリオでなら似たようなことをしたくなる人はいるはずです。</p>
<p>まず、以下のように、構造体の配列で木構造を表現する例を考えます。</p>
<pre class="source" title="配列に Parent と Next を持たせた型を入れて木構造を表現">
<span class="comment">// 配列に Parent と Next を持たせた型を入れて木構造を表現。</span>
<span class="comment">// A も B もツリー。</span>
<span class="comment">// A からは B も参照。</span>
<span class="reserved">class</span> <span class="type">Tree</span>
{
    <span class="type struct">A</span>[] <span class="field">A</span>;
    <span class="type struct">B</span>[] <span class="field">B</span>;
}

<span class="reserved">struct</span> <span class="type struct">A</span>
{
    <span class="reserved">int</span> <span class="field">Parent</span>;
    <span class="reserved">int</span> <span class="field">Next</span>;
    <span class="reserved">int</span> <span class="field">BIndex</span>;
}

<span class="reserved">struct</span> <span class="type struct">B</span>
{
    <span class="reserved">int</span> <span class="field">Parent</span>;
    <span class="reserved">int</span> <span class="field">Next</span>;
}
</pre>
<p>実際にはさらに、「インデックスとは関係ない別の <code>int</code> も持ちたくなったりするはずで、なおのこと「この <code>int</code> は何？」みたいになると思います。</p>
<pre class="source" title="この int は何？">
<span class="reserved">struct</span> <span class="type struct">A</span>
{
    <span class="comment">// 木とは別に持ちたいデータ。</span>
    <span class="reserved">int</span> <span class="field">Value</span>;
    <span class="reserved">int</span> <span class="field">Length</span>;
    <span class="input">...</span>

    <span class="comment">// 木構造表現用。</span>
    <span class="reserved">int</span> <span class="field">Parent</span>;
    <span class="reserved">int</span> <span class="field">Next</span>;

    <span class="comment">// 別の木を参照</span>
    <span class="reserved">int</span> <span class="field">BIndex</span>;
}
</pre>
<p>ということで、<code>Parent</code> や <code>Next</code> が「配列 <code>A[]</code> のインデックス」であることが一目でわかるようにしたくなったりします。
よくやるのが、以下のように「<code>int</code> をラップした構造体を用意」みたいな手段。</p>
<pre class="source" title="「配列 T[] のインデックス」用の int のラッパー構造体">
<span class="reserved">struct</span> <span class="type struct">Index</span>&lt;<span class="type param">T</span>&gt;
{
    <span class="reserved">public</span> <span class="reserved">int</span> <span class="property">Value</span> { <span class="reserved">get</span>; }
    <span class="reserved">public</span> <span class="type struct">Index</span>(<span class="reserved">int</span> <span class="variable local">value</span>) <span class="operator">=&gt;</span> <span class="property">Value</span> <span class="operator">=</span> <span class="variable local">value</span>;
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">implicit</span> <span class="reserved">operator</span> <span class="type struct">Index</span>&lt;<span class="type param">T</span>&gt;(<span class="reserved">int</span> <span class="variable local">value</span>) <span class="operator">=&gt;</span> <span class="reserved">new</span>(<span class="variable local">value</span>);
}
</pre>
<p>この型を使って先ほどの <code>Tree</code>, <code>A</code>, <code>B</code> を書き換えると以下のような感じになります。</p>
<pre class="source" title="Index 構造体の導入">
<span class="comment">// 配列に Parent と Next を持たせた型を入れて木構造を表現。</span>
<span class="comment">// A も B もツリー。</span>
<span class="comment">// A からは B も参照。</span>
<span class="reserved">class</span> <span class="type">Tree</span>
{
    <span class="type struct">A</span>[] <span class="field">A</span>;
    <span class="type struct">B</span>[] <span class="field">B</span>;
}

<span class="reserved">struct</span> <span class="type struct">A</span>
{
    <span class="reserved">int</span> <span class="field">Value</span>;
    <span class="reserved">int</span> <span class="field">Length</span>;
    <span class="type struct">Index</span>&lt;<span class="type struct">A</span>&gt; <span class="field">Parent</span>;
    <span class="type struct">Index</span>&lt;<span class="type struct">A</span>&gt; <span class="field">Next</span>;
    <span class="type struct">Index</span>&lt;<span class="type struct">B</span>&gt; <span class="field">BIndex</span>;
}

<span class="reserved">struct</span> <span class="type struct">B</span>
{
    <span class="type struct">Index</span>&lt;<span class="type struct">B</span>&gt; <span class="field">Parent</span>;
    <span class="type struct">Index</span>&lt;<span class="type struct">B</span>&gt; <span class="field">Next</span>;
}
</pre>
<p><strong>便利！</strong></p>
<p>と思ったところで、冒頭の <code>Empty&lt;T&gt;</code> の例と同じ理屈の過剰防衛で、
<code>TypeLoadException</code> を起こします…</p>
<h2>回避策</h2>
<p>ちょっと不格好でもよければ解決方法は簡単で、
1段ダミーのクラスを挟むだけだったり。</p>
<pre class="source" title="ダミーのクラスを1個用意">
<span class="reserved">struct</span> <span class="type struct">Index</span>&lt;<span class="type param">T</span>&gt;
{
    <span class="reserved">public</span> <span class="reserved">int</span> <span class="property">Value</span> { <span class="reserved">get</span>; }
    <span class="reserved">public</span> <span class="type struct">Index</span>(<span class="reserved">int</span> <span class="variable local">value</span>) <span class="operator">=&gt;</span> <span class="property">Value</span> <span class="operator">=</span> <span class="variable local">value</span>;
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">implicit</span> <span class="reserved">operator</span> <span class="type struct">Index</span>&lt;<span class="type param">T</span>&gt;(<span class="reserved">int</span> <span class="variable local">value</span>) <span class="operator">=&gt;</span> <span class="reserved">new</span>(<span class="variable local">value</span>);
}

<span class="comment">// Index&lt;Dummy&lt;T&gt;&gt; とか Index&lt;Empty&lt;T&gt;&gt; よりは Index&lt;Of&lt;T&gt;&gt; の方がマシかなと…</span>
<span class="reserved">class</span> <span class="type">Of</span>&lt;<span class="type param">T</span>&gt; { }
</pre>
<pre class="source" title="やむなく Index&lt;Of&lt;T&gt;&gt;">
<span class="reserved">class</span> <span class="type">Tree</span>
{
    <span class="type struct">A</span>[] <span class="field">A</span>；
    <span class="type struct">B</span>[] <span class="field">B</span>;
}

<span class="reserved">struct</span> <span class="type struct">A</span>
{
    <span class="reserved">int</span> <span class="field">Value</span>;
    <span class="reserved">int</span> <span class="field">Length</span>;
    <span class="type struct">Index</span>&lt;<span class="type">Of</span>&lt;<span class="type struct">A</span>&gt;&gt; <span class="field">Parent</span>;
    <span class="type struct">Index</span>&lt;<span class="type">Of</span>&lt;<span class="type struct">A</span>&gt;&gt; <span class="field">Next</span>;
    <span class="type struct">Index</span>&lt;<span class="type">Of</span>&lt;<span class="type struct">B</span>&gt;&gt; <span class="field">BIndex</span>;
}

<span class="reserved">struct</span> <span class="type struct">B</span>
{
    <span class="type struct">Index</span>&lt;<span class="type">Of</span>&lt;<span class="type struct">B</span>&gt;&gt; <span class="field">Parent</span>;
    <span class="type struct">Index</span>&lt;<span class="type">Of</span>&lt;<span class="type struct">B</span>&gt;&gt; <span class="field">Next</span>;
}
</pre>
<p>だいぶ不格好で嫌なので、
<a href="https://github.com/dotnet/runtime/issues/6924">件の issue</a> の優先度を上げてもらえるように👍を付けまくってもらえたりすると大変うれしかったりは…</p>
<p>この issue は2016年からずっと「Future」(いつかね、いつか)なんですよね。
これ、C# 6.0 (つまり、Roslyn 化/C# への移植)の頃に始めて報告されたというだけで、
実際には .NET Framework が生まれてこの方ずっとかも。</p>
<p>※(2023/8/3追記) .NET 8 で直るそうです。C# にジェネリクスが導入されて以来の20年越しの修正に。</p>
 ]]></description>
				<pubDate>Sun, 11 Dec 2022 18:17:58 +0900</pubDate>
			</item>
			<item>
				<title>拡張メソッドは暗黙型変換を見ない</title>
				<link>http://ufcpp.net/blog/2022/12/extension-resolution/</link>
				<description><![CDATA[ <p>こないだ、C# で <a href="https://ufcpp.net/blog/2022/12/stackalloc-natural-type/"><code>(stackalloc T[N]).M()</code></a> とか書けるという話を書いたわけですが。
その過程で出てきた「そういえばこんなのも」話をもう1個。</p>
<p><a href="https://ufcpp.net/study/csharp/st_string.html#string-interpolation">文字列補間</a>の拡張メソッド呼びがちょっと変という話になります。</p>
<h2>拡張メソッドの解決</h2>
<p><a href="https://ufcpp.net/study/csharp/sp3_extension.html">拡張メソッド</a>の存在意義は、
「語順を変更して、<code>x.M().N()</code> みたいな呼び出しができる」という点です。
ほとんどの場合は本当に「語順」だけの問題で、通常のメソッド呼び出しの形でも同じコードが書けます。</p>
<pre class="source" title="同じメソッドを通常のメソッド呼び出しと拡張メソッド呼び出しの両方の書き方をする">
<span class="comment">// 拡張メソッド呼び。</span>
<span class="number">1</span><span class="operator">.</span><span class="method">M</span>();

<span class="comment">// 同じものを通常のメソッド呼び出しで書く。</span>
<span class="static"><span class="type">Ex</span></span><span class="operator">.</span><span class="method"><span class="static">M</span></span>(<span class="number">1</span>);

<span class="reserved">static</span> <span class="reserved">class</span> <span class="type"><span class="static">Ex</span></span>
{
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="static"><span class="method">M</span></span>(<span class="reserved">this</span> <span class="reserved">int</span> <span class="variable local">_</span>) { }
}
</pre>
<p>ただ、まあ、通常のメソッド呼びと拡張メソッド呼びでは、ちょっとだけ「解決ルール」みたいなやつが違ったりします。</p>
<p>無変換の場合、つまり、
「<code>1</code> を <code>int</code> 引数に渡す」とか「<code>&quot;&quot;</code> を <code>string</code> 引数に渡す」みたいなときには変な挙動はしないんですが、
問題は型変換が絡む場合です。</p>
<h2>解決できる例</h2>
<p>先に、大丈夫な例から行きます。</p>
<p>親クラスや、実装するインターフェイスへの変換は問題なく行けて、
拡張メソッド呼び出しもできます。</p>
<pre class="source" title="親クラスや、実装しているインターフェイスへの変換">
<span class="comment">// 親クラスや、実装しているインターフェイスへの変換は、拡張メソッド呼び出しできる。</span>
<span class="number">1</span><span class="operator">.</span><span class="method">Object</span>();
<span class="number">1</span><span class="operator">.</span><span class="method">Interface</span>();

<span class="type"><span class="static">Ex</span></span><span class="operator">.</span><span class="method"><span class="static">Object</span></span>(<span class="number">1</span>);
<span class="static"><span class="type">Ex</span></span><span class="operator">.</span><span class="static"><span class="method">Interface</span></span>(<span class="number">1</span>);

<span class="reserved">static</span> <span class="reserved">class</span> <span class="type"><span class="static">Ex</span></span>
{
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="static"><span class="method">Object</span></span>(<span class="reserved">this</span> <span class="reserved">object</span> <span class="variable local">_</span>) { }
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">Interface</span></span>(<span class="reserved">this</span> <span class="type">IComparable</span> <span class="variable local">_</span>) { }
}
</pre>
<p>オーバーロードがあるときには
「階層が近い方優先」で、これも通常メソッド呼び・拡張メソッド呼びで共通です。</p>
<pre class="source" title="オーバーロードは階層が近い方優先">
<span class="comment">// どっちも IComparable の方が呼ばれる。</span>
<span class="number">1</span><span class="operator">.</span><span class="method">M</span>();
<span class="type"><span class="static">Ex</span></span><span class="operator">.</span><span class="static"><span class="method">M</span></span>(<span class="number">1</span>);

<span class="reserved">static</span> <span class="reserved">class</span> <span class="static"><span class="type">Ex</span></span>
{
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="static"><span class="method">M</span></span>(<span class="reserved">this</span> <span class="reserved">object</span> <span class="variable local">_</span>) <span class="operator">=&gt;</span> <span class="static"><span class="type">Console</span></span><span class="operator">.</span><span class="method"><span class="static">WriteLine</span></span>(<span class="string">&quot;object&quot;</span>);
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="static"><span class="method">M</span></span>(<span class="reserved">this</span> <span class="type">IComparable</span> <span class="variable local">_</span>) <span class="operator">=&gt;</span> <span class="static"><span class="type">Console</span></span><span class="operator">.</span><span class="method"><span class="static">WriteLine</span></span>(<span class="string">&quot;IComparable&quot;</span>);
}
</pre>
<h2>ユーザー定義の型変換</h2>
<p>拡張メソッドの解決時、ユーザー定義の型変換はみません。
一方で、通常のメソッド解決の時には見るので、
「拡張メソッド呼びだけできない」みたいなことがあります。</p>
<p>標準ライブラリでいうと、<code>DateTime</code> → <code>DateTimeOffset</code> とか、
<code>Span&lt;T&gt;</code> → <code>ReadOnlySpan&lt;T&gt;</code> とか、
<code>string</code> → <code>ReadOnlySpan&lt;char&gt;</code> とかがあります。</p>
<pre class="source" title="拡張メソッド呼びできない例: ユーザー定義の型変換">
<span class="comment">// 通常のメソッドとしてなら呼べる。</span>
<span class="static"><span class="type">Ex</span></span><span class="operator">.</span><span class="method"><span class="static">M</span></span>(<span class="string">&quot;&quot;</span>);                 <span class="comment">// string → ReadOnlySpan&lt;char&gt;</span>
<span class="type"><span class="static">Ex</span></span><span class="operator">.</span><span class="method"><span class="static">M</span></span>(<span class="reserved">stackalloc</span> <span class="reserved">char</span>[<span class="number">1</span>]); <span class="comment">// Span&lt;char&gt; → ReadOnlySpan&lt;char&gt;</span>
<span class="type"><span class="static">Ex</span></span><span class="operator">.</span><span class="static"><span class="method">M</span></span>(<span class="type struct">DateTime</span><span class="operator">.</span><span class="property"><span class="static">Now</span></span>);       <span class="comment">// DateTime → DateTimeOffset</span>

<span class="comment">// 拡張メソッドでは呼べない…</span>
<span class="string"><span class="error" title="CS1929">&quot;&quot;</span></span><span class="operator">.</span>M();
(<span class="error" title="CS1929"><span class="reserved">stackalloc</span> <span class="reserved">char</span>[<span class="number">1</span>]</span>)<span class="operator">.</span>M();
<span class="error" title="CS1929"><span class="type struct">DateTime</span><span class="operator">.</span><span class="static"><span class="property">Now</span></span></span><span class="operator">.</span>M();

<span class="reserved">static</span> <span class="reserved">class</span> <span class="type"><span class="static">Ex</span></span>
{
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">M</span></span>(<span class="reserved">this</span> <span class="type struct">ReadOnlySpan</span>&lt;<span class="reserved">char</span>&gt; <span class="variable local">_</span>) { }
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">M</span></span>(<span class="reserved">this</span> <span class="type struct">DateTimeOffset</span> <span class="variable local">_</span>) {}
}
</pre>
<p>これがまあ、<a href="https://ufcpp.net/blog/2022/12/stackalloc-natural-type/">こないだのブログ</a>とのつながりでして。
「<code>(stackalloc char[1]).M()</code> が呼べない？そうだっけ？」からの、
「<code>ReadOnly</code> を削ったら呼べた」ということがありました。</p>
<h2>ターゲットからの型推論</h2>
<p>ターゲットからの型推論系の処理も、拡張メソッドでは働きません。</p>
<p><code>new()</code>、<code>default</code> 辺りはダメです。</p>
<pre class="source" title="">
<span class="comment">// 通常のメソッドとしてなら呼べる。</span>
<span class="type"><span class="static">Ex</span></span><span class="operator">.</span><span class="method"><span class="static">M</span></span>(<span class="reserved">new</span>());      <span class="comment">// new object()</span>
<span class="type"><span class="static">Ex</span></span><span class="operator">.</span><span class="method"><span class="static">M</span></span>(<span class="reserved">default</span>); <span class="comment">// null</span>

<span class="comment">// 拡張メソッド前に型推論は働かない。</span>
<span class="comment">// エラーに。</span>
<span class="error" title="CS8754"><span class="reserved">new</span>()</span><span class="operator">.</span>M();
<span class="reserved"><span class="error" title="CS8716">default</span></span><span class="operator">.</span>M();

<span class="reserved">static</span> <span class="reserved">class</span> <span class="type"><span class="static">Ex</span></span>
{
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">M</span></span>(<span class="reserved">this</span> <span class="reserved">object</span><span class="operator">?</span> <span class="variable local">_</span>) {}
}
</pre>
<h2>ターゲットからの型推論 + 自然な型</h2>
<p>ターゲットからの型推論は効かないものの、
自然な型を持っているやつはどうなるかというと…</p>
<p>基本的に、自然な型の時だけは拡張メソッド呼びもできます。</p>
<pre class="source" title="自然な型の時なら拡張メソッドが呼べる">
<span class="comment">// 通常のメソッドとして、当然呼べる。</span>
<span class="type"><span class="static">Ex</span></span><span class="operator">.</span><span class="method"><span class="static">M</span></span>(<span class="number">1</span>);
<span class="type"><span class="static">Ex</span></span><span class="operator">.</span><span class="method"><span class="static">M</span></span>(<span class="string">$&quot;</span>{<span class="number">1</span>}<span class="string">&quot;</span>);

<span class="comment">// 整数リテラルの自然な型は int で、 int の拡張メソッドなら呼べる。</span>
<span class="number">1</span><span class="operator">.</span><span class="method">M</span>();

<span class="comment">// 同、string の拡張メソッドなら呼べる。</span>
<span class="string">$&quot;</span>{<span class="number">1</span>}<span class="string">&quot;</span><span class="operator">.</span><span class="method">M</span>();

<span class="reserved">static</span> <span class="reserved">class</span> <span class="type"><span class="static">Ex</span></span>
{
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">M</span></span>(<span class="reserved">this</span> <span class="reserved">int</span> <span class="variable local">_</span>) { }
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">M</span></span>(<span class="reserved">this</span> <span class="reserved">string</span> <span class="variable local">_</span>) {}
}
</pre>
<p>例えば整数リテラルは <code>short</code> や <code>byte</code> 型に変換できますし、
文字列補間 <code>$&quot;&quot;</code> は <code>IFormattable</code> や文字列補間ハンドラーに変換できます。
ところが、こういう場合は拡張メソッド呼びできません。</p>
<pre class="source" title="ターゲットからの型判定がかかるような例では拡張メソッドは呼べない">
<span class="reserved">using</span> System<span class="operator">.</span>Runtime<span class="operator">.</span>CompilerServices;

<span class="comment">// 通常のメソッドとしてなら呼べる。</span>
<span class="type"><span class="static">Ex</span></span><span class="operator">.</span><span class="method"><span class="static">M</span></span>(<span class="number">1</span>);
<span class="static"><span class="type">Ex</span></span><span class="operator">.</span><span class="static"><span class="method">M</span></span>(<span class="string">$&quot;</span>{<span class="number">1</span>}<span class="string">&quot;</span>);

<span class="comment">// ターゲットからの型判定がかかるような例では拡張メソッドは呼べない。</span>
<span class="number"><span class="error" title="CS1929">1</span></span><span class="operator">.</span>M();
<span class="error" title="CS1929"><span class="string">$&quot;</span>{<span class="number">1</span>}<span class="string">&quot;</span></span><span class="operator">.</span>M();

<span class="reserved">static</span> <span class="reserved">class</span> <span class="type"><span class="static">Ex</span></span>
{
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="static"><span class="method">M</span></span>(<span class="reserved">this</span> <span class="reserved">byte</span> <span class="variable local">_</span>) { }
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">M</span></span>(<span class="reserved">this</span> <span class="type struct">DefaultInterpolatedStringHandler</span> <span class="variable local">_</span>) {}
}
</pre>
<h3>ラムダ式の自然な型</h3>
<p>ちなみに、自然な型決定できるようになったにもかかわらず、
ラムダ式は自然な型に対しても拡張メソッド呼びはできません。
これは意図的で、<code>() =&gt; {}.M()</code> みたいな文法を認めたくなかったみたいです。
<code>(() =&gt; {}).M()</code> でもダメ。 </p>
<pre class="source" title="ラムダ式のときは自然な型に対しても拡張メソッド呼び不可">
<span class="comment">// これは行ける。</span>
<span class="comment">// 何なら Delegate とか object 引数相手でもこう書ける。</span>
<span class="type"><span class="static">Ex</span></span><span class="operator">.</span><span class="static"><span class="method">M</span></span>(() <span class="operator">=&gt;</span> { });

<span class="comment">// これはダメ。</span>
<span class="comment">// 自然な型は Action なはずだけど。</span>
<span class="error" title="CS0023">(() <span class="operator">=&gt;</span> { })<span class="operator">.</span>M</span>();

<span class="reserved">static</span> <span class="reserved">class</span> <span class="static"><span class="type">Ex</span></span>
{
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">M</span></span>(<span class="reserved">this</span> <span class="type">Action</span> <span class="variable local">_</span>) {}
}
</pre>
<h3>特殊なオーバーロード解決順序</h3>
<p>文字列補間のオーバーロード解決順序はちょっと特殊です。</p>
<p>C# 10 でパフォーマンス改善のために<a href="https://ufcpp.net/study/csharp/start/improvedinterpolatedstring/">ハンドラー パターン</a>を導入したわけですが、
その時に検討された内容:</p>
<ul>
<li>たいていのクラスがすでに <code>string</code> のオーバーロードを持っている</li>
<li>普通に考えれば <code>$&quot;&quot;</code> の自然な型は <code>string</code> で、オーバーロード解決でも <code>string</code> 引数が優先されるべき</li>
<li>ところが <code>string</code> オーバーロードが呼ばれたらパフォーマンス改善されない</li>
<li>何なら C# 6 で<a href="https://ufcpp.net/study/csharp/st_string.html#string-interpolation">文字列補間</a>を導入したときにも、<code>IFormattable</code> オーバーロードが呼ばれなくて困った</li>
</ul>
<p>このような背景がありまして。
結果的に、「文字列補間ハンドラーがあれば、それを優先的に使う」という特殊処理が挟まっています。</p>
<pre class="source" title="">
<span class="reserved">using</span> System<span class="operator">.</span>Runtime<span class="operator">.</span>CompilerServices;

<span class="comment">// ハンドラー優先の特殊処理が働く。</span>
<span class="static"><span class="type">Ex</span></span><span class="operator">.</span><span class="method"><span class="static">M</span></span>(<span class="string">$&quot;</span>{<span class="number">1</span>}<span class="string">&quot;</span>); <span class="comment">// interpolation の方が呼ばれる</span>

<span class="reserved">static</span> <span class="reserved">class</span> <span class="static"><span class="type">Ex</span></span>
{
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">M</span></span>(<span class="reserved">string</span> <span class="variable local">_</span>) <span class="operator">=&gt;</span> <span class="static"><span class="type">Console</span></span><span class="operator">.</span><span class="method"><span class="static">WriteLine</span></span>(<span class="string">&quot;string&quot;</span>);
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="static"><span class="method">M</span></span>(<span class="type struct">DefaultInterpolatedStringHandler</span> <span class="variable local">_</span>) <span class="operator">=&gt;</span> <span class="type"><span class="static">Console</span></span><span class="operator">.</span><span class="method"><span class="static">WriteLine</span></span>(<span class="string">&quot;interpolation&quot;</span>);
}
</pre>
<p>これは本当に特殊処理です。
例えば、整数リテラルの場合は普通に int が優先されます。</p>
<pre class="source" title="int 優先">
<span class="comment">// 普通に考えれば「自然な型」優先。</span>
<span class="comment">// 実際、整数リテラルは int 優先。</span>
<span class="static"><span class="type">Ex</span></span><span class="operator">.</span><span class="static"><span class="method">M</span></span>(<span class="number">1</span>); <span class="comment">// int が呼ばれる</span>

<span class="comment">// int におさまらない桁のリテラルを書くと long リテラルになって、long オーバーロードが呼ばれるのに。</span>
<span class="type"><span class="static">Ex</span></span><span class="operator">.</span><span class="method"><span class="static">M</span></span>(<span class="number">0x1_0000_0000</span>); <span class="comment">// long が呼ばれる。</span>

<span class="reserved">static</span> <span class="reserved">class</span> <span class="type"><span class="static">Ex</span></span>
{
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">M</span></span>(<span class="reserved">int</span> <span class="variable local">_</span>) <span class="operator">=&gt;</span> <span class="type"><span class="static">Console</span></span><span class="operator">.</span><span class="static"><span class="method">WriteLine</span></span>(<span class="string">&quot;int&quot;</span>);
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="static"><span class="method">M</span></span>(<span class="reserved">byte</span> <span class="variable local">_</span>) <span class="operator">=&gt;</span> <span class="static"><span class="type">Console</span></span><span class="operator">.</span><span class="static"><span class="method">WriteLine</span></span>(<span class="string">&quot;byte&quot;</span>);
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="static"><span class="method">M</span></span>(<span class="reserved">long</span> <span class="variable local">_</span>) <span class="operator">=&gt;</span> <span class="static"><span class="type">Console</span></span><span class="operator">.</span><span class="method"><span class="static">WriteLine</span></span>(<span class="string">&quot;long&quot;</span>);
}
</pre>
<p>で、この <code>$&quot;&quot;</code> に対する特殊処理が、拡張メソッド解決の際には働かないということは…
以下のように、通常メソッド呼びと拡張メソッド呼びで呼ばれるオーバーロードが変わるという症状を起こします。</p>
<pre class="source" title="$&quot;&quot; の拡張メソッド呼び">
<span class="reserved">using</span> System<span class="operator">.</span>Runtime<span class="operator">.</span>CompilerServices;

<span class="comment">// ハンドラー優先の特殊処理が働く。</span>
<span class="type"><span class="static">Ex</span></span><span class="operator">.</span><span class="method"><span class="static">M</span></span>(<span class="string">$&quot;</span>{<span class="number">1</span>}<span class="string">&quot;</span>); <span class="comment">// interpolation の方が呼ばれる</span>

<span class="comment">// そしてその特殊処理は、拡張メソッド解決時には働かない！</span>
<span class="string">$&quot;</span>{<span class="number">1</span>}<span class="string">&quot;</span><span class="operator">.</span><span class="method">M</span>(); <span class="comment">// string の方が呼ばれる！</span>

<span class="reserved">static</span> <span class="reserved">class</span> <span class="static"><span class="type">Ex</span></span>
{
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="static"><span class="method">M</span></span>(<span class="reserved">this</span> <span class="reserved">string</span> <span class="variable local">_</span>) <span class="operator">=&gt;</span> <span class="type"><span class="static">Console</span></span><span class="operator">.</span><span class="method"><span class="static">WriteLine</span></span>(<span class="string">&quot;string&quot;</span>);
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="static"><span class="method">M</span></span>(<span class="reserved">this</span> <span class="type struct">DefaultInterpolatedStringHandler</span> <span class="variable local">_</span>) <span class="operator">=&gt;</span> <span class="static"><span class="type">Console</span></span><span class="operator">.</span><span class="method"><span class="static">WriteLine</span></span>(<span class="string">&quot;interpolation&quot;</span>);
}
</pre>
<p>特殊処理が挟まった背景を知らないと意味が分からない仕様ですよね。
一応、バグじゃなくて仕様通りです。</p>
 ]]></description>
				<pubDate>Thu, 08 Dec 2022 23:07:13 +0900</pubDate>
			</item>
			<item>
				<title>stackalloc の自然な型</title>
				<link>http://ufcpp.net/blog/2022/12/stackalloc-natural-type/</link>
				<description><![CDATA[ <p>今日は
<code>stackalloc T[N]</code> と <code>(stackalloc T[N])</code> に差があるとか、
<code>(stackalloc T[N]).M()</code> が許されるとか、
そんな感じの話。</p>
<h2><a id="natural-type">ターゲット型推論と自然な型</a></h2>
<p>C# の文法の中には、「基本的にはターゲットを見て型決定するけども、別にターゲットがなくても型決定できる」ような文法がいくつかあります。
例えば整数リテラルがそうなんですが、以下のように、ターゲット(左辺)の型が決まっていても決まっていなくても大丈夫です。</p>
<pre class="source" title="ターゲットからの型推論もできるし、推論できなかった時の自然な型も決まってる">
<span class="comment">// ターゲット(左辺)の型に合わせて「100」の型を決めてる。</span>
<span class="reserved">byte</span> <span class="variable">x</span> <span class="operator">=</span> <span class="number">100</span>;
<span class="reserved">short</span> <span class="variable">y</span> <span class="operator">=</span> <span class="number">100</span>;
<span class="reserved">int</span> <span class="variable">z</span> <span class="operator">=</span> <span class="number">100</span>;

<span class="comment">// 一方で、var だとターゲットからは型決定できない。</span>
<span class="comment">// そういう場合の 100 は int になる。</span>
<span class="reserved">var</span> <span class="variable">v</span> <span class="operator">=</span> <span class="number">100</span>;
</pre>
<p>ちなみに、<code>var v = 100;</code> みたいに「普段ターゲットから型を決めている式が、決めれないときにデフォルトで何の型になるか」を指して「自然な型」(natural type)と言います。
上述の場合、「整数リテラルの自然な型は <code>int</code> 」ということになります。</p>
<p>他だと、補間文字列リテラルも「ターゲット型推論 + 自然な型持ち」です。</p>
<pre class="source" title="補間文字列の自然な型">
<span class="reserved">using</span> System<span class="operator">.</span>Runtime<span class="operator">.</span>CompilerServices;

<span class="reserved">var</span> <span class="variable">x</span> <span class="operator">=</span> <span class="number">100</span>;

<span class="comment">// ターゲット(左辺)の型に合わせて「$&quot;abc{x}&quot;」の型を決めてる。</span>
<span class="reserved">string</span> <span class="variable">s</span> <span class="operator">=</span> <span class="string">$&quot;</span><span class="string">abc</span>{<span class="variable">x</span>}<span class="string">&quot;</span>;
<span class="type">IFormattable</span> <span class="variable">f</span> <span class="operator">=</span> <span class="string">$&quot;</span><span class="string">abc</span>{<span class="variable">x</span>}<span class="string">&quot;</span>;
<span class="type struct">DefaultInterpolatedStringHandler</span> <span class="variable">h</span> <span class="operator">=</span> <span class="string">$&quot;</span><span class="string">abc</span>{<span class="variable">x</span>}<span class="string">&quot;</span>;

<span class="comment">// 一方で、こちらはターゲットからは型決定できない。</span>
<span class="comment">// そういう場合の $&quot;abc{x}&quot; は string になる。</span>
<span class="reserved">var</span> <span class="variable">v</span> <span class="operator">=</span> <span class="string">$&quot;</span><span class="string">abc</span>{<span class="variable">x</span>}<span class="string">&quot;</span>;
</pre>
<h2><a id="stackalloc">stackalloc</a></h2>
<p><code>stackalloc</code> は元々 <a href="https://ufcpp.net/study/csharp/sp_unsafe.html"><code>unsafe</code></a> 限定機能で、
当然利用者も少ない機能でした。</p>
<p>ところが C# 7.2 で <a href="https://ufcpp.net/study/csharp/resource/span/"><code>Span&lt;T&gt;</code> 構造体</a>とか<a href="https://ufcpp.net/study/csharp/sp_unsafe.html#safe-stackalloc">安全な <code>stackalloc</code></a>とか、
安全性を犠牲にせずにパフォーマンスを向上させれる文法が追加されて、
利用範囲が急に広がりました。</p>
<p>そして、安全な <code>stackalloc</code> の方が後入りなのもあって、<code>stackalloc</code> の自然な型はポインターのままです。</p>
<pre class="source" title="stackalloc は基本的にはポインター">
<span class="reserved">unsafe</span>
{
    <span class="comment">// stackalloc の昔からの用法。</span>
    <span class="comment">// 元々がこういう文法なので、 stackalloc の結果は T* (ポインター)。</span>
    <span class="reserved">int</span><span class="operator">*</span> <span class="variable">i1</span> <span class="operator">=</span> <span class="reserved">stackalloc</span> <span class="reserved">int</span>[<span class="number">4</span>];

    <span class="comment">// 型推論でも T* 扱い。</span>
    <span class="comment">// ↓の i2 は int* になる。</span>
    <span class="reserved">var</span> <span class="variable">i2</span> <span class="operator">=</span> <span class="reserved">stackalloc</span> <span class="reserved">int</span>[<span class="number">4</span>];
}

<span class="comment">// C# 7.2 から</span>
<span class="comment">// ターゲットが Span のときに限り、safe コンテキストで stackalloc が使える。</span>
<span class="type struct">Span</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">s</span> <span class="operator">=</span> <span class="reserved">stackalloc</span> <span class="reserved">int</span>[<span class="number">4</span>];

<span class="comment">// ところが、stackalloc の自然な型はポインターのまま。</span>
<span class="comment">// 以下の行は「safe コンテキストでポインターは使えません」エラー。</span>
<span class="reserved">var</span> <span class="variable">p</span> <span class="operator">=</span> <span class="error" title="CS0214"><span class="reserved">stackalloc</span> <span class="reserved">int</span>[<span class="number">4</span>]</span>;
</pre>
<p>その後、C# 8.0 で、式の途中に <code>stackalloc</code> を書けるようになりました。
(C# 8.0 未満では、ここまで上げてきた例のように、変数に直接代入する場所にしか書けませんでした。)</p>
<pre class="source" title="式の途中で stackalloc">
<span class="comment">// C# 8.0 未満でも書けた書き方:</span>
<span class="type struct">Span</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">s</span> <span class="operator">=</span> <span class="reserved">stackalloc</span> <span class="reserved">int</span>[<span class="number">4</span>];

<span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">M</span></span>(<span class="type struct">Span</span>&lt;<span class="reserved">int</span>&gt; <span class="variable local">s</span>) { }

<span class="comment">// こういう書き方は C# 8.0 以降でだけ書ける。</span>
<span class="method"><span class="static">M</span></span>(<span class="reserved">stackalloc</span> <span class="reserved">int</span>[<span class="number">4</span>]);
</pre>
<p>こういう歴史的な流れから、現状の <code>stackalloc</code> がどうなっているかというと…</p>
<h2><a id="stackalloc-anywhere">式の途中の stackalloc</a></h2>
<p>C# 8.0 のとき、「式の途中に <code>stackalloc</code> を書いた場合に限り、自然な型を <code>Span&lt;T&gt;</code> にする」という決定をしていたりします。</p>
<p>例えば、以下のようなコードを書くと、<code>M(int*)</code> と <code>M(Span&lt;int&gt;)</code> の呼び分けが掛かります。</p>
<pre class="source" title="式の途中かどうかで自然な型が違う stackalloc">
<span class="reserved">unsafe</span>
{
    <span class="comment">// こちらは昔ながらの型決定で、 stackalloc の自然な型はポインター。</span>
    <span class="reserved">var</span> <span class="variable">p</span> <span class="operator">=</span> <span class="reserved">stackalloc</span> <span class="reserved">int</span>[<span class="number">4</span>]; <span class="comment">// int* 扱い。</span>
    <span class="type">C</span><span class="operator">.</span><span class="static"><span class="method">M</span></span>(<span class="variable">p</span>); <span class="comment">// M(int*) の方が呼ばれる。</span>

    <span class="comment">// こちらは「式の途中」ということで、C# 8.0 以降のルールで、自然な型が Span&lt;T&gt; に。</span>
    <span class="type">C</span><span class="operator">.</span><span class="method"><span class="static">M</span></span>(<span class="reserved">stackalloc</span> <span class="reserved">int</span>[<span class="number">4</span>]); <span class="comment">// M(Span&lt;int&gt;) の方が呼ばれる。(なので実は unsafe 不要。)</span>
}

<span class="reserved">class</span> <span class="type">C</span>
{
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">unsafe</span> <span class="reserved">void</span> <span class="static"><span class="method">M</span></span>(<span class="reserved">int</span><span class="operator">*</span> <span class="variable local">_</span>) { }
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="static"><span class="method">M</span></span>(<span class="type struct">Span</span>&lt;<span class="reserved">int</span>&gt; <span class="variable local">_</span>) { }
}
</pre>
<p>で、この「式の途中なら <code>Span&lt;T&gt;</code>」な仕様を使うと、以下のようなこともできたりします。</p>
<ul>
<li><code>var</code> + <code>stackalloc</code> の自然な型を <code>Span&lt;T&gt;</code> にする</li>
<li><code>stackalloc</code> に対して拡張メソッドを呼ぶ</li>
</ul>
<h3><a id="natural-type-span">var + stackalloc を Span に</a></h3>
<p>式の途中なら自然な型が <code>Span&lt;T&gt;</code> になるということは…
実は <code>()</code> の有無で自然な型を変えれます。
<code>()</code> を付ければ safe。</p>
<pre class="source" title="() を付ければ safe">
<span class="comment">// 前述のとおり、自然な型が int* で、unsafe 必須。</span>
<span class="comment">// (今は unsafe を付けていないのでコンパイル エラー。)</span>
<span class="reserved">var</span> <span class="variable">p</span> <span class="operator">=</span> <span class="error" title="CS0214"><span class="reserved">stackalloc</span> <span class="reserved">int</span>[<span class="number">4</span>]</span>;

<span class="comment">// こっちは自然な型が Span&lt;int&gt;。</span>
<span class="comment">// var に対して使っても Span&lt;int&gt; になるので safe。</span>
<span class="reserved">var</span> <span class="variable">s</span> <span class="operator">=</span> (<span class="reserved">stackalloc</span> <span class="reserved">int</span>[<span class="number">4</span>]);
</pre>
<p>そしてまあ、型推論推進派(左辺と右辺で2度同じ型名を書きたくない)にとっては、
安全な <code>stackalloc</code> を使いつつも型推論を掛けるための回避策になります。</p>
<pre class="source" title="左右に同じ型名を2度も書きたくない">
<span class="comment">// こう書いてもいいけども…</span>
<span class="type struct">Span</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">s1</span> <span class="operator">=</span> <span class="reserved">stackalloc</span> <span class="reserved">int</span>[<span class="number">4</span>];

<span class="comment">// こっちの方が短いという。</span>
<span class="reserved">var</span> <span class="variable">s2</span> <span class="operator">=</span> (<span class="reserved">stackalloc</span> <span class="reserved">int</span>[<span class="number">4</span>]);

<span class="comment">// まして、型名が長いときは… だいぶ差が大きい。</span>
<span class="type struct">Span</span>&lt;<span class="type struct">LongLongStructName1234567890qwertyuiopasdfghjklzxcvbnm</span>&gt; <span class="variable">s3</span> <span class="operator">=</span> <span class="reserved">stackalloc</span> <span class="type struct">LongLongStructName1234567890qwertyuiopasdfghjklzxcvbnm</span>[<span class="number">4</span>];
<span class="reserved">var</span> <span class="variable">s4</span> <span class="operator">=</span> (<span class="reserved">stackalloc</span> <span class="type struct">LongLongStructName1234567890qwertyuiopasdfghjklzxcvbnm</span>[<span class="number">4</span>]);

<span class="reserved">struct</span> <span class="type struct">LongLongStructName1234567890qwertyuiopasdfghjklzxcvbnm</span> { }
</pre>
<h3><a id="extension-method">stackalloc に対して拡張メソッドを呼ぶ</a></h3>
<p>そして、拡張メソッドも呼べるみたいですよ。</p>
<pre class="source" title="(stackalloc) なら拡張メソッドも呼べる">
<span class="reserved">var</span> <span class="variable">x</span> <span class="operator">=</span> (<span class="reserved">stackalloc</span> <span class="reserved">int</span>[<span class="number">4</span>])<span class="operator">.</span><span class="method">M</span>(<span class="number">123</span>);

<span class="reserved">static</span> <span class="reserved">class</span> <span class="static"><span class="type">C</span></span>
{
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="type struct">ReadOnlySpan</span>&lt;<span class="type param">T</span>&gt; <span class="method"><span class="static">M</span></span>&lt;<span class="type param">T</span>&gt;(<span class="reserved">this</span> <span class="type struct">Span</span>&lt;<span class="type param">T</span>&gt; <span class="variable local">span</span>, <span class="type param">T</span> <span class="variable local">value</span>)
    {
        <span class="variable local">span</span><span class="operator">.</span><span class="method">Fill</span>(<span class="variable local">value</span>);
        <span class="control">return</span> <span class="variable local">span</span>;
    }
}
</pre>
<p>できる気はしていたものの、ほんとにできた…</p>
<p>というか、以下のようなコードを書いててふと思いつき。</p>
<pre class="source" title="&quot;&quot;u8 拡張メソッド">
<span class="reserved">using</span> System<span class="operator">.</span>Text;

<span class="comment">// u8 リテラルの自然な型は ReadOnlySpan&lt;byte&gt; だったはず。</span>
<span class="comment">// なら拡張メソッド M も呼べるはず。</span>
<span class="string">&quot;abcあいう&quot;<span class="reserved">u8</span></span><span class="operator">.</span><span class="method">M</span>();

<span class="comment">// そういや stackalloc にも自然な型あるはずよな…?</span>

<span class="reserved">static</span> <span class="reserved">class</span> <span class="type"><span class="static">C</span></span>
{
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="static"><span class="method">M</span></span>(<span class="reserved">this</span> <span class="type struct">ReadOnlySpan</span>&lt;<span class="reserved">byte</span>&gt; <span class="variable local">span</span>)
    {
        <span class="control">foreach</span> (<span class="reserved">var</span> <span class="variable">x</span> <span class="control">in</span> <span class="variable local">span</span>)
        {
            <span class="type"><span class="static">Console</span></span><span class="operator">.</span><span class="method"><span class="static">Write</span></span>(<span class="string">$&quot;</span>{<span class="variable">x</span>:<span class="string">X2</span>}<span class="string"> </span><span class="string">&quot;</span>);
        }
        <span class="type"><span class="static">Console</span></span><span class="operator">.</span><span class="method"><span class="static">WriteLine</span></span>();
        <span class="type"><span class="static">Console</span></span><span class="operator">.</span><span class="static"><span class="method">WriteLine</span></span>(<span class="type">Encoding</span><span class="operator">.</span><span class="property"><span class="static">UTF8</span></span><span class="operator">.</span><span class="method">GetString</span>(<span class="variable local">span</span>));
    }
}
</pre>
<p>ちなみに、拡張メソッド解決の仕様的に、以下のようなコードだとダメ(コンパイル エラー)だったりします。
<code>Span&lt;T&gt;</code> から <code>ReadOnlySpan&lt;T&gt;</code> への暗黙の型変換は、拡張メソッド解決の際には使われません。</p>
<pre class="source" title="ReadOnlySpan の拡張メソッドに対しては使えない">
<span class="reserved">using</span> System<span class="operator">.</span>Text;

<span class="comment">// これは呼べない。</span>
<span class="comment">// Span&lt;byte&gt; → ReadOnlySpan&lt;byte&gt; には暗黙の型変換があるものの、</span>
<span class="comment">// 拡張メソッド解決の際に暗黙の型変換を挟むことは許容していない。</span>
(<span class="error" title="CS1929"><span class="reserved">stackalloc</span> <span class="reserved">byte</span>[<span class="number">4</span>]</span>)<span class="operator">.</span>M();

<span class="reserved">static</span> <span class="reserved">class</span> <span class="static"><span class="type">C</span></span>
{
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="static"><span class="method">M</span></span>(<span class="reserved">this</span> <span class="type struct">ReadOnlySpan</span>&lt;<span class="reserved">byte</span>&gt; <span class="variable local">span</span>)
    {
        <span class="control">foreach</span> (<span class="reserved">var</span> <span class="variable">x</span> <span class="control">in</span> <span class="variable local">span</span>)
        {
            <span class="static"><span class="type">Console</span></span><span class="operator">.</span><span class="static"><span class="method">Write</span></span>(<span class="string">$&quot;</span>{<span class="variable">x</span>:<span class="string">X2</span>}<span class="string"> </span><span class="string">&quot;</span>);
        }
        <span class="static"><span class="type">Console</span></span><span class="operator">.</span><span class="method"><span class="static">WriteLine</span></span>();
        <span class="type"><span class="static">Console</span></span><span class="operator">.</span><span class="static"><span class="method">WriteLine</span></span>(<span class="type">Encoding</span><span class="operator">.</span><span class="static"><span class="property">UTF8</span></span><span class="operator">.</span><span class="method">GetString</span>(<span class="variable local">span</span>));
    }
}
</pre> ]]></description>
				<pubDate>Mon, 05 Dec 2022 22:24:10 +0900</pubDate>
			</item>
			<item>
				<title>raw string の空白文字</title>
				<link>http://ufcpp.net/blog/2022/12/rawstringwhitespace/</link>
				<description><![CDATA[ <p>書き捨ててたコードの供養ブログ シリーズ。
今日は、<a href="https://ufcpp.net/study/csharp/cheatsheet/ap_ver11/#raw-string">C# 11 で入った生文字列(raw string literals)</a>は、C# には珍しく、空白文字の数や並び順に影響を受けるという話。</p>
<h2><a id="csharp-whitespace">C# と空白文字</a></h2>
<p>C# は空白文字の影響を受けにくい言語仕様になっています。
主に2点。</p>
<ul>
<li>空白の有無によって意味が変わる場所が極めて少ない</li>
<li>全角スペースとかが混入していても ASCII のスペースと同じ扱いをする</li>
</ul>
<p>(C# に限らず、
C 言語の影響を受けて作られた言語で、
Unicode に対応している言語は結構こういう仕様のものが多いはず。)</p>
<h3><a id="existence">空白の有無</a></h3>
<p>「空白の有無」は、<code>A B</code> と <code>AB</code> みたいな単語区切りを除けば、
自分の思いつく限り、意味が変わるのは <code>x +++ y</code> くらいでした。</p>
<pre class="source" title="+++">
<span class="reserved">var</span> <span class="variable">x</span> <span class="operator">=</span> <span class="number">1</span>;
<span class="reserved">var</span> <span class="variable">y</span> <span class="operator">=</span> <span class="number">2</span>;

<span class="reserved">var</span> <span class="variable">z</span> <span class="operator">=</span> <span class="variable">x</span><span class="operator">++</span><span class="operator">+</span><span class="variable">y</span>; <span class="comment">// ここの +++</span>

<span class="static"><span class="type">Console</span></span><span class="operator">.</span><span class="method"><span class="static">WriteLine</span></span>((<span class="variable">x</span>, <span class="variable">y</span>, <span class="variable">z</span>));
</pre>
<p>ちなみに、以下のような差。</p>
<pre class="source" title="++ + と + ++ と + + +">
<span class="reserved">var</span> <span class="variable">z1</span> <span class="operator">=</span> <span class="variable">x</span><span class="operator">++</span> <span class="operator">+</span> <span class="variable">y</span>; <span class="comment">// (x++) + y</span>
<span class="reserved">var</span> <span class="variable">z2</span> <span class="operator">=</span> <span class="variable">x</span> <span class="operator">+</span> <span class="operator">++</span><span class="variable">y</span>; <span class="comment">// x + (++y)</span>
<span class="reserved">var</span> <span class="variable">z3</span> <span class="operator">=</span> <span class="variable">x</span> <span class="operator">+</span> <span class="operator">+</span> <span class="operator">+</span><span class="variable">y</span>; <span class="comment">// x + (+(+y))</span>
<span class="comment">// +++ は ++ + の意味になる。</span>
</pre>
<p>コメントまで含めると <code>//*/</code> と <code>//* /</code> とかも思いつきますが、
すぐに思いついたのはこれだけでした。</p>
<h3><a id="whitespace-category">ASCII 以外の空白文字</a></h3>
<p>C# は割かし全角スペース耐性があります。
C# は「空白かどうか」を Unicode カテゴリーを見て判定しているので、
スペースの半角・全角は問いませんし、なんだったら nbsp (HTML を書いてて時々出てくる「ここで改行しちゃだめ」スペース)とかが混入しても大丈夫です。</p>
<p>正確に言うと、C# の文法では以下の文字が「空白」になっています。</p>
<ul>
<li>Unicode の文字カテゴリーが Zs (Space Separator)の文字</li>
<li>水平タブ(U+0009)</li>
<li>垂直タブ(U+000B)</li>
<li>フォーム フィード(U+000C)</li>
</ul>
<p>ちなみに、Zs の文字は以下の通り。</p>
<ul>
<li>U+0020: space</li>
<li>U+00A0: no-break space</li>
<li>U+1680: ogham space mark (<a href="https://ja.wikipedia.org/wiki/%E3%82%AA%E3%82%AC%E3%83%A0%E6%96%87%E5%AD%97">オガム文字</a>)</li>
<li>
幅違い
<ul>
<li>U+2000: en quad</li>
<li>U+2001: em quad</li>
<li>U+2002: en space</li>
<li>U+2003: em space</li>
<li>U+2004: three-per-em space</li>
<li>U+2005: four-per-em space</li>
<li>U+2006: six-per-em space</li>
<li>U+2007: figure space</li>
<li>U+2008: punctuation space</li>
<li>U+2009: thin space</li>
<li>U+200A: hair space</li>
</ul>
</li>
<li>
幅違い no-break
<ul>
<li>U+202F: narrow no-break space</li>
<li>U+205F: medium matematical space</li>
</ul>
</li>
<li>U+3000: ideographic space (全角スペース)</li>
</ul>
<p>こんな文字は入力する方が大変なんですが…
頑張って入力すると、<a href="https://gist.github.com/ufcpp/3eeebaf3c79c0af2f76336f8e38b3104">以下のようなソースコード</a>が書けたりします。</p>
<pre class="source" title="スペース混在">
<span class="reserved">var</span> <span class="variable">a</span> <span class="operator">=</span> <span class="reserved">new</span>[] {
				<span class="number">0</span>,
<span class="number">1</span>,
<span class="number">2</span>,
    <span class="number">3</span>,
    <span class="number">4</span>,
    <span class="number">5</span>,
    <span class="number">6</span>,
    <span class="number">7</span>,
    <span class="number">8</span>,
    <span class="number">9</span>,
    <span class="number">10</span>,
    <span class="number">11</span>,
    <span class="number">12</span>,
    <span class="number">13</span>,
    <span class="number">14</span>,
    <span class="number">15</span>,
    <span class="number">16</span>,
    <span class="number">17</span>,
    <span class="number">18</span>,
　　　　<span class="number">19</span>,
};
</pre>
<p>入力も大変なら、Visual Studio みたいな IDE は自動整形機能でごっそり全部、消すか、通常のスペース(U+0020)に置き換えてくれるので、
この変なソースコードを維持するのもそれなりに大変です。</p>
<p>ちなみに今回は、以下のコードでコード生成しました。</p>
<pre class="source" title="スペース混在コード生成">
<span class="reserved">using</span> <span class="reserved">var</span> <span class="variable">f</span> <span class="operator">=</span> <span class="reserved">new</span> <span class="type">StreamWriter</span>(<span class="string">&quot;a.cs&quot;</span>);

<span class="reserved">var</span> <span class="variable">ws</span> <span class="operator">=</span> <span class="reserved">new</span>[] { <span class="number">0x0009</span>, <span class="number">0x000B</span>, <span class="number">0x000C</span>, <span class="number">0x20</span>, <span class="number">0xA0</span>, <span class="number">0x1680</span>, <span class="number">0x2000</span>, <span class="number">0x2001</span>, <span class="number">0x2002</span>, <span class="number">0x2003</span>, <span class="number">0x2004</span>, <span class="number">0x2005</span>, <span class="number">0x2006</span>, <span class="number">0x2007</span>, <span class="number">0x2008</span>, <span class="number">0x2009</span>, <span class="number">0x200A</span>, <span class="number">0x202F</span>, <span class="number">0x205F</span>, <span class="number">0x3000</span> }<span class="operator">.</span><span class="method">Select</span>(<span class="variable local">i</span> <span class="operator">=&gt;</span> (<span class="reserved">char</span>)<span class="variable local">i</span>)<span class="operator">.</span><span class="method">ToArray</span>();

<span class="variable">f</span><span class="operator">.</span><span class="method">WriteLine</span>(<span class="string">&quot;&quot;&quot;
    var a = new[] {
    &quot;&quot;&quot;</span>);

<span class="control">for</span> (<span class="reserved">int</span> <span class="variable">i</span> <span class="operator">=</span> <span class="number">0</span>; <span class="variable">i</span> <span class="operator">&lt;</span> <span class="variable">ws</span><span class="operator">.</span><span class="property">Length</span>; <span class="variable">i</span><span class="operator">++</span>)
{
    <span class="reserved">var</span> <span class="variable">w</span> <span class="operator">=</span> <span class="variable">ws</span>[<span class="variable">i</span>];
    <span class="variable">f</span><span class="operator">.</span><span class="method">WriteLine</span>(<span class="string">$&quot;</span>{<span class="variable">w</span>}{<span class="variable">w</span>}{<span class="variable">w</span>}{<span class="variable">w</span>}{<span class="variable">i</span>}<span class="string">,</span><span class="string">&quot;</span>);
}

<span class="variable">f</span><span class="operator">.</span><span class="method">WriteLine</span>(<span class="string">&quot;&quot;&quot;
    };
    &quot;&quot;&quot;</span>);
</pre>
<h2><a id="raw-string">raw string と空白文字</a></h2>
<p>C# についてまとめると以下の通り。</p>
<ul>
<li>空白文字の種類に影響を受けることはない</li>
<li>空白文字の有無や個数、順序に影響を受けることもほとんどない</li>
<li>Visual Studio が軒並み整形してしまうので、U+0020 (通常のスペース)以外の空白文字は維持するのも難しい</li>
</ul>
<p>ところで、C# 11 では以下のような「<a href="https://ufcpp.net/study/csharp/st_string.html?p=2#multiline-indent">複数行文字列リテラル</a>」を書けるようになりました。</p>
<pre class="source" title="生文字列で複数行文字列リテラルを書く例">
<span class="reserved">var</span> <span class="variable">raw</span> <span class="operator">=</span> <span class="string">&quot;&quot;&quot;
    raw string literals (生文字列リテラル)
    | ← ここよりも左側にあるインデントは無視される。
    ここまでがリテラル。
    &quot;&quot;&quot;</span>; <span class="comment">// この「閉じ引用符」行のインデントが基準。</span>

<span class="type"><span class="static">Console</span></span><span class="operator">.</span><span class="method"><span class="static">WriteLine</span></span>(<span class="variable">raw</span>); <span class="comment">// 「raw」から始まる。「    raw」にはならない。末尾も改行は入らない。</span>
</pre>
<p>ここでちょっと好奇心を働かせます。
空白文字を混在させたときの扱いはどうなるんだろう？</p>
<p>試してみると、コンパイル エラーでした。
CS9003「閉じ行と異なる空白を含んでいます」エラー。</p>
<pre class="source" title="異なる空白文字を使うとコンパイル エラー">
<span class="reserved">_</span> <span class="operator">=</span> <span class="string">&quot;&quot;&quot;
<span class="error" title="CS9003">　　　　</span>全角スペース4つ。
    &quot;&quot;&quot;</span>; <span class="comment">// スペース4つ。</span>
</pre>
<pre class="source" title="1個だけ変えてもダメ">
<span class="reserved">_</span> <span class="operator">=</span> <span class="string">&quot;&quot;&quot;
<span class="error" title="CS9003">   　</span>4つ中1個だけ全角。
    &quot;&quot;&quot;</span>; <span class="comment">// スペース4つ。</span>
</pre>
<p>おっ？異なる文字がダメということは？
もしや？…</p>
<pre class="source" title="順序まで完全一致していればOK！">
<span class="reserved">_</span> <span class="operator">=</span> <span class="string">&quot;&quot;&quot;
　 	 　全角、半角、タブ、半角、全角。
　 	 　&quot;&quot;&quot;</span>; <span class="comment">// 全角、半角、タブ、半角、全角。</span>
</pre>
<p>混在していても、順序を含めて完全に一致していればコンパイルできるみたいです。</p>
<p>じゃあ、こんな感じで…</p>
<pre class="source" title="空白文字全部入りコード生成">
<span class="reserved">using</span> <span class="reserved">var</span> <span class="variable">f</span> <span class="operator">=</span> <span class="reserved">new</span> <span class="type">StreamWriter</span>(<span class="string">&quot;a.cs&quot;</span>);

<span class="reserved">var</span> <span class="variable">ws</span> <span class="operator">=</span> <span class="reserved">new</span>[] { <span class="number">0x0009</span>, <span class="number">0x000B</span>, <span class="number">0x000C</span>, <span class="number">0x20</span>, <span class="number">0xA0</span>, <span class="number">0x1680</span>, <span class="number">0x2000</span>, <span class="number">0x2001</span>, <span class="number">0x2002</span>, <span class="number">0x2003</span>, <span class="number">0x2004</span>, <span class="number">0x2005</span>, <span class="number">0x2006</span>, <span class="number">0x2007</span>, <span class="number">0x2008</span>, <span class="number">0x2009</span>, <span class="number">0x200A</span>, <span class="number">0x202F</span>, <span class="number">0x205F</span>, <span class="number">0x3000</span> }<span class="operator">.</span><span class="method">Select</span>(<span class="variable local">i</span> <span class="operator">=&gt;</span> (<span class="reserved">char</span>)<span class="variable local">i</span>)<span class="operator">.</span><span class="method">ToArray</span>();
<span class="reserved">var</span> <span class="variable">w</span> <span class="operator">=</span> <span class="reserved">string</span><span class="operator">.</span><span class="static"><span class="method">Join</span></span>(<span class="string">&quot;&quot;</span>, <span class="variable">ws</span>);

<span class="variable">f</span><span class="operator">.</span><span class="method">WriteLine</span>(<span class="string">$&quot;&quot;&quot;&quot;
</span><span class="string">    _ = &quot;&quot;&quot;
    </span>{<span class="variable">w</span>}<span class="string">abc
    </span>{<span class="variable">w</span>}<span class="string">&quot;&quot;&quot;;</span><span class="string">
    &quot;&quot;&quot;&quot;</span>);
</pre>
<p>どうかな？</p>
<pre class="source" title="空白文字全部入り(コンパイルできる)">
<span class="reserved">_</span> <span class="operator">=</span> <span class="string">&quot;&quot;&quot;
	                　abc
	                　&quot;&quot;&quot;</span>;
</pre>
<p>コンパイルできる！</p>
<p>そして、どうも現状 (Visual Studio 17.5 時点) で、
この raw string のインデント部分の自動整形はしないみたいです。
(<a href="https://github.com/dotnet/roslyn/issues/64237">下手に整形するとさっきの CS9003 エラーの原因になる</a>ので。)</p>
<p>まあ、こんなコード入力するの自体困難なコードで問題を起こす愉快犯もそうそういないと思いますが。</p>
<p>C# らしからぬ、</p>
<ul>
<li>空白の順序に意味がある</li>
<li>Visual Studio に自動整形されない</li>
</ul>
<p>というのが珍しかったという話になります。</p>
<h2><a id="symbol-font">余談: 謎の記号</a></h2>
<p>ところで、先ほどのコード、Visual Studio で開くとこんな感じ:</p>
<p><img src="/media/1214/malefemale.png" alt="謎の♂♀" /></p>
<p>なぜか♂♀記号が…</p>
<p>気になっていろいろ試してみたところ、
制御文字全般謎の記号に置き換わりました。
0～0x20 までの文字を書き込んで Visual Studio で開くと以下のような感じ。</p>
<p><img src="/media/1215/controlecharinvs.png" alt="0～0x20" /></p>
<p>以下のような話かも？</p>
<ul>
<li>「空白を表示」をオンにしたときに、スペースとタブの代わりに ‣ と • を表示している辺りのロジックが悪さをしている？</li>
<li>一部は<a href="https://en.wikipedia.org/wiki/Code_page_437">CP437</a>の文字が表示されてる</li>
</ul>
<p>どうでもいいものの一応はバグ報告:</p>
<ul>
<li>Visual Studio Developer Community に: <a href="https://developercommunity.visualstudio.com/t/Visual-Studio-IDE-displays-ASCII-control/10156578">10156578</a></li>
</ul>
<p>まあ報告しておいてなんですけども、優先度付かないでしょうね、こんなの。</p>
 ]]></description>
				<pubDate>Thu, 01 Dec 2022 23:40:04 +0900</pubDate>
			</item>
			<item>
				<title>Visual Studio の .NET Core 化まだー？</title>
				<link>http://ufcpp.net/blog/2022/11/vsnetfx/</link>
				<description><![CDATA[ <p><a href="https://www.youtube.com/@ufcppdotnet">C# 配信</a>でちょくちょく出てくる話題の1つに</p>
<p>「Visual Studio (for Windows)はいまだに .NET Framework だから」</p>
<p>というものがあります。
もちろん、「.NET Core 化はよ」みたいな文脈です。</p>
<p>Visual Studio は .NET 製アプリの中でも大規模なものの1つなわけで、ドッグフーディング的な意味で早く .NET Core 化してほしいというのもありますし。</p>
<p>.NET Framework → .NET 5 → .NET 6 → .NET 7 と、毎度2・3割は速くなってるというベンチマークがあるわけで合計すると2倍以上速いかもしれず、
普通にパフォーマンス上の理由でも早く .NET Core 系になってほしかったりもします。</p>
<p>そしてもう1個、
実は <em>.NET Framework の方は Unicode 8.0 で止まっている</em>という話があったり。</p>
<h2>C# の lexer/parser は .NET ランタイム依存</h2>
<p>C# では、空白文字とか識別子に使える文字とかの定義に Unicode の文字カテゴリーを使っています。</p>
<ul>
<li>言語仕様: 6 Lexical structure / <a href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/lexical-structure#643-identifiers">6.4.3 Identifiers</a></li>
<li>うちのサイト内の解説: <a href="https://ufcpp.net/study/csharp/misc_identifier.html">識別子名に使える文字</a></li>
</ul>
<p>そして、<a href="https://github.com/dotnet/roslyn">C# コンパイラー自身が C# 製</a>になって以来、
カテゴリー判定には普通に .NET の <a href="https://learn.microsoft.com/ja-jp/dotnet/api/system.char.getunicodecategory"><code>GetUnicodeCategory</code></a> を使っています。</p>
<p>そして、
「Visual Studio は .NET Framework 動作」
と「.NET Framework は Unicode 8.0 止まり」
のコンボで、
Visual Studio 上でだけコンパイルできないコードが割かし簡単に書けたりします。</p>
<h2>C# 9.0 以降に追加された letter</h2>
<p>C# で識別子に使える文字は、まあかなり端折って言うと、いわゆる letter と言われる文字です。</p>
<p>で、Unicode の各バージョンで追加された文字は、 <a href="https://unicode.org/Public/UNIDATA/">unicode.org 内の各種データ置き場</a> の <a href="https://unicode.org/Public/UNIDATA/DerivedAge.txt">DerivedAge.txt</a> とかで調べられます。</p>
<p>ちょっと Unicode 8.0 から 14.0 まで1文字ずつそれっぽい letter を適当に拾って…</p>
<ul>
<li>Unicode 8.0: ᏸ U+13F8, Cherokee Small Letter Ye</li>
<li>Unicode 9.0: Ɪ U+A7AE, Small Captital I</li>
<li>Unicode 10.0: ৼ U+09FC, Bengali Letter Vedic Anusvara</li>
<li>Unicode 11.0: ՠ U+0560, Armenian Small Letter Turned Ayb</li>
<li>Unicode 12.0: Ꞻ U+A7BA, Latin Capital Letter Glottal A</li>
<li>Unicode 13.0: ഄ U+0D04, Malayalam Letter Vedic Anusvara</li>
<li>Unicode 14.0: ౝ U+0C5D, Telugu Letter Nakaara Pollu</li>
</ul>
<p>これを、こうじゃ:</p>
<pre class="source" title="Unicode 8.0 以降に追加された letter">
<span class="comment">// Unicode 8.0</span>
<span class="reserved">int</span> <span class="variable">ᏸ</span> <span class="operator">=</span> <span class="number">8</span>; <span class="comment">// U+13F8, Cherokee Small Letter Ye</span>

<span class="comment">// Unicode 9.0</span>
<span class="reserved">int</span> <span class="variable">Ɪ</span> <span class="operator">=</span> <span class="number">9</span>; <span class="comment">// U+A7AE, Small Captital I</span>

<span class="comment">// Unicode 10.0</span>
<span class="reserved">int</span> <span class="variable">ৼ</span> <span class="operator">=</span> <span class="number">10</span>; <span class="comment">// U+09FC, Bengali Letter Vedic Anusvara</span>

<span class="comment">// Unicode 11.0</span>
<span class="reserved">int</span> <span class="variable">ՠ</span> <span class="operator">=</span> <span class="number">11</span>; <span class="comment">// U+0560, Armenian Small Letter Turned Ayb</span>

<span class="comment">// Unicode 12.0</span>
<span class="reserved">int</span> <span class="variable">Ꞻ</span> <span class="operator">=</span> <span class="number">12</span>; <span class="comment">// U+A7BA, Latin Capital Letter Glottal A</span>

<span class="comment">// Unicode 13.0</span>
<span class="reserved">int</span> <span class="variable">ഄ</span> <span class="operator">=</span> <span class="number">13</span>; <span class="comment">// U+0D04, Malayalam Letter Vedic Anusvara</span>

<span class="comment">// Unicode 14.0</span>
<span class="reserved">int</span> <span class="variable">ౝ</span> <span class="operator">=</span> <span class="number">14</span>; <span class="comment">// U+0C5D, Telugu Letter Nakaara Pollu</span>

<span class="type"><span class="static">Console</span></span><span class="operator">.</span><span class="method"><span class="static">WriteLine</span></span>(<span class="variable">ᏸ</span> <span class="operator">+</span> <span class="variable">Ɪ</span> <span class="operator">+</span> <span class="variable">ৼ</span> <span class="operator">+</span> <span class="variable">ՠ</span> <span class="operator">+</span> <span class="variable">Ꞻ</span> <span class="operator">+</span> <span class="variable">ഄ</span> <span class="operator">+</span> <span class="variable">ౝ</span>);</pre>
<p>(ちなみに C# コンパイラーっていまだに<a href="https://ja.wikipedia.org/wiki/Unicode#%E3%82%B5%E3%83%AD%E3%82%B2%E3%83%BC%E3%83%88%E3%83%9A%E3%82%A2">サロゲートペア</a>に対応していないので、<a href="https://ja.wikipedia.org/wiki/%E5%9F%BA%E6%9C%AC%E5%A4%9A%E8%A8%80%E8%AA%9E%E9%9D%A2">BMP</a> 内で当該文字を探さないといけないんですが。
見ての通り、最近でも BMP への文字追加が意外とたくさんあります。)</p>
<p>これをエディターで開いてみましょう。</p>
<p><img src="/media/1213/uc9ident.png" alt="Visual Studio for Windows (左)と VS Code (右)" /></p>
<p>左が Visual Studio for Windows、右が VS Code。
.NET Framework が Unicode 8.0 で止まっている証拠の1つとなります。</p>
<p>ちなみに、 .NET SDK のバージョンによってもどこまでコンパイルできるか変わるはずです。
確か、 .NET 6 は Unicode 13.0 なので、 ౝ (U+0C5D、Unicode 14 での追加)はコンパイルできないと思います。</p>
<h2>おまけ: 対 Visual Studio 専用ホモグラフ攻撃</h2>
<p>ほんとたまたまで、
「DerivedAge.txt を眺めてて各バージョン最初に目に入った letter っぽい文字」
を選んだだけなんですが…</p>
<p><em>Ɪ と ՠ の2文字、ASCII 文字と似てて<a href="https://ja.wikipedia.org/wiki/%E3%83%9B%E3%83%A2%E3%82%B0%E3%83%A9%E3%83%95%E6%94%BB%E6%92%83">ホモグラフ攻撃</a>できそうじゃない…</em></p>
<pre class="source" title="おもむろに謎のクラスを1つ定義">
<span class="reserved">class</span> <span class="type">Ɪՠage</span> { }
</pre>
<p>この <code>Ɪՠage</code> クラス、最初の2文字が先ほどの Ɪ (U+A7AE)と ՠ (U+0560)です。</p>
<p>これ、たぶん、CI とかも通っちゃうんですよね。
これがコンパイルできないのは本当に Visual Studio for Windows だけ…</p>
 ]]></description>
				<pubDate>Sun, 27 Nov 2022 21:56:06 +0900</pubDate>
			</item>
			<item>
				<title>共変配列事故</title>
				<link>http://ufcpp.net/blog/2022/11/covariantarrayincident/</link>
				<description><![CDATA[ <p>またちょっと Gist に書き捨ててたコードが増えてきたので供養ブログをしばらく書いていこうかと。</p>
<p>(今年はまだ少な目。一人アドベントカレンダーな量にはならず。)</p>
<h2>配列の共変性</h2>
<p>悪名高いんですが、C# のというか、.NET の配列は<a href="https://ufcpp.net/study/csharp/sp4_variance.html?p=2#covariant-array">共変</a>だったりします。</p>
<pre class="source" title="配列の共変性">
<span class="comment">// ↓.NET 的に許されていはいるものの、 items[0] = new Base(); が例外を起こすので今となってはあんまり使いたくない機能。</span>
<span class="comment">// 意図的に使うことはめったにないものの…</span>
<span class="type">Base</span>[] <span class="variable">items</span> <span class="operator">=</span> <span class="reserved">new</span> <span class="type">Derived</span>[<span class="number">1</span>];

<span class="comment">// これは問題ない</span>
<span class="variable">items</span>[<span class="number">0</span>] <span class="operator">=</span> <span class="reserved">new</span> <span class="type">Derived</span>();

<span class="comment">// これも問題ない。 Base に Derived を代入するのは安全。</span>
<span class="type">Base</span> <span class="variable">item</span> <span class="operator">=</span> <span class="variable">items</span>[<span class="number">0</span>];

<span class="comment">// これがダメ。</span>
<span class="comment">// 実行時例外が出る。</span>
<span class="variable">items</span>[<span class="number">0</span>] <span class="operator">=</span> <span class="reserved">new</span> <span class="type">Base</span>();

<span class="reserved">class</span> <span class="type">Base</span> { }
<span class="reserved">class</span> <span class="type">Derived</span> : <span class="type">Base</span> { }
</pre>
<p>実行時例外出ることわかってるんだからコンパイル時に禁止しろと…
(みんな言ってる。何度でも言ってる。)</p>
<p><code>IEnumerable&lt;T&gt;</code> や <code>ReadOnlySpan&lt;T&gt;</code> がある現在では本当に意味不明な仕様なんですが、
まあ、 .NET の最初期(.NET Framework 1.0)の頃はジェネリクスすらなかったので、
やむなくこんな仕様を入れたんだと思います。</p>
<p>ちなみに、実のところ Java も配列が共変で、.NET はそれに右に倣えな感じは多少あります(初期にジェネリクスがなかったのも共通)。</p>
<h2>事故発生</h2>
<p>まあ、この仕様は昔の名残丸出しの気持ち悪い仕様なので、意図的に使うことはほとんどないんですが。
時々事故るんですよねぇ。</p>
<p><code>Base[] items = new Derived[1];</code> とかいうわかりやすいコードならやらないのであって、
型推論が絡むと時々間違っちゃう。</p>
<pre class="source" title="型推論の過程でやらかし">
<span class="comment">// 配列の型推論はソース側(右辺側)からしかやらない。</span>
<span class="comment">// となると…</span>
<span class="type">Base</span>[] <span class="variable">items</span> <span class="operator">=</span> <span class="reserved">new</span>[] { <span class="reserved">new</span> <span class="type">Derived</span>() };

<span class="comment">// 1. new[]{} の中身が Derived である</span>
<span class="comment">// 2. 中身からの型推論で、右辺の型は Derived[] になる</span>
<span class="comment">// 3. Base[] に Derive[] を代入(共変)している</span>

<span class="comment">// はい、アウト。実行時例外が出る。</span>
<span class="variable">items</span>[<span class="number">0</span>] <span class="operator">=</span> <span class="reserved">new</span> <span class="type">Base</span>();

<span class="reserved">class</span> <span class="type">Base</span> { }
<span class="reserved">class</span> <span class="type">Derived</span> : <span class="type">Base</span> { }
</pre>
<p>数年に1度はやっちゃう…</p>
<p>ちなみに今年やったのはもうちょっと複雑で、要点を抜き出すと以下のようなコードでした。</p>
<pre class="source" title="気づきにくい共変配列バグ">
<span class="reserved">var</span> <span class="variable">testData</span> <span class="operator">=</span> <span class="reserved">new</span>[]
{
    <span class="comment">// たくさん new A() が並んでる。</span>
    <span class="reserved">new</span> <span class="type">A</span>
    {
        <span class="field">Child</span> <span class="operator">=</span> <span class="reserved">new</span>()
        {
            <span class="field">Items</span> <span class="operator">=</span> <span class="reserved">new</span>[] <span class="comment">// これの推論結果は Base[] なのでセーフ。</span>
            {
                <span class="reserved">new</span> <span class="type">Base</span>(), <span class="reserved">new</span> <span class="type">Derived</span>(),
            },
        },
    },
    <span class="reserved">new</span> <span class="type">A</span>
    {
        <span class="field">Child</span> <span class="operator">=</span> <span class="reserved">new</span>()
        {
            <span class="field">Items</span> <span class="operator">=</span> <span class="reserved">new</span>[] <span class="comment">// これが Derived[] になってアウト。</span>
            {
                <span class="reserved">new</span> <span class="type">Derived</span>(), <span class="reserved">new</span> <span class="type">Derived</span>(),
            },
        },
    },
    <span class="comment">// たくさん new A() が並んでる。</span>
};

<span class="comment">// いろいろあって最終的に B.Items が Deserialize に渡る。</span>
<span class="comment">// こっちは平気だけど…</span>
<span class="type">Serializer</span><span class="operator">.</span><span class="static"><span class="method">Deserialize</span></span>(<span class="variable">testData</span>[<span class="number">0</span>]<span class="operator">.</span><span class="field">Child</span><span class="operator">!</span><span class="operator">.</span><span class="field">Items</span><span class="operator">!</span>);

<span class="comment">// こっちは実行時例外起こす。</span>
<span class="type">Serializer</span><span class="operator">.</span><span class="static"><span class="method">Deserialize</span></span>(<span class="variable">testData</span>[<span class="number">1</span>]<span class="operator">.</span><span class="field">Child</span><span class="operator">!</span><span class="operator">.</span><span class="field">Items</span><span class="operator">!</span>);

<span class="reserved">class</span> <span class="type">Serializer</span>
{
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">Deserialize</span></span>&lt;<span class="type param">T</span>&gt;(<span class="type param">T</span>[] <span class="variable local">value</span>)
    {
        <span class="comment">// ちなみに、共変配列が来てるとここの Span へのキャストのタイミングで実行時例外。</span>
        <span class="static"><span class="method">Deserialize</span></span>((<span class="type struct">Span</span>&lt;<span class="type param">T</span>&gt;)<span class="variable local">value</span>);
    }

    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="method"><span class="static">Deserialize</span></span>&lt;<span class="type param">T</span>&gt;(<span class="type struct">Span</span>&lt;<span class="type param">T</span>&gt; <span class="variable local">value</span>)
    {
        <span class="control">foreach</span> (<span class="reserved">ref</span> <span class="reserved">var</span> <span class="variable">x</span> <span class="control">in</span> <span class="variable local">value</span>)
        {
            <span class="comment">// x = ...</span>
        }
    }
}

<span class="reserved">class</span> <span class="type">A</span> { <span class="reserved">public</span> <span class="type">B</span><span class="operator">?</span> <span class="field">Child</span>; }
<span class="reserved">class</span> <span class="type">B</span> { <span class="reserved">public</span> <span class="type">Base</span>[]<span class="operator">?</span> <span class="field">Items</span>; }

<span class="reserved">class</span> <span class="type">Base</span> { }
<span class="reserved">class</span> <span class="type">Derived</span> : <span class="type">Base</span> { }
</pre>
<p>来年には入るかもと目されている<a href="https://ufcpp.net/blog/2021/12/collection-literal/">コレクション リテラル</a>ではこんな問題起こさないように設計されていそうで。
この時ばかりはかなり本気で、一刻も早くコレクション リテラルに来てほしいと思いました。</p>
 ]]></description>
				<pubDate>Thu, 24 Nov 2022 23:50:02 +0900</pubDate>
			</item>
			<item>
				<title>Blazor Wasm 実動作デモはじめました</title>
				<link>http://ufcpp.net/blog/2022/10/blazorwasmdemo/</link>
				<description><![CDATA[ <p>昔、うちのサイトのページ内に iframe で張り付けとくような実動作デモを<a href="https://github.com/ufcpp/UfcppSample/tree/master/Chapters/ufcpp2000/csharp/source">いろいろと Silverlight 作ってた</a>んですが、
Silverlight のサポート終了後、移行先がなくてほったらかしになっていました。</p>
<p>「<a href="https://github.com/ufcpp/UfcppSample/labels/%E3%81%9D%E3%81%AE%E6%99%82%E3%81%8C%E6%9D%A5%E3%81%9F%E3%82%89%E6%9C%AC%E6%B0%97%E5%87%BA%E3%81%99">その時が来たら本気出す</a>」とかいう雑なタグをつけて放置してたんですが、
そろそろ <a href="https://learn.microsoft.com/ja-jp/aspnet/core/blazor/#blazor-webassembly">Blazor WebAssembly</a> 化でもしてみようかという感じで数年越しに作業する気になり。</p>
<p>とりあえず、ソートのページで使っていたソートの可視化プログラムを移植。</p>
<ul>
<li><a href="https://ufcpp.net/study/algorithm/sort.html#demo">ソート概要</a></li>
<li><a href="https://ufcpp.net/study/algorithm/sort_bubble.html#abstract">バブルソート</a></li>
<li><a href="https://ufcpp.net/study/algorithm/sort_quick.html#abstract">クイックソート</a></li>
<li>(他、一通りのソートのページに)</li>
</ul>
<p>移植というか、もう完全に忘れてるし、なんだったら思い立った瞬間には昔のコードをどこに置いたかわからなくなっていたので1から作ったんですが。</p>
<ul>
<li>ソースコード: <a href="https://github.com/ufcpp/StaticWebApps/tree/main/BlazorWasm/SortVisualizer">SortVisualizer</a></li>
<li><a href="https://azure.microsoft.com/ja-jp/products/app-service/static/">Static Web App</a> のデプロイ先: <a href="https://black-ocean-009cb0000.2.azurestaticapps.net/">https://black-ocean-009cb0000.2.azurestaticapps.net/</a></li>
</ul>
<p>実物 iframe (クイックソート単品):</p>
<div><iframe src="https://black-ocean-009cb0000.2.azurestaticapps.net/?a=quick&i=0&s=0&w=300" width="304" height="332"></iframe></div>
<p>実物 iframe (一覧):</p>
<div><iframe src="https://black-ocean-009cb0000.2.azurestaticapps.net/?i=0&s=0&w=150" width="780" height="500"></iframe></div>
<p><code>&lt;span style=&quot;witdh: ...; height: ...&quot; /&gt;</code> とかでバーを表示するという雑なことやっても、
スマホとかで表示しても結構ちゃんと動いていてほんと富豪的…</p>
<p>まあさらっとやってさらっと動いたので、
他にも何かしらこの手の実動作デモがページ内にあるとよさげなものがあれば作ろうかなという気分になっています。
(何かいいものがあれば。)</p>
 ]]></description>
				<pubDate>Mon, 31 Oct 2022 22:14:02 +0900</pubDate>
			</item>
			<item>
				<title>.NET 7 Preview 7 で、C# 11 の機能が一通りそろったみたい</title>
				<link>http://ufcpp.net/blog/2022/8/net7p7/</link>
				<description><![CDATA[ <p>久々のブログになります。
C# 11 の機能追加があるたびに <a href="https://www.youtube.com/c/ufcppdotnet">YouTube 配信</a>ではちょくちょく紹介していましたが、
こっちではかなりの久々。</p>
<p>そういえば去年とかは新しい Preview が出るたびに「今回はこの機能が実装されたよ」一覧くらいはブログに書いてたなと思いつつ。
まあ、今年は早い段階から「<a href="https://ufcpp.net/study/csharp/cheatsheet/ap_ver11/">C# 11.0 の新機能</a>」の方を埋める作業をしているので、何もしてなかったわけでもないんですが。
ちなみに、「<a href="https://ufcpp.net/study/csharp/cheatsheet/ap_ver11/">C# 11.0 の新機能</a>」の方は現在、
<a href="https://github.com/ufcpp/UfcppSample/issues/387">進捗 12/19</a> です。</p>
<h2>.NET 7 Preview 7 での C</h2>
<p>しばらくブログとしては書いてなかった Preview 版の紹介を、今回久々に書いているのは、
.NET 7 Preview 7 で、</p>
<ul>
<li>予定されている C# 11 の機能が一通り全部入った。今ないものは RC/GA でもない</li>
<li><code>LangVersion</code> に <code>preview</code> を指定しなくても (net7.0 ターゲットならデフォルトで) C# 11 が使えるようになった</li>
</ul>
<p>という2点から。</p>
<p>去年どうでしたっけ。.NET 6 では RC 1 のタイミングで <code>preview</code> が外れてたような…</p>
<h3>C# 11 最終版</h3>
<p>とりあえず、<a href="https://github.com/dotnet/roslyn/pull/63010">Language Feature Status では一通り「11」の機能がそろいました</a>。
まあ、一部、ちょっと修正が入りそうな部分はありますが、大まかな機能としてはもう変更はなさそうな雰囲気です。</p>
<p>「ちょっとした修正」も、例えば以下のようなバグの修正みたいなレベルの話です。</p>
<pre class="source" title="Preview 7 だと挙動が怪しいやつの例">
<code><span class="reserved">unsafe</span>
{
    <span class="comment">// ref フィールドを持ってる構造体、 .NET 7 Preview 7 では managed 扱いされないバグがあるみたい。</span>
    <span class="comment">// (ガベコレ的にまずいコード。)</span>
    <span class="reserved">var</span> <span class="variable">a</span> <span class="operator">=</span> <span class="reserved">stackalloc</span> <span class="type struct">RefInt</span>[<span class="number">4</span>];
}

<span class="reserved">ref</span> <span class="reserved">struct</span> <span class="type struct">RefInt</span>
{
    <span class="reserved">public</span> <span class="reserved">ref</span> <span class="reserved">int</span> <span class="field">Reference</span>;
}
</code></pre>
<h3>preview 外れた</h3>
<p>とりあえず、<code>TargetFramework</code> が <code>net7.0</code> なプロジェクトは <code>LangVersion</code> を書かなくても C# 11 になります。
あと、<code>LangVersion</code> を <code>latest</code> とかにしているプロジェクトでも C# 11 になります。</p>
<p>注意点として、今回、「<code>net6.0</code> と C# 11」みたいな組み合わせにするとちょっと問題を起こすような破壊的変更があったりします。
以下のようなやつで、まあ、めったに踏むようなコードでもないとは思いますが、一応。</p>
<pre class="source" title="net6.0 + C# 11 でだけ問題を起こすコードの例">
<code><span class="reserved">using</span> System<span class="operator">.</span>Runtime<span class="operator">.</span>InteropServices;

<span class="reserved">public</span> <span class="reserved">struct</span> <span class="type struct">Buffer</span>
{
    <span class="reserved">private</span> <span class="reserved">int</span> <span class="field">_item0</span>;

    <span class="comment">// net7.0 なら問題なくコンパイルできる。</span>
    <span class="comment">// net6.0 + C# 10 でも問題なくコンパイルできる。</span>
    <span class="comment">// net6.0 + C# 11 だとコンパイルエラーになるので注意。</span>
    <span class="reserved">public</span> <span class="type struct">Span</span>&lt;<span class="reserved">int</span>&gt; <span class="method">AsSpan</span>() <span class="operator">=&gt;</span> <span class="type">MemoryMarshal</span><span class="operator">.</span><span class="method">CreateSpan</span>(<span class="reserved">ref</span> <span class="field">_item0</span>, <span class="number">1</span>);
}
</code></pre> ]]></description>
				<pubDate>Sat, 13 Aug 2022 11:56:03 +0900</pubDate>
			</item>
			<item>
				<title>C# でキーワードをできるだけ多く並べる遊び</title>
				<link>http://ufcpp.net/blog/2022/5/consecutive-keywords/</link>
				<description><![CDATA[ <p>以下のコード、有効な(エラーなくコンパイルできる) C# コードの一部です。</p>
<p><img src="/media/1212/consecutivekeywords.png" alt="青いなぁ" /></p>
<h2>きっかけ</h2>
<p>Twitter でこんなのを見かけて。</p>
<div>
<blockquote class="twitter-tweet"><p lang="en" dir="ltr">Can you think of a valid C# program containing 16 keywords in a row, where at least half of them are all different?</p>&mdash; Kirill Osenkov 🇺🇦 (@KirillOsenkov) <a href="https://twitter.com/KirillOsenkov/status/1529288974757339136?ref_src=twsrc%5Etfw">May 25, 2022</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
</div>
<p>雑に翻訳:</p>
<blockquote>
<p>有効な C# プログラムで1行に16キーワード並べられる？少なくともそのうち半分は異なるキーワードとして。</p>
</blockquote>
<p>その後の返信から、</p>
<ul>
<li>連続したキーワードのみ(<code>&lt;</code> とかの記号が間に挟まってるのはダメ)</li>
<li><a href="https://ufcpp.net/blog/2021/2/lexicalkeywords/">文脈キーワード</a>はあり</li>
</ul>
<p>とのこと。</p>
<h2>書いたコード</h2>
<p>試しに色々考えてみたところ、「半分は異なる」どころか、「全部異なる」でも20個超えれることが判明。</p>
<p>Gist に全体像:</p>
<ul>
<li><a href="https://gist.github.com/ufcpp/93caaa4f7652846b1f68fe687ef2d5d5">ConsecutiveKeywords.cs</a></li>
</ul>
<p>キーワードが連続しているのは以下の部分。</p>
<p>とりあえず重複を許容して62個、44種並べられたもの:</p>
<pre class="source" title="キーワードを並べられるだけ並べた物(重複を許容して62個、44種)">
<code><span class="reserved">in</span> <span class="reserved">await</span> <span class="reserved">value</span> <span class="reserved">is</span> <span class="reserved">not</span> <span class="reserved">bool</span> <span class="reserved">or</span> <span class="reserved">char</span> <span class="reserved">or</span> <span class="reserved">byte</span> <span class="reserved">or</span> <span class="reserved">sbyte</span> <span class="reserved">or</span> <span class="reserved">short</span>
<span class="reserved">or</span> <span class="reserved">ushort</span> <span class="reserved">or</span> <span class="reserved">int</span> <span class="reserved">or</span> <span class="reserved">uint</span> <span class="reserved">or</span> <span class="reserved">nint</span> <span class="reserved">or</span> <span class="reserved">nuint</span> <span class="reserved">or</span> <span class="reserved">long</span> <span class="reserved">or</span> <span class="reserved">ulong</span> <span class="reserved">or</span>
<span class="reserved">float</span> <span class="reserved">or</span> <span class="reserved">double</span> <span class="reserved">or</span> <span class="reserved">decimal</span> <span class="reserved">or</span> <span class="reserved">string</span> <span class="reserved">and</span> <span class="reserved">var</span> <span class="reserved">_</span> <span class="reserved">as</span> <span class="reserved">dynamic</span> <span class="reserved">as</span>
<span class="reserved">object</span> <span class="reserved">on</span> <span class="reserved">false</span> <span class="reserved">equals</span> <span class="reserved">null</span> <span class="reserved">where</span> <span class="reserved">this</span> <span class="reserved">orderby</span> <span class="reserved">default</span> <span class="reserved">ascending</span>
<span class="reserved">orderby</span> <span class="reserved">null</span> <span class="reserved">descending</span> <span class="reserved">group</span> <span class="reserved">null</span> <span class="reserved">by</span> <span class="reserved">static</span> <span class="reserved">ref</span> <span class="reserved">readonly</span> <span class="reserved">global</span>
</code></pre>
<p>これ、多少インデントをまともに整形すると以下のようなコードです。</p>
<pre class="source" title="上記コードを整形">
<code><span class="reserved">from</span> x <span class="reserved">in</span> <span class="reserved">value</span>
<span class="reserved">join</span> y
    <span class="reserved">in</span> <span class="reserved">await</span> <span class="reserved">value</span>
        <span class="reserved">is</span> <span class="reserved">not</span> <span class="reserved">bool</span> <span class="reserved">or</span> <span class="reserved">char</span> <span class="reserved">or</span> <span class="reserved">byte</span> <span class="reserved">or</span> <span class="reserved">sbyte</span> <span class="reserved">or</span> <span class="reserved">short</span>
            <span class="reserved">or</span> <span class="reserved">ushort</span> <span class="reserved">or</span> <span class="reserved">int</span> <span class="reserved">or</span> <span class="reserved">uint</span> <span class="reserved">or</span> <span class="reserved">nint</span> <span class="reserved">or</span> <span class="reserved">nuint</span>
            <span class="reserved">or</span> <span class="reserved">long</span> <span class="reserved">or</span> <span class="reserved">ulong</span> <span class="reserved">or</span> <span class="reserved">float</span> <span class="reserved">or</span> <span class="reserved">double</span>
            <span class="reserved">or</span> <span class="reserved">decimal</span> <span class="reserved">or</span> <span class="reserved">string</span> <span class="reserved">and</span> <span class="reserved">var</span> <span class="reserved">_</span>
        <span class="reserved">as</span> <span class="reserved">dynamic</span>
        <span class="reserved">as</span> <span class="reserved">object</span>
    <span class="reserved">on</span> <span class="reserved">false</span> <span class="reserved">equals</span> <span class="reserved">null</span>
<span class="reserved">where</span> <span class="reserved">this</span>
<span class="reserved">orderby</span> <span class="reserved">default</span> <span class="reserved">ascending</span>
<span class="reserved">orderby</span> <span class="reserved">null</span> <span class="reserved">descending</span>
<span class="reserved">group</span> <span class="reserved">null</span> <span class="reserved">by</span>
    <span class="reserved">static</span> <span class="reserved">ref</span> <span class="reserved">readonly</span> <span class="reserved">global</span>::System.<span class="type">Int32</span>() =&gt; <span class="reserved">ref</span> <span class="method">NullRef</span>&lt;<span class="reserved">int</span>&gt;()
</code></pre>
<p>とりあえず、「Visual Studio 上で青色か紫色になるやつはキーワードとする」という前提。
<a href="https://docs.microsoft.com/ja-jp/dotnet/api/microsoft.codeanalysis.classification.classifier">Classifier</a> が <code>&quot;keyword&quot;</code> か <code>&quot;keyword - control&quot;</code> を返してるやつです。</p>
<p>ちなみに、重複を一切認めなくても27個のキーワードを並べられました。</p>
<pre class="source" title="キーワードを並べられるだけ並べた物(重複なし27個)">
<code><span class="reserved">in</span> <span class="reserved">await</span> <span class="reserved">value</span> <span class="reserved">is</span> <span class="reserved">not</span> <span class="reserved">bool</span> <span class="reserved">or</span> <span class="reserved">byte</span> <span class="reserved">and</span> <span class="reserved">var</span> <span class="reserved">_</span> <span class="reserved">as</span> <span class="reserved">object</span> <span class="reserved">on</span> <span class="reserved">false</span> <span class="reserved">equals</span>
<span class="reserved">null</span> <span class="reserved">where</span> <span class="reserved">this</span> <span class="reserved">orderby</span> <span class="reserved">default</span> <span class="reserved">ascending</span> <span class="reserved">group</span> <span class="reserved">true</span> <span class="reserved">by</span> <span class="reserved">static</span> <span class="reserved">ref</span> <span class="reserved">readonly</span> <span class="reserved">int</span>
</code></pre>
<p>昨日、最初につぶやいた時点では20個くらいだったんですが、そこからだいぶ増えて27個に。</p>
<h2>過程</h2>
<h3>水増し要員</h3>
<p>重複を際限なく許すのなら、以下のように、何回でも繰り返せるものがあります。</p>
<ul>
<li><code>x is</code> (<code>not</code>)×n <code>null</code></li>
<li><code>x is int</code> (<code>or int</code>)×n</li>
<li><code>from x in y</code> (<code>where true</code>)×n <code>select null</code></li>
<li><code>x</code> (<code>as object</code>)×n</li>
</ul>
<p>特に <code>not</code> は単独でいくらでも増やせるので、1個単位で個数の調整が可能。
なので、きっかけとなったツイートの「半分は異なる」の条件を満たすために「<code>not</code> を増やす」という水増しが可能。</p>
<p>とりあえず、Kirill さんの言っていた16個程度であれば、<code>x is not null or byte or short or int</code>... で余裕で達成できます。
Kirill さんもこれを想定してつぶやいていたんじゃないかなぁと思います。</p>
<h3>クエリ式</h3>
<p>キーワード並べ放題という意味では<a href="https://ufcpp.net/study/csharp/sp3_linq.html#query">クエリ式</a>が強すぎでした。
<code>select</code>, <code>where</code>, <code>orderby</code>, <code>group</code>, <code>by</code> 等々、クエリ式内限定の文脈キーワードがたくさんありますし、
<code>where true</code> みたいにキーワードだけで式を構築しやすくて。</p>
<p>以下のように、「<code>object</code> 引数で何でも受け付ける拡張メソッド」を置いておくことでさらに自由度が増します。
<code>where null</code> でも <code>group default by false</code> でも何でもありです。</p>
<pre class="source" title="何でも受け付けるLINQ演算子(拡張メソッド)">
<code><span class="reserved">static</span> <span class="reserved">partial</span> <span class="reserved">class</span> <span class="type">Ex</span>
{
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">object</span> <span class="method">Select</span>(<span class="reserved">this</span> <span class="reserved">object</span> <span class="variable">x</span>, <span class="type">Func</span>&lt;<span class="reserved">object</span>, <span class="reserved">object</span>&gt; <span class="variable">f</span>) =&gt; <span class="reserved">null</span>;
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">object</span> <span class="method">Join</span>(<span class="reserved">this</span> <span class="reserved">object</span> <span class="variable">x</span>, <span class="reserved">object</span> <span class="variable">y</span>, <span class="type">Func</span>&lt;<span class="reserved">object</span>, <span class="reserved">object</span>&gt; <span class="variable">a</span>, <span class="type">Func</span>&lt;<span class="reserved">object</span>, <span class="reserved">object</span>&gt; <span class="variable">b</span>, <span class="type">Func</span>&lt;<span class="reserved">object</span>, <span class="reserved">object</span>, <span class="reserved">object</span>&gt; <span class="variable">c</span>) =&gt; <span class="reserved">null</span>;
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">object</span> <span class="method">Where</span>(<span class="reserved">this</span> <span class="reserved">object</span> <span class="variable">x</span>, <span class="type">Func</span>&lt;<span class="reserved">object</span>, <span class="reserved">object</span>&gt; <span class="variable">f</span>) =&gt; <span class="reserved">true</span>;
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">object</span> <span class="method">OrderBy</span>(<span class="reserved">this</span> <span class="reserved">object</span> <span class="variable">x</span>, <span class="type">Func</span>&lt;<span class="reserved">string</span>, <span class="reserved">object</span>&gt; <span class="variable">f</span>) =&gt; <span class="reserved">null</span>;
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">object</span> <span class="method">OrderByDescending</span>(<span class="reserved">this</span> <span class="reserved">object</span> <span class="variable">x</span>, <span class="type">Func</span>&lt;<span class="reserved">object</span>, <span class="reserved">object</span>&gt; <span class="variable">f</span>) =&gt; <span class="reserved">null</span>;
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">object</span> <span class="method">GroupBy</span>(<span class="reserved">this</span> <span class="reserved">object</span> <span class="variable">x</span>, <span class="type">Func</span>&lt;<span class="reserved">object</span>, <span class="reserved">object</span>&gt; <span class="variable">a</span>, <span class="type">Func</span>&lt;<span class="reserved">string</span>, <span class="reserved">object</span>&gt; <span class="variable">b</span>) =&gt; <span class="reserved">null</span>;
}
</code></pre>
<h3>他の選択肢</h3>
<p>クエリ式が強すぎることで、他の選択肢が消えます。</p>
<p>例えば、<code>protected internal</code> とか <code>sealed override</code> とかの選択肢が消えます。
余談として、こういう「修飾子系のキーワード」で頑張る場合、現状、 <code>unsafe protected internal sealed override partial ref readonly int</code> の9個が最長でした。</p>
<p>あと、当初は<a href="https://ufcpp.net/study/csharp/datatype/patterns/">パターンマッチ</a>を中心に考えていて、
「じゃあ <code>case</code> とか <code>when</code> を使えば伸びるのでは… と思っていたものの、
ここもクエリ式を組み込めなくて没になりました(キーワード14個)。</p>
<pre class="source" title="case, when (没案)">
<code><span class="control">case</span> <span class="reserved">not</span> <span class="reserved">null</span> <span class="reserved">and</span> <span class="reserved">bool</span> <span class="reserved">or</span> <span class="reserved">byte</span> <span class="control">when</span> <span class="reserved">true</span> <span class="reserved">as</span> <span class="reserved">object</span> <span class="reserved">is</span> <span class="reserved">var</span> <span class="reserved">_</span>
</code></pre>
<h3>式の並べ方</h3>
<p><code>let</code> みたいに絶対に <code>=</code> が挟まってしまって途切れるものは置いておいて、クエリ式の候補には以下のようなものがあります。</p>
<p>先頭要素(<code>x</code> をキーワードにできないのでそこで連続性が途切れる):</p>
<ul>
<li><code>from x in a</code></li>
<li><code>join x in a on b equals c</code></li>
</ul>
<p>それ以降の要素:</p>
<ul>
<li><code>where a</code></li>
<li><code>orderby a</code> (さらに後ろに <code>ascending</code> または <code>descending</code> を付けれる)</li>
<li><code>group a by b</code></li>
</ul>
<p>(<code>select</code> は <code>group</code> と競合するので没。)</p>
<p><code>join</code> から始めて、<code>in</code> から後ろを使うのが最長の候補です。</p>
<pre class="source" title="クエリ式の最長候補">
<code><span class="reserved">from</span> x <span class="reserved">in</span> <span class="variable">n</span> <span class="reserved">join</span> y
<span class="comment">// ここから下がキーワード候補</span>
<span class="reserved">in</span> <span class="variable">a</span> <span class="reserved">on</span> <span class="variable">b</span> <span class="reserved">equals</span> <span class="variable">c</span>
<span class="reserved">where</span> <span class="variable">d</span>
<span class="reserved">orderby</span> <span class="variable">e</span> <span class="reserved">ascending</span>
<span class="reserved">group</span> <span class="variable">f</span> <span class="reserved">by</span> <span class="variable">g</span>
</code></pre>
<p>(重複を許すなら <code>orderby descending</code> を追加。)</p>
<h3>単独キーワード</h3>
<p>前節のクエリ式のうち <code>a</code>～<code>f</code> の6個には、単独で有効な式になれるキーワードが必要です。
<code>x is int or int</code>... とか <code>x as object as object</code>... とかで水増しするにしても、
起点 <code>x</code> になれる物が必要なので。</p>
<p>候補には、</p>
<ul>
<li><code>null</code>, <code>true</code>, <code>false</code>: どこでも使えるリテラル</li>
<li><code>default</code>: ターゲット型推論が効くとき限定で使えるリテラル</li>
<li><code>this</code>: クラスのインスタンスメンバー内限定</li>
<li><code>value</code>: プロパティの <code>set</code> 内限定</li>
<li><code>args</code>: <a href="https://ufcpp.net/study/csharp/cheatsheet/ap_ver9/#top-level-statements">トップ レベル</a>内限定</li>
</ul>
<p>があって、このうち、<code>value</code> と <code>args</code> は両立不可能。
<code>this</code> と <code>args</code> も両立不可。
両立できなくて困る <code>args</code> を除いて、偶然にも、ちょうど必要な6種でした。
(C# チームはこの縛りを見抜いていた！？)</p>
<p><code>where default</code> (ちゃんと <code>Where</code> メソッドの引数から型推論可能)とかが通ったのも助かりました。</p>
<p>あと、将来(たぶん、C# 11 で)、プロパティ内限定で使える <code>field</code> キーワードも追加されそうです。
(これも <code>args</code> と両立不可。<code>value</code>, <code>this</code> とは可能。)</p>
<h3>末尾キーワード</h3>
<p>前述のクエリ式のうち <code>g</code> については、「どうやっても後ろに記号がくっついてくるキーワード」が使えます。
例えば、以下のような候補あり。</p>
<ul>
<li><code>new object()</code>: <code>object</code> の代わりに <code>global::System.Object</code> とかを使えば <code>global</code> の巻き込みもできる</li>
<li><code>true with { }</code>: <code>with</code> の前は構造体でないとダメなので <code>true</code> か <code>false</code> くらいしか選択肢なし</li>
<li><code>static () =&gt; { }</code>: ラムダ式</li>
</ul>
<p>ラムダ式の案を思いつくまでは <code>new global::System.Object()</code> が最長だと思って使っていました。
(<code>true</code> は <code>a</code>～<code>f</code> の方で使いたい。)</p>
<p>で、途中で<a href="https://ufcpp.net/study/csharp/functional/fun_localfunctions/#lambda-csharp10">C# 10 で導入されたラムダ式の戻り値指定</a>が使えることに気づいて一気に伸びました。
パターン (<code>x is int</code> みたいなところ)には使えなくても、
ラムダ式戻り値としてなら <code>static</code>, <code>ref</code>, <code>readonly</code> などの修飾子が使えます。</p>
<p>以下のようなコードの、<code>static ref readonly global</code> の部分が使えました。</p>
<pre class="source" title="ラムダ式戻り値">
<code><span class="reserved">using</span> <span class="reserved">static</span> System.Runtime.CompilerServices.<span class="type">Unsafe</span>;

<span class="reserved">var</span> <span class="variable">f</span> = <span class="reserved">static</span> <span class="reserved">ref</span> <span class="reserved">readonly</span> <span class="reserved">global</span>::System.<span class="type">Int32</span> () =&gt; <span class="reserved">ref</span> <span class="method">NullRef</span>&lt;<span class="reserved">int</span>&gt;()
</code></pre>
<p>末尾限定で <a href="https://ufcpp.net/study/csharp/sp_namespace.html#global"><code>global</code></a> が使えることも分かっているので、型名は <code>int</code> ではなく <code>global::System.Int32</code> で参照しています。</p>
<h2>修飾</h2>
<p><code>null</code> とか <code>value</code> とかは、<code>await value is null</code> みたいにある程度前後を修飾できます。</p>
<h3>await</h3>
<p><code>await</code> も以下のような拡張メソッドを用意しておくことで任意のオブジェクトに対して使えます。</p>
<pre class="source" title="任意のオブジェクトを awaitable にする拡張メソッド">
<code><span class="reserved">using</span> System.Runtime.CompilerServices;

<span class="reserved">static</span> <span class="reserved">partial</span> <span class="reserved">class</span> <span class="type">Ex</span>
{
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="type">ValueTaskAwaiter</span>&lt;<span class="reserved">object</span>&gt; <span class="method">GetAwaiter</span>(<span class="reserved">this</span> <span class="reserved">object</span> <span class="variable">x</span>) =&gt; <span class="reserved">default</span>;
}
</code></pre>
<p>ただ、前述の通り、<code>value</code> を使いたければプロパティの <code>set</code> 内である必要があります。
プロパティは非同期にはできないので、1段工夫が必要で、以下のように、ラムダ式で覆う必要がありました。</p>
<pre class="source" title="プロパティ内で await を使う">
<code><span class="reserved">public</span> <span class="reserved">object</span> X
{
    <span class="reserved">set</span> =&gt; _x = <span class="reserved">async</span> () =&gt; ...
</code></pre> 
<h3>is</h3>
<p><code>Where</code> とか <code>OrderBy</code> とかを <code>object</code> 引数で定義したので、別に <code>bool</code> を渡しても大丈夫です。
なので、<code>orderby value is null</code> (<code>bool</code> になっちゃう)とかも書けます。
ということで、パターン使い放題。</p>
<p>特に、C# 9 で <a href="https://ufcpp.net/study/csharp/datatype/patterns/?p=3#pattern-combintor"><code>not</code>, <code>and</code>, <code>or</code></a>が追加されたので、これで結構伸ばせます。</p>
<p>重複なしなら以下のパターン。</p>
<pre class="source" title="not or and var _">
<code><span class="reserved">is</span> <span class="reserved">not</span> <span class="reserved">bool</span> <span class="reserved">or</span> <span class="reserved">int</span> <span class="reserved">and</span> <span class="reserved">var</span> <span class="reserved">_</span>
</code></pre>
<p><code>not null</code> とかも書けるんですが、<code>null</code> は前述の「単独で使える貴重なキーワード」なので、ここでは避けます。</p>
<p>また、この文脈においては <code>_</code> は <a href="https://ufcpp.net/study/csharp/datatype/patterns/?p=1#discard">discard</a> の意味になるので、キーワード扱い(Visual Studio 上で青色)になります。</p>
<p>重複を許すのであれば、<code>or byte or sbyte or short</code>... というように、全ての組み込み型を <code>or</code> でつなぐことでかさ増しできます。</p>
<p>当初、<code>char</code>, <a href="https://ufcpp.net/study/csharp/cheatsheet/ap_ver9/#nint"><code>nint</code>, <code>nuint</code></a> を忘れてました…</p>
<h3>as</h3>
<p><code>as</code> も含めたいがために、1個だけ <code>or object</code> とはせずに <code>as object</code> で使いました。</p>
<p>ここで、<code>x is dynamic</code> とは書けないものの、<a href="https://twitter.com/Benshi_Orator/status/1529649583688937473"><code>x as dynamic</code> なら書ける</a>とご指摘いただき、
無事1キーワード増えました。</p>
<h2>まとめ</h2>
<p>青いなぁ。</p>
<p>「こんなコード書きたくないし、書いた自分でも読めない」な状態ですが、
思った以上にキーワードを大量に並べることができました。</p>
<p>当初は<a href="https://twitter.com/ufcpp/status/1529782647483797506">35個</a>だったんですが、
9個増えて44個になりました。</p>
<ul>
<li><code>char</code>, <code>nint</code>, <code>nuint</code> 忘れ</li>
<li><code>orderby descending</code> 忘れ</li>
<li><code>await</code> 導入</li>
<li><code>as dynamic</code> 導入</li>
<li>ラムダ式戻り値の導入</li>
</ul>
<p>だいたいはクエリ式のせいですが、
クエリ式を使わず重複なしでも <code>case</code> から始まる14キーワードとかを並べられるみたいです。</p>
<p>色々やっているうちに、<code>in a on b equals c where d orderby e group f by</code>... みたいなのに必要な6種類のキーワードがピッタリあって、この縛りを見抜かれていた感があります。</p>
 ]]></description>
				<pubDate>Thu, 26 May 2022 22:32:02 +0900</pubDate>
			</item>
			<item>
				<title>引数 null チェックの !!、取りやめ</title>
				<link>http://ufcpp.net/blog/2022/5/double-bang-removed/</link>
				<description><![CDATA[ <p><code>!!</code> を使った引数の null チェック、なくなるって。</p>
<h2>引数 null チェック</h2>
<p><a href="https://ufcpp.net/blog/2022/2/parameter-null-check/">2月にブログに書きましたが</a>、
Visual Studio 17.1 Preview 3の頃、C# 11 候補として「引数の null チェック」構文が入っていました。</p>
<pre class="source" title="引数 null チェックの !!">
<code><span class="method">m</span>(<span class="reserved">null</span>); <span class="comment">// ArgumentNull 例外が出る。</span>

<span class="reserved">void</span> <span class="method">m</span>(<span class="reserved">string</span> <span class="variable">x</span><em>!!</em>) { }
</code></pre>
<p>今現在(VS 17.2 Preview 5)でもこの構文は生きているんですが、次(たぶん、17.2正式リリースでも17.3 Preview 1でも)でいったん取りやめになるそうです。</p>
<h2>取りやめの経緯</h2>
<p>C# チームとしては、今、Preview リリースをしてみて反応を見てその後どうするかを決めたりしているわけですが。
<a href="https://ufcpp.net/study/csharp/cheatsheet/langversionoption/#new-options">LangVersion preview</a> があるのはそのためです。</p>
<p>とはいえ、普通に考えて、Preview 機能まで追いかけている人がそんなに多いわけもなく、
正式リリースされるまでどんな機能が追加されているのか知らない人の方が多数派でしょうね。
ところが今回は大変目立つ Pull Request が1個ありまして。</p>
<ul>
<li>[1,232ファイル、+4,540行、-21,372行の Pull Request]</li>
</ul>
<p>こういうので急に話題になると、大体燃えます。
以下のような質問 Discussion が立ったんですが、コメントが荒れる荒れる。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/discussions/5735">質問: <code>!!</code> はどう使われることを想定しているの？</a></li>
</ul>
<p>というか、null チェックがらみはいつも荒れるんですが…</p>
<p>この荒れ具合を受けて、4月6日に再検討:</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/blob/main/meetings/2022/LDM-2022-04-06.md">LDM-2022-04-06</a></li>
</ul>
<p>この日の検討では、</p>
<ul>
<li>
やるべきじゃない？
<ul>
<li>→ やる価値はあると信じてる</li>
</ul>
</li>
<li>
もっと完全な契約プログラミングにする？
<ul>
<li>→ null チェック以外の価値は微小</li>
</ul>
</li>
<li>
NRT で自動的に実行時 null チェックも入れる？
<ul>
<li>→ 破壊的変更(急に例外出るようになる)の度合いが大きすぎるし、無条件の null チェック挿入の実行時コストはちょっと許容しかねる</li>
</ul>
</li>
<li>
構文再考: <code>!!</code> 以外を考える？
<ul>
<li>→ <code>!</code> はない。かといって他の案(T parameter not null みたいなの)は長ったらしかったりできつい</li>
</ul>
</li>
</ul>
<p>みたいな話に。
で、次の4月13日に<code>!!</code> 以外の構文について色々検討。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/blob/main/meetings/2022/LDM-2022-04-13.md#c-language-design-meeting-for-april-11th-2022">LDM-2022-04-13</a></li>
</ul>
<p>とはいえ、しっくりこなかったみたいで「C# 11からは取り下げて、後日改めて検討する」ということに決定。</p>
<p>そして .NET Runtime 側、
<code>!!</code>構文をやめて、<a href="https://docs.microsoft.com/ja-jp/dotnet/api/system.argumentnullexception.throwifnull"><code>ArgumentNullException.ThrowIfNull</code></a>に書き換える Pull Request が改めて出ました。</p>
<ul>
<li><a href="https://github.com/dotnet/runtime/pull/68178">Remove usage of !! from dotnet/runtime</a></li>
</ul>
<h2>荒れた理由</h2>
<p>いくつか私見。</p>
<h3>突然の登場</h3>
<p>一般的な C# 開発者に取って唐突に出て来た機能ではあったと思います。</p>
<p>前述の「1,232ファイル Pull Request」を見ての通り、
.NET Runtime チームにとっては結構強く求められる機能で、
要するに「内需」です。
内需の場合、割かしあっという間に C# チームに需要が伝わって、あっという間に実装されてリリースにこぎつけたりするので。</p>
<p>「外部開発者が知らないとこで“中の人”で勝手に話進めやがって」感があって、「これだからお前のとこの会社は」みたいに思われたんでしょうね。</p>
<h3>マイノリティのための構文</h3>
<p>null チェック機能は「.NET Runtime みたいに、大規模に使われているライブラリ作者にとっては有用なものの、ライブラリを使う側にとっては大して必要のない機能」です。</p>
<p>よっぽどかっちりライブラリを書くのでなければ、
「引数の null チェックして自分で <code>throw new ArgumentNullException()</code> する必要あるの？」
「自分でチェックしなくてもどうせすぐに <code>NullReferenceException</code> 出るし、大差ないじゃない？」
「どうせ <code>catch</code> もせず、デバッガーで例外が出たところに飛んで直すだけだし」
とか思いますし。</p>
<p>なので、「なんでそんな必要のない機能を先に実装するの？」みたいな反発を買っていそうな雰囲気があります。
(ライブラリは作る側よりも使う側の人の方が圧倒的多数なので、人口ベースで見るとマイノリティのための機能になります。)</p>
<h3>null 理想論</h3>
<p>この機能は「不完全な <a href="https://ufcpp.net/study/csharp/resource/nullablereferencetype/">NRT</a> のしりぬぐい」感もあるんですよね。</p>
<p>NRT のフロー解析が完璧ならそもそもとして「null であってはいけないところに null が渡ること自体がない」はずで、
だったら「null チェック」も「<code>ArgumentNullException</code>」も本来起こりえないので不要なものなわけで。</p>
<p>じゃあどこから null が漏れてくるかというと、</p>
<ul>
<li>NRT が不完全で、構造体の <a href="https://ufcpp.net/study/csharp/rm_default.html"><code>default</code></a> とかで簡単に「null チェックをすり抜けてくる null」がいる</li>
<li>他の言語との相互運用、NRT 導入前の古い C# のコードなど、解析しようがないところから来る null がいる</li>
</ul>
<p>という辺り。
この辺りのしりぬぐいとして、「フロー解析に加えて、実行時チェックして <code>throw new ArgumentNullException()</code>」とか、ある種の冗長な処理をやっているわけです。</p>
<p>結果、NRT に対する理想を抱く人ほど、<code>!!</code> を気持ちが悪がってる感じがあります。</p>
<h2>個人的な意見</h2>
<p>大多数の人間にとってはどっちでもよくて、
.NET Runtime チームにとってはそれなりに必要なんだから、
多少みっともない構文でも入れちゃっていいと思うんですけどね。</p>
<p>とはいえ、構文がみっともない以外にも多少、はまりそうなポイントがあったりはします。
例えば、<a href="https://ufcpp.net/study/csharp/datatype/record/"><code>record</code></a> が絡むとどうなの？とか。
以下のようなコードの挙動を見ると、構文の問題以上にもうちょっと見当が必要かもなー、とかは思います。</p>
<pre class="source" title="record のプライマリーコンストラクターで !! を使ってみて">
<code><span class="comment">// これは例外を出してもらえる。</span>
<span class="reserved">var</span> <span class="variable">r1</span> = <span class="reserved">new</span> <span class="type">R</span>(<span class="reserved">null</span>);

<span class="comment">// でもこれは例外が出ない。</span>
<span class="comment">// init アクセッサーにも同種の null チェックを備えられるようにすべきではないか？</span>
<span class="reserved">var</span> <span class="variable">r2</span> = <span class="reserved">new</span> <span class="type">R</span>(<span class="string">&quot;&quot;</span>) { X = <span class="reserved">null</span> };

<span class="reserved">record</span> <span class="type">R</span>(<span class="reserved">string</span> <span class="variable">X</span>!!);
</code></pre> ]]></description>
				<pubDate>Wed, 04 May 2022 22:37:57 +0900</pubDate>
			</item>
			<item>
				<title>【C# 10.0 変更点】 構造体のフィールド初期化子にはコンストラクター必須</title>
				<link>http://ufcpp.net/blog/2022/2/csharp10-breaking-change-field-init/</link>
				<description><![CDATA[ <p>先日 Visual Studio 17.1.0 (正式リリース)と 17.2 Preview 1 が出たわけですが。</p>
<p>これをインストールすると、ちょこっと C# 10.0 の構造体のフィールド初期化子の挙動が変わります。
以下のようなコード、17.0/17.1 Preview 時代はコンパイルできていたんですが、17.1/17.2 Preview ではコンパイル エラーになります。</p>
<pre class="source" title="しれっと破壊的変更が掛かった文法">
<code><span class="reserved">struct</span> <span class="type"><span class="error">S</span></span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> X = 1; <span class="comment">// ここが原因。<span>
}
</code></pre>
<p>ちなみに、C# の言語バージョンが改まったわけではなく、
バグ修正とかと同じノリでサイレント修正です。</p>
<p>仕様: <a href="https://github.com/dotnet/csharplang/pull/5637">Never synthesize parameterless struct constructor</a></p>
<h2>問題</h2>
<p>上記のコードの 17.0/17.1 Preview 時代の挙動なんですが、
まあ、暗黙的に引数なしコンストラクターが追加されています。
以下のような挙動。</p>
<pre class="source" title="17.0 時代の挙動">
<code><span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="reserved">new</span> <span class="type">S</span>().X); <span class="comment">// 1</span>

<span class="reserved">struct</span> <span class="type">S</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> X = 1;
    <span class="comment">// public S() { } これがある時と同じ挙動になってた。<span>
}
</code></pre>
<p>問題は、このコードに引数ありコンストラクターを足したとき。
以下のようになっていたそうです。</p>
<pre class="source" title="引数ありコンストラクターを手動で足すと、引数なしコンストラクターの自動生成がなくなる">
<code><span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="reserved">new</span> <span class="type">S</span>().X); <span class="comment">// 0。 default(S).X 扱い…</span>

<span class="reserved">struct</span> <span class="type">S</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> X = 1;
    <span class="reserved">public</span> <span class="type">S</span>(<span class="reserved">int</span> <span class="variable">x</span>) =&gt; X = <span class="variable">x</span>;
    <span class="comment">// public S() { } これが生成されなくなる。</span>
}
</code></pre>
<p>この挙動が罠すぎるので、傷が浅いうちに不具合扱いして挙動を変えようということになりました。</p>
<h2>案1: 現状維持</h2>
<p>もちろん、現状維持も検討されたみたいなんですが、
C# 10.0 リリース後のユーザーの反応的には相当に強い懸念の声が出ていて、無視はできないレベルと判断されたそうです。</p>
<h2>案2: 常に引数なしコンストラクターを生成する</h2>
<p>以下のように直すのが自然な気がしなくもないわけですが…</p>
<pre class="source" title="案2: 常に引数なしコンストラクターを生成する">
<code><span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="reserved">new</span> <span class="type">S</span>().X); <span class="comment">// ちゃんと1になればいいわけで。</span>

<span class="reserved">struct</span> <span class="type">S</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> X = 1;
    <span class="reserved">public</span> <span class="type">S</span>(<span class="reserved">int</span> <span class="variable">x</span>) =&gt; X = <span class="variable">x</span>;
    <span class="comment">// public S() { } これが生成されればいい。</span>
}
</code></pre>
<p>これで問題になるのが、<code>record struct</code> の<a href="https://ufcpp.net/study/csharp/datatype/record/#primary-constructor">プライマリ コンストラクター</a>だそうで。</p>
<p>プライマリ コンストラクターがある場合、「全てのコンストラクターは最終的にプライマリ コンストラクターにたどり着く必要がある」ということになっています。</p>
<pre class="source" title="必ず最終的にはプライマリ コンストラクターにたどり着く">
<code><span class="reserved">record</span> <span class="reserved">struct</span> <span class="type">S</span>(<span class="reserved">int</span> <span class="variable">X</span>)
{
    <span class="comment">// 必ず S(int X) にたどり着くように書かないとダメ。</span>
    <span class="reserved">public</span> <span class="type">S</span>() : <span class="reserved">this</span>(1) { }
    <span class="reserved">public</span> <span class="type">S</span>(<span class="reserved">int</span> <span class="variable">a</span>, <span class="reserved">int</span> <span class="variable">b</span>) : <span class="reserved">this</span>(<span class="variable">a</span> * <span class="variable">b</span>) { }
}
</code></pre>
<p>ここで、じゃあ、先ほどの、フィールド初期化子があるときにどうするか。
コンパイラーが自動的に引数なしコンストラクターを追加するのであれば、プライマリ コンストラクターには何を渡すべきかという問題がでます。</p>
<pre class="source" title="引数なしコンストラクターはどう実装されるべきか…">
<code><span class="reserved">record</span> <span class="reserved">struct</span> <span class="type">S</span>(<span class="reserved">string</span> <span class="variable">X</span>)
{
    <span class="reserved">public</span> <span class="reserved">int</span> Y = 1;

    <span class="comment">// public S() : this(null) { } を足す？</span>
    <span class="comment">// 非 null が期待される string に null が渡ってしまう…</span>
}
</code></pre>
<p>これがあるから、当初、「引数ありコンストラクターがあるときにはむやみに引数なしコンストラクターを追加しない」という判断になったようです。</p>
<h2>案3: コンストラクターが1つもないとき、フィールド初期化子をエラーに</h2>
<p>ということで、今日のブログの冒頭の話に戻ります。</p>
<p>以下のコードがエラーになりました。</p>
<pre class="source" title="しれっと破壊的変更が掛かった文法">
<code><span class="reserved">struct</span> <span class="type"><span class="error">S</span></span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> X = 1;
}
</code></pre>
<p>ちなみに、Visual Studio 17.2 Preview 1 では、この状態の(エラーのある)コードに対して「引数なしコンストラクターを追加する」というリファクタリング機能が追加されています。</p>
<p><img src="/media/1211/generateconstructor.png" alt="Generate constructor リファクタリング" /></p>
<p>ただ、最初から以下のようなコードを書くと罠っぽい挙動になるのは今と同じ。</p>
<pre class="source" title="引数ありコンストラクターを手動で足すと new S() が default(S) 扱い">
<code><span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="reserved">new</span> <span class="type">S</span>().X); <span class="comment">// 0。 default(S).X 扱い…</span>

<span class="reserved">struct</span> <span class="type">S</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> X = 1;
    <span class="reserved">public</span> <span class="type">S</span>(<span class="reserved">int</span> <span class="variable">x</span>) =&gt; X = <span class="variable">x</span>;
    <span class="comment">// public S() { } これは生成されない。</span>
}
</code></pre>
<p>ただ、「後から迂闊に引数ありコンストラクターを足してしまう」という状況は減るはずです。</p>
<p>エラーにならないようにするのは元々が以下のようなコードのはずで、</p>
<pre class="source" title="エラーにならないコード">
<code><span class="reserved">struct</span> <span class="type">S</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> X = 1;
    <span class="reserved">public</span> <span class="type">S</span>() { }
}
</code></pre>
<p>ここに引数ありコンストラクターを足すはずなので、
以下のような挙動が期待されます。</p>
<pre class="source" title="コンストラクターが明示的にあれば解決">
<code><span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="reserved">new</span> <span class="type">S</span>().X); <span class="comment">// ちゃんと1。</span>

<span class="reserved">struct</span> <span class="type">S</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> X = 1;
    <span class="reserved">public</span> <span class="type">S</span>() { }
    <span class="reserved">public</span> <span class="type">S</span>(<span class="reserved">int</span> <span class="variable">x</span>) =&gt; X = <span class="variable">x</span>;
}
</code></pre> ]]></description>
				<pubDate>Sat, 19 Feb 2022 18:29:28 +0900</pubDate>
			</item>
			<item>
				<title>C# 中の埋め込み言語</title>
				<link>http://ufcpp.net/blog/2022/2/embedded-languages/</link>
				<description><![CDATA[ <p><a href="https://ufcpp.net/blog/2018/1/pickuproslyn0103/">さかのぼること4年前</a>、C# 中に正規表現な文字列を書くと以下のように構文ハイライトされるようになりました。</p>
<p><img src="/media/1208/langregex.png" alt="lang=regex" /></p>
<p>色が付く以外に、コード補完や構文ミスに対する警告とかも出ます。</p>
<p>今日はこの手の「C# 中への別言語の埋め込み」がらみの話です。</p>
<p>先日、4件くらい <a href="https://ufcpp.net/blog/2022/2/ref-field/">low level imprevements のブログ</a>を書いて、その中で「実に5年ぶりの low level の機運」とか書きましたが、
「埋め込み言語」にも4年ぶりの機運が来ています。</p>
<h2>JSON</h2>
<p>4年ぶりに何が起きたかというと、JSON にも構文ハイライトが働くようになりました。</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/pull/59034">Enable feature lightup on json strings (classification, bracematching, diagnostics).</a></li>
</ul>
<p>そして <a href="https://docs.microsoft.com/en-us/visualstudio/releases/2022/release-notes-preview#17.2.0-pre.1.0">Visual Studio 17.2 Preview 1</a> にこのコードが入っていりました。
以下スクショ。</p>
<p><img src="/media/1210/langjson.png" alt="lang=json" /></p>
<p>「JSON に対応した」というだけだと、
正直「なんで今更…」という感想が多少します。
外部の JSON ファイルを読む機会は近年どんどん増えていますが、
C# 中に JSON を埋め込む需要ってそんなにあったっけ？という感じ。</p>
<p>まあ、今後、対応する「埋め込み言語」を増やすか、
任意の開発者が任意の「埋め込み言語」を増やせるようにする予兆かも？
という淡い期待をしつつ今後の動きを待ちましょう…</p>
<h2>StringSyntax 属性</h2>
<p>もう1個新しいのが、<code>StringSyntax</code> という属性が増えました。</p>
<ul>
<li><a href="https://github.com/dotnet/runtime/issues/62505">[API Proposal]: System.Diagnostics.CodeAnalysis.StringSyntaxAttribute</a></li>
<li><a href="https://github.com/dotnet/runtime/pull/62995">[API Implementation]: System.Diagnostics.CodeAnalysis.StringSyntaxAttribute</a></li>
<li><a href="https://github.com/dotnet/runtime/pull/64081">Add StringSyntaxAttribute.Json</a></li>
</ul>
<p>これまで、「正規表現扱いされる文字列」の判定は結構特殊なことをやっていました。</p>
<ul>
<li><code>Regex</code> クラス関連のメソッドで、<code>pattern</code> という名前の引数に渡している</li>
<li>直前に <code>lang=regex</code> みたいな文字列が入ったコメントが書かれている</li>
</ul>
<p>みたいな判定をしています。</p>
<p>ちなみに、この2個目の仕様があるので、以下のようなコードにも構文ハイライトが掛かります。</p>
<pre class="source" title="lang= 隠し仕様">
<code><span class="comment">//lang=regex</span>
<span class="reserved">var</span> <span class="variable">regex</span> = <span class="string">@&quot;(?&lt;name&gt;\w+?\d{3}).txt&quot;</span>;

<span class="comment">//lang=json</span>
<span class="reserved">var</span> <span class="variable">json</span> = <span class="string">@&quot;{ 'value': 123 }&quot;</span>;
</code></pre>
<p>ほぼ「隠し仕様」みたいになってますが。</p>
<p>で、まあ、あんまりこういう特殊対応するのも微妙なので、
このたび、埋め込み言語指定用の属性ができました。
それが <code>StringSyntax</code> 属性。
<code>Regex</code> クラスのコンストラクターや <code>Match</code> メソッドにもこの属性が追加されています。</p>
<pre class="source" title="Regex クラスに StringSyntax 属性追加">
<code><span class="reserved">public</span> <span class="reserved">class</span> <span class="type">Regex</span>
{
    <span class="reserved">public</span> <span class="type">Regex</span>([<span class="type">StringSyntax</span>(<span class="type">StringSyntaxAttribute</span>.Regex, <span class="string">&quot;options&quot;</span>)] <span class="reserved">string</span> <span class="variable">pattern</span>) { }
}
</code></pre>
<h2>raw string literal</h2>
<p>今このタイミングでなのは、
<a href="https://ufcpp.net/blog/2021/2/rawstringliteral/">raw string literal</a> が入ったからでしょうね。
C# の文字列リテラル中にコードを埋め込みやすくなったので。
(さらに大本をたどると、raw string literal が入るきっかけは <a href="https://ufcpp.net/study/csharp/misc/analyzer-generator/">source generator</a> です。
コード生成しだすと raw string が欲しくなるので。)</p>
<p>Visual Studio 17.2 Preview 1 で、以下のようなコードが書けるようになりました。
(C# 11 候補。現状は LangVersion preview が必要。)</p>
<pre class="source" title="raw string literal の例">
<code><span class="reserved">const</span> <span class="reserved">string</span> regex = <span class="string">@&quot;(?&lt;name&gt;\w+?\d{3}).txt&quot;</span>;
<span class="reserved">var</span> <span class="variable">json</span> = <span class="string">@&quot;{ 'value': 123 }&quot;</span>;

<span class="reserved">var</span> <span class="variable">raw</span> = $$&quot;&quot;<span class="string">&quot;</span>
<span class="reserved">class</span> <span class="type">A</span>
{
    <span class="reserved">public</span> <span class="reserved">const</span> <span class="reserved">string</span> R = <span class="string">@&quot;{{regex}}&quot;</span>
    <span class="reserved">public</span> <span class="reserved">const</span> <span class="reserved">string</span> J = <span class="string">@&quot;{{json}}&quot;</span>
}
<span class="string">&quot;&quot;</span><span class="string">&quot;;</span>
</code></pre>
<h2>EmbeddedLanguages</h2>
<p>この辺りの「埋め込み言語」の実装は Roslyn リポジトリ内の以下の場所にあります。</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/tree/main/src/Features/Core/Portable/EmbeddedLanguages">src/Features/Core/Portable/EmbeddedLanguages</a></li>
</ul>
<p>現状、正規表現と JSON の他に2つほど実装があります。</p>
<ul>
<li>DateAndTime: <code>DateTime</code> などの <code>ToString</code> 時に使う書式。<code>yyyy</code> みたいなやつを補完してくれます(補間のみ)。</li>
<li>StackFrame: スタック トレース情報のハイライト。たぶん他の用途にコードを流用しただけで、今回説明しているような文字列中のハイライトには使われてなさげ。</li>
</ul>
<h3>プラグイン式</h3>
<p>まあここまで話しておいてあれですが、
今日書いた内容、結構気持ち悪いと感じる人も多いんじゃないでしょうか。
コンパイラーの中に別言語を埋め込むとかリスクも非常に高く。</p>
<p>一度コンパイラーに組み込んじゃったものはめったなことでは消せないですからね。
例えばまあ、「XML リテラルを書けるようにしたら XML 自体が廃れた」みたいなこともあるわけでして。
(Visual Basic であった実話。)</p>
<p>そんなリスク、C# チームはよくわかっているので、
今日話したような「埋め込み言語」はコンパイラー内のコードではなく、
<a href="https://docs.microsoft.com/ja-jp/dotnet/framework/mef/">MEF</a> プラグインとして外から渡す作りになっています。</p>
<p>素の Roslyn コンパイラー(<code>Microsoft.CodeAnalysis.CSharp</code> パッケージ)だけを参照していると正規表現や JSON の構文ハイライト(<code>Classifier.GetClassifiedSpansAsync</code>)は得られません。</p>
<p>前述の <a href="https://github.com/dotnet/roslyn/tree/main/src/Features/Core/Portable/EmbeddedLanguages">EmbeddedLanguages</a> にある埋め込み言語を有効にしたければ、
<code>Microsoft.CodeAnalysis.CSharp.Features</code> パッケージを参照する必要があります。
このパッケージ内の MEF Export として埋め込み言語が入っていて、
それをコンパイラーが読み込むことで始めて構文ハイライトが掛かります。</p>
<p>という一連の流れのデモ:</p>
<ul>
<li><a href="https://github.com/ufcpp/UfcppSample/tree/master/Demo/2022/EmbeddedLanguages">UfcppSample Demo/2022/EmbeddedLanguages</a></li>
</ul>
<p>この辺りの仕組み、まだこなれていないから public にしたくないので、4年間ずっと internal だったりします。
public になってくれればも、誰もが埋め込み言語を作れるようになりそうなんですけどね。
raw string literal とか source generator とかがこなれてきたくらいにそうなることを期待しています。</p>
 ]]></description>
				<pubDate>Wed, 16 Feb 2022 22:02:18 +0900</pubDate>
			</item>
			<item>
				<title>【C# 11 候補】 引数の null チェック</title>
				<link>http://ufcpp.net/blog/2022/2/parameter-null-check/</link>
				<description><![CDATA[ <p>先日出た Visual Studio 17.1 Preview 3 で、引数 null チェックの簡素化構文が入りました。</p>
<pre class="source" title="引数 null チェックの !!">
<code><span class="method">m</span>(<span class="reserved">null</span>); <span class="comment">// ArgumentNull 例外が出る。</span>

<span class="reserved">void</span> <span class="method">m</span>(<span class="reserved">string</span> <span class="variable">x</span><em>!!</em>) { }
</code></pre>
<h2>展開結果</h2>
<p>上記の <code>void m(string x!!)</code> は以下のように展開されます。
(クラス名は実際には通常の C# では書けない変な名前で生成されます。)</p>
<pre class="source" title="!! の展開結果">
<code><span class="reserved">void</span> <span class="method">m</span>(<span class="reserved">string</span> <span class="variable">x</span>)
{
    <span class="type">Internal</span>.<span class="method">ThrowIfNull</span>(<span class="variable">x</span>, <span class="string">&quot;x&quot;</span>);
}

<span class="reserved">internal</span> <span class="reserved">class</span> <span class="type">Internal</span>
{
    <span class="reserved">internal</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="method">Throw</span>(<span class="reserved">string</span> <span class="variable">paramName</span>)
    {
        <span class="control">throw</span> <span class="reserved">new</span> <span class="type">ArgumentNullException</span>(<span class="variable">paramName</span>);
    }

    <span class="reserved">internal</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="method">ThrowIfNull</span>(<span class="reserved">object</span> <span class="variable">argument</span>, <span class="reserved">string</span> <span class="variable">paramName</span>)
    {
        <span class="control">if</span> (<span class="variable">argument</span> == <span class="reserved">null</span>)
        {
            <span class="method">Throw</span>(<span class="variable">paramName</span>);
        }
    }
}
</code></pre>
<p>もしかしたら、C# 11.0 リリースまでには、internal なコンパイラー生成メソッドではなくて、
標準ライブラリ中の <a href="https://docs.microsoft.com/ja-jp/dotnet/api/system.argumentnullexception.throwifnull"><code>ArgumentNullException.ThrowIfNull</code></a> メソッドに置き変わったりするかもしれませんが、まあ、やってることは一緒です。</p>
<p>ちなみに、<code>ThrowIfNull</code> メソッドから <code>Throw</code> メソッドだけがさらに抽出されているのはその方がパフォーマンスがいいからです。
<code>throw</code> ステートメントがあるとインライン展開を阻害したりするので。</p>
<h2>NRT と相補的な機能</h2>
<p><a href="https://github.com/dotnet/csharplang/issues/2145">初期提案</a>が出たのは2019年の1月頃で、
C# 8.0 (2019年9月リリース)の <a href="https://ufcpp.net/study/csharp/cheatsheet/ap_ver8/#nullable-reference-type">null 許容参照型</a> (略して NRT)と同時期に検討されていたものです。</p>
<p>下手に NRT と同時期だったので紛らわしいのは紛らわしいんですが、</p>
<table>
<thead>
<tr>
	<th>NRT</th>
	<th>引数!!</th>
</tr>
</thead>
<tbody>
<tr>
	<td>コンパイル時のチェック(警告)</td>
	<td>実行時のチェック(例外)</td>
</tr>
<tr>
	<td>コンパイル結果には全く影響を及ぼさない</td>
	<td>コンパイル結果が変わる</td>
</tr>
<tr>
	<td>メタデータに残る(外から見える・区別がある)</td>
	<td>残らない(あくまで内部実装の簡単化)</td>
</tr>
</tbody>
</table>
<p>という感じで、相補的な機能です。</p>
<h2>文法案</h2>
<p>文法的にはちょっと悩ましいんですが… 例えば、</p>
<ul>
<li>
使う記号は何がいいか
<ul>
<li>初期案では <code>!</code> だった</li>
<li>他に <code>??</code>、<code>?? throw</code>、<code>?!</code> みたいな話は出てはいる</li>
<li>結局現在は <code>!!</code></li>
</ul>
</li>
<li>
場所
<ul>
<li>内部実装にしか影響ないのにメソッド宣言部分にあっていいのか</li>
<li><code>void m(string x) { x!! }</code> みたいにメソッドの中になくていいのか</li>
<li>NRT に合わせるなら <code>string?</code> に倣って <code>string! x</code> とかにしなくていいのか </li>
</ul>
</li>
<li>変に記号にせず、汎用的な contract として、<code>requires x is not null</code> とか書けないか</li>
<li><code>&lt;Nullable&gt;throw&lt;/Nullable&gt;</code> みたいなオプションで、問答無用で全ての引数に実行時 null チェックを挟めないか</li>
<li><code>[DisallowNull]</code> みたいな属性ではどうか</li>
</ul>
<p>とかさんざん言われています。</p>
<p>これに対して、</p>
<ul>
<li>
<code>!</code> は <a href="https://ufcpp.net/study/csharp/resource/nullablereferencetype/?p=3#null-forgiving">null 抑止</a>と同じ記号なのがまずい
<ul>
<li>null 抑止は「何もせず警告を無視」、<code>!!</code> は「実行時に例外」で大きな差</li>
</ul>
</li>
<li><code>??</code> は、<a href="https://ufcpp.net/study/csharp/rm_nullusage.html#null-coalesce">null 合体</a>との弁別が構文解析する上で大変</li>
<li><code>?!</code> も条件演算子 + 単項前置き <code>!</code></li>
<li><code>?? throw</code> は単純に長い</li>
<li><code>string!</code> は NRT との混同しててちょっとずれてる。NRT はあくまでコンパイル時チェックだけしたい</li>
<li><code>void m(string x) { x!! }</code> は <code>x</code> を2度書くのが結局つらい</li>
<li>汎用 contract (<code>requres</code>) は、NRT 以前から何度か案が出て、プロトタイプ実装もされては何度も没ってる</li>
<li>全ての引数に実行時 null チェックを挟むのはパフォーマンス的に論外。コンパイル オプションで <code>throw</code> の有無が変わるのもあまり好ましくない</li>
<li>属性が実行時の挙動に大きな影響を及ぼすのはあんまり本望ではない</li>
</ul>
<p>等々ありまして、結局は <code>void m(string x!!)</code> 案で実装されました。</p>
<h2>再燃</h2>
<p>で、<code>!!</code> の実装がリリースされたことで、
先日、dotnet/runtime 内のコードにそれを適用する pull request が出たわけですが。</p>
<ul>
<li><a href="https://github.com/dotnet/runtime/pull/64720">Initial roll out of !!</a></li>
</ul>
<p>約1200ファイル、2万行の差分。</p>
<p>そしてこれが Twitter 上で話題になり、今更ながら反発の声多数。</p>
<p>元々色々もめ気味の機能ですからねぇ。
まして、急に Twitter 上で話題になったことで、
普段 csharplang にいない人が急にわらわらと出てくる事態になり。
2019年にさんざんやった話を蒸し返し中…</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/discussions/5735">Question: How is !! envisaged to be used?</a></li>
</ul>
<p>ほんと、普段こんなに人いないのに…
みんなぬるぽが好きすぎ…</p>
 ]]></description>
				<pubDate>Sun, 13 Feb 2022 13:03:28 +0900</pubDate>
			</item>
			<item>
				<title>【C# 11候補】 ref field</title>
				<link>http://ufcpp.net/blog/2022/2/ref-field/</link>
				<description><![CDATA[ <p>今日は「low level」関連4個目。</p>
<ul>
<li>1個目: <a href="https://ufcpp.net/blog/2022/2/span-optimization/">【C# 11 候補】 ReadOnlySpan 最適化</a></li>
<li>2個目: <a href="https://ufcpp.net/blog/2022/2/params-span/">【C# 11 候補】 params Span</a></li>
<li>3個目: <a href="https://ufcpp.net/blog/2022/2/ref-generic-arguments/">【C# 11 候補】 ref 型引数</a></li>
</ul>
<p>今日は ref フィールドとか、構造体を使ったパフォーマンス改善系の話。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/blob/main/proposals/low-level-struct-improvements.md">Low Level Struct Improvements</a></li>
</ul>
<p>昨年10月の low level hackathon で何かプロトタイプ実装があったわけじゃないですし、提案自体は2020年からあります。
ただ、昨年10月頃から本腰を入れて動き始めているみたいで、
.NET 7 / C# 11 でのリリースに向けて割かし前向きみたいです。</p>
<h2>Span 構造体の中身</h2>
<p><a href="https://ufcpp.net/study/csharp/cheatsheet/ap_ver7_2/">C# 7.2</a> の頃に入った <a href="https://ufcpp.net/study/csharp/resource/span/"><code>Span&lt;T&gt;</code> 構造体</a>ですが、理屈上は以下のような構造体です。</p>
<pre class="source" title="Span&lt;T&gt; の理屈上の中身">
<code><span class="reserved">readonly</span> <span class="reserved">ref</span> <span class="reserved">struct</span> <span class="type">Span</span>&lt;<span class="type">T</span>&gt;
{
    <span class="reserved">private</span> <span class="reserved">readonly</span> <em><span class="reserved">ref</span> <span class="type">T</span> <span class="method">_field</span></em>;
    <span class="reserved">private</span> <span class="reserved">readonly</span> <span class="reserved">int</span> _length;
}
</code></pre>
<p>配列とか、<code>stackalloc</code> で確保したメモリ領域の先頭を <code>ref</code> で持っています。</p>
<p>「理屈上は」と前置きしているのは、この当時 (というか C# 10.0 現在でも)、C# には <code>ref</code> をフィールドに持つ機能がありません。</p>
<p>ちょこっと背景的な話をすると、</p>
<ul>
<li>初期プロトタイプ時点では、<code>Span&lt;T&gt;</code> の中身はポインター (unmanaged なやつ)で実装していた</li>
<li>それで劇的なパフォーマンス改善が得られることが実証された</li>
<li>その後、やっぱりポインター(ガベージ コレクションのトラッキング対象にならない)だとダメで、マネージ参照(要するにガベコレ対象にしたい)が必要という話になった</li>
<li><code>ref</code> フィールドの追加は負担が大きいので、<code>ByReference&lt;T&gt;</code> という特殊な internal 構造体を用意して、それを .NET ランタイム内で特別扱いしてしのいだ</li>
</ul>
<p>という経緯があります。</p>
<p>ということで、C# 10.0 / .NET 6 時点での <code>Span&lt;T&gt;</code> の中身は概ね以下のようになっています。</p>
<pre class="source" title=".NET 6 時点の Span&lt;T&gt; の理屈上の中身">
<code><span class="reserved">public</span> <span class="reserved">readonly</span> <span class="reserved">ref</span> <span class="reserved">struct</span> <span class="type">Span</span>&lt;<span class="type">T</span>&gt;
{
    <span class="reserved">private</span> <span class="reserved">readonly</span> <span class="type">ByReference</span>&lt;<span class="type">T</span>&gt; _pointer;
    <span class="reserved">private</span> <span class="reserved">readonly</span> <span class="reserved">int</span> _length;
}

<span class="reserved">internal</span> <span class="reserved">readonly</span> <span class="reserved">ref</span> <span class="reserved">struct</span> <span class="type">ByReference</span>&lt;<span class="type">T</span>&gt;
{
    <span class="comment">// 形式上こんな定義が入っているものの、ランタイム内で特殊処理して ref T に置き換えてる。</span>
    <span class="reserved">private</span> <span class="reserved">readonly</span> <span class="type">IntPtr</span> _value;

    [<span class="type">Intrinsic</span>]
    <span class="reserved">public</span> <span class="reserved">ref</span> <span class="type">T</span> Value =&gt; <span class="control">throw</span> <span class="reserved">new</span> <span class="type">PlatformNotSupportedException</span>();
}
</code></pre>
<h2>ref がらみの改善</h2>
<p>この <code>Span&lt;T&gt;</code> を導入した当時から、
<code>ByReference&lt;T&gt;</code> の特別扱いがだいぶ「やっつけ」っぽいことは百も承知です。
「いつかは直すべきだが、差し当たって一番需要が高い <code>Span&lt;T&gt;</code> をリリースすることの方が先決」という判定です。</p>
<p>そしてその「いつか」が今ついに来たというのが冒頭で紹介したこの提案。
<code>Span&lt;T&gt;</code> / C# 7.2 が2017年末のことなので、実に5年ぶりの low level の機運。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/blob/main/proposals/low-level-struct-improvements.md">Low Level Struct Improvements</a></li>
</ul>
<p>この提案には複数の機能・目標が含まれていて、以下のようなものがあります。</p>
<ul>
<li><code>ref</code> 構造体に <code>ref</code> フィールドを持てるようにする</li>
<li><code>ByReference&lt;T&gt;</code> の特別扱いをやめて、<code>Span&lt;T&gt;</code> などを普通に <code>ref T</code> を使った実装に置き換えれるようにする</li>
<li><code>ref</code> 構造体が <code>this</code> 参照を <a href="https://ufcpp.net/study/csharp/sp_ref.html?p=2#ref-returns"><code>ref</code> 戻り値</a>で返せるようにする</li>
<li>現在認められていない <code>new Span&lt;T&gt;(ref T reference, int length)</code> みたいなものを、unsafe なしで作れるようにする</li>
<li>固定長バッファーを unsafe なしで作れるようにする</li>
</ul>
<p><code>Span&lt;T&gt;</code> を先にリリースして、<code>ref</code> フィールドが後なので、
互換性のために、エスケープ解析が多少複雑になっている感じはありますが…</p>
<p>ちなみに、C# コンパイラー側だけじゃなく、
ラインタイム側の作業も結構必要になります。
以下のものがトラッキング用の issue。
今日の時点でも結構完了済み。</p>
<ul>
<li><a href="https://github.com/dotnet/runtime/issues/63768">ref field support in .NET runtimes</a></li>
</ul>
 ]]></description>
				<pubDate>Fri, 11 Feb 2022 21:53:43 +0900</pubDate>
			</item>
			<item>
				<title>【C# 11 候補】 ref 型引数</title>
				<link>http://ufcpp.net/blog/2022/2/ref-generic-arguments/</link>
				<description><![CDATA[ <p>今日は「low level」系統の話3個目。</p>
<ul>
<li>1個目: <a href="https://ufcpp.net/blog/2022/2/span-optimization/">【C# 11 候補】 ReadOnlySpan 最適化</a></li>
<li>2個目: <a href="https://ufcpp.net/blog/2022/2/params-span/">【C# 11 候補】 params Span</a></li>
</ul>
<h2>ref 構造体の制限</h2>
<p>今日もさかのぼること C# 7.2 の頃、<a href="https://ufcpp.net/study/csharp/resource/span/"><code>Span&lt;T&gt;</code> 構造体</a>が入ったときの話から。</p>
<p><code>Span&lt;T&gt;</code> 構造体は内部に <code>ref</code> フィールド的なものを持っていて、
変なところ(例えばもう解放したあとの不正な場所)を参照したりしないよう、ヒープ上にコピーできないという制限が掛かっています。
(詳しくは<a href="https://ufcpp.net/study/csharp/resource/refstruct/"><code>ref</code> 構造体</a>で説明しています。)</p>
<p>その制限が守られているかどうかはコンパイラーがちゃんとチェックしているので安全に使えます。
ただ、C# 7.2 時点ではコンパイラーのチェックがまだ貧弱で、
過剰防衛気味になっています。
すなわち、コンパイラーや .NET ランタイムがもう少し頑張れば、
ref 構造体に掛かっている制限は多少緩めることができます。</p>
<p>その「過剰防衛」のうちで深刻なのが以下の2つ。</p>
<ul>
<li><a href="https://ufcpp.net/study/csharp/sp2_generics.html">ジェネリクス</a>の型引数に使えない</li>
<li>インターフェイスを実装できない</li>
</ul>
<h2>デリゲートの型引数に ref T</h2>
<p>で、昨年10月にあった low level hachathon でその制限を緩めるプロトタイプ実装の1つとして、以下のような pull request が出ていました。</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/pull/57135">Support 'ref' type arguments in delegates</a></li>
</ul>
<p>デリゲートはフィールドを一切何も持っていないことがわかっているので、
型引数に <code>ref</code> 構造体を与えても実は問題を起こさないだろうことがわかっています。</p>
<p>そして .NET の型システムは C# のレベルの型システムよりも元からチェックが甘いので、元から <code>ref</code> 構造体や <code>ref T</code> を型引数として与えることができるようです。</p>
<p>ということで、デリゲートに対して <code>ref T</code> を型引数として与えられるようにしたのが上記 pull request。
以下のようなコードが書けるようになります。</p>
<pre class="source" title="デリゲートの ref T 型引数">
<code><span class="type">Func</span>&lt;<em><span class="reserved">ref</span> <span class="reserved">int</span></em>, <em><span class="reserved">ref</span> <span class="reserved">int</span></em>&gt; <span class="variable">f</span> = (<span class="reserved">ref</span> <span class="reserved">int</span> <span class="variable">x</span>) =&gt; <span class="reserved">ref</span> <span class="variable">x</span>;
</code></pre>
<p>デリゲートだけ特別扱いと言うのがちょっと気持ち悪くはあるんですが…</p>
<p>C# 10.0 の<a href="https://ufcpp.net/study/csharp/sp_delegate.html#natural-type">デリゲートの自然の型</a>の仕様も十分気持ち悪いですからね…
「<code>Action</code> や <code>Func</code> で表現できないものは匿名の型を作る」みたいなことをしていて、これはこれで微妙です。</p>
<pre class="source" title="C# 10.0 のデリゲートの自然な型決定">
<code><span class="comment">// C# 10.0 時点では Func&lt;ref int, ref int&gt; というデリゲートは作れないので、</span>
<span class="comment">// しょうがないので delegate ref int Anonymous(ref int x) という匿名のデリゲート型を作ってる。</span>
<span class="reserved">var</span> <span class="variable">f</span> = (<span class="reserved">ref</span> <span class="reserved">int</span> <span class="variable">x</span>) =&gt; <span class="reserved">ref</span> <span class="variable">x</span>;

<span class="reserved">int</span> <span class="variable">x</span> = 10;
<span class="reserved">ref</span> <span class="reserved">var</span> <span class="variable">y</span> = <span class="reserved">ref</span> <span class="variable">f</span>(<span class="reserved">ref</span> <span class="variable">x</span>);
</code></pre>
<h2>ジェネリック型引数に ref 構造体</h2>
<p>デリゲートだけ特別扱いではやっぱりまだ制限が厳しすぎるわけですが。</p>
<p>具体的には、以下のような事をしたいという需要が結構高いです。</p>
<ul>
<li><code>Span&lt;Span&lt;T&gt;&gt;</code> みたいな、入れ子 <code>Span</code> を作りたい</li>
<li><code>Span&lt;T&gt;</code> に <code>ISpanFormattable</code> インターフェイスを実装させたい</li>
</ul>
<p>ということで、これを認めるべく、提案ドキュメントが上がっています。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/pull/5689">Support for ref struct as generic arguments</a></li>
</ul>
<p>これで、例えば以下のようなコードを書けるようになります。</p>
<pre class="source" title="ref struct 制約">
<code><span class="reserved">class</span> <span class="type">Writer</span>
{
    <span class="reserved">void</span> <span class="method">Write</span>&lt;<span class="type">T</span>&gt;(<span class="type">T</span> <span class="variable">value</span>)
        <span class="reserved">where</span> <span class="type">T</span> : <em><span class="reserved">ref</span> <span class="reserved">struct</span>, <span class="type">ISpanFormattable</span></em>
    {
        <span class="type">Span</span>&lt;<span class="reserved">char</span>&gt; <span class="variable">buffer</span> = <span class="reserved">stackalloc</span> <span class="reserved">char</span>[100];

        <span class="comment">// Constrained interface call which does not box</span>
        <span class="control">if</span> (<span class="variable">value</span>.<span class="method">TryFormat</span>(<span class="variable">buffer</span>, <span class="reserved">out</span> <span class="reserved">var</span> <span class="variable">written</span>, <span class="reserved">default</span>, <span class="reserved">null</span>))
        {
            <span class="reserved">this</span>.<span class="method">Write</span>(<span class="variable">buffer</span>);
        }
    }

    <span class="reserved">void</span> <span class="method">Write</span>(<span class="type">ReadOnlySpan</span>&lt;<span class="reserved">char</span>&gt; <span class="variable">data</span>) { <span class="comment">/* 省略 */</span> }
}
</code></pre>
<p>ここでちょっと気持ち悪い点が1つあるんですが…
<code>where T : ref struct</code> は「アンチ制約」になっています。</p>
<p>普通、<code>where</code> で制約を掛けると「何も付けないときよりも渡せる型が減る」という状態になります。
例えば <code>where T : class</code> と書くと参照型しか渡せなくなります。</p>
<p>一方、<code>where T : ref struct</code> の場合は、「無制約だと渡せなかった <code>ref</code> 構造体を渡せるようになる」ということで、「何も付けないときよりも渡せる型が増える」ということになります。
制約が増えてるのではなく減っているので「アンチ制約」。</p>
<p>なので、もしかしたら <code>where</code> とは逆の単語、例えば <code>allow</code> とかを新キーワードとして追加すべきなのかもという話もあったりします。</p>
 ]]></description>
				<pubDate>Mon, 07 Feb 2022 23:34:12 +0900</pubDate>
			</item>
			<item>
				<title>【C# 11 候補】params Span</title>
				<link>http://ufcpp.net/blog/2022/2/params-span/</link>
				<description><![CDATA[ <p>今日は「low level hackathon」話2個目。</p>
<ul>
<li>1個目: <a href="https://ufcpp.net/blog/2022/2/span-optimization/">【C# 11 候補】 ReadOnlySpan 最適化</a></li>
</ul>
<h2>可変長引数</h2>
<p>C# の可変長引数は、一時的にデータを詰めておく配列を作ってメソッドに渡す作りになっています。
例えば、<code>void m(params int[] args)</code> というメソッドがあったとして、
<code>m(1, 2, 3);</code> みたいに呼び出した場合、
<code>m(new int[] { 1, 2, 3 });</code> みたいに展開されます。</p>
<p>ここで問題になるのが <code>new int[]</code> でヒープ アロケーションが発生する点。
あまりにも数が重なると無視できないコストになってきます。</p>
<h2>params Span</h2>
<p>C# 7.2 の頃に <a href="https://ufcpp.net/study/csharp/resource/span/"><code>Span&lt;T&gt;</code> 構造体</a>が入ったことで、
当然 <code>params T[]</code> の <code>new T[]</code> によるアロケーションも避けたいという話が出てきます。</p>
<p>つまるところ、</p>
<ul>
<li>
メソッド定義
<ul>
<li>今あるもの: <code>void m(params T[] args)</code></li>
<li>欲しいもの: <code>void m(params Span&lt;T&gt; args)</code></li>
</ul>
</li>
<li>
呼び出し側の展開結果:
<ul>
<li>今あるもの: <code>m(new int[] { 1, 2, 3 });</code> とか</li>
<li>欲しいもの: <code>m(stackalloc int[] { 1, 2, 3 });</code> とか</li>
</ul>
</li>
</ul>
<p>みたいなものが欲しいと。</p>
<p>実際、案自体は結構昔からあります:</p>
<p><a href="https://github.com/dotnet/csharplang/blob/main/proposals/params-span.md"><code>params Span&lt;T&gt;</code></a></p>
<h2>参照型 stackalloc (没気味)</h2>
<p>ただ、<code>stackalloc</code> の制限が結構きついので、素直に上記のような展開はできません。</p>
<p>わかりやすい原因は、参照型に対して <code>stackalloc</code> を使えない点。
以下のようなコードはコンパイル エラーになります。</p>
<pre class="source" title="参照型の stackalloc は禁止">
<code><span class="type">Span</span>&lt;<span class="reserved"><span class="error">string</span></span>&gt; <span class="variable">span</span> = <span class="reserved">stackalloc</span> <span class="reserved">string</span>[4];
</code></pre>
<p>これは元々ある .NET ランタイムの制限です。</p>
<p>参照型に対する <code>stackalloc</code> を下手に認めてしまうとガベージコレクションの参照トラッキングの負担が上がって、GC 発生時のコストまで見た時トータルではかえって遅くなる可能性が高いとのこと。</p>
<p>この制限に対して、low level hachathon で1回、任意の型に対する <code>stackalloc</code> をやってみる実験をしたみたいです。</p>
<p><a href="https://github.com/dotnet/runtime/pull/60428">Experiment with <code>Unsafe.StackAlloc&lt;T&gt;</code></a></p>
<p>pull request がそっ閉じされてるんで、
やっぱり上記のような <code>stackalloc</code> の問題が許容されなかったんですかね。</p>
<h2>ValueArray</h2>
<p>他に、<code>params Span&lt;T&gt;</code> に使いたいのであれば固定長配列の類でもいいわけでして。
例えば以下のようなコードで「長さ4固定の配列もどき」を作ることはできます。</p>
<pre class="source" title="長さ固定の配列もどき">
<code><span class="reserved">using</span> System.Runtime.InteropServices;

<span class="type">ValueArray4</span>&lt;<span class="reserved">string</span>&gt; <span class="variable">buffer</span> = <span class="reserved">default</span>;
<span class="type">Span</span>&lt;<span class="reserved">string</span>&gt; <span class="variable">span</span> = <span class="type">MemoryMarshal</span>.<span class="method">CreateSpan</span>(<span class="reserved">ref</span> <span class="variable">buffer</span>.X0, 4);

<span class="reserved">struct</span> <span class="type">ValueArray4</span>&lt;<span class="type">T</span>&gt;
{
    <span class="reserved">public</span> <span class="type">T</span> X0, X1, X2, X3;
}
</code></pre>
<p>とはいえ、こんなコードを都度手書きはしたくないわけでして。
あと、できれば <code>ValueArray&lt;string, 4&gt;</code> みたいな感じで何らかの手段で「長さ」の情報はジェネリクス的に渡したかったりはします。</p>
<p>それに類するものをとりあえず実装してみたという pull request が low level hackathon で出てたりします。</p>
<p><a href="https://github.com/dotnet/runtime/pull/60519">[hackathon] ValueArray</a></p>
<p>「試しにやってみた」実装なのでなかなかにキモイです…
現状の .NET は「ジェネリクスに型引数代わりに整数を渡す」みたいなことができないので、
1 の代わりに <code>object[]</code>、2 の代わりに <code>object[,]</code>、3 の代わりに <code>object[,,]</code>、… みたいな、<code>object</code> 配列の次元を整数代わりに使うというすごい実装。
本来であれば <code>ValueArray&lt;string, 4&gt;</code> と書きたいところを <code>ValueArray&lt;string, object[,,,]&gt;</code> と書くことになります…</p>
<pre class="source" title="object[,,,] でジェネリック整数引数を代用…">
<code><span class="reserved">using</span> System.Runtime.InteropServices;

<span class="type">ValueArray</span>&lt;<span class="reserved">string</span>, <span class="reserved">object</span>[,,,]&gt; <span class="variable">buffer</span> = <span class="reserved">default</span>;
<span class="type">Span</span>&lt;<span class="reserved">string</span>&gt; <span class="variable">span</span> = <span class="variable">buffer</span>.<span class="method">AsSpan</span>();
</code></pre>
<p>これはさすがにあまりにもきもいので没気味。
代替案として、「いったん属性を付けて特殊処理しようか」みたいな話になっています。</p>
<p>こちらだと、いちいち構造体の定義が要るみたいです。</p>
<pre class="source" title="InlineArray 属性">
<code><span class="reserved">using</span> System.Runtime.InteropServices;

<span class="type">ValueArray4</span>&lt;<span class="reserved">string</span>&gt; <span class="variable">buffer</span> = <span class="reserved">default</span>;
<span class="type">Span</span>&lt;<span class="reserved">string</span>&gt; <span class="variable">span</span> = <span class="variable">buffer</span>.<span class="method">AsSpan</span>();

<span class="comment">// この属性を付けた構造体は T 4つ分のメモリを確保する。</span>
[<span class="type">InlineArray</span>(Length = 4)]
<span class="reserved">struct</span> <span class="type">ValueArray4</span>&lt;<span class="type">T</span>&gt;
{
    <span class="reserved">private</span> <span class="type">T</span> _element0;
    <span class="reserved">public</span> <span class="type">Span</span>&lt;<span class="type">T</span>&gt; <span class="method">AsSpan</span>() =&gt; <span class="type">MemoryMarshal</span>.<span class="method">CreateSpan</span>(<span class="reserved">ref</span> _element0, 4);
}
</code></pre>
<p>やっぱ、根本的にはジェネリクスに整数を渡せるようにしてほしいところですけどね…
それは結構型システムに手を入れないといけないみたいでちょっと大変みたいです。</p>
 ]]></description>
				<pubDate>Fri, 04 Feb 2022 23:07:02 +0900</pubDate>
			</item>
			<item>
				<title>【C# 11 候補】 ReadOnlySpan 最適化</title>
				<link>http://ufcpp.net/blog/2022/2/span-optimization/</link>
				<description><![CDATA[ <p><a href="https://github.com/dotnet/runtime">dotnet/runtime</a>のコミット履歴とかにうっすら痕跡が見て取れるんですが、
去年の10月中旬頃、
「low level hackathon」とかいう Microsoft 社内イベントをやっていたみたいです。</p>
<p>今、<a href="https://ufcpp.net/study/csharp/cheatsheet/ap_ver7_2/">C# 7.2</a>とかの頃に <a href="https://ufcpp.net/study/csharp/resource/span/"><code>Span&lt;T&gt;</code> 構造体</a>が追加されて以来の4年ぶりくらいの動きになりますが、
.NET ランタイムの低層に手を入れてパフォーマンス改善を図りたい流れになっているみたいです。</p>
<p>その後の様子を見るに、これは昨年10月の hackathon 時だけの短期的なブームというわけでもなくて、割かし .NET 7 目標にちゃんと動き出している雰囲気です。</p>
<p>ということで、今日の分のブログから数回はこの手の low level なパフォーマンス改善系の話をしていこうかと思います。</p>
<h2>定数配列</h2>
<p>今日は、以下のような、
全要素が定数の配列を書いたときの最適化の話になります。</p>
<pre class="source" title="全要素が定数の配列">
<code><span class="type">ReadOnlySpan</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">data</span> = <span class="reserved">new</span>[] { 1, 2, 3, 4, 5, 6, 7, 8 };
</code></pre>
<p>例えば以下のような2つのメソッドを比べてみましょう。</p>
<pre class="source" title="ReadOnlySpan int と sbyte">
<code><span class="reserved">static</span> <span class="reserved">int</span> <span class="method">M1</span>(<span class="reserved">int</span> <span class="variable">i</span>)
{
    <span class="type">ReadOnlySpan</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">table</span> = <span class="reserved">new</span>[] { 1, 0, -1, 0 }; <span class="comment">// 差はこの行だけ</span>
    <span class="control">return</span> <span class="variable">table</span>[<span class="variable">i</span> % 4];
}

<span class="reserved">static</span> <span class="reserved">int</span> <span class="method">M2</span>(<span class="reserved">int</span> <span class="variable">i</span>)
{
    <span class="type">ReadOnlySpan</span>&lt;<span class="reserved">sbyte</span>&gt; <span class="variable">table</span> = <span class="reserved">new</span> <span class="reserved">sbyte</span>[] { 1, 0, -1, 0 }; <span class="comment">// 差はこの行だけ</span>
    <span class="control">return</span> <span class="variable">table</span>[<span class="variable">i</span> % 4];
}
</code></pre>
<p>4要素の定数テーブルを引いているだけのシンプルなコードです。
<code>M1</code> と <code>M2</code> の差はテーブルが <code>int</code> か <code>sbyte</code> かという点だけになりますが、
(少なくとも .NET 6 / C# 10.0 では) この差だけでパフォーマンスが数倍違います。</p>
<p><a href="https://gist.github.com/ufcpp/6326920e1fefe48a91c6f11a05ae9b6e">ベンチマーク用コード</a></p>
<p>一番大きな差は、</p>
<ul>
<li><code>int</code> の方は普通に配列が <code>new</code> されている (newarr 命令が発行されてる)</li>
<li><code>sbyte</code> の方は 生データが直接参照されて、<code>new ReadOnlySpan(void*, int)</code> が呼ばれている</li>
</ul>
<p>という点になります。
その結果、配列のヒープ アロケーションが発生するかどうかでパフォーマンスに大きな差が出ます。
(<code>int</code> の方がだいぶ遅い。)</p>
<h3>エンディアン</h3>
<p>C# 10.0 な現状、この手の最適化は <code>byte</code> と <code>sbyte</code> に対してしか掛からないという制限があります。</p>
<p>理由は主にエンディアンで、
一応、.NET ランタイムはビッグエンディアンにも対応しているので、
<code>new[] { 1, 2, ... }</code> と書いてバイト列としてデータを記録するとき、
<code>0, 0, 0, 1, 0, 0, 0, 2, ...</code> と並べるか、
<code>1, 0, 0, 0, 2, 0, 0, 0, ...</code> と並べるかという問題があります。</p>
<p>とはいえ、これは別に今までの「要素が全部定数の配列」でも同じ問題はあって、</p>
<ul>
<li>DLL 中にデータが埋め込まれる場合、.NET はリトルエンディアン</li>
<li>埋め込みデータから配列を作るときに <code>RuntimeHelpers.InitializeArray</code> メソッドを呼ぶ</li>
<li><code>InitializeArray</code> の中で、ビッグエンディアン環境だったらエンディアンをひっくり返す処理が入っている</li>
</ul>
<p>みたいな動作をしているみたいです。</p>
<h2>CreateSpan</h2>
<p>ならまあ、やるべきことは割かしわかりやすいわけでして。
埋め込みデータから直接 <code>ReadOnlySpan</code> を作る部分を <code>InitializeArray</code> と同様のヘルパー メソッドにして、
ビッグエンディアン環境だったらひっくり返す処理を挟めばいいということになります。</p>
<p>それがこちら:</p>
<p><a href="https://github.com/dotnet/runtime/pull/60451">Add non-intrinsic implementation for <code>CreateSpan&lt;T&gt;</code>.`</a></p>
<p>Roslyn (C# コンパイラー)側の対応:</p>
<p><a href="https://github.com/dotnet/roslyn/pull/57123">RuntimeHelpers.CreateSpan optimization for stackalloc</a></p>
<p>dotnet/runtime 内で既存コードに対してこれを前提にした最適化を掛けたもの:</p>
<p><a href="https://github.com/dotnet/runtime/pull/60327">Experiment with Roslyn optimization for <code>ROS&lt;T&gt;</code> in assembly data section</a></p>
<p>これが正式に採用されれば、
最初に例に挙げた <code>M1</code> メソッドと <code>M2</code> メソッドのパフォーマンス差はもう少し縮まるはずです。</p>
 ]]></description>
				<pubDate>Tue, 01 Feb 2022 22:13:09 +0900</pubDate>
			</item>
			<item>
				<title>nullable 警告もみ消し(来年までの我慢)の手段</title>
				<link>http://ufcpp.net/blog/2022/1/nullable-property-disable/</link>
				<description><![CDATA[ <p>今日はとあるアンケートの結果を乗せておこう的な話。</p>
<h2>背景: 非 null プロパティの初期化</h2>
<p><a href="https://ufcpp.net/study/csharp/resource/nullablereferencetype/">null 許容参照型</a>の仕様が入って以来、以下のようなコードに警告が出るようになりました。</p>
<pre class="source" title="NRT 警告がどうしても出てしまう例">
<code><span class="reserved">class</span> <span class="type">A</span>
{
    <span class="reserved">public</span> <span class="reserved">string</span> <span class="warning">X</span>;
    <span class="reserved">public</span> <span class="reserved">string</span> <span class="warning">Y</span> { <span class="reserved">get</span>; <span class="reserved">set</span>; }
    <span class="reserved">public</span> <span class="reserved">string</span> <span class="warning">Z</span> { <span class="reserved">get</span>; <span class="reserved">init</span>; }
}
</code></pre>
<p>C# 10.0 現在、この警告を回避する唯一の方法は「ちゃんとコンストラクターで初期化すること」です。</p>
<pre class="source" title="C# 10.0 現在の唯一の回避方法">
<code><span class="reserved">class</span> <span class="type">A</span>
{
    <span class="reserved">public</span> <span class="reserved">string</span> X;
    <span class="reserved">public</span> <span class="reserved">string</span> Y { <span class="reserved">get</span>; <span class="reserved">set</span>; }
    <span class="reserved">public</span> <span class="reserved">string</span> Z { <span class="reserved">get</span>; <span class="reserved">init</span>; }

    <span class="reserved">public</span> <span class="type">A</span>(<span class="reserved">string</span> <span class="variable">x</span>, <span class="reserved">string</span> <span class="variable">y</span>, <span class="reserved">string</span> <span class="variable">z</span>) =&gt; <em>(X, Y, Z) = (<span class="variable">x</span>, <span class="variable">y</span>, <span class="variable">z</span>)</em>;
}
</code></pre>
<p>困るのが、「このプロパティは <code>new() { X = &quot;&quot;, Y = &quot;&quot;, Z = &quot;&quot; }</code> みたいに初期化子で初期化したい」という場面。
結構あると思うんですよね、コンストラクターを定義したくない・できないとき。
今のところいい解決策がない状態です。</p>
<h3>【将来予定】 required</h3>
<p>一応補足。
将来的には解消する予定です。
今のところ C# 11.0 目標で、<code>required</code> 修飾子を付けるという案が進められています。</p>
<pre class="source" title="required 修飾子">
<code><span class="reserved">class</span> <span class="type">A</span>
{
    <span class="reserved">public</span> <span class="reserved"><em>required</em></span> <span class="reserved">string</span> X;
    <span class="reserved">public</span> <span class="reserved"><em>required</em></span> <span class="reserved">string</span> Y { <span class="reserved">get</span>; <span class="reserved">set</span>; }
    <span class="reserved">public</span> <span class="reserved"><em>required</em></span> <span class="reserved">string</span> Z { <span class="reserved">get</span>; <span class="reserved">init</span>; }
}
</code></pre>
<p>これが付いていると、オブジェクト初期化子で非 null な値を渡すことを義務付けられるようになるので、クラス定義側には警告が出なくなります。</p>
<pre class="source" title="required の効果">
<code><span class="reserved">var</span> <span class="variable">a1</span> = <span class="reserved">new</span> <span class="type"><span class="warning">A</span></span>(); <span class="comment">// required プロパティ/フィールドに値を与えていないので警告</span>

<span class="reserved">var</span> <span class="variable">a2</span> = <span class="reserved">new</span> <span class="type">A</span>()
{
    X = <span class="reserved"><span class="warning">null</span></span>, <span class="comment">// null を与えたので警告</span>
};

<span class="comment">// required プロパティ/フィールド全てにちゃんと値を与えたのでOKに</span>
<span class="reserved">var</span> <span class="variable">a3</span> = <span class="reserved">new</span> <span class="type">A</span>()
{
    X = <span class="string">&quot;&quot;</span>,
    Y = <span class="string">&quot;&quot;</span>,
    Z = <span class="string">&quot;&quot;</span>,
};
</code></pre>
<h2>現状の回避策</h2>
<p>ということで、<code>required</code> によって来年には根本解決の当てがあるわけですが。
そうなると、今現在 <code>A</code> の作者が頑張って回避策を取る必要もないよなぁ…
ということになって、
「来年まではやっつけ対処でもみ消ししとこう」という発想になります。</p>
<p>ただ、
こういうやっつけほど具体的にどう対処しようか迷います。
また、もみ消しにいくつかの手段があるのでその点もちょっと迷うポイント。</p>
<p>ということでアンケート。</p>
<h3>選択肢</h3>
<p>選択肢1. 該当行を <code>nullable disable</code></p>
<pre class="source" title="nullable disable">
<code><span class="reserved">class</span> <span class="type">A</span>
{
<span class="preprocess">#</span><span class="preprocess">nullable</span> <span class="preprocess">disable</span> <span class="preprocess">warnings</span>
    <span class="reserved">public</span> <span class="reserved">string</span> X;
    <span class="reserved">public</span> <span class="reserved">string</span> Y { <span class="reserved">get</span>; <span class="reserved">set</span>; }
    <span class="reserved">public</span> <span class="reserved">string</span> Z { <span class="reserved">get</span>; <span class="reserved">init</span>; }
<span class="preprocess">#</span><span class="preprocess">nullable</span> <span class="preprocess">restore</span> <span class="preprocess">warnings</span>
}
</code></pre>
<p>選択肢2. 該当行を <code>pragma warning disable</code></p>
<pre class="source" title="pragma warning disable">
<code><span class="reserved">class</span> <span class="type">A</span>
{
<span class="preprocess">#</span><span class="preprocess">pragma</span> <span class="preprocess">warning</span> <span class="preprocess">disable</span> CS8618
    <span class="reserved">public</span> <span class="reserved">string</span> X;
    <span class="reserved">public</span> <span class="reserved">string</span> Y { <span class="reserved">get</span>; <span class="reserved">set</span>; }
    <span class="reserved">public</span> <span class="reserved">string</span> Z { <span class="reserved">get</span>; <span class="reserved">init</span>; }
<span class="preprocess">#</span><span class="preprocess">pragma</span> <span class="preprocess">warning</span> <span class="preprocess">restore</span> CS8618
}
</code></pre>
<p>選択肢3. とりあえず <code>default!</code> や <code>null!</code> を代入</p>
<pre class="source" title="null!">
<code><span class="reserved">class</span> <span class="type">A</span>
{
    <span class="reserved">public</span> <span class="reserved">string</span> X = <span class="reserved">null</span>!;
    <span class="reserved">public</span> <span class="reserved">string</span> Y { <span class="reserved">get</span>; <span class="reserved">set</span>; } = <span class="reserved">null</span>!;
    <span class="reserved">public</span> <span class="reserved">string</span> Z { <span class="reserved">get</span>; <span class="reserved">init</span>; } = <span class="reserved">null</span>!;
}
</code></pre>
<p>選択肢4. ノーガード。警告出っぱなしなのをあきらめる</p>
<pre class="source" title="あきらめて警告出っぱなし">
<code><span class="reserved">class</span> <span class="type">A</span>
{
    <span class="reserved">public</span> <span class="reserved">string</span> <span class="warning">X</span>;
    <span class="reserved">public</span> <span class="reserved">string</span> <span class="warning">Y</span> { <span class="reserved">get</span>; <span class="reserved">set</span>; }
    <span class="reserved">public</span> <span class="reserved">string</span> <span class="warning">Z</span> { <span class="reserved">get</span>; <span class="reserved">init</span>; }
}
</code></pre>
<h3>結果</h3>
<p>C# 配信中にこの話題になり、
配信真っ最中に Twitter アンケートを作って投票してもらったり。</p>
<p><a href="https://twitter.com/ufcpp/status/1434168597060853760">https://twitter.com/ufcpp/status/1434168597060853760</a></p>
<p><code>!</code> でもみ消し派が35%くらいでちょっと多めですね。
まあ思ったよりは差が広がらず。</p>
 ]]></description>
				<pubDate>Fri, 28 Jan 2022 20:49:46 +0900</pubDate>
			</item>
			<item>
				<title>【C# 11 候補】 トップ レベル ステートメントの Main に属性を付ける</title>
				<link>http://ufcpp.net/blog/2022/1/main-attribute/</link>
				<description><![CDATA[ <p>ちょっと体調崩し気味だったので軽いネタに逃げる感じでわかりやすい C# 11 候補を1つ。</p>
<p><a href="https://github.com/dotnet/csharplang/issues/5045">トップ レベル ステートメント(が作る <code>Main</code> メソッド)に属性を付けたい</a>という話があります。</p>
<p>もう、割かし以下の利用例1個で説明終わりな感じ。</p>
<pre class="source" title="main: 属性">
<code>[<span class="reserved"><em>main</em></span>: <span class="type">STAThread</span>]

<span class="reserved">using</span> System.Windows;

<span class="type">Clipboard</span>.<span class="method">SetData</span>(<span class="type">DataFormats</span>.Text, <span class="type">Environment</span>.OSVersion.<span class="method">ToString</span>());
</code></pre>
<p>今、これと同じことをしようと思ったら、これだけのために <code>class Program { static void Main() { } }</code> が必要です。</p>
<p>とはいえ、<code>Main</code> メソッドに付けたい属性って <code>STAThread</code> 以外に何かありますかね？</p>
<p>という意味でニッチな需要ではあるんですけど、まあ、実装コストも低そうなので割かしやる気みたいです。</p>
 ]]></description>
				<pubDate>Tue, 25 Jan 2022 21:27:32 +0900</pubDate>
			</item>
			<item>
				<title>MemberNotNull (値型) 判定</title>
				<link>http://ufcpp.net/blog/2022/1/member-not-null/</link>
				<description><![CDATA[ <p>こないだ、[null フロー解析]と似たノリで、<a href="https://ufcpp.net/blog/2022/1/defaultable/">構造体の default フロー解析が必要</a>という話をしました。</p>
<p>まあ、難航しそうではあるんですが…</p>
<p>とはいえ実は現在でも、「null チェックといいつつ、構造体に対しても働くフロー解析」があったりします。</p>
<h2>MemberNotNull</h2>
<p><a href="https://ufcpp.net/study/csharp/resource/nullablereferencetype/#opt-in">nullable enable</a> のとき、
非 null 参照型のフィールドやプロパティは、
コンストラクター内でちゃんと初期化する必要があります。</p>
<p>例えば以下のコードはプロパティ定義の行に警告。</p>
<pre class="source" title="非 null 参照型のプロパティが未初期化">
<code><span class="reserved">class</span> <span class="type">C</span>
{
    <span class="reserved">public</span> <span class="reserved">string</span> <span class="warning">S</span> { <span class="reserved">get</span>; } <span class="comment">// CS8618 警告</span>
}
</code></pre>
<p>以下のようにコンストラクターを足すと、今度はコンストラクターの行に警告。</p>
<pre class="source" title="コンストラクター内でも非 null 参照型のプロパティが未初期化">
<code><span class="reserved">class</span> <span class="type">C</span>
{
    <span class="reserved">public</span> <span class="reserved">string</span> S { <span class="reserved">get</span>; }
    <span class="reserved">public</span> <span class="type"><span class="warning">C</span></span>() { } <span class="comment">// CS8618 警告</span>
}
</code></pre>
<p>以下のように書くと警告は消えるんですが、</p>
<pre class="source" title="ちゃんと非 null 値で初期化したので OK に">
<code><span class="reserved">class</span> <span class="type">C</span>
{
    <span class="reserved">public</span> <span class="reserved">string</span> S { <span class="reserved">get</span>; }
    <span class="reserved">public</span> <span class="type">C</span>()
    {
        S = <span class="string">&quot;値は適当&quot;</span>; <span class="comment">// これで警告が消える。</span>
    }
}
</code></pre>
<p>これをメソッド抽出してしまうと再び警告が出ます。</p>
<pre class="source" title="初期化コードはコンストラクターに直にないとダメ">
<code><span class="reserved">class</span> <span class="type">C</span>
{
    <span class="reserved">public</span> <span class="reserved">string</span> S { <span class="reserved">get</span>; <span class="reserved">private</span> <span class="reserved">set</span>; }

    <span class="reserved">public</span> <span class="type"><span class="warning">C</span></span>() <span class="comment">// 再び CS8618</span>
    {
        <span class="method">Initialize</span>();
    }

    <span class="reserved">private</span> <span class="reserved">void</span> <span class="method">Initialize</span>()
    {
        S = <span class="string">&quot;値は適当&quot;</span>;
    }
}
</code></pre>
<p>null 許容参照型の初期リリースではこの問題を回避する手段はなかったんですが、後々、<a href="https://ufcpp.net/study/csharp/resource/nullablereferencetype/?p=4#MemberNotNull"><code>MemberNotNull</code></a> という属性が追加されていて、
以下のように書けば警告をなくすことができるようになりました。</p>
<pre class="source" title="MemberNotNull 属性">
<code><span class="reserved">using</span> System.Diagnostics.CodeAnalysis;

<span class="reserved">class</span> <span class="type">C</span>
{
    <span class="reserved">public</span> <span class="reserved">string</span> S { <span class="reserved">get</span>; <span class="reserved">private</span> <span class="reserved">set</span>; }

    <span class="reserved">public</span> <span class="type">C</span>()
    {
        <span class="method">Initialize</span>();
    }

    [<span class="type">MemberNotNull</span>(<span class="reserved">nameof</span>(S))]
    <span class="reserved">private</span> <span class="reserved">void</span> <span class="method">Initialize</span>()
    {
        S = <span class="string">&quot;値は適当&quot;</span>; <span class="comment">// 逆に、この行を消すと CS8774 警告。</span>
    }
}
</code></pre>
<h2>値型に対して MemberNotNull</h2>
<p>そしてここでようやく本題。</p>
<p><code>MemberNotNull</code> なんて名前をしていますが、
実際には「値を代入したかどうか」を見ているようで、
値型に対しても使えたりします。</p>
<pre class="source" title="MemberNotNull(値型プロパティ)">
<code><span class="reserved">using</span> System.Diagnostics.CodeAnalysis;

<span class="reserved">class</span> <span class="type">C</span>
{
    <span class="reserved">public</span> <span class="type">DateOnly</span> D { <span class="reserved">get</span>; <span class="reserved">private</span> <span class="reserved">set</span>; }
    <span class="reserved">public</span> <span class="type">C</span>() = &gt; <span class="method">Initialize</span>();

    [<span class="type">MemberNotNull</span>(<span class="reserved">nameof</span>(D))]
    <span class="reserved">private</span> <span class="reserved">void</span> <span class="method">Initialize</span>()
    {
    <span class="warning">}</span> <span class="comment">// CS8774</span>
    <span class="comment">// member not &quot;null&quot; と言いつつ、非 null が確定している値型に対してもフロー解析してる。</span>
}
</code></pre>
<p>「代入したかどうか」しか調べてない雰囲気？</p>
<p>代入さえされていれば <code>D = default;</code> でも警告が消えたりします。
(C# 10.0 時点では。)</p>
<pre class="source" title="D = default でもよかったりする">
<code><span class="reserved">using</span> System.Diagnostics.CodeAnalysis;

<span class="reserved">class</span> <span class="type">C</span>
{
    <span class="reserved">public</span> <span class="type">DateOnly</span> D { <span class="reserved">get</span>; <span class="reserved">private</span> <span class="reserved">set</span>; }
    <span class="reserved">public</span> <span class="type">C</span>() =&gt; <span class="method">Initialize</span>();

    [<span class="type">MemberNotNull</span>(<span class="reserved">nameof</span>(D))]
    <span class="reserved">private</span> <span class="reserved">void</span> <span class="method">Initialize</span>()
    {
        D = <span class="reserved">default</span>; <span class="comment">// これでも OK。</span>
    }
}
</code></pre>
<p>ということで、<a href="https://ufcpp.net/blog/2022/1/defaultable/">defaultable value type</a> の仕様が入るまではまだ機能不足ではあるんですが。
とりあえず、<code>MemberNotNull</code> に対して値型のプロパティを渡せなくするみたいな処理をあえて入れたりはしていないようです。
将来的に defaultable value type のフロー解析もあるだろう見込みがあるのではじかないようにしてあるんじゃないかなぁと思います。</p>
 ]]></description>
				<pubDate>Tue, 11 Jan 2022 20:34:58 +0900</pubDate>
			</item>
			<item>
				<title>【Visual Studio】 Naming Style 設定</title>
				<link>http://ufcpp.net/blog/2022/1/naming-style/</link>
				<description><![CDATA[ <p>こないだの <a href="https://youtu.be/lxr0QlZR0M4">C# 配信</a>で、
「フィールドの naming style を <code>_camelCase</code> にするための設定を .editorconfig で書いておきたい」という話になったやつ。</p>
<p><a href="https://youtu.be/lxr0QlZR0M4?t=7072">.editorconfig がらみの話になったのは 1:57:52 頃～</a></p>
<h2>private/internal フィールドの名前規約</h2>
<p>長らく C#/.NET 方面は private なところの規約についてはそこまでうるさく言われない文化だったりしたのでそこまで統一見解はないんですが、
皆様は private フィールドの名前をどうしていますでしょうか。</p>
<p>最近では、 <a href="https://github.com/dotnet/runtime">dotnet/runtime</a> が <code>_</code> 開始の <code>camelCase</code> を採用したということで、このルールを支持する人が増えたというか、
<code>this.x</code> 派だった人も「dotnet/runtime がそういうのなら」という感じでちらほら改宗していたりはします。</p>
<pre class="source" title="_ 始まり推奨">
<code><span class="reserved">class</span> <span class="type">C</span>
{
    <span class="reserved">private</span> <span class="type">DateTime</span> <em>_date</em>;
}
</code></pre>
<p>ところで、以下のスクショをご覧ください。
(フィールドに対する名前の提案。)</p>
<p><img src="/media/1206/suggestedname1.png" alt="Visual Studio が提案してくる名前(元)" /></p>
<p>Visual Studio を触っている人なら1度は思ったことがあると思うんですが、
「あっ、そこは <code>_</code> 付けてくれないんだ…」</p>
<h2>Naming Style 設定</h2>
<p>ということで、<a href="https://twitter.com/okazuki">okazuki さん</a>曰く、
ちゃんと <code>_</code> 始まりで提案してもらえるように設定を入れているとのこと。</p>
<p>.editorconfig に以下のような行を入れておくと <code>_</code> 始まりになります。</p>
<pre class="source" title="begin_with__">
<code>[*.{cs,vb}]

dotnet_naming_rule.private_or_internal_field_should_be_begin_with__.severity = suggestion
dotnet_naming_rule.private_or_internal_field_should_be_begin_with__.symbols = <span style="color:blue">private_or_internal_field</span>
dotnet_naming_rule.private_or_internal_field_should_be_begin_with__.style = <span style="color:red">begin_with__</span>

dotnet_naming_symbols.<span style="color:blue">private_or_internal_field</span>.applicable_kinds = field
dotnet_naming_symbols.<span style="color:blue">private_or_internal_field</span>.applicable_accessibilities = internal, private
dotnet_naming_symbols.<span style="color:blue">private_or_internal_field</span>.required_modifiers = 

dotnet_naming_style.<span style="color:red">begin_with__</span>.required_prefix = _
dotnet_naming_style.<span style="color:red">begin_with__</span>.required_suffix = 
dotnet_naming_style.<span style="color:red">begin_with__</span>.word_separator = 
dotnet_naming_style.<span style="color:red">begin_with__</span>.capitalization = camel_case
</code></pre>
<p>(style, symbols, rule の3つ組が必要みたいです。)</p>
<p>この状態で先ほどと同じ変数名の提案を出すと以下のように変化します。</p>
<p><img src="/media/1207/suggestedname2.png" alt="Visual Studio が提案してくる名前(設定追加後)" /></p>
<p>ちなみに、こんな構文＆変数名、覚えられるわけもなく、okazuki さんは Visual Studio 上のオプション画面でこの設定を入れて、.editorconfig にエクスポートして使っていたそうです。</p>
<p>そこに、Visual Studio 17.1 Preview 2 の .editorconfig の GUI 設定画面に Naming Style のタブが増えたということで期待しているという状態。
(といっても、 .editorconfig GUI では &quot;<code>begin_with__</code>&quot; みたいな新規スタイル追加はできないっぽくてまだまだいまいちな感じ。)</p>
 ]]></description>
				<pubDate>Mon, 10 Jan 2022 20:42:57 +0900</pubDate>
			</item>
			<item>
				<title>【C# 11 候補】defaultable value type</title>
				<link>http://ufcpp.net/blog/2022/1/defaultable/</link>
				<description><![CDATA[ <p><a href="https://ufcpp.net/blog/2021/12/immutable-array-init/"><code>ImmutableArray</code> に対してコレクション初期化子は使えないという話</a>でちょっと出しましたが、この問題の原因の1つは「<a href="https://ufcpp.net/study/csharp/rm_default.html">既定値</a>(<code>default</code>、0初期化)のまま放置してはいけない型がある」というものです。</p>
<p><code>default</code> 放置問題は「null を null のまま放置してはいけない」という問題に直結するので、
<a href="https://ufcpp.net/study/csharp/resource/nullablereferencetype/">null 許容参照型</a>とも関連します。</p>
<p>ということで「<a href="https://github.com/dotnet/csharplang/discussions/5337">クラスの <code>null</code> 解析と同様に、構造体の <code>default</code> に関するフロー解析を行う</a>」という提案が前々からあるんですが。
状況としては「提案のドラフトは書いてみたけど、まだ思い悩んでる点があって、Design Meeting に議題を上げる段階にない」みたいな感じです。</p>
<h2>default 放置問題</h2>
<p>C# 8.0 で<a href="https://ufcpp.net/study/csharp/resource/nullablereferencetype/">null 許容参照型</a>(nullable reference type、通称 NRT)が入って、以下のように、null 参照例外が出そうな箇所にはコンパイル時に警告を出してくれるようになりました。</p>
<pre class="source" title="C# 8.0 の NRT">
<code><span class="preprocess">#</span><span class="preprocess">nullable</span> <span class="preprocess">enable</span>

<span class="comment">// 警告: ? が付いてない変数に null を渡してる。</span>
<span class="reserved">string</span> <span class="variable">s</span> = <span class="reserved"><span class="warning">null</span></span>;

<span class="comment">// この行でも警告: s に null が入ってることを認識してる。</span>
<span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="variable"><span class="warning">s</span></span>.Length);

<span class="comment">// OK</span>
<span class="reserved">string</span>? <span class="variable">n</span> = <span class="reserved">null</span>;

<span class="comment">// 警告: null かもしれないもののメンバー参照してる。</span>
<span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="variable"><span class="warning">n</span></span>.Length);

<span class="comment">// これなら OK: not null 判定してるのでメンバー参照してももう大丈夫。</span>
<span class="control">if</span> (<span class="variable">n</span> <span class="reserved">is</span> <span class="reserved">not</span> <span class="reserved">null</span>) <span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="variable">n</span>.Length);
</code></pre>
<p>この解析は「できる範囲で、できることからやる」みたいな感じなので結構判定漏れもあるんですが。
その判定漏れの中で特に深刻なのが、構造体の <code>default</code> を挟んだ場合。</p>
<p>例えば以下のようなコードで、簡単に判定から漏れた null を残せます。</p>
<pre class="source" title="default を介して null が紛れ込む例">
<code><span class="preprocess">#</span><span class="preprocess">nullable</span> <span class="preprocess">enable</span>

<span class="comment">// これは警告にしてもらえる: 非 null な S に null を渡した。</span>
<span class="type">A</span> <span class="variable">a1</span> = <span class="reserved">new</span>(<span class="reserved"><span class="warning"null</span></span>);
<span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="variable">a1</span>.S.Length); <span class="comment">// OK</span>

<span class="comment">// これだと警告が出ない: default に対する解析がまだない(提案段階)。</span>
<span class="type">A</span> <span class="variable">a</span> = <span class="reserved">default</span>;
<span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="variable">a</span>.S.Length); <span class="comment">// OK じゃないんだけど OK になる</span>

<span class="comment">// S は非 null なはず。</span>
<span class="reserved">record</span> <span class="reserved">struct</span> <span class="type">A</span>(<span class="reserved">string</span> <span class="variable">S</span>);
</code></pre>
<p>この問題を一番深刻に踏み抜いてるのが、
最近のブログで何度か出て来た <a href="https://ufcpp.net/blog/2021/12/immutable-array-init/"><code>ImmutableArray</code></a> なわけです。</p>
<pre class="source" title="ImmutableArray の default によるぬるぽ">
<code><span class="preprocess">#</span><span class="preprocess">nullable</span> <span class="preprocess">enable</span>
<span class="reserved">using</span> System.Collections.Immutable;

<span class="reserved">var</span> <span class="variable">a</span> = <span class="reserved">new</span> <span class="type">ImmutableArray</span>&lt;<span class="reserved">int</span>&gt;();

<span class="comment">// コードのぱっと見の印象からすると 0 とか返ってきて欲しい。</span>
<span class="comment">// 実際にはぬるぽ発生。</span>
<span class="comment">// ぬるぽるんだったら、NRT 警告みたいなの出してほしい(これが課題)。</span>
<span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="variable">a</span>.Length);
</code></pre>
<h2>defaultable value type</h2>
<p>この問題に対する解決策、方向性としてはシンプルで、
「参照型に対して null を認めないようにフロー解析する」というのと同じノリで、「値型に対して <code>default</code> を認めないようにフロー解析する」というやり方で解決できるはずです。
それが今回説明する<a href="https://github.com/dotnet/csharplang/discussions/5337">defaultable value type</a> (default 許容値型)。
nullable reference type (null 許容参照型)との対比でこんな名前になっています。</p>
<p>要は、</p>
<ul>
<li><code>ImmutableArray</code> みたいな型に対して <code>default</code> を渡しているところには警告を出す</li>
<li>
あえて <code>default</code> を渡したい箇所には、NRT の <code>T?</code> に類する何か(仮に <code>T~</code> とか書く)みたいなアノテーションを付ける
<ul>
<li>これが defaultable value type</li>
</ul>
</li>
</ul>
<p>というもの。</p>
<h3>nullable と defaultable</h3>
<p>ただ、まあ、ちょっとややこしいのが nullable と defaultable があるという点。
C# 2.0 の頃から null 許容値型があるので、
null → default → 有効な値 みたいな「2段の無効な値」ができてしまうという問題があります。</p>
<pre class="source" title="2段の無効な値">
<code><span class="reserved">using</span> System.Collections.Immutable;

<span class="comment">// null</span>
<span class="comment">// Nullable&lt;T&gt;.HasValue で null 判定。</span>
<span class="type">ImmutableArray</span>&lt;<span class="reserved">int</span>&gt;? <span class="variable">a1</span> = <span class="reserved">null</span>;
<span class="type">ImmutableArray</span>&lt;<span class="reserved">int</span>&gt;? <span class="variable">a2</span> = <span class="reserved">default</span>; <span class="comment">// これは null になる</span>

<span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="variable">a1</span>.HasValue); <span class="comment">// false</span>

<span class="comment">// default</span>
<span class="comment">// HasValue は true。</span>
<span class="comment">// ImmutableArray.IsDefault みたいな別判定が必要。</span>
<span class="type">ImmutableArray</span>&lt;<span class="reserved">int</span>&gt;? <span class="variable">a3</span> = <span class="reserved">new</span>();
<span class="type">ImmutableArray</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">a4</span> = <span class="reserved">new</span>();
<span class="type">ImmutableArray</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">a5</span> = <span class="reserved">default</span>; <span class="comment">// これは new() になる</span>

<span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="variable">a3</span>.HasValue); <span class="comment">// true</span>
<span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="variable">a4</span>.IsDefault); <span class="comment">// true</span>

<span class="comment">// 有効な値</span>
<span class="type">ImmutableArray</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">a6</span> = <span class="type">ImmutableArray</span>.<span class="method">Create</span>&lt;<span class="reserved">int</span>&gt;();

<span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="variable">a6</span>.IsDefault); <span class="comment">// false</span>
</code></pre>
<p>これがあるので、defaltable value type に対して <code>T?</code> という記法は使えません。
なので提案では<em>仮に</em> <code>T~</code> としています。
当初は <code>T??</code> みたいな案も出ていたんですが、
<a href="https://ufcpp.net/study/csharp/sp2_nullable.html#coalescing">null 合体演算の <code>??</code></a>との弁別が(構文解析が重たくなるという意味で)難しいとのこと。</p>
<p>この仮の <code>~</code> を使って話を進めると、とりあえず書きたいコードは以下のようなものになります。</p>
<pre class="source" title="defaultable value type の例 (~ 案)">
<code><span class="reserved">using</span> System.Collections.Immutable;

<span class="method">m1</span>(<span class="reserved"><span class="warning">default</span></span>); <span class="comment">// 警告</span>
<span class="method">m1</span>(<span class="type">ImmutableArray</span>.<span class="method">Create</span>&lt;<span class="reserved">int</span>&gt;()); <span class="comment">// OK</span>
m2(<span class="reserved">default</span>); <span class="comment">// OK</span>

<span class="reserved">void</span> <span class="method">m1</span>(<span class="type">ImmutableArray</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">a</span>)
{
    <span class="comment">// a に default が入ることはなく、a.Length が有効。</span>
    <span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="variable">a</span>.Length);
}

<span class="reserved">void</span> <span class="method">m2</span>(<span class="type">ImmutableArray</span>&lt;<span class="reserved">int</span>&gt;<em>~</em> a)
{
    <span class="comment">// a に default が入る可能性があり、a.Length のところに警告を出したい。</span>
    <span class="type">Console</span>.WriteLine(<span class="warning">a</span>.Length);

    <span class="comment">// 非 default を保証するような仕組みも欲しい。</span>
    <span class="control">if</span> (!a.IsDefault)
    {
        <span class="type">Console</span>.WriteLine(a.Length); <span class="comment">// これは OK にしたい。</span>
    }
}
</code></pre>
<h3>参照型フィールドで自動判定</h3>
<p>この defaultable value types の最大の目的は <code>ImmutableArray</code> みたいな、内部に参照型フィールドを持っている場合の null 解析です。</p>
<p>なので、</p>
<ul>
<li>非 null 参照型フィールドを1つでも持っていると「<code>default</code> のまま放置してはいけない型」判定になる</li>
<li>非 null 参照型フィールドをすべて非 null 初期化した時点で「<code>default</code> 状態から脱した」判定になる</li>
</ul>
<p>という判定を自動的にする予定です。</p>
<pre class="source" title="非 null 参照型フィールドで自動判定">
<code><span class="type">A</span> <span class="variable">a</span> = <span class="reserved">default</span>;

<span class="comment">// 警告: default のまま使った。</span>
<span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="variable"><span class="warning">a</span></span>.S);

<span class="comment">// OK: S が非 null になった時点で a は非 default。</span>
<span class="variable">a</span>.S = <span class="string">&quot;&quot;</span>;
<span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="variable">a</span>.S);

<span class="reserved">record</span> <span class="reserved">struct</span> <span class="type">A</span>(<span class="reserved">string</span> <span class="variable">S</span>);
</code></pre>
<h3>opt-in</h3>
<p>上記の通り、非 null 参照型フィールドを持っている値型は自動的に <code>default</code> 解析の対象になるわけですが、
それ以外の構造体でも「<code>default</code> 放置するとまずい」というものはあります。</p>
<p>例として挙がってるのは &quot;ハンドル&quot; の類ですが、
要は、ポインターに類する値を <code>int</code> とか <code>IntPtr</code> で持っているような構造体。
昔からの習慣で、null と同じく「0 なら無効なハンドル値」とすることが多いです。
こういう型は null 許容参照型とほぼ同じが扱いが必要。</p>
<p>こういう型に対して何らかの新構文を追加すべきか、
それとも属性か何かでアノテーションを付けるかはまだ検討の余地がありますが、
仮に属性を使う案でいうと以下のような感じになります。</p>
<pre class="source" title="属性を使って defaultable value type opt-in">
<code>[<span class="type">MaybeDefault</span>] <span class="comment">// 「default 放置はダメ」を表す何らかの属性</span>
<span class="reserved">public</span> <span class="reserved">struct</span> <span class="type">BlobHandle</span>
{
    <span class="reserved">private</span> <span class="reserved">readonly</span> <span class="reserved">nuint</span> _value;

    [<span class="type">AllowDefault</span>] <span class="comment">// 「このプロパティが true なら非 default」を表す何らかの属性</span>
    <span class="reserved">public</span> <span class="reserved">bool</span> IsNil =&gt; _value != 0;

    <span class="reserved">public</span> <span class="reserved">byte</span> <span class="method">Read</span>() =&gt; <span class="comment">// ...</span>
}

<span class="reserved">void</span> <span class="method">M1</span>(<span class="type">BlobHandle</span>~ handle)
{
    <span class="control">if</span> (!handle.IsNil)
    {
        handle.Read(); <span class="comment">// ok</span>
    }
}
M1(<span class="reserved">default</span>); <span class="comment">// ok</span>

<span class="reserved">void</span> <span class="method">M2</span>(<span class="type">BlobHandle</span> <span class="variable">handle</span>)
{
    <span class="variable">handle</span>.<span class="method">Read</span>();
}
<span class="method">M2</span>(<span class="reserved"><span class="warning">default</span></span>); <span class="comment">// warning</span>
</code></pre>
<p>ちなみに、属性はこれ専用のものを用意すべきか、
それとも null 許容参照型で使っている <code>MaybeNull</code> などの属性をそのまま流用すべきかみたいな点も検討途中です。</p>
<h3>default 演算子</h3>
<p>前述の <code>IsDefault</code> (<code>ImmutableArray</code> が今持ってるやつ)とか <code>IsNil</code> (前節の例に挙げた <code>BlobHandle</code> のやつ)とかじゃなくて、
<code>default</code> 判定専用の演算子定義も必要なんじゃないかという話もあります。</p>
<p>というのも、以下のようなコード(また <code>ImmutableArray</code> が起こす問題)を考えます。</p>
<pre class="source" title="ImmutableArray に対してパターン マッチングでぬるぽる">
<code><span class="reserved">using</span> System.Collections.Immutable;

<span class="reserved">void</span> <span class="method">m</span>(<span class="type">ImmutableArray</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">a</span>)
{
    <span class="comment">// ImmutableArray に対してリスト パターンを使う。</span>
    <span class="comment">// パターンマッチングは暗黙的に非 null 判定を含んでいて、たいていの型に対してはぬるぽを起こさない。</span>
    <span class="comment">// ところが…</span>
    <span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="variable">a</span> <span class="reserved">is</span> [1, ..]);
}

<span class="comment">// こういうのは大丈夫。</span>
<span class="method">m</span>(<span class="type">ImmutableArray</span>.<span class="method">Create</span>(1)); <span class="comment">// true</span>
<span class="method">m</span>(<span class="type">ImmutableArray</span>.<span class="method">Create</span>(2)); <span class="comment">// false</span>

<span class="comment">// これが例外を起こす。</span>
<span class="comment">// null チェックに代わる「default チェック」が必要…</span>
<span class="method">m</span>(<span class="reserved">default</span>);
</code></pre>
<p>こんな感じで「<code>default</code> を放置しちゃダメ」な型に対するパターン マッチングをするにあたって、「null チェック代わりに何か <code>default</code> チェックを挟みたい」という要件があります。</p>
<p>で、「何か特定のプロパティを呼ぶ」とかよりは、以下のように、<code>operator default</code> みたいなものを書けるようにした方がいいのではないかという案も出ています。</p>
<pre class="source" title="operator default">
<code><span class="reserved">public</span> <span class="reserved">struct</span> <span class="type">ImmutableArray</span>&lt;<span class="type">T</span>&gt;
{
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">bool</span> <span class="reserved">operator</span> <span class="reserved">default</span>(<span class="type">ImmutableArray</span>&lt;<span class="type">T</span>&gt; <span class="variable">arr</span>) =&gt; <span class="variable">arr</span>._array <span class="reserved">is</span> <span class="reserved">null</span>;
}
</code></pre>
<h2>課題</h2>
<p>NRT で問題を起こしている以上、defaultable value type みたいなフロー解析が必要なこと自体はもう分かっているわけですが。
話が進まないのはまだ悩ましい点が残っているから。</p>
<p>特に悩ましいとされるのが2点あって、以下のようなものです。</p>
<ul>
<li>プロパティはどうするか</li>
<li>NRT 並みに「既存コードの移行作業」に手間が掛かる</li>
</ul>
<h3>プロパティ</h3>
<p><a href="https://ufcpp.net/study/csharp/cheatsheet/ap_ver10/#record-struct"><code>record struct</code></a>では、メンバーは(フィールドではなく)プロパティで作られます。
例えば、<code>record struct A(string S);</code> と書くと、<code>S</code> はプロパティです。</p>
<p>この場合、「すべての非 null 参照型フィールドを初期化していれば非 <code>default</code>」の判定をどうするかという問題があります。
プロパティ <code>S</code> 越しにそのバッキングフィールドを初期化することになるわけですが、プロパティとフィールドの紐づけができないとフロー解析できません。</p>
<h3>既存コードの移行</h3>
<p>null 許容参照型を導入するときもかなり苦労しました。
.NET の標準ライブラリに null アノテーションを付けて回る作業には2年くらい掛かっています。</p>
<p>しかも、既存コードを壊さないように、「null 解析をするかどうか」は <a href="https://ufcpp.net/study/csharp/resource/nullablereferencetype/#opt-in">opt-in</a> (明示的にオプション指定しない限り有効化されない)になっていて、「オプションの有無で2種類の C# がある」といってもいいような状況になっています。
(C# チームもこれを好ましいとは思っていないので、
null 許容参照型はそれだけ「無理してでも必要」とされる唯一の機能です。)</p>
<p>defaultable value type ではこの「アノテーション追加」と「opt-in」をもう1度やる必要があります。</p>
 ]]></description>
				<pubDate>Fri, 07 Jan 2022 21:48:20 +0900</pubDate>
			</item>
			<item>
				<title>【C# 11 で再検討】Countable</title>
				<link>http://ufcpp.net/blog/2022/1/countable/</link>
				<description><![CDATA[ <p><a href="https://ufcpp.net/blog/2021/12/list-pattern/">リスト パターン</a>の実装で、「Count もしくは Length を持った型なら何にでも使える」と説明しました。
C# ではこれを「Countable」と呼んでいます。</p>
<p>この Countable というコンセプト、最初に出て来たのは C# 8.0 の <a href="https://ufcpp.net/study/csharp/data/dataranges/"><code>Index</code></a> のときです。
で、リスト パターンや<a href="https://ufcpp.net/blog/2021/12/collection-literal/">コレクション リテラル</a>でも Countable が出て来たところで、
<code>Index</code> に対する Countable の扱いも拡張しよう見たいな話がちょこっと出ています。</p>
<p>ちょっと課題もあるので C# 11 時点はおろか、その先でもどうなるかわからないですがとりあえず提案が出ました。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/5596">[Proposal]: Adding Index support to existing library types (redux) #5596</a></li>
</ul>
<h2>Countable</h2>
<p><code>Index</code> 構文では、<code>^i</code> みたいな書き方で「末尾要素から i 個前」みたいなインデックスを表します
(一方、「先頭から」の方は普通に <code>int</code> を使います)。
「末尾から」を取るためにはコレクションの要素数を必要としますが、
これは<a href="https://ufcpp.net/study/csharp/misc/miscpatternbased/">パターン ベースな構文</a>になっていて、以下の条件を満たす型なら何でも使えます。</p>
<ul>
<li><code>Index</code> 型を受け取るインデクサーがある場合は <code>x[^i]</code> の <code>^i</code> は <code>Index.FromEnd(i)</code> として解釈される</li>
<li>
<code>int</code> 型を受け取るインデクサーがあって、
<ul>
<li><code>int</code> 型の <code>Length</code> プロパティを持っている場合、<code>x[^i]</code> を <code>x[x.Length - i]</code> に展開する</li>
<li>それ以外で、<code>int</code> 型の <code>Count</code> プロパティを持っている場合、<code>x[^i]</code> を <code>x[x.Count - i]</code> に展開する</li>
</ul>
</li>
</ul>
<p>この条件を満たす型を Countable と言います。
リスト パターンも Countable な型に対して使えます。</p>
<h2>Index サポートの拡張</h2>
<p>C# 8.0 時点ではインデクサーだけに対応しました。
前述の通り「<code>x[^i]</code> を <code>x[x.Length - i]</code> に展開する」みたいな処理が掛かります。</p>
<p>一方、<code>RemoveAt</code> メソッドとかでも同様に <code>RemoveAt(^i)</code> を使いたいという話があります。
C# の文法的に対応しなくても、ライブラリ側で <code>RemoveAt(Index)</code> なオーバーロードを足せば今でも <code>RemoveAt(^i)</code> と書けます。
ただ、全てのコレクション型に対してオーバーロードを足して回るというのも大変なので、改めて「Countable のサポート範囲の拡張」の話が出てきました。</p>
<h3>問題1: Add(int) が誤判定しそう</h3>
<p>パターン ベースな構文は無節操にやると結構「意図せずパターンを満たしてしまった」と言うことが起こります。
今回の場合も、以下のような書き方ができてしまうという懸念あり。</p>
<pre class="source" title="Add(int)">
<code><span class="type">List</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">list</span> = <span class="reserved">new</span>();
<span class="variable">list</span>.Add(^1);
</code></pre>
<p>これが <code>list.Add(list.Count - 1)</code> と解釈されかねないわけで、それが望まれる挙動にはならないでしょう。</p>
<p>一応、この問題は「<code>Add</code> などの引数で、引数名が <code>index</code> の時にだけこの構文を使える」みたいな制限を掛けることである程度の対処はできそうです。</p>
<h3>問題2: Range にも似た処理が欲しい？</h3>
<p><code>Index</code> の <code>^i</code> のサポート範囲を拡張するんなら、
<code>Range</code> の <code>i..j</code> も拡張したいという話も自然と出てきます。
<code>list.RemoveRange(1..^1)</code> みたいなので一定範囲の要素をまとめて削除みたいな感じで。</p>
<p>とはいえ、こちらは今現在デファクトになっているパターンがないですし、
どうせオーバーロードを今から足すのであれば <code>RemoveRange(Range)</code> なオーバーロードを足せば、C# の文法の拡張なしでライブラリだけで対応できます。</p>
<p>また、<code>RemoveRange(1..^1)</code> の部分を <code>RemoveRange(1, list.Count - 2)</code> みたいな感じで、引数の数が増えるような展開が必要になるのでちょっと分かりにくい仕様になります。</p>
<h2>問題3: オーバーロード解決</h2>
<p>新機能を足すたびに問題になるオーバーロード解決なんですが…</p>
<p><code>RemoveAt(^i)</code> みたいなやつでも、下手な実装をすると破壊的変更になりかねません。
例えば今現在、インスタンス メソッドとして <code>RemoveAt(int)</code> があって、拡張メソッドとして <code>RemoveAt(Index)</code> があったとして、
新構文で <code>RemoveAt(^i)</code> を <code>RemoveAt(Count - i)</code> に展開するようになると、<code>RemoveAt(int)</code> と <code>RemoveAt(Index)</code> のどちらを呼ぶかが変わってしまうことがあります。</p>
<h2>今でも起こりうるパターン ベース問題</h2>
<p><code>Vector&lt;T&gt;</code> 型(<code>System.Numerics</code> 名前空間)はインデクサーを持っているわけですが、以下のような<a href="https://ufcpp.net/blog/2021/12/list-pattern/">リスト パターン</a>を書きたいかどうかという話もあります。</p>
<pre class="source" title="Vector に対するリスト パターン">
<code><span class="reserved">using</span> System.Numerics;

<span class="type">Vector</span>&lt;<span class="reserved">byte</span>&gt; <span class="variable">v</span> = <span class="reserved">new</span>();

<span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="variable">v</span> <span class="reserved">is</span> [ 0, .., 0 ]);
</code></pre>
<p>これを書けるようにするには <code>Vector&lt;T&gt;</code> を Countable にすればいいんですが…
<code>Vector&lt;T&gt;</code> の文脈的に「<code>Length</code> と言われても要素数には見えない」という別問題が発生します。
「ベクトルの Length」というと多くの場合はユークリッド距離を指していて、要素数ではありません。</p>
<p>ということで、なんらかの opt-out 手段、すなわち、「Countable になりそうだけど Countable 扱いしてほしくない」というのを表明する手段も必要になるんじゃない？という提案も出ていたりします。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/discussions/5278">Provide a way to opt-out of structural typing. #5278</a></li>
</ul>
<p>こないだ <a href="https://ufcpp.net/blog/2021/12/immutable-array-init/"><code>ImmutableArray</code> の話</a>で書いたみたいに、
望まれない形でたまたまパターンを満たしてしまった場合、
結構悲惨なことになりますんで…</p>
 ]]></description>
				<pubDate>Tue, 04 Jan 2022 20:33:50 +0900</pubDate>
			</item>
			<item>
				<title>【C# 11 候補】コレクション リテラル</title>
				<link>http://ufcpp.net/blog/2021/12/collection-literal/</link>
				<description><![CDATA[ <p>今日は<a href="https://ufcpp.net/blog/2021/12/list-pattern/#collection-literal">リスト パターンの回でちょこっと出て来た <code>[]</code> リテラルの話</a>。</p>
<p>逆に、リスト パターン側でも <code>{}</code> ではなく <code>[]</code> を使う決断に至った理由でもあります。</p>
<p>もう実装があるリスト パターンと違って、こちらはまだ案が出たてで、
もしかしたら C# 11 よりもさらに後になるかもしれないです。</p>
<h2><a id="collection-literal">[] リテラルの導入</a></h2>
<p>元々、C# よりも後に世に出たり、大幅改修したことがあるプログラミング言語には結構「コレクション リテラル」系の文法があります。
で、多くの場合、<code>[ 1, 2, 3 ]</code> みたいに角括弧を利用。</p>
<p>そして現在の C# には <code>new[] { 1, 2, 3 }</code> みたいな書き方はあるにはあるものの、いろんなコレクション型があって、それぞれ書き方に統一感がない状態。</p>
<pre class="source" title="C# のコレクションあれこれ">
<code><span class="comment">// 型を明示、かつ、配列の時に限り {} だけで OK。</span>
<span class="reserved">int</span>[] <span class="variable">array1</span> = { 1, 2, 3 };

<span class="comment">// 型推論を使いたければ new[] {}。</span>
<span class="reserved">var</span> <span class="variable">array2</span> = <span class="reserved">new</span>[] { 1, 2, 3 };

<span class="comment">// Target-typed new + コレクション初期化子。 () は省略不可。</span>
<span class="type">List</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">list1</span> = <span class="reserved">new</span>() { 1, 2, 3 };

<span class="comment">// 通常の new + コレクション初期化子。こっちの場合は () 省略 OK。</span>
<span class="reserved">var</span> <span class="variable">list2</span> = <span class="reserved">new</span> <span class="type">List</span>&lt;<span class="reserved">int</span>&gt; { 1, 2, 3 };

<span class="comment">// Span にはまあ、new で配列を割り当ててもいいものの、</span>
<span class="comment">// パフォーマンス的には stackalloc を使った方が大体の場合有利。</span>
<span class="type">Span</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">span</span> = <span class="reserved">stackalloc</span> <span class="reserved">int</span>[] { 1, 2 };

<span class="comment">// ReadOnlySpan も同様。</span>
<span class="comment">// あと、stackalloc の後ろは型推論で省略可能。</span>
<span class="type">ReadOnlySpan</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">ros</span> = <span class="reserved">stackalloc</span>[] { 1, 2, 3 };

<span class="comment">// new() もコレクション初期化子も使えないかわいそうな型あり。</span>
<span class="reserved">var</span> <span class="variable">immutable</span> = System.Collections.Immutable.<span class="type">ImmutableArray</span>.<span class="method">Create</span>(1, 2, 3);
</code></pre>
<p>C# でももう少し統一感あるコレクション リテラルがあった方がいいし、
だったら他の言語に倣って <code>[]</code> を使った新文法を導入でいいのではないかという話になります。</p>
<pre class="source" title="[] をもっていろんなコレクションを初期化したい">
<code><span class="comment">// ぜんぶ [] にしたい。</span>
<span class="reserved">int</span>[] <span class="variable">array1</span> = [ 1, 2, 3 ];
<span class="type">List</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">list1</span> = [ 1, 2, 3 ];
<span class="type">Span</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">span</span> = [ 1, 2, 3 ];
<span class="type">ReadOnlySpan</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">ros</span> = [ 1, 2 ];
System.Collections.Immutable.<span class="type">ImmutableArray</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">immutable</span> = [ 1, 2, 3 ];
</code></pre>
<p>そしてこっち(リテラル側)でも <code>[]</code> を使うのであれば、
<a href="https://ufcpp.net/blog/2021/12/list-pattern/">パターンの方</a>で <code>{}</code> (プロパティ パターンと区別が付かない)とか <code>[]{}</code> (<code>new[]{}</code> との対称性はいいかもしれないもののキモい)とか考えず、そっちも素直に <code>[]</code> を使えばいいということに。</p>
<h2><a id="spread">[] リテラル中の .. (spread 演算)</a></h2>
<p><a href="https://ufcpp.net/blog/2021/12/list-pattern/">パターンの方</a>で「<code>[1, ..[2, 3, 4], 5]</code> と <code>[1, 2, 3, 4, 5]</code> が同じ意味になる」と書きましたが、コレクション リテラル中でも同じく「入れ子のコレクションを展開」みたいな仕様があります。</p>
<pre class="source" title=".. で入れ子のコレクションを展開">
<code><span class="reserved">int</span>[] <span class="variable">array</span> = [ 1, 2, 3 ];
<span class="type">List</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">list</span> = [ 0, ..<span class="variable">array</span>, 4 ]; <span class="comment">// 0, 1, 2, 3, 4</span>
</code></pre>
<p>他の言語で unpacking とか splat (* 記号が一部の人にそう呼ばれていて、この機能に * を使ってる言語ではこう呼ぶ)とか spread (拡散)演算子とか呼ばれているやつです。</p>
<p>C# ではまあ、LINQ の <code>Concat</code>, <code>Append</code>, <code>Prepend</code> とかを使って同様のものは書けていましたが、煩雑、かつ、パフォーマンスはいまいちでした。</p>
<pre class="source" title="Concat, Append, Prepend">
<code><span class="reserved">int</span>[] <span class="variable">array1</span> = { 1, 2, 3 };
<span class="reserved">int</span>[] <span class="variable">array2</span> = { 4, 5, 6 };

<span class="comment">// enumerator のインスタンスが余計に new されたりで遅い。</span>
<span class="reserved">var</span> <span class="variable">linq</span> = <span class="variable">array1</span>.<span class="method">Concat</span>(<span class="variable">array2</span>).<span class="method">Prepend</span>(0).<span class="method">Append</span>(7);

<span class="comment">// 列挙も結構遅い。</span>
<span class="control">foreach</span> (<span class="reserved">var</span> <span class="variable">x</span> <span class="control">in</span> <span class="variable">linq</span>)
{
    <span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="variable">x</span>);
}

<span class="comment">// LINQ のよりも速い実装になる予定(後述)。</span>
<span class="comment">// かつ、Preapend よりはだいぶわかりやすい。</span>
<span class="reserved">var</span> <span class="variable">spread</span> = [ 0, .. <span class="variable">array1</span>, .. <span class="variable">array2</span>, 7 ];
</code></pre>
<h2><a id="brace">おまけ: {} 案</a></h2>
<p>一時期はパターンの方も <code>is {}</code> にしたいみたいな話もあったんですが。
元々配列初期化子が <code>{}</code> ですし、コレクション初期化子も <code>{}</code> になる案もなくはなかったです。</p>
<p>ただ、<code>{}</code> の用途としては他に <a href="https://github.com/dotnet/csharplang/issues/3086">Expression blocks</a> という提案も出ていて、それとの弁別が無理そうということで没。</p>
<h2><a id="lowering">展開結果</a></h2>
<p>展開結果、基本的には「前から順に詰める」です。
配列の場合だと割かしシンプルで、例えば以下のような感じ。</p>
<pre class="source" title="配列に対するコレクション リテラルの展開結果">
<code><span class="reserved">int</span>[] <span class="variable">array1</span> = { 1, 2, 3 };
<span class="reserved">int</span>[] <span class="variable">array2</span> = { 4, 5, 6 };

<span class="comment">// var spread = [ 0, .. array1, .. array2, 7 ];</span>

<span class="reserved">var</span> <span class="variable">len</span> = 1 + <span class="variable">array1</span>.Length + <span class="variable">array2</span>.Length + 1;
<span class="reserved">var</span> <span class="variable">spread</span> = <span class="reserved">new</span> <span class="reserved">int</span>[<span class="variable">len</span>];

<span class="reserved">var</span> <span class="variable">i</span> = 0;
<span class="variable">spread</span>[<span class="variable">i</span>++] = 0;
<span class="control">for</span> (<span class="reserved">int</span> <span class="variable">j</span> = 0; <span class="variable">j</span> &lt; <span class="variable">array1</span>.Length; <span class="variable">j</span>++, <span class="variable">i</span>++) <span class="variable">spread</span>[<span class="variable">i</span>] = <span class="variable">array1</span>[<span class="variable">j</span>];
<span class="control">for</span> (<span class="reserved">int</span> <span class="variable">j</span> = 0; <span class="variable">j</span> &lt; <span class="variable">array2</span>.Length; <span class="variable">j</span>++, <span class="variable">i</span>++) <span class="variable">spread</span>[<span class="variable">i</span>] = <span class="variable">array2</span>[<span class="variable">j</span>];
<span class="variable">spread</span>[<span class="variable">i</span>] = 7;
</code></pre>
<p><code>Span&lt;T&gt;</code> の場合には <code>new T[]</code> のところを <code>stackalloc T[]</code> に変更。
<code>ReadOnlySpan&lt;T&gt;</code> の場合はいったん <code>Span&lt;T&gt;</code> と同じ処理でデータを書き込んでから、最後に <code>ReadOnlySpan&lt;T&gt;</code> に変換。</p>
<p>それ以外の型については「所定のパターンを満たすコンストラクターと <code>Init</code> メソッドを呼ぶ」と言うことになっています。</p>
<ul>
<li><code>capacity</code> という名前の引数があるコンストラクターがある場合はそれを、なければ引数なしコンストラクターを呼ぶ</li>
<li><code>void Init(T1)</code> があって、<code>T1</code> が <code>T[]</code> なら <code>new[]</code> で、<code>T1</code> が <code>Span&lt;T&gt;</code>, <code>ReadOnlySpan&lt;T&gt;</code> なら <code>stackalloc[]</code> で一時バッファーを作ってから <code>Init</code> メソッドに渡す</li>
</ul>
<p>例えば <code>Init(int[])</code> だけ持っている型だと以下のような感じ。</p>
<pre class="source" title="一時 new int[] が作られるパターン">
<code><span class="comment">// A a = [ 1, 2, 3 ];</span>
<span class="reserved">int</span>[] <span class="variable">tempA</span> = { 1, 2, 3 };
<span class="type">A</span> <span class="variable">a</span> = <span class="reserved">new</span>();
<span class="variable">a</span>.<span class="method">Init</span>(<span class="variable">tempA</span>);

<span class="reserved">class</span> <span class="type">A</span>
{
    <span class="reserved">public</span> <span class="reserved">void</span> <span class="method">Init</span>(<span class="reserved">int</span>[] <span class="variable">items</span>) { }
}
</code></pre>
<p><code>capacity</code> コンストラクターと <code>Init(ReadOnlySpan&lt;int&gt;)</code> を持つ型だと以下のような感じ。</p>
<pre class="source" title="一時 stackalloc int[] が作られるパターン">
<code><span class="comment">// A a = [ 1, 2, 3 ];</span>
<span class="type">ReadOnlySpan</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">tempA</span> = <span class="reserved">stackalloc</span>[] { 1, 2, 3 };
<span class="type">A</span> <span class="variable">a</span> = <span class="reserved">new</span>(3);
<span class="variable">a</span>.<span class="method">Init</span>(<span class="variable">tempA</span>);

<span class="reserved">class</span> <span class="type">A</span>
{
    <span class="reserved">public</span> <span class="type">A</span>(<span class="reserved">int</span> <span class="variable">capacity</span>) { }
    <span class="reserved">public</span> <span class="reserved">void</span> <span class="method">Init</span>(<span class="type">ReadOnlySpan</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">items</span>) { }
}
</code></pre>
<h2>immutable コレクション初期化</h2>
<p>ちょっと別の機能追加も必要なのでさらに不透明なんですが、
この <code>[]</code> リテラルは前に話した <a href="immutable-array-init"><code>ImmutableArray</code> の初期化問題</a>の解決策としても期待されています。</p>
<p>とりあえず、<code>ImmutableArray</code> についても前節と同じルールで初期化を掛けることを考えます。</p>
<pre class="source" title="ImmutableArray.Init">
<code><span class="reserved">using</span> System.Collections.Immutable;

<span class="comment">// ImmutableArray&lt;int&gt; a = [ 1, 2, 3 ];</span>
<span class="type">ReadOnlySpan</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">tempA</span> = <span class="reserved">stackalloc</span>[] { 1, 2, 3 };
<span class="type">ImmutableArray</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">a</span> = <span class="reserved">new</span>();
<span class="variable">a</span>.Init(<span class="variable">tempA</span>); <span class="comment">// こういうメソッドを足したいという話。今はない。</span>
</code></pre>
<p>こういう <code>Init</code> メソッドを足せればいいわけですが、
immutable を名乗る以上、<code>new()</code> とは別に呼ばれるとまずいという話になります。</p>
<p>で、そこは<a href="https://ufcpp.net/study/csharp/oo_property.html#init-only-internal">init-only プロパティ</a>と同じ方式で乗り切りたいとのこと。</p>
<p>任意のメソッドに対して、<code>new()</code> 中、もしくは、直後にしか呼ばない・呼ばれない保証をコンパイラーがするような仕様(メソッドに対する <code>init</code> 修飾)があればいいわけで、そういう仕様も模索中とのこと。</p>
<pre class="source" title="init 修飾子">
<code><span class="reserved">struct</span> <span class="type">ImmutableArray</span>&lt;<span class="type">T</span>&gt;
{
    <span class="reserved">readonly</span> <span class="type">T</span>[] _items;

    <span class="comment">// init 修飾を付けたメソッドは new() 内、もしくは、直後でしか呼べないように、</span>
    <span class="comment">// コンパイラーが呼び出し箇所をチェックする。</span>
    <span class="reserved">public</span> <span class="reserved">init</span> <span class="reserved">void</span> <span class="method">Init</span>(<span class="type">ReadOnlySpan</span>&lt;<span class="type">T</span>&gt; <span class="variable">items</span>)
    {
        <span class="comment">// 本来、コンストラクター内でしか書き換えてはいけないはずのフィールドを、</span>
        <span class="comment">// init 修飾子が付いたメソッド内に限り書き換え可能にする。</span>
        _items = <span class="variable">items</span>.<span class="method">ToArray</span>();
    }
}
</code></pre> ]]></description>
				<pubDate>Fri, 31 Dec 2021 19:42:44 +0900</pubDate>
			</item>
			<item>
				<title>ImmutableArray に対してコレクション初期化子</title>
				<link>http://ufcpp.net/blog/2021/12/immutable-array-init/</link>
				<description><![CDATA[ <p>Immutable コレクションは現状いろんな使いにくさがあって悪名高いわけですが。
今日は「<a href="https://ufcpp.net/blog/2021/12/list-pattern/#collection-literal">リスト パターンの回に出した <code>[]</code> リテラルの話</a>」と絡むので、特に <code>ImmutableArray</code> とかに対して<a href="https://ufcpp.net/blog/2016/12/tipscollectioninitializer/">コレクション初期化子</a>が使えないという話をします。</p>
<h2>クイズ</h2>
<p>以下のようなコード。</p>
<pre class="source" title="ImmutableArray にコレクション初期化子">
<code><span class="reserved">using</span> System.Collections.Immutable;

<span class="type">ImmutableArray</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">a</span> = <span class="reserved">new</span>() { 1, 2 };

<span class="control">foreach</span> (<span class="reserved">var</span> <span class="variable">x</span> <span class="control">in</span> <span class="variable">a</span>)
{
    <span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="variable">x</span>);
}
</code></pre>
<p>どういう結果になるでしょう？</p>
<ul>
<li>1, 2, 3 が表示される</li>
<li>何も表示されない</li>
<li><code>foreach</code> のところで例外が出る</li>
<li><code>new</code> のところで例外が出る</li>
<li>コンパイルできない</li>
</ul>
<p>ちなみに、<a href="https://youtu.be/AzJd1tAZdfo?t=2466">C# ライブ配信中に参加者みんな間違えてました</a>。</p>
<h2>答え</h2>
<p><code>new</code> のところで例外です。
しかもぬるぽ。</p>
<pre>
Unhandled exception. System.NullReferenceException: Object reference not set to an instance of an object.
   at System.Collections.Immutable.ImmutableArray`1.get_Length()
   at System.Collections.Immutable.ImmutableArray`1.Add(T item)
   at Program.<Main>$(String[] args) in C:\source\repos\ConsoleApp1\ConsoleApp1\Program.cs:line 4
</pre>
<p>そして、どうしてこうなるかの説明にも何段階かの変形が必要という…</p>
<p>とりあえず、<code>foreach</code> のところは無罪というか、その行までたどり着かないのでいったん削除。
(ちなみに、もしたどり着けた場合、<code>foreach</code> でも例外が出ます。)</p>
<pre class="source" title="問題のコード">
<code><span class="reserved">using</span> System.Collections.Immutable;

<span class="type">ImmutableArray</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">a</span> = <span class="reserved">new</span>() { 1, 2 };
</code></pre>
<p>コレクション初期化子は、以下のように、<code>new()</code> の後に <code>Add</code> メソッドを呼ぶという展開のされ方になります。</p>
<pre class="source" title="コレクション初期化子を展開">
<code><span class="reserved">using</span> System.Collections.Immutable;

<span class="type">ImmutableArray</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">a</span> = <span class="reserved">new</span>();
<span class="variable">a</span>.<span class="method">Add</span>(1); <span class="comment">// ぬるぽるのはこの行になる。</span>
<span class="variable">a</span>.<span class="method">Add</span>(2);
</code></pre>
<p>まあ、この時点ですでに問題の原因が分かってくる頃かと思いますが、一応もう1段。
<code>ImmutableArray</code> は構造体で、C# 10.0 より前には構造体に引数なしコンストラクターがなかったので、これは以下のコードと同じ意味になります。</p>
<pre class="source" title="new() の顛末">
<code><span class="reserved">using</span> System.Collections.Immutable;

<span class="type">ImmutableArray</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">a</span> = <span class="reserved"><em>default</em></span>;
<span class="variable">a</span>.<span class="method">Add</span>(1); <span class="comment">// ぬるぽるのはこの行。</span>
<span class="variable">a</span>.<span class="method">Add</span>(2);
</code></pre>
<p><a href="https://ufcpp.net/study/csharp/rm_default.html#sec-default-value">構造体の <code>default</code></a> は「全ビットを0にする」みたいな扱いで、
参照型の場合には <code>null</code> が入ります。</p>
<p>要するに、実質以下のコードと同じような挙動になります。</p>
<pre class="source" title="説明用: 実質同じ挙動のコード">
<code><span class="comment">// 実質これと同じ結果</span>
<span class="reserved">using</span> System.Collections.Immutable;

<span class="type">ImmutableArray</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">a</span> = <span class="type">ImmutableArray</span>.<span class="method">Create</span>&lt;<span class="reserved">int</span>&gt;(<span class="variable">items</span>: <span class="reserved">null</span>);
<span class="variable">a</span>.<span class="method">Add</span>(1); <span class="comment">// ぬるぽる原因は items: null なせい。</span>
<span class="variable">a</span>.<span class="method">Add</span>(2);
</code></pre>
<p>ちなみに、「既存の構造体に引数なしコンストラクターを足すのは破壊的変更」なので、破壊的変更を極力割けて通っている .NET 的に、追加されることはないと思います。なのでたぶん、<code>ImmutableArray&lt;T&gt;</code> がこんな変な挙動から解放される未来もないと思われます。</p>
<p>また、以下のようにぬるぽ回避コードを入れても、おそらくほとんどの人にとって所望の結果にはならないと思います。</p>
<pre class="source" title="ぬるぽ回避">
<code><span class="reserved">using</span> System.Collections.Immutable;

<span class="comment">// ぬるぽ回避</span>
<span class="type">ImmutableArray</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">a</span> = <span class="type">ImmutableArray</span>.<span class="method">Create</span>(<span class="type">Array</span>.<span class="method">Empty</span>&lt;<span class="reserved">int</span>&gt;());
<span class="variable">a</span>.<span class="method">Add</span>(1); <span class="comment">// 無事通過。</span>
<span class="variable">a</span>.<span class="method">Add</span>(2);

<span class="comment">// ただし、a の中身は Empty のまま。</span>
<span class="comment">// まあ、immutable ですからね。初期状態から変わるはずないですよね。</span>
<span class="control">foreach</span> (<span class="reserved">var</span> <span class="variable">x</span> <span class="control">in</span> <span class="variable">a</span>)
{
    <span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="variable">x</span>);
}
</code></pre>
<p>ええ、immutable ですから。
<code>Add</code> は「元の配列に1要素 append した新しい配列を作って返す」という仕様。
自身の書き換えはしません。</p>
<h2>課題</h2>
<p>2つの問題が重なってこんなことになっています。</p>
<ul>
<li>コレクション初期化子に適さないのに、C# の構文上はコレクション初期化子が使える条件を満たしてしまっている</li>
<li><code>default</code> が不正な状態になる構造体を作ってしまっている</li>
</ul>
<p>と言うことで、また日を改めて書くと思うんですが、それぞれ以下のような解決策が考えられています。</p>
<ul>
<li>今後追加予定の新構文の <code>[]</code> リテラルでは、<code>ImmutableArray</code> でも使えるような展開の仕方をする</li>
<li>基本的に <code>default</code> 禁止なアノテーション(<a href="https://ufcpp.net/study/csharp/resource/nullablereferencetype/">null 許容参照型</a>の構造体版)を作る</li>
</ul>
 ]]></description>
				<pubDate>Thu, 30 Dec 2021 18:31:17 +0900</pubDate>
			</item>
			<item>
				<title>【C# 11 候補】リスト パターン【VS 17.1 p2 で追加予定】</title>
				<link>http://ufcpp.net/blog/2021/12/list-pattern/</link>
				<description><![CDATA[ <p>C# に<a href="https://ufcpp.net/study/csharp/datatype/patterns/">パターン</a>がまた1個増えます。
今回はリスト。<code>is [..]</code> とかで配列や <code>List&lt;T&gt;</code> にマッチ。
これをリスト パターンと言います。</p>
<p>Roslyn 化(C# コンパイラーを C# で書き直し)した初期の頃から、C# の進化の長期テーマになってる <a href="https://github.com/dotnet/csharplang/discussions/3107">&quot;Programming With Data&quot;</a> の続きです。
以下の表の赤丸を付けたところ。</p>
<p><img src="/media/1205/listpattern.png" alt="リスト パターンの立ち位置" /></p>
<p>ちなみにこのリスト パターンは Visual Studio 17.1 Preview 2 向けですでに merge 済み。近々動くコンパイラーを実際に触れるはずです。</p>
<h2><a id="square-bracket">角括弧</a></h2>
<p>リスト パターンには <code>[]</code> を使うことになりました。</p>
<p>当初予定は <code>{}</code> (プロパティ パターンと被る)とか <code>[]{}</code> (これはこれでキモイ)とかも検討されていたんですが。
配列初期化子とかコレクション初期化子との対称性のためでしたが、
構文解析的にきつくて断念。</p>
<pre class="source" title="当初案(没)">
<code><span class="reserved">var</span> <span class="variable">array</span> = <span class="reserved">new</span>[] { 1, 2 };

<span class="comment">// 当初案1:</span>
<span class="comment">// int[] array = { 1, 2 }; との対比。</span>
<span class="comment">// { Length: &gt; 0 } とかとの区別が付かなくて断念。</span>
<span class="control">if</span> (<span class="variable">array</span> <span class="reserved">is</span> { })
{
}

<span class="comment">// 当初案2:</span>
<span class="comment">// var array = new[] { 1, 2 }; との対比。</span>
<span class="comment">// まだ {} の部分がきついのと、length を必要としないときに [] を付けるのがだいぶつらい。</span>
<span class="reserved">const</span> <span class="reserved">int</span> length = 2;
<span class="control">if</span> (<span class="variable">array</span> <span class="reserved">is</span> [length] { 1, _ })
{
}
</code></pre>
<p>結果的に、<code>[]</code> だけにすることに。</p>
<pre class="source" title="[] でリスト パターンを表現">
<code><span class="reserved">var</span> <span class="variable">array</span> = <span class="reserved">new</span>[] { 1, 2 };

<span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="variable">array</span> <span class="reserved">is</span> []); <span class="comment">// 長さ0マッチ。false。</span>
<span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="variable">array</span> <span class="reserved">is</span> [_, _]); <span class="comment">// 長さ2マッチ。true。</span>
<span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="variable">array</span> <span class="reserved">is</span> [ .. ]); <span class="comment">// 任意長さマッチ。true。</span>

<span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="variable">array</span> <span class="reserved">is</span> [ 1 ]); <span class="comment">// 長さ1マッチ。false。</span>
<span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="variable">array</span> <span class="reserved">is</span> [ 1, .. ]); <span class="comment">// 1で開始、任意長さ。true。</span>
<span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="variable">array</span> <span class="reserved">is</span> [ .., 2 ]); <span class="comment">// 2で終了、任意長さ。true。</span>
<span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="variable">array</span> <span class="reserved">is</span> [ 1, .., 2 ]); <span class="comment">// 1で開始、2で終了、任意長さ。true。</span>
</code></pre>
<p>基本的には「長さピッタリ」にだけマッチします。
任意長さとマッチさせたい場合は <code>..</code> を挟むという仕様です。</p>
<h2><a id="slice-pattern">..パターン</a></h2>
<p>ちなみに、 <code>..</code> の後ろには入れ子でパターンを書けます。
主に <a href="https://ufcpp.net/study/csharp/datatype/patterns/#var">var パターン</a>で「マッチ結果の一部分」を抜き出すのに使います。</p>
<pre class="source" title="..var">
<code><span class="type">ReadOnlySpan</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">a</span> = <span class="reserved">new</span>[] { 1, 2, 3, 4, 5 };

<span class="control">if</span> (<span class="variable">a</span> <span class="reserved">is</span> [1, ..<span class="reserved">var</span> <span class="variable">middle</span>, 5])
{
    <span class="type">Console</span>.WriteLine(<span class="variable">middle</span>.Length); <span class="comment">// 2, 3, 4 で長さ3</span>
}
</code></pre>
<p>あんまり意味はないですが、<code>[..[]]</code> とかも書けます。</p>
<pre class="source" title=".. の後ろに再度 []">
<code><span class="type">ReadOnlySpan</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">a</span> = <span class="reserved">new</span>[] { 1, 2, 3, 4, 5 };
<span class="type">Console</span>.WriteLine(<span class="variable">a</span> <span class="reserved">is</span> [1, ..[2, 3, 4], 5]); <span class="comment">// true</span>
</code></pre>
<p><code>[1, ..[2, 3, 4], 5]</code> と <code>[1, 2, 3, 4, 5]</code> が同じ意味になるので、
ある意味スプレッド演算(<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax">JavaScript とかにある配列を展開するやつ</a>)です。</p>
<h2><a id="lowering">展開結果</a></h2>
<p>リスト パターンは、<code>Length</code> チェックと<a href="https://ufcpp.net/study/csharp/data/dataranges/">インデックス・範囲処理</a>を使ったようなコードに展開されます。</p>
<p>例えば先ほどの <code>a is [1, ..var middle, 5]</code> であれば、以下のようなコードと同じ結果になります。</p>
<pre class="source" title="[1, ..var middle, 5] を展開">
<code><span class="type">ReadOnlySpan</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">a</span> = <span class="reserved">new</span>[] { 1, 2, 3, 4, 5 };

<span class="control">if</span> (<span class="variable">a</span>.Length &gt;= 2 &amp;&amp; <span class="variable">a</span>[0] == 1)
{
    <span class="reserved">var</span> <span class="variable">middle</span> = <span class="variable">a</span>[1..^1];
    <span class="control">if</span> (<span class="variable">a</span>[^1] == 5)
    {
        <span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="variable">middle</span>.Length);
    }
}
</code></pre>
<p><code>^</code> と <code>..</code> もさらに展開すると以下のコードと同じ意味。</p>
<pre class="source" title="^ と .. も展開">
<code><span class="type">ReadOnlySpan</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">a</span> = <span class="reserved">new</span>[] { 1, 2, 3, 4, 5 };

<span class="reserved">var</span> <span class="variable">length</span> = <span class="variable">a</span>.Length;
<span class="control">if</span> (<span class="variable">length</span> &gt;= 2 &amp;&amp; <span class="variable">a</span>[0] == 1)
{
    <span class="reserved">var</span> <span class="variable">middle</span> = <span class="variable">a</span>.<span class="method">Slice</span>(1, <span class="variable">length</span> - 1 - 1);
    <span class="control">if</span> (<span class="variable">a</span>[<span class="variable">length</span> - 1] == 5)
    {
        <span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="variable">middle</span>.Length);
    }
}
</code></pre>
<p>ちなみに、<code>Length</code> か <code>Count</code> プロパティとインデクサーを持っている型に対してリスト パターンを使えます。</p>
<h2><a id="collection-literal">[] リテラル (C# 11 より後かも)</a></h2>
<p><code>new[] {}</code> との対称性をあきらめてパターン側を <code>[]</code> にしたわけですが、
ここで逆の発想が出て来たみたいです。
配列・コレクションの初期化の方も <code>[]</code> リテラルでやる案。</p>
<pre class="source" title="[] でコレクション初期化">
<code><span class="reserved">using</span> System.Collections.Immutable;

<span class="reserved">int</span>[] <span class="variable">array</span> = [ 1, 2 ];
<span class="type">Span</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">span</span> = [ 1, 2 ];
<span class="type">ReadOnlySpan</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">ros</span> = [ 1, 2 ];
<span class="type">List</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">list</span> = [ 1, 2 ];
<span class="type">ImmutableArray</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">immutable</span> = [1, 2];
</code></pre>
<p>これの話はまた回を改めて書くと思いますが、<code>ImmutableArray</code> の初期化も視野に入れています。 (<code>ImmutableArray</code> は今の <code>new() { 1, 2 }</code> だと望まれる動作にならない。)</p>
 ]]></description>
				<pubDate>Wed, 29 Dec 2021 17:27:45 +0900</pubDate>
			</item>
			<item>
				<title>【C# 11 候補】 UTF-8 リテラル</title>
				<link>http://ufcpp.net/blog/2021/12/utf8-literal/</link>
				<description><![CDATA[ <p>.NET の UTF-8 対応がらみの続報。</p>
<h2>byte でやりくり</h2>
<p>元々、<code>string</code> (UTF-16 でデータを持ってる)に加えて <code>Utf8String</code> みたいな名前で UTF-8 な型を追加しようか何て話もあったんですが。
<code>string</code> と <code>Utf8String</code> の2重管理がしんどいだろう、これだけ <code>string</code> 前提で .NET エコシステムが確立された状況で追加は無理だろうという雰囲気になっています。</p>
<p><code>string</code> の中身を UTF-8 に変更した方が建設的かもしれないという話も出るくらいですが、さすがにそれをやりだすと大工事過ぎて短期では無理でしょう。
著者個人的にも「10年先ならわからないけども」くらいのお気持ちになりつつあります。</p>
<p>そうこうしているうちに、「生 byte 列で UTF-8 を扱う」と言うのが .NET エコシステム内でデファクトスタンダード化してしまいました(今ここ)。
例えば <code>System.Text.Unicode</code> 名前空間中のメソッドは以下のような感じになっています。</p>
<pre class="source" title="">
<code><span class="reserved">using</span> System.Buffers;

<span class="reserved">namespace</span> System.Text.Unicode;

<span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">class</span> <span class="type">Utf8</span>
{
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="type">OperationStatus</span> <span class="method">FromUtf16</span>(
        <span class="type">ReadOnlySpan</span>&lt;<span class="reserved">char</span>&gt; <span class="variable">source</span>, <em><span class="type">Span</span>&lt;<span class="reserved">byte</span>&gt; <span class="variable">destination</span></em>, <span class="reserved">out</span> <span class="reserved">int</span> <span class="variable">charsRead</span>, <span class="reserved">out</span> <span class="reserved">int</span> <span class="variable">bytesWritten</span>,
        <span class="reserved">bool</span> <span class="variable">replaceInvalidSequences</span> = <span class="reserved">true</span>, <span class="reserved">bool</span> <span class="variable">isFinalBlock</span> = <span class="reserved">true</span>);

    <span class="reserved">public</span> <span class="reserved">static</span> <span class="type">OperationStatus</span> <span class="method">ToUtf16</span>(
        <em><span class="type">ReadOnlySpan</span>&lt;<span class="reserved">byte</span>&gt; <span class="variable">source</span></em>, <span class="type">Span</span>&lt;<span class="reserved">char</span>&gt; <span class="variable">destination</span>, <span class="reserved">out</span> <span class="reserved">int</span> <span class="variable">bytesRead</span>, <span class="reserved">out</span> <span class="reserved">int</span> <span class="variable">charsWritten</span>,
        <span class="reserved">bool</span> <span class="variable">replaceInvalidSequences</span> = <span class="reserved">true</span>, <span class="reserved">bool</span> <span class="variable">isFinalBlock</span> = <span class="reserved">true</span>);
}
</code></pre>
<p><code>Span&lt;byte&gt;</code> と <code>ReadOnlySpan&lt;byte&gt;</code> で UTF-8 文字列を扱っています。</p>
<p>文字なのかその他のバイナリ形式なのかがわからなくなるんであんまり親切設計ではないんですが…
型変換やオーバーロードをあんまり増やすのもしんどく、
「生 byte 列で UTF-8 を扱う」は結構定着しちゃうんじゃないかという感じ。</p>
<h2>リテラル問題</h2>
<p>とはいえ。
UTF-8 扱いで <code>Span&lt;byte&gt;</code> とかを使うにあたって困るのが文字列リテラル。
今だと以下のように <code>byte</code> 定数的に <code>new byte[]</code> するしか方法がありません。</p>
<pre class="source" title="UTF-8 代わりの byte 定数">
<code><span class="type">ReadOnlySpan</span>&lt;<span class="reserved">byte</span>&gt; <span class="variable">_true</span> = <span class="reserved">new</span> <span class="reserved">byte</span>[] { (<span class="reserved">byte</span>)<span class="string">'t'</span>, (<span class="reserved">byte</span>)<span class="string">'r'</span>, (<span class="reserved">byte</span>)<span class="string">'u'</span>, (<span class="reserved">byte</span>)<span class="string">'e'</span> };
<span class="type">ReadOnlySpan</span>&lt;<span class="reserved">byte</span>&gt; <span class="variable">_false</span> = <span class="reserved">new</span> <span class="reserved">byte</span>[] { (<span class="reserved">byte</span>)<span class="string">'f'</span>, (<span class="reserved">byte</span>)<span class="string">'a'</span>, (<span class="reserved">byte</span>)<span class="string">'l'</span>, (<span class="reserved">byte</span>)<span class="string">'s'</span>, (<span class="reserved">byte</span>)<span class="string">'e'</span> };
<span class="type">ReadOnlySpan</span>&lt;<span class="reserved">byte</span>&gt; <span class="variable">_null</span> = <span class="reserved">new</span> <span class="reserved">byte</span>[] { (<span class="reserved">byte</span>)<span class="string">'n'</span>, (<span class="reserved">byte</span>)<span class="string">'u'</span>, (<span class="reserved">byte</span>)<span class="string">'l'</span>, (<span class="reserved">byte</span>)<span class="string">'l'</span> };
</code></pre>
<p>一応、これ、最適化はされて <code>new byte[]</code> のヒープ アロケーションは発生せず、
直接 DLL 中のデータ領域からデータが読まれます。</p>
<p>この3つくらいならいいんですけども、極まってくるとありとあらゆる文字列リテラルを UTF-8 byte 列化したくなり…</p>
<ul>
<li><a href="https://github.com/dotnet/aspnetcore/blob/8b30d862de6c9146f466061d51aa3f1414ee2337/src/Servers/Kestrel/Core/src/Internal/Http2/Http2Connection.Generated.cs">HTTP のヘッダーとかで使う文字列</a></li>
<li><a href="https://github.com/dotnet/aspnetcore/blob/52eff90fbcfca39b7eb58baad597df6a99a542b0/src/Shared/runtime/Http2/Hpack/StatusCodes.cs">HTTP のステータス コード</a></li>
</ul>
<p>とかを見てもらえるとなかなかにつらみを感じてもらえるのではないかと思います。</p>
<p><code>&quot;100&quot;</code> みたいなものすら <code>new byte[] { (byte)'1', (byte)'0', (byte)'0' }</code>。</p>
<h2>UTF-8 文字列リテラル</h2>
<p>と言うことで着地点として、<a href="https://github.com/dotnet/csharplang/blob/main/proposals/utf8-string-literals.md">リテラルだけ UTF-8 なものを用意しようか</a>という雰囲気になっています。</p>
<ul>
<li><code>Span&lt;byte&gt;</code> や <code>ReadSpan&lt;byte&gt;</code> に対して文字列リテラルを渡すと自動的に上記のような UTF-8 byte 列を生成する</li>
<li>オーバーロード解決や <code>var</code> 型推論用に <code>u8</code> 接尾辞を用意</li>
</ul>
<p>例えば以下のように書けるようになります。</p>
<p>暗黙的変換:</p>
<pre class="source" title="byte[] とかへの文字列リテラル代入は UTF-8 byte 列扱い">
<code><span class="reserved">byte</span>[] <span class="variable">array</span> = <span class="string">&quot;hello&quot;</span>;             <span class="comment">// new byte[] { 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x20 }</span>
<span class="type">Span</span>&lt;<span class="reserved">byte</span>&gt; <span class="variable">span</span> = <span class="string">&quot;dog&quot;</span>;            <span class="comment">// new byte[] { 0x64, 0x6f, 0x67 }</span>
<span class="type">ReadOnlySpan</span>&lt;<span class="reserved">byte</span>&gt; <span class="variable">span</span> = <span class="string">&quot;cat&quot;</span>;    <span class="comment">// new byte[] { 0x63, 0x61, 0x74 }</span>
</code></pre>
<p><code>u8</code> 接尾辞:</p>
<pre class="source" title="u8 を付けると UTF-8 リテラルに">
<code><span class="reserved">string</span> <span class="variable">s1</span> = <span class="string">&quot;hello&quot;</span>u8;      <span class="comment">// エラー。型が合ってない。</span>
<span class="reserved">var</span> <span class="variable">s2</span> = <span class="string">&quot;hello&quot;</span>u8;         <span class="comment">// Ok。型は ReadOnlySpan&lt;byte&gt;。</span>
<span class="type">Span</span>&lt;<span class="reserved">byte</span>&gt; <span class="variable">s3</span> = <span class="string">&quot;hello&quot;</span>u8;  <span class="comment">// Ok。</span>
<span class="reserved">byte</span>[] <span class="variable">s4</span> = <span class="string">&quot;hello&quot;</span>u8;      <span class="comment">// Ok。</span>
</code></pre>
<p>UTF-8 として不正になる文字列リテラルはコンパイル エラーにするそうです。
.NET の文字列は UTF-16 というか実際には「古き良き Unicode」(2バイト固定長で行けると思ってた頃の Unicode)なので、「<a href="https://codezine.jp/article/detail/1592">サロゲート ペア</a>の片割れ」みたいな今となってはダメなやつを受け付けてしまうので。</p>
<pre class="source" title="不正な UTF-16 はコンパイル エラーに">
<code><span class="reserved">byte</span>[] <span class="variable">array</span> = <span class="string">&quot;\uD801&quot;</span>; <span class="comment">// ハイ サロゲートのみ。コンパイル エラーにする。</span>
</code></pre>
<p>ちなみに、<code>const string</code> から UTF-8 リテラルも作れるし、
「不正な UTF-16 を <code>+</code> でつないで、その結果が有効な UTF-8 になるなら OK」だそうです。</p>
<pre class="source" title="不正 UTF-16 な const string 2つ → 有効な UTF-8 リテラル">
<code><span class="reserved">const</span> <span class="reserved">string</span> first = <span class="string">&quot;\uD83D&quot;</span>;  <span class="comment">// ハイ サロゲート。</span>
<span class="reserved">const</span> <span class="reserved">string</span> second = <span class="string">&quot;\uDE00&quot;</span>; <span class="comment">// ロー サロゲート。</span>
<span class="type">ReadOnlySpan</span>&lt;<span class="reserved">byte</span>&gt; <span class="variable">span</span> = first + second; <span class="comment">// これは OK</span>
</code></pre>
<h2>Utf8String 型の可能性</h2>
<p>前述の通り、今の <code>string</code> を置き換えるような <code>Utf8String</code> 型が追加される可能性はかなり低くなってきたんですが。</p>
<p>一応まだ可能性 0 とは断じない方がいいので、一応この仮定的な <code>Utf8String</code> の存在は考慮しているそうです。</p>
<p>もしも <code>Utf8String</code> が積極的に使いたい「良い型」になったとしても、
たぶん、<code>&quot;&quot;</code> から <code>byte[]</code>、<code>Span&lt;byte&gt;</code>、<code>ReadOnlySpan&lt;byte&gt;</code> への暗黙的変換は対して問題にならなさそう。</p>
<p>後悔するとしたら <code>u8</code> 接尾辞の「自然な型」を <code>ReadOnlySpan&lt;byte&gt;</code> にしてしまう点で、これに関しては「やっぱり <code>Utf8String</code> に変えたい」となっても変えれるものではなくなります。
とはいえ、「なので今は自然な型を決めるのはやめておこう」と思うほどのものではない(ので、<code>ReadOnlySpan&lt;byte&gt;</code> な方針でいく)でしょう。</p>
 ]]></description>
				<pubDate>Tue, 28 Dec 2021 14:45:05 +0900</pubDate>
			</item>
			<item>
				<title>【C# 11 候補】 半自動プロパティ</title>
				<link>http://ufcpp.net/blog/2021/12/semi-auto-property/</link>
				<description><![CDATA[ <p><a href="https://ufcpp.net/blog/2021/11/2022-ga-soon/">11月くらいからなんとか消化し始めた</a>「<a href="https://www.youtube.com/channel/UCY-z_9mau6X-Vr4gk2aWtMQ">C# ライブ配信</a>で口頭では言ったけどブログ化はしてなかったやつ」、
「C# 10.0 の補足」とか、文字コード・絵文字がらみの雑談話を抜けて、
やっと「C# 11.0 候補」の話になります。</p>
<p>こんな時間かかるかー…</p>
<h2>半自動プロパティ</h2>
<p>C# 11 目標で、自動プロパティにちょっと手が入りそうです。</p>
<p><a href="https://ufcpp.net/study/csharp/oo_property.html#auto">バッキング フィールド</a>を <code>field</code> キーワードで読み書きできるようにするというもの。
俗称「半自動プロパティ」。</p>
<h2>おさらい: 初期 C# のプロパティ</h2>
<p>C# 1.0 の頃からの一番煩雑な書き方だとプロパティは以下のように書いていました。追加でフィールドが1個必要。</p>
<pre class="source" title="C# 初期のプロパティ">
<code><span class="reserved">class</span> <span class="type">A</span>
{
    <span class="reserved">private</span> <span class="reserved">int</span> _x;
    <span class="reserved">public</span> <span class="reserved">int</span> X { <span class="reserved">get</span> { <span class="control">return</span> _x; } <span class="reserved">set</span> { _x = <span class="reserved">value</span>; } }
}
</code></pre>
<p>それに対して C# 3.0 で書けるようになった簡易記法が自動プロパティ(automatically implemented property、通称 auto-property)。
<code>get; set;</code> だけ書くと、上記の <code>_x</code> フィールド相当のものを自動的に作ってくれます。</p>
<pre class="source" title="C# 3.0 の自動プロパティ">
<code><span class="reserved">class</span> <span class="type">A</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> X { <span class="reserved">get</span>; <span class="reserved">set</span>; }
}
</code></pre>
<h2>自動プロパティが使えなかったものの例</h2>
<p>(この後もプロパティは細かく色々な改善があるんですが、それは置いておいて)</p>
<p>C# 3.0～10.0 までの “完全に自動な” プロパティだと一部の頻出する用途に使えなくて、結局は自前でフィールドを用意しないといけないことがありました。
特に有名な例を2つ挙げると、</p>
<p>1． PropertyChanged</p>
<pre class="source" title="PropertyChanged のためにフィールドが必要">
<code><span class="reserved">using</span> System.ComponentModel;
<span class="reserved">using</span> System.Runtime.CompilerServices;

<span class="reserved">class</span> <span class="type">A</span> : <span class="type">INotifyPropertyChanged</span>
{
    <span class="reserved">private</span> <span class="reserved">int</span> _x;
    <span class="reserved">public</span> <span class="reserved">int</span> X { <span class="reserved">get</span> =&gt; _x; <span class="reserved">set</span> =&gt; <span class="method">SetProperty</span>(<span class="reserved">ref</span> _x, <span class="reserved">value</span>); }

    <span class="reserved">public</span> <span class="reserved">event</span> <span class="type">PropertyChangedEventHandler</span>? PropertyChanged;

    <span class="reserved">protected</span> <span class="reserved">void</span> <span class="method">SetProperty</span>&lt;<span class="type">T</span>&gt;(<span class="reserved">ref</span> <span class="type">T</span> <span class="variable">storage</span>, <span class="type">T</span> <span class="variable">newValue</span>, [<span class="type">CallerMemberName</span>] <span class="reserved">string</span>? <span class="variable">propertyName</span> = <span class="reserved">null</span>)
    {
        <span class="variable">storage</span> = <span class="variable">newValue</span>;
        PropertyChanged?.<span class="method">Invoke</span>(<span class="reserved">this</span>, <span class="reserved">new</span>(<span class="variable">propertyName</span>));
    }
}
</code></pre>
<ol>
<li>遅延初期化</li>
</ol>
<pre class="source" title="初回限りの重たい処理を、プロパティの初アクセス時に呼びたい">
<code><span class="reserved">class</span> <span class="type">A</span>
{
    <span class="reserved">private</span> <span class="reserved">string</span>? _x;
    <span class="reserved">public</span> <span class="reserved">string</span> X =&gt; _x ?? <span class="method">GetX</span>();

    <span class="reserved">private</span> <span class="reserved">string</span> <span class="method">GetX</span>()
    {
        <span class="comment">// 初回限りの重たい処理</span>
    }
}
</code></pre>
<h2>field キーワードの追加</h2>
<p>で、要望自体は結構昔からあったんですがようやく C# 11.0 で採用されそうなのが「<code>field</code> キーワード」。</p>
<p>例えば前節の例は以下のように書けます。</p>
<p>1． PropertyChanged</p>
<pre class="source" title="">
<code><span class="reserved">class</span> <span class="type">A</span> : <span class="type">INotifyPropertyChanged</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> X { <span class="reserved">get</span> =&gt; <em><span class="reserved">field</span></em>; <span class="reserved">set</span> =&gt; SetProperty(<span class="reserved">ref</span> <em><span class="reserved">field</span></em>, <span class="reserved">value</span>); }

    <span class="comment">// 以下元と同じ</span>
}
</code></pre>
<ol>
<li>遅延初期化</li>
</ol>
<pre class="source" title="field キーワードで遅延初期化">
<code><span class="reserved">class</span> <span class="type">A</span>
{
    <span class="reserved">public</span> <span class="reserved">string</span> X =&gt; <em><span class="reserved">field</span></em> ?? <span class="method">GetX</span>();

    <span class="comment">// 以下元と同じ</span>
}
</code></pre>
<h2>細々補足</h2>
<p>以下のような補足あり。</p>
<ul>
<li>
C# らしく(破壊的変更を避けて)、<code>field</code> は文脈キーワード
<ul>
<li><code>field</code> と言う名前のフィールドがない場合だけキーワード扱い</li>
</ul>
</li>
<li>キーワード扱いを受けた場合、<code>nameof(value)</code> はコンパイルできないという仕様。</li>
<li>
<code>get</code> 側しかない場合は get-only プロパティと同様
<ul>
<li>コンストラクターでだけ <code>set</code> 可能</li>
<li>生成されるフィールドは <code>readonly</code> 扱い</li>
</ul>
</li>
</ul>
<p>この新機能、俗称としては「半自動プロパティ」(semi-auto-property)なんですが、実装上・仕様書上は「自動プロパティの項目を修正」みたいです。</p>
<p>元:</p>
<ul>
<li>セミコロンのみの <code>get;</code> <code>set;</code> しかないプロパティを自動プロパティと呼ぶ</li>
</ul>
<p>変更後:</p>
<ul>
<li>
以下の2つを自動プロパティと呼ぶ
<ul>
<li>セミコロンのみの <code>get;</code> <code>set;</code> アクセサーしかないプロパティ</li>
<li>アクセサー内で <code>field</code> キーワードを使っているプロパティ</li>
</ul>
</li>
</ul>
<h2>おまけ field はキーワードで value は変数？キーワード？</h2>
<p>ちょっと余談。</p>
<p>field は明確に「文脈キーワード」です。補足説明の通り、<code>nameof(field)</code> 不可。</p>
<p>ところで、じゃあ、C# 1.0 の頃からある <code>value</code> はと言うと…
とりあえず、Visual Studio 上では「青」(キーワード扱いの色)です。
(↓ うちのサイトの色付けは Visual Studio 初期設定準拠。)</p>
<pre class="source" title="value は青">
<code><span class="reserved">class</span> <span class="type">A</span>
{
    <span class="reserved">private</span> <span class="reserved">int</span> _x;
    <span class="reserved">public</span> <span class="reserved">int</span> X { <span class="reserved">set</span> =&gt; _x = <span class="reserved">value</span>; }
    <span class="comment">// ↑ Visual Studio 上、value の文字は青(キーワードの色)になってる。</span>
}
</code></pre>
<p>ところで、この <code>value</code>、仕様書上は「<code>set</code> アクセサーには暗黙の引数 <code>value</code> がある」みたいな書かれ方になっています。
そして、結果的に <code>nameof(value)</code> は許されるという。</p>
<pre class="source" title="nameof(value)">
<code><span class="reserved">class</span> <span class="type">A</span>
{
    <span class="reserved">private</span> <span class="reserved">string</span> _x;
    <span class="reserved">public</span> <span class="reserved">int</span> X { <span class="reserved">set</span> =&gt; _x = <span class="reserved">nameof</span>(<span class="reserved">value</span>); }
    <span class="comment">// 意味あるコードではないものの、とりあえずコンパイル可能。</span>
}
</code></pre>
<p><code>nameof(int)</code> とかも許されておらず、<code>nameof</code> の中に「青」が来る(たぶん)唯一の例となります。</p>
<p>時代の名残りと言うかなんというか…
今なら <code>value</code> も文脈キーワードにしたかもしれないですね。</p>
<p>ちなみに、同じく仕様からして「暗黙の引数」とされている<a href="https://ufcpp.net/study/csharp/misc/miscentrypoint/#top-level-statements">トップ レベル ステートメント</a>の<a href="https://ufcpp.net/study/csharp/misc/miscentrypoint/#args-returns">コマンドライン引数の <code>args</code></a> はちゃんと「群青」(変数・引数の色)です。</p>
<pre class="source" title="args は群青">
<code><span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="variable">args</span>[0]);
</code></pre>
<p>まあ、<code>field</code> キーワードは最初から「キーワード扱い」の予定です。</p>
<pre class="source" title="field は青">
<code><span class="reserved">class</span> <span class="type">A</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> X { <span class="reserved">set</span> =&gt; <span class="reserved">field</span> = <span class="reserved">value</span>; }
}
</code></pre> ]]></description>
				<pubDate>Mon, 27 Dec 2021 15:16:10 +0900</pubDate>
			</item>
			<item>
				<title>悪い意味でお気に入りの文字 〠〄</title>
				<link>http://ufcpp.net/blog/2021/12/notorious-compat-char/</link>
				<description><![CDATA[ <p>こないだ書いた<a href="https://ufcpp.net/blog/2021/12/unicode-benzene/">ベンゼン環の話</a>と<a href="https://ufcpp.net/blog/2021/12/ninjacatdies/">ニンジャキャット終了のお知らせ</a>はある意味前振りだったりしまして。</p>
<p>個人的にやべぇなと思う Unicode の文字で1・2を争うのは 〠 と 〄 だったりします。</p>
<ul>
<li>〠: U+3020、postal mark face、顔郵便マーク</li>
<li>〄: U+3004、Japanese industrial standard symbol、JIS マーク</li>
</ul>
<p><img src="/media/1203/japanesesymbols.png" alt="〠〄" /></p>
<p><a href="#apple-log">アップルロゴ</a>の話で書きましたが、
商標になるようなものを Unicode に入れるとか普通は考えられないわけですが。
〠 と 〄 は一体…</p>
<h2>出どころ</h2>
<p>2文字とも出自は <a href="https://ja.wikipedia.org/wiki/MacJapanese">MacJapanese</a> でして。
要は Shift_JIS の Mac 独自拡張。</p>
<p>どうも元々は日本の中小印刷所が使っていた外字だったらしい？
それがデファクトスタンダード化して Mac OS に取り込まれ。
それとの「互換性用文字」として Unicode にも含まれてしまったという経緯。</p>
<p>商標的にも怪しいですし、今の Unicode は「1国のローカルでだけ通用する記号の類」を文字として追加することには否定的なんで、今の基準でいうと絶対に入らなさそうな文字です。
ただ、MacJapanse としてもう流通してしまっている以上、互換性用としては必要。</p>
<p>とはいえ、商標の権利上の懸念から<a href="https://emojipedia.org/apple-logo/">アップルのロゴ</a>は Unicode には収録されなかったわけで、
じゃあどうして 〠 と 〄 は平気だったのか…
私企業じゃく公的な物だとか、商標登録されてるかとかの差はあるでしょうけども。</p>
<h2>〠</h2>
<p>郵便番号を 〒 で表すこと自体、日本独自です。
この記号は逓信(ていしん)の「テ」か「T」から来てるとする説が有力らしく、今となってはその元ネタの「逓」の文字すら使われておらず。</p>
<p>まして顔の方。
郵政省のマスコットですよね？</p>
<p>一応、正確に言うと、〠 に手と胴体の付いたキャラクターが「<a href="https://ja.wikipedia.org/wiki/%E9%A1%94%E9%83%B5%E4%BE%BF%E3%83%9E%E3%83%BC%E3%82%AF#%E3%83%8A%E3%83%B3%E3%83%90%E3%83%BC%E3%81%8F%E3%82%93">ナンバーくん</a>」という郵政省(郵政民営化前)のマスコットだったみたいです。
(「胴体が付いてないからナンバーくんではない」と言えなくもない。)</p>
<p>そしてこの「ナンバーくん」は「役割を終えた」、「民営化に伴い新会社では『撤去が望ましい』」とか言われているそうで。
日本郵便のマスコット キャラクターとしては今現在「ポストンくん」という別キャラがいるそうです。</p>
<p>ちなみに、<a href="https://ja.wikipedia.org/wiki/%E9%A1%94%E9%83%B5%E4%BE%BF%E3%83%9E%E3%83%BC%E3%82%AF#%E3%83%9D%E3%82%B9%E3%83%88%E3%83%B3%E3%81%AE%E5%B0%8E%E5%85%A5">Wikipedia のポストンくんのところ</a>を読んでると、「フォントのメイリオでは、ベータ版公開時には郵便マークのコードポイントのU+3020にポストンの記号が使用されていた」とか書かれていたりします。
要は、互換性のためだけに存在する文字(しかも権利的に怪しい文字)に対して字形変更をすべきかどうか問題が発生。</p>
<h2>〄</h2>
<p>要は JIS マーク。
「JIS 適合していることを認証された」というのを1文字で印刷所に送れるのは昔は重宝したんでしょうね…</p>
<p>ところでこの記号、よく見てください。
いわゆる「旧 JIS マーク」になっています。
2004年に工業規格の法改正に伴って JIS マークも刷新されています。
「ポストンくん」問題同様、こっちでも「<a href="https://www.unicode.org/mail-arch/unicode-ml/y2009-m07/0111.html">Unicode 中の 〄 もグリフ字形すべき？</a>」みたいな話があったりします。</p>
<h2>新字形の文字コード</h2>
<p>ここでまあ、<a href="https://ufcpp.net/blog/2021/12/unicode-benzene/">ベンゼン環は ⌬ と ⏣ の2文字ある</a>という話につながります。</p>
<p>JIS マークも「やるんだったら新旧両方の字体があるべきだろう」という所までは話した出ており。
現実的には、元々の 〄 (U+3004) に<a href="https://ja.wikipedia.org/wiki/%E7%95%B0%E4%BD%93%E5%AD%97%E3%82%BB%E3%83%AC%E3%82%AF%E3%82%BF">異体字セレクター</a>でも付けるのがいいんじゃないかということになっています。</p>
<p>ちなみに、需要がなさ過ぎて具体的な議論は進んでいないので、
そんな文字が Unicode に追加されることはまあまずないと思います。</p>
<p>ただ、<a href="https://glyphwiki.org/">GlyphWiki</a> (共同編集で保守されている文字字形 Wiki)には 〄 のバリエーションとして<a href="https://glyphwiki.org/wiki/u3004-var-001">新 JIS マークのページ</a>があったり、
一部の DTP 向けフォントには外字として新 JIS マークがあるらしかったり、
今でも日本には「文字として JIS マークを印刷したい」需要はあるんですね…</p>
<h2>まとめ</h2>
<p>ということで改めて 〠 と 〄、</p>
<ul>
<li>互換性のためだけにある</li>
<li>権利関係が謎</li>
<li>しかも今現在、新意匠が作られたのでもう使われなくなった字形</li>
<li>Unicode 的にも字形変更すべきか議論がある</li>
</ul>
<p>というなかなかに罪深い文字だったりします。</p>
<p>なので絵文字に関する地雷話をしてるときとかに、「まあ絵文字じゃなくてもこんなやべぇやつがいるんで今更」みたいな話をよくしたり。</p>
 ]]></description>
				<pubDate>Sun, 26 Dec 2021 20:48:53 +0900</pubDate>
			</item>
			<item>
				<title>任意色絵文字？</title>
				<link>http://ufcpp.net/blog/2021/12/full-color-emoji/</link>
				<description><![CDATA[ <p>🐈‍⬛</p>
<p>Windows にもついに Unicode 13.0 が来ました(今更)。</p>
<h2>Unicode 13.0</h2>
<p>Unicode 13.0 のリリース、2020年3月なんですよね。
ずいぶんと前。</p>
<p>それに対して、Windows 10 の間は Unicode 13.0 には一向に対応せず…
今思えば新しい絵柄(Windows 11 の新絵文字)を作っていたから、古い絵柄(Windows 10 の絵文字)を更新するリソースを割かなかったんだろうなとは思うんですが。</p>
<p>Unicode 13.0 の新文字の分かりやすいのが本項冒頭の黒猫でして、
🐈‍⬛ の文字、Windows 10 だと 🐈⬛ (ネコ + 黒四角)になるはずです。</p>
<p>というか、Windows 11 でも対応したのはつい最近です。
こないだ<a href="https://ufcpp.net/blog/2021/12/ninjacatdies/">ニンジャキャット終了のお知らせ</a>のときに書いた新絵文字のタイミングでやっと黒猫が表示できるようになりました。</p>
<p>iOS とかから遅れること1年半以上…</p>
<p><a href="https://twitter.com/AXIA_96NE">にじさんじの新人さん(今年7月デビュー)</a>が 🐈‍⬛ を推し絵文字に決定した時には「やべ、Windows で表示できねぇ…」ってなって焦りました。</p>
<h2>色選択</h2>
<p>さてこの黒猫、典型的な ZWJ シーケンスです。
最近書いた<a href="https://ufcpp.net/blog/2021/12/regional-indicator/">UTF-8の敗北話</a>とか、
<a href="https://ufcpp.net/blog/2021/12/ninjacatdies/">ニンジャキャット終了のお知らせ</a>とかでも触れてるんですが、</p>
<p>🐈 (U+1F408)、ZWJ (U+200D)、⬛ (U+2B1B)</p>
<p>という3文字から構成される、🐈 の色違い絵文字です。</p>
<p>ちなみにこの ⬛ なんですが、「Black Large Square」という名前の文字です。
そして、実は Large Square シリーズ、現在(Unicode 12.0 以降)、他に7色あります。</p>
<ul>
<li>🟥 (U+1F7E5) Large Red Square</li>
<li>🟦 (U+1F7E6) Large Blue Square</li>
<li>🟧 (U+1F7E7) Large Orange Square</li>
<li>🟨 (U+1F7E8) Large Yellow Square</li>
<li>🟩 (U+1F7E9) Large Green Square</li>
<li>🟪 (U+1F7EA) Large Purple Square</li>
<li>🟫 (U+1F7EB) Large Brown Square</li>
</ul>
<p>これもしや、もはやゲーミング動物絵文字が作れるのでは…</p>
<p>※画像はイメージです</p>
<p><img src="/media/1202/gamingneko.jpg" alt="ゲーミング猫 ※画像はイメージです" /></p>
<p>どう見ても「文字コード」の仕様の範疇を超えてますけども。</p>
<p>実際、こういうのは「文字」のレイヤーの1段上の「マークアップ」とかを使ってやってくれ(要するに、Unicode の債務ではなく、HTML の style 属性とか CSS とかを使って色を付けて欲しい)ということになってたはずなんですけども。</p>
<p>絵文字で Unicode に色の概念を持ち込んじゃったから…
むしろ今、カラー絵文字には foreground-color が効かないですからねぇ。</p>
<p>まあ、こんなカラフル動物絵文字が <a href="https://unicode.org/reports/tr51/#def_rgi_set">RGI</a> (どのベンダーも実装すべきという推奨絵文字)に採用されるとは思えませんが。
むしろ、なんで黒猫を足しちゃったんですかね…</p>
<h2>某4色窓</h2>
<p>そしてこのカラフル四角形があるなら…</p>
<pre>
🟥🟩
🟦🟨
</pre>
<p>あのロゴ行けるんじゃない？
ZWJ シーケンスで四角を4つ繋げば。</p>
<p>みたいな話も <a href="https://www.youtube.com/channel/UCY-z_9mau6X-Vr4gk2aWtMQ">C# ライブ配信</a>中ではよくコメントが付いたりします。</p>
<p>まあ、<a href="https://ufcpp.net/blog/2021/12/ninjacatdies/#apple-log">先日、権利的にまずそうなロゴは Unicode に採用しかねる</a>という話を書いたところなので、こんな絵文字が採用されることはあり得ないんですけども。</p>
<p>特に<a href="https://www.microsoft.com/ja-jp/mscorp/legal/trademarks-corplogo.aspx">この会社、ロゴ利用のガイドラインがものすごくしっかり規定されてるんで</a>、簡単に色々抵触しそうですし。</p>
 ]]></description>
				<pubDate>Wed, 22 Dec 2021 20:24:20 +0900</pubDate>
			</item>
			<item>
				<title>ニンジャキャット&#128049;‍&#128100;</title>
				<link>http://ufcpp.net/blog/2021/12/ninjacatdies/</link>
				<description><![CDATA[ <p>ニンジャキャット終了のお知らせ。</p>
<p><img src="/media/1199/ninjacat11.png" alt="ニンジャキャット終了のお知らせ" /></p>
<p>そんなキャラはいなかった。いいね？</p>
<h2><a id="new-emoji-glyph-win11">Windows の絵文字の絵柄一新</a></h2>
<p>Windows 11 で Unicode 絵文字の絵柄が一新されると言われていたわけですが。
Windows 11 初期リリースでは変更がなく、<a href="https://forest.watch.impress.co.jp/docs/news/1368473.html">先月ようやく新絵文字の一般提供開始</a>されました。
そろそろ万人に(Dev 版とか Beta 版に登録してない人にも)届く頃ではないかと思います。</p>
<p>その結果が冒頭の絵文字。
ちなみに、同じものをこれまでの(Windows 10 とかの)絵文字で表示すると以下のようになります。</p>
<p><img src="/media/1200/ninjacat10.png" alt="Windows 10 のとき" /></p>
<h2><a id="windows-original-emoji">Windows オリジナル絵文字</a></h2>
<p>この猫の絵文字、Windows のオリジナル絵文字です。
一応、ニュースになるくらいにはなってたんですが:</p>
<ul>
<li><a href="https://gigazine.net/news/20160413-emoji-ninja-cat/">Windows 10にオリジナル絵文字「ニンジャキャット」が追加されることが明らかに</a></li>
</ul>
<p>こいつ、元々は「内輪ネタ」だそうです。</p>
<p>このバージョンの Windows 10 (Build 14316)は ZWJ シーケンス(後述)に対応した初めてのバージョンっぽい(たぶん)ので、
それの社内テスト用に「内輪のキャラ」を使っていたんですかね。
なぜ公開した…</p>
<p>ちなみに、<a href="https://blogs.windows.com/windows-insider/2016/04/06/announcing-windows-10-insider-preview-build-14316/">Windows 公式ブログ</a>では「いろんな絵文字に対応したよ」というアピールはあるものの、
「オリジナル絵文字を足したよ」なんて言葉はどこにもないので、
特に「良かれと思って足した文字」ではないんじゃないかと思います。
ただの茶目っ気。</p>
<h2><a id="uax29">Unicode の仕様的な話</a></h2>
<p>Unicode の絵文字がらみの仕様には何段階かあるんですが…</p>
<ul>
<li>
<a href="https://unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries">Graphme Cluster Boundaries</a>
<ul>
<li>「一連の文字を、ユーザーインターフェース上は1文字として扱え」という仕様</li>
<li>例えば、「<a href="https://ja.wikipedia.org/wiki/%E3%83%80%E3%82%A4%E3%82%A2%E3%82%AF%E3%83%AA%E3%83%86%E3%82%A3%E3%82%AB%E3%83%AB%E3%83%9E%E3%83%BC%E3%82%AF">発音区別符号</a>の手前で切ってはいけない」みたいなの</li>
</ul>
</li>
<li>
<a href="https://unicode.org/reports/tr29/#GB11">ZWJ シーケンス</a>
<ul>
<li>Graphme Cluster の作り方の1つ</li>
<li>「<a href="https://ja.wikipedia.org/wiki/%E3%82%BC%E3%83%AD%E5%B9%85%E6%8E%A5%E5%90%88%E5%AD%90">接合子</a>と呼ばれる文字の前後で切ってはいけない」という仕様</li>
<li>わりかし機械的に判定可能</li>
<li>「複数の絵文字を ZWJ でつないで別の絵文字を作る」という仕様あり</li>
</ul>
</li>
<li>
<a href="https://unicode.org/reports/tr51/#def_rgi_set">RGI 絵文字</a>
<ul>
<li>Recommended for General Interchange (一般にやり取り可能にすることを推奨)</li>
<li>最低ラインどのベンダーでも実装してくれることを期待する絵文字の一覧</li>
<li>1文字1文字リストアップしていて機械判定できない</li>
</ul>
</li>
<li>
<a href="https://unicode.org/reports/tr51/#def_emoji_ZWJ_sequences">RGI 絵文字 ZWJ シーケンス</a>
<ul>
<li>ZWJ シーケンスとして定義されている RGI 絵文字</li>
<li>もし対応していない場合、ZWJ を無視して複数の絵文字で描画すればいいと言うことになってる</li>
</ul>
</li>
</ul>
<p>みたいな仕様があります。</p>
<p>(<a href="https://ufcpp.net/blog/2021/12/regional-indicator/">12月4日に書いたブログのネタ</a>もこの類です。)</p>
<h2><a id="ninja-cat-dies">ニンジャキャット終了</a></h2>
<p>で、ニンジャキャットは、「RGI ではない ZWJ 絵文字シーケンス」ということになります。なので、</p>
<ul>
<li>ZWJ シーケンスの仕様に沿って機械判定で「1文字扱い」はどのベンダーでもできる</li>
<li>RGI ではないので別に Windows 以外のベンダーが実装する義理は全くない</li>
<li>対応していないベンダーでは単に「🐱 と 👤 の2文字」とかで描画すればいい</li>
</ul>
<p>という文字。</p>
<p>で、冒頭の画像に戻るわけですが、</p>
<p>Windows 10 の頃:</p>
<p><img src="/media/1200/ninjacat10.png" alt="Windows 10" /></p>
<p>Windows 11 (最近のアップデート):</p>
<p><img src="/media/1199/ninjacat11.png" alt="Windows 11" /></p>
<p>はい、オリジナル絵文字だったものが、「対応していないので2文字で表示します」状態に変わりました。</p>
<p>元から本当に公開するつもりで作った絵文字なのかどうかすら定かではないですからねぇ。
絵柄一新時に追加するとも思えず…</p>
<p>消えたのは順当。
むしろ、IME の変換候補に痕跡が残ってることが問題…</p>
<p>まあ、「<a href="https://github.com/ufcpp/emoji/blob/3e1196a129e5dc1aa557ef2e2c4eeee982a012fc/src/RgiSequenceFinder.Test/FallbackFindIndexTest.cs#L177-L185">対応する必要性がない ZWJ シーケンス用のテストデータ</a>」としては結構便利だったんですけどね。</p>
<h2><a id="kankyo-izon-windows">Windows 曰く、環境依存</a></h2>
<p>もう1個、IME の問題なんですけども…
Windows の IME は「<a href="https://ja.wikipedia.org/wiki/Shift_JIS">JIS X 0208</a> にない文字は全部環境依存扱いする」というのがありまして。</p>
<p>要するに Unicode が普及する前、Shift_JIS が主流、かつ、Windows (<a href="https://ja.wikipedia.org/wiki/Microsoft%E3%82%B3%E3%83%BC%E3%83%89%E3%83%9A%E3%83%BC%E3%82%B8932">CP932</a>) と Mac (<a href="https://ja.wikipedia.org/wiki/MacJapanese">MacJapanese</a>) でそれぞれが Shift_JIS の独自拡張をしていた時代の名残り。</p>
<p>今となっては Windows でも Mac でも Linux でも iOS でも Android でも表示できる文字も「環境依存」扱いしてきます。
以下一例。</p>
<p><img src="/media/1201/kankyoizon.png" alt="環境依存文字の例" /></p>
<p>ちなみに、ひとくくりに環境依存と言っても「何の環境に依存した文字か」が全然違います。</p>
<ul>
<li>
Unicode からの逆輸入で現在の Shift_JIS (<a href="https://ja.wikipedia.org/wiki/Shift_JIS-2004">Shift_JIS-2004</a>) には入っている文字
<ul>
<li>スペード(♠): MacJapanese にあった文字</li>
<li>あお(靑): CP932 にあった文字</li>
<li>おんぷ(♬): Unicode 1.1 での追加</li>
</ul>
</li>
<li>
Unicode にもない文字
<ul>
<li>にんじゃきゃっと(🐱‍👤とか): Windows 以外で表示するつもりのない真に独自の文字</li>
</ul>
</li>
</ul>
<p>真に Windows 独自の文字と、今となっては Shift_JIS にすら入っている文字を同じ「環境依存」でくくるのはさすがにどうかと思うんですけどねぇ…</p>
<h2><a id="kankyo-izon-nowadays">現代の環境依存文字</a></h2>
<h3><a id="benzene">⌬</a></h3>
<p>ちなみに、<a href="https://ufcpp.net/blog/2021/12/unicode-benzene/">12月8日に書いたベンゼン環 ⌬ ⏣</a>は、Unicode にはあるけども意図的に Shift_JIS には逆輸入されなかった文字です。</p>
<p>あと、Unicode に入っている以上、たいていの環境で表示はできる(実際、iOS でも Android でも大丈夫)ので、「環境依存」かと言われると微妙。</p>
<p>(まあ、こいつは IME では変換できませんが。文字コード直打ちからの変換とかネットで検索してコピペ以外の手段で入力する方法、一通りどの OS でも僕は知らないです。)</p>
<h3><a id="apple-log">林檎</a></h3>
<p>他に、MacJapanese にはあって Unicode には輸入されなかった文字として<a href="https://emojipedia.org/apple-logo/">某林檎マーク</a>とかがあったりします。
「特定の一社のロゴマークとかは Unicode に採用しかねる」という理由で Unicode には入らず、
Mac、iOS では<a href="https://ja.wikipedia.org/wiki/%E7%A7%81%E7%94%A8%E9%9D%A2">私用領域</a>を使って林檎マークを表示しています。</p>
<p>私用領域なのでどこの誰がどういう文字のために使おうと自由です。
そういう意味で本当に環境依存。
どこかの誰かがこの文字コードに対して💩を表示しようとも文句は言えません。</p>
<p>今だったら🍎(U+1F34E、red apple)と🌈(U+1F308、rainbow)を使った ZWJ シーケンスとかで表現するんでしょうけどねぇ。
MacJapanese から Unicode への移行期には絵文字も ZWJ シーケンスの仕様もありませんでしたから。</p>
 ]]></description>
				<pubDate>Sun, 19 Dec 2021 15:07:48 +0900</pubDate>
			</item>
			<item>
				<title>【近々警告追加】小文字 a～z 型名</title>
				<link>http://ufcpp.net/blog/2021/12/lower-cased-type-names/</link>
				<description><![CDATA[ <h2>型名のコードスタイル</h2>
<p>C# も最近はコードスタイル的なものに対するおせっかいをするようになってきました。
そのうちの1つが「型名は小文字始まりやめろ」。</p>
<p><img src="/media/1198/ide1006.png" alt="型名は小文字始まりやめろ" /></p>
<p>現在はこれが Suggestion レベルのメッセージ(警告ほど深刻ではないものの、Visual Studio 上で常に下線が表示されて結構「直せ」圧強め)になります。</p>
<p>まあ、このスタイルに違反する人はそんなにいないんじゃないかと思います。
C# の型名と言えば大体大文字始まりの UpperCamelCase。
類縁なプログラミング言語の Java でも型名は UpperCamel なのでこれに関して宗教論争になることはほとんどないかと思われます。</p>
<h2>型名とキーワードの弁別</h2>
<p>C# は後方互換性をものすごく大事にする言語で、
極端な話20年近く前の C# 1.0 時代に書いたコードも8～9割方そのまま今の C# 10.0 で動くんじゃないかと思います。</p>
<p>そんな言語なので、新文法のためにキーワードを追加したい場合、
ほとんどは「文脈キーワード」(contextual keyword)です。
文字通り「文脈を見てキーワードなのか、通常の識別子なのかを弁別」みたいなことをしています。
この辺り、<a href="https://ufcpp.net/blog/2021/2/lexicalkeywords/">今年の2月にも同じような話をしています</a>が、<code>var</code> なんかは</p>
<ul>
<li><code>var</code> と言う名前の型がどこかに存在したら型名扱い</li>
<li>それがなければキーワード</li>
</ul>
<p>みたいな扱いになります。</p>
<p>で、その2月のブログでも言っていますが、
あんまりにも文脈に頼った弁別をするのはなかなかに大変と言う議題が上がっています。</p>
<p>特に、C# 9.0 で<a href="https://ufcpp.net/study/csharp/datatype/record/">レコード型</a>を追加するにあたって問題になったんですが、
(識別子の中でも特に)型名がキーワードとぶつかると弁別がかなりしんどいそうです。</p>
<p>ということで、<code>record</code> キーワードの追加にあっては破壊的変更(過去に <code>record</code> という名前の型を作って運用しているコードは C# 9.0 にするとコンパイルが通らなくなる)を認めることになりました。
例えば以下のコードは C# 8.0 と 9.0 で意味が変わります。</p>
<pre class="source" title="C# 9.0 での破壊的変更">
<code><span class="reserved">class</span> <span class="type">A</span>
{
    <span class="reserved">record</span> <span class="type">record</span>;
}
</code></pre>
<ul>
<li>C# 8.0: <code>record</code> と言う名前の型の、<code>record</code> という名前のフィールドになる</li>
<li>C# 9.0: <code>record</code> という名前のレコード型を定義</li>
</ul>
<p>この破壊的変更に際して、そもそもとして、「<code>record</code> という名前の型自体に警告」というのも追加しています。</p>
<pre class="source" title="">
<code><span class="comment">// C# 8.0 までは無警告。</span>
<span class="comment">// C# 9.0 で CS8860 警告を追加。</span>
<span class="reserved">class</span> <span class="type"><span class="warning">record</span></span> { }
</code></pre>
<h2>lowerCase 型名要る？</h2>
<p><code>record</code> キーワードの件、
C# にしては珍しい規模の大胆な破壊的変更なんですが。</p>
<p>でも実際のところ、誰かこれで困った人はいらっしゃいます？</p>
<p>今のところ C# チームにもこれを問題視するクレームは全然入ってこないそうです。</p>
<p>そりゃまあ。
そもそも lowerCase な型名、C# では使わないですからね。</p>
<p>そして次の C# 11.0 候補として <code>required</code> というキーワードを足したいそうなんですが、
ここでも改めて「<code>required</code> という名前の型には警告」を出すかどうかが議題に上がりました。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/5439">[Open Question]: required parsing #5439</a></li>
</ul>
<p>ぶっちゃけ、<code>record</code> の時と比べると文脈を見た弁別は簡単だそうです。
とはいえ、<code>record</code> (この名前の方がよっぽど使われる可能性が高い)でも問題を起こさなかったんだから、いっそ <code>required</code> も警告にした方が幸せなのではないかと。</p>
<h2>全部小文字 a～z 型名の禁止</h2>
<p>ということで、将来キーワードとして被りかねない型名は全部警告にしてしまえという話があります。</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/pull/56905">Report a level 7 warning for lower-cased type names #56905</a></li>
</ul>
<p>C# において、キーワードはすべて「小文字のラテンアルファベットのみ」なので、小文字 a～z だけの型名を全部警告に。
Visual Studio 17.1 で導入される予定です。</p>
<p>本項の冒頭の <code>class abc</code> とか <code>record xyz</code> は Suggestion どころではなく、警告になります。
<code>class var</code> とか <code>class dynamic</code> とかもダメですよ！</p>
<p>ちなみに、どうしても小文字アルファベットな型名が必要な場合、<code>@</code> を付けておけば警告は出ないそうです。</p>
<pre class="source" title="CS8981 警告の追加">
<code><span class="comment">// class record だと CS8860 警告。</span>
<span class="comment">// class @record だと IDE1006 suggest だけ。</span>
<span class="reserved">class</span> <span class="type">@record</span> { }

<span class="comment">// class abc だと今後 CS8981 警告が出る予定。</span>
<span class="comment">// class @abc だと IDE1006 suggest だけ。</span>
<span class="reserved">class</span> <span class="type">@abc</span> { }
</code></pre>
<h2>小文字型名警告に備える</h2>
<p>dotnet/runtime 内ではすでにこの警告追加に対する備え済み。</p>
<ul>
<li><a href="https://github.com/dotnet/runtime/pull/62507">Escape lower-cased type names #62507</a></li>
</ul>
<p>ほとんどはちゃんと UpperCamelCase になるようにリネームして対処しています。</p>
<p>一部、<a href="https://github.com/dotnet/runtime/pull/62507#issuecomment-988711116">C/C++ との相互運用の場合は元の型名をそのまま引き継いだ方がいい</a>という理由でそのまま。
これは <code>@</code> を付けて対処したようです。</p>
 ]]></description>
				<pubDate>Fri, 17 Dec 2021 21:47:30 +0900</pubDate>
			</item>
			<item>
				<title>【C# 11 候補】 {} 中の改行</title>
				<link>http://ufcpp.net/blog/2021/12/newlines-in-interpolated-string/</link>
				<description><![CDATA[ <p>今日は「実は Visual Studio 17.1 Preview 1 (先月) の時点で既に入ってた」という機能の話。</p>
<p>C# 11 で、<code>$&quot;{ここ}&quot;</code> みたいな「補完穴」(interpolation hole: 補完文字列の <code>{}</code> の中)の改行に関する仕様がちょっと変わります。</p>
<h2><a id="new-line-in-string">文字列リテラル中の改行</a></h2>
<p>C# の<a href="https://ufcpp.net/study/csharp/st_embeddedtype.html#charl">文字列リテラル</a>は、<code>@</code> を付けると逐語的(<code>\</code> を使ったエスケープをしなくなる)になって、その中には改行を直接入れることができます。</p>
<pre class="source" title="@ を付けると文字列内での改行 OK になる">
<code><span class="comment">// @ を付けると文字列内での改行 OK になる。</span>

<span class="reserved">var</span> <span class="variable">s1</span> = <span class="string">&quot;&quot;</span>; <span class="comment">// 改行入れれない。</span>
<span class="reserved">var</span> <span class="variable">s2</span> = <span class="string">@&quot;
&quot;</span>; <span class="comment">// 改行 OK。</span>
<span class="reserved">var</span> <span class="variable">s3</span> = <span class="string">&quot;</span>
<span class="string"><span class="error">&quot;</span>; // 当然これはコンパイル エラー。</span>
</code></pre>
<p>この仕様、<a href="https://ufcpp.net/study/csharp/st_string.html#key-interpolated-string">補間文字列</a>に対しても同様です。</p>
<pre class="source" title="">
<code><span class="comment">// @ を付けると文字列内での改行 OK になるのは $&quot;&quot; でも一緒。</span>

<span class="reserved">var</span> <span class="variable">x</span> = 123;

<span class="reserved">var</span> <span class="variable">s1</span> = <span class="string">$&quot;</span>{<span class="variable">x</span>}<span class="string">&quot;</span>; <span class="comment">// 改行入れれない。</span>
<span class="reserved">var</span> <span class="variable">s2</span> = <span class="string">@$&quot;</span><span class="string">
</span>{<span class="variable">x</span>}<span class="string">
</span><span class="string">&quot;</span>; <span class="comment">// 改行 OK。</span>
<span class="reserved">var</span> <span class="variable">s3</span> = <span class="string">$&quot;</span>{<span class="variable">x</span>}
<span class="string"><span class="error">&quot;</span>; // 当然これはコンパイル エラー。</span>
</code></pre>
<h2><a id="new-line-in-interpolation-hole">補間穴中の改行</a></h2>
<p>C# はほぼ全ての構文で改行の有無を問わないので、例えば以下の2つのコードは全く同じ意味になります。</p>
<pre class="source" title="1行">
<code><span class="reserved">var</span> <span class="variable">x</span> = 123 + 987;
</code></pre>
<pre class="source" title="改行を入れたもの">
<code><span class="reserved">var</span>
    <span class="variable">x</span>
    =
    123
    +
    987
    ;
</code></pre>
<p>で、補間穴 (<code>{}</code>)の中は普通の C# 構文になります。
前述のような「改行の有無を問わない」という常識に照らし合わせると、
以下のようなコードを書けていいはずです。
(C# 10 まではなぜかダメ。)</p>
<pre class="source" title="{} 中の改行">
<code><span class="comment">// なぜかダメだったコード。</span>

<span class="reserved">var</span> <span class="variable">x</span> = 123;

<span class="reserved">var</span> <span class="variable">s1</span> = <span class="string">$&quot;</span>{
    <span class="variable">x</span>
    }<span class="string"><span class="error">&quot;</span></span>;
</code></pre>
<p>ちなみに、これに <code>@</code> を付けると C# 10 でもコンパイルできます。
というか、さらに言うと割かし何でも書けます。
<code>//</code> コメントすら書けます。</p>
<pre class="source" title="@ を付ければなぜか OK">
<code><span class="comment">// @ を付ければなぜか OK。</span>

<span class="reserved">var</span> <span class="variable">x</span> = 123;

<span class="reserved">var</span> <span class="variable">s1</span> = <span class="string">$@&quot;</span>{
    <span class="variable">x</span>
    +
    987 <span class="comment">// コメントすら OK</span>
    }<span class="string">&quot;</span>;
</code></pre>
<h2><a id="new-line-in-interpolation-hole-11">C# 11 での変更</a></h2>
<p>で、まあ、<code>$&quot;{}&quot;</code> と <code>$@&quot;{}&quot;</code> で挙動が違うの、
<a href="https://github.com/dotnet/csharpstandard/blob/draft-v6/standard/grammar.md">仕様</a>的にもそうなってるらしいんですが、
中の人曰く「<a href="https://github.com/dotnet/csharplang/blob/main/meetings/2021/LDM-2021-09-20.md#newlines-in-non-verbatim-interpolated-strings">改行を禁止した実際の理由、覚えてない</a>」とのこと。</p>
<p>挙動が違うのも変なのでさらっと直したみたいです。
気づいたタイミング的に <a href="https://ufcpp.net/study/csharp/cheatsheet/ap_ver10/">C# 10</a> 正式リリースには間に合わなかったものの、
ほぼ修正は終わってたみたいで、即座に merge、実は 17.1 Preview 1 には入っていたみたいです。</p>
<p>ということで、実は <a href="https://ufcpp.net/study/csharp/cheatsheet/langversionoption/#langversion">LangVersion preview</a> を入れればもう動くらしい。</p>
<p><img src="/media/1197/newlineininterpolation.png" alt="LangVersion preview を入れればもう動くらしい" /></p>
<p>(このスクショは Visual Studio 17.1.0 Preview 1.1 で撮影。)</p>
<p>さよなら、LangVersion default。おかえり、preview (1年ぶり2度目)。</p>
<p>ということで、以下のようなコード、C# 11 候補になっていて、
preview 指定すると現在でもコンパイルできたりします。</p>
<pre class="source" title="C# 11 で有効になりそうなコード">
<code><span class="comment">// C# 11 候補。</span>

<span class="reserved">var</span> <span class="variable">x</span> = 123;

<span class="reserved">var</span> <span class="variable">s1</span> = <span class="string">$&quot;</span><span class="string">こっちは C# 11 から OK </span>{
    <span class="variable">x</span>
    +
    987 <span class="comment">// コメントすら OK</span>
    }<span class="string">&quot;</span>;

<span class="reserved">var</span> <span class="variable">s2</span> = <span class="string">$@&quot;</span><span class="string">こっちは元から OK
</span>{
    <span class="variable">x</span>
    +
    987 <span class="comment">// コメントすら OK</span>
    }<span class="string">
def</span><span class="string">&quot;</span>;
</code></pre>
<p>と言うのを<a href="https://github.com/dotnet/roslyn/pull/58250">昨日の Pull Request</a> を見て初めて気づいたという話でした。</p>
 ]]></description>
				<pubDate>Thu, 16 Dec 2021 21:48:13 +0900</pubDate>
			</item>
			<item>
				<title>ベンゼン環の文字コード: ⌬ (U+232C), ⏣ (U+23E3)</title>
				<link>http://ufcpp.net/blog/2021/12/unicode-benzene/</link>
				<description><![CDATA[ <p><a href="https://twitter.com/hakuikoyori">ベンゼン環が髪についてる子</a>の Twitter 凍結<sup>※</sup>が解けた記念。</p>
<p>というわけではないんですけども、<a href="https://www.youtube.com/channel/UCY-z_9mau6X-Vr4gk2aWtMQ">C# 配信</a>でたびたびネタにしてる Unicode のベンゼン環記号の話。</p>
<p>(<sup>※</sup> 開始10分で Twitter 凍結。ものの数分で数万単位でフォロワーが増えるとか言う不自然な動きが何の不正もなく達成されてしまうのが大手企業勢 VTuber の恐ろしいところ…)</p>
<h2>ベンゼン環文字コード</h2>
<p>なぜか Unicode にはベンゼン環に文字コードが割当たっています。</p>
<ul>
<li>⌬ (U+232C)</li>
<li>⏣ (U+23E3)</li>
</ul>
<p>なぜか。</p>
<p>マジで、「なぜか」。
しかも2文字あります。</p>
<p>うちの配信でなんでよく出てくるかと言うと、2点変な点があるからでして。</p>
<ul>
<li>そもそもなんで Unicode に入ってるのかわからない</li>
<li>2文字ある</li>
</ul>
<h2>文字なの？？</h2>
<p>Unicode にはまあ、変な文字もそこそこたくさんあるんですが。
概ね、変なやつは「出どころが変」。
要するに過去にそういう文字を入れちゃった誰か(Shift_JIS が犯人である率高め)がいて、それとの互換性のために入っています。
分かりやすい例でいうと ♨ (U+2668、温泉マーク)とかですが、これは Shift_JIS の頃からある文字です。</p>
<p>ところが、ベンゼン環の ⌬ が入ったのは Unicode から。
なんなら、Unicode 1.1 からの追加(要するに最初からはいない)です。</p>
<p>本当に変なんですよね、これ。
Unicode に収録されるにあたって1つの基準になるのが、
「現実にある文献(の本文中)で使われている」というのがあります。
要するに電子化以前からあるあらゆる文字を電子的に表したいという目論見。
「本文中」と注釈してるのは、要するに「図表は除く」という意味。</p>
<p>そこで改めて ⌬ という記号について考えてみた時、
「本文中に書く？そりゃ図表として化学式には出てくるけども…」
ということになります。</p>
<p>本当になんで文字コードが割当たってるのかわからない…</p>
<p>Unicode 1.1 の頃のドキュメントってなかなかネットで見つからないので詳しくは僕も知らないんですが、どうも「科学のシンボル的に使うことがある」みたいな感じで入ったみたいです。</p>
<p>使う？図じゃなく文字として？…
絵文字が文字として普及した今となってはこれも文字かも？とは思わなくもないですが、Unicode 1.1 の頃に？
そりゃ ♨ よりはまともかもしれませんけど、わざわざ追加で？</p>
<p>(Unicode で増えた文字を Shift_JIS に逆輸入することがあったりもするんですが、上記のような背景からベンゼン環の ⌬ に関しては<a href="http://hp.vector.co.jp/authors/VA000964/html/benzen.htm">徹底抵抗</a>があったらしく、無事、逆輸入は阻止されたそうです。)</p>
<h2>2文字ある</h2>
<p>さて、ちょこっと化学の話。</p>
<p><a href="https://ja.wikipedia.org/wiki/%E3%83%99%E3%83%B3%E3%82%BC%E3%83%B3">ベンゼン</a>は分子式 C<sub>6</sub>H<sub>6</sub> で、炭素 C が六角形につながった有機化合物です。
この辺りは高校の授業とかでも出てくるので多くの方が知っているかと思います。</p>
<p>で、量子力学が発達して分子中の原子核や電子の配置が具体的に予測できるようになる以前、ベンゼンの C は「1重結合が3個、2重結合が3個で結びついている」と思われていました。それを表したのが ⌬ という記号。</p>
<p>その後、分子中の原子の配置が観測できるようになったり、
量子力学を使って電子軌道を計算できるようになると、
どうもベンゼン中の C は正六角形になっていて、1重・2重の結合の区別はないらしいということがわかってきます。
6個の C の間で6個の電子を共有しているようなモデルの方が正確とされていて、それを表現するのが ⏣ という記号を使うようになった背景。</p>
<p>よく言われるのが、「⌬ という記号は間違った理解を助長してしまうので使うべきではない」という話。
記号通りに ⌬ を解釈するのであれば、<a href="https://ja.wikipedia.org/wiki/1,3,5-%E3%82%B7%E3%82%AF%E3%83%AD%E3%83%98%E3%82%AD%E3%82%B5%E3%83%88%E3%83%AA%E3%82%A8%E3%83%B3">シクロヘキサトリエン</a>というベンゼンとは違う化学物質になるんですが、ベンゼンと比べて著しく不安定なためもし作れたとしてもすぐに壊れると思われます。</p>
<h2>文字追加</h2>
<p>なぜか ⌬ という記号を追加してしまった Unicode ですが、その後当然こんな話が出ます、「⌬ は間違っている。⏣ に変更すべき。」と。</p>
<p>ところが、まあ、簡単に「変更」とはできなかったわけです。
<a href="https://www.unicode.org/wg2/docs/n2874.pdf">Unicode 5.0 の頃の提案</a>によれば、</p>
<ul>
<li>⏣ の方がモダンで、多くの人が ⏣ を使うようになっている</li>
<li>⏣ の方が実際の物理構造をよく表している</li>
<li>⌬ と ⏣ は同じ分子を表しているものの、意図的に使い分けられることがある(上記のシクロヘキサトリエンみたいな)</li>
<li>したがって、<a href="https://ja.wikipedia.org/wiki/%E7%95%B0%E4%BD%93%E5%AD%97%E3%82%BB%E3%83%AC%E3%82%AF%E3%82%BF">バリエーション</a>としてではなく、別の文字とすべき</li>
</ul>
<p>はい。その結果、ベンゼン環が2文字になりました。
ただでさえ使われない文字に文字コード2つ目が発生。</p>
<p>実際どうなんですかね。
少なくとも僕は、僕みたいな人間がネタにするか、批判するか以外の場所でこの文字を見たことがないんですが…</p>
<p>Windows でも Android でも iOS でも IME にこの記号出てきませんし。
ちなみにこのブログはググって出て来た文字をコピペで書いています。
「232c」って打って F5 キーを押すことで変換はできるんですが(Windows 10 以降、文字コードから文字を出せる)、それもしてません。コピペです。</p>
<h2>意匠としてのベンゼン</h2>
<p>ちなみにおまけ。
冒頭で<a href="https://twitter.com/hakuikoyori">博衣こより</a>さんをネタにしてしまった手前。</p>
<p>こよりさんの配信背景中に以下のようなロゴがあったり。</p>
<p><img src="/media/1196/koyologo.png" alt="博衣こより配信背景画像" /></p>
<p>「あー、確かに、意匠としては2重結合の方が可愛いもんなぁ」、
「⏣ だとナットか何かに見えるもんなぁ」という気持ちに。</p>
<p>ちなみにこのロゴ、よく見るとシクロヘキサトリエンとしても2重結合の位置がおかしくて、これだと「1つの C に対して結合の腕が5本ある」ということでちょっとだけネットがざわついたみたいです。</p>
<p>いや、まあ、そこはデザインだから…</p>
 ]]></description>
				<pubDate>Wed, 08 Dec 2021 22:33:20 +0900</pubDate>
			</item>
			<item>
				<title>【C# 10.0 関連】引数なしコンストラクターの Activator バグ</title>
				<link>http://ufcpp.net/blog/2021/12/activator-net48/</link>
				<description><![CDATA[ <p>そういえば<a href="https://github.com/ufcpp-live/UfcppLiveAgenda/issues/43#issuecomment-903272324">ライブ配信(8月)</a>とか Twitter では話しているものの、ちゃんとこのサイト内には書いていなかったなと言う話。</p>
<p>C# 10.0 で<a href="https://ufcpp.net/study/csharp/cheatsheet/ap_ver10/#struct-parameterless-ctor">構造体の引数なしコンストラクター</a>が書けるようになりました。</p>
<pre class="source" title="構造体の引数なしコンストラクター">
<code><span class="reserved">struct</span> <span class="type">A</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> X;
    <span class="reserved">public</span> <span class="type">A</span>() =&gt; X = 1; <span class="comment">// ←要はこういうの</span>
}
</code></pre>
<p><a href="https://ufcpp.net/blog/2021/2/parameterlessstructctor/">今年2月にブログで書いてるんですが</a>、これ、C# 6.0 の時に一度採用しようとしたものの、<a href="https://docs.microsoft.com/ja-jp/dotnet/api/system.activator.createinstance"><code>Activator.CreateInstance</code></a> にバグがあって、いくつかの場面でまっとうに動かないということで延期されたという経緯があります。</p>
<p>で、それは直したし、直っていない頃の古いランタイムはサポート外にしていいだろうということで、晴れて C# 10.0 で採用されました。</p>
<p>ところが、「バグを直したと思ったら別のバグが残ってるランタイムが現存している」と言うことが後から発覚…
実は、 .NET Framework で実行すると引数なしコンストラクターがちゃんと動かいことがあったりします。</p>
<h2>旧バグ</h2>
<p>C# の構造体は <code>new T()</code> と <code>default(T)</code> が同じ「0初期化」を表してた時期が長かったので、<code>Activator.CreateInstance</code> がコンストラクターを呼んでくれず、単に0初期化した値(要するに <code>default(T)</code>)を返してくるというものでした。</p>
<p><code>Activator.CreateInstance</code> を直接呼ぶことはまああんまりないでしょうが、ジェネリック型の <code>new()</code> 制約は内部的に <code>Activator.CreateInstance</code> を使っていて、間接的に影響を受ける人は結構多いと思います。</p>
<p>例えば、先ほどの、引数なしコンストラクターで <code>X</code> を 1 に初期化しているはずの構造体 <code>A</code> を使って以下のようなコードを書いたとします。</p>
<pre class="source" title="引数なしコンストラクターが呼ばれなかったコードの例">
<code><span class="reserved">var</span> <span class="variable">a</span> = <span class="method">New</span>&lt;<span class="type">A</span>&gt;();

<span class="comment">// 古いランタイムだとこれで a.X == 0 に</span>
<span class="comment">// 1 になるはずなのに…</span>
<span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="variable">a</span>.X);

<span class="reserved">static</span> <span class="type">T</span> <span class="method">New</span>&lt;<span class="type">T</span>&gt;()
    <span class="reserved">where</span> <span class="type">T</span> : <span class="reserved">new</span>()
    =&gt; <span class="reserved">new</span> <span class="type">T</span>();
</code></pre>
<p>直接 <code>new A()</code> すればちゃんと <code>X</code> が 1 に初期化されるんですが、
<code>New&lt;T&gt;</code> メソッドを介すると 0 になっていました。</p>
<p>C# 6.0 当時の話なので確か、
「.NET Framework 4.5 で問題が発覚して、4.6 では直した(つもり)」
とかだったと思います。
当時のポリシーだと古いランタイムのサポートを切れないのでお蔵入り。</p>
<h2>現バグ</h2>
<p>直した<strong>つもり</strong>。</p>
<p>実際、.NET Core では(.NET 5, .NET 6 も)ちゃんと直っています。
問題は .NET Framework の方でして、現行の最新版である .NET Framework 4.8 で別のバグり方をしています。</p>
<p><code>CreateInstance</code> を呼ぶのが1回目なら正しく引数なしコンストラクターが呼ばれるんですが、
2回目以降は <code>default(T)</code> を返してしまうという内容。</p>
<p>察しは付くと思いますが、キャッシュ関連のバグです。
何らかのキャッシュを持たせて <code>CreateInstance</code> を高速化する最適化は後から追加されたものなので、「1回直したはずのものが再発」という状態です。</p>
<p>先ほどと同じ構造体 <code>A</code> と <code>New&lt;T&gt;</code> メソッドを使った場合、
.NET Framework 4.8 で実行すると「2度目がおかしい」という状態になります。</p>
<pre class="source" title=".NET Framework 限定 Activator バグ">
<code><span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="method">New</span>&lt;<span class="type">A</span>&gt;().X); <span class="comment">// 1回目は大丈夫。ちゃんと 1。</span>
<span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="method">New</span>&lt;<span class="type">A</span>&gt;().X); <span class="comment">// 2回目以降なぜか 0 に… (.NET Framework 限定のバグ)</span>
</code></pre>
<h2>TargetFramework net4.8 じゃなくてもバグる</h2>
<p>これ、コンパイル時(C# コンパイラー側)の問題ではなくて、
実行時(.NET Framework ランタイム側)の問題なので、
例えばの話、</p>
<ol>
<li>netstandard2.0 なライブラリで以下のようなコードを書く (LangVersion 指定で明示的に C# のバージョンを 10.0 に上げる)</li>
</ol>
<pre class="source" title="netstandard2.0 で C# 10.0 を有効化して書く">
<code><span class="reserved">namespace</span> ClassLibrary1;

<span class="reserved">public struct</span> <span class="type">A</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> X;
    <span class="reserved">public</span> <span class="type">A</span>() =&gt; X = 1;
}
</code></pre>
<ol>
<li>以下のようなアプリ コードを書く (これは C# 7.3 でも動く)</li>
</ol>
<pre class="source" title="アプリ コード">
<code><span class="reserved">using</span> System;

<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> <span class="method">Main</span>()
    {
        <span class="comment">// ジェネリックな new() は、内部的には CreateInstance&lt;T&gt;() と一緒</span>
        <span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="method">New</span>&lt;ClassLibrary1.<span class="type">A</span>&gt;().X);
        <span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="method">New</span>&lt;ClassLibrary1.<span class="type">A</span>&gt;().X);
        <span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="method">New</span>&lt;ClassLibrary1.<span class="type">A</span>&gt;().X);
        <span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="method">New</span>&lt;ClassLibrary1.<span class="type">A</span>&gt;().X);
    }

    <span class="reserved">static</span> <span class="type">T</span> <span class="method">New</span>&lt;<span class="type">T</span>&gt;()
        <span class="reserved">where</span> <span class="type">T</span> : <span class="reserved">new</span>()
        =&gt; <span class="reserved">new</span> <span class="type">T</span>();
}</code></pre>
<p>とやると、アプリ側、 netcoreapp1.0 とか net5.0 とかで動かす分には問題なく 1, 1, 1, 1 という結果になるんですが、
これを .NET Framework 4.8 で実行すると、1, 0, 0, 0 という結果になります。</p>
<h2>影響範囲</h2>
<p>現在の C# は「<a href="https://ufcpp.net/study/csharp/cheatsheet/langversionoption/#new-options">TargetFramework に応じて言語バージョンを自動選択</a>」という方針になっていて、
「古いランタイムで最新の C# 構文を使う」というのは「わかってる人だけがやってくれ」と言うことになっています。</p>
<p>通常 .NET Framework 4.8 で使える C# は C# 7.3 で、
C# 10.0 の新機能が正しく動かなくても概ね問題は起こさないはず…</p>
<p>なんですが、そこで問題になるのが、
先ほどの「ライブラリ側で C# 10.0 にして引数なしコンストラクターを使っている」という場合。</p>
<ol>
<li>ライブラリ側が netstandard2.0 で、引数なしコンストラクターを使っている</li>
<li>アプリ側が net48 で、<code>new()</code> 制約越しにジェネリックなメソッドで <code>new T()</code> している</li>
<li>それを Windows 上で .NET Framework 4.8 で実行する</li>
</ol>
<p>みたいな状況で問題を起こします。</p>
<p>レアな条件ではあるんですが、
「わかっている人が書いたライブラリを、わかっていない人が参照する」というものなので、
「ありえなくもない」くらいには警戒が必要です。</p>
<h3>おまけ: Unity</h3>
<p>ちなみに、TargetFramework が net48 であっても、
<a href="https://unity.com/ja">Unity</a> (<a href="https://ja.wikipedia.org/wiki/Mono_(%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2)">Mono</a>)で実行する分には問題を起こしません。
あくまでランタイムが .NET Framework の時にだけ起こります。</p>
 ]]></description>
				<pubDate>Tue, 07 Dec 2021 22:01:23 +0900</pubDate>
			</item>
			<item>
				<title>Regional Indicator (国旗絵文字)</title>
				<link>http://ufcpp.net/blog/2021/12/regional-indicator/</link>
				<description><![CDATA[ <p>今日は<a href="https://youtu.be/7-E3GYiQU9o?t=2546">10/31 にやった配信で出てた国旗絵文字の話とか</a>。</p>
<p>絵文字を検索したら別の絵文字が引っかかるというのの原理的な話になります。</p>
<p><img src="/media/1195/findcharacter.png" alt="絵文字を検索したら別の絵文字が引っかかる" /></p>
<h2>元ネタ</h2>
<p>まず配信中になんで国旗の話が出たか(「先日、国旗絵文字をどうデコードするか問題を見たなぁ」というのの元ネタ)の紹介。</p>
<p>この配信の数日前に、こんなネタがバズっておりまして。</p>
<ul>
<li><a href="https://twitter.com/hsjoihs/status/1453681402130534400">EUC-JP では『海』 (b3 a4) を検索した際に『ここ』(a4 b3 a4 b3) にマッチしてしまう</a></li>
<li><a href="https://twitter.com/mandel59/status/1453685117650563072">UTF-8は自己同期になるように考えられているし、UTF-16だってサロゲートペアもハイサロゲートとローサロゲートを分けているのに、国旗絵文字は教訓を生かしておらず</a></li>
</ul>
<p>ここから派生して、国旗絵文字の仕様がいかにひどいかという話に…</p>
<h2>UTF-8 の勝利</h2>
<p>UTF-8 「多バイト文字の1バイト目」と「多バイト文字の2バイト目以降」が被らないように作ってあります。
その結果、任意のバイト列の任意の区間を切り出したとしても、以下の3つのうちのいずれかであることが確実に判定できます。</p>
<ul>
<li>前後に何がつながろうと関係なく、一意にデコードできる</li>
<li>前後数バイトを読まないと正しくデコードできないことがわかる</li>
<li>前後に何がつながろうと関係なく、不正な(デコードできない)バイト列だとわかる</li>
</ul>
<p>上記の「『ここ』の中に『海』が見つかる」みたいな、「一部区間を切り取ると別の文字に見える」みたいな問題を絶対に起こしません。
(ただしこれは符号点レベルでの話。「国旗絵文字問題」みたいな、書記素って単位で区切る必要があるものに関しては UTF-8 でも今だ問題あり。後述。)</p>
<h2>UTF-16</h2>
<p>UTF-16 も「2バイトずつ区切る」という前提を持つ限りには同様に、「一部区間を切り取ると別の文字に見える」みたいな問題を絶対に起こしません。</p>
<p>UTF-16 には4バイト使って表現する文字があるんですが、
それも<a href="http://www.asahi-net.or.jp/~ax2s-kmtn/ref/unicode/surrogate.html">ハイ サロゲート(上位2バイト)とロー サロゲート(下位2バイト)</a>と呼ばれる文字コードが完全に分かれていて、順序が違ったり、ペアになってない文字は「不正な UTF-16 データ列である」という判定ができます。一部区間を切り取ったとしても別の文字と誤認識することはありません。</p>
<p>ただし、これはあくまで「2バイトずつ区切る」という前提の話で、
「1バイト削る」とかやってしまうと誤判定します。
そういう意味では UTF-16 は Shift_JIS とか EUC-JP とかの時代からそんなに変わっていないです。
(この辺りも UTF-8 が主流になった理由の1つ。)</p>
<p>分かりやすいのは以下のような文字列。この例だと ‰ (パーミル記号)が〠 (顔郵便マーク)に化けています。</p>
<pre class="source" title="UTF-16 から1バイト削るとかやっちゃダメ">
<code><span class="reserved">using</span> System.Text;

<span class="comment">// UTF-16 (Little Endian) だと…</span>
<span class="reserved">var</span> <span class="variable">s1</span> = <span class="string">&quot;‰‰&quot;</span>; <span class="comment">// 30 20 30 20</span>
<span class="reserved">var</span> <span class="variable">b</span> = <span class="type">Encoding</span>.Unicode.<span class="method">GetBytes</span>(<span class="variable">s1</span>);
<span class="reserved">var</span> <span class="variable">s2</span> = <span class="type">Encoding</span>.Unicode.<span class="method">GetString</span>(<span class="variable">b</span>[1..^1]); <span class="comment">// 20 30</span>
<span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="variable">s2</span>); <span class="comment">// 〠 (U+3020)</span>
</code></pre>
<p>他にも、2バイト目に ASCII 文字を含む文字なんかも地雷です。
2バイト目(UTF-16 Little Endian だとすると上位バイト)が 5C (ASCII だと \ 記号)の文字とかはなかなかやばい地雷を踏めます。
C 言語みたいに \ 記号に特別な意味がある言語がありますんで。</p>
<p>割と使いそうな文字だと 尺、尼、尾、局、居、届 とかですかね。
例えば「局」は U+5C40 なんですが、これを UTF-16 LE で保存してから ASCII とか UTF-8 で読み込みなおすと @\ になります。</p>
<p>C 言語だと、行末に \ を置くと「改行コードを無視して次の行とつなぐ」みたいに意味になるので、 <code>//局</code> みたいなコメントを書いて、UTF-16 で保存して、文字コード指定なし(今時だいたいのコンパイラーで UTF-8 扱い)でコンパイルするとコメントの後ろの行が消えます。</p>
<pre class="source" title="UTF-16 から1バイト削るとかやっちゃダメ">
<code><span class="reserved">#include</span> <span class="string">&lt;stdio.h&gt;</span>

<span class="reserved">void</span> <span class="method">main</span>()
{<span class="comment">//局
    printf("Hello World"); // なぜか表示されない</span>
}
</code></pre>
<h2>UTF-8 の逆転敗北(主に絵文字のせい)</h2>
<p>「コンピューター内部における<a href="https://www.buildinsider.net/language/csharpunicode/01">文字ってなんだ</a>」という話になってくるんですが、結局、Unicode には「複数の文字を組み合わせて1文字を表現する」みたいな仕様があったりします。</p>
<p>前述の「符号点レベルでは大丈夫だけど、書記素のレベルではダメ」という話なんですが、</p>
<ul>
<li>符号点 (code point): 32ビット数値を振られている文字</li>
<li>書記素 (grapheme): レンダリング上1文字に見える単位。複数の符号点から成り立つことがある</li>
</ul>
<p>みたいなのがあります。</p>
<p>例えば以下のような「文字」(書記素)。</p>
<ul>
<li>
人 + 職業
<ul>
<li>👩‍💻: 👩 (U+1F469), U+200D, 💻 (U+1F4BB)</li>
<li>👩‍⚕️: 👩 (U+1F469), U+200D, ⚕ (U+2695), U+FE0F</li>
<li>👩‍🎓: 👩 (U+1F469), U+200D, 🎓 (U+1F393)</li>
<li>👩‍🏫: 👩 (U+1F469), U+200D, 🏫 (U+1F3EB)</li>
</ul>
</li>
<li>
職業 + 性別
<ul>
<li>👮‍♀️: 👮 (U+1F46E), U+200D, ♀ (U+2640), U+FE0F</li>
<li>🕵️‍♀️: 🕵 (U+1F575), U+FE0F, U+200D, ♀ (U+2640), U+FE0F</li>
<li>💂‍♀️: 💂 (U+1F482), U+200D, ♀ (U+2640), U+FE0F</li>
<li>👷‍♀️: 👷 (U+1F477), U+200D, ♀ (U+2640), U+FE0F</li>
</ul>
</li>
</ul>
<p>まあ、理由は分かりますよね… この例の場合はジェンダー問題。
この他に、肌の色とか髪の色とかのバリエーションもあります。</p>
<p>「亜種のために符号点は増やさない」というのが現在の絵文字の方針っぽい雰囲気でして、
最近(Unicode 13.0)だと「色違いの動物」絵文字とかも「符号点を複数組み合わせた書記素」として追加されました。
(Unicode 13.0 (2020年リリース)は Windows 10 だと表示できないので注意。Android, iOS, Windows 11 では表示できます。)</p>
<ul>
<li>
色違い亜種の動物
<ul>
<li>🐈‍⬛: 🐈 (U+1F408), U+200D, ⬛ (U+2B1B) の3符号点</li>
<li>🐻‍❄️: 🐻 (U+1F43B), U+200D, ❄ (U+2744),️ U+FE0F の4符号点</li>
</ul>
</li>
</ul>
<p>で、「文字の中に別の文字が現れる」問題が再発します。</p>
<p>それで冒頭のスクショになります。再掲:</p>
<p><img src="/media/1195/findcharacter.png" alt="絵文字を検索したら別の絵文字が引っかかる" /></p>
<p>👩‍💻👩‍⚕️👩‍🎓👩‍🏫👩‍⚖️👩‍🌾👩‍🍳👩‍🔧 という絵文字列の中に 👩 という別の絵文字が見つかってしまいます。</p>
<p>(ほんとはそれは「正しく書記素を扱えていない」ということになるのでエディターの不具合なんですが。
後述しますが、書記素単位で検索するというのが必ずしもいいことではないのでなんとも。)</p>
<h2>書記素分割の仕様</h2>
<p>符号点は単純に UTF-8 とか UTF-16 をデコードしたら得られる32ビット数値なので非常にわかりやすいんですが。
書記素の方はどうなっているかと言うと、結構複雑な仕様があります。</p>
<ul>
<li><a href="https://unicode.org/reports/tr29/">UAX29 Unicode Text Segmentation</a></li>
</ul>
<p>この仕様の中に「ここで文字を区切ってはいけない」とか「ここで文字を区切る」みたいなルールが書かれています。
このうち、絵文字の分割は「<a href="https://unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries">3 Grapheme Cluster Boundaries</a>」(書記素クラスターの境界)の仕様に従います。</p>
<p>この「区切ってはいけない」のルールに従うのではあれば、
「👩‍💻 の中に 👩 を見つけてしまう」みたいなことも避けられます。
U+200D (Zero Width Joiner、2つの符号点をくっつけるための文字)の前後は区切ってはいけないというルールがあるので、👩‍💻 (U+1F469, U+200D, U+1F4BB) を 👩 (U+1F469)と 💻 (U+1F4BB)に分けてはいけないということになります。</p>
<h2>改行も書記素</h2>
<p>ちなみにまあ、絵文字以外にも書記素になるものはあって、
日本人でも注意が必要なものとしては「CR と LF の間は区切ってはいけない」(<a href="https://unicode.org/reports/tr29/#GB3">GB3</a>)というルールがあります。</p>
<p>歴史的背景から、Windows での改行コードは CR LF (U+000D, U+000A)で、
Unix 系 OS の改行コードは LF (U+000A) なわけですが。
これを横着して、「LF で検索すれば CR LF でも LF でも引っかかるはず」と思っていると事故る(CR LF にマッチしない)可能性があるということです。
書記素として見るなら CR LF と LF は別の文字ということになります。</p>
<p>「まあ普通『書記素として検索』とかしませんよね！」
とか思っていたら、C# でも1回事故ってるんですよね。</p>
<ul>
<li><a href="https://github.com/dotnet/runtime/issues/43736">Breaking change with string.IndexOf(string) from .NET Core 3.0 -&gt; .NET 5.0
</a></li>
</ul>
<p>.NET Core 3.0 から .NET 5.0 にアップグレードしたら <code>IndexOf</code> と <code>Contains</code> で改行文字の扱いが変わってしまったという。
(ちなみにこれ、<a href="https://ufcpp.net/blog/2021/8/invariantculture/">カルチャー依存問題</a>です。
さらに言うと結局、.NET 6.0 で改行の扱いが .NET Core 3.0 と同じに戻ったみたいです。)</p>
<h2>国旗 (Regional Indicator)</h2>
<p>で、そんな元からつらい絵文字の中でも、国旗絵文字の仕様は特にひどいんですよね…</p>
<p>「国コードに相当する2文字を並べて国旗を表現」とかやります。
このために使う文字を <a href="https://en.wikipedia.org/wiki/Regional_indicator_symbol">Regional Indicator</a> といって、U+1F1E6～1F1FF の範囲に並んでいます。</p>
<p>そりゃね… <a href="https://emojipedia.org/flag-south-korea/">KR</a> (韓国)と <a href="https://emojipedia.org/flag-united-states/">US</a> (アメリカ)を並べたら <a href="https://emojipedia.org/flag-russia/">RU</a> (ロシア)が出てきますとも…</p>
<p>UAX29 の分割アルゴリズム的にはどう対処しているかと言うと…</p>
<p><strong><a href="https://unicode.org/reports/tr29/#GB12">奇数個の Region Indicator では区切るな。</a></strong></p>
<p>はい。個数依存です。
先ほどの 👩‍💻 なら U+200D の周りだけ見れば判定可能なんですが。
Regional Indicator の場合は国旗が連続しているとき、端っこまでさかのぼった上で、通算の個数を数えないと判定できません。</p>
<p>AZ (アゼルバイジャン)と ZA (南アフリカ)みたいな国コードもあるので、同じ国の国旗を大量に並べるだけで、2国のうちどちらなのか判定するのが急に大変になります。</p>
<p>(極端な話、1,000個くらい同じ国旗を並べたら、8,000バイトくらいさかのぼらないと AZ なのか ZA なのかが確定しない場合があります。
完全に冒頭の「EUC-JP における『こ』と『海』」と同じ問題を踏んでいて、
「国旗絵文字は教訓を生かしていない」と言われても仕方がない状態。)</p>
<p>「さかのぼる」とか「繰り返す」みたいな処理は他の書記素分割アルゴリズムでも出てくるんですが、「個数を数える」は本当に Region Indicator だけ。</p>
<h2>国旗 (Tag Sequence)</h2>
<p>「国」(country)というと角が立つんで本当は「地域」(territory)とすべきなんですが、
まあ国旗(地域の旗)絵文字はその後、3つほど追加されています。
<a href="https://emojipedia.org/flag-england/">England</a>、
<a href="https://emojipedia.org/flag-scotland/">Scotland</a>、
<a href="https://emojipedia.org/flag-wales/">Wales</a>。
(要するに、連合王国内の country を「国」と訳してしまうと国旗になってしまう3地域。)</p>
<p>さすがに Regional Indicator のクソ仕様は反省しているみたいで、新しい旗は別の構成方法を取っています。</p>
<p>例えば England 旗は U+1F3F4, U+E0067, U+E0062, U+E0065, U+E006E, U+E0067, U+E007F という並びになっていて、</p>
<ul>
<li>U+1F3F4: 元々ある「黒い旗」絵文字🏴。</li>
<li>U+E0000～E007F: 0～7F の ASCII 文字に対応する「タグ文字」と呼ばれる文字</li>
<li>地域の旗は「黒い旗」から始めて、地域コード(gbeng, gbsct, gbwls)に相当するタグ文字を並べ、最後にエスケープ タグ(U+E007F)で閉じる</li>
</ul>
<p>という仕様。</p>
<p>開始文字と終端文字が決まっているので、Region Indicator 時代にあったみたいな「連続していると最初まで延々とさかのぼらないと確定しない」問題はなくなっています。</p>
<p>(他に、原理的には、2文字の制限がなくなったのでかなり細かい単位の地域の旗であっても対応できるとか、開始文字を変えることで旗以外の地域に関連した何かを表現するとかできるので、将来の拡張性も非常に高いです。
この仕様に対応していない文字レンダリング環境では単に黒旗🏴が表示されますし、その意味でも親切設計。)</p>
<p>こういう仕様を Tag Sequence って言うみたいです。
無茶苦茶変な仕様ですし、1文字辺りのバイト数もすごいこと(上記の3つの旗はいずれも UTF-8 で28バイト)になるんですが、まあ Region Indicator の反省を踏まえた結果こうなっています。</p>
 ]]></description>
				<pubDate>Sat, 04 Dec 2021 22:07:28 +0900</pubDate>
			</item>
			<item>
				<title>Unicode 演算子 (∑Σ とか ∫ʃ とか)</title>
				<link>http://ufcpp.net/blog/2021/11/unicode-operator/</link>
				<description><![CDATA[ <p>C# ライブ配信をしていて、「<a href="https://youtu.be/7-E3GYiQU9o?t=6523">括弧用の記号の種類が少なすぎる</a>」みたいな話題から、
「あるよ、括弧。Unicode には」みたいな話になり、
「Swift ではマジでいろんな記号が使える」という話に脱線したときの話。</p>
<p>配信では「括弧がたくさんある」という話と「Swift では演算子にいろんな文字が使える」という話が混ざっていて、
実際に Swift で色々使えるのは括弧ではないんですけど、演算子の方は本当に Swift で使えるものがかなり自由が効く仕様になっていまして。
例えば以下のコードはコンパイルして実行できます。
(1から5の和で、15が出力されます。)</p>
<pre class="source" title="Swift の Unicode 演算子">
<code><span class="reserved">prefix operator</span> <span class="method">∑</span>

<span class="reserved">prefix func</span> <span class="method">∑</span> (<span class="variable">x</span>: [<span class="type">Int</span>]) -> <span class="type">Int</span> {
  <span class="reserved">var</span> <span class="variable">sum</span> = 0
  <span class="reserved">for</span> <span class="variable">i</span> <span class="reserved">in</span> <span class="variable">x</span> {
    <span class="variable">sum</span> += <span class="variable">i</span>
  }
  <span class="reserved">return</span> <span class="variable">sum</span>
}

<span class="reserved">let</span> <span class="variable">Σ</span> = [ 1, 2, 3, 4, 5 ]

<span class="method">print</span>(<span class="method">∑</span><span class="variable">Σ</span>)
</code></pre>
<p><code>∑Σ</code>。</p>
<p>シグマシグマ。</p>
<p>ちなみにこれ、同じ記号に見えて実は違う文字でして。</p>
<ul>
<li>(1個目の)∑ : U+2211。数学記号の「和」の意味のシグマ。</li>
<li>(2個目の)Σ : U+03A3。ギリシャ文字大文字のシグマ。</li>
</ul>
<p>Swift は、</p>
<ul>
<li>変数名に使える文字も<a href="https://github.com/apple/swift/blob/08e7963/include/swift/AST/Identifier.h#L87-L121">演算子に使える文字</a>も許可リスト方式</li>
<li><a href="https://en.wikipedia.org/wiki/Greek_and_Coptic">ギリシャ文字</a>の letter は変数名に使える</li>
<li><a href="https://en.wikipedia.org/wiki/Mathematical_operators_and_symbols_in_Unicode">数学記号</a>は演算子に使える</li>
</ul>
<p>という仕様になっているので、上記のようなコードが合法になります。</p>
<h2>シグマとシグマ</h2>
<p>まあ、「なんで文字コード分けた」という話ではあります。
Unicode、同じような意味、読み、形の文字は統合する方針じゃないの？
シグマとシグマを分けるんだったら、日中韓漢字統合(いわゆる<a href="https://www.itmedia.co.jp/news/articles/2110/29/news136.html">中華フォント問題</a>)とかやめてよ…</p>
<p>そしてまあ、同じようなことができる組み合わせは他にもいろいろとあります。
ぱっと思いつくのは以下のようなもの。</p>
<p>パイ:</p>
<ul>
<li>∏ : U+220F。数学記号の「積」の意味のパイ。</li>
<li>Π : U+03A0。ギリシャ文字大文字のパイ。</li>
</ul>
<p>long S:</p>
<ul>
<li>∫ : U+222B。積分記号。積分記号自体が「S を引き延ばしたもの」が由来。</li>
<li>
ʃ : U+0283。発音記号の &quot;esh&quot;。S 亜種の発音。
<ul>
<li>letter 扱いらしく、変数名に使える。</li>
</ul>
</li>
</ul>
<p>Union:</p>
<ul>
<li>∪: U+222A。Union (和集合)の数学記号。</li>
<li>U: U+0055。ローマ字の(ASCII コード中にある) U の大文字。</li>
</ul>
<p>c の丸囲み: </p>
<ul>
<li>© : U+00A9。コピーライト記号。演算子にできるらしい…</li>
<li>
c⃝: U+0063 U+20DD。c に combining enclosing circle を付けて丸囲み。
<ul>
<li>サポートしているフォントは少ないものの、ものによっては © と似たような描画をされるはず。</li>
<li>letter + diacritical mark なので変数名に使える。</li>
</ul>
</li>
</ul>
<p>他に ℵ(U+2135。ヘブライ文字を元にした数学記号のアレフ)と א (U+05D0。元々のヘブライ文字のアレフ)とかも思いついたんですけど、これは両方後も letter (変数名に使えて、演算子には使えない文字)でした。
ちなみにこのアレフに至っては、数学記号の方は L to R (左書き)、ヘブライ文字の方は R to L (右書き)の文字で、後ろに続く文字のレンダリングに影響を及ぼしたりします。</p>
 ]]></description>
				<pubDate>Sun, 28 Nov 2021 14:10:33 +0900</pubDate>
			</item>
			<item>
				<title>【C# 10.0】 トップ レベル ステートメントの変更点</title>
				<link>http://ufcpp.net/blog/2021/11/top-level-csharp10/</link>
				<description><![CDATA[ <p>そういえば、文法的な変更ではないのでどこにも告知は出ていないもの(サイレント修正)なんですが、<a href="/study/csharp/cheatsheet/ap_ver9/#top-level-statements">トップ レベル ステートメント</a> (C# 9.0 で追加)に変更点が2つあります。</p>
<h2>空ステートメント禁止</h2>
<p>以下の2つのコードを見比べてください。</p>
<p>1つ目:</p>
<pre class="source" title="Hello World">
<code><span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> <span class="method">Main</span>() =&gt; <span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="string">&quot;Hello World!&quot;</span>);
}
</code></pre>
<p>2つ目:</p>
<pre class="source" title=";">
<code>;
<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> <span class="method">Main</span>() =&gt; <span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="string">&quot;Hello World!&quot;</span>);
}
</code></pre>
<p>C# 9.0 当初、2つ目のコードもコンパイルできていました。
そして、実行結果がどうなるかと言うと…</p>
<ul>
<li>1つ目: <code>Program.Main</code> が呼ばれて、Hello World! が表示される</li>
<li>2つ目: トップ レベル ステートメント扱いされて、何も表示されない</li>
</ul>
<p>さすがに <code>;</code> 1個で挙動が変わっちゃうのはためらわれるというか、
<a href="https://github.com/dotnet/roslyn/issues/53472">「2つ目で何も表示されなくなるのはバグだ」と認識しちゃう人もいた</a>ので<a href="https://github.com/dotnet/roslyn/pull/54385">修正がかかりました</a>…</p>
<p>今は、2つ目のコードはコンパイル エラーになります。
空ステートメント1個だけのトップ レベル ステートメントは禁止。</p>
<p>でも、以下のようなコードは今 (C# 10.0) でも認められてるんですよね…</p>
<p>空じゃないステートメントもある:</p>
<pre class="source" title="1つでも空じゃないものがあればOK">
<code>;
<span class="type">Console</span>.<span class="method">WriteLine</span>();
</code></pre>
<p>空ブロック:</p>
<pre class="source" title="; はダメでも {} は OK">
<code>{}
</code></pre>
<p><code>;</code> だけのものが禁止された経緯を考えると、<code>{}</code> だけのものも禁止されてもおかしくはないんですけど。
「<code>Main</code> を呼ぶかトップ レベル ステートメントを呼ぶか」の分岐条件が緩すぎるんですよね。
今後どうなるか…</p>
<h2>トップ レベル ステートメントを使った時のクラス名</h2>
<p>トップ レベル ステートメントを使った時、例えば以下のようなコードを書くと、</p>
<pre class="source" title="トップ レベル ステートメント利用例">
<code><span class="type">Console</span>.<span class="method">WriteLine</span>();
</code></pre>
<p>扱いとしては以下のようなコードに展開されていました。</p>
<pre class="source" title="C# 9.0 時点でのトップ レベル ステートメントの展開結果">
<code><span class="reserved">using</span> System;

<span class="reserved">internal</span> <span class="reserved">class</span> <span class="type">&lt;Program&gt;$</span>
{
    <span class="reserved">private</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="method">&lt;Main&gt;$</span>(<span class="reserved">string</span>[] <span class="variable">args</span>)
    {
        <span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="string">&quot;Hello World!&quot;</span>);
    }
}
</code></pre>
<p>クラス名、メソッド名がどうなるかは仕様には明記されておらず、実装依存(変更が掛かっても文句は言えない)です。
とりあえず、「通常の C# では書けない名前」(unspeakable name というそうです)になっていました。
実装依存ですが、現在の実装では <code>&lt;Program&gt;$</code> みたいに <code>&lt;&gt;$</code> を入れて unspeakable にしています。</p>
<p>ところが、クラス名が unspeakable だと、<a href="https://github.com/dotnet/roslyn/issues/54877">ASP.NET の単体テストで困ったそう</a>です。
ということで、<a href="https://github.com/dotnet/roslyn/pull/55368">クラス名だけは speakable な <code>Program</code> に変更</a>。
C# 10.0 では上記のコードは以下のような展開結果に変更されています。</p>
<pre class="source" title="C# 10.0 時点でのトップ レベル ステートメントの展開結果">
<code><span class="reserved">using</span> System;

<span class="reserved">internal</span> <span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">private</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="method">&lt;Main&gt;$</span>(<span class="reserved">string</span>[] <span class="variable">args</span>)
    {
        <span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="string">&quot;Hello World!&quot;</span>);
    }
}
</code></pre>
<p>トップ レベル ステートメントだけを使っている分には特に影響のない修正のはずなんですが…
例えば以下のようなコードがコンパイル エラーを起こすようになります。</p>
<pre class="source" title="C# 10.0 ではエラーになるコード">
<code><span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="string">&quot;Hello World!&quot;</span>);

<span class="reserved">internal</span> <span class="reserved">class</span> <span class="error"><span class="type">Program</span></span>
{
}
</code></pre>
<p>コンパイラーが生成する <code>Program</code> クラスと、コード中に手書きした <code>Program</code> クラスが衝突しています。</p>
<p>一方で、現状のこの実装を逆手に取ると、以下のようなコードはコンパイルできるようになります。</p>
<pre class="source" title="現状の実装を逆手に取ったコード">
<code><span class="method">A</span>(); <span class="comment">// Program.A が呼ばれる。</span>

<span class="reserved">partial</span> <span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="method">A</span>() =&gt; <span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="string">&quot;Hello World!&quot;</span>);
}
</code></pre>
<p>ただ、<code>Program</code> というクラス名が仕様書上に明記されているわけではないので、将来もこのコードが有効であるという保証はあんまりできません。その点はご注意ください。</p>
 ]]></description>
				<pubDate>Tue, 23 Nov 2021 15:15:33 +0900</pubDate>
			</item>
			<item>
				<title>【C# 10.0】 AppendLiteral(&quot; &quot;)</title>
				<link>http://ufcpp.net/blog/2021/11/appendliteral/</link>
				<description><![CDATA[ <p>C# 10.0 で、<a href="/study/csharp/cheatsheet/ap_ver10/#improved-string-interpolation">文字列補間に対するパフォーマンス改善</a>が入りました。
例えば、以下のようなコードがあったとして、</p>
<pre class="source" title="文字列補間の例">
<code><span class="reserved">static</span> <span class="reserved">string</span> <span class="method">A</span>(<span class="reserved">int</span> <span class="variable">x</span>, <span class="reserved">int</span> <span class="variable">y</span>) =&gt; <span class="string">$&quot;</span><span class="string">(</span>{<span class="variable">x</span>}<span class="string">, </span>{<span class="variable">y</span>}<span class="string">)</span><span class="string">&quot;</span>;
<span class="reserved">static</span> <span class="reserved">string</span> <span class="method">B</span>(<span class="reserved">int</span> <span class="variable">a</span>, <span class="reserved">int</span> <span class="variable">b</span>, <span class="reserved">int</span> <span class="variable">c</span>) =&gt; <span class="string">$&quot;</span>{<span class="variable">a</span>}<span class="string">.</span>{<span class="variable">b</span>}<span class="string">.</span>{<span class="variable">c</span>}<span class="string">&quot;</span>;
</code></pre>
<p>C# 10.0 では <code>$&quot;&quot;</code> の部分がそれぞれ以下のように展開されます。</p>
<pre class="source" title="文字列補間の C# 10.0 での展開結果">
<code><span class="reserved">using</span> System.Runtime.CompilerServices;

<span class="reserved">static</span> <span class="reserved">string</span> <span class="method">A</span>(<span class="reserved">int</span> <span class="variable">x</span>, <span class="reserved">int</span> <span class="variable">y</span>)
{
    <span class="type">DefaultInterpolatedStringHandler</span> <span class="variable">h</span> = <span class="reserved">new</span>(4, 2);
    <span class="variable">h</span>.<span class="method">AppendLiteral</span>(<span class="string">&quot;(&quot;</span>);
    <span class="variable">h</span>.<span class="method">AppendFormatted</span>(<span class="variable">x</span>);
    <span class="variable">h</span>.<span class="method">AppendLiteral</span>(<span class="string">&quot;, &quot;</span>);
    <span class="variable">h</span>.<span class="method">AppendFormatted</span>(<span class="variable">y</span>);
    <span class="variable">h</span>.<span class="method">AppendLiteral</span>(<span class="string">&quot;)&quot;</span>);
    <span class="control">return</span> <span class="variable">h</span>.<span class="method">ToStringAndClear</span>();
}

<span class="reserved">static</span> <span class="reserved">string</span> <span class="method">B</span>(<span class="reserved">int</span> <span class="variable">a</span>, <span class="reserved">int</span> <span class="variable">b</span>, <span class="reserved">int</span> <span class="variable">c</span>)
{
    <span class="type">DefaultInterpolatedStringHandler</span> <span class="variable">h</span> = <span class="reserved">new</span>(4, 2);
    <span class="variable">h</span>.<span class="method">AppendFormatted</span>(<span class="variable">a</span>);
    <span class="variable">h</span>.<span class="method">AppendLiteral</span>(<span class="string">&quot;.&quot;</span>);
    <span class="variable">h</span>.<span class="method">AppendFormatted</span>(<span class="variable">b</span>);
    <span class="variable">h</span>.<span class="method">AppendLiteral</span>(<span class="string">&quot;.&quot;</span>);
    <span class="variable">h</span>.<span class="method">AppendFormatted</span>(<span class="variable">c</span>);
    <span class="control">return</span> <span class="variable">h</span>.<span class="method">ToStringAndClear</span>();
}
</code></pre>
<p>今日の話はこの <code>AppendLiteral</code> のところの最適化の話。</p>
<h2>インライン展開</h2>
<p>上記の展開結果を最初に見た時の感想は「<code>AppendLiteral(char)</code> はなくていいの？」でした。
C# 的に、文字 (<code>'.'</code>) は単なる数値(2バイトの値型)なのに対して、文字列(<code>&quot;.&quot;</code>) は参照型(ヒープ アロケーションが掛かる)なので、効率が悪いんじゃないかと。</p>
<p>実際、例えば類似のメソッドとして、<code>StringBuilder.Append</code> なんかは「文字列じゃなくて文字のオーバーロードを使え」というコード解析が出てきたりします。</p>
<p><img src="/media/1194/ca1834.png" alt="文字列じゃなくて文字のオーバーロードを使え" /></p>
<p>何も対処しないと確かに問題になるっぽいんですが、これに対して、<code>DefaultInterpolatedStringHandler.AppendLiteral</code> の実装を工夫して、効率を落とさないようにしているそうです。</p>
<p>今現在(2021/11/7)の <code>DefaultInterpolatedStringHandler.AppendLiteral</code> の中身は以下のような感じ。</p>
<p><a href="https://github.com/dotnet/runtime/blob/f54ab52d24ee524a246e463d754e526832850d4a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/DefaultInterpolatedStringHandler.cs#L136">DefaultInterpolatedStringHandler.cs#L136</a></p>
<p>まんまコメントが書かれていますが、</p>
<blockquote>
<p>AppendLiteral is expected to always be called by compiler-generated code with a literal string.
By inlining it, the method body is exposed to the constant length of that literal, allowing the JIT to
prune away the irrelevant cases.  This effectively enables multiple implementations of AppendLiteral,
special-cased on and optimized for the literal's length.  We special-case lengths 1 and 2 because
they're very common, e.g.</p>
<pre><code>1: ' ', '.', '-', '\t', etc.
2: &quot;, &quot;, &quot;0x&quot;, &quot;=&gt;&quot;, &quot;: &quot;, etc.
</code></pre>

<p>but we refrain from adding more because, in the rare case where AppendLiteral is called with a non-literal,
there is a lot of code here to be inlined.</p>
</blockquote>
<p>文字列長が1文字と2文字のときの特殊分岐を書いた上で、
<code>AggressiveInlining</code> を付けています。
要点だけを抜き出すと以下のようなコード。</p>
<pre class="source" title="AppendLiteral 中の特殊分岐">
<code><span class="reserved">using</span> System.Runtime.CompilerServices;

[<span class="type">MethodImpl</span>(<span class="type">MethodImplOptions</span>.AggressiveInlining)]
<span class="reserved">void</span> <span class="method">AppendLiteral</span>(<span class="reserved">string</span> <span class="variable">value</span>)
{
    <span class="control">if</span> (<span class="variable">value</span>.Length == 1)
    {
        <span class="comment">// value[0] しか参照しないコード</span>
        <span class="control">return</span>;
    }

    <span class="control">if</span> (<span class="variable">value</span>.Length == 2)
    {
        <span class="comment">// value[0], value[1] しか参照しないコード</span>
        <span class="control">return</span>;
    }

    <span class="comment">// 汎用ロジック</span>
    <span class="method">AppendStringDirect</span>(<span class="variable">value</span>);
}
</code></pre>
<p><code>AppendLiteral</code> には文字通りリテラルしか渡ってこないという前提ありきですが、
これで1文字の場合と2文字の場合はかなり速くなるとのこと。</p>
<p>JIT 時最適化で、
1文字の文字列リテラルが渡ってきたときには <code>if (value.Length) == 1)</code>、
2文字のが渡ってきたときには <code>if (value.Length) == 2)</code> の中身しか残らないそうです。</p>
 ]]></description>
				<pubDate>Sat, 20 Nov 2021 21:32:05 +0900</pubDate>
			</item>
			<item>
				<title>TargetFramework net5.0 なコードを .NET 6 ランタイムで動かす</title>
				<link>http://ufcpp.net/blog/2021/11/latestmajor/</link>
				<description><![CDATA[ <h2>.NET のアップデート</h2>
<p>昔の C# アプリ (例えば去年作った TargetFramework net5.0 なアプリ)をそのまま最新のランタイム(例えば .NET 6 ランタイム)で動かすことを考えます。</p>
<p>.NET は API レベルでの破壊的変更はめったにないので、
「API が合わなくてロードできない」みたいな根本的な問題はほぼ起こりません。</p>
<p>一方、挙動レベルでは時々破壊的変更があるんで、確実に動く保証はなかったりします。
(それでも、体感、9割方は動きますが。)</p>
<p>ここ数バージョンであった影響がありそうな変更でいうと、</p>
<ul>
<li>
.NET Core 3.0 の頃同期 I/O が例外を出すようになったものがちらほらある
<ul>
<li>ネットワークなどを介する場合、非同期でないとパフォーマンスが出ないので</li>
</ul>
</li>
<li>
.NET 5 で、国際化対応に <a href="https://icu.unicode.org/">ICU</a> を使うようになった
<ul>
<li>文字列の紹介順や、<code>IndexOf</code> の挙動がちょっと変わった</li>
</ul>
</li>
<li>.NET 6 で、<a href="https://docs.microsoft.com/en-us/dotnet/core/compatibility/core-libraries/6.0/filestream-file-locks-unix"><code>FileStream</code></a> とか <a href="https://docs.microsoft.com/en-us/dotnet/core/compatibility/core-libraries/6.0/partial-byte-reads-in-streams"><code>CryptoStream</code></a> の挙動がちょっと変わった</li>
</ul>
<p>とかがあって、時々、最新のランタイム上で動かそうとしてもうまくいかないことがあります。</p>
<h2>アップデート手順</h2>
<p>そういうのは「わかってる人だけやって欲しい」ということらしく、 .NET Core 3.1 以降の .NET は「バイナリは昔のままで最新のランタイム上で動かす」という操作に対してかなり保守的です。</p>
<p>例えば、オプション指定なしだと、.NET 5 向けに作った C# アプリを .NET 6 ランタイム上で動かせません。</p>
<p>手間をかけられるなら、</p>
<ul>
<li>プロジェクトの TargetFramwork を net6.0 に上げる</li>
<li>SDK/ランタイムも .NET 6 に上げる</li>
<li>その状態で単体テストが通るようにコードを書き換える</li>
</ul>
<p>という3つを同時にやってくれと言うことだと思います。
(実際、挙動の破壊的変更がまれにある以上、そうするしかアップデート後の動作保証は取れないはずですが。)</p>
<p>とはいえ、できることからコツコツやっていきたいことだってよくあるわけで、</p>
<ul>
<li>CI 環境の .NET SDK を先にバージョンアップしておく</li>
<li>それに合わせてできるプロジェクトからちょっとずつ TargetFramework を変更していく</li>
</ul>
<p>みたいなことをしたい方も結構多いんじゃないかと思います。</p>
<h2>Roll Forward</h2>
<p>まあ、API レベルでの破壊的変更がほとんどなく、挙動レベルでも9割方は動くものに対して常に最近に追従する作業が必要かという話もあり。
ちゃんと、「古いバイナリを最新のランタイムでそのまま動かす」というオプションがあります。</p>
<p>正確に言うと、「バージョン不一致のどき、どのくらいずれてても OK か」を指定するためのオプションがあって、これを <a href="https://docs.microsoft.com/ja-jp/dotnet/core/whats-new/dotnet-core-3-0#major-version-runtime-roll-forward">roll forward</a> と言います。</p>
<p>デフォルトが Minor で、これがなかなか厳しい…
(メジャー バージョンが一致するものがないと実行できない。)</p>
<p>こうことで、先ほどの「.NET SDK を先にバージョンアップしておく」シナリオをやるなら roll forward 設定の変更が必要になります。
Major か LatestMajor なら動かせるはずですが、
僕みたいな「常に最新の SDK/ランタイムに追従」ポリシーの人はとりあえず LatestMajor で大丈夫です。</p>
<h3>Roll Forward オプションの指定方法</h3>
<p>Roll Forward オプションの指定の仕方はいくつかあるみたいです。
dotnet コマンドに<a href="https://docs.microsoft.com/ja-jp/dotnet/core/tools/dotnet#runtime-options">直接オプションを書く</a>方法もありますし、</p>
<pre class="console">
<code>dotnet run --roll-forward LatestMajor
</code></pre>
<p>(ただ、<code>dotnet run</code> はこのオプションを受け付けるものの、<code>dotnet test</code> は受け付けないらしい？)</p>
<p><a href="https://docs.microsoft.com/ja-jp/dotnet/core/tools/global-json?tabs=netcore3x#rollforward">global.json に書いておく</a>のでもいいそうですし、</p>
<pre class="source">
<code>{
  "sdk": {
    "version": "6.0.100",
    "rollForward": "latestMajor"
  }
}
</code></pre>
<p><a href="https://docs.microsoft.com/ja-jp/dotnet/core/tools/dotnet-environment-variables#dotnet_roll_forward">環境変数で <code>DOTNET_ROLL_FORWARD</code> を設定しておく</a>のでもいいそうです。</p>
<p>今回のシナリオ(CI)だと、たぶん環境変数を設定するのがよくて、
例えば GitHub Actions の build.yml に以下の行を足せばいいということになります。</p>
<pre class="source">
<code>env:
  DOTNET_ROLL_FORWARD: latestMajor
</code></pre>
<h3>実例</h3>
<p>昔、<a href="https://github.com/ufcpp/TryGithubActions">GitHub Actions を試してみるためだけに空っぽのライブラリに空っぽの単体テストを定義したリポジトリ</a>があったので、
それを .NET 5 から .NET 6 にアップデートしてみました。</p>
<p>CI が失敗:</p>
<ul>
<li>
<a href="https://github.com/ufcpp/TryGithubActions/pull/6">TargetFramework だけアップデート</a>
<ul>
<li>The current .NET SDK does not support targeting .NET 6.0.</li>
</ul>
</li>
<li>
<a href="https://github.com/ufcpp/TryGithubActions/pull/5">CI 設定だけアップデート (Roll Forward なし)</a>
<ul>
<li>version '5.0.0' (x64) was not found.</li>
<li>(今回のシナリオだとこれがつらい)</li>
</ul>
</li>
</ul>
<p>CI が成功:</p>
<ul>
<li><a href="https://github.com/ufcpp/TryGithubActions/pull/4">CI 設定と TargetFramework を同時にアップデート</a></li>
<li><a href="https://github.com/ufcpp/TryGithubActions/pull/7">CI 設定だけアップデート (Roll Forward あり)</a></li>
</ul>
 ]]></description>
				<pubDate>Sun, 14 Nov 2021 21:47:39 +0900</pubDate>
			</item>
			<item>
				<title>【C# 10.0】 ImplicitUsings (自動 global using)</title>
				<link>http://ufcpp.net/blog/2021/11/implicitusings/</link>
				<description><![CDATA[ <p>今日は<a href="https://ufcpp.net/blog/2021/11/fix-all-file-scoped-namespace/">先日のファイル スコープ名前空間の話</a>に続いて、
<a href="https://ufcpp.net/study/csharp/cheatsheet/ap_ver10/#global-using">global using</a> に関する話を<a href="https://ufcpp.net/blog/2021/8/newprojecttemplate/">最初にブログに書いたとき</a>にちょこっと「正式リリースまでには変更が掛かる予定」と話していた <code>ImplicitUsings</code> の話をしたいと思います。</p>
<h2>global using</h2>
<p>何回か話してはいるんですが、 .NET 6 SDK から、C# プロジェクトのテンプレートの初期状態が以下のような(コメントを除けば)1行だけのソースコードになっています。</p>
<pre class="source" title="新コンソール アプリ テンプレート">
<code><span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="string">"Hello, World!"</span>);
</code></pre>
<p>C# コンパイラーとしては <a href="https://ufcpp.net/study/csharp/cheatsheet/ap_ver10/#global-using">global using</a> という文法を追加したわけですが、
わざわざ C# の文法として追加した(コンパイル オプションにはしなかった)のは <a href="https://ufcpp.net/study/csharp/misc/analyzer-generator/">Source Generator</a> を使って global using を生成するような手法も取れるようにするためです。</p>
<p>ただし、主な用途は上記のような「テンプレートの初期状態を簡素化する」というもので、
多くの場合「自動的に裏のどこかで global using が追加されている」みたいな使われ方になります。</p>
<h2>global using の自動生成</h2>
<p>で、誰が「自動的に global using を追加」しているかというと、.NET 6 SDK です。
.NET 6 / Visual Studio 2022 で新規プロジェクトを作って、1回 build してみて、
<code>obj/Debug/net6.0</code> フォルダーを覗いてみると以下のようなファイルが <code>ConsoleApp1.GlobalUsings.g.cs</code> みたいな名前で作られています。</p>
<p>(<code>Debug</code> のところは build 設定次第では <code>Release</code> になりますし、
<code>net6.0</code> のところは TargetFramework、
<code>ConsoleApp1</code> のところはプロジェクト名によって変わります。)</p>
<p><img src="/media/1193/globalusings.png" alt="global usings" /></p>
<p>ちなみに、このコードはコンソール アプリの場合の結果で、
プロジェクトのタイプごとに生成される global using 対象の名前空間が変わります。</p>
<p>例えば Windows Forms の場合は <code>System.Drawing</code> と <code>System.Windows.Forms</code> が、
Web アプリの場合は <code>Microsoft.AspNetCore.*</code>、<code>Microsoft.Extensions.*</code>、<code>System.Net.Http.Json</code> などの名前空間も追加されます。
この辺りは Windows Forms や Web を作っているチームごとのポリシーによるみたいです。</p>
<h2>ImplicitUsings</h2>
<p><a href="https://ufcpp.net/blog/2021/8/newprojecttemplate/">.NET 6 Preview 7 の頃に書いたブログ</a>で、初期案としては「TargetFramework が <code>net6.0</code> の時は無条件に global using を自動追加」みたいなことをやろうとしていました。</p>
<p>が、global using は既存コードベースに後から追加するとたまに事故ります。
分かりやすい例でいうと、自前で LINQ っぽい拡張メソッドを定義した場合。
例えば .NET 5 の頃に以下のようなコードを書いていたとして、
これを .NET 6 にアップデートしたら、「<code>Select</code> が <code>System.Linq</code> と <code>MyExtensions</code> の2か所にあって弁別できない」というエラーが起き得ます。
(実際、Preview 7 の頃はエラーになりました。)</p>
<pre class="source" title="自前 LINQ で global using が競合する例">
<code><span class="reserved">using</span> System;
<span class="reserved">using</span> MyExtensions;

<span class="reserved">var</span> <span class="variable">result</span> = <span class="reserved">new</span>[] { 1, 2, 3, 4 }.Select(<span class="variable">x</span> =&gt; <span class="variable">x</span> * <span class="variable">x</span>);

<span class="reserved">namespace</span> MyExtensions
{
    <span class="reserved">static</span> <span class="reserved">class</span> <span class="type">Enumerable</span>
    {
        <span class="reserved">public</span> <span class="reserved">static</span> <span class="type">IEnumerable</span>&lt;<span class="type">T2</span>&gt; <span class="method">Select</span>&lt;<span class="type">T1</span>, <span class="type">T2</span>&gt;(<span class="reserved">this</span> <span class="type">IEnumerable</span>&lt;<span class="type">T1</span>&gt; <span class="variable">array</span>, <span class="type">Func</span>&lt;<span class="type">T1</span>, <span class="type">T2</span>&gt; <span class="variable">selector</span>)
        {
            <span class="comment">// 実装は省略。</span>
            <span class="control">return</span> <span class="reserved">null</span>!;
        }
    }
}
</code></pre>
<p>わざわざ <code>Select</code> を自作する人は少ないかもしれませんが、
例えば、「これまで標準でなかったから <code>MinBy</code>、<code>MaxBy</code> を自作していた。これらが .NET 6 で標準入りした」みたいな衝突は割かし起こるんじゃないかと思います。</p>
<p>その他、被りやすい名前でいうと <code>Task</code> クラスがそうで、<code>global using System.Threading.Tasks;</code> の自動追加が問題になったりします。</p>
<p>あと、「TargetFramwork は <code>net6.0</code> だけど、 LangVersion は 9 とか 8 とかで維持したい」みたいな場合に「global using を生成してしまったけど C# 9.0 以前では使えない」というコンパイル エラーを起こしていました。</p>
<p>ということで、明示的に設定を追加したときだけ「global using の自動追加」が働くように変更されました。
具体的には、csproj に以下の1行(<code>ImplicitUsings</code> オプションが true もしくは enable)があるときにだけ自動追加が働きます。</p>
<pre class="xsource" title="ImplicitUsings">
<code>    &lt;</span><span class="element">ImplicitUsings</span><span class="attvalue">&gt;</span>enable<span class="attvalue">&lt;/</span><span class="element">ImplicitUsings</span><span class="attvalue">&gt;</span>
</code></pre>
<p>で、この行は、.NET 6 SDK を使って新規プロジェクトを作成すると、初期状態で入っています。
.NET 6 SDK の、例えばコンソール アプリの csproj の初期状態は以下のような感じ。</p>
<pre class="xsource" title=".NET 6 で dotnet new console した直後の csproj の中身">
<code><span class="attvalue">&lt;</span><span class="element">Project</span><span class="attvalue"> </span><span class="attribute">Sdk</span><span class="attvalue">=</span>&quot;<span class="attvalue">Microsoft.NET.Sdk</span>&quot;<span class="attvalue">&gt;</span>
 
<span class="attvalue">  &lt;</span><span class="element">PropertyGroup</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">OutputType</span><span class="attvalue">&gt;</span>Exe<span class="attvalue">&lt;/</span><span class="element">OutputType</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">TargetFramework</span><span class="attvalue">&gt;</span>net6.0<span class="attvalue">&lt;/</span><span class="element">TargetFramework</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">ImplicitUsings</span><span class="attvalue">&gt;</span>enable<span class="attvalue">&lt;/</span><span class="element">ImplicitUsings</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">Nullable</span><span class="attvalue">&gt;</span>enable<span class="attvalue">&lt;/</span><span class="element">Nullable</span><span class="attvalue">&gt;</span>
<span class="attvalue">  &lt;/</span><span class="element">PropertyGroup</span><span class="attvalue">&gt;</span>
 
<span class="attvalue">&lt;/</span><span class="element">Project</span><span class="attvalue">&gt;</span>
</code></pre>
<h2>Using オプション</h2>
<p>ちなみに、(C# ソースコードで global using を書くのではなくあくまで csproj 設定で) 自動的に global using される名前空間を追加したり削除したりする手段も用意されています。</p>
<p><code>ItemGroup</code> 配下に <code>Using</code> というタグを書いて、</p>
<ul>
<li><code>Include</code> 属性を書くと名前空間追加</li>
<li><code>Remove</code> 属性を書くと名前空間削除</li>
</ul>
<p>になります。</p>
<p>例えば以下のように書くと、<code>System.Text.RegularExpressions</code> 名前空間が追加されて(<code>Regex</code> クラスなどが使える)、
<code>System.Linq</code> 名前空間が削除されます(自前 LINQ との衝突がなくなる)。</p>
<pre class="xsource" title="Using タグの例">
<code><span class="attvalue">&lt;</span><span class="element">Project</span><span class="attvalue"> </span><span class="attribute">Sdk</span><span class="attvalue">=</span>&quot;<span class="attvalue">Microsoft.NET.Sdk</span>&quot;<span class="attvalue">&gt;</span>

  <span class="comment">他の設定は省略</span>

<span class="attvalue">  &lt;</span><span class="element">ItemGroup</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">Using</span><span class="attvalue"> </span><span class="attribute">Include</span><span class="attvalue">=</span>&quot;<span class="attvalue">System.Text.RegularExpressions</span>&quot;<span class="attvalue">/&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">Using</span><span class="attvalue"> </span><span class="attribute">Remove</span><span class="attvalue">=</span>&quot;<span class="attvalue">System.Linq</span>&quot;<span class="attvalue">/&gt;</span>
<span class="attvalue">  &lt;/</span><span class="element">ItemGroup</span><span class="attvalue">&gt;</span>
 
<span class="attvalue">&lt;/</span><span class="element">Project</span><span class="attvalue">&gt;</span>

</code></pre>
<h2>全域一括 ImplicitUsings</h2>
<p>この <code>ImplicitUsings</code> と、あと、 C# 8.0 / の頃からある <code>Nullable</code> オプションですが、まあ、既存コードベースを壊さないために opt-in (明示的に書かないと有効化されない、デフォルトで無効)なわけです。</p>
<p>とはいえ、今、まっさらな状態から新規コードを書き始めるにはこの2つは「ノイズ」です。
そこでお薦めするのが <a href="https://ufcpp.net/blog/2018/12/directorybuild/"><code>Directory.Build.props</code></a> に書き足してしまう手法。</p>
<p>この名前のファイルに csproj に入れたい設定類を書いておくと、
そのファイルがあるフォルダー配下にある全 csproj に対して設定が有効化されます。
なので、リポジトリのルート フォルダーに以下の内容で <code>Directory.Build.props</code> ファイルを置いておけば、リポジトリ全域に対して <code>ImplicitUsings</code> と <code>Enullable</code> が有効化されます。</p>
<pre class="xsource" title="お薦め Directory.Build.props">
<code><span class="attvalue">&lt;</span><span class="element">Project</span><span class="attvalue">&gt;</span>
 
<span class="attvalue">  &lt;</span><span class="element">PropertyGroup</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">ImplicitUsings</span><span class="attvalue">&gt;</span>enable<span class="attvalue">&lt;/</span><span class="element">ImplicitUsings</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">Nullable</span><span class="attvalue">&gt;</span>enable<span class="attvalue">&lt;/</span><span class="element">Nullable</span><span class="attvalue">&gt;</span>
<span class="attvalue">  &lt;/</span><span class="element">PropertyGroup</span><span class="attvalue">&gt;</span>
 
<span class="attvalue">&lt;/</span><span class="element">Project</span><span class="attvalue">&gt;</span>
</code></pre>
<p>新規リポジトリにはこのファイルを置いておいていいんじゃないでしょうか。
(<code>ImplicitUsings</code> に関しては既存リポジトリに対しても、前述のような名前の衝突は経験上、数千～数万行に1個くらいしか起きない程度なので割かし追加しちゃっていいと思います。)</p>
 ]]></description>
				<pubDate>Fri, 12 Nov 2021 21:51:44 +0900</pubDate>
			</item>
			<item>
				<title>【C# 10.0】ファイル スコープ名前空間 (一斉置換設定)</title>
				<link>http://ufcpp.net/blog/2021/11/fix-all-file-scoped-namespace/</link>
				<description><![CDATA[ <p>昨日、C# 10.0 が正式リリースされたわけですが、皆様もう C# 10.0 へのアップグレードはお済でしょうか(当日アプグレが当たり前のような口調)。</p>
<p>まあ、
C# はそんなに大きな破壊的変更はしない言語ですし、
TargetFramework や LangVersion を書き換えるだけならそこまで大きな問題は起きないんじゃないかと思います。
(たぶん。
僕は <a href="https://docs.microsoft.com/en-us/dotnet/core/compatibility/core-libraries/6.0/partial-byte-reads-in-streams">CryptoStream の破壊的変更</a>由来のテスト失敗を1件踏みましたが。)</p>
<p>あえて踏み込むのであれば、</p>
<ul>
<li>名前空間を <code>namespace N {}</code> からファイル スコープな <code>namespace N;</code> に書き換え</li>
<li><code>ImplicitUsings</code> を true にして未使用 <code>using</code> になる部分をごっそり削除</li>
</ul>
<p>とかやると、機械的にできてリスクは低いものの大量の差分行を産むコミットを作れたりします。
<a href="https://twitter.com/ufcpp/status/1456993276066627591">ASP.NET では95万行の差分が出たそうですよ</a>(もちろん、「Hide whitespace」とかやるとほとんどの行が消える)。</p>
<p>とりあえず今日はこのうち前者、
ファイル スコープ名前空間の一斉全置換の話をしようかと思います。</p>
<h2>ファイル スコープ名前空間</h2>
<p>C# 10.0 のテーマの1つは「<a href="https://ufcpp.net/study/csharp/cheatsheet/ap_ver10/#simple-program">シンプル プログラム</a>」になっています。
その一環で、</p>
<pre class="source" title="従来のコード">
<code><span class="reserved">namespace</span> Namespace
{
    <span class="reserved">class</span> <span class="type">A</span> { }
}
</code></pre>
<p>という従来コードを、</p>
<pre class="source" title="C# 10 からできる名前空間の書き方">
<code><span class="reserved">namespace</span> Namespace;

<span class="reserved">class</span> <span class="type">A</span> { }
</code></pre>
<p>と書き換えられる機能(<a href="https://ufcpp.net/study/csharp/sp_namespace.html#file-scoped-namespace">ファイル スコープ名前空間</a>)が入りました。</p>
<p>まあ、名前空間とかパッケージ宣言とかで1段インデントを下げない言語の方が多いですしね。</p>
<p>C# はこの手の「新しい体験が得られるわけではなく、単にシンプルに書けるようになるだけ」みたいな新文法はこれまでそんなに積極的に追加はしてこなかったんですけども、
最近の流暢に乗ってついに折れた感じはします。</p>
<h2>ファイル スコープ名前空間を採用する？</h2>
<p>正直まあ、「新しい体験」は何もなく、単なる書式的な問題になるわけで、
既存コードに導入するモチベーションはそんなに高くないと思います。
手動で書き換えろと言われたら絶対に拒否。</p>
<p>ですが、全自動だと言われたら？</p>
<p>既存コードベースは1操作で変換可能で、
新規 C# ソースコードの追加時にもデフォルトでファイル スコープ名前空間な状態のファイルができるとしたら？</p>
<p>自分は「全自動ならまあ、やってもいいかな」くらいには思っています。</p>
<h2>設定が必要 (.editorconfig)</h2>
<p>ただまあ、この機能、「絶対にやれ」とも「絶対にやるな」とも言いにくい割かしどっちでもいい機能なわけでして。
「使えるならファイル スコープ名前空間を率先して使う」というモードにするためには設定が必要です。</p>
<p>書式・Code Fix 上の問題なので、Visual Studio のオプションで設定するか、
.editorconfig に設定を書くかする必要があります。
どちらを好むかはプロジェクトごとに違うでしょうから、Visual Studio オプション(全部のプロジェクトに影響)ではなく、
.editorconfig で設定する方が好ましいと思います。
(なのでそちらだけ説明します。)</p>
<p>ファイル スコープ名前空間を率先して使いたい方は .editorconfig に以下の行を追加してみてください。</p>
<pre class="source">
<code><span class="type">[*.{cs,vb}]</span>
<span class="reserved">csharp_style_namespace_declarations</span>=file_scoped:suggestion
</code></pre>
<p>これで、Visual Studio の一斉置換機能が働くようになります。</p>
<p><img src="/media/1192/ide0161.png" alt="Convert to file-scoped namespace" /></p>
<p>この行だけを修正するか、ドキュメント全体、プロジェクト全体、ソリューション全体を一斉置換するかはお好みでどうぞ。
ソリューション一斉置換とかすると数千～数万行の差分を作れます。
僕は昨日・今日で合計10万行くらいの差分を作りました。</p>
<p>末尾の suggestion (Visual Studio の Error List ペインにメッセージが出ちゃう)のところは silent (何もメッセージは出ないものの Code Fix を掛けることはできる)でも warning (修正しないと警告が出る)でも大丈夫です。</p>
<p>ちなみに、warning にしておけば、<code>dotnet format</code> コマンドでの自動整形も掛かります。
過激派の方はぜひとも warning に。</p>
 ]]></description>
				<pubDate>Wed, 10 Nov 2021 21:33:46 +0900</pubDate>
			</item>
			<item>
				<title>RC 出てた話からの、GA 迫ってたりする話</title>
				<link>http://ufcpp.net/blog/2021/11/2022-ga-soon/</link>
				<description><![CDATA[ <p><a href="/blog/2021/8/invariantculture/">8月</a>からしばらくブログをさぼっていたわけですが。
ブログとしてはお久しぶりです。</p>
<h2>C# 10.0 記事</h2>
<p>まあ、とはいえ、別に消息不明になっていたわけでもなく、<a href="https://ufcpp.net/study/csharp/">C# によるプログラミング入門</a>の方の記事書きをちゃんとしていただけでして。</p>
<div>
<section class="latest-posts sub-info-section">
<header><h3>更新履歴</h3></header>
<article>
<time datetime="2021-10-24T00:00:00.0000000">2021/10/24</time>
<header>
<h4>更新：<a href="/study/csharp/cheatsheet/ap_ver10/">C# 10.0 の新機能</a></h4>
<span class="subject">[C#]</span>
</header>
</article>
<article>
<time datetime="2021-10-17T00:00:00.0000000">2021/10/17</time>
<header>
<h4>更新：<a href="/study/csharp/functional/fun_localfunctions/">ローカル関数と匿名関数</a></h4>
<span class="subject">[C#]</span>
</header>
</article>
<article>
<time datetime="2021-09-23T00:00:00.0000000">2021/09/23</time>
<header>
<h4>更新：<a href="/study/csharp/start/improvedinterpolatedstring/">C# 10.0 の補間文字列の改善</a></h4>
<span class="subject">[C#]</span>
</header>
</article>
<article>
<time datetime="2021-09-20T00:00:00.0000000">2021/09/20</time>
<header>
<h4>更新：<a href="/study/csharp/datatype/patterns/">パターン マッチング</a></h4>
<span class="subject">[C#]</span>
</header>
</article>
<article>
<time datetime="2021-09-12T00:00:00.0000000">2021/09/12</time>
<header>
<h4><a href="/study/csharp/start/miscreservedattribute/">[雑記] コンパイル結果に影響を及ぼす属性</a></h4>
<span class="subject">[C#]</span>
</header>
</article>
</section>
</div>
<p><a href="https://github.com/ufcpp/UfcppSample/issues/342">C# 10.0 機能リスト</a>のうち、最低限必要なものは埋まったというか、残りは、</p>
<ul>
<li>限られた人だけが使う(大部分の人は間接的恩恵しか受けない)もの</li>
<li>細かい挙動変更</li>
<li>C# 10.0 リリース時点でどの道 <code>&lt;LangVersion&gt;preview&lt;/LangVersion&gt;</code> 必須なもの</li>
</ul>
<p>だけのはずです。</p>
<p><img src="/media/1191/csharp10-todo-2021-11-05.png" alt="C# 10.0 記事執筆状況" /></p>
<p>まあこの時期どうせネタ元であるところの <a href="https://github.com/dotnet/csharplang/">csharplang</a> も <a href="https://github.com/dotnet/roslyn/">roslyn</a> も11月の .NET 6.0 / C# 10.0 正式リリースに向けた作業をしているわけで、
うちのサイト的にも C# 入門ページを更新する方の優先度高めでおかしくないはず。
(という言い訳。)</p>
<h2>RC (リリース候補版)出てた</h2>
<p>そうこうしている間に、
<a href="https://github.com/ufcpp-live/UfcppLiveAgenda/issues/45">.NET 6 も RC になり</a>、
<a href="https://github.com/ufcpp-live/UfcppLiveAgenda/issues/47">Visual Studio も RC になり</a>、
それに対するライブ配信では「今日の本題は &quot;go-live&quot; の一言で終わりです。あとはその先の話を」とかやっていたりしました。</p>
<h2>GA (正式リリース)する</h2>
<p>そして、Visual Studio 2022 も .NET 6.0 も C# 10.0 も、来週には正式リリース(Generally Available)になりますね。
正式リリースされた暁には…
毎年あるあるなんですが、プレビューの時に遊びつくしていてリリースのタイミングで改めて言うこともないので記念雑談でもしようかと…</p>
<p><a href="https://github.com/ufcpp-live/UfcppLiveAgenda/issues/49">C# 10.0 / .NET 6.0 / Visual Studio 2022 正式リリース記念</a></p>
<div>
<iframe width="400" height="225" src="https://www.youtube.com/embed/-5jmoMUCQnc" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div>
<p>今年、なんか、<a href="https://www.dotnetconf.net/">.NET Conf</a> の前日に <a href="https://visualstudio.microsoft.com/ja/launch/">Visual Studio 2022 のローンチ イベント</a>をやるみたいですね。
Visual Studio 2022 はそのタイミングで正式リリースとのこと。</p>
<p>ということで、上記「記念配信」は、Visual Studio はリリース済み(アメリカ太平洋標準時8日以降)、
.NET Conf 開催(同 PST 9日8時半)直前のはずの、日本時間の9日夜にする予定です。</p>
<h2>その先の話しようか</h2>
<p>上記 RC ライブ配信でも「その先の話」してましたし、直近のライブ配信なんて「<a href="https://github.com/ufcpp-live/UfcppLiveAgenda/issues/48">時代は既に what's next for VS</a>」とかやってたわけでして。</p>
<p>要は、うちのブログで「ピックアップRoslyn」って銘打ってやってる話を最近さぼり気味で、ネタがたまり気味…</p>
<p>C# 10.0 記事の方が(ニッチなネタを除けば)落ち着いたんで、ちょこちょこ消化していければいいなぁと思う所存です。(「明日から本気出す」なやつ。)</p>
 ]]></description>
				<pubDate>Fri, 05 Nov 2021 23:56:08 +0900</pubDate>
			</item>
			<item>
				<title>.NET のカルチャー依存 API 問題</title>
				<link>http://ufcpp.net/blog/2021/8/invariantculture/</link>
				<description><![CDATA[ <p>以下のコード、実行環境によって出力結果が変わります。</p>
<pre class="source" title="DateTime の ToString がカルチャー依存">
<code><span class="type">Console</span>.<span class="method">WriteLine<span class="type">(<span class="reserved">new</span> <span class="type">DateTime</span>(2021, 8, 22));
</code></pre>
<p>日本語 Windows 環境だと <code>2021/08/22 0:00:00</code> と表示されると思いますが、
OS 設定でカルチャーを変更すると別の書式になります。
例えば、en-US カルチャーにすると <code>8/22/2021 12:00:00 AM</code> になります。
要するに、<code>DateTime.ToString</code> は OS のカルチャー依存になっています。</p>
<p>問題点はいくつかあるんですが…</p>
<ul>
<li><code>ToString</code> みたいなよく使うメソッドの既定動作がカルチャー依存</li>
<li><a href="https://docs.microsoft.com/ja-jp/aspnet/core/blazor/host-and-deploy/webassembly?view=aspnetcore-5.0">WebAssembly</a> みたいな、カルチャー情報を使いたくない環境がある</li>
<li>カルチャー非依存にしたければ北米カルチャーを強要されがち</li>
<li>北米カルチャーが思った以上に世界から浮いてる</li>
</ul>
<p>今日はこの辺りの話を書きたいと思います。</p>
<h2><a id="why-now">なぜ今</a></h2>
<p>国際化対応をしたことがある人ならたぶん、 .NET Framework 1.0 リリース当初であったり、
さらに言うと C# のリリース前、Windows アプリは Visual Basic (無印)や C++ を使って書いていた頃からこの手の問題には悩まされていたと思います。</p>
<p>ところが最近(去年くらいから)、別に国際化対応をしなくても悩むことが出てきました。</p>
<h3><a id="dotnet-icu">ICU 化</a></h3>
<p>元々、(Windows 向けの) .NET Framework では NLS (National Language Support)という Windows 組み込みの多言語対応データを使って国際化対応をしていました。</p>
<p>一方、マルチプラットフォームの .NET Core (.NET 5 以降は単に「.NET」と呼ぶようになったやつ)が出たことで、
Windows 以外では ICU (International Components for Unicode) という Unicode 標準に基づくライブラリを使うことになりました。
多くの Unix 系 OS では標準搭載、あるいは、割かし簡単な手間で ICU を組み込むことができるようになっています。
Windows 10 でも、2017年のアップデート以降、標準で ICU が入るようになりました。</p>
<p>.NET Core 3.1 までは、実は、Windows は NLS を、他の OS では ICU を使っていたことで、
実行環境によって微妙に実行結果が変わることがありました。
この挙動があまり望ましくないということで、
.NET 5 (2020年11月リリース)からは <a href="https://docs.microsoft.com/ja-jp/dotnet/core/extensions/globalization-icu">Windows でも ICU を使うように変更されました</a>。</p>
<p>その結果、.NET Core 3.1 から .NET 5 にアップデートすると、微妙に文字列処理に変化があったりします。
(NLS に戻すオプションもあるので、まずそうならそのオプションを指定することになります。)</p>
<p><a href="https://github.com/dotnet/runtime/issues/43736">軽く騒動もあった</a>んですが、
そこで初めて、「えっ、このメソッドもカルチャー依存だったんだ…」みたいな事実に気づいたという方も多いんじゃないかともいます。</p>
<p>ちなみに日本語でも、「<a href="https://github.com/dotnet/runtime/issues/54987">IgnoreCase を付けると &quot;つ&quot; と &quot;っ&quot; が Equals 扱いになった</a>」みたいなことが起きています。
(.NET 5 リリースのから今年7月まで気づかれてなかったっぽい。)</p>
<h3><a id="no-icu-env">OS 搭載の ICU に頼れない環境</a></h3>
<p>ICU のデータはフルに持つと結構なでかさになります。
.NET アプリの実行に必要な分だけ抜き出しても 1.4MB くらいあります。</p>
<p>まあ 1.4MB くらいのサイズであれば、サーバー OS ではそれほどきついサイズではないので、「たいてい OS が持ってる」を前提にしても問題ありませんでした。
問題は iOS や WebAssembly 実行で、
これらの環境ではアプリごとに ICU データを同梱して配布する必要があります。
WebAssembly なんかはブラウザーでダウンロードして実行する前提なので、
1.4MB もバカにならないサイズになります。
(だいたいはブラウザー自身、iOS であれば WebKit が ICU 依存なので、データとしては ICU を持っているはずなんですけどね… そのデータをアプリ開発者が参照する手段はないです。)</p>
<p>ということで、.NET も <a href="https://docs.microsoft.com/ja-jp/aspnet/core/blazor/host-and-deploy/webassembly?view=aspnetcore-5.0">Blazor WebAssembly</a> とかに注力している昨今、
「カルチャー依存をなくしたい」という要望も強くなってきました。</p>
<p>Blazor では、</p>
<ul>
<li>EFIGS (西欧向けのフランス語、イタリア語、ドイツ語、スペイン語だけを持つ)のデータだけを持つ</li>
<li>CJK (データがでかくなりがちな日中韓)のデータだけ抜く</li>
<li>完全にカルチャーを抜く(<a href="https://docs.microsoft.com/ja-jp/dotnet/api/system.globalization.cultureinfo.currentculture"><code>CurrentCulture</code></a> を取ろうとしても <a href="https://docs.microsoft.com/ja-jp/dotnet/api/system.globalization.cultureinfo.invariantculture"><code>InvariantCulture</code></a> が返ってくる)</li>
</ul>
<p>みたいなモードが選べるようになっていたりします。
完全にカルチャーを抜くモードは Blazor に限らず、<a href="https://github.com/dotnet/runtime/blob/main/docs/design/features/globalization-invariant-mode.md"><code>InvariantGlobalization</code> というオプション</a>を指定することでどのタイプの .NET アプリでも同じモードで実行できます。</p>
<h2><a id="culture-dependent-apis">謎のカルチャー依存</a></h2>
<p>ということで今になってカルチャー依存問題を踏んでいるわけですが。
ここでもう1個問題になるのが、「えっ、このメソッドもカルチャー依存だったの？」みたいな意外さ。</p>
<p>冒頭の例でも書きましたが、ただの <code>ToString</code> すらカルチャー依存です。
.NET が Windows 限定で、しかもアプリと言えば Windows GUI アプリだった時代にはこれでもよかったんですが…</p>
<p>当然ですが、Web アプリだとこの挙動は結構イラっとします。
クラウド インスタンスを新規で立ててカルチャー設定を忘れて <code>ToString</code> の結果が変わるみたいなやつ。</p>
<p>先ほど「<a href="https://github.com/dotnet/runtime/issues/43736">軽く騒動もあった</a>」と紹介したやつなんて結構ひどくて、「<a href="https://docs.microsoft.com/ja-jp/dotnet/api/system.string.indexof"><code>IndexOf</code></a> と <a href="https://docs.microsoft.com/ja-jp/dotnet/api/system.string.contains"><code>Contains</code></a> で結果が違う」という状態です。
なんでこんなことになるかというと、<code>IndexOf</code> は <code>CurrentCulture</code> 依存で、<code>Contains</code> は <a href="https://docs.microsoft.com/ja-jp/dotnet/api/system.stringcomparison">Ordinal</a> 比較だからです。
混ざってるのはさすがにつらい…</p>
<p>古くからある API ほどカルチャー依存で、新しめの API は <code>Ordinal</code> もしくは <code>InvariantCulture</code> 利用に変わっています。</p>
<p>ちなみに、「実行環境によって結果が変わる」という問題がある他にも、
パフォーマンス上の差もあります。
そもそも <code>CurrentCulture</code> 取得がそこそこ負担が掛かる処理というのもありますし、
<code>Ordinal</code> (文字コード通りに単なる数値比較するだけ)と比べてカルチャー依存処理(&quot;a&quot; と &quot;à&quot; や、&quot;か&quot; と &quot;が&quot; 等の関係性を考慮)する方が重たいに決まっています。</p>
<p>「<a href="https://docs.microsoft.com/ja-jp/dotnet/fundamentals/code-analysis/quality-rules/ca1304">カルチャー依存の API を呼ぶときは明示的にカルチャー指定しろよ</a>」というアナライザーがあったりするので、できればこの設定は有効にしておいた方がいいかもしれません。</p>
<h2><a id="invariant-culture">Invariant とは…</a></h2>
<p>で、まあ、<code>Ordinal</code> でいいものは <code>Ordinal</code> にするとして。
どうしてもカルチャー依存なものは <code>InvariantCulture</code> にするとして。
次の問題は <code>InvariantCulture</code> が invariant (不変な) という名前を名乗っているくせに北米基準という点。</p>
<p>以下のようなコードを書くと、北米フォーマットになります。</p>
<pre class="source" title="Invariant = 北米">
<code><span class="reserved">using</span> System.Globalization;
<span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="reserved">new</span> <span class="type">DateTime</span>(2021, 8, 22).<span class="method">ToString</span>(<span class="type">CultureInfo</span>.InvariantCulture));
</code></pre>
<p>90年代の IT 業界にはあるあるだったんですけどね、「北米がデフォルト」な動作。
Java なんかでも、<code>println(new Date())</code> すると <code>Sun Aug 22 08:18:22 UTC 2021</code> とかになりますよね、たぶん。</p>
<p>元をたどるとこの「未設定なら北米準拠にする」みたいなの、
「&quot;C&quot; ロケール」とか言われてるみたいですね。
古い C 言語多言語対応ライブラリがそういう挙動だったからという。</p>
<p>一方の2000年代言語だと yyyy-MM-dd フォーマットなことが多いんですが(Go とか Rust とか)…</p>
<p>まあ、日本人にとって困るのはたぶん日付のフォーマットくらいだと思います。
小数点は北米と同じなので。
ところがまあ、小数点・桁区切り記号に . を使うか , を使うかは、<a href="https://twitter.com/ufcpp/status/1426474277541322760">結構世界で2分されているみたい</a>なので注意が必要です。</p>
<h2><a id="usa">北米フォーマット</a></h2>
<p>日本にいると「欧米」なんていう区切りで一括りにしてしまいがちなんですが…
アメリカ合衆国、結構異端ですからね。</p>
<ul>
<li><a href="https://twitter.com/ufcpp/status/1426473850632491009">ヤードポンド利用国</a></li>
<li><a href="https://twitter.com/ufcpp/status/1426473940453494786">ファーレンハイト利用国</a></li>
<li><a href="https://twitter.com/ufcpp/status/1426474093096833027">MM/dd/yyyy 利用国</a></li>
</ul>
<p>英語圏の中でも <a href="https://imgur.com/MQ7LVC3">Arbitrary Retarded Rollercoaster</a>(勝手で遅れたジェットコースター)とか言われてるネタ画像出てきますからね、これ。
ちなみに、「アメリカはおかしい」って主張に対して「違うよ、アメリカの中でも合衆国だけだよ、一緒にしないで」までがセット。</p>
<p>それを見て「さすがに言いすぎじゃない？」って思って調べるとマジで1国だけ浮いているという。
特に日付。 dd-MM-yyyy (リトル エンディアン)と yyyy-MM-dd (ビッグ エンディアン)はどちらも分からなくはないものの、
さすがに MM-dd-yyyy (ミドル エンディアン？？？)はちょっと…</p>
<p>もちろん元々イギリスの文化なんですけども、当のイギリスはメートル法に改宗済み。
(といっても、法律上メートル法に変わってはいても、人が急に変われるわけもなく街中にはヤードポンドが残ってるそうですが。)
日付はぶれ気味(当人たちも混乱する)なので、Aug 22 みたいに書かないと MM-dd なのか dd-MM なのかわからなくなるから避けるみたいです。</p>
<p>という感じなので、そんな異端児をもって Invariant とか言われましても困ります… という感じになります。</p>
<p>最近、<a href="https://www.youtube.com/channel/UCY-z_9mau6X-Vr4gk2aWtMQ">C# 配信</a>をしていて、文字列処理の話をするたびに
「ヤードポンドの国なので」という話になるのはこういう背景から。
実害を受けるのは日付の MM-dd-yyyy 書式だけなんですけども、 MM-dd-yyyy の国 ≒ ヤードポンドの国 ≒ ファーレンハイトの国 という。</p>
<h2><a id="">ISO 8601 フォーマット</a></h2>
<p>と言うことで最近至った結論として、文字列処理は、</p>
<ul>
<li><code>Ordinal</code> にできるならそれを、何らかのカルチャーに依存するなら <code>InvariantCulture</code> にする</li>
<li>その上で、日付だけはフォーマットを明示的に指定</li>
</ul>
<p>でやらないと事故る。</p>
<p>そこでまあ、ちょうど C# 10.0 で <a href="https://ufcpp.net/study/csharp/st_string.html#string-interpolation"><code>$&quot;{X}&quot;</code></a> の<a href="https://github.com/ufcpp/UfcppSample/issues/355">カスタマイズをパフォーマンスを落とさずにできる仕様が入る</a>ので、
それを使って <code>InvariantCulture</code> 指定、かつ、日付だけは <code>O</code> 書式(<a href="https://ja.wikipedia.org/wiki/ISO_8601">ISO 8601</a>形式)を常に指定するコードを書いてみたり。</p>
<ul>
<li><a href="https://github.com/ufcpp/UfcppSample/commit/930db8d2430417b412dfcdbefce6fa5b4323a4ee">Iso8601.Format</a></li>
</ul>
<p>ちょうどカルチャー依存で困る時期だったので、ちょうど C# 10.0 でこの機能が入ったのは助かるかも。</p>
 ]]></description>
				<pubDate>Sun, 22 Aug 2021 20:38:16 +0900</pubDate>
			</item>
			<item>
				<title>最初の C# プログラム(.NET 6 新テンプレート)</title>
				<link>http://ufcpp.net/blog/2021/8/newprojecttemplate/</link>
				<description><![CDATA[ <p>.NET 6 ではプロジェクト テンプレートが更新されて、かなりシンプルになります。
例えば、コンソール アプリの場合(<code>dotnet new console</code> コマンドで生成)は(コメント行を除けば実質)以下の1行だけの C# ファイルが生成されます。</p>
<pre class="source" title="新コンソール アプリ テンプレート">
<code><span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="string">"Hello, World!"</span>);
</code></pre>
<p><a href="https://ufcpp.net/blog/2021/8/net6p7/">先日の .NET 6 Preview 7</a> から、コンソール アプリと Web アプリがこの新テンプレートになっています。
<a href="https://github.com/dotnet/templating/issues/3359">トラッキング issue</a> を見るに、他のタイプのプロジェクトも同じ方針で書き換え中みたいです。</p>
<p>今日はこの新テンプレートがらみで、背景とか、内部挙動的な話とか、Preview 7 から正式リリースまでの間に掛かる予定の変更の話とか。</p>
<h2>旧テンプレート</h2>
<p>まあ、これまでのテンプレートが以下のようなものでしたから、ずいぶんとすっきりしました。</p>
<pre class="source" title="旧テンプレート">
<code><span class="reserved">using</span> System;

<span class="reserved">namespace</span> ConsoleApp1
{
    <span class="reserved">class</span> <span class="type">Program</span>
    {
        <span class="reserved">static</span> <span class="reserved">void</span> Main(<span class="reserved">string</span>[] <span type="variable">args</span>)
        {
            <span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="string">"Hello, World!"</span>);
        }
    }
}
</code></pre>
<p>C# の勉強を続けているとそのうちどこかで出会うことになるコンセプトとはいえ、完全な初心者にとってはノイズにしかならない「おまじない」が結構あります。</p>
<ul>
<li><a href="https://ufcpp.net/study/csharp/sp_namespace.html#using">using</a></li>
<li><a href="https://ufcpp.net/study/csharp/sp_namespace.html#namespace">namespace</a></li>
<li><a href="https://ufcpp.net/study/csharp/oo_class.html">class</a></li>
<li><a href="https://ufcpp.net/study/csharp/oo_static.html">static</a></li>
<li><a href="https://ufcpp.net/study/csharp/st_command.html">コマンドライン引数</a></li>
<li><a href="https://ufcpp.net/study/csharp/misc/miscentrypoint/">エントリーポイント</a></li>
</ul>
<p>ということで、「初心者向けにもっとシンプルに書ける言語になりたい」というのが結構前から C# の課題でした。</p>
<p><a href="https://ufcpp.net/study/csharp/cheatsheet/apscripting/">C# 6.0 の時にスクリプト実行用の構文</a>ができたりもしましたし、
<a href="https://ufcpp.net/study/csharp/cheatsheet/ap_ver9/#top-level-statements">C# 9.0 ではトップ レベル ステートメント</a>が導入されました。
その流れで、C# 10.0 では <a href="https://github.com/ufcpp/UfcppSample/issues/345">global using</a> や <a href="https://github.com/ufcpp/UfcppSample/issues/352">file-scoped namespace</a> などが入りましたし、 .NET 6 以降、標準のプロジェクト テンプレートも積極的にこれら「シンプル化のための機能」を使ったものになります。</p>
<h2>「最初の C# プログラム」構想</h2>
<p>今時のプログラミング言語は大体公式サイトで「ブラウザー内で試してみる」機能が付いています。</p>
<p>というか「プログラミングを始めるにはまず Visual Studio をインストールします」なんて言うと、今時そこで9割の人が離脱します…</p>
<p>ということで、C# も現在では公式サイトで、</p>
<ul>
<li><a href="https://docs.microsoft.com/ja-jp/dotnet/csharp/">C# 関連のドキュメント</a></li>
<li><a href="https://docs.microsoft.com/ja-jp/dotnet/csharp/tour-of-csharp/tutorials/hello-world">オンライン、対話的な Hello World</a></li>
<li><a href="https://docs.microsoft.com/ja-jp/dotnet/csharp/tour-of-csharp/tutorials/hello-world?tutorial-step=1">最初の C# プログラムの実行</a></li>
</ul>
<p>とたどって、ブラウザー内で C# コードを試してみることができます。
そこで表示されているのが「新テンプレート」にもある以下の1行。</p>
<pre class="source" title="最初の C# プログラム">
<code><span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="string">"Hello, World!"</span>);
</code></pre>
<p>今まで、この1行、実は正規の C# だと動かなかったんですよね。
「適切な場所にこの C# をコピペすれば動く」と言う意味ではちゃんと動く C# コードなんですが、
「この1行だけをコピペしても動かない」という意味で「動かないコード」でした。</p>
<p>ところが、この公式サイト内では以下のように「動いてます」。</p>
<p><img src="/media/1188/tutorialstep1.png" alt="最初の C# プログラムをブラウザー内で実行" /></p>
<p>(そして、「公式サイトで動くことになっているコードが手元では動かない」と言うようなクレーム、結構あると思うんですよね。
僕も Twitter 上でこの手の文句を言っている人を数度見たことがあり。)</p>
<p>これ、最初は「C# スクリプト(通常の C# とちょっと別文法)なのかな？」とも思ったんですが、
<a href="https://github.com/ufcpp-live/UfcppLiveAgenda/issues/21#issuecomment-739150490">以前ちょっと試した感じ</a>、
どうも<a href="https://ufcpp.net/study/csharp/cheatsheet/apscripting/">スクリプト用の構文</a>ではなさそうと言う結論に。</p>
<p>少なくとも今日(2021年8月16日)の時点では、おそらく、前後に以下のコードを文字列結合してからコンパイルしているのだろうという推測をしています。</p>
<p>前:</p>
<pre class="source" title="前に concat してる文字列">
<code><span class="reserved">using</span> System;
<span class="reserved">using</span> System.Collections.Generic;
<span class="reserved">using</span> System.IO;
<span class="reserved">using</span> System.Linq;
<span class="reserved">using</span> System.Net.Http;
<span class="reserved">using</span> System.Threading;
<span class="reserved">using</span> System.Threading.Tasks;

<span class="reserved">namespace</span> Program
{
    <span class="reserved">class</span> <span class="type">Program</span>
    {
        <span class="reserved">static</span> <span class="reserved">void</span> <span class="method">Main</span>()
        {
</code></pre>
<p>後ろ:</p>
<pre class="source" title="後ろに concat してる文字列">
<code>        }
    }
}
</code></pre>
<p>その結果、以下のようなおかしな真似ができます。</p>
<p><img src="/media/1189/tutorialstepabuse.png" alt="おかしな対話型 C# コード" /></p>
<h2>「最初の C# プログラム」を動く C# コードに</h2>
<p>で、C# 10.0 でようやくこの「最初の C# プログラム」が動くコードになりました。</p>
<p>C# 9.0 時点でも以下のコードまでは書けていたんですが…</p>
<pre class="source" title="C# 9.0 での「最初の C# プログラム」">
<code><span class="reserved">using</span> System;

<span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="string">"Hello, World!"</span>);
</code></pre>
<p>ここで最後のノイズが <code>using System;</code> だったわけですが、
これが C# 10.0 の <a href="https://github.com/ufcpp/UfcppSample/issues/345">global using</a> で解消します。</p>
<p>要は、「暗黙的に using してる名前空間がある」という情報を何らかの方法で C# コンパイラーに伝えられればいいんですが、C# 10.0 では以下のような方式を取ることにしました。</p>
<ul>
<li>global using という C# の文法を追加</li>
<li>.NET SDK 側で、コンパイル開始時に所定の global using コードを生成</li>
</ul>
<p>例えば、コンソール アプリの場合、以下のようなソースコードが自動的に作られて、
手書きコードと一緒にコンパイルされます。</p>
<pre class="source" title="標準で自動生成される global using コード">
<code><span class="comment">// &lt;autogenerated /&gt;</span>
<span class="reserved">global</span> <span class="reserved">using</span> <span class="reserved">global</span>::System;
<span class="reserved">global</span> <span class="reserved">using</span> <span class="reserved">global</span>::System.Collections.Generic;
<span class="reserved">global</span> <span class="reserved">using</span> <span class="reserved">global</span>::System.IO;
<span class="reserved">global</span> <span class="reserved">using</span> <span class="reserved">global</span>::System.Linq;
<span class="reserved">global</span> <span class="reserved">using</span> <span class="reserved">global</span>::System.Net.Http;
<span class="reserved">global</span> <span class="reserved">using</span> <span class="reserved">global</span>::System.Threading;
<span class="reserved">global</span> <span class="reserved">using</span> <span class="reserved">global</span>::System.Threading.Tasks;
</code></pre>
<h2>.NET 6 Preview 7 でのバグ挙動と破壊的変更問題</h2>
<p>ただし、先日リリースしたての .NET 6 Preview 7 ではこれのせいでいくつか問題を起こしています。
すでに対処はされていて、次のリリース(おそらく RC 1)までに治るっぽいです。</p>
<p>とりあえずは Preview 7 時点のバグ挙動の説明。</p>
<p>上記の global using コードをどういう条件で生成するかと言うのが問題でして、
Preview 7 時点では「TargetFramework が net6.0 なら生成」となっていました。
これでどういう問題を起こすかと言うと、</p>
<ul>
<li>
TargetFramework net6.0 なのにあえて LangVersion を9以下に設定して global using を使えなくする
<ul>
<li>「global using を使うなら C# 10.0 以降を使え」というエラーが出る</li>
</ul>
</li>
<li>
TargetFrameworks で複数の TargetFrameworks を混在させる
<ul>
<li>net6.0 のときだけ global using が掛かっている状態になるので、net6.0 のときにしかコンパイルできないコードが生まれる</li>
</ul>
</li>
</ul>
<p>そして、TargetFramework を net6.0 に変えるだけで、既存のコードを壊すことがあります。
まあ、勝手に using している名前空間が足されている状態なので、そこに含まれている型と名前被りがあると「不明瞭な型」扱いを受けてコンパイル エラーを起こします。</p>
<p>例えば、<a href="https://github.com/dotnet/runtime/pull/56744">.NET チーム自身が地雷を踏んで、暗黙的な global using 生成を止める</a>という一時的な対処をやっています。</p>
<p>当初はこれを「<a href="https://docs.microsoft.com/ja-jp/dotnet/core/compatibility/sdk/6.0/implicit-namespaces">.NET 6 での破壊的変更</a>」としてユーザーに受け入れてもらおうと思っていたみたいなんですが、さすがに無理だと思ったのか、方式を改めるみたいです。</p>
<h2>次のリリースまでに掛かる変更</h2>
<p>ということで、<a href="https://github.com/dotnet/sdk/issues/19521">変更計画</a> (6.0.100-rc.1 に入れる目標とのこと)。</p>
<p>今(Preview 7 時点):</p>
<ul>
<li>net6.0 だと自動的に global using コードが生成されてしまう</li>
<li>それを抑止するために、DisableImplicitNamespaceImports というオプションがある(本来は Visual Basic 用)</li>
<li>プロジェクト テンプレートにはこれ関連の項目は何も含めない</li>
</ul>
<p>変更後(RC 1 目標):</p>
<ul>
<li>
ImplicitUsings というオプションを用意して、これが true もしくは enable の時だけ global using コードを生成する
<ul>
<li>DisableImplicitNamespaceImports は C# 向けにはなくす(Visual Basic 用オプションの流用をやめる)</li>
</ul>
</li>
<li>プロジェクト テンプレートに <code>&lt;ImplicitUsings&gt;enable&lt;/ImplicitUsings&gt;</code> の行を足す</li>
</ul>
<p>明示的なオプション指定を必須にして、標準のテンプレートにこのオプションを足すという方向性。</p>
<p>なので、既存のプロジェクトを net6.0 に変えただけで破壊的変更ということにはならなくなる予定です。
その代わり、csproj (プロジェクト設定ファイル)に1行ノイズが増えますが…
これはさすがにしょうがなさそう。</p>
 ]]></description>
				<pubDate>Mon, 16 Aug 2021 23:49:40 +0900</pubDate>
			</item>
			<item>
				<title>.NET 6 Preview 7 &amp; Visual Studio 2020 Preview 3</title>
				<link>http://ufcpp.net/blog/2021/8/net6p7/</link>
				<description><![CDATA[ <p>一昨日くらいに来てました。</p>
<ul>
<li><a href="https://devblogs.microsoft.com/visualstudio/visual-studio-2022-preview-3-now-available/">Visual Studio 2022 Preview 3 now available!</a></li>
<li><a href="https://devblogs.microsoft.com/dotnet/announcing-net-6-preview-7/">Announcing .NET 6 Preview 7</a></li>
<li><a href="https://devblogs.microsoft.com/dotnet/preview-features-in-net-6-generic-math/">Preview Features in .NET 6 – Generic Math</a></li>
<li><a href="https://devblogs.microsoft.com/dotnet/string-interpolation-in-c-10-and-net-6/">String Interpolation in C# 10 and .NET 6</a></li>
<li><a href="https://docs.microsoft.com/ja-jp/dotnet/core/tutorials/top-level-templates">新しい C# テンプレート</a></li>
<li><a href="https://devblogs.microsoft.com/aspnet/asp-net-core-updates-in-net-6-preview-7/">ASP.NET Core updates in .NET 6 Preview 7</a></li>
<li><a href="https://devblogs.microsoft.com/dotnet/announcing-net-maui-preview-7/">Announcing .NET MAUI Preview 7</a></li>
</ul>
<p>当日、このネタでライブ配信:</p>
<div>
<iframe width="560" height="315" src="https://www.youtube.com/embed/5m2qiJ24tqI" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div>
<p>「一気に情報が来ても小一時間では話しきれない」って感じで極々一部しか話せませんでしたが。</p>
<p>「Visual Studio 2020 Preview 3 の方が CDN トラブルで配信が1日延期」というトラブルに見舞われ、
「SDK だけを先に .NET 6 Preview 7 に上げてしまうと、標準のテンプレートがコンパイル エラーを起こす」という事件もありましたが、1日経って問題は解消済みです。</p>
<p>とりあえず、ブログとしては「今回入った C# 10.0 機能」の話を書こうと思います。
ちなみに、今回の更新でほぼ C# 10.0 の全機能が入っています。
(1個だけまだなものがあるけども、「10.0 リリース時点で preview 機能として残る」判定を受けている機能なので、非 preview な 10.0 機能は全部 merge 済み。)</p>
<p>(全機能一覧は<a href="https://github.com/ufcpp/UfcppSample/issues/342">トラッキング issue</a> を立ててるので現状そちらを見ていただけると。)</p>
<h2>.NET 6 Preview 7 での C# 10.0 新機能</h2>
<p><a href="https://github.com/dotnet/roslyn/blob/main/docs/Language%20Feature%20Status.md">Language Feature Status</a>で Merged into 17.0 と 17.0p3 になっているやつが今回入っています。
(17.0 になってる2つはもっと前に入ってた疑惑ちょっとあり。 Visual Studio 2020 Preview 2.1 のときかも。)</p>
<p>以下の6つ。</p>
<ul>
<li><a href="#definite-assignment">Improved Definite Assignment</a></li>
<li><a href="#property-pattern">Extended property patterns</a></li>
<li><a href="#interpolated-string">Interpolated string improvements</a></li>
<li><a href="#file-scoped-namespace">File-scoped namespace</a></li>
<li><a href="#parameterless-ctor">Parameterless struct constructors</a></li>
<li><a href="#caller-expression">Caller expression attribute</a></li>
</ul>
<p>あと、<a href="#lambda">Lambda improvements</a> も1個前の Preview では動いていなかった機能が増えているので、合計7つ。</p>
<h3><a id="definite-assignment">Improved Definite Assignment</a></h3>
<p>C# には元々、確実な代入ルールってのがあって、「未初期化変数から未定義な値を取り出す」みたいなことはできない仕様になっています。</p>
<pre class="source" title="未初期化変数を触らせない">
<code><span class="reserved">int</span> x;

<span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="error">x</span>); <span class="comment">// コンパイルエラー</span>

<span class="control">if</span> (<span class="reserved">int</span>.<span class="method">TryParse</span>(<span class="type">Console</span>.<span class="method">ReadLine</span>(), <span class="reserved">out</span> x))
{
    <span class="comment">// ここでは x が初期化済みな保証があるのでエラーが消える。</span>
    <span class="type">Console</span>.<span class="method">WriteLine</span>(x);
}
</code></pre>
<p>これのためのフロー解析に改善の余地があることが周知の事実で長らく手つかずだったんですが、それが C# 10.0 でちょっと改善します。</p>
<p>これまで <a href="https://ufcpp.net/study/csharp/rm_nullusage.html#null-conditional"><code>?.</code></a> とか <a href="https://ufcpp.net/study/csharp/rm_nullusage.html#null-coalesce"><code>??</code></a> とか <a href="https://ufcpp.net/study/csharp/st_operator.html#condition"><code>? :</code></a> が絡むときの解析が甘くて、過剰にエラーになっていました。
それが緩和されて、例えば、以下のようなコードがコンパイルできるようになっています。</p>
<pre class="source" title="?. が絡むときの確実な代入判定の改善例">
<code><span class="reserved">using</span> System.Diagnostics.CodeAnalysis;

m(<span class="reserved">null</span>);
m(<span class="reserved">new</span> R&lt;<span class="reserved">string</span>&gt;(<span class="reserved">null</span>));
m(<span class="reserved">new</span> R&lt;<span class="reserved">string</span>&gt;(<span class="string">"abc"</span>));

<span class="reserved">void</span> m(R&lt;<span class="reserved">string</span>&gt;? x)
{
    <span class="reserved">if</span> (x?.TryGetValue(<span class="reserved">out</span> var v) == <span class="reserved">true</span>) <span class="comment">// ここの var v の definite assignment 判定が改善された。</span>
    {
        Console.WriteLine(v.Length); <span class="comment">// 前までこの行がエラーになってた(C# 10.0 から OK に)。</span>
    }
    <span class="reserved">else</span>
    {
        Console.WriteLine(<span class="string">"null"</span>);
    }
}

<span class="reserved">record</span> <span class="reserved">class</span> <span class="type">R</span>&lt;<span class="type">T</span>&gt;(T? Value)
{
    <span class="reserved">public</span> <span class="reserved">bool</span> TryGetValue([NotNullWhen(<span class="reserved">true</span>)] <span class="reserved">out</span> T value)
    {
        <span class="reserved">if</span>(Value <span class="reserved">is</span> { } v)
        {
            value = v;
            <span class="reserved">return</span> <span class="reserved">true</span>;
        }
        <span class="reserved">else</span>
        {
            value = <span class="reserved">default</span>!;
            <span class="reserved">return</span> <span class="reserved">false</span>;
        }
    }
}
</code></pre>
<h3><a id="property-pattern"> Extended property patterns</a></h3>
<p><a href="https://ufcpp.net/study/csharp/datatype/patterns/?p=2#property">プロパティ パターン</a>で、
多段のメンバーを <code>.</code> でつないでマッチングできるようになりました。</p>
<pre class="source" title="多段プロパティ パターン">
<code><span class="reserved">var</span> x = <span class="reserved">new</span> <span class="type">A</span>(<span class="reserved">new</span> <span class="type">B</span>(<span class="string">"a"</span>));

<span class="control">if</span> (x <span class="reserved">is</span> <span class="type">A</span> { <em>X.Value.Length</em>: 1 })
{
    <span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="string">"len 1"</span>);
}

<span class="reserved">record</span> <span class="type">A</span>(<span class="type">B</span> X);
<span class="reserved">record</span> <span class="type">B</span>(<span class="reserved">string</span> Value);
</code></pre>
<h3><a id="interpolated-string"> Interpolated string improvements</a></h3>
<p><a href="https://ufcpp.net/study/csharp/st_string.html#string-interpolation">文字列補間</a>のパフォーマンスが大幅に向上します。</p>
<p>以下のようなコードがあったとして、</p>
<pre class="source" title="文字列補間の例">
<code><span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="method">m</span>(1, 2, 3, 4));

<span class="reserved">string</span> m(<span class="reserved">int</span> a, <span class="reserved">int</span> b, <span class="reserved">int</span> c, <span class="reserved">int</span> d) =&gt; <span class="string">$"</span>{a}<span class="string">.</span>{b}<span class="string">.</span>{c}<span class="string">.</span>{d}<span class="string">"</span>;
</code></pre>
<p>これまでは <code>string.Format(&quot;{0}.{1}.{2}.{3}&quot;, new object[] { a, b, c, d })</code> に展開されていました。
それが、所定の条件を満たせば(普通にやってれば .NET 6 をターゲットにして C# 10.0 でコンパイルすると)、以下のようなコードに変化します。</p>
<pre class="source" title="パフォーマンス改善結果">
<code><span class="reserved">var</span> h = <span class="reserved">new</span> System.Runtime.CompilerServices.<span class="type">DefaultInterpolatedStringHandler</span>(3, 4);
h.<span class="method">AppendFormatted</span>(a);
h.<span class="method">AppendLiteral</span>(<span class="string">"."</span>);
h.<span class="method">AppendFormatted</span>(b);
h.<span class="method">AppendLiteral</span>(<span class="string">"."</span>);
h.<span class="method">AppendFormatted</span>(c);
h.<span class="method">AppendLiteral</span>(<span class="string">"."</span>);
h.<span class="method">AppendFormatted</span>(d);
<span class="reserved">return</span> h.<span class="method">ToStringAndClear</span>();
</code></pre>
<p>ちなみに、C# コンパイラーのレベルで頑張っていることなので再コンパイルが必要です。
これに関しては「既存のコンパイル済みプログラムを .NET 6 で動かすだけで速くなる」みたいなことはないです。</p>
<h3><a id="file-scoped-namespace"> File-scoped namespace</a></h3>
<p>いままで:</p>
<pre class="source" title="{} 名前空間">
<code><span class="reserved">using</span> System;
<span class="reserved">using</span> System.Collections.Generic;
<span class="reserved">using</span> System.Linq;
<span class="reserved">using</span> System.Text;
<span class="reserved">using</span> System.Threading.Tasks;

<span class="reserved">namespace</span> ConsoleApp1
{
    <span class="reserved">class</span> <span class="type">A</span>
    {
    }
}
</code></pre>
<p>これから:</p>
<pre class="source" title="1行名前空間">
<code><span class="reserved">namespace</span> ConsoleApp1;

<span class="reserved">class</span> <span class="type">A</span>
{
}
</code></pre>
<p>「たかが1インデント」と言われてたやつなんですが…
まあ確かにこの1インデントが深い言語の方が、今となっては少なく。</p>
<h3><a id="parameterless-ctor"> Parameterless struct constructors</a></h3>
<p><a href="https://ufcpp.net/blog/2021/2/parameterlessstructctor/">さかのぼること C# 6.0 の時に、<code>Activator</code> のバグでできなかったやつ</a>、再チャレンジ(成功)。</p>
<p>構造体のフィールドでも非 null 保証とかがやりやすくなります。</p>
<pre class="source" title="構造体の引数なしコンストラクターの例">
<code><span class="reserved">struct</span> <span class="type">A</span>
{
    <span class="reserved">public</span> <span class="reserved">string</span> S { <span class="reserved">get</span>; } = <span class="string">"abc"</span>; <span class="comment">// 前まで初期化子を書けなかった</span>
}

<span class="reserved">struct</span> <span class="type">B</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span>[] Array { <span class="reserved">get</span>; }
    <span class="reserved">public</span> <span class="type">B</span>() =&gt; Array = <span class="reserved">new</span> <span class="reserved">int</span>[4]; <span class="comment">// 前まで B() を書けなかった</span>
}
</code></pre>
<p>まあ、<code>default</code> からは逃げられないんですが…</p>
<pre class="source" title="参照型の null 問題と同程度にやっかいな default 問題">
<code><span class="comment">// これは大丈夫。引数なしコンストラクターで new int[] されてる。</span>
Array4 a = <span class="reserved">new</span>();
Console.WriteLine(a[0]);

<span class="comment">// default は引数なしコンストラクターを呼ばない。</span>
a = <span class="reserved">default</span>;
Console.WriteLine(a[0]); <span class="comment">// ぬるぽ</span>

<span class="reserved">struct</span> <span class="type">Array4</span>
{
    <span class="reserved">private</span> <span class="reserved">readonly</span> <span class="reserved">int</span>[] _array;
    <span class="reserved">public</span> <span class="type">Array4</span>() =&gt; _array = <span class="reserved">new</span> <span class="reserved">int</span>[4];
    <span class="reserved">public</span> <span class="reserved">int</span> <span class="reserved">this</span>[<span class="reserved">int</span> index] =&gt; _array[index];
}
</code></pre>
<h3><a id="caller-expression"> Caller expression attribute</a></h3>
<p><a href="https://ufcpp.net/study/csharp/ap_ver5.html#CallerInfo">CallerInfo 系の属性</a>に新しい仲間が増えました。</p>
<p><code>CallerArgumentExpression</code> 属性で、「引数に渡した式」を取れるようになります。</p>
<pre class="source" title="CallerArgumentExpression の例">
<code><span class="reserved">using</span> System.Runtime.CompilerServices;

<span class="method">m</span>(2 * 3 * 4); <span class="comment">// 2 * 3 * 4 = 24</span>

<span class="reserved">var</span> (x, y, z) = (1, 2, 3);
<span class="method">m</span>(x + y + z); <span class="comment">// x + y + z = 6</span>

<span class="reserved">static</span> <span class="reserved">void</span> <span class="method">m</span>(<span class="reserved">int</span> result, [<span class="type">CallerArgumentExpression</span>(<span class="string">"result"</span>)] <span class="reserved">string</span>? expression = <span class="reserved">null</span>)
{
    <span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="string">$"</span>{expression}<span class="string"> = </span>{result}<span class="string">"</span>);
}
</code></pre>
<p>主にロギング用途になると思います。</p>
<h3><a id="lambda"> Lambda improvements</a></h3>
<p>.NET 6 Preview 6 時点で以下のようなコードは書けていたんですが。</p>
<pre class="source" title="Delegate にラムダ式を代入">
<code><span class="type">Delegate</span> f = <span class="reserved">int</span> (<span class="reserved">int</span> x) =&gt; x * x;
</code></pre>
<p>Prevew 7 から以下のようなコードも書けるようになりました。</p>
<pre class="source" title="ラムダ式の自然な型を自動決定">
<code><span class="reserved">var</span> f = <span class="reserved">int</span> (<span class="reserved">int</span> x) =&gt; x * x;
</code></pre>
<p>この場合、<code>f</code> の型は <code>Func&lt;int, int&gt;</code> になります。
<code>System.Action</code> か <code>System.Func</code> が使える場合にはそれを、
使えない場合には internal なデリゲート型をコンパイラー生成して使うそうです。</p>
<p>デリゲートの仕様上、以下のような挙動をするのでその点には注意が必要です。</p>
<pre class="source" title="ラムダ式の自然な型の罠の例">
<code><span class="comment">// これは target-typed 型決定で、Predicate&lt;int&gt; になる(コンパイル可)。</span>
m(x =&gt; x == 0);

<span class="comment">// 一方で、これは f の型が Func&lt;int, bool&gt; になる。</span>
<span class="reserved">var</span> f = (<span class="reserved">int</span> x) =&gt; x == 0;
m(<span class="error">f</span>); <span class="comment">// Func&lt;int, bool&gt; を Predicate&lt;int&gt; に変換でしません(コンパイル エラー)。</span>

<span class="reserved">static</span> <span class="reserved">void</span> m(Predicate&lt;<span class="reserved">int</span>&gt; f) { }
</code></pre> ]]></description>
				<pubDate>Fri, 13 Aug 2021 20:31:31 +0900</pubDate>
			</item>
			<item>
				<title>C# 10.0 に入れるかどうか確定させる時期が来たようです</title>
				<link>http://ufcpp.net/blog/2021/7/csharp10featurestatus/</link>
				<description><![CDATA[ <p>今年もそろそろ、どの機能を C# 10.0 にして、どの機能を &quot;Next&quot; のまま(11 以降に先送り)にするかを決めないといけない時期が来ましたと言う話。</p>
<h2>マージ済み機能</h2>
<p>まず、<a href="https://github.com/dotnet/roslyn/blob/main/docs/Language%20Feature%20Status.md">Language Feature Status</a> が更新されました。</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/pull/54728">roslyn#54728</a></li>
</ul>
<p>「C# 10.0」の方に移ったのが以下の4つ。
(17.0p2 が Visual Studio 17 Preview 2、
17.0p3 が Preview 3。)</p>
<table>
<thead>
<tr>
	<th>機能</th>
	<th>Merge 先</th>
</tr>
</thead>
<tbody>
<tr>
	<td><a href="https://github.com/dotnet/csharplang/blob/main/proposals/lambda-improvements.md">Lambda improvements</a></td>
	<td>17.0p2</td>
</tr>
<tr>
	<td><a href="https://github.com/dotnet/csharplang/issues/4436">Static Abstract Members In Interfaces</a> ※</td>
	<td>17.0p2</td>
</tr>
<tr>
	<td><a href="https://github.com/dotnet/csharplang/issues/4487">Interpolated string improvements</a></td>
	<td>17.0p3</td>
</tr>
<tr>
	<td><a href="https://github.com/dotnet/csharplang/issues/137">File-scoped namespace</a></td>
	<td>17.0p3</td>
</tr>
</tbody>
</table>
<p>※ これだけ「Preview」です(後述)。</p>
<p>Visual Studio 17 Preview 1 が出てからそろそろ1か月くらいですし、
このリストに「p3」(次の次)の文字が並び始めたんで、そろそろ Preview 2 が出るんでしょうね。</p>
<h2>10.0 には間に合わせるリスト</h2>
<p>それとは別に、<a href="https://github.com/dotnet/csharplang/blob/main/meetings/2021/LDM-2021-07-12.md">7月12日の LDM</a> では残りの &quot;Next&quot; について、10.0 に入れるべきかどうかの話があったみたいです。それによれば、</p>
<ul>
<li>
<a href="https://github.com/dotnet/csharplang/issues/99">Parameterless struct constructors</a>
<ul>
<li>record structs の一部みたいなものだし入る。p3 にマージ予定</li>
</ul>
</li>
<li>
<a href="https://github.com/dotnet/csharplang/issues/373">nameof(parameter)</a>
<ul>
<li>需要あるのはわかってるけど10には間に合わなさそう</li>
</ul>
</li>
<li>
<a href="https://github.com/dotnet/csharplang/issues/2145">Parameter null-checking</a>
<ul>
<li>11 入りを目指す</li>
</ul>
</li>
<li>
<a href="https://github.com/dotnet/csharplang/issues/946">Relax ordering of ref and partial modifiers</a>
<ul>
<li>進捗ないです。&quot;Next&quot; からも消した方がいいか</li>
</ul>
</li>
<li>
<a href="https://github.com/dotnet/csharplang/issues/287">Caller expression attribute</a>
<ul>
<li>ほぼできてる。たぶん 10 入り</li>
</ul>
</li>
<li>
<a href="https://github.com/dotnet/csharplang/issues/124">Generic attributes</a>
<ul>
<li>できてる。たぶん 10 入り</li>
</ul>
</li>
<li>
<a href="https://github.com/dotnet/csharplang/issues/3435">List patterns</a>
<ul>
<li>11 入りを目指す</li>
</ul>
</li>
</ul>
<p>だそうです。</p>
<p>あと、ひっそりと、<a href="https://ufcpp.net/blog/2021/2/rawstringliteral/">raw string literals</a> の実装コードの中に「<a href="https://github.com/dotnet/roslyn/pull/54789/commits/9d7b780045316eb3429538ca4b8a91dc9a2bc114#diff-3ac66c25866171b5ebdd5ff2622127096c9b78b7f724d7936b64872faa977894R1986">C# 11.0</a>」の文字が
(コンセプト検証用のコードですけど、「既成事実化」を狙ってそうな匂いが多少)。</p>
<h2>※ Preview</h2>
<p>これまでだいたい、Preview というと、</p>
<ul>
<li>
1月～7月くらいまでの間、<a href="https://ufcpp.net/study/csharp/cheatsheet/langversionoption/#langversion">LangVersion preview</a> 指定必須で機能提供
<ul>
<li>.NET 6 Preview を使っていても LangVersion preview 指定が必須</li>
</ul>
</li>
<li>
8月くらいから、時期 .NET SDK と同期して LangVersion default 扱い
<ul>
<li>.NET 6 Preview を使うと LangVersion default が C# 10.0 になる</li>
</ul>
</li>
<li>
11月の .NET SDK リリースに合わせて言語機能もリリース
<ul>
<li>.NET 6 のリリースと同時に C# 10.0 としてリリース</li>
</ul>
</li>
</ul>
<p>みたいなものしかありませんでした。</p>
<p>ただ、今回、 .NET 6 リリース時点でも Preview として残りそうな機能が1個あります。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/4436">Static Abstract Members In Interfaces</a></li>
</ul>
<p>こいつだけは、 Visual Studio 17 Preview 2 時点で動く物が世に出るものの、.NET 6 リリース時点でも LangVersion preview 必須になりそうです。
要するに、Preview である期間を十分長く取りたいくらいチャレンジ度合いの高い機能です。</p>
<p>C# 側だけでなく、 .NET ランタイム側にも Preview オプション指定での実行が必要だし、<code>RequiresPreviewFeatures</code> 属性が付いていて「ランタイム側の Preview 機能を使う前提」のライブラリでしか使えないようにアナライザーでチェックを行うみたいです。</p>
 ]]></description>
				<pubDate>Wed, 14 Jul 2021 23:32:43 +0900</pubDate>
			</item>
			<item>
				<title>Visual Studio 16.11 Preview 2: record struct と global using</title>
				<link>http://ufcpp.net/blog/2021/6/vs16_11_p2/</link>
				<description><![CDATA[ <p><a href="https://docs.microsoft.com/en-us/visualstudio/releases/2019/release-notes-preview#16.11.0.pre.2.0">Visual Studio 16.11 Preview 2</a> が来ていて、これに C# 10.0 の新機能が2つほど merge されています。
(いつも通り、<a href="https://ufcpp.net/study/csharp/cheatsheet/langversionoption/#new-options">LangVersion preview</a> を入れれば利用可能になっています。)</p>
<ul>
<li><a href="https://ufcpp.net/study/csharp/datatype/record/#record-struct">record struct</a></li>
<li><a href="https://ufcpp.net/blog/2021/3/usingimprovements/">global using</a></li>
</ul>
<p>ちなみに本当は <a href="https://github.com/ufcpp-live/UfcppLiveAgenda/issues/34">16.10 Preview 3 のとき</a>に sealed record ToString って機能もひっそりと入ってるんですが、
まあ下手すると誰も気づかないレベルの修正なので説明省略…
(先月全然ブログを書いてないことへの言い訳。)</p>
<h2><a id="record-struct">record struct</a></h2>
<p>はい。<a href="https://ufcpp.net/study/csharp/datatype/record/">レコード型</a>を<a href="https://ufcpp.net/study/csharp/oo_reference.html#valtype">値型</a>(構造体)でも作れるようになりました。
C# 9.0 時点で、単に <code>record</code> キーワードを使って型定義すると必ず<a href="https://ufcpp.net/study/csharp/oo_reference.html#reftype">参照型</a>(クラス)になっていたんですが、C# 10.0 では <code>record struct</code> と <code>record class</code> で値型・参照型を選べるようになりました。</p>
<pre class="source" title="record struct, record class">
<code><span class="comment">// こっちは構造体なのでヒープ アロケーション起きない。</span>
<span class="comment">// あんまりでかいデータを持たせるとコピーのコストが結構でかい。</span>
<span class="reserved">var</span> s = <span class="reserved">new</span> <span class="type">S</span>(1, 2);

<span class="comment">// こっちはクラスなのでアロケーション発生。</span>
<span class="reserved">var</span> c = <span class="reserved">new</span> <span class="type">C</span>(1, 2);

<span class="reserved">record</span> <span class="reserved">struct</span> <span class="type">S</span>(<span class="reserved">int</span> X, <span class="reserved">int</span> Y);
<span class="reserved">record</span> <span class="reserved">class</span> <span class="type">C</span>(<span class="reserved">int</span> X, <span class="reserved">int</span> Y);
</code></pre>
<p>ちなみに、単なる <code>record</code> はこれまで通りクラスです。
<code>record</code> と <code>record class</code> は完全に同じ意味。</p>
<h3>struct と record struct</h3>
<p>レコード型は元々「構造体的な扱いができる参照型」でした。
構造体みたいに、メンバーごとのクローン、メンバーごとの値比較ができるクラスみたいなものです。</p>
<p>じゃあ、<code>record struct</code> は普通の <code>struct</code> と何が違うかと言うと、以下のような点。</p>
<ul>
<li>プライマリ コンストラクターを持てる</li>
<li>プライマリ コンストラクターの引数からプロパティが自動生成される</li>
<li>
以下のメソッドが自動的に作られる
<ul>
<li><a href="https://ufcpp.net/study/csharp/datatype/deconstruction/"><code>Deconstruct</code> メソッド</a></li>
<li><code>ToString</code></li>
<li><code>Equals</code>, <code>GetHashCode</code> (<code>IEqualtable&lt;T&gt;</code> インターフェイスの実装)</li>
<li><code>==</code>, <code>!=</code> 演算子</li>
</ul>
</li>
</ul>
<h3>struct と with</h3>
<p>あと、今回一緒に、普通の構造体に対しても <a href="https://ufcpp.net/study/csharp/datatype/record/#with"><code>with</code> 式</a>が使えるようになっています。</p>
<pre class="source" title="普通の構造体に対して with ">
<code><span class="reserved">var</span> s1 = <span class="reserved">new</span> S { X = 1, Y = 2 };
<span class="reserved">var</span> s2 = s1 <span class="reserved">with</span> { X = 3 };

Console.WriteLine(s2); <span class="comment">// (3, 2)</span>

<span class="reserved">struct</span> <span class="type">S</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> X { <span class="reserved">get</span>; <span class="reserved">init</span>; }
    <span class="reserved">public</span> <span class="reserved">int</span> Y { <span class="reserved">get</span>; <span class="reserved">init</span>; }
    <span class="reserved">public</span> <span class="reserved">override</span> <span class="reserved">string</span> ToString() =&gt; (X, Y).ToString();
}
</code></pre>
<p>構造体では、ある変数から別の変数に代入したとき、元から自動的にコピーを作っていたので、それをそのまま使っています。</p>
<h2>global using</h2>
<p><code>global using</code> を使うと、プロジェクト全体に対して有効な <a href="https://ufcpp.net/study/csharp/sp_namespace.html#using">using ディレクティブ</a>を書けます。</p>
<p>例えば、ある1ファイルに以下のようなコードを書いたとします。</p>
<pre class="source" title="global using を書いたファイル">
<code><span class="reserved">global</span> <span class="reserved">using</span> <span class="reserved">static</span> System.<span class="type">Console</span>;
<span class="reserved">global</span> <span class="reserved">using</span> System.Linq;
<span class="reserved">global</span> <span class="reserved">using</span> System.Collections.Generic;
</code></pre>
<p>そのプロジェクト内では、以下のようなコードが普通に書けます。</p>
<pre class="source" title="global using の影響下にあるコードの例">
<code><span class="reserved">var</span> x = <span class="reserved">new</span> <span class="type">List</span>&lt;<span class="reserved">int</span>&gt; { 1, 2, 3 };
<span class="reserved">var</span> y = x.<span class="method">Select</span>(i =&gt; i * i);
<span class="control">foreach</span> (<span class="reserved">var</span> i <span class="reserved">in</span> y) <span class="method">WriteLine</span>(i);
</code></pre>
<p><a href="https://ufcpp.net/study/csharp/misc/miscentrypoint/#top-level-statements">トップ レベル ステートメント</a>と合わせると、本当にこの3行だけで「コンパイルできて実行できるコード」になります。
「ネットで見かけたサンプル コードをコピペしたら動かない」というクレームが減るかと思われます。
(これが一番のメリット。)</p>
<p>あと、「<a href="https://devblogs.microsoft.com/dotnet/date-time-and-time-zone-enhancements-in-net-6/"><code>DateOnly</code> なんて名前</a>嫌だーーー」という方は以下のように書いておけます。一応。(別に推奨はしない。)</p>
<pre class="source" title="">
<code><span class="reserved">global</span> <span class="reserved">using</span> Date = System.DateOnly;
</code></pre>
<h3>通常 using と同列</h3>
<p><code>global using</code> は、「そのプロジェクト内のすべてのファイルの先頭に <code>using</code> があるのと一緒」みたいな挙動をします。
つまり、「通常 <code>using</code> よりも外側のスコープ」みたいなことにはなりません。
あくまで「通常 <code>using</code> と同列」です。</p>
<p>例えばどこかのファイルに以下のような <code>System</code> への <code>global using</code> があったとします。</p>
<pre class="source" title="System への global using">
<code><span class="reserved">global</span> <span class="reserved">using</span> System;
</code></pre>
<p>で、これと同じプロジェクト内で通常の <code>using</code> を書く場合、以下のような挙動をします。</p>
<pre class="source" title="global using System; 影響下のコード">
<code><span class="reserved">using</span> <span class="warning">System</span>; <span class="comment">// すでに global using System; があるので「重複」警告あり</span>

<span class="reserved">using</span> X = <span class="error">DateTime</span>; <span class="comment">// この行はコンパイル エラー。ここでは using System; ありきにはならない。</span>
<span class="reserved">using</span> <span class="type">Y</span> = System.<span class="type">DateTime</span>; <span class="comment">// こっちは OK</span>

<span class="reserved">namespace</span> A
{
    <span class="reserved">using</span> <span class="type">X</span> = <span class="type">DateTime</span>; <span class="comment">// これも OK。A の外に using System; があるので。</span>
}
</code></pre>
<h3>知らないところで using されてる問題</h3>
<p>別に <code>global</code> かどうか以前の問題なんですが、「<code>using</code> しすぎ」は問題を起こすことがあります。
まず、同じ名前の型があった場合に「どっちかわからない」エラーを起こします。
単純に IDE 上での補完候補が増えすぎてうざいとかもあります。
それに、C# の場合、<a href="https://ufcpp.net/study/csharp/sp3_extension.html#problem">拡張メソッド</a>という、<code>using</code> の有無で挙動が変わる機能があったりもします。</p>
<p><code>global using</code> ではそれをプロジェクト全体にわたってできるわけですから、
嫌がらせしようと思えばいくらでも嫌がらせができます。
とりあえず名前被りの例:</p>
<pre class="source" title="同名クラスを持つ別名前空間を global using">
<code><span class="comment">// JsonSerializer クラスがどれにもあるので、フルネームで書かないと弁別不能になる。</span>
<span class="reserved">global</span> <span class="reserved">using</span> Newtonsoft.Json;
<span class="reserved">global</span> <span class="reserved">using</span> Utf8Json;
<span class="reserved">global</span> <span class="reserved">using</span> System.Text.Json;
</code></pre>
<p>ちなみに、<code>global using</code> は複数のファイルに書けます。
上記嫌がらせの3行を、それぞれ全く別のファイルに書いておくということもできます。</p>
<p>一方で、一応、<em>ファイルの先頭にしか書けない</em>という縛りはあります。</p>
<pre class="source" title="先頭以外に global using を書くとさすがにエラー">
<code><span class="reserved">using</span> System;

<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> <span class="method">Main</span>()
    {
        <span class="comment">// 超絶長い Main 処理を延々と書いたりもありえなくはない</span>
    }
}

<span class="error"><span class="reserved">global</span> <span class="reserved">using</span> System.Linq;</span> <span class="comment">// さすがにこの行はコンパイル エラー</span>
</code></pre>
<h4>問題を起こせる範囲</h4>
<p>ただまあ、<code>global using</code> の影響範囲はプロジェクト内に限られるので、
嫌がらせができるとすれば基本的に「内部犯」になります。</p>
<p>「<a href="https://github.com/ufcpp-live/UfcppLiveAgenda/issues/36">global using で一番邪悪なことやった人が優勝</a>」とかいうひどいタイトルで配信してアイディアを募ろうとしていたり。</p>
<p>それで例として「<code>Where</code> 拡張メソッドの乗っ取り」を挙げてはいるんですが…
拡張メソッドで悪さをしたければ、トップ レベルのクラス(名前空間なしのグローバルなクラス)に拡張メソッドを書く方がはるかにたちが悪いです。</p>
<p>で、内部犯であれば、レビューや単体テストをちゃんとしていればある程度は防げるはずです。
悪意を持って攻めるなら「数千行のコミットにしれっと混ぜ込む」とかも考えられますけども。</p>
<p>たいてい以下のような <a href="https://ufcpp.net/study/csharp/misc/analyzer-generator/#analyzer">Analyzer</a> を書いてしまえば対処できちゃいそうなんですよねぇ…</p>
<ul>
<li>複数のファイルに <code>global using</code> を書けなくする</li>
<li>拡張メソッドを含む名前空間を <code>global using</code> できなくする</li>
<li><code>global using</code> した名前空間中の型名の被りに対して警告を出す</li>
</ul>
<p>あと、<code>global using</code> は <a href="(https://ufcpp.net/study/csharp/misc/analyzer-generator/#analyzer)">Source Generator</a> で生成することもできます。
これが唯一の「プロジェクト外に影響を及ぼせる <code>global using</code>」になるんですが…
こちらはこちらで、「信用ならないパッケージを参照するのが怖いのは元から」ですし、
Source Generator を書ける人自体が割合そんなに多くないですし。</p>
<p>なんかこう、レビューをうまくすり抜けたり、「嫌な予感しかしないんだけどメリットもありそうでやむなく使う」みたいな邪悪さを出せないものかと悩み中…</p>
 ]]></description>
				<pubDate>Wed, 16 Jun 2021 22:10:57 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 4/4: static virtual/abstract members</title>
				<link>http://ufcpp.net/blog/2021/4/staticvirtual/</link>
				<description><![CDATA[ <p>インターフェイスの静的メソッドを virtual/abstract 指定できるようにする話が出ています。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/4436">[Proposal]: Static abstract members in interfaces #4436</a></li>
</ul>
<p>主な用途は、</p>
<ul>
<li>ファクトリ</li>
<li>比較 (<code>Equatable</code> とか <code>Comparable</code>)</li>
<li>数値計算</li>
</ul>
<p>とかになると思います。
一番求められている用途は数値計算で、要は <a href="https://ja.wikipedia.org/wiki/NumPy">NumPy</a> みたいなことを C# でも苦痛なく、かつ、パフォーマンスを損なうことなく実現したいというものです。</p>
<h2><a id="factory">ファクトリ</a></h2>
<p>数値計算に特化した仕様かと言うとそんなこともないので、先に他の用途について触れておきます。</p>
<p>ジェネリックなメソッドを作るとき、<code>new()</code> 制約を付けることで引数なしのコンストラクターなら呼び出せるんですが…</p>
<pre class="source" title="new() 制約">
<code><span class="reserved">void</span> <span class="method">m</span>&lt;<span class="type">T</span>&gt;() <span class="reserved">where</span> <span class="type">T</span> : <span class="reserved">new</span>()
{
    <span class="reserved">var</span> <span class="variable">x</span> = <span class="reserved">new</span> <span class="type">T</span>(); <span class="comment">// OK</span>
}
</code></pre>
<p>ところが、この <code>new</code> には引数を渡せません。</p>
<pre class="source" title="new(X) は書けない">
<code><span class="reserved">void</span> <span class="method">m</span>&lt;<span class="type">T</span>&gt;(<span class="reserved">int</span> <span class="variable">i</span>)
    <span class="reserved">where</span> <span class="type">T</span> : <span class="reserved">new</span>(<span class="reserved">int</span>) <span class="comment">// こう書きたい(ダメ)</span>
{
    <span class="reserved">var</span> <span class="variable">x</span> = <span class="reserved">new</span> T(i); <span class="comment">// ダメ</span>
}
</code></pre>
<p>これを例えば以下のように書けるようにすることで代替できるようになります。</p>
<pre class="source" title="new(X) の代替で T.New(X)">
<code><span class="reserved">void</span> <span class="method">m</span>&lt;<span class="type">T</span>&gt;(<span class="reserved">int</span> <span class="variable">i</span>)
    <span class="reserved">where</span> <span class="type">T</span> : <span class="type">IConvartibleFromInt</span> <span class="comment">// 普通のインターフェイス制約</span>
{
    <span class="reserved">var</span> <span class="variable">x</span> = <span class="type">T</span>.New(<span class="variable">i</span>); <span class="comment">// こう書けるようにする</span>
}

<span class="reserved">interface</span> <span class="type">IConvartibleFromInt</span>
{
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">abstract</span> <span class="type">IConvartibleFromInt</span> <span class="method">New</span>(<span class="reserved">int</span> <span class="variable">i</span>);
}
</code></pre>
<h2><a id="generic-math">generic math</a></h2>
<p>たびたび出てくる要望として、 <code>+</code>, <code>-</code>, <code>*</code>, <code>/</code> をジェネリックな型で使いたいというものがあります。
わかりやすい例だと「<a href="https://source.dot.net/#System.Linq/System/Linq/Sum.cs,17ae8142727f08ee"><code>Enumerable.Sum</code></a> の実装何個あるんだ」って話で。
中身はほぼ定型文で、以下のようなコードのコピペが何個も並んでいます。</p>
<pre class="source" title="Sum">
<code><span class="control">foreach</span> (<span class="reserved">int</span> <span class="variable">v</span> <span class="control">in</span> <span class="variable">source</span>)
{
    <span class="variable">sum</span> += <span class="variable">v</span>;
}
</code></pre>
<p>コピペせざるを得ないのはジェネリックな型に対して <code>+</code> を使えないからです。</p>
<p>業務アプリ開発とかでは大体 <code>int</code> か <code>double</code>、せいぜい <code>decimal</code> を使っておけばいいのでジェネリックじゃなくてもそこまで困らないんですが、
汎用数学ライブラリみたいなのを作ろうとすると結構困ります。
<a href="https://ja.wikipedia.org/wiki/NumPy">NumPy</a> みたいなものの利用者を取り込みたいし、この問題を解決したいという流れ。</p>
<p>現状の C# で汎用数学処理を書こうとするとどうなるかと言うと、以下のような感じ(3年位前のブログ):</p>
<ul>
<li><a href="/blog/2018/5/metricspace/">C# にも型クラス(Shapes)が欲しい…</a></li>
</ul>
<p>ブログタイトルが「型クラス」となっていますが、まあ、それが今回出ている「<a href="https://github.com/dotnet/csharplang/issues/4436">static virtual 提案</a>」の原型。</p>
<ul>
<li><a href="/blog/2017/2/pickuproslyn0223/">Shapes and Extensions</a></li>
</ul>
<p>この「Shapes」というやつは結構込み入った仕様なんですが、
いったんこのうちの一部分というか、既存の文法からそう大きく外れない範囲でできるものが
「インターフェイスの <a href="/study/csharp/oo_static.html">static</a> メソッドに <a href="/study/csharp/oo_polymorphism.html#virtual">virtual</a>/<a href="/study/csharp/oo_abstract.html">abstract</a> を認めよう」というものです。</p>
<p>上記の <code>Sum</code> であれば、「0 を取得」と「足し算」の2つがあれば書けるので、まず以下のようなインターフェイスを用意。</p>
<pre class="source" title="static virtual / static abstract の宣言">
<code><span class="reserved">interface</span> <span class="type">IAddable</span>&lt;<span class="type">T</span>&gt; <span class="reserved">where</span> <span class="type">T</span> : <span class="type">IAddable</span>&lt;<span class="type">T</span>&gt;
{
    <span class="reserved">static</span> <span class="reserved">virtual</span> <span class="type">T</span> Zero { <span class="reserved">get</span>; } =&gt; <span class="reserved">default</span>(<span class="type">T</span>);
    <span class="reserved">static</span> <span class="reserved">abstract</span> <span class="type">T</span> <span class="reserved">operator</span> +(<span class="type">T</span> <span class="variable">t1</span>, <span class="type">T</span> <span class="variable">t2</span>);
}
</code></pre>
<p>これが入るのであれば、標準の <code>int</code> 型(<code>Int32</code> 構造体(<code>System</code> 名前空間))に以下のような実装も足されることになります。</p>
<pre class="source" title="static virtual / static abstract の実装">
<code><span class="reserved">struct</span> <span class="type">Int32</span> : …, <span class="type">IAddable</span>&lt;<span class="type">Int32</span>&gt;
{
    <span class="reserved">static</span> <span class="type">Int32</span> I.<span class="reserved">operator</span> +(<span class="type">Int32</span> x, <span class="type">Int32</span> y) =&gt; x + y; <span class="comment">// Explicit</span>
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">int</span> Zero =&gt; 0;                          <span class="comment">// Implicit</span>
}
</code></pre>
<p>これを使って <code>Sum</code> メソッドを書くと以下のようになります。</p>
<pre class="source" title="static virtual / static abstract の利用">
<code><span class="reserved">public</span> <span class="reserved">static</span> <span class="type">T</span> <span class="method">Sum</span>&lt;<span class="type">T</span>&gt;(<span class="type">T</span>[] <span class="variable">ts</span>) <span class="reserved">where</span> <span class="type">T</span> : <span class="type">IAddable</span>&lt;<span class="type">T</span>&gt;
{
    <span class="type">T</span> <span class="variable">result</span> = <span class="type">T</span>.Zero;                   <span class="comment">// Call static operator</span>
    <span class="control">foreach</span> (<span class="type">T</span> <span class="variable">t</span> <span class="control">in</span> <span class="variable">ts</span>) { <span class="variable">result</span> <span class="method">+=</span> <span class="variable">t</span>; } <span class="comment">// Use `+`</span>
    <span class="control">return</span> <span class="variable">result</span>;
}
</code></pre>
<p>これ、下手な実装をするとパフォーマンスを著しく損ねます。
<code>+</code> なんてネイティブコード化されると CPU の1命令だったりするわけですが、
そこに、インターフェイスが挟まることで仮想関数呼び出しが挟まったり、インライン展開阻害が起きたりして数倍～1桁遅くなります。</p>
<p>とはいえ、<a href="/blog/2018/5/metricspace/">前述の3年前のブログ</a>でやっているような「値型ジェネリクスを使った黒魔術」でパフォーマンスは解決できるんですが、型引数が余分に1個増えたり、演算子を使えなかったり、だいぶ使い勝手は悪いです。</p>
<pre class="source" title="これまでの黒魔術的な回避策">
<code><span class="reserved">public</span> <span class="reserved">static</span> <span class="type">T</span> <span class="method">Sum</span>&lt;<span class="type">T</span>, <span class="type">TAddable</span>&gt;(<span class="type">T</span>[] <span class="variable">ts</span>) <span class="reserved">where</span> <span class="type">TAddable</span> : <span class="type">IAddable</span>&lt;<span class="type">T</span>&gt;
{
    <span class="type">T</span> <span class="variable">result</span> = <span class="reserved">default</span>(<span class="type">TAddable</span>).Zero;
    <span class="control">foreach</span> (<span class="type">T</span> <span class="variable">t</span> <span class="control">in</span> <span class="variable">ts</span>) { <span class="variable">result</span> = <span class="reserved">default</span>(<span class="type">TAddable</span>).Add(<span class="variable">result</span>, <span class="variable">t</span>); }
    <span class="control">return</span> <span class="variable">result</span>;
}
</code></pre>
<h2><a id="type-param">型引数による分岐</a></h2>
<p>普通の、既存の virtual/abstract メソッドの場合、
実際にどのメソッドが呼び出されるかはインスタンスの実行時の型によって決まります。</p>
<pre class="source" title="通常の virtual/abstract は実行時の型によって呼び出し先が決定される">
<code><span class="reserved">using</span> System;
 
<span class="comment">// 型引数が何だろうと、インスタンスが A なので表示されるのは &quot;A&quot;。</span>
<span class="method">m</span>&lt;<span class="type">I</span>&gt;(<span class="reserved">new</span> <span class="type">A</span>());
<span class="method">m</span>&lt;<span class="type">A</span>&gt;(<span class="reserved">new</span> <span class="type">A</span>());
 
<span class="comment">// 型引数が何だろうと、インスタンスが B なので表示されるのは &quot;B&quot;。</span>
<span class="method">m</span>&lt;<span class="type">I</span>&gt;(<span class="reserved">new</span> <span class="type">B</span>());
<span class="method">m</span>&lt;<span class="type">A</span>&gt;(<span class="reserved">new</span> <span class="type">B</span>());
<span class="method">m</span>&lt;<span class="type">B</span>&gt;(<span class="reserved">new</span> <span class="type">B</span>());
 
<span class="reserved">void</span> <span class="method">m</span>&lt;<span class="type">T</span>&gt;(<span class="type">T</span> <span class="variable">x</span>) <span class="reserved">where</span> <span class="type">T</span> : <span class="type">I</span> =&gt; <span class="variable">x</span>.<span class="method">M</span>();
 
<span class="reserved">interface</span> <span class="type">I</span>
{
    <span class="reserved">void</span> <span class="method">M</span>();
}
 
<span class="reserved">class</span> <span class="type">A</span> : <span class="type">I</span>
{
    <span class="reserved">public</span> <span class="reserved">virtual</span> <span class="reserved">void</span> <span class="method">M</span>() =&gt; <span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="string">&quot;A&quot;</span>);
}
 
<span class="reserved">class</span> <span class="type">B</span> : <span class="type">A</span>
{
    <span class="reserved">public</span> <span class="reserved">override</span> <span class="reserved">void</span> <span class="method">M</span>() =&gt; <span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="string">&quot;B&quot;</span>);
}
</code></pre>
<p>一方、static virtual/abstract の場合は型引数を見ます。
コンパイル時に決定済み。
abstract なままのもの(実態がないもの)を使うとコンパイル自体できません。</p>
<pre class="source" title="static virtual/abstract はコンパイル時に渡した型引数で決定される">
<code><span class="reserved">using</span> System;
 
<span class="comment">// static virtual/abstract の場合は型引数の方で呼び出し先が決まる。</span>
<span class="method">m</span>&lt;<span class="type">I</span>&gt;(<span class="reserved">new</span> <span class="type">A</span>()); <span class="comment">// コンパイル エラー。 I.M に実装がない。</span>
<span class="method">m</span>&lt;<span class="type">A</span>&gt;(<span class="reserved">new</span> <span class="type">A</span>()); <span class="comment">// &quot;A&quot;</span>
 
<span class="method">m</span>&lt;<span class="type">I</span>&gt;(<span class="reserved">new</span> <span class="type">B</span>()); <span class="comment">// コンパイル エラー。 I.M に実装がない。</span>
<span class="method">m</span>&lt;<span class="type">A</span>&gt;(<span class="reserved">new</span> <span class="type">B</span>()); <span class="comment">// &quot;A&quot;</span>
<span class="method">m</span>&lt;<span class="type">B</span>&gt;(<span class="reserved">new</span> <span class="type">B</span>()); <span class="comment">// &quot;B&quot;</span>
 
<span class="reserved">void</span> <span class="method">m</span>&lt;<span class="type">T</span>&gt;(<span class="type">T</span> <span class="variable">x</span>) <span class="reserved">where</span> <span class="type">T</span> : <span class="type">I</span> =&gt; <span class="type">T</span>.M();
 
<span class="reserved">interface</span> <span class="type">I</span>
{
    <span class="reserved">public</span> <span class="reserved">abstract</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="method">M</span>();
}
 
<span class="reserved">class</span> <span class="type">A</span> : <span class="type">I</span>
{
    <span class="reserved">public</span> <span class="reserved">override</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="method">M</span>() =&gt; <span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="string">&quot;A&quot;</span>);
}
 
<span class="reserved">class</span> <span class="type">B</span> : <span class="type">A</span>
{
    <span class="reserved">public</span> <span class="reserved">override</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="method">M</span>() =&gt; <span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="string">&quot;B&quot;</span>);
}
</code></pre>
<h2><a id="runtime-mod">型システムの修正</a></h2>
<p>これ、C# コンパイラーのレベルで実現しようと思うと、多分前述の「黒魔術的な構造体ジェネリクス」みたいなコードを生成することになります。
さすがにちょっと「コンパイラーが裏でこっそり生成するコード」にするのもためらわれる(型引数の個数が変わるとかだいぶつらい)レベルです。</p>
<p>なので、.NET ランタイムの型システム自体に手を入れる必要がありました。
実際、型システムに手を入れる(.NET 5 以前では使えない機能になる)方向で実装を進めるそうです。</p>
<p>C# 8.0 くらいから、こういう「古いランタイムでは動かない機能」がちらほら入ってきています。</p>
<ul>
<li>C# 8.0 の<a href="/study/csharp/oo_interface.html?p=5#dim">インターフェイスのデフォルト実装</a>: .NET Core 3.0 以降でだけ動く</li>
<li>C# 9.0 の<a href="/study/csharp/oo_polymorphism.html#covariance">共変戻り値</a>: .NET 5.0 以降でだけ動く</li>
</ul>
<p>(ちなみに、この辺りの一定バージョン以上のランタイムでしか動かない機能については「<a href="/blog/2018/12/runtimefeature/">RuntimeFeature</a>」でちょっと書いています。)</p>
<p>とはいえ、デフォルト実装とか共変戻り値と比べても、static virtual/abstract は実装が難しめの機能になります。</p>
<p>結構な大事なんですが、<a href="https://github.com/migueldeicaza">Miguel de Icaza</a> (<a href="https://ja.wikipedia.org/wiki/Mono_(%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2)">Mono</a> 創設者)が<a href="https://github.com/partydonk/partydonk/">プロトタイプ</a>を作っていて、これをベースに話が進んでいるみたいです。</p>
 ]]></description>
				<pubDate>Sun, 04 Apr 2021 17:07:36 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn: ラムダ式の改善</title>
				<link>http://ufcpp.net/blog/2021/3/lambdaimprovements/</link>
				<description><![CDATA[ <p>ラムダ式、これまでのバージョンでもこまごまと小さい改善があったりしたので今「lambda improvements」と言われてもタイトル的にはインパクト薄そうですが… C# 10.0 向けに結構大きな改善を入れようとしているみたいです。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/pull/4451">Add proposal for lambda improvements #4451</a></li>
</ul>
<h2><a id="background">背景</a></h2>
<p>C# 2.0 で<a href="https://ufcpp.net/study/csharp/sp_delegate.html#definition">メソッドをデリゲート型の変数に代入するときに <code>new</code> が要らなくなった</a>のとか、<a href="https://ufcpp.net/study/csharp/sp_delegate.html#anonymous-method">匿名メソッド式</a>が入り、C# 3.0 で<a href="https://ufcpp.net/study/csharp/sp_delegate.html#lambda">ラムダ式</a>が入って以来、C# 9.0 に至るまでずっと、デリゲートの型推論の向きはずっと<a href="https://ufcpp.net/study/csharp/start/misctyperesolution/#target-type">ターゲット型からの推論</a>になっています。</p>
<p>C# の文法にはソース型からの推論の方が多いので、デリゲート(特にラムダ式)のターゲット型推論の挙動を「何か変」と思う人は多いんじゃないかと思います。
一番多いのは、「以下のコードがコンパイルできないのは変じゃない？」みたいに思うこと。</p>
<pre class="source" title="コンパイルできないことへの不満を目にすることが多いコード">
<code><span class="reserved">var</span> <span class="variable">f</span> = (<span class="reserved">int</span> <span class="variable">x</span>) =&gt; <span class="variable">x</span> * <span class="variable">x</span>;
</code></pre>
<p>大体は、デリゲートが「同じ引数・戻り値でも別の型を作れるし、それらは互いに区別する」という仕様のせい。
ターゲットの方の型が決まらないとラムダ式の型を決定できません。</p>
<pre class="source" title="同じ引数・戻り値で別の型なデリゲート">
<code><span class="reserved">using</span> System;
 
<span class="type">A</span> <span class="variable">a</span> = (<span class="reserved">int</span> <span class="variable">x</span>) =&gt; <span class="variable">x</span> * <span class="variable">x</span>;
<span class="type">B</span> <span class="variable">b</span> = (<span class="reserved">int</span> <span class="variable">x</span>) =&gt; <span class="variable">x</span> * <span class="variable">x</span>;
<span class="type">Func</span>&lt;<span class="reserved">int</span>, <span class="reserved">int</span>&gt; <span class="variable">f</span> = <span class="variable">x</span> =&gt; <span class="variable">x</span> * <span class="variable">x</span>;
 
<span class="comment">// A, B, Func&lt;int, int&gt; は同じ引数、同じ戻り値だけど別の型。</span>
<span class="comment">// 互いに代入不可。</span>
<span class="variable">a</span> = <span class="variable"><span class="error">b</span></span>;
<span class="variable">b</span> = <span class="variable"><span class="error">f</span></span>;
<span class="variable">f</span> = <span class="variable"><span class="error">a</span></span>;
 
<span class="reserved">delegate</span> <span class="reserved">int</span> <span class="type">A</span>(<span class="reserved">int</span> <span class="variable">x</span>);
<span class="reserved">delegate</span> <span class="reserved">int</span> <span class="type">B</span>(<span class="reserved">int</span> <span class="variable">x</span>);
</code></pre>
<p>今でこそ「ターゲット型がわからないときは <code>Func&lt;T, TResult&gt;</code> にすればいいんじゃない？」みたいなことを言われますが…</p>
<p>確かに今なら「できる限りは <code>Func&lt;T, TResult&gt;</code> を使う」みたいな習慣ができていますが、
<code>Func&lt;T, TResult&gt;</code> が標準ライブラリに入ったの自体が C# 3.0 (後付け)だったりするので、
「デフォルトは <code>Func&lt;T, TResult&gt;</code>」というほど盤石な地位かと言うと微妙に悩んだりします。</p>
<p>あと、C# の<a href="https://ufcpp.net/study/csharp/sp2_generics.html">ジェネリクス</a>の制限のせいで、<code>Func</code> には以下の問題もあったりします。</p>
<ul>
<li><code>Func&lt;ref int, readonly ref int&gt;</code> みたいな、<code>ref</code> (参照渡し)な型引数を作れない</li>
<li><code>Func&lt;T1, ..., T16, TResult&gt;</code> みたいな、引数の個数違いを1個1個書く必要があって、標準ライブラリで提供しているものは最大で16引数しかない</li>
</ul>
<p>あと、まあ、ラムダ式の最大の用途である LINQ が「ターゲット型推論だけあれば十分」なのもあります。</p>
<pre class="source" title="LINQ はターゲット型推論が効くのでラムダ式の型決定で困ることがない">
<code><span class="reserved">using</span> System.Linq;
 
<span class="reserved">var</span> <span class="variable">q</span> = <span class="reserved">new</span>[] { 1, 2, 3, 4, 5, 6 }
    .<span class="method">Where</span>(<span class="variable">x</span> =&gt; (<span class="variable">x</span> % 2) == 0) <span class="comment">// ターゲット型推論で Func&lt;int, bool&gt; に決定</span>
    .<span class="method">Select</span>(<span class="variable">x</span> =&gt; <span class="variable">x</span> * <span class="variable">x</span>);      <span class="comment">// ターゲット型推論で Func&lt;int, int&gt; に決定</span>
</code></pre>
<p>一方で、最近、 ASP.NET 方面から「<a href="https://github.com/dotnet/aspnetcore/pull/30556">任意のデリゲートを受け付ける <code>Map</code> メソッドを作りたい</a>」という話が上がっています。</p>
<p>例えば、以下のような短い書き方で所定の URL に対するアクションを登録できるようにしたいそうです。</p>
<pre class="source" title="任意デリゲートを受け付ける ASP.NET Map メソッド">
<code>builder.<span class="method">MapGet</span>(<span class="string">&quot;/&quot;</span>, () =&gt; { });
builder.<span class="method">MapGet</span>(<span class="string">&quot;/category/{c}&quot;</span>, (<span class="reserved">char</span> <span class="variable">c</span>) =&gt; <span class="reserved">char</span>.<span class="method">GetUnicodeCategory</span>(<span class="variable">c</span>));
</code></pre>
<p>C# としてもこの路線は支持したいそうで、
そうなると3点ほどラムダ式に変更を入れたいとのこと。</p>
<ul>
<li>ラムダ式に属性を付けれるようにする</li>
<li>ラムダ式の戻り値を(ターゲット型推論じゃなく、ラムダ式側で)明示できるようにする</li>
<li>(ターゲット型がない時の) ラムダ式の「自然な型」を導入する</li>
</ul>
<h2><a id="attributes">属性</a></h2>
<p><a href="https://ufcpp.net/study/csharp/cheatsheet/ap_ver9/#local-function-attribute">C# 9.0 でローカル関数に属性を付けれるようにした</a>わけで、ラムダ式にも属性を付けれるようにしてもいいんじゃないかという話があります。
あと、同じく C# 9.0 で<a href="https://ufcpp.net/study/csharp/cheatsheet/ap_ver9/#static-anonymous-function">ラムダ式に <code>static</code> を付けても大丈夫だった</a>ので、だったらさらに <code>[]</code> が付いても大丈夫っぽい。</p>
<p>名前通り「式」(どこにでも書ける構文)なのであんまり長いものは書きたくはないですが、
例えば以下のようなコードは十分に「書ける範囲」かと思います。</p>
<pre class="source" title="ラムダ式に属性を付ける例">
<code><span class="variable">app</span>.<span class="method">MapAction</span>([<span class="type">HttpGet</span>(<span class="string">&quot;/&quot;</span>)]() =&gt; <span class="reserved">new</span> <span class="type">Todo</span>(Id: 0, Name: <span class="string">&quot;Name&quot;</span>));
<span class="variable">app</span>.<span class="method">MapAction</span>([<span class="type">HttpPost</span>(<span class="string">&quot;/&quot;</span>)]([<span class="type">FromBody</span>] <span class="type">Todo</span> <span class="variable">todo</span>) =&gt; todo);
</code></pre>
<p>C# 10.0 でこれらを認めたいそうです。</p>
<h2><a id="explicit-returns">明示的な戻り値の型</a></h2>
<p>ラムダ式、C# 3.0 の頃からの構文でも、引数の型は明示できます。
一方で、戻り値の型は常に推論任せだったわけですが、いい加減明示する方法が欲しいそうです。</p>
<p>例えば戻り値の型を明示できなくて困る？例は以下の通り。</p>
<pre class="source" title="戻り値の型を明示できなくて困る例">
<code><span class="reserved">using</span> System;
 
<span class="reserved">var</span> <span class="variable">a</span> = <span class="method">m</span>(<span class="variable">x</span> =&gt; <span class="variable">x</span> * <span class="variable">x</span>, 1); <span class="comment">// これはターゲット型推論任せで int, int に決定。</span>
<span class="reserved">var</span> <span class="variable">b</span> = <span class="error">m</span>((<span class="reserved">short</span> <span class="variable">x</span>) =&gt; <span class="variable">x</span> * <span class="variable">x</span>, 1); <span class="comment">// これが実は型決定できなかったり。</span>
 
<span class="type">T2</span> <span class="method">m</span>&lt;<span class="type">T1</span>, <span class="type">T2</span>&gt;(<span class="type">Func</span>&lt;<span class="type">T1</span>, <span class="type">T2</span>&gt; <span class="variable">f</span>, <span class="type">T1</span> <span class="variable">x</span>) =&gt; <span class="variable">f</span>(<span class="variable">x</span>);
</code></pre>
<p>この例の場合は以下のように型引数を明示することで一応は解決しますが、これが書き心地いいかと言われると微妙な感じ。</p>
<pre class="source" title="型引数を明示して型推論が働くように変更">
<code><span class="reserved">var</span> <span class="variable">b</span> = <span class="method">m</span>&lt;<span class="reserved">short</span>, <span class="reserved">long</span>&gt;(<span class="variable">x</span> =&gt; <span class="variable">x</span> * <span class="variable">x</span>, 1);
</code></pre>
<p>ジェネリクスの場合は型引数の方を明示するという手段を取れますが、
後述する「自然な型」を導入しようと思うと戻り値の型の明示がないと困る場面が出てきます。
ということで、以下のような「引数リストの後ろに <code>: T</code> を書く」という文法で戻り値の型を明示できるようにしたいそうです。</p>
<pre class="source" title="ラムダ式の戻り値の型を明示する例">
<code><span class="reserved">var</span> <span class="variable">b</span> = m((<span class="reserved">short</span> <span class="variable">x</span>) : <span class="reserved">long</span> =&gt; x * <span class="variable">x</span>, 1); <span class="comment">// ラムダ式の戻り値の型を明示的に long にする。</span>
</code></pre>
<h2><a id="natural-type">デリゲートの自然な型</a></h2>
<p>最後が一番大きな変更になるんですが、ラムダ式を <code>var</code>、<code>object</code>、<code>Delegate</code> に代入できるようにするために、
「ターゲット型がわからないときはこの型を選択する」みたいなもの(natural delegate type: デリゲートの自然な型)を決めておくことにするそうです。</p>
<p>候補が搾れる分にはラムダ式やメソッドからデリゲートの型を自動決定。</p>
<p>ラムダ式の例:</p>
<pre class="source" title="ラムダ式の自然な型">
<code><span class="reserved">var</span> <span class="variable">f1</span> = () =&gt; <span class="reserved">default</span>;        <span class="comment">// error: no natural type (決定不能)</span>
<span class="reserved">var</span> <span class="variable">f2</span> = <span class="variable">x</span> =&gt; { };             <span class="comment">// error: no natural type (決定不能)</span>
<span class="reserved">var</span> <span class="variable">f3</span> = <span class="variable">x</span> =&gt; <span class="variable">x</span>;               <span class="comment">// error: no natural type (決定不能)</span>
<span class="reserved">var</span> <span class="variable">f4</span> = () =&gt; 1;              <span class="comment">// System.Func&lt;int&gt;</span>
<span class="reserved">var</span> <span class="variable">f5</span> = () : <span class="reserved">string</span> =&gt; <span class="reserved">null</span>;  <span class="comment">// System.Func&lt;string&gt;</span>
</code></pre>
<p>メソッド グループの例:</p>
<pre class="source" title="メソッド グループの自然な型">
<code><span class="reserved">static</span> <span class="reserved">void</span> <span class="method">F1</span>() { }
<span class="reserved">static</span> <span class="reserved">void</span> <span class="method">F1</span>&lt;<span class="type">T</span>&gt;(<span class="reserved">this</span> <span class="type">T</span> <span class="variable">t</span>) { }
<span class="reserved">static</span> <span class="reserved">void</span> <span class="method">F2</span>(<span class="reserved">this</span> <span class="reserved">string</span> <span class="variable">s</span>) { }
 
<span class="reserved">var</span> <span class="variable">f6</span> = F1;    <span class="comment">// error: multiple methods (F1() と F1&lt;T&gt;(T) の区別が付かない)</span>
<span class="reserved">var</span> <span class="variable">f7</span> = <span class="string">&quot;&quot;</span>.F1; <span class="comment">// System.Action</span>
<span class="reserved">var</span> <span class="variable">f8</span> = F2;    <span class="comment">// System.Action&lt;string&gt;</span>
</code></pre>
<p>で、「自然な型」は以下のように作るそうです。</p>
<ul>
<li><code>System.Action</code> か <code>System.Func</code> を使えるとき(<code>ref</code> とかが付いていなくて16引数以下のとき)はそれを選ぶ</li>
<li>非同期メソッドの場合、戻り値の型は <code>Task</code>/<code>Task&lt;T&gt;</code> (<code>System.Threading.Tasks</code> 名前空間)にする</li>
<li><code>System.Action</code> か <code>System.Func</code> を使えないときは、<a href="https://ufcpp.net/study/csharp/sp3_inference.html#anonymous">匿名型</a>みたいに、 <code>internal</code> な匿名のデリゲートを作る</li>
</ul>
<p>匿名の型を作ってしまうのは、ASP.NET の <code>MapAciton</code> みたいに <code>Delegate</code> に代入して <code>MethodInfo</code> を見て分岐する用途では十分そうです。</p>
<p>一方で、例えば以下のような <code>is</code> 分岐はできないはずなので、この用途には使えません。</p>
<pre class="source" title="引数・戻り値の型が一致していても別デリゲート型になる">
<code><span class="reserved">using</span> System;
 
<span class="comment">// これはターゲット型からの型推論で成り立っているので OK。</span>
<span class="method">a</span>((<span class="reserved">ref</span> <span class="reserved">int</span> <span class="variable">x</span>) =&gt; <span class="reserved">ref</span> <span class="variable">x</span>);
 
<span class="reserved">void</span> <span class="method">a</span>(<span class="type">RefDelegate</span> <span class="variable">d</span>) { }
 
<span class="comment">// C# 10.0 でコンパイルできるようにしたい書き方。</span>
<span class="comment">// この行はコンパイルできるようになる。</span>
<span class="comment">// Func&lt;ref int, ref int&gt; とは書けないので、匿名型が作られる。</span>
b((<span class="reserved">ref</span> <span class="reserved">int</span> <span class="variable">x</span>) =&gt; <span class="reserved">ref</span> <span class="variable">x</span>);
 
<span class="reserved">void</span> <span class="method">b</span>(<span class="type">Delegate</span> <span class="variable">d</span>)
{
    <span class="comment">// (ref int x) =&gt; ref x は匿名のデリゲート型が作られてその型になる。</span>
    <span class="comment">// delegate ref int Anonymous1$(ref int x) みたいな「通常の C# コードでは書けない名前の型」になるはず。</span>
    <span class="comment">// 例え引数・戻り値の型が一致していても、RefDelegate とは違う型なので、is RefDelegate が true になることはない。</span>
    <span class="control">if</span> (<span class="variable">d</span> <span class="reserved">is</span> <span class="type">RefDelegate</span> <span class="variable">r</span>)
    {
    }
}
 
<span class="reserved">delegate</span> <span class="reserved">ref</span> <span class="reserved">int</span> <span class="type">RefDelegate</span>(<span class="reserved">ref</span> <span class="reserved">int</span> <span class="variable">x</span>);
</code></pre> ]]></description>
				<pubDate>Sun, 28 Mar 2021 17:40:12 +0900</pubDate>
			</item>
			<item>
				<title>YouTube で C# がらみのライブ配信初めてました(1年経った)</title>
				<link>http://ufcpp.net/blog/2021/3/ufcpplive/</link>
				<description><![CDATA[ <p>なんか割かし真面目に YouTube で C# ライブ配信するようになってから、気が付けばもう1年経ってるらしい。</p>
<ul>
<li><a href="https://www.youtube.com/channel/UCY-z_9mau6X-Vr4gk2aWtMQ">ufcpp YouTube チャンネル</a></li>
</ul>
<p>元々、「落ち着いたらちゃんとした告知的なものをここのブログでも書きたい」と思ってたら1年経ちました(今ここ)。</p>
<p><a href="https://youtu.be/a5Qs7u6CoqM">始めた当初の頃</a>とか、ノート PC で無線 LAN で配信してましたからね、これ。
諸事情あって。</p>
<p>配信やるようになった経緯もまあ<a href="https://www.youtube.com/watch?v=wEGhEAl4iEg">1回動画にしてますが</a>、そういえばスライドを上げておらず、先ほどようやくアップロード。</p>
<div>
<iframe src="//www.slideshare.net/slideshow/embed_code/key/jjEoEDswPq1VGm" width="595" height="485" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe> <div style="margin-bottom:5px"> <strong> <a href="//www.slideshare.net/ufcpp/youtube-244839075" title="YouTube ライブ配信するようになった話" target="_blank">YouTube ライブ配信するようになった話</a> </strong> </div>
</div>
<h2>ネタの仕入れ</h2>
<p>概ねまあ、以下のスライドに全てが詰まっているわけですが。</p>
<p><img src="/media/1186/interaction.png" alt="オンラインでインタラクションが欲しい" /></p>
<p>「色々と自分の記憶にはあるけども、需要あるのかどうかわからなくて書くモチベーションが湧かない」みたいな「ネタはあるのにネタ切れ」状態だったので、なんかライブ配信でもやってみようかと。</p>
<p>ぶっちゃけて言うと「あれ？ なんか Virtual YouTuber の配信が投稿動画型からライブ配信型に入れ替わってない？」みたいなのに唐突に気づいてしまいまして。
これ、自分が配信を始めた2020年の3月とか、さかのぼって言うと配信しようと考え始めた2020年の正月頃なんですけど、その時点でもすでに“今更な話”(にじさんじとかホロライブとかの大手の「箱」ができてからも1年半～2年経ってるくらいの時期)なんですが。
とりあえず、「チャット欄とほぼリアルタイムで会話しながらゲームしてるのすげぇな」とか、
「雑談配信で2・3時間行けるんだ」とかいうことを自分が認識したのが大体その頃。</p>
<p>そしてその結果、「今の自分に必要なのはこのチャット欄じゃない？」とか思ってライブ配信をすることにしました。
普通はまあ、そんないきなりライブ配信を始めたってチャットなんて付かないんですけども。
幸いまあ、「勉強会を開いてた頃から知った名前」な方からのコメントが結構つきまして、なんとか定着して今に至ります。</p>
<p>今目下の悩みとして「新規層はチャットに入ってきてくれるのか」みたいなのはあるんですが…</p>
<h2>ネタの書き出し</h2>
<p>そしてまあ1年経って。</p>
<p>とりあえずなんかやっとペースみたいなものはつかめてきたかなと。
あんまり頻度多くてもしんどい。
かといってあんまりやらないとなまって再開がしんどい。
折衷案で、「C# 配信かマイクラ作業を垂れ流すだけの配信のどっちかを週1くらいでやる」みたいなところで落ち着けて、C# 配信は2・3週に1回くらいのペース。</p>
<p>(おまけでついてきたマイクラの方はすっかり整地厨に。段差は許さない。)</p>
<p><img src="/media/1187/%E3%81%BF%E3%82%93%E3%82%AF%E3%83%A9ufcpp.jpg" alt="オレ、段差、ユルサナイ" /></p>
<p>話を戻して C# 配信の方、当初目的であるネタの仕入れに関しては期待以上の成果を得ていて、むしろアウトプットが全然できていないみたいな状態になっています。</p>
<p>毎度2・3時間しゃべっておいて自分でいうのもなんですが、
文字に書き残しておきたかったりするネタが多いので、
そういう意味では最終成果物である文字メディアが未完成。</p>
<p>毎回、ライブ配信中に書き捨てたコードを GitHub issue に書き残してるんですが。</p>
<ul>
<li><a href="https://github.com/ufcpp-live/UfcppLiveAgenda/issues">++C++; の中の人が YouTube ライブ配信する際に使ってる配信内容まとめ用リポジトリ。</a></li>
</ul>
<p>このメモ書き issue を掘り起こしてちゃんとしたブログにできそうだなとか思うものが、去年の8月くらいの配信までさかのぼれる状態だったりします。</p>
<p>うちのサイトのブログ、<a href="https://ufcpp.net/blog/2016/">2016年</a>とか<a href="https://ufcpp.net/blog/2018/">2018年</a>とか見てもらうとわかるんですが、「1・2年かけて <a href="https://gist.github.com/">Gist</a> に書き捨ててたコードを発掘するだけで1人アドベントカレンダーができた」みたいな年がちらほらあります。
今、1人 2・3アドベントカレンダー分くらいは書き捨てコード溜まってるんじゃないですかね。</p>
<p>正直、入出力のペースが合っていない(入力過剰)のでさばききれる気もしてないので、
「ご興味がある方はご自由に使ってブログにしてください…」みたいな気持ちにもなっていたりします。</p>
<p>今年、<a href="https://ufcpp.net/study/csharp/cheatsheet/ap_ver9/">C# 9.0 の新機能</a>ページもまだ埋まってない状態ですからねぇ… (<a href="https://github.com/ufcpp/UfcppSample/issues/297">残タスク</a>。まだあと record とか function pointer とかの重たいやつが残ってる。)</p>
<p>当初理念スライドにある「文章メディアはなくならい」の言葉はどこに… (やる気はある)</p>
<h2>おまけで宣伝</h2>
<p>配信中に急に思い付きで言ってみたことを、そのまま<a href="https://twitter.com/xin9le">じんぐるさん</a>に押し付けたやつがありまして。</p>
<p>C# がらみで日本語で話せる Discord サーバー持ちたいとか思って立てたやつがあります。</p>
<ul>
<li><a href="https://discord.gg/kZzNCknB">C# Japan Discord サーバー</a></li>
</ul>
<p>立ててから自分では2か月くらい<a href="https://twitter.com/ufcpp/status/1352923382782652416">告知出す</a>のもやっておらず、ブログを書いてる今に至ってはもう4か月を過ぎているという。</p>
<p>4か月ほどで、今、約700人くらいのサーバーになっています。</p>
 ]]></description>
				<pubDate>Sun, 21 Mar 2021 20:00:10 +0900</pubDate>
			</item>
			<item>
				<title>なんとかしてくれるゼロ幅スペース</title>
				<link>http://ufcpp.net/blog/2021/3/200b/</link>
				<description><![CDATA[ <div>
<iframe width="560" height="315" src="https://www.youtube.com/embed/ZZyyeuEw9SE" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div>
<p><img src="/media/1185/200b-f5.png" alt="２００ｂと打って F5 キー" /></p>
<p>今の Windows の IME は文字コード直打ちから F5 キーを押すことで任意の文字を入力できる機能を持っています。</p>
<p>いつからだろう。 Windows 10 が「新しい Micorsoft IME」になってからだとは思うんですが、気が付けばそんな機能が。
というか、逆に IME パッドはショートカットキーでは出せなくなった？ (右クリック メニューからの選択では出せます。)</p>
<p><a href="https://youtu.be/NqJkCm85CSM?t=6775">昨日の C# ライブ配信中</a>で、「200B だけはよく使う」とおっしゃってる方が要らっしまして。
「ゼロ幅スペースって嫌がらせ以外の用途で使えるの？」、「あえとすさんって実用性ない黒魔術をよく使う人だっけ？」となって「どういう状況で使うんですか？」と聞いた結果が</p>
<p><span style="font-size:200%">「Twitter で ASP.NET をリンクにさせない技」</span></p>
<p>あっ…</p>
<p>それは確かに使うわ…</p>
<p>しかし、文字コード覚えて直打ちする手段に、 F5 なんていうわかりやすいショートカットキーが割当たる時代になったんですねぇ…</p>
<p>追記: その後もうちょっと試して見てる感じ、200B (ゼロ幅スペース)よりも 200D (ZWJ)の方がいいかも。</p>
<div>
<iframe width="560" height="315" src="https://www.youtube.com/embed/A9S2HF0BEDM" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div> ]]></description>
				<pubDate>Sun, 21 Mar 2021 09:53:01 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn: Improved Interpolated Strings</title>
				<link>http://ufcpp.net/blog/2021/3/improvedinterpolatedstrings/</link>
				<description><![CDATA[ <p><a href="https://ufcpp.net/study/csharp/st_string.html#string-interpolation">string interplation</a> の改善するって。</p>
<h2><a id="csharp-6">現行仕様</a></h2>
<p>C# 6.0 から以下のようなコードで <code>string.Format</code> 相当のことができるようになったわけですが。</p>
<pre class="source" title="string interpolation の例">
<code><span class="reserved">var</span> <span class="variable">s</span> = <span class="string">$&quot;(</span>{<span class="variable">a</span>}<span class="string">, </span>{<span class="variable">b</span>}<span class="string">)&quot;</span>;
</code></pre>
<p>これは、以下のように展開されます。</p>
<pre class="source" title="上記コードの展開結果">
<code><span class="reserved">var</span> <span class="variable">s</span> = <span class="reserved">string</span>.<span class="method">Format</span>(<span class="string">&quot;({0}, {1})&quot;</span>, <span class="variable">a</span>, <span class="variable">b</span>);
</code></pre>
<p>これがパフォーマンス的にあんまりよろしくなくて…</p>
<p>特に、<a href="https://ufcpp.net/study/csharp/st_string.html#string-interpolation">冒頭の提案ドキュメント</a>にもある通り、ロギング用途との相性が最悪で、
<a href="https://docs.microsoft.com/ja-jp/dotnet/api/microsoft.extensions.logging.ilogger.log?WT.mc_id=DT-MVP-4028921&amp;view=dotnet-plat-ext-5.0"><code>ILogger</code></a>のメソッドがなかなか使いにくそうな感じの引数になっています。</p>
<pre class="source" title="ILogger.Log メソッドの引数が意味不明な件">
<code><span class="reserved">void</span> <span class="method">Log</span>&lt;<span class="type">TState</span>&gt;(<span class="type">LogLevel</span> <span class="variable">logLevel</span>, <span class="type">EventId</span> <span class="variable">eventId</span>, <span class="type">TState</span> <span class="variable">state</span>, <span class="type">Exception</span> <span class="variable">exception</span>, <span class="type">Func</span>&lt;<span class="type">TState</span>, <span class="type">Exception</span>, <span class="reserved">string</span>&gt; <span class="variable">formatter</span>);
</code></pre>
<p>「<code>formatter</code> でラムダ式を渡して、その中で文字列化」みたいなことをしないといけなくて、結構面倒です。</p>
<p>もちろんこのまま使うのは大変なので <code>LogDebug</code> とか <code>LogTrace</code> とかの拡張メソッドには素直に <code>string</code> を引数として受け取るオーバーロードもあったりするんですが、
それがまた罠というか、パフォーマンスにシビアな場面で使ってしまうと露骨に遅くなるという問題が。</p>
<p>遅くなる原因はいくつかあって、</p>
<ul>
<li>引数(上記の例でいうと <code>a</code> と <code>b</code>)を <code>object</code> で受け取ってしまう。引数が値型の時に<a href="https://ufcpp.net/study/csharp/RmBoxing.html">ボックス化</a>を起こす</li>
<li>引数の数が多いと <a href="https://ufcpp.net/study/csharp/sp_params.html#params"><code>params</code></a> 扱いになって配列の確保も起きる</li>
<li>即時評価なので、実際には不要なものも(ログレベル的に無視する文字列であっても)必ず文字列化される</li>
<li><a href="https://ufcpp.net/study/csharp/resource/span/"><code>Span&lt;T&gt;</code></a> みたいな、C# 7.2 以降、パフォーマンスが重要な場面で多用することになった型を使えない</li>
</ul>
<p>例えば以下のようなコード(一部仮想コードですが)があった場合、</p>
<pre class="source" title="呼ばれ方としてまずいロギング処理">
<code><span class="reserved">using</span> System;
 
<span class="method">Log</span>(<span class="string">$&quot;</span>{<span class="method">DiagnosticMetric</span>()}<span class="string">, </span>{<span class="method">DiagnosticMetric</span>()}<span class="string">, </span>{<span class="method">DiagnosticMetric</span>()}<span class="string">, </span>{<span class="method">DiagnosticMetric</span>()}<span class="string">&quot;</span>);
 
<span class="reserved">string</span> <span class="method">DiagnosticMetric</span>()
{
    <span class="comment">// 診断専用で、日常的に読むには少々重たい値がなにかあるとして</span>
    <span class="control">return</span> その値を返す;
}
 
<span class="reserved">void</span> <span class="method">Log</span>(<span class="reserved">string</span> <span class="variable">message</span>)
{
    <span class="comment">// LogLevel はコンパイル時に確定しない設定ファイルとかから読んだりする想定で</span>
    <span class="control">if</span> (LogLevel &lt; 1) <span class="control">return</span>;
 
    <span class="comment">// もし、たいていの場面では LogLevel 0 で運用してるとここにはほとんど来ない。</span>
    <span class="comment">// 実際には message を読む必要がない。</span>
    <span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="variable">message</span>);
}
</code></pre>
<p>以下のように展開されて処理されます。</p>
<pre class="source" title="string interpolation の展開結果">
<code><span class="comment">// ただでさえ「必要な時にだけ呼びたい」というつもりのメソッドが無条件に呼ばれる。</span>
<span class="reserved">object</span> <span class="variable">tmp1</span> = <span class="method">DiagnosticMetric</span>(); <span class="comment">// int → object に代入しててボックス化。</span>
<span class="reserved">object</span> <span class="variable">tmp2</span> = <span class="method">DiagnosticMetric</span>();
<span class="reserved">object</span> <span class="variable">tmp3</span> = <span class="method">DiagnosticMetric</span>();
<span class="reserved">object</span> <span class="variable">tmp4</span> = <span class="method">DiagnosticMetric</span>();
 
<span class="comment">// params 用の配列が作られる。</span>
<span class="reserved">var</span> <span class="variable">paramsArray</span> = <span class="reserved">new</span> <span class="reserved">object</span>[] { <span class="variable">tmp1</span>, <span class="variable">tmp2</span>, <span class="variable">tmp3</span>, <span class="variable">tmp4</span> };
 
<span class="comment">// こういう文字列リテラルもプログラム中に埋め込まれて {0} とかの部分が無駄と言えば無駄。</span>
<span class="reserved">var</span> <span class="variable">format</span> = <span class="string">&quot;{0}, {1}, {3}, {4}&quot;</span>;
 
<span class="comment">// これも必要性の有無にかかわらず必ず string 生成。</span>
<span class="reserved">var</span> <span class="variable">message</span> = <span class="reserved">string</span>.<span class="method">Format</span>(<span class="variable">format</span>, <span class="variable">paramsArray</span>);
 
<span class="comment">// 作ったはいいけど、 Log の中で、LogLevel 的に使われない。</span>
<span class="method">Log</span>(<span class="variable">message</span>);
</code></pre>
<p><a href="https://ufcpp.net/study/csharp/st_string.html#FormattableString"><code>IFormattable</code> で受け取ると <code>string</code> 生成は遅らせれる</a>仕様はあるんですが、
あんまりカスタマイズ性もなくて、ボックス化とか <code>params</code> 同様の配列の生成は避けれません。</p>
<h2><a id="csharp-next">提案仕様</a></h2>
<p>ということで、以下のように「特定パターンを満たす builder を作って、それの <code>TryFormat</code> メソッドを1個1個呼ぶ」みたいな形に展開できるようにしたいそうです。</p>
<pre class="source" title="builder.TryFormat に展開">
<code><span class="type">Builder</span>.<span class="method">GetInterpolatedStringBuilder</span>(<span class="variable">baseLength</span>: 6, <span class="variable">formatHoleCount</span>: 4, <span class="reserved">out</span> <span class="reserved">var</span> <span class="variable">builder</span>);
<span class="reserved">_</span> = <span class="variable">builder</span>.<span class="method">TryFormat</span>(<span class="method">DiagnosticMetric</span>())
    &amp;&amp; <span class="variable">builder</span>.<span class="method">TryFormat</span>(<span class="string">&quot;, &quot;</span>)
    &amp;&amp; <span class="variable">builder</span>.<span class="method">TryFormat</span>(<span class="method">DiagnosticMetric</span>())
    &amp;&amp; <span class="variable">builder</span>.<span class="method">TryFormat</span>(<span class="string">&quot;, &quot;</span>)
    &amp;&amp; <span class="variable">builder</span>.<span class="method">TryFormat</span>(<span class="method">DiagnosticMetric</span>())
    &amp;&amp; <span class="variable">builder</span>.<span class="method">TryFormat</span>(<span class="string">&quot;, &quot;</span>)
    &amp;&amp; <span class="variable">builder</span>.<span class="method">TryFormat</span>(<span class="method">DiagnosticMetric</span>())
    ;
</code></pre>
<p><code>&amp;&amp;</code> でつないでいるので、1個目で <code>false</code> を返せばもう2個目以降は呼ばれないという実装。
<code>TryFormat</code> にちゃんとしたオーバーロードを増やせば「<code>object</code> を介するせいでボックス化」も避けれます。</p>
<p>「ログレベルに応じて即 <code>false</code> を返す」みたいなのも、以下のような実装でできるようにしたいみたいです。</p>
<p>まず、<code>Logger</code> 自体の定義。
<code>LogTrace</code> メソッドの引数を「特定パターンを満たす builder」にします(この例の場合 <code>TraceLoggerParamsBuilder</code> 型)。</p>
<pre class="source" title="想定している Logger の作り方">
<code><span class="reserved">public</span> <span class="reserved">class</span> <span class="type">Logger</span>
{
    <span class="comment">// どこかで設定</span>
    <span class="reserved">public</span> <span class="type">LogLevel</span> EnabledLevel;
 
    <span class="comment">// TraceLoggerParamsBuilder の作りは後述。TryFormat とかを持ってる型</span>
    <span class="reserved">public</span> <span class="reserved">void</span> <span class="method">LogTrace</span>(<span class="type">TraceLoggerParamsBuilder</span> <span class="variable">builder</span>)
    {
        <span class="comment">// TraceLoggerParamsBuilder から文字列を取り出してログ取りする。</span>
    }
}
</code></pre>
<p>これで、以下のようなコードを書いたとして、</p>
<pre class="source" title="logger.LogTrace 利用例">
<code><span class="type">Logger</span> <span class="variable">logger</span> = GetLogger(<span class="type">LogLevel</span>.Info);
<span class="variable">logger</span>.LogTrace(<span class="string">$&quot;</span>{<span class="string">&quot;this&quot;</span>}<span class="string"> will never be printed because info is &lt; trace!&quot;</span>);
</code></pre>
<p><code>logger.LogTrace</code> の行は以下のように展開するそうです。</p>
<pre class="source" title="logger.LogTrace の展開結果">
<code><span class="reserved">var</span> <span class="variable">receiverTemp</span> = <span class="variable">logger</span>;
<span class="type">TraceLoggerParamsBuilder</span>.<span class="method">GetInterpolatedStringBuilder</span>(<span class="variable">baseLength</span>: 47, <span class="variable">formatHoleCount</span>: 1, <span class="variable">receiverTemp</span>, <span class="reserved">out</span> <span class="reserved">var</span> <span class="variable">builder</span>);
<span class="reserved">_</span> = <span class="variable">builder</span>.<span class="method">TryFormat</span>(<span class="string">&quot;this&quot;</span>) &amp;&amp; <span class="variable">builder</span>.<span class="method">TryFormat</span>(<span class="string">&quot; will never be printed because info is &lt; trace!&quot;</span>);
<span class="variable">receiverTemp</span>.<span class="method">LogTrace</span>(<span class="variable">builder</span>);
</code></pre>
<p>ログレベルを伝搬できるように、<code>Logger</code> のインスタンスも <code>GetInterpolatedStringBuilder</code> メソッド(builder のファクトリメソッド)に渡せるようにするとのこと。</p>
<p><code>TraceLoggerParamsBuilder</code> 型は最低ライン以下のように作ります。</p>
<pre class="source" title="ログレベルに応じて必要な時だけ文字列書き込みする builder の例">
<code><span class="reserved">public</span> <span class="reserved">struct</span> <span class="type">TraceLoggerParamsBuilder</span>
{
    <span class="reserved">bool</span> _logLevelEnabled;
 
    <span class="reserved">internal</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="method">GetInterpolatedStringBuilder</span>(<span class="reserved">int</span> <span class="variable">baseLength</span>, <span class="reserved">int</span> <span class="variable">formatHoleCount</span>, <span class="type">Logger</span> <span class="variable">logger</span>, <span class="reserved">out</span> <span class="type">TraceLoggerParamsBuilder</span> <span class="variable">builder</span>)
    {
        <span class="comment">// 実際は baseLength, formatHoleCount とかも使って初期サイズを決定したバッファーとかも作る想定。</span>
        <span class="comment">// とりあえず「レベルが合わないログは無視」のためのコードのみ例示。</span>
        <span class="variable">builder</span> = <span class="reserved">new</span> <span class="type">TraceLoggerParamsBuilder</span> { _logLevelEnabled = <span class="variable">logger</span>.EnabledLevel &lt;= <span class="type">LogLevel</span>.Trace };
    }
 
    <span class="reserved">public</span> <span class="reserved">bool</span> <span class="method">TryFormat</span>(<span class="reserved">string</span> <span class="variable">message</span>)
    {
        <span class="control">if</span> (!_logLevelEnabled) <span class="control">return</span> <span class="reserved">false</span>;
 
        <span class="comment">// バッファーへの文字列書き込み</span>
 
        <span class="control">return</span> <span class="reserved">true</span>;
    }
}
</code></pre>
<h3><a id="overload">オーバーロード解決</a></h3>
<p><code>$&quot;&quot;</code> を渡すときに限り、<code>string</code> のオーバーロードよりも、「特定のパターンを満たす builder」型の方の優先度を高くするそうです。
しかも、<code>$&quot;&quot;</code> がリテラルに展開されい場合だけ。
以下のような挙動になります。</p>
<pre class="source" title="オーバーロード解決">
<code><span class="reserved">void</span> <span class="method">Log</span>(<span class="reserved">string</span> <span class="variable">s</span>) { ... }
<span class="reserved">void</span> <span class="method">Log</span>(<span class="type">TraceLoggerParamsBuilder</span> <span class="variable">p</span>) { ... }
 
<span class="method">Log</span>(<span class="string">$&quot;test&quot;</span>); <span class="comment">// {} を含んでないので $ が付かない &quot;test&quot;と同じ扱い → Log(string) の方が呼ばれる</span>
<span class="method">Log</span>(<span class="string">$&quot;</span>{<span class="string">&quot;test&quot;</span>}<span class="string">&quot;</span>); <span class="comment">// {} の中身が文字列定数なのでコンパイル時に &quot;test&quot; に展開される → Log(string)</span>
<span class="method">Log</span>(<span class="string">$&quot;</span>{1}<span class="string">&quot;</span>); <span class="comment">// コンパイル時の展開が利かない文字列補間 → Log(TraceLoggerParamsBuilder) 扱いで TryFormat に展開</span>
</code></pre>
<h3><a id="InterpolatedStringBuilder">InterpolatedStringBuilder</a></h3>
<p><a href="https://ufcpp.net/study/csharp/resource/span/"><code>Span&lt;T&gt;</code></a> と <a href="https://github.com/dotnet/runtime/blob/79ae74f5ca5c8a6fe3a48935e85bd7374959c570/src/libraries/System.Private.CoreLib/src/System/Buffers/ArrayPool.cs"><code>ArrayPool</code></a> ベースでパフォーマンスが出るように作った builder を標準提供したいそうです。</p>
<p>現状、<code>InterpolatedStringBuilder</code> という名前で提案されています。</p>
<p>で、<code>string.Format</code> にも以下のオーバーロードを追加。</p>
<pre class="source" title="string.Format(InterpolatedStringBuilder)">
<code><span class="reserved">public</span> <span class="reserved">class</span> <span class="type">String</span>
{
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">string</span> <span class="method">Format</span>(<span class="type">InterpolatedStringBuilder</span> <span class="variable">builder</span>) =&gt; <span class="variable">builder</span>.<span class="method">ToString</span>();
}
</code></pre>
<p>これで、通常の <code>var s = $&quot;{x}, {y}&quot;;</code> みたいな string interpolation も <code>InterpolatedStringBuilder</code> に対する <code>TryFormat</code> に展開されるようになるとのこと。</p>
<h3><a id="other">その他、考慮する点</a></h3>
<p>その他、以下のような話も。</p>
<ul>
<li>builder 自体、キャッシュしたインスタンスを使いまわすことを考慮してコンストラクターにはしない (<code>GetInterpolatedStringBuilder</code> メソッドを介する)</li>
<li><code>bool TryFormat</code> だけじゃなくて <code>void Format</code> も認めるかどうか</li>
<li><code>stackalloc</code> を使ってバッファーでもヒープ アロケーションを完全になくす案</li>
<li><code>Utf8Formatter</code> みたいにそもそも書き込み先を <code>Span&lt;byte&gt;</code> にする案</li>
<li>パフォーマンスを考えると builder は <a href="https://ufcpp.net/study/csharp/resource/refstruct/"><code>ref struct</code></a> になるはずで、だったら非同期メソッド内での利用に制限がかかりそう</li>
</ul>
<h2><a id="conclusion">まとめ</a></h2>
<p>文字列処理、やればやるほど「<a href="https://github.com/ufcpp/StringLiteralGenerator/blob/master/src/StringLiteralGenerator/Utf8StringLiteralGenerator.cs"><code>StringBuilder.Append</code> 直呼びするしかない…</a>」みたいな気持ちになることが多々あるんですが、それがだいぶ解消されそうです。</p>
<p>そこそこ複雑な仕様になっていますが、
現状の <a href="https://docs.microsoft.com/ja-jp/dotnet/api/microsoft.extensions.logging.ilogger.log?WT.mc_id=DT-MVP-4028921&amp;view=dotnet-plat-ext-5.0"><code>ILogger</code></a> の <code>Log</code> メソッドの実装のしにくさを考えるとだいぶマシかなという感じ。</p>
 ]]></description>
				<pubDate>Sat, 20 Mar 2021 20:47:11 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn: using がらみ (using エイリアスの改善と global using)</title>
				<link>http://ufcpp.net/blog/2021/3/usingimprovements/</link>
				<description><![CDATA[ <p>今日も「C# Language Design Meeting 議事録」の中から1個1個機能紹介。</p>
<p>今日は<a href="https://github.com/dotnet/csharplang/blob/main/meetings/2021/LDM-2021-02-10.md#global-usings">2/10</a>、<a href="https://github.com/dotnet/csharplang/blob/main/meetings/2021/LDM-2021-02-22.md#using-alias-improvements">2/22</a>辺りの話になります。</p>
<p><a href="https://ufcpp.net/study/csharp/sp_namespace.html#using">using</a>がらみに色々更新が掛かるみたいです。
大まかに2点。</p>
<ul>
<li>using エイリアス改善: これまで書けてもよさそうなのに書けないエイリアスを書けるようにする</li>
<li>global using: プロジェクト全域に対して有効な <code>using</code> ディレクティブ</li>
</ul>
<p><a href="https://github.com/dotnet/csharplang/blob/main/proposals/GlobalUsingDirective.md">global using の方は提案ドキュメントが merge 済み</a>、
<a href="https://github.com/dotnet/csharplang/pull/4452">using エイリアスの話はレビュー中</a>です。</p>
<h2>using エイリアス改善</h2>
<p>これも細かく言うと3点。</p>
<ul>
<li>キーワードになってる型を直接使えるようにする</li>
<li>配列の <code>[]</code>、nullable の <code>?</code>、ポインターの <code>*</code>、タプルとかを使えるようにする</li>
<li>型引数を持てるようにする</li>
</ul>
<p>今でも OK なパターンだと以下のような書き方ができます。</p>
<pre class="source" title="これは C# 1.0 の頃から書ける">
<code><span class="reserved">using</span> <span class="type">Ok1</span> = System.<span class="type">Int32</span>;
<span class="reserved">using</span> <span class="type">Ok2</span> = System.<span class="type">Nullable</span>&lt;<span class="reserved">int</span>&gt;;
</code></pre>
<p>ところが以下のようなやつは現状ではコンパイル エラー。
ジェネリック型引数の中なら <code>int</code> を書けるのに、直接は書けない。</p>
<pre class="source" title="using エイリアスの右辺にキーワードは直接書けない">
<code><span class="reserved">using</span> Ng1 = <span class="reserved"><span class="type">int</span></span>;
<span class="reserved">using</span> Ng2 = <span class="reserved"><span class="type">int</span></span>?;
</code></pre>
<p>以下のようなやつもコンパイル エラー。
配列の <code>[]</code>、nullable の <code>?</code>、ポインターの <code>*</code>は現状書けません。</p>
<pre class="source" title="? [] * も付けれない">
<code><span class="reserved">using</span> <span class="type">Ng3</span> = System.<span class="type">Int32</span><span class="error">?</span>;
<span class="reserved">using</span> Ng4 = System.Int32<span class="error">[]</span>;
<span class="reserved">using</span> Ng5 = System.Int32<span class="error">*</span>;
</code></pre>
<p>あと、頻出で出ている要望がタプルで、
以下のようなやつも「書きたいのに書けない」筆頭です。</p>
<pre class="source" title="タプルのエイリアスを作りたいという要望は頻出">
<code><span class="reserved">using</span> Ng6 = (<span class="error">System.<span class="type">Int32</span></span>, <span class="error">System.<span class="type">String</span></span>); <span class="comment">// これがダメな時点でお察しだけど…</span>
<span class="reserved">using</span> Ng7 = (<span class="reserved"><span class="error">int</span></span>, <span class="reserved"><span class="error">string</span></span>); <span class="comment">// ほんとに書きたいのはこうだし、</span>
<span class="reserved">using</span> Ng8 = <span class="error">(<span class="reserved">int</span> <span class="variable">id</span>, <span class="reserved">string</span> <span class="variable">name</span>)</span>; <span class="comment">// 名前付きタプルも書きたい。</span>
</code></pre>
<p>この辺り、C# 10.0 でまとめて解消しようという感じになっています。
ちなみに、似たような話だと、<code>enum</code> の基底にキーワードを書けるかどうかみたいなのが C# 6.0 の時に変わっています。</p>
<pre class="source" title="enum の基底に int を書けるかどうかも C# 6.0 からの変更">
<code><span class="comment">// これなら C# 1.0 の頃から書けた。</span>
<span class="reserved">enum</span> <span class="type">A</span> : System.<span class="type">Int32</span> { }
 
<span class="comment">// これが書けるようになったのは C# 6.0 から。</span>
<span class="reserved">enum</span> <span class="type">B</span> : <span class="reserved">int</span> { }
</code></pre>
<p>タプルのエイリアスを付けれるようにしようとなると、まあ、「ジェネリックなエイリアス」も作りたくなります。
これもこの際、C# 10.0 で一緒にやるそうです。</p>
<pre class="source" title="ジェネリックなエイリアス">
<code><span class="reserved">using</span> <span class="error">Fix2&lt;T&gt;</span> = (T, T);
<span class="reserved">using</span> <span class="error">Fix3&lt;T&gt;</span> = (T, T, T);
<span class="reserved">using</span> <span class="error">Fix4&lt;T&gt;</span> = (T, T, T, T);
</code></pre>
<p>もちろんタプル以外の「ジェネリックなエイリアス」も同じく C# 10.0 で取り組み。</p>
<pre class="source" title="タプル以外のエイリアスものもジェネリックにしたい">
<code><span class="reserved">using</span> Option&lt;T&gt; = T ?;
</code></pre>
<p>「部分適用」もできるようにしたいみたいです。
以下のような、「2引数のうち片方だけ確定」みたいな「ジェネリックなエイリアス」も作れるようにする予定です。</p>
<pre class="source" title="部分適用なジェネリック エイリアス">
<code><span class="reserved">using</span> StringDictionary&lt;T&gt; = System.Collections.Generic.<span class="type">Dictionary</span>&lt;<span class="reserved">string</span>, T&gt;;
</code></pre>
<p>arity (型引数の数)違いのエイリアスは並べられるようにする予定だそうです。</p>
<pre class="source" title="arity 違いのエイリアスも OK になる予定">
<code><span class="reserved">using</span> <span class="type">MyDictionary</span> = System.Collections.Generic.<span class="type">Dictionary</span>&lt;<span class="reserved">string</span>, <span class="reserved">string</span>&gt;;
<span class="reserved">using</span> MyDictionary&lt;T&gt; = System.Collections.Generic.<span class="type">Dictionary</span>&lt;<span class="reserved">string</span>, T&gt;;
<span class="reserved">using</span> MyDictionary&lt;T1, T2&gt; = System.Collections.Generic.<span class="type">Dictionary</span>&lt;T1, T2&gt;;
</code></pre>
<p>ちなみに、以下のようなオープン ジェネリック(引数なしの状態)は C# 10.0 でも書けません。</p>
<pre class="source" title="これは C# 10.0 でもダメ">
<code><span class="comment">// これは引き続き今後もダメ。</span>
<span class="comment">// 空っぽの &lt;&gt; が許されるのは typeof(T&lt;&gt;) だけ</span>
<span class="reserved">using</span> <span class="type">OpenGeneric</span> = System.Collections.Generic.<span class="error"><span class="type">List</span>&lt;&gt;</span>;
</code></pre>
<p>これをやるうえでちょっと悩ましいのが、「制約違反」みたいなのをどこで判定するか。
選択肢は2つあって、1つ目はエイリアスを作る時点 (<code>using T = ...;</code> の行) でエラーにする方法。
エイリアスを「実際にある型」に近い扱いにしようという感じ。
(現状あんまり乗り気ではなさげ。)</p>
<pre class="source" title="選択肢1: エイリアス自体に where 制約">
<code><span class="reserved">using</span> Optional&lt;T&gt; = <span class="type">Nullable</span>&lt;<span class="error">T</span>&gt;; <span class="comment">// 「T に制約が付いてないのでダメ」扱いする</span>
<span class="reserved">using</span> Optional&lt;T&gt; = <span class="type">Nullable</span>&lt;T&gt; <span class="variable">where</span> T : <span class="reserved">struct</span> <span class="comment">// と言うことはここに型制約(where)を書けるようにする必要あり</span>
</code></pre>
<p>もう1つの選択肢は、「エイリアスの時点では素通し」で、現状、こっちが有力みたいです。
「エイリアスはあくまでエイリアス」で、C 言語のマクロっぽい挙動というか。</p>
<pre class="source" title="エイリアスの時点では素通し">
<code><span class="reserved">using</span> Optional&lt;T&gt; = <span class="type">Nullable</span>&lt;T&gt;; <span class="comment">// この時点では T のチェックしない。</span>
 
<span class="comment">// Nullable&lt;string&gt; とは書けないので、そのエイリアスの Optional&lt;string&gt; もダメ。</span>
<span class="reserved">void</span> <span class="method">m</span>(Optional&lt;<span class="reserved"><span class="error">string</span></span>&gt; <span class="variable">opt</span>) { }
</code></pre>
<p>後者が有力なので、<code>using A&lt;T&gt; = T?;</code> が <a href="https://ufcpp.net/study/csharp/sp2_nullable.html">null 許容値型</a>になるか、
<a href="https://ufcpp.net/study/csharp/resource/nullablereferencetype/">null 許容参照型</a>になるか、
<a href="https://ufcpp.net/study/csharp/resource/nullablereferencetype/?p=3#unconstrained-generics">defaultable</a>になるかはおそらく利用側次第になります。</p>
<h2>global using</h2>
<p>プロジェクト全域に影響を及ぼす <code>using</code> ディレクティブを書きたいという要望も昔からちらほらあります。</p>
<p>これはまあ、「全域に影響を及ぼす」ってのが怖くてやってなかっただけなんですが、
それももう今更なのかなぁという感じになっています。
と言うのも、</p>
<ul>
<li><a href="https://ufcpp.net/study/csharp/resource/nullablereferencetype/">null 許容参照型</a>は <code>&lt;Nullable&gt;enable&lt;/Nullable</code> オプションを与えるとプロジェクト全体で有効・無効が切り替わる</li>
<li><a href="https://ufcpp.net/study/csharp/cheatsheet/ap_ver9/#skip-locals-init">SkipLocalsInit</a> は <code>[module:SkipLocalsInit]</code> と書けばプロジェクト全体に影響を及ぼせる</li>
</ul>
<p>みたいな文法がすでにあります。</p>
<p>あと、 ASP.NET なプロジェクトを作るとテンプレート内に <code>_ViewImports.cshtml</code> っていうのが最初から存在しますが、その中身は以下のようになっています。</p>
<pre class="source" title="テンプレート通りの _ViewImports.cshtml">
<code><span style="background:yellow;">@</span><span class="reserved">using</span> WebApplication1
<span style="background:yellow;">@</span><span class="reserved">using</span> WebApplication1.Models
<span style="background:yellow;">@addTagHelper</span> <span class="string">*, Microsoft.AspNetCore.Mvc.TagHelpers
</span>
</code></pre>
<p>これ、やってることはまさに「プロジェクト中のすべての cshtml に影響を及ぼす <code>using</code>」になります。</p>
<p>あと例えば、最近の <a href="https://docs.microsoft.com/en-us/dotnet/csharp/tour-of-csharp/tutorials/hello-world?tutorial-step=1">C# 公式チュートリアル</a>では、普通に以下のコードがコンパイルできたりします。
どうも、暗黙的に、<code>System</code>、<code>System.Linq</code>、<code>System.Collections.Generic</code> 辺りがデフォルトで <code>using</code> されていそうな雰囲気。</p>
<pre class="source" title="C# 公式チュートリアルではなぜか using System; が要らない">
<code><span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="string">&quot;Hello World!&quot;</span>);
</code></pre>
<p>ちなみに、現時点での実装はどうも「ごり押し」っぽい雰囲気があります。
<a href="https://www.youtube.com/watch?v=yDrQ2nCPfR8&amp;t=4338s">Visual Studio Users Community Japan 勉強会 #6 質疑応答枠 1:12:18～</a>で話したことがあるですが、
おそらく、「書いたコードの前に以下のコードを追加」みたいな実装になっていると思います。</p>
<pre class="source" title="テンプレコードを string.Concat してからコンパイルしてると思う、たぶん">
<code><span class="reserved">using</span> System;
<span class="reserved">using</span> System.Linq;
<span class="reserved">using</span> System.Collections.Generic;
 
<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> <span class="method">Main</span>()
    {
</code></pre>
<p>相当に気持ち悪い実装ですが、
こんな気持ち悪いことをしてまで、「<code>using</code> はおまじない」を消したいという状態になっています。</p>
<p>だったら認めようと。</p>
<p>問題は実現方法なんですが、これも初期案としては2案出ていました。</p>
<ul>
<li><code>&lt;Nullable&gt;enable&lt;/Nullable&gt;</code> みたいに、C# コンパイラーに渡すオプション/csproj ファイルに書く設定として提供</li>
<li>C# ソースコード中に <code>global using N = int;</code> みたいなのを書けるようにする</li>
</ul>
<p>ちなみに、後者が有力になっています。<code>global using N = int;</code> 支持になっているのは以下のような理由。</p>
<ul>
<li>Source Generator で使う場合に C# コードで書ける方が助かる</li>
<li>dotnet コマンドから csc (C# コンパイラー)に素通ししてあげないといけないオプションがすでに大量にあってあんまりもう増やしたくない</li>
<li>「global using が欲しい」という要望も長年ずっと出続けてる</li>
</ul>
<p>で、後は文法なわけですが、<code>global using</code> で行くみたいです。</p>
<pre class="source" title="global using ディレクティブ">
<code><span class="reserved">global</span> <span class="reserved">using</span> System;
<span class="reserved">global</span> <span class="reserved">using</span> System.Linq.<span class="type">Enumerable</span>;
<span class="reserved">global</span> <span class="reserved">using</span> System.Collections.Generic;
<span class="reserved">global</span> <span class="reserved">using static</span> System.Linq.<span class="type">Enumerable</span>;
</code></pre>
<p>まあ、迷うとしたら語順くらいですかね。
普通に <code>global</code> という単語を名前空間にもクラス名にも使えてしまうので、<code>using global</code> だと「キーワードの <code>global</code> か名前空間の <code>global</code> か」の弁別が大変だそうで。</p>
<pre class="source" title="global も文脈キーワード">
<code><span class="reserved">using</span> global;
 
<span class="reserved">namespace</span> global
{
    <span class="reserved">class</span> <span class="type">global</span> { }
}
</code></pre>
<p>あと、さすがにファイル中散り散りに「プロジェクト全体に影響あり」なものが書かれるのは怖いということで、
<code>global using</code> を書けるのはファイルの先頭(普通の <code>using</code> ディレクティブよりも前)だけにするみたいです。</p>
 ]]></description>
				<pubDate>Mon, 15 Mar 2021 01:02:08 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn: 分解時の宣言と変数の混在</title>
				<link>http://ufcpp.net/blog/2021/3/mix-deconstruction/</link>
				<description><![CDATA[ <p><a href="https://devblogs.microsoft.com/dotnet/announcing-net-6-preview-1/">.NET 6 Preview 1</a>とか <a href="https://devblogs.microsoft.com/visualstudio/vs2019-v16-9-and-v16-10-preview-1/">Visual Studio 16.9 正式版＆ 16.10 Preview 1</a>とかが出ましたね。</p>
<p>というの、ライブ配信はしてたんですが。</p>
<div>
<iframe width="560" height="315" src="https://www.youtube.com/embed/y7kqEYov5ro" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div>
<div>
<iframe width="560" height="315" src="https://www.youtube.com/embed/99ek2n6F_1U" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div>
<p>その中で、今日は C# 10.0 候補で、すでに Visual Studio 16.10 にマージ済みの機能の紹介。
以下のようなコードがコンパイルできるようになっています。</p>
<pre class="source" title="宣言と変数の混在分解">
<code><span class="reserved">int</span> <span class="variable">x</span>;
(<span class="variable">x</span>, <span class="reserved">var</span> <span class="variable">y</span>) = (1, <span class="string">&quot;abc&quot;</span>);
</code></pre>
<p>配信では言ってるんですが、 .NET 6 Preview 1 が出た時点で、コマンドライン (dotnet コマンド)ではコンパイルできていました。
「今回、.NET SDK と Visual Studio で2週間くらいリリースタイミング違うんですね」とか「Visual Studio は <a href="https://myignite.microsoft.com/home">Ignite</a> のために取っといたんですかね」とかいう感じ。</p>
<p>で、Visual Studio の方は、16.10 の方で「<a href="https://ufcpp.net/study/csharp/cheatsheet/langversionoption/#langversion">LangVersion preview</a>」にした時だけ上記コードがコンパイルできます。</p>
<h2><a id="deconstruction">分解(C# 7.0)</a></h2>
<p><a href="https://ufcpp.net/study/csharp/datatype/deconstruction/">分解</a>という機能自体は C# 7.0 の頃に入っています。
以下のようなコード、どれも C# 7.0 として有効。</p>
<p>1つ目。<code>()</code> 内で変数宣言。</p>
<pre class="source" title="() 内で変数宣言">
<code>(<span class="reserved">int</span> <span class="variable">x</span>, <span class="reserved">string</span> <span class="variable">y</span>) = (1, <span class="string">&quot;abc&quot;</span>);
</code></pre>
<p>2つ目。これを型推論(var)で書いたもの。型推論してる点以外は1つ目のコードと同じ。コンパイラーの解釈結果は全く同じです。</p>
<pre class="source" title="() 内で変数宣言 (`var` 利用)">
<code>(<span class="reserved">var</span> <span class="variable">x</span>, <span class="reserved">var</span> <span class="variable">y</span>) = (1, <span class="string">&quot;abc&quot;</span>);
</code></pre>
<p>3つ目。タプル変数宣言。頭に1個だけ <code>var</code> を書いて、複数の変数の宣言をまとめてやる構文。</p>
<pre class="source" title="タプル変数宣言">
<code><span class="reserved">var</span> (<span class="variable">x</span>, <span class="variable">y</span>) = (1, <span class="string">&quot;abc&quot;</span>);
</code></pre>
<p>4つ目。既存の変数を使って分解。</p>
<pre class="source" title="既存の変数を使って分解">
<code><span class="reserved">int</span> <span class="variable">x</span>;
<span class="reserved">string</span> <span class="variable">y</span>;
(<span class="variable">x</span>, <span class="variable">y</span>) = (1, <span class="string">&quot;abc&quot;</span>);
</code></pre>
<h2><a id="mix-deconstruction">混在分解(C# 10.0)</a></h2>
<p>で、これの実装時点で、変数宣言と既存変数の混在についても検討はされていました。
「何か地雷を踏みそうで怖い」みたいな感じで「後でやる」扱い。</p>
<p>それが今回、16.10 Preview 1 でマージされました。
以下のコードが通ります。</p>
<pre class="source" title="変数宣言と既存変数が混在した分解">
<code><span class="reserved">int</span> <span class="variable">x</span>;
(<span class="variable">x</span>, <span class="reserved">string</span> <span class="variable">y</span>) = (1, <span class="string">&quot;abc&quot;</span>);
</code></pre>
<p>変数宣言には <code>var</code> も使えて、それが冒頭のコードになります。</p>
<pre class="source" title="変数宣言と既存変数が混在した分解(var 型推論あり)">
<code><span class="reserved">int</span> <span class="variable">x</span>;
(<span class="variable">x</span>, <span class="reserved">var</span> <span class="variable">y</span>) = (1, <span class="string">&quot;abc&quot;</span>);
</code></pre>
<p>欲しいかと言われると微妙なライン… と感じますが、
実装負担がほとんどなかったみたいですね。</p>
<p>「あえてエラーにしてたけど、そのあえてエラーにする行を消すだけで動く」というレベルだったみたいで。
コミュニティ(C# チームの外の人)から「<a href="https://github.com/dotnet/roslyn/pull/44476">エラー行を消して、テストを足しといたよ</a>」っていう pull request が出ていました。</p>
<p>pull request をみるに、式ステートメントと <code>for</code> の初期化式(1項目)中でだけ認めるみたいです。</p>
<pre class="source" title="宣言と変数の混在分解ができる場所">
<code><span class="reserved">int</span> <span class="variable">x</span>;
 
<span class="comment">// OK な例1</span>
(<span class="variable">x</span>, <span class="reserved">string</span> <span class="variable">y1</span>) = (1, <span class="string">&quot;abc&quot;</span>);
 
<span class="comment">// OK な例2</span>
<span class="control">for</span> ((<span class="variable">x</span>, <span class="reserved">string</span> <span class="variable">y2</span>) = (1, <span class="string">&quot;abc&quot;</span>); <span class="reserved">false</span>;)
{
}
 
<span class="comment">// ダメな例1</span>
<span class="reserved">var</span> <span class="variable">t</span> = (<span class="variable">x</span>, <span class="reserved">string</span> <span class="variable">y3</span>) = (1, <span class="string">&quot;abc&quot;</span>);
 
<span class="comment">// ダメな例2</span>
<span class="method">m</span>(<span class="reserved">out</span> (<span class="variable">x</span>, <span class="reserved">string</span> <span class="variable">y4</span>));
<span class="reserved">void</span> <span class="method">m</span>(<span class="reserved">out</span> (<span class="reserved">int</span>, <span class="reserved">string</span>) <span class="variable">t</span>) =&gt; <span class="variable">t</span> = (1, <span class="string">&quot;abc&quot;</span>);
</code></pre>
<p>ちなみに、コミュニティ貢献であってもレビューのコストは掛かるわけで、
この手の pull request が常にうまくいくわけではないんですが。
今回に関しては <a href="https://github.com/YairHalberstadt">pull request 作者さん</a>が元々 <a href="https://github.com/dotnet/csharplang/">charplang</a>/<a href="https://github.com/dotnet/roslyn">roslyn</a> への貢献が大きい人なのと、
本当に「ほぼテストを足しただけ」レベルの修正だったからあっさりと通ったんじゃないかなという感じはします。</p>
 ]]></description>
				<pubDate>Fri, 05 Mar 2021 21:47:26 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn: 文脈キーワードの複雑さ低減</title>
				<link>http://ufcpp.net/blog/2021/2/lexicalkeywords/</link>
				<description><![CDATA[ <p>ここ数回やってる「C# Language Design Meeting 議事録が1か月分くらいたまったので1個1個機能紹介」シリーズに見せかけて、もうちょっと別枠。
Design Meeting の場に上がっていなくて、まだ単体の提案ドキュメントが出ただけの状態のものです。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/4460">[Proposal]: Only Allow Lexical Keywords in the Language #4460</a></li>
</ul>
<p><a href="https://ufcpp.net/study/csharp/ap_compatibility.html#contextual-keyword">文脈キーワード</a>の判定方法をもうちょっと単純にしたいという話になります。</p>
<h2>文脈キーワード</h2>
<p>C# は極力互換性を保つ(破壊的変更になるものを避ける)ように進化を続けてきました。
なので、「<code>var</code> というキーワードを使った新機能を追加したいけど、元々 <code>var</code> という名前の型がいた場合は型名を優先して、キーワード扱いしない」みたいなことを毎度やっています。
こういう文脈次第でキーワード扱いになるものを指して<a href="https://ufcpp.net/study/csharp/ap_compatibility.html#contextual-keyword">文脈キーワード</a> (contextual keyword) と言います。</p>
<p>ということで、以下のようなコードを書いた場合、C# 9.0 現在、1単語目の <code>var</code> はクラスの <code>var</code> になります。</p>
<pre class="source" title="1単語目の var はクラスの var">
<code><span class="type">var</span> <span class="variable">var</span> = <span class="reserved">new</span> <span class="type">var</span>();
<span class="reserved">class</span> <span class="type">var</span> { }
</code></pre>
<p>一方で、以下のコードの場合、1単語目はキーワードの <code>var</code> です。
(先ほどのコードとの差はクラス名が大文字始まりの <code>Var</code> な点だけ。)</p>
<pre class="source" title="1単語目はキーワードの var">
<code><span class="reserved">var</span> <span class="variable">var</span> = <span class="reserved">new</span> <span class="type">Var</span>();
<span class="reserved">class</span> <span class="type">Var</span> { }
</code></pre>
<h2>文脈キーワードのわかりにくさ</h2>
<p>先ほどの <code>var var = new var();</code> は割かし悪名高くて、
「互換性を保つため」という理由がなければどう考えても悪い文法です。
IDE 上は型名とキーワードで色が違うのでギリギリ判別は付きますが、
色なしのテキストになったら読めないと思います。</p>
<p>このブログは Visual Studio で書いた結果から型名かキーワードかの「色」を取って書いているので大丈夫なんですが、
そこまでマメなブログがどれだけあるか…
例えば単に Markdown 記法で以下のようなコードを書いたとき、
大体の環境で、<code>var</code> は無条件にキーワード扱いされると思います。</p>
<pre class="source" title="1単語目はキーワードの var">
<code>```cs
var var = new var();
```
</code></pre>
<p>「文脈を見る」みたいなこと自体学習ハードルを上げてしまうものですし、
挙句、インターネットで調べものをしていて変な色付けで表示されるとなると、
かなり初心者に優しくない状態になっています。</p>
<h2>record</h2>
<p>ところで、C# 9.0 で導入された<a href="https://ufcpp.net/blog/2020/6/record0609/">レコード型</a>についてはちょっと条件が違ったりします。
以下のコードはコンパイル エラー。</p>
<pre class="source" title="record は型名よりもキーワードの優先度が高い">
<code><span class="reserved">record</span> <span class="type"><span class="warning">record</span></span> <span class="error">= <span class="reserved">new</span> <span class="type">record</span>();</span>
<span class="reserved">record</span> <span class="error"><span class="type">record</span></span> { }
</code></pre>
<p>1単語目の <code>record</code> がキーワード扱いされていて、結果的に、以下の警告・エラーが出ます。</p>
<ul>
<li>警告: 型名に <code>record</code> は避けてほしい</li>
<li>エラー: レコード型の宣言に <code>=</code> は書けない</li>
<li>エラー: レコード型の宣言が2つある</li>
</ul>
<p>ここで、2行目を <code>class</code> に書き換えて、あと、C# 8.0 の文法として成立するように1行目をクラスで覆ってみます。
C# 8.0 ではこれは有効な C# コードでした。</p>
<pre class="source" title="C# 8.0 で普通にコンパイルできるコード">
<code><span class="reserved">class</span> <span class="type">A</span>
{
    <span class="type">record</span> record = <span class="reserved">new</span> <span class="type">record</span>();
}
 
<span class="reserved">class</span> <span class="type">record</span> { }
</code></pre>
<p>これを C# 9.0 でコンパイルすると以下のようになります。
色付けが変わって、コンパイル エラーが出ます。</p>
<pre class="source" title="さっきと同じコード。C# 9.0 では無効">
<code><span class="reserved">class</span> <span class="type">A</span>
{
    <span class="reserved">record</span> <span class="type"><span class="warning">record</span></span> <span class="error">=</span> <span class="reserved">new</span> <span class="type"><span class="error">record</span></span>();
}
 
<span class="reserved">class</span> <span class="type"><span class="warning">record</span></span> { }
</code></pre>
<p>ということで、実は <code>record</code> キーワードの追加は破壊的変更を起こしています。</p>
<p>ちなみに、文脈キーワードじゃなくなっているわけではないです。
例えば以下のコードはコンパイル可能。
1単語目だけ <code>@</code> を付けて「キーワードではない」ことを明示しています。
<code>new</code> の後ろなら<code>@</code> なしでも型名。</p>
<pre class="source" title="@ を付ければキーワードじゃなくなる">
<code><span class="type">@record</span> <span class="variable">record</span> = <span class="reserved">new</span> <span class="type">record</span>();
<span class="reserved">class</span> <span class="type">record</span> { }
</code></pre>
<p>あと、以下の書き方でも大丈夫です。
<code>global::</code> (<code>global</code> はキーワード)の後ろなので型名であることが明白。</p>
<pre class="source" title="global:: の後ろは常に型名">
<code><span class="reserved">global</span>::<span class="type">record</span> <span class="variable">record</span> = <span class="reserved">new</span> <span class="type">record</span>();
<span class="reserved">class</span> <span class="type">record</span> { }
</code></pre>
<p><code>record record = new record();</code> を書けるようにしようと思ったら判定がかなり複雑になるのであきらめたみたいです。</p>
<p>そしてもう1点、互換性に対するポリシーもだいぶ今と昔で違っています。</p>
<h2>互換性に関するポリシー</h2>
<p>まあ、現実的に、C# で <code>var</code> とか <code>record</code> とかを型名として使うことはありません。
C# では型名は大文字始まりにする文化なので、同じ単語を使うにしても <code>Var</code> とか <code>Record</code>とかを使います。</p>
<p>それでも、昔だったら「世の中にはどんなコードがあるかわからないので、<code>var</code> 型・<code>record</code> 型が存在する前提で考える」となったと思います。
一方で、今は、「GitHub でコードを探してみたけど9割9分使ってないよ」みたいなのが判断材料になるようです。
実際まあ、この文章みたいに「変なことができる」という指摘をするためのコード以外ではほぼ出てこないと思います。</p>
<p>あと、<a href="https://ufcpp.net/study/csharp/cheatsheet/langversionoption/">言語バージョンとターゲット フレームワークのバージョン</a>に関するポリシーも変わりました。
昔は、「古い .NET Framework がターゲットの時でも最新の C# を使えるようにサポートする」という方針でした。
一方で今は、「既定動作では .NET のバージョンによって、それと同世代の C# バージョンに固定される」、
「明示的に C# バージョンを変えることもできるけども、わかってる人だけにやってほしくて、『サポートする』とは言わない」という方針。
基本的には、「C# のバージョンを上げるときには色々と書き換えが発生する覚悟があるはず」、
「保守モードなコードさえ壊さなければまあ許す」という前提になります。</p>
<h2>字句解析で文脈判定</h2>
<p>話を戻しますが、<code>record</code> キーワードの話。
文脈を見てはいるんですよね。<code>record</code> という名前の型があっても大丈夫です。
ただ、<code>record</code> の場合は以下のような判定をしています。</p>
<ul>
<li>ステートメントとかメンバー宣言の先頭で出てきたらキーワード</li>
<li>それ以外の、<code>::</code> とか <code>new</code> とか他の型名の後ろに出てきたら識別子(型名、変数名、メソッド名等々)</li>
</ul>
<p><code>var</code> と何が違うかというと、「型名として使われているかどうか」みたいな情報を必要としていない点。
字句解析の段階(lexical analysis: コンパイラーの仕事のかなり初期の段階)でキーワードかどうかの判定ができます。</p>
<p>(注:
原文が lexical analysis と書いているのでここでもそう書いているものの、
正しくは構文解析(syntax analysis)での判定な気もする。
「その名前の型がある」みたいな情報(semantics: 意味解析)は必要としないものの、
「<code>new</code> の後ろ」とか「<code>::</code> の後ろ」みたいな情報(syntax)は必要としてそう。
lexical というと普通は <code>new</code> とか <code>::</code> とかの「単語の切り出し」のこと。)</p>
<p>字句解析だけで判定できるということは、前述の「Markdown が誤判定する問題」も回避できます。
1ファイルだけとか、コードの一部分だけを切り出したものとかを読んでも「キーワードなのか型名なのか」の判別を間違えません。</p>
<h2>既存の文脈キーワードも字句解析時の判定に</h2>
<p>で、<code>record</code> キーワードの追加で破壊的変更をしたわけですが、それで困った人いる？</p>
<p>さらにいうと、今更 <code>var var = new var();</code> が書けなくなって困る人いる？</p>
<p>ということで、以下の文脈キーワードの判定方法を変えたい(<code>record</code> と同じく字句解析時に判定)という話が出ています。</p>
<ul>
<li><code>var</code>: <a href="https://ufcpp.net/study/csharp/start/misctyperesolution/#source-type">型推論</a></li>
<li><code>nameof</code>: <a href="https://ufcpp.net/study/csharp/st_string.html#nameof-operator">nameof 演算子</a></li>
<li><code>dynamic</code>: <a href="https://ufcpp.net/study/csharp/sp4_dynamic.html">dynamic 型</a></li>
<li><code>_</code>: <a href="https://ufcpp.net/study/csharp/datatype/declarationexpressions/#discards">値の破棄</a></li>
</ul>
<p>これらも完全にキーワードになるわけじゃなく、<code>record</code> と同じく例えば <code>@var var = new var();</code> なら有効なコードになります。</p>
<p>多分、<code>var</code>、<code>nameof</code>、<code>dynamic</code> については異論は出ないと思います。
<code>var</code> と <code>dynamic</code> はクラス名と、
<code>nameof</code> はメソッド名と競合するんですが、クラス名もメソッド名も普通は大文字開始で書くので。
影響を受けるコードは実用的にはほとんど現れないし、
影響を受けるとしても「<code>@</code> を足す程度なら許容できる」という範囲に収まる思います。</p>
<p>迷うとすると <code>_</code> で、<code>_ =&gt; _.Name</code> みたいな<a href="https://ufcpp.net/study/csharp/functional/fun_localfunctions/#anonymous-function">ラムダ式</a>は「聞かないこともない」程度には存在しています。
なのでこいつだけは現状維持の可能性はあります。</p>
<h2>まとめ</h2>
<p>もう <code>var var = new var();</code> 書けなくてもいいんじゃない？という話。</p>
<p>メリットとして、GitHub の Markdown などに「コードの一部分だけ記載」とかをやっても型名かキーワードかの誤判定しなくて済むようになります。
(あくまで実装依存ですが、現状の semantics 依存な文法よりはだいぶ実装者にやさしくなります。)</p>
<p>一方で、文脈キーワード自体がなくなるわけではなくて、<code>@record record = new record();</code> は普通に有効なコードです。
生誕20年のプログラミング言語の「負債の返却」作業としては悪くない落としどころかなと思います。</p>
<p>個人的にはやってほしい変更なので、このブログを読んだ方にぜひとも<a href="https://github.com/dotnet/csharplang/issues/4460">提案 issue</a> への 👍 をお願いしたかったりします。
(C# チームはある程度 👍👎 の数を見ています。)</p>
 ]]></description>
				<pubDate>Sun, 28 Feb 2021 19:51:58 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn: 構造体の引数なしコンストラクター</title>
				<link>http://ufcpp.net/blog/2021/2/parameterlessstructctor/</link>
				<description><![CDATA[ <p><a href="https://ufcpp.net/blog/2021/2/rawstringliteral/">前回の続き</a>。
というかしばらく「C# Language Design Meeting 議事録が1か月分くらいたまったので1個1個機能紹介」シリーズ。</p>
<p>議事録(前回と比べて2/24議事録が増えてます):</p>
<p><a href="https://github.com/dotnet/csharplang/blob/master/meetings/2021/LDM-2021-01-27.md">1/27</a>、<a href="https://github.com/dotnet/csharplang/blob/master/meetings/2021/LDM-2021-02-03.md">2/3</a>、<a href="https://github.com/dotnet/csharplang/blob/master/meetings/2021/LDM-2021-02-08.md">2/8</a>、<a href="https://github.com/dotnet/csharplang/blob/master/meetings/2021/LDM-2021-02-10.md">2/10</a>、<a href="https://github.com/dotnet/csharplang/blob/master/meetings/2021/LDM-2021-02-22.md">2/22</a>、<a href="https://github.com/dotnet/csharplang/blob/master/meetings/2021/LDM-2021-02-24.md">2/24</a></p>
<p>今日は「構造体の引数なしコンストラクター」の話。</p>
<h2>概要: 構造体の引数なしコンストラクター</h2>
<p>現状ではコンパイル エラーになる以下のコードを書けるようにしようという話です。</p>
<pre class="source" title="構造体の引数なしコンストラクターとフィールド初期化子">
<code><span class="reserved">struct</span> <span class="type">S1</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> X;
    <span class="reserved">public</span> <span class="reserved">int</span> Y;
 
    <span class="reserved">public</span> <span class="type">S1</span>() <span class="comment">// これとか</span>
    {
        X = 1;
        Y = 2;
    }
}
 
<span class="reserved">struct</span> <span class="type">S2</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> X = 1;
    <span class="reserved">public</span> <span class="reserved">int</span> Y = 2; <span class="comment">// この2行とか</span>
}
</code></pre>
<p>C# 6.0 の頃に一度採用しようとしたものの、<code>Activator.CreateInstance</code> のバグを踏んでしまって取りやめになっていました。
(6・7年前の話ですが、まあ、覚えている方も中にはいらっしゃるかも。)</p>
<p>上記議事録上は直接出てきてはいないんですが、record structs と関連して「やっぱり必要だよね」みたいな空気になっていて、改めて提案が出ました。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/pull/4459">Add proposal for explicit parameterless struct constructors #4459</a></li>
</ul>
<p><a href="https://github.com/dotnet/roslyn/blob/master/docs/Language%20Feature%20Status.md#user-content-c-next">Language Feature Status の C# Next のところ</a>にも並んだので C# 10.0 に内定。</p>
<h2>背景: default(T) と new T()</h2>
<p>さかのぼること C# 1.0。
最初のバージョンの C# には <a href="https://ufcpp.net/study/csharp/rm_default.html#default-keyword"><code>default</code> 式</a>がありませんでした。
でも、(既定値の作成」(0 埋め)は必要で、それを構造体の場合、単に <code>new T()</code> と書いていました。</p>
<p>結果的に、C# の仕様は以下のようになりました。</p>
<ul>
<li>構造体には明示的に引数なしコンストラクターを書くことはできない</li>
<li>
構造体は暗黙的な引数なしコンストラクターがあるかのようなふるまいをしていた
<ul>
<li>構造体に対して <code>new T()</code> と書くと既定値(すべてのフィールドを0埋め)を作る</li>
<li><a href="https://ufcpp.net/study/csharp/oo_construct.html#initializer"><code>: this()</code></a> も0埋め処理になる</li>
</ul>
</li>
</ul>
<p>その後、C# 2.0 では<a href="https://ufcpp.net/study/csharp/sp2_generics.html">ジェネリクス</a>の導入に伴って <code>default(T)</code> という書き方で既定値を作れるようになりました。
この時点で実は、「構造体の <code>new T()</code> は既定値を作るために使う」という必要性はなくなっています。
ただ、あくまで「変えても大丈夫になった」というだけで、実際に変えようという話になったのは C# 6.0 が初出だし、実現しそうなのは 10.0 です。</p>
<p>つまり現状、</p>
<ul>
<li>
<code>new T()</code> と <code>default(T)</code> は全く同じ意味
<ul>
<li>どちらも「規定値の作成」で0初期化</li>
</ul>
</li>
</ul>
<p>で、これを、 C# 10.0 で、</p>
<ul>
<li>構造体に明示的な引数なしコンストラクターを書けるようにする</li>
<li>
明示的な引数なしコンストラクターを書いた場合に限り、<code>new T()</code> と <code>default(T)</code> が別の意味になる
<ul>
<li><code>new T()</code> はコンストラクター呼び出し</li>
<li><code>default(T)</code> は規定の作成</li>
</ul>
</li>
</ul>
<p>にしようとしています。</p>
<h2>Activator バグ</h2>
<p>C# 6.0 でこの話が出た時、なんで即座に実装できなかったというと、<a href="https://docs.microsoft.com/ja-jp/dotnet/api/system.activator.createinstance?WT.mc_id=DT-MVP-4028921"><code>Activator.CreateInstance</code></a> の実装に問題が発覚したからだそうです。</p>
<p>前述の通り、元々、構造体に対して <code>new T()</code> は <code>default(T)</code> と同じ意味で使っていました。
<code>Activator.CreateInstance</code> はその前提で実装されていたそうで、
構造体に引数なしコンストラクターを書けるようにしたのにコンストラクターを呼んでもらえないという状態になったそうです。
当時、構造体に対する <code>CreateInstance&lt;T&gt;()</code> は常に既定値(<code>default(T)</code>)を返す実装になっていました。
(ちなみに、 .NET の型システム上は元々構造体に引数なしコンストラクターを持たせられるにも関わらず、です。)</p>
<p>「<code>Activator.CreateInstance</code> なんて使ったことないし、そんなに問題なの？」と思う方もいらっしゃるかと思いますが、
実際には多分、無意識に使っています。
と言うのも、ジェネリクスの <code>new()</code> 制約を付けた型を実際に <code>new T()</code> すると、内部的に <code>Activator.CreateInstance&lt;T&gt;()</code> が呼ばれます。</p>
<pre class="source" title="new() 制約付きの型 T に対する new T()">
<code><span class="reserved">class</span> <span class="type">C</span>&lt;<span class="type">T</span>&gt;
    <span class="reserved">where</span> <span class="type">T</span> : <span class="reserved">new</span>()
{
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="type">T</span> <span class="method">M</span>() =&gt; <span class="reserved">new</span> <span class="type">T</span>(); <span class="comment">// これが実は Activator.CreateInstanct&lt;T&gt;() になってる。</span>
}
</code></pre>
<p>C# 6.0 でこの問題に気づいたあとすぐに <code>CreateInstance</code> は修正されて、
今はちゃんと「構造体でも引数なしコンストラクターがある場合はそれを呼ぶ」という実装に変更されています。</p>
<p>この修正は .NET Framework 4.6 の時に入っていて、となると基本的に「サポートがまだ切れていない .NET ランタイムで <code>CreateInctansce</code> がバグっているものはもうほとんどない」という状態。
(時代的背景があって .NET Framework 3.5 SP 1 とかが実はまだサポート期間中だったりしますが、
さすがに .NET Framework 3.5 で C# 10.0 を使いたいという需要はほとんどないと思われます。)</p>
<h2>そして実装へ (C# 10.0)</h2>
<p>C# 9.0 で追加された<a href="https://ufcpp.net/blog/2020/6/record0609/">レコード型</a>(まだちゃんと <a href="https://ufcpp.net/study/csharp/">C# によるプログラミング入門</a>内に書いてない…)は参照型(クラスと一緒)になります。
で、レコードと同じことを値型でもやりたいという話は 9.0 の頃から当然あって、
単に「後からの追加でも問題ないし、9.0 に間に合わないから 10.0 でやる」という話になっていました。
それが record struct。
基本的にはほぼ「C# 9.0 でレコード型に対してやったことをほぼそのまま構造体に対してもやる」というものです。</p>
<p>C# 9.0 のレコード型では、例えば以下のような書き方ができます。
型名の直後の <code>()</code> はプライマリ コンストラクターとか呼ばれています。</p>
<pre class="source" title="プライマリ コンストラクターの例">
<code><span class="comment">// プライマリ コンストラクター</span>
<span class="reserved">record</span> <span class="type">A</span>(<span class="reserved">int</span> <span class="variable">x</span>)
{
    <span class="reserved">public</span> <span class="reserved">int</span> X { <span class="reserved">get</span>; <span class="reserved">init</span>; } = <span class="variable">x</span>;
}
 
<span class="comment">// 引数なしプライマリ コンストラクター</span>
<span class="reserved">record</span> <span class="type">B</span>() : <span class="type">A</span>(1)
{
    <span class="reserved">public</span> <span class="reserved">int</span> Y { <span class="reserved">get</span>; <span class="reserved">init</span>; } = 2;
}
</code></pre>
<p>これと同じようなことをしたいんだから、自然と、record struct でも以下のような書き方もできてほしくなります。</p>
<pre class="source" title="record struct でも引数なしプライマリ コンストラクター">
<code><span class="reserved">record</span> <span class="reserved">struct</span> <span class="type">S</span>()
{
    <span class="reserved">public</span> <span class="reserved">int</span> X { <span class="reserved">get</span>; <span class="reserved">init</span>; } = 1;
}
</code></pre>
<p>まあ、record struct は単なる契機であって、元から以下のような書き方をしたいという要望はずっと昔からあります。</p>
<pre class="source" title="普通の構造体でもフィールド初期化子">
<code><span class="reserved">struct</span> <span class="type">S</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> X = 1;
}
</code></pre>
<p>はい、いいタイミングなのでやりましょう(いまここ)。</p>
<h2>踏みそうな問題</h2>
<p>まあ概ね「今までできなかったことの方が不自然」レベルの機能なので、そんなに説明が必要な部分はないと思います。
「フィールド初期化子があると暗黙的に引数なしコンストラクターが作られる」とか「フィールド初期化子は上から順に呼ばれる」とか、大体は「クラスと一緒」の一言で終わりそうな仕様。</p>
<p>いくつかだけ注意点を紹介:</p>
<ul>
<li>引数なしコンストラクターのアクセシビリティは、フィールドとして含んでいる構造体のアクセシビリティ以上でないとダメ</li>
<li><code>where T : struct</code> と <code>where T : new()</code> の入れ子に注意</li>
<li><a href="https://ufcpp.net/study/csharp/sp4_optional.html">オプション引数</a>に注意</li>
</ul>
<h3>アクセシビリティ</h3>
<p>以下のようなコードはダメだそうです。</p>
<pre class="source" title="アクセシビリティの問題">
<code><span class="reserved">internal</span> <span class="reserved">struct</span> <span class="type">Internal</span> { }
 
<span class="reserved">public</span> <span class="reserved">struct</span> <span class="type">PublicContainsInternal</span>
{
    <span class="reserved">private</span> <span class="type">Internal</span> _internal;
 
    <span class="comment">// このコンストラクターが Internal 構造体よりも広いアクセシビリティなのでダメ。</span>
    <span class="comment">// internal とか private なら OK。</span>
    <span class="error"><span class="reserved">public</span> <span class="type">PublicContainsInternal</span>()</span>
    {
        _internal = <span class="reserved">new</span>();
    }
}
</code></pre>
<p>引数なしコンストラクターの有無で <code>new T()</code> の意味が変わるので、既存の型への引数なしコンストラクター追加は破壊的変更になります。
なので、より広い範囲に公開されてしまうコンストラクターがあると問題を起こしかねないので禁止とのこと。</p>
<h3>where T : struct</h3>
<p>これまで、構造体は無条件に <code>new T()</code> できていました。
なので、以下のようなメソッドを書いて、<code>CreateStruct&lt;T&gt;()</code> を呼んで実行できないケースは全くありませんでした。</p>
<pre class="source" title="C# 9.0 までなら絶対に大丈夫なコード">
<code><span class="reserved">static</span> <span class="type">T</span> <span class="method">CreateNew</span>&lt;<span class="type">T</span>&gt;() <span class="reserved">where</span> <span class="type">T</span> : <span class="reserved">new</span>() =&gt; <span class="reserved">new</span> <span class="type">T</span>();
<span class="reserved">static</span> <span class="type">T</span> <span class="method">CreateStruct</span>&lt;<span class="type">T</span>&gt;() <span class="reserved">where</span> <span class="type">T</span> : <span class="reserved">struct</span> =&gt; <span class="method">CreateNew</span>&lt;<span class="type">T</span>&gt;();
</code></pre>
<p>一方で、<code>Activator.CreateInstance&lt;T&gt;()</code> は <code>T</code> 型の引数なしコンストラクターが public でないと例外を起こします。
ということで、もし、C# 10.0 で非 public な引数なしコンストラクターを定義した構造体に対して上記の <code>CreateStruct&lt;T&gt;()</code> を呼ぶと実行時に <code>MissingMethod</code> 例外が出るようになります。
(さすがに、上記 <code>CreateNew&lt;T&gt;()</code> 呼び出しの方をコンパイル エラーにする変更はできなさそう。)</p>
<h3>オプション引数</h3>
<p>C# のオプション引数で、構造体な引数は <code>default(T)</code> だけを既定値設定できます。
例えば以下のようなコードは <code>new TimeSpan(0)</code> のところだけコンパイル エラーになります。</p>
<pre class="source" title="オプション引数に default(T) は渡せても new T(...) は渡せない">
<code><span class="reserved">void</span> <span class="method">M</span>(
    <span class="reserved">int</span> <span class="variable">x</span> = 1, <span class="comment">// 組み込み型の場合は const にできるもの何でも OK</span>
    <span class="type">CancellationToken</span> <span class="variable">c</span> = <span class="reserved">default</span>, <span class="comment">// default だけは渡せる。この行も OK。</span>
    <span class="type">TimeSpan</span> <span class="variable">t</span> = <span class="error"><span class="reserved">new</span> <span class="type">TimeSpan</span>(0)</span> <span class="comment">// これはダメ。一見定数にできそうに見えてもダメ。</span>
    )
{
}
</code></pre>
<p>ここで問題になるのは、昔は <code>new T()</code> と <code>default(T)</code> は全く同じ意味だったという点。
ということで、以下のコードは有効な C# コードになります。</p>
<pre class="source" title="new T() と default(T) が同じ意味なので OK">
<code><span class="reserved">void</span> <span class="method">M</span>(
    <span class="type">CancellationToken</span> <span class="variable">c</span> = <span class="reserved">new</span>() <span class="comment">// new T() と default(T) が同じ意味なので OK。</span>
    )
{
}
</code></pre>
<p>で、C# 10.0 では「引数なしコンストラクターを持っている構造体に対しては <code>new T()</code> の意味が変わるので…
以下のような状態になります。</p>
<pre class="source" title="引数なしコンストラクターを追加すると破壊的変更になる例">
<code><span class="reserved">void</span> <span class="method">M</span>(<span class="type">S</span> <span class="variable">s</span> = <span class="reserved">new</span>()) <span class="comment">// S に引数なしコンストラクターを足したらコンパイル エラーになる。</span>
{
}
 
<span class="reserved">struct</span> <span class="type">S</span>
{
    <span class="reserved">int</span> x;
    <span class="reserved">public</span> <span class="type">S</span>() =&gt; x = 1; <span class="comment">// この行の有無で M がコンパイルできるかどうか変わる。</span>
}
</code></pre> ]]></description>
				<pubDate>Sat, 27 Feb 2021 19:01:53 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn: raw string literal</title>
				<link>http://ufcpp.net/blog/2021/2/rawstringliteral/</link>
				<description><![CDATA[ <p>ブログで取り上げたい C# Language Design Meeting 議事録が1か月分くらいたまっているわけですが:</p>
<p><a href="https://github.com/dotnet/csharplang/blob/master/meetings/2021/LDM-2021-01-27.md">1/27</a>、<a href="https://github.com/dotnet/csharplang/blob/master/meetings/2021/LDM-2021-02-03.md">2/3</a>、<a href="https://github.com/dotnet/csharplang/blob/master/meetings/2021/LDM-2021-02-08.md">2/8</a>、<a href="https://github.com/dotnet/csharplang/blob/master/meetings/2021/LDM-2021-02-10.md">2/10</a>、<a href="https://github.com/dotnet/csharplang/blob/master/meetings/2021/LDM-2021-02-22.md">2/22</a></p>
<p>しばらく、機能ごとに1個1個取り上げていこうかなという感じになっていまして、今日は raw string literal の話から。</p>
<h2>概要</h2>
<p>以下のような書き方で、複数行、かつ、一切のエスケープなしの文字列リテラルを導入したいという話が出ています。</p>
<pre class="source" title="raw string literal">
<code><span class="reserved">string</span> <span class="variable">xml</span> = <span class="string">&quot;&quot;&quot;
    &lt;a&gt;
        &lt;b c=&quot;abc&quot; /&gt;
    &lt;/a&gt;
    &quot;&quot;&quot;;</span>
 
<span class="reserved">string</span> json = <span class="string">&quot;&quot;&quot;
    {
        &quot;a&quot; : {
            &quot;b&quot; : {
                &quot;c&quot; : &quot;abc&quot;
            }
        }
    }&quot;&quot;&quot;;</span>
</code></pre>
<p>C# の文字列中に XML、Json/JavaScript とか、さらに言うと C# 自身を書きたいことが多々あって、
結構昔から要望はありました。</p>
<p>近い機能として、C# には 1.0 の頃から <a href="https://ufcpp.net/study/csharp/st_embeddedtype.html#verbatim-string"><code>@&quot;&quot;</code></a> という書き方があったりしますし、Visual Studio などの IDE が自動補完で補ってくれたりはしていました。</p>
<pre class="source" title="逐語的文字列リテラル(C# 1.0 からある)">
<code><span class="reserved">string</span> <span class="variable">s</span> = <span class="string">@&quot;
{
    </span><span style="color:#b776fb;">&quot;&quot;</span><span class="string">a</span><span style="color:#b776fb;">&quot;&quot;</span><span class="string"> : </span><span style="color:#b776fb;">&quot;&quot;</span><span class="string">abc</span><span style="color:#b776fb;">&quot;&quot;</span><span class="string">
}&quot;</span>;
</code></pre>
<p><img src="/media/1183/idenewline.png" alt="Visual Studio の自動補完で複数行文字列を書く例" /></p>
<p>でも、 <code>\&quot;</code> とか <code>{{</code> とか <code>&quot;&quot;</code> とか書くのがめんどくさいのでもっと「生文字列」を書きたいということで出て来た文法案になります。</p>
<h2>背景: 言語内言語</h2>
<p>C# 中に XML とか Json とか SQL を直接リテラルに埋め込もうとして、
外部で編集して来たものをコピペしたら <code>&quot;</code> のエスケープで困るということはよくあると思います。</p>
<p>C# の文字列中に何らかの言語を埋め込むこと自体どうなんだという話はあるんですが、
最近の C# は普通に言語内言語を解釈してるんですよね。</p>
<p><img src="/media/1184/langinlang.png" alt="言語内言語" /></p>
<p>今のところ<a href="https://docs.microsoft.com/ja-jp/dotnet/api/system.text.regularexpressions.regex?WT.mc_id=DT-MVP-4028921">正規表現</a>と<a href="https://docs.microsoft.com/ja-jp/dotnet/api/system.datetime.tostring?WT.mc_id=DT-MVP-4028921#System_DateTime_ToString_System_String_">時刻・日付のフォーマット</a>だけなんですが、一応、C# コンパイラー内には任意の文字列に対して自作の色付け(highlight)・補完候補(completion)を出すための仕組みを持っていたりします。</p>
<ul>
<li>正規表現用: <a href="https://github.com/dotnet/roslyn/tree/master/src/Features/Core/Portable/EmbeddedLanguages/RegularExpressions">RegularExpressions</a></li>
<li>時刻・日付用: <a href="https://github.com/dotnet/roslyn/tree/master/src/Features/Core/Portable/EmbeddedLanguages/DateAndTime">DateAndTime</a></li>
</ul>
<p>C# 9.0 世代では <a href="https://ufcpp.net/study/csharp/misc/analyzer-generator/">Source Generator</a> も入ったわけで、
言語内言語を書く機会は増えるかもしれません。
というか、<a href="https://github.com/ufcpp/TextTemplateSourceGenerator/blob/main/samples/StringToUtf8Preprocessor/Generator.cs">自分は割かし定期的にもくろんでいます</a>。</p>
<p>上記の正規表現・時刻・日付の実装は今のところ internal なんですが、
Source Generator によって需要が増えれば、言語内言語の色付け・補完用の機能も public にしてもらえるかもしれません。
(一度 public にすると変更が難しくなるので、結構しっかり作ってあっても需要が上がらないとなかなか public にならない。)</p>
<p>昔から要望がある raw string literal の具体案が今になって本腰が入ったのは、こういう背景からだと思います。
(ちなみに、raw string literal 提案のオーナーになっているのは上記の正規表現・時刻・日付の色付け・補完の実装者の方だったりします。)</p>
<h2>3個以上、任意個の &quot;</h2>
<p>この手の raw string を実装する上で問題になるのは、「自分自身を含む可能性」だったりします。
C# Source Generator で C# から C# をコード生成したりするとき、結構困ります。</p>
<p>C# 1.0 の頃からある <code>@&quot;&quot;</code> の一番の問題点も <code>&quot;</code> 自体を含みにくい(<code>&quot;&quot;</code> と、2文字並べるエスケープ処理が必要)ことです。
なんせ、XML、Json など含め、たいていのものが文字列の表現に <code>&quot;</code> を使います。
物によっては <code>'</code> (single quotation) か <code>&quot;</code> (double quotation) かを選べたりしますが、両方を含むことも多いです。
まして、Java とか JavaScript とか C# とかは C 言語由来の文法が多くて、<code>&quot;</code> とか <code>{</code> とかの使い方がほとんど同じです。
これらをそのまま書けないというのが <code>@&quot;&quot;</code> の使いづらいところです。</p>
<p>そこでまあ、<code>&quot;&quot;&quot;</code> とか、「<code>&quot;</code> を3つ並べた場合、そのあと、再び <code>&quot;&quot;&quot;</code> が現れるまで <code>&quot;</code> をエスケープなしの生の <code>&quot;</code> 扱いする」みたいな文法が考えられます。
ところが、「その文法を採用した自分自身」を含もうとすると、<code>&quot;&quot;&quot;</code> をエスケープできる手段が再び必要になったりします。</p>
<p>ということで、今提案されている raw string literal では「3個以上、任意個の <code>&quot;</code> から開始して、同数の <code>&quot;</code> で終わる」という仕様にしてあります。<code>&quot;&quot;&quot;</code> (3個)をエスケープなしで含みたければ <code>&quot;&quot;&quot;&quot;</code> (4個)から開始すればいいじゃない。</p>
<pre class="source" title="C# raw string in C# raw string">
<code><span class="reserved">var</span> <span class="variable">cs</span> = <span class="string">&quot;&quot;&quot;&quot;
    var s = &quot;&quot;&quot;
        C# in C#
        &quot;&quot;&quot;;
    &quot;&quot;&quot;&quot;</span>;
</code></pre>
<h2>インデント</h2>
<p>もう1個、<code>@&quot;&quot;</code> の嫌なところはインデントがそろわなくなるところです。</p>
<p>以下のような文字列リテラルを書くと、1行目の位置と2行目以降の位置がだいぶ離れるのが結構見づらくなります。</p>
<pre class="source" title="逐語的文字列リテラルでの改行。2行目以降の位置がだいぶずれる">
<code><span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> <span class="method">M</span>()
    {
        <span class="reserved">const</span> <span class="reserved">string</span> s = <span class="string">@&quot;1行目
    2行目
3行目
&quot;</span>;
    }
}
</code></pre>
<p>本当は以下のように書けるとだいぶ見やすくなると思います。</p>
<pre class="source" title="整形… した結果余計のスペースが含まれる">
<code><span class="reserved">const</span> <span class="reserved">string</span> s = <span class="string">@&quot;
    1行目
        2行目
    3行目
    &quot;</span>;
</code></pre>
<p>もちろんこれは有効な C# コードなんですが、1行目の前に改行文字が1つ入っちゃうのと、全部の行の行頭にスペースが入っちゃうわけで、空白文字を含めて一字一句一致しないとまずい場合には使えません。</p>
<p>ということで、今回の提案の raw string literal は以下のような仕様になります。</p>
<ul>
<li>開始の <code>&quot;&quot;&quot;</code> (3個以上の <code>&quot;</code>) の後ろには改行必須</li>
<li>1行目のインデントを基準にして、それよりも前の空白文字は無視</li>
</ul>
<p>例えば先ほどの <code>@&quot;&quot;</code> で書いた文字列リテラルと同じものを新しい raw string literal で書くと以下のようになります。</p>
<pre class="source" title="raw string は開始行の改行必須 ＆ 1行目でインデント量を決定">
<code><span class="reserved">const</span> <span class="reserved">string</span> s = <span class="string">&quot;&quot;&quot;
    1行目
        2行目
    3行目
    &quot;&quot;&quot;</span>;
</code></pre>
<h3>文字列補間はやらない</h3>
<p>まあ一番の目的が「全くエスケープ処理をしないでいい文字列リテラルが欲しい」という点なので、<a href="https://ufcpp.net/study/csharp/st_string.html#string-interpolation"><code>$&quot;&quot;</code></a> みたいな特殊なことは一切やらないそうです。</p>
<p>文字列補間には、<code>$@&quot;&quot;</code> もしくは <code>@$&quot;&quot;</code> という書き方で、「複数行、かつ、文字列補間が掛かるリテラル」が書けます。</p>
<pre class="source" title="$@">
<code>    <span class="reserved">static</span> <span class="reserved">void</span> <span class="method">M</span>(<span class="reserved">string</span> <span class="variable">@namespace</span>, <span class="reserved">string</span> <span class="variable">className</span>)
    {
        <span class="reserved">string</span> <span class="variable">s</span> = <span class="string">$@&quot;
namespace </span>{<span class="variable">@namespace</span>}<span class="string">
</span><span style="color:#b776fb;">{{</span><span class="string">
    class </span>{<span class="variable">className</span>}<span class="string">
    </span><span style="color:#b776fb;">{{</span><span class="string">
    </span><span style="color:#b776fb;">}}</span><span class="string">
</span><span style="color:#b776fb;">}}</span><span class="string">
&quot;</span>;
    }
</code></pre>
<p>はい、もうこの時点で何が嫌かわかるかと思います。<code>{{</code> が嫌。
実際、「C# 内 C#」みたいなことをやると、上記のコードは以下のように書き直した方がまだマシなんじゃないかと思ったりすることが結構あります。</p>
<pre class="source" title="もう、 + でつなげばいいんじゃ…">
<code>    <span class="reserved">static</span> <span class="reserved">void</span> <span class="method">M</span>(<span class="reserved">string</span> <span class="variable">@namespace</span>, <span class="reserved">string</span> <span class="variable">className</span>)
    {
        <span class="reserved">string</span> <span class="variable">s</span> = <span class="string">@&quot;
namespace &quot;</span> + <span class="variable">@namespace</span> + <span class="string">@&quot;
{
    class &quot;</span> + <span class="variable">className</span> + <span class="string">@&quot;
    {
    }
}
&quot;</span>;
    }
</code></pre>
<p>ものすごく本末転倒…</p>
<p>ということで、とりあえず、raw string literal に関しては <code>$&quot;&quot;&quot;</code> みたいなものは提供しないとのこと。</p>
<h3>他の言語の類似機能</h3>
<p>似たような複数行・エスケープなし・インデント調整可能なリテラルを導入した言語もちらほらあります。</p>
<p>Java は Java 15 で text blocks という名前でこの機能を導入したみたいですが、開始文字は <code>&quot;&quot;&quot;</code> (3個)で固定みたいです。
自分自身を含むときにやっぱりエスケープが必要。</p>
<p>Swift は元々あった「<code>&quot;&quot;&quot;</code> (3個固定)で複数行文字列」(multiline string)という仕様に、
Swift 5 で導入した「任意個の <code>#</code> の後ろに <code>&quot;</code> (単体行) か <code>&quot;&quot;&quot;</code> (複数行)でエスケープなし文字列」(raw string)みたいな文法を組み合わせて同様のことができるみたいです。先に <code>&quot;&quot;&quot;</code> (3個固定)があったから <code>#</code> になっちゃった感じ。</p>
 ]]></description>
				<pubDate>Thu, 25 Feb 2021 22:15:43 +0900</pubDate>
			</item>
			<item>
				<title>UAX31: Unicode Identifier の話</title>
				<link>http://ufcpp.net/blog/2021/2/uax31/</link>
				<description><![CDATA[ <p>今日はまた<a href="https://github.com/ufcpp-live/UfcppLiveAgenda/issues/6">去年の作業が元ネタ</a>で、プログラミング言語の識別子に使える文字に関する話です。</p>
<h2>レターか数字</h2>
<p><em>「1文字目にはアルファベットか <code>_</code>、2文字目以降にはそれに加えて数字を使えます。」</em></p>
<p>30年くらい前にはこれが「プログラミング言語の識別子(変数名など)に使える文字列」の定義でした。
<code>_</code> の部分はプログラミング言語次第ですが、「1文字目にアルファベット、2文字目以降に数字」の部分は結構いろんな言語でそうだったんじゃないかと思います。</p>
<p>まあ、昔のプログラミング言語は <a href="https://ja.wikipedia.org/wiki/ASCII">ASCII コード</a>で書く物だったので、上記の条件は <code>[a-zA-Z]</code> とか <code>[0-9]</code> みたいな正規表現で書けたんですが。
<a href="https://ja.wikipedia.org/wiki/Unicode">Unicode</a> の時代になると「アルファベットだけでいいのか」とか「アルファベットって何だ」という話になります。</p>
<h3>レター</h3>
<p>まず、「アルファベット(alphabet)」というと母音と子音が分かれてる文字のことで、ラテン文字、ギリシャ文字、キリル文字なんかのことを指します。アラビア文字みたいに母音しか表記しないやつはアブジャド(abjad)、漢字は表意文字(ideogram)、ひらがな・カタカナみたいなのは音節文字(syllabary)と呼ぶらしく、「1文字目はアルファベット」と言ってしまうと一部の自然言語に偏ってしまいます。</p>
<p>Unicode 的にこの辺りの「記号や数字じゃない文字全般」を指してレター(letter)と呼ぶので、冒頭の条件は以下のように書き換わります。</p>
<p><em>「1文字目にはレターか <code>_</code>、2文字目以降にはそれに加えて数字を使えます。」</em></p>
<h3>レターとは…</h3>
<p>Unicode では文字ごとにカテゴリーが決められているので「ある文字列がレターかどうか」を調べるのは簡単…</p>
<p>かというとそうでもなくて、確かに1文字1文字がレターかどうかを判定するのは素直なんですが、2文字以上がくっついて1文字になることがあってそれが面倒だったりします。</p>
<p>例えば「ら゚」の文字。
現代日本語では普通は使わない文字ですが、R 音の「ら」と L 音の「ら」を区別するために L 音の方を「ら゚」と書く用法が一時期あったそうです。今現在ほとんど流通していないレア文字なので、この文字を Unicode 1文字で表す方法はない(符号が割当たってない)んですが、普通の「ら」(U+3089)の後ろに<a href="https://www.compart.com/en/unicode/U+309A">半濁点(U+309A)</a>を並べることで「ら゚」を表せます。</p>
<p>ちなみに、Unicode の文字カテゴリー的には</p>
<ul>
<li>ら(U+3089) は Letter, Other (Lo)</li>
<li>゚゚   (U+309A) は  Mark, NonSpacing (Mn)</li>
</ul>
<p>となっています。マーク(mark)ってものが出てきましたが、「レターにくっついて修飾する系の文字」は大体この分類です。日本語の濁点・半濁点以外にも、ラテン文字に対する<a href="https://ja.wikipedia.org/wiki/%E3%83%80%E3%82%A4%E3%82%A2%E3%82%AF%E3%83%AA%E3%83%86%E3%82%A3%E3%82%AB%E3%83%AB%E3%83%9E%E3%83%BC%E3%82%AF">ダイアクリティカルマーク</a>もマークの類です。</p>
<p>日本語とかラテン文字の場合はこういうレア文字を除いてほとんどの文字が、
わざわざレター + マークの組み合わせを使わなくても大体 Unicode の符号が割当たっているのでそこまで困りません。
一方で、<a href="https://th.wikipedia.org/wiki/%E0%B8%AD%E0%B8%B1%E0%B8%81%E0%B8%A9%E0%B8%A3%E0%B9%84%E0%B8%97%E0%B8%A2">タイ文字</a>(อักษรไทย みたいなの)とか<a href="https://hi.wikipedia.org/wiki/%E0%A4%B8%E0%A4%82%E0%A4%B8%E0%A5%8D%E0%A4%95%E0%A5%83%E0%A4%A4_%E0%A4%AD%E0%A4%BE%E0%A4%B7%E0%A4%BE">サンスクリット</a>(संस्कृत みたいなの)は普通に日常的に使う文字がレター + マーク構成になっています。</p>
<p>ということで、「人の認識上」でレターっぽいものは受け付けたいとなったとき、
「Unicode の処理の都合上」では「1文字目にレター、2文字目以降にマーク」になります。
その結果、冒頭の条件はさらに以下のように書き換わります。</p>
<p><em>「1文字目にはレターか <code>_</code>、2文字目以降にはそれに加えて数字とマークを使えます。」</em></p>
<h2>Unicode カテゴリーを使ったちゃんとした定義</h2>
<p>この「1文字目にはレター、2文字目以降にはそれに加えて数字とマーク」という方向性、たぶん最初に採用したのは Java ですかね。<a href="https://docs.oracle.com/javase/7/docs/api/java/lang/Character.html#isJavaIdentifierStart(char)"><code>isJavaIdentifierStart</code></a>、<a href="https://docs.oracle.com/javase/7/docs/api/java/lang/Character.html#isJavaIdentifierPart(char)">isJavaIdentifierPart</a> というメソッドで判定してるみたいなんですが、ここに並んでいる条件がおおむね「レターと数字とマーク」です。</p>
<p><a href="https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/lexical-structure#identifiers?WT.mc_id=DT-MVP-4028921">C# の場合</a>は Unicode カテゴリーがそのまま列挙されていて、</p>
<ul>
<li>1文字目: Lu, Ll, Lt, Lm, Lo, Nl</li>
<li>2文字目以降: 上記に加えて、Mc, Nd, Pc, Cf</li>
</ul>
<p>みたいになっていますが、これがだいたい「レターと数字とマーク」になります。</p>
<h3>カテゴリーの安定性問題</h3>
<p>Unicode 曰く、「カテゴリーはできる限り安定させたいけど希に変わることがある」とのこと。</p>
<p>実際、日本語だと以下の文字のカテゴリーに変更がありました。</p>
<ul>
<li>
゛ と ゜ (U+309B と U+309C、単独の濁点・半濁点)
<ul>
<li>これとは別に、マーク(直前のレターにくっつく)扱いの濁点・半濁点がある(U+3099 と U+309A)</li>
<li>昔はマークの方の濁点・半濁点との混同があった</li>
<li>今は Symbol, Modifier で識別子として使えない</li>
</ul>
</li>
<li>
・ (U+30FB、<a href="https://ja.wikipedia.org/wiki/%E4%B8%AD%E9%BB%92">中黒</a>)
<ul>
<li>昔は Punctuation, Connector で識別子の2文字目以降に使えた</li>
<li>今は Punctuation, Other で識別子として使えない</li>
</ul>
</li>
</ul>
<p>特に・(U+30FB) の変更は比較的新しい話で、
Java 7 (2011年)とか C# 6.0 (2015年) の頃に「今までコンパイルできていたコードが急にコンパイルできなくなった」みたいな騒ぎがありました。</p>
<h2>UAX31</h2>
<p>Unicode、「何番のコードに何の文字を割り当てるか」みたいな基本的な定義に加えて、例えば以下のような様々なレポートを出していたりします。</p>
<ul>
<li><a href="https://unicode.org/reports/tr9/">右書き・左書き</a></li>
<li><a href="https://www.unicode.org/reports/tr10/">文字列の照合順序</a></li>
<li><a href="https://www.unicode.org/reports/tr11/">全角・半角</a></li>
</ul>
<p>昔は Unicode Technical Report、今は Unicode Standard Annex (付録)みたいに呼んでいるようで、
後者は UAX と略したりします。</p>
<p>で、その中に「識別子として使える文字」の話もあります。通称 UAX31。</p>
<ul>
<li><a href="https://www.unicode.org/reports/tr31/">UNICODE IDENTIFIER AND PATTERN SYNTAX</a></li>
</ul>
<p>あくまで recommended defaults (推奨される既定動作)であって何か拘束力のある標準仕様ではないんですが、
「迷うくらいならこれに従っておけ」くらいの材料にはなります。</p>
<p>概ね Java/C# のものを踏襲していそうな感じで、以下の条件がベースです。</p>
<ul>
<li>1文字目: Lu, Ll, Lt, Lm, Lo, Nl</li>
<li>2文字目以降: 上記に加えて、Mc, Nd, Pc, Cf</li>
</ul>
<p>少なくとも<a href="https://www.unicode.org/reports/tr31/tr31-1.html">2003年のバージョン1</a>はほぼこの条件。
違いというか、先ほどのカテゴリーの安定性問題を避けるためにいくつか付帯説明があります。</p>
<ul>
<li>「<a href="https://www.unicode.org/reports/tr31/tr31-1.html#Alternative_Identifier_Syntax">Alternative Identifier</a>」(代替案)として、一部の記号だけ避けてほぼすべての文字を識別子として使える案もある</li>
<li>後方互換性のため、4文字ほど、カテゴリー変更があった文字に追加で Other_ID_Start という属性を持たせて識別子として使えるようにしている</li>
</ul>
<p><a href="https://www.unicode.org/reports/tr31/tr31-33.html">2020年のバージョン</a>ではもう少し複雑になっていますが、大体安定性のためです。
Other_ID_Start だけでは文字のカテゴリー変更に対応できなかったみたいで、追加で Other_ID_Continue という属性が定義されています。
また、Alternative Identifier 向けに定義している Pattern_Syntax (プログラミング言語の構文に使いそうな記号類)、Pattern_White_Space  (同、空白文字の類)を避けることが明言されています。
これら Other_ID_Start 、Other_ID_Continue、Pattern_Syntax、Pattern_White_Space は、カテゴリーと違って、今後破壊的変更を起こさないように運用するとのこと。</p>
<p>また、初期バージョンで「Alternative Identifier」と呼んでいたものは、現在は「<a href="https://www.unicode.org/reports/tr31/tr31-33.html#Immutable_Identifier_Syntax">Immutable Identifier</a>」という呼び名に変わっています。
名前通り、Unicode のバージョンによらず常に不変な保証があります。
ただ、何の文字でも受け付けすぎるのであまり推奨はされていません。</p>
<h2>C++ の UAX31 採用</h2>
<p>Java と C# は、Unicode のカテゴリー変更を受け入れる方向性になっています。
中黒(U+30FB)のカテゴリー変更のとき、そこまで大きな問題にしなかったので。
UAX31 の<a href="https://www.unicode.org/reports/tr31/tr31-33.html#Table_Optional_Medial">オプションとして使ってもいい文字</a>のテーブルに中黒(KATAKANA MIDDLE DOT)が追加されたりはしましたが、
それだけです。</p>
<p>これに対して、C++ (かつては ASCII 文字しか受け付けなかった)が Unicode 識別子に対応しようとした際には UAX31 に従おうという話になったそうです。</p>
<h3>UAX31 Immutable Identifier</h3>
<p>ただ、問題は UAX31 の安定性。
ちょうど Java が中黒(U+30FB)問題を踏んだ時期だったので、カテゴリー変更を警戒して、
Alternative Identifier (現在の Immutable Identifier)を採用しようとしました
(<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3146.html">2010年発案</a>)。
(結局標準化はしてなさそう？ですが)いくつかの C++ コンパイラーはこの案で実装あり。
例えば<a href="https://releases.llvm.org/3.3/tools/clang/docs/ReleaseNotes.html">Clang は 3.3 で</a>、
<a href="https://gcc.gnu.org/gcc-10/changes.html">gcc は 10 で</a>対応。</p>
<p>と言うことで現在、たいていの C++ コンパイラーで以下のコードがコンパイルできます。</p>
<pre class="source" title="Emoji C++">
<code><span class="reserved">#include</span> <span class="string">&lt;iostream&gt;</span>
 
<span class="reserved">int</span> <span class="method">main</span>()
{
    <span class="reserved">int</span> 😱 = 2;
    <span class="reserved">int</span> 😇 = 3;
    <span class="reserved">int</span> 🥺 = 5;
    std::cout &lt;&lt; 😱 * 😇 * 🥺 &lt;&lt; std::endl;
}
</code></pre>
<h3>UAX31 Default Identifier</h3>
<p>その後、前述のとおり UAX31 にも手が入っていて、安定性が改善しました。</p>
<p>と言うことで改めて、C++ の標準仕様として、C++ の識別子を UAX31 に従うようにしようという話になっているみたいです。
今度はちゃんと Default Identifier (Java とか C# とかに近いやつ)で。</p>
<ul>
<li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1949r6.html">C++ Identifier Syntax using Unicode Standard Annex 31 (P1949R6)</a></li>
</ul>
<p><a href="https://github.com/cplusplus/papers/issues/688">現状、賛成多数</a>で、C++ 23 で採用されそうな雰囲気。</p>
<p>ということで、Immutable Identifier (絵文字を含んでる)から Default Identifier (絵文字を含んでいない)に<em>変更</em>されそうです。前節の絵文字ソースコードは C++ 23 から<em>コンパイルできなくなる</em>予定。</p>
<h3>Immutable Identifier から Default Identifier への変更</h3>
<p>これまで使えてた文字が使えなくなる(破壊的変更する)わけで、
この提案にはそれ相応の説得材料が必要になります。
なので、<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1949r6.html">P1949R6</a> には結構詳細に、これまで(Immutable Identifier)の問題とか、変更の影響がまとめられています。</p>
<p>その中から2つほど紹介。</p>
<ul>
<li>絵文字が使えなくなる問題</li>
<li>元から一部の絵文字は使えなかった問題</li>
</ul>
<h4>絵文字が使えなくなる問題</h4>
<p>まんま抜粋。</p>
<pre class="source" title="Throwing Pile of Poo">
<code><span class="reserved">class</span> 💩 : <span class="reserved">public</span> std::<span class="type">exception</span> { };
</code></pre>
<blockquote>
<p>Throwing “PILE OF POO” becomes ill-formed. Conference slide-ware will be less entertaining.</p>
<p>(絵文字が使えなくなることで) うんこ投げるコードは受け付けなくなった。スライド映えしなくなる。</p>
</blockquote>
<p>基本的に破壊的変更をよしとしない C++ で、破壊的変更が賛成多数になるくらいですから…</p>
<p>絵文字識別子の扱い、やっぱり「スライド映え」ですよね。</p>
<h4>元から一部の絵文字は使えなかった問題</h4>
<p>Immutable Identifier は</p>
<ul>
<li>
所定の文字を1つ1つリストアップして識別子として使えないように禁止してる
<ul>
<li>基本的には記号類は禁止</li>
</ul>
</li>
<li><a href="https://ja.wikipedia.org/wiki/Unicode#%E6%8B%A1%E5%BC%B5%E9%A0%98%E5%9F%9F">サロゲートペア</a>は無条件に許可</li>
</ul>
<p>みたいなことをしているので…
以下のように、使える絵文字と使えない絵文字があります(not valid コメントの行のものだけダメ)。</p>
<pre class="source" title="Immutable Identifier での絵文字">
<code><span class="reserved">int</span> ⏰ = 0; <span class="comment">//not valid</span>
<span class="reserved">int</span> 🕐 = 0;
 
<span class="reserved">int</span> ☠ = 0; <span class="comment">//not valid</span>
<span class="reserved">int</span> 💀 = 0;
 
<span class="reserved">int</span> ✋ = 0; <span class="comment">//not valid</span>
<span class="reserved">int</span> 👊 = 0;
 
<span class="reserved">int</span> ✈ = 0; <span class="comment">//not valid</span>
<span class="reserved">int</span> 🚀 = 0;
 
<span class="reserved">int</span> ☹ = 0; <span class="comment">//not valid</span>
<span class="reserved">int</span> 😀 = 0;
</code></pre>
<p>要するに、「基本的に記号を禁止しているのに、サロゲートペアなやつは禁止されない」という状態。
上から順に文字コードは以下のようになっています。</p>
<ul>
<li>⏰ : U+23F0</li>
<li>🕐 : U+1F550</li>
<li>☠  : U+2620</li>
<li>💀  : U+1F480</li>
<li>✋  : U+270B</li>
<li>👊 :  U+1F44A</li>
<li>✈  : U+2708</li>
<li>🚀  : U+1F680</li>
<li>☹  : U+2639</li>
<li>😀  : U+1F600</li>
</ul>
<p>この辺りはまあ、「なんか変だな」で済む話なんですが、1個、ポリコレ的な地雷を踏みそうな事案も発見されています。</p>
<pre class="source" title="ポリコレ地雷を踏みそうな絵文字">
<code><span class="reserved">bool</span> 👷 = <span class="reserved">true</span>; <span class="comment">//  Construction Worker</span>
<span class="reserved">bool</span> 👷‍♀ = <span class="reserved">false</span>; <span class="comment">// Woman Construction Worker ({Construction Worker}{ZWJ}{Female Sign})</span>
</code></pre>
<p>男の建築作業員はよくて女の建築作業員はダメなのか！</p>
<p>これ、<a href="https://emojipedia.org/emoji-zwj-sequence/">Emoji ZWJ Sequence</a> というやつでして。
「絵文字が特定の性別に偏っている」という問題に対する解決策として、「絵文字をいくつか <a href="https://ja.wikipedia.org/wiki/%E3%82%BC%E3%83%AD%E5%B9%85%E6%8E%A5%E5%90%88%E5%AD%90">ZWJ</a> でつなぐことで別の字形に変える」という対処をしています。
で、👷‍♀ の絵文字シーケンスが Female Sign (♀、U+2640)を含んでいて、これが「サロゲートペアじゃない記号」なので Immutable Identifier でも禁止されている文字になります。</p>
<p>当初は「スライド映えしなくなるくらい別にいいよね」というだけの問題だったものが「ポリコレ的に今のままの方がまずい」になったことでちょっと賛成票が増えたみたいです。</p>
<h2>まとめ</h2>
<p>元々は C# の識別子について調べてる過程で、源流は Java っぽいという話だったんですが、
近い仕様が Unicode の推奨仕様(<a href="https://www.unicode.org/reports/tr31/">UAX31</a>)になっていました。
ここまでは結構前から知っていたものの、UAX31 に類する仕様を採用しようとするプログラミング言語は少数派だと思っていました。</p>
<p>それが最近になって、C++ が実質的に破壊的変更になりえる状況で UAX31 Default Identifier を採用しそうな流れになっていて、提案文書に「<em>💩投げれなくなる</em>」のパワーワードが含まれていたという話でした。</p>
 ]]></description>
				<pubDate>Fri, 12 Feb 2021 00:52:24 +0900</pubDate>
			</item>
			<item>
				<title>Visual Studio 16.9 Preview 3 (C# Next チョットある)</title>
				<link>http://ufcpp.net/blog/2021/1/vs169p3/</link>
				<description><![CDATA[ <p>Visual Studio 16.9 Preview 3 が出たということでライブ配信をしていました。</p>
<div>
<iframe width="560" height="315" src="https://www.youtube.com/embed/xS_AlnXMFwo" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div>
<p>冒頭で話しているんですが、Preview 1 は 16.8 正式リリースと同時だったので 16.8 の方を紹介、
Preview 2 はそんなに大きな変化もなかったので、Preview 3 で初めて 16.9 の話です。</p>
<h2>ポロリ</h2>
<p>YouTube 配信前に作ってある<a href="https://github.com/ufcpp-live/UfcppLiveAgenda/issues/24">お品書き issue</a>のタイトルには「C# Next ポロリもあるよ」とか書いているんですが。
まあ変なタイトルを付けたかっただけで、ポロリといっても「出ちゃいけないものが出ちゃった」みたいなことはないです。</p>
<ul>
<li>C# にもちょっとした新 preview 機能追加あったよ</li>
<li>9.0 には間に合わなかったものがさらっと merge されたよ</li>
</ul>
<p>くらいの意味でポロリと言っています。</p>
<p>昨年、C# 9.0 のときは最初に Preview 機能追加があったのは4月のことだったので、小さな機能追加といってもずいぶんフットワークが軽くなったなぁと思います。
ほんとにもうできたものから Preview リリースしていくんだ、と。</p>
<h3>LangVersion Preview</h3>
<p><a href="https://www.youtube.com/watch?t=568&amp;v=xS_AlnXMFwo&amp;feature=youtu.be">9:28～</a></p>
<p>復活の <a href="https://ufcpp.net/study/csharp/cheatsheet/langversionoption/#langversion">LangVersion</a> Preview。</p>
<p>今年はほんとに <code>&lt;LangVersion&gt;latest&lt;/LangVersion&gt;</code> (とか <code>default</code>) とは短いおつきあい(2か月ほど)でした。</p>
<h3>Constant Interpolated Strings</h3>
<p><a href="https://www.youtube.com/watch?t=618&amp;v=xS_AlnXMFwo&amp;feature=youtu.be">10:18～</a></p>
<p>入ったのは <a href="https://github.com/dotnet/csharplang/issues/2951">Constant  Interpolated Strings</a>(<a href="https://ufcpp.net/study/csharp/st_string.html#string-interpolation">文字列補間</a>の const 扱い)です。</p>
<pre class="source" title="Constant  Interpolated Strings">
<code><span class="reserved">class</span> <span class="type">Sample</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> A { <span class="reserved">get</span>; }
    <span class="reserved">public</span> <span class="reserved">int</span> B { <span class="reserved">get</span>; }
    <span class="reserved">public</span> <span class="reserved">const</span> <span class="reserved">string</span> S = <span class="string">$&quot;</span>{<span class="reserved">nameof</span>(A)}<span class="string"> </span>{<span class="reserved">nameof</span>(B)}<span class="string">&quot;</span>;
}
</code></pre>
<p>文字列補間の <code>$&quot;{}&quot;</code> の <code>{}</code> の中が全部定数の時、<code>$&quot;{}&quot;</code> も定数扱いされるという仕様になりました。</p>
<p><a href="https://www.youtube.com/watch?t=1119&amp;v=xS_AlnXMFwo&amp;feature=youtu.be">10:39～</a></p>
<p>ちなみに、<code>{}</code> の中には、たとえ <a href="https://ufcpp.net/study/csharp/sp_const.html#const">const</a> であっても数値とかは受け付けず、const string の入れ子だけを受け付けます。</p>
<pre class="source" title="">
<code><span class="reserved">public</span> <span class="reserved">const</span> <span class="reserved">string</span> S = <span class="error"><span class="string">$&quot;</span>{123}<span class="string">&quot;</span></span>;
</code></pre>
<p><a href="https://www.youtube.com/watch?t=1380&amp;v=xS_AlnXMFwo&amp;feature=youtu.be">23:00～</a></p>
<p>なんでかというと、文字列以外の文字列補間は <code>ToString</code> を経由していて、その <code>ToString</code> はカルチャー依存だから…
コンパイル時に定数化できません。</p>
<p>カルチャー依存の例:</p>
<pre class="source" title="double のカルチャー依存 ToString/Parse">
<code><span class="reserved">using</span> System;
<span class="reserved">using</span> System.Globalization;
 
<span class="reserved">var</span> <span class="variable">ja</span> = <span class="type">CultureInfo</span>.<span class="method">GetCultureInfo</span>(<span class="string">&quot;ja-jp&quot;</span>);
<span class="reserved">var</span> <span class="variable">fr</span> = <span class="type">CultureInfo</span>.<span class="method">GetCultureInfo</span>(<span class="string">&quot;fr-fr&quot;</span>);
<span class="comment">//Console.WriteLine(double.Parse(1.234.ToString(ja), fr)); // 例外</span>
<span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="reserved">double</span>.<span class="method">Parse</span>(1.234.<span class="method">ToString</span>(<span class="variable">fr</span>), <span class="variable">ja</span>)); <span class="comment">// 1234 扱い…</span>
 
<span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="reserved">double</span>.<span class="method">Parse</span>(1.234.<span class="method">ToString</span>(<span class="variable">fr</span>))); <span class="comment">// CurrentCulture...</span>
 
System.Threading.<span class="type">Thread</span>.CurrentThread.CurrentCulture = <span class="variable">fr</span>;
<span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="reserved">double</span>.<span class="method">Parse</span>(1.234.<span class="method">ToString</span>(<span class="variable">fr</span>))); <span class="comment">// CurrentCulture...</span>
</code></pre>
<pre class="console" title="double のカルチャー依存 ToString/Parse">
<code>1234
1234
1,234
</code></pre>
<h2>IDE Productivity</h2>
<p><a href="https://www.youtube.com/watch?t=2036&amp;v=xS_AlnXMFwo&amp;feature=youtu.be">33:56～</a></p>
<p><code>#if</code> にコード補完がかかるように。</p>
<p><a href="https://www.youtube.com/watch?t=4426&amp;v=xS_AlnXMFwo&amp;feature=youtu.be">1:13:46～</a></p>
<p>警告等のツールチップヒントからヘルプページに飛べるように。</p>
<p><a href="https://www.youtube.com/watch?t=5813&amp;v=xS_AlnXMFwo&amp;feature=youtu.be">1:36:53～</a></p>
<p>Source Generator の生成物のファイルが Solution Explorer 上に表示されるように。</p>
<p><a href="https://www.youtube.com/watch?t=5942&amp;v=xS_AlnXMFwo&amp;feature=youtu.be">1:39:2～</a></p>
<p>同じく Source Generator の生成物のファイル、Ctrl + , とかの検索結果に現れるように。</p>
<p><a href="https://www.youtube.com/watch?t=10020&amp;v=xS_AlnXMFwo&amp;feature=youtu.be">2:47:00～</a></p>
<p>XAML からの ViewModel C# コード生成ができるように。</p>
<h2>OR_GREATER</h2>
<p><a href="https://www.youtube.com/watch?t=2663&amp;v=xS_AlnXMFwo&amp;feature=youtu.be">44:23～</a></p>
<p>OR_GREATER シンボル…</p>
<p>OR_GREATER に関するアナウンスは特に大々的に行われておらず、
<a href="https://devblogs.microsoft.com/visualstudio/visual-studio-2019-v16-9-preview-3/#net-productivity"><code>#if</code> のコード補完の話のスクショ</a>でしれっとお披露目…</p>
<p>「あるバージョンより新しいものだけで」みたいな条件コンパイルをしたいという話は昔からありまして。
それがついに入りました。</p>
<p>当初予定では「<code>NET5_0</code> だけで .NET 5 以降」という扱いで行くつもりだったものの、
.NET 5 リリース直前でダメだしを受けて急遽取りやめ。
その代案として出て来た話がこの「<code>_OR_GREATER</code> を付ける」でした。</p>
<p><a href="https://www.youtube.com/watch?t=3152&amp;v=xS_AlnXMFwo&amp;feature=youtu.be">52:32～</a></p>
<p><code>NETSTANDARD</code> には <code>OR_GREATER</code> シンボルはないとか…</p>
<p><a href="https://www.youtube.com/watch?t=3398&amp;v=xS_AlnXMFwo&amp;feature=youtu.be">56:38～</a></p>
<p><code>NET4</code> 系(要するに .NET Framework) と <code>NET5</code> 系(&quot;.NET&quot; に統合後)は不連続なので注意とか…</p>
<p><a href="https://www.youtube.com/watch?t=3540&amp;v=xS_AlnXMFwo&amp;feature=youtu.be">59:00～</a></p>
<p>大人は嘘つきではないのです。間違いをするだけなのです。</p>
<h2>CsWin32</h2>
<p><a href="https://www.youtube.com/watch?t=6190&amp;v=xS_AlnXMFwo&amp;feature=youtu.be">1:43:10～</a></p>
<p>ちょっと本題(VS 16.9 Preview 3、C# 10.0)から離れましたが、Win32 P/Invoke の話題でも盛り上がったり…</p>
<p>ちょうどこの配信の日に <a href="https://github.com/microsoft/win32metadata">win32metadata</a> とか <a href="https://github.com/microsoft/CsWin32/">CsWin32</a> とかの告知が出ていて、「Twitter とかでみんな盛り上がってるなぁ」とか思っていたら、自分のライブ配信でも盛り上がるなど。</p>
<p>Win32 API の P/Invoke 用のコードを Source Generator で生成してくれるものです。</p>
<p><a href="https://www.youtube.com/watch?t=9281&amp;v=xS_AlnXMFwo&amp;feature=youtu.be">2:34:41</a></p>
<p>Linux マシン上とかでもちゃんとソースコード生成からビルドまでできてちょっと盛り上がりました。
(さすがに実行はできなくて、DllNotFound。)</p>
<p><a href="https://www.youtube.com/watch?t=7362&amp;v=xS_AlnXMFwo&amp;feature=youtu.be">2:02:42～</a></p>
<p>C# の <code>string</code> とかからネイティブの <code>char*</code> とかへの変換などのいわゆるマーシャリング処理は今まで .NET Runtime 内で動的にやっていたみたいなんですが、この度 Source Generator 化されたことでパフォーマンス的にもちょっとうれしいはずです。
これまでも .NET Native とかではビルド時にやっていたそうなので、それが .NET Native (UWP 向けの AOT)という特定環境向けのビルド ツールに限らない汎用的なものになりました。</p>
 ]]></description>
				<pubDate>Sat, 23 Jan 2021 14:25:22 +0900</pubDate>
			</item>
			<item>
				<title>C# の null 判定の話</title>
				<link>http://ufcpp.net/blog/2020/12/isnull/</link>
				<description><![CDATA[ <p>null、一般名詞としては「無効なもの」とか「0個」とかの意味の単語です。
zero も語源をたどるとアラビア語とかサンスクリット語の「空っぽ (nothing)」にあたる単語から来ていて、実のところ一般名詞としては出自が違うだけで null = zero だったり。</p>
<p>一方、C# (とそれに類するプログラミング言語)では、 <code>null</code> というキーワードを「無効なものを 0 を使って表す」という意味で使っていて、
一般名詞としての null が持つ2つの意味を同時に指していたりします。</p>
<p>とはいえ、別に null という英単語の意味を考慮して「無効なものを 0 を使って表す」にしたわけではなくて、
単に実装上「0 かどうかの判定は非常に高速なのでパフォーマンス的に都合がいい」という現実的な理由で 0 を使っています。</p>
<p>前置きが長くなりましたが、C# において null 判定をするというのは、内部的には単に 0 比較で、
大体の CPU 上で最速の部類に入る命令を使って実装できます。</p>
<h2>x == null</h2>
<p>null 判定というとまずどういうコードを思い浮かべるでしょうか？
「昔から書けた」という意味で、まず <code>x == null</code> が真っ先に思い浮かぶ人が多いと思います。</p>
<pre class="source" title="== null">
<code><span class="reserved">bool</span> <span class="method">M</span>(<span class="type">A</span> <span class="variable">x</span>) =&gt; <span class="variable">x</span> == <span class="reserved">null</span>;
<span class="reserved">class</span> <span class="type">A</span> { }
</code></pre>
<p>これも、この状態であれば単なる 0 比較になります。
実際、コンパイル結果を覗いてみればわかるんですが、以下のコードと同じコードが生成されます。</p>
<pre class="source" title="== 0">
<code><span class="reserved">bool</span> <span class="method">M</span>(<span class="reserved">int</span> <span class="variable">x</span>) =&gt; <span class="variable">x</span> == 0;
</code></pre>
<p>ただ、ここで問題になるのが<a href="https://ufcpp.net/study/csharp/oo_operator.html">演算子オーバーロード</a>でして、これをやっちゃってると「単なる 0 比較」ではなくなってしまいます。
特に以下のように、<code>==</code> の中でそこそこ重たい処理をやっちゃっているときが問題になります。</p>
<pre class="source" title="== の中でそこそこ重たい処理をやっちゃってる場合">
<code><span class="reserved">bool</span> <span class="method">M</span>(<span class="type">A</span> <span class="variable">x</span>) =&gt; <span class="variable">x</span> <span class="method">==</span> <span class="reserved">null</span>;
<span class="reserved">class</span> <span class="type">A</span>
{
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">bool</span> <span class="reserved">operator</span> ==(<span class="type">A</span> <span class="variable">x</span>, <span class="type">A</span> <span class="variable">y</span>) =&gt; そこそこ重たい処理;
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">bool</span> <span class="reserved">operator</span> !=(<span class="type">A</span> <span class="variable">x</span>, <span class="type">A</span> <span class="variable">y</span>) =&gt; そこそこ重たい処理;
}
</code></pre>
<p><code>==</code> を使っている側、この例でいうと メソッド <code>M</code> の中身は最初にあげた「速い」コードと同じ見た目なのが罠で、「本当は 0 比較でいいはずなのにわざわざ重たい <code>operator ==</code> が呼ばれてしまう」という状況が往々にして発生します。</p>
<p>過激派な意見としては「<code>==</code> をオーバーロード(ユーザー裁量で中身を変更)可能にしてしまったことがよくなかった」という話もあるんですが、まあ、できるものは仕方がないとして。
本来の「無効かどうかの判定は単なる 0 比較で済む」という状態にしたければ、<code>==</code> を避けた方がいいということが多々あります。</p>
<h2>ReferenceEquals(x, null)</h2>
<p>この罠にはまっちゃってるコードは案外世の中にあふれているというか、
.NET の標準ライブラリでも結構あったみたいです。</p>
<p>この問題は昔の C# でも簡単に解消する方法が1つあって、それが、<code>ReferenceEquals</code> を使うという案。</p>
<pre class="source" title="ReferenceEquals(null)">
<code><span class="reserved">bool</span> <span class="method">M</span>(<span class="reserved">object</span> <span class="variable">x</span>) =&gt; <span class="method">ReferenceEquals</span>(<span class="variable">x</span>, <span class="reserved">null</span>);
</code></pre>
<p>これで、ユーザー定義の <code>==</code> オーバーロードは呼ばれることなく、常に 0 比較で null 判定が走ります。</p>
<p>めでたしめでたし。</p>
<p>となるわけはなく、見栄えが悪すぎる…</p>
<p>ということで、「<code>ReferenceEquals</code> に書き換えて問題ないし、書き換えたら露骨にパフォーマンスがよくなるんだけど、この見栄えの悪さを許容するべき？」みたいな議題になっていました。</p>
<h2>x is null</h2>
<p>そこに来て、C# 7.0 で<a href="https://ufcpp.net/study/csharp/datatype/patterns/">パターン マッチング</a>という文法が入りました。
この頃には「<code>== null</code> の罠」が周知の事実だったので、「<code>is null</code> と書いたときにはユーザー定義の <code>==</code> を呼ばない。常に 0 比較にする」という判断が下りました。</p>
<pre class="source" title="is null">
<code><span class="reserved">bool</span> <span class="method">M</span>(<span class="reserved">object</span> <span class="variable">x</span>) =&gt; <span class="variable">x</span> <span class="reserved">is</span> <span class="reserved">null</span>; <span class="comment">// operator == は呼ばない。常に ReferenceEquals(x, null) と同じ。</span>
<span class="reserved">class</span> <span class="type">A</span>
{
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">bool</span> <span class="reserved">operator</span> ==(<span class="type">A</span> <span class="variable">x</span>, <span class="type">A</span> <span class="variable">y</span>) =&gt; そこそこ重たい処理;
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">bool</span> <span class="reserved">operator</span> !=(<span class="type">A</span> <span class="variable">x</span>, <span class="type">A</span> <span class="variable">y</span>) =&gt; そこそこ重たい処理;
}
</code></pre>
<p>これに「見栄え的に <code>ReferenceEquals</code> は NG」派が飛びつきました。
<code>== null</code> から <code>is null</code> への書き換えで救われたコードが結構あったみたいです。
(実際、僕が保守しているコードでもいくつかこの書き換えでパフォーマンス改善しています。)</p>
<p>めでたしめでたし？</p>
<h2>非 null</h2>
<p>めでたくなかった。</p>
<p>実際に多いのは以下のようなコードだったりします。</p>
<pre class="source" title="null じゃないときだけ処理">
<code><span class="reserved">void</span> <span class="method">M</span>(<span class="type">A</span> <span class="variable">a</span>)
{
    <span class="reserved">var</span> <span class="variable">x</span> = <span class="variable">a</span>.X; // プロパティ参照コストを避けるために変数に受ける。
 
    <span class="control">if</span> (<span class="variable">x</span> <span class="reserved">is</span> <span class="reserved">null</span>) <span class="control">return</span>;
 
    <span class="comment">// x を使って何か処理をする。</span>
}

<span class="reserved">class</span> <span class="type">A</span>
{
    <span class="comment">// virtual がついていたり、いくつかの場面では X プロパティの参照に多少コストがかかる。</span>
    <span class="reserved">public</span> <span class="reserved">virtual</span> <span class="reserved">object</span>? X { <span class="reserved">get</span>; <span class="reserved">set</span>; }
}
</code></pre>
<p>これはいわゆる early return (先頭で検査して不適切なら即 return)な書き方ですが、
判定を逆転させて同じ結果になるコードを以下のように書きたいこともあります。</p>
<pre class="source" title="!(is null)">
<code><span class="reserved">void</span> <span class="method">M</span>(<span class="type">A</span> <span class="variable">a</span>)
{
    <span class="reserved">var</span> <span class="variable">x</span> = <span class="variable">a</span>.X;
 
    <span class="control">if</span> (!(<span class="variable">x</span> <span class="reserved">is</span> <span class="reserved">null</span>))
    {
        <span class="comment">// x を使って何か処理をする。</span>
    }
}
</code></pre>
<p>何にしてもポイントが2つあって、</p>
<ul>
<li>1度変数 <code>x</code> で受けたい</li>
<li>「null である」判定じゃなく、「null じゃない」判定をしたい</li>
</ul>
<p>という要件があって、<code>x is null</code> の導入だけだとまだちょっと面倒が残っている感じになっています。</p>
<h2>x is object (非 null)</h2>
<p>「null じゃない」判定に使える書き方はいくつかあるんですが、前半で話した <code>x == null</code> の話と同様、<code>x != null</code> はユーザー定義の演算子オーバーロードを呼ばれて遅くなることがあります。
そこで <code>x is null</code> と同様、比較的新しめの文法であるパターン マッチングを使った「null じゃない」判定が欲しくなります。</p>
<p>C# の場合、「null は型を持っていない」という扱いになるので、すべての型の共通基底クラスである <code>object</code> 型にすらマッチしません。
なので、以下のように、<code>is object</code> というパターンを書くと「null じゃない」という判定になります。</p>
<pre class="source" title="is object">
<code><span class="reserved">void</span> <span class="method">M</span>(<span class="type">A</span> <span class="variable">a</span>)
{
    <span class="control">if</span> (<span class="variable">a</span>.X <span class="reserved">is</span> <span class="reserved">object</span> <span class="variable">x</span>)
    {
        <span class="comment">// ここに来るのは a.X が null じゃなかった時だけ。</span>
        <span class="comment">// x を使って何か処理をする。</span>
    }
}
</code></pre>
<h3>注意: x is var (null 判定しない)</h3>
<p>ここで注意すべきことが1点。結構な罠なんですが、上記のように <code>is object</code> が「null じゃない」判定になるのに対して、<code>is var</code> だと null / 非 null に関わらず常にマッチします(<code>is var</code> 単体だと常に true)。</p>
<pre class="source" title="is var の場合は null 判定しないので注意">
<code><span class="reserved">void</span> <span class="method">M</span>(<span class="type">A</span> <span class="variable">a</span>)
{
    <span class="control">if</span> (<span class="variable">a</span>.X <span class="reserved">is</span> <span class="reserved">var</span> x)
    {
        <span class="comment">// ここは常に通る。</span>
        <span class="comment">// if なしで var x = a.X; と書くのとほぼ同じ意味なので非推奨。</span>
    }
}
</code></pre>
<p><code>var</code> パターンは <code>switch</code>-<code>case</code> の <code>default</code> 句みたいなもので、「他のどの条件も満たさないときの最後の受け口」みたいに使うものです。
なので、今回の主題の null 判定に限らず、<code>if</code> 単体で使うものではありません。</p>
<h2>x is { } (非 null)</h2>
<p>もう1個、<code>is { }</code> という書き方でも「null じゃない」判定ができます。
知らないと何が何だかわからない謎な書き方ですが、
文法的にいうとこれは「<a href="https://ufcpp.net/study/csharp/datatype/patterns/?p=2#property">プロパティ パターン</a>」というものになります。</p>
<pre class="source" title="is { } で null じゃない判定">
<code><span class="reserved">void</span> <span class="method">M</span>(<span class="type">A</span> <span class="variable">a</span>)
{
    <span class="control">if</span> (<span class="variable">a</span>.X <span class="reserved">is</span> { } x)
    {
        <span class="comment">// ここに来るのは a.X が null じゃなかった時だけ。</span>
        <span class="comment">// 起こる結果は is object x と同じ。</span>
        <span class="comment">// x を使って何か処理をする。</span>
    }
}
</code></pre>
<p>本来は以下のように、再帰的にプロパティの中身を確認できる「パターン」です。</p>
<pre class="source" title="{ } の本来の使い方は「再起プロパティ パターン」">
<code><span class="reserved">void</span> <span class="method">M</span>(<span class="type">A</span> <span class="variable">a</span>)
{
    <span class="control">if</span> (<span class="variable">a</span> <span class="reserved">is</span> { X: <span class="reserved">object</span> <span class="variable">x</span> })
    {
        <span class="comment">// a の中身の X プロパティの中身をチェック。</span>
        <span class="comment">// ちなみにこの場合、a 自体の null チェックもかかるので、a != null &amp;&amp; a.X != null と似た処理。</span>
    }
}
</code></pre>
<p>ただ、<code>{}</code> の中に何もなくても「null じゃない」判定だけはかかるので、その用途に流用できます。
ちょっと濫用・悪用気味ではありますが、「null じゃない」判定をしつつ変数で受ける手段としては一番短い書き方になります。</p>
<h2>is not null</h2>
<p><code>x is { }</code> は最も短く「null じゃない」判定を書ける手段ではあるんですが、
なにぶん濫用気味な書き方で、知らない人が見て理解しにくい、知っていても「null じゃない」という意図が伝わりにくいという問題があります。</p>
<p>そこで結局、<code>!(x is null)</code> という書き方の方がいいんじゃないかという話にもなるんですが…
これはこれで、<code>!()</code> も十分に見にくい(<code>()</code> が邪魔だし、意味を真逆にする割には <code>!</code> という記号は視認性が悪すぎて見逃す)という問題があります。</p>
<p>あと、以下のような「書き間違い」をする人が後を絶たないという問題も起こしました。</p>
<pre class="source" title="!is 問題">
<code><span class="reserved">void</span> <span class="method">M</span>(<span class="type">A</span> <span class="variable">a</span>)
{
    <span class="control">if</span> (<span class="variable">a</span>.X !<span class="reserved">is</span> <span class="reserved">null</span>) <span class="comment">// is not のつもりで !is とか書く</span>
    {
        <span class="comment">// ちなみにこの ! は not の意味にならず、このコードは is null (意図と真逆)になる。</span>
    }
}
</code></pre>
<p>この <code>!</code> は<a href="https://ufcpp.net/study/csharp/resource/nullablereferencetype/?p=3#null-forgiving">null 判定の抑止</a>、要するに、コンパイラーが正しくフロー解析できなさそうな微妙なコードで、コンパイラーの警告をもみ消すために使う演算子です。
フロー解析(あくまでコンパイラー内での処理)に使うだけであって、この <code>!</code> の有無はコンパイル結果には全く影響を及ぼしません。
なので、<code>x !is null</code> と <code>x is null</code> が全く同じ意味。</p>
<p>一方、C# 9.0 では <code>not</code> パターンというものが導入されて、今度こそ is not の意味のパターンが書けるようになりました。</p>
<pre class="source" title="is not null">
<code><span class="reserved">void</span> <span class="method">M</span>(<span class="type">A</span> <span class="variable">a</span>)
{
    <span class="control">if</span> (<span class="variable">a</span>.X <span class="reserved">is</span> <span class="reserved">not</span> <span class="reserved">null</span>)
    {
        <span class="comment">// ちゃんと null じゃないときだけここを通る。</span>
        <span class="comment">// != null と違ってユーザー定義演算子は呼ばれず、単なる 0 比較。</span>
    }
}
</code></pre>
<h2>is not { } (null の時に early return)</h2>
<p>ここからは C# 9.0 のバグの話。
Visual Studio 16.8 (C# 9.0 の初期リリース。2020年11月リリース版)時点の C# には
<code>is not { } x</code> という書き方にバグがあります(<code>is not object x</code> でも同様にバグあり)。</p>
<p><code>not { }</code> は「null じゃない」をさらに否定しているので結局「null である」という判定になります。
単に「null である」判定をしたいだけなら <code>is null</code> と書けばいい話なんですが、
「変数で受けつつ null である判定」という処理をしたいときに <code>is not { } x</code> という書き方をします。</p>
<pre class="source" title="is not { } で null 時 early return">
<code><span class="reserved">void</span> <span class="method">M</span>(<span class="type">A</span> <span class="variable">a</span>)
{
    <span class="control">if</span> (<span class="variable">a</span>.X <span class="reserved">is</span> <span class="reserved">not</span> { } x) <span class="control">return</span>; <span class="comment">// null だったら early return。</span>
 
    <span class="comment">// x を使って何か処理をする。</span>
    <span class="comment">// ここでは x に非 null な値が入っているはず。</span>
}
</code></pre>
<p><code>is not { } x</code> や <code>is not object x</code> とい書き方はまさにこの「null のときに early return」のためにあって、null じゃなければその値が変数 <code>x</code> に入った上で <code>else</code> 側に流れます。</p>
<p>ですが、バグで、時々その「null じゃない値を変数 <code>x</code> で受ける」という処理が消えてしまうことがあるそうです。
上記コードはちゃんと動くんですが、例えば以下のコードだと <code>x</code> が null のままになっていて実行時例外を起こします。</p>
<pre class="source" title="16.8 時点の is not { } のバグ">
<code><span class="reserved">using</span> System;
 
<span class="method">M</span>(<span class="string">&quot;abc&quot;</span>);
 
<span class="reserved">void</span> <span class="method">M</span>(<span class="reserved">string</span>? <span class="variable">s</span>)
{
    <span class="control">if</span> (<span class="variable">s</span> <span class="reserved">is</span> <span class="reserved">not</span> { } x) <span class="control">return</span>; <span class="comment">// null だったら early return。</span>
 
    <span class="comment">// x には s が代入されていないとおかしいはずなのに…</span>
    <span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="variable">x</span>.Length); <span class="comment">// ここでぬるぽ(バグ)。</span>
}
</code></pre>
<p>バグです。
バグ報告済みというか、<a href="https://github.com/dotnet/roslyn/pull/49369">報告されて早々に修正・ merge 済み</a>で、Visual Studio 16.9 では直る見込みです(16.8.1 とかにもこの修正が取り込まれるかは未定)。</p>
 ]]></description>
				<pubDate>Sun, 13 Dec 2020 20:20:17 +0900</pubDate>
			</item>
			<item>
				<title>祝 .NET 5.0 リリース: .NET Core 3.1 からの移行話</title>
				<link>http://ufcpp.net/blog/2020/11/net5_0ga/</link>
				<description><![CDATA[ <p>祝 .NET 5.0 GA。</p>
<ul>
<li><a href="https://devblogs.microsoft.com/dotnet/announcing-net-5-0/">Announcing .NET 5.0</a></li>
<li><a href="https://devblogs.microsoft.com/dotnet/c-9-0-on-the-record/">C# 9.0 on the record</a></li>
<li><a href="https://devblogs.microsoft.com/visualstudio/visual-studio-2019-v16-8/">Visual Studio 2019 v16.8 and v16.9 Preview 1 Release Today</a></li>
<li><a href="https://devblogs.microsoft.com/aspnet/announcing-asp-net-core-in-net-5/">Announcing ASP.NET Core in .NET 5</a></li>
<li><a href="https://docs.microsoft.com/ja-jp/visualstudio/releases/2019/release-notes#16.8.0">Visual Studio 2019 16.8 リリースノート</a></li>
<li><a href="https://docs.microsoft.com/en-us/visualstudio/releases/2019/release-notes-preview#16.9.0-pre-1.0">Visual Studio 2019 18.9 Preview 1 リリースノート</a></li>
<li><a href="https://www.youtube.com/watch?v=mS6ykjdOVRg">.NET Conf 2019 - Day 1 ライブ配信</a></li>
</ul>
<p>一応注釈なんですが、 .NET は以下のような状態です。</p>
<ul>
<li>
.NET 5.0 からは単に「.NET」になります
<ul>
<li>.NET Framework, Standard, Core の統合結果です</li>
<li>TargetFramework 名、 net5.0 で、 netstandard2.1 と netcoreapp3.1 の後続扱い(後方互換あり)です</li>
</ul>
</li>
<li>
年次リリース＆偶数バージョンにだけ長期サポート(LTS: Long Term Support)あり
<ul>
<li>
5.0 は長期サポートなし(6.0 が出たら移行を推奨)
<ul>
<li>この状態を指して GA (General Availability) と呼んでる</li>
</ul>
</li>
<li>6.0 は来年同時期にリリース予定</li>
<li>LTS は「3年もしくは次の LTS リリース後1年間のうち、いずれかのより長い方」がサポート期間</li>
</ul>
</li>
</ul>
<p>一応リリースの日の夜に「記念雑談」をしてました(割かし本当に記念だけして、雑談です。話題それまくり)。</p>
<div>
<iframe width="560" height="315" src="https://www.youtube.com/embed/i02HL8g-D1w" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div>
<h2>.NET Core 3.1 からの移行</h2>
<p>前回、 .NET Core 2.2 から 3.0 の時は ASP.NET に破壊的変更があってそこでコード修正が必須だったりしたんですが。
今回、3.1 から 5.0 の以降では ASP.NET の破壊的変更もなさそうで、自分がかかわっているコードで大きな修正が必要なものはなかったです。</p>
<p>小さい修正はちょっとだけあって、自分のコードでも以下の2点は踏みました:</p>
<ul>
<li>WPF (WinForms でも同様のはず)で、csproj の書き方がちょっと変わる</li>
<li>警告がアグレッシブに追加される</li>
</ul>
<p>あと、「コンパイルは通るけど挙動が変わっている可能性がある」という警戒を要する点もあります(自分では今のところは踏んでいない):</p>
<ul>
<li>国際化対応が NLS (Windows が元々持っていたライブラリ)から ICU (Unicode 標準に沿ったオープンな実装)に切り替わった</li>
</ul>
<h3>Windows 向けプロジェクト</h3>
<p>元:</p>
<pre class="xsource" title="WPF プロジェクト(Windows 向け .NET プロジェクト) 修正前">
<code><span class="attvalue">&lt;</span><span class="element">Project</span><span class="attvalue"> </span><span class="attribute">Sdk</span><span class="attvalue">=</span>&quot;<span class="attvalue">Microsoft.NET.Sdk.<em>WindowsDesktop</em></span>&quot;<span class="attvalue">&gt;</span>
 
<span class="attvalue">  &lt;</span><span class="element">PropertyGroup</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">OutputType</span><span class="attvalue">&gt;</span>WinExe<span class="attvalue">&lt;/</span><span class="element">OutputType</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">TargetFrameworks</span><span class="attvalue">&gt;</span>netcoreapp3.1<span class="attvalue">&lt;/</span><span class="element">TargetFrameworks</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">UseWPF</span><span class="attvalue">&gt;</span>true<span class="attvalue">&lt;/</span><span class="element">UseWPF</span><span class="attvalue">&gt;</span>
<span class="attvalue">  &lt;/</span><span class="element">PropertyGroup</span><span class="attvalue">&gt;</span>
 
<span class="attvalue">&lt;/</span><span class="element">Project</span><span class="attvalue">&gt;</span>

</code></pre>
<p>後:</p>
<pre class="xsource" title="WPF プロジェクト(Windows 向け .NET プロジェクト) 修正後">
<code><span class="attvalue">&lt;</span><span class="element">Project</span><span class="attvalue"> </span><span class="attribute">Sdk</span><span class="attvalue">=</span>&quot;<span class="attvalue">Microsoft.NET.Sdk</span>&quot;<span class="attvalue">&gt;</span>
 
<span class="attvalue">  &lt;</span><span class="element">PropertyGroup</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">OutputType</span><span class="attvalue">&gt;</span>WinExe<span class="attvalue">&lt;/</span><span class="element">OutputType</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">TargetFramework</span><span class="attvalue">&gt;</span>net5.0<em>-windows</em><span class="attvalue">&lt;/</span><span class="element">TargetFramework</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">UseWPF</span><span class="attvalue">&gt;</span>true<span class="attvalue">&lt;/</span><span class="element">UseWPF</span><span class="attvalue">&gt;</span>
<span class="attvalue">  &lt;/</span><span class="element">PropertyGroup</span><span class="attvalue">&gt;</span>
 
<span class="attvalue">&lt;/</span><span class="element">Project</span><span class="attvalue">&gt;</span>

</code></pre>
<h3>警告がアグレッシブに追加される</h3>
<p>C# はこれまで警告の追加も破壊的変更になりうるということで、追加には消極的でした。
今では「仕様の穴だった」と認識されている問題のあるコードでも、
かつて警告なしでコンパイルできてしまっていたものに新たに警告を足すということは避けていました。
(世の中にはコンパイルはできてしまう上でたまたま問題を踏まず動いてしまっていたコードがたくさんあります。)</p>
<p>.NET 5.0 世代ではこの方針に変更があって、以下のようになっています。</p>
<ul>
<li>TargetFramework を変えない限りには警告の追加はないものの、net5.0 に上げた場合には警告が出るようにする
-C# 言語バージョン(LangVersion) とは別に「警告バージョン」(AnalysisLevel)を指定できるようにする</li>
<li>この条件下で、これまでだったら足さなかったようなレベルの警告を大幅に追加する</li>
</ul>
<p>.NET 5.0 をターゲットにしたいし、C# 9.0 の新機能も使いたいけども警告だけは増やしたくないという人は、以下の2つのオプションを csproj に追加してください。</p>
<pre class="xsource" title="警告レベルを昔のまま維持するためのオプション">
<code><span class="attvalue">&lt;</span><span class="element">Project</span><span class="attvalue"> </span><span class="attribute">Sdk</span><span class="attvalue">=</span>&quot;<span class="attvalue">Microsoft.NET.Sdk</span>&quot;<span class="attvalue">&gt;</span>
 
<span class="attvalue">  &lt;</span><span class="element">PropertyGroup</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">EnableNETAnalyzers</span><span class="attvalue">&gt;</span>false<span class="attvalue">&lt;/</span><span class="element">EnableNETAnalyzers</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">AnalysisLevel</span><span class="attvalue">&gt;</span>4.0<span class="attvalue">&lt;/</span><span class="element">AnalysisLevel</span><span class="attvalue">&gt;</span>
<span class="attvalue">  &lt;/</span><span class="element">PropertyGroup</span><span class="attvalue">&gt;</span>
 
<span class="attvalue">&lt;/</span><span class="element">Project</span><span class="attvalue">&gt;</span>
</code></pre>
<p>ちなみに、自分が踏んだ「追加警告」は以下のような警告だけでした(CS8881 の追加)。</p>
<pre class="source" title=".NET 5.0 にすると増える警告">
<code><span class="comment">// エラーにならなくなってた条件</span>
<span class="comment">// - X と Y が別 DLL (別 csproj)</span>
<span class="comment">// - X が参照型だけを含む</span>
<span class="reserved">public</span> <span class="reserved">struct</span> <span class="type">X</span>&lt;<span class="type">T</span>&gt;
{
    <span class="reserved">private</span> <span class="reserved">string</span> _x;
}

<span class="reserved">struct</span> <span class="type">Y</span>
{
    <span class="type">X</span>&lt;<span class="reserved">int</span>&gt; _x;
 
    <span class="reserved">public</span> <span class="type">Y</span>(<span class="reserved">bool</span> <span class="variable">x</span>)
    {
        <span class="comment">// 一定の条件下で、 _x を初期化しなくてもエラーが出なかった。</span>
        <span class="comment">// C# 9.0 (AnalysisLevel 5.0) では警告だけは出るようになった。</span>
        <span class="control">if</span> (<span class="variable">x</span>) <span class="control"><span class="warning">return</span></span>;
 
        _x = <span class="reserved">new</span> <span class="type">X</span>&lt;<span class="reserved">int</span>&gt;();
    }
}
</code></pre>
<h3>ICU (International Components for Unicode) 化</h3>
<p>もしかしたら踏むかもしれない地雷として話題になっているのが、国際化対応の ICU 化です。</p>
<ul>
<li><a href="https://docs.microsoft.com/ja-jp/dotnet/standard/globalization-localization/globalization-icu?WT.mc_id=DT-MVP-4028921">.NET グローバリゼーションと ICU</a></li>
<li><a href="https://docs.microsoft.com/ja-jp/dotnet/standard/base-types/string-comparison-net-5-plus?WT.mc_id=DT-MVP-4028921">.NET 5 以降で文字列を比較するときの動作の変更</a></li>
<li><a href="https://docs.microsoft.com/ja-jp/dotnet/core/compatibility/globalization?WT.mc_id=DT-MVP-4028921">グローバリゼーションに関する破壊的変更</a></li>
<li><a href="https://github.com/dotnet/runtime/issues/43956">Improving the developer experience with regard to default string globalization</a></li>
</ul>
<p>.NET Core では今まで以下のような状態でした。</p>
<ul>
<li>Windows 上では NLS (National Language Support) という Windows 組み込みの国際化ライブラリを使っていた</li>
<li>非 Windows 環境では (<a href="http://site.icu-project.org/home">ICU</a>)を使っていた</li>
<li>なので、カルチャー依存の文字列処理などが、Windows とそうでない環境に差があった</li>
</ul>
<p>.NET 5.0 では、Windows 上でも ICU を使う方針に変わりました。
「ICU を使えるオプション」(opt-in)にするか「デフォルトは ICU で、NLS に戻せるオプション」(opt-out)にするかは迷っていたみたいなんですが、結局は後者、デフォルト動作は ICU になりました。</p>
<p>「同じバージョンの .NET が Windows とその他で挙動が違う」という問題はなくなった一方で、
「Windows 上では .NET Core 3.1 と .NET 5.0 で挙動が違う」ということが一部起こります。</p>
<p>カルチャー依存な API を使わなければ問題ないんですが…
.NET の string は歴史的背景で、一部はカルチャー依存、一部は非依存みたいになっているので注意が必要です。
例えば、<a href="https://github.com/dotnet/runtime/issues/43736"><code>IndexOf</code> はカルチャー依存で、<code>Contains</code> は非依存</a>みたいなことがあったりします。</p>
<h4>¥ 記号</h4>
<p>日本語 Windows がやっている余計なお世話として有名なのが、「いまだに ¥ 記号と <code>\</code> (逆スラッシュ)を同一視する」というのがあります。</p>
<pre class="source" title="ja-jp カルチャーでの破壊的変更">
<code><span class="reserved">using</span> System;
<span class="reserved">using</span> System.Globalization;
<span class="reserved">using</span> System.Threading;
 
<span class="reserved">var</span> <span class="variable">s1</span> = <span class="string">@&quot;</span><span style="color:#b776fb;">\</span><span class="string">&quot;</span>;
<span class="reserved">var</span> <span class="variable">s2</span> = <span class="string">&quot;¥&quot;</span>;
 
<span class="reserved">var</span> <span class="variable">culture</span> = <span class="type">CultureInfo</span>.<span class="method">GetCultureInfo</span>(<span class="string">&quot;ja-jp&quot;</span>);
<span class="type">Thread</span>.CurrentThread.CurrentCulture = <span class="variable">culture</span>;
<span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="variable">s1</span>.<span class="method">Contains</span>(<span class="variable">s2</span>)); <span class="comment">// CurrentCulture 非依存。今までもこれからも False。</span>
<span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="variable">s1</span>.<span class="method">IndexOf</span>(<span class="variable">s2</span>)); <span class="comment">// CurrentCulture 依存。今まで 0。これから -1。</span>
</code></pre>
<p>昔、逆スラッシュのコード(U+005C)は国ごとに解釈を変えてもいいという扱いになっていて、
日本語では¥(円記号)、韓国語では₩(ウォン記号)に使っていたという時代の名残りです。
というか、日本語 Windows 上ではフォントによってはいまだに U+005C が円記号で表示されますし…</p>
<p>今(Unicode)では、¥ (U+00A5)、₩ (U+20A9)にはちゃんと別コードが割当たっていますが、NLS は今でも <code>\</code> (U+005C) と同一視する処理が入っていたりします。</p>
<p>ちなみに、それぞれ日本語カルチャー(ja-jp)、韓国語カルチャー(ko-kr)でだけこの処理が起こります。</p>
<h4>改行</h4>
<p>ICU では CR LF は「分割不可」らしく、CR LF と LF は別文字扱いになっています。
NLS はこの処理をしていないので、以下のコードは NLS と ICU で結果が変わります。</p>
<pre class="source" title="改行の扱いの変化">
<code><span class="reserved">using</span> System;
 
<span class="reserved">var</span> <span class="variable">s1</span> = <span class="string">&quot;</span><span style="color:#b776fb;">\r\n</span><span class="string">&quot;</span>;
<span class="reserved">var</span> <span class="variable">s2</span> = <span class="string">&quot;</span><span style="color:#b776fb;">\n</span><span class="string">&quot;</span>;
 
<span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="variable">s1</span>.<span class="method">IndexOf</span>(<span class="variable">s2</span>)); <span class="comment">// NLS だと 1。ICU だと -1。</span>
</code></pre>
<h4>対処法</h4>
<p>もしこの手の問題を踏んだ場合、対処方法としては2つあります。</p>
<ul>
<li>NLS に戻す</li>
<li>カルチャー依存をやめる</li>
</ul>
<p>NLS に戻すなら、csproj に以下の設定を追加します。</p>
<pre class="xsource" title="国際化対応を .NET 5.0 でも NLS でやるためのオプション">
<code><span class="attvalue">  &lt;</span><span class="element">ItemGroup</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">RuntimeHostConfigurationOption</span><span class="attvalue"> </span><span class="attribute">Include</span><span class="attvalue">=</span>&quot;<span class="attvalue">System.Globalization.UseNls</span>&quot;<span class="attvalue"> </span><span class="attribute">Value</span><span class="attvalue">=</span>&quot;<span class="attvalue">true</span>&quot;<span class="attvalue"> /&gt;</span>
<span class="attvalue">  &lt;/</span><span class="element">ItemGroup</span><span class="attvalue">&gt;</span>
</code></pre>
<p>一方、カルチャー依存するようなメソッドは大体、第2引数にオプション指定できるので、それを <code>Ordinal</code> にしてしまえばカルチャー問題は踏まなくなります。</p>
<pre class="xsource" title="Ordinal 推奨">
<code><span class="xsl">Console</span>.<span style="color:#74531f;">WriteLine</span>(<span style="color:#1f377f;">s1</span>.<span style="color:#74531f;">IndexOf</span>(<span style="color:#1f377f;">s2</span>)); <span class="comment">// CurrentCulture になってるのが問題</span>
<span class="xsl">Console</span>.<span style="color:#74531f;">WriteLine</span>(<span style="color:#1f377f;">s1</span>.<span style="color:#74531f;">IndexOf</span>(<span style="color:#1f377f;">s2</span>, <span class="xsl">StringComparison</span>.CurrentCulture)); <span class="comment">// \ と ￥ の問題を踏む</span>
<span class="xsl">Console</span>.<span style="color:#74531f;">WriteLine</span>(<span style="color:#1f377f;">s1</span>.<span style="color:#74531f;">IndexOf</span>(<span style="color:#1f377f;">s2</span>, <span class="xsl">StringComparison</span>.InvariantCulture)); <span class="comment">// \r\n と \n の問題を踏む</span>
<span class="xsl">Console</span>.<span style="color:#74531f;">WriteLine</span>(<span style="color:#1f377f;">s1</span>.<span style="color:#74531f;">IndexOf</span>(<span style="color:#1f377f;">s2</span>, <span class="xsl">StringComparison</span>.Ordinal)); <span class="comment">// カルチャー依存したくなければこれを指定すればいい</span>
</code></pre>
<p>「デフォルトが <code>CurrentCulture</code> なことが問題」とは認識されていて、
近いうちにこの手の API に対して <code>StringComparison</code> を指定していなかった場合に警告を出すようなアナライザーを提供しようかという話になっていたりもします。</p>
 ]]></description>
				<pubDate>Mon, 16 Nov 2020 00:29:37 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 10/31: csharplang の運営方針とかトリアージとか</title>
				<link>http://ufcpp.net/blog/2020/10/pickuproslyn1030/</link>
				<description><![CDATA[ <p>また何件かまとめて、C# Language Design Meeting 議事録を紹介。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-10-12.md">October 12th, 2020</a></li>
<li><a href="https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-10-14.md">October 14th, 2020</a></li>
<li><a href="https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-10-26.md">October 26st, 2020</a></li>
</ul>
<p>主に、csharplang の運営方針に関する話と、こまごまとトリアージ話。</p>
<p>(この他に、
<a href="https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-10-21.md">October 21st, 2020</a>ではプライマリ コンストラクターの話があったり、
Meeting 議事録とは別に<a href="https://github.com/dotnet/csharplang/issues/4032">派生型の網羅性の話</a>が出てたりするんですが、
またちょっと話が大きくなりそうなので別の回で改めて。)</p>
<h2>csharplang の運営方針</h2>
<h3>C# コミュニティ大使</h3>
<p>先週の配信:</p>
<div>
<iframe width="560" height="315" src="https://www.youtube.com/embed/aDXHl3S8oik" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div>
<p>これの割と冒頭で話してるんですけども、<a href="https://github.com/dotnet/csharplang">csharplang</a>で、Community Ambassador (コミュニティ大使)を設けようという話が出ていました。
(実際、ほぼ即日、何名か任命。)</p>
<p>C# はオープンソース開発されているといっても、マイクロソフトの C# チームが責任を負ってどの機能をいつまでに実装するかなどは独裁的に決定しています。
バグ修正の類などは <a href="https://github.com/dotnet/roslyn/">roslyn</a> (コンパイラー実装に関するリポジトリ)に直接 Pull Request を出して通ったりしますが、
言語仕様に関しては <a href="https://github.com/dotnet/csharplang/">csharplang</a> (言語仕様だけに絞ったリポジトリ)でのディスカッションを経て、
C# チームが承認したものだけが受け付けられます。</p>
<p>あるいは、C# チームが「微妙なラインなので、もし実装してくれる人がいるなら受け付けるけども、C# チーム内では実装しない」と判定した言語機能であれば外部貢献が受け付けられたりはします。
ただ、これも、「例え外部貢献だろうとリジェクト」と判定される言語機能もあって、その場合は誰かがその機能を実装したとしても Pull Request が承認されることはありません。</p>
<p>とはいえ、そういう運営体制だとしてコミュニティ(要するにマイクロソフト外の協力者)側でサポートできることがあるだろうというのが今回の流れです。</p>
<p>csharplang には、Design Meeting でこの話題が出た12日時点で1500件を超える issue が立っていたわけですが…</p>
<ul>
<li>そもそも GitHub に Discussions 機能が追加される前からあるもので、今であれば discussion にすべきものが大半</li>
<li>ほとんどが重複</li>
<li>残る issue も具体的なメリットや、逆にそれを実装した場合のリスクなどの観点が抜けている</li>
</ul>
<p>というような状態です。</p>
<p>これに対して、</p>
<ul>
<li>issue から discussion への移行</li>
<li>disucussion の answered 判定</li>
<li>重複 issue の close</li>
<li>具体性のある提案ドキュメント化(に向けた誘導)</li>
</ul>
<p>などは、最終決定権を持たないコミュニティ メンバーでも可能なわけです。
そこで、csharplang 内で特にアクティブに活動していて、その辺りの整理作業を任せられそうな信頼のおける数名に「大使」として issue/discussion の編集権限を与えることになったそうです。</p>
<p>そして効果のほどなんですが、その後3週間弱となる現在、csharplang の issue はついに900ほどまで減っています。
ほぼ1日30個くらいの一定ペースで減少中。</p>
<h3>マイルストーンの整理</h3>
<p>前節の通り、C# の言語機能に関しては C# チームの決定権が絶対的なんですが、
その決定結果は「やる/やらない」の2択ではなくて、以下のように積極度に段階があります。</p>
<ul>
<li>Working Set: やりたいし、C# チーム自身が活発に手がける</li>
<li>Backlog: やりたいけども、ちょっと決め手に欠けていて、言語設計のレベルで何かいいアイディアが欲しい(いきなりコミュニティ実装を受け付けられるというレベルでもない)</li>
<li>Any Time: やってもいいけども、優先度低めで C# チームのリソースを割けない(コミュニティ実装は受け付けられる)</li>
<li>Likely Never: よっぽどのことがないとやらない</li>
</ul>
<p>今まで 9.0 とか 10.0 とかの C# のバージョンをそのままマイルストーンにしていましたが、
「活発に手掛けているからと言っても短期間で完成するものではなくて数バージョン先になる」みたいな機能もあれば、
「そんなに優先度が高くなかったけども、コミュニティ貢献の質が良くて採用」みたいな機能もあるので、
取り組みの活発さとマイルストーンの温度感に差がありました。</p>
<p>ということで、Working Set と Backlog マイルストーンを新設したとのこと
(Any Time と Likely Never は元からあったものの、ここで改めて意図を明文化)。</p>
<p>これからはまず Working Set か Backlog かに分類された上で、
具体的に実装が進んできてリリースに含められそうかどうかが見えてきてから初めて C# バージョン番号を冠したマイルストーンに移動という流れになりそうです。
また、バージョン番号も実際にリリースされる(マイルストーンが close される)までは、「予定ではそのバージョンで入れるけども、重大な問題が発覚したらそのバージョンからは外すこともある」みたいな状態です。</p>
<h2>トリアージ</h2>
<p>いくつか抜粋。</p>
<h3>Repeated Attributes in Partial Members</h3>
<p>C# 9.0 で追加する新しい partial method ですが、以下のようなコードを書くとコンパイル エラーを起こします。</p>
<pre class="source" title="AllowMultiple = false な属性">
<code><span class="reserved">partial</span> <span class="reserved">class</span> <span class="type">C</span>
{
    [<span class="reserved">return</span>: <span class="type">MaybeNull</span>]
    <span class="reserved">public</span> <span class="reserved">partial</span> <span class="reserved">string</span> <span class="method">M</span>();
}
 
<span class="reserved">partial</span> <span class="reserved">class</span> <span class="type">C</span>
{
    [<span class="reserved">return</span>: <span class="type">MaybeNull</span>]
    <span class="reserved">public</span> <span class="reserved">partial</span> <span class="reserved">string</span> <span class="method">M</span>() =&gt; <span class="string">&quot;&quot;</span>;
}
</code></pre>
<p><code>AttributeUsage</code> で重複不可(<code>AllowMultiple = false</code>) になっている属性が partial の宣言側と実装側の両方についている場合、「重複」判定を受けてしまっているという状態。
この例のように null 許容関連の属性は宣言側と実装側の両方に付けたいことが結構あって、これをエラーにされると結構困りそうです。
ということで、重複不可になっている属性でも、全く同じパラメーターで指定されている場合は両側に同じ属性が付いている状態を認めたいとのこと。
working set 判定。</p>
<h3>params Span</h3>
<p>現状、<a href="https://ufcpp.net/study/csharp/sp_params.html#params">可変長引数</a>は配列が作られてしまうのでアロケーションが発生します。
これを、<code>Span&lt;T&gt;</code> で受け付けられるようにしてアロケーションをなくしたいという話は前々からあります。</p>
<p><a href="https://ufcpp.net/blog/2020/10/pickuproslynlowlevel10/">11日に書いた低水準機能改善</a>の一環として「safe な固定長バッファー」みたいな話もあって、
これがあればそんなに難なく <code>params Span&lt;T&gt;</code> ができるはずなので、今このタイミングで working set 判定。</p>
<h3>Sequence Expressions</h3>
<p><code>(var x = Read(); x * x)</code> みたいな書き方で、複数のステートメントを並べつつ、最後の値を返す「<a href="https://ufcpp.net/study/csharp/structured/miscexpressions/#key-expression">式</a>」にできる文法が欲しいという話。</p>
<p><a href="https://ufcpp.net/study/csharp/oo_construct.html#member_initializer">初期化子</a>とか <a href="https://ufcpp.net/study/csharp/datatype/typeswitch/?p=5#switch-expression"><code>switch</code> 式</a>とか、
式しか受け付けない便利な文法が結構あります。</p>
<p>これと関連しそうないくつかの提案 (<a href="https://github.com/dotnet/csharplang/issues/3038">3038</a>、<a href="https://github.com/dotnet/csharplang/issues/3037">3037</a>、<a href="https://github.com/dotnet/csharplang/issues/3086">3086</a>)がすでに working set 判定済みなので、この Sequence Expressions も working set 入り。</p>
<h3>utf8 string literals</h3>
<p>C# に UTF-8 関連の特殊対応文法を入れるよりもまず 「<code>Utf8String</code> 型の実装](https://github.com/dotnet/corefxlab/issues/2350)が先だろという話でして。</p>
<p>そっちは <a href="https://github.com/dotnet/corefxlab/issues/2350#issuecomment-718917142">nightly ビルドの NuGet パッケージを入れて試してみてフィードバックが欲しい</a>らしいですよ。</p>
<p>ということで、C# 側としては Backlog 判定だそうです。</p>
<h3>File scoped namespaces</h3>
<p>今までの、</p>
<pre class="source" title="名前空間">
<code><span class="reserved">namespace</span> N
{
    <span class="reserved">class</span> <span class="type">C</span>
    {
    }
}
</code></pre>
<p>これを、</p>
<pre class="source" title="1ライン名前空間">
<code><span class="reserved">namespace</span> N;
 
<span class="reserved">class</span> <span class="type">C</span>
{
}
</code></pre>
<p>こうじゃ。
(1ライン名前空間の導入。)</p>
<p>最近の C# は<a href="https://ufcpp.net/study/csharp/misc/miscentrypoint/#top-level-statements">トップ レベル ステートメント</a>しかり、「見栄えがすっきりすること」に割と前向きです。</p>
<p>もちろん、「主張が弱くなりすぎていて、書くのはいいとしても、読むときには逆に見逃してしまうリスクが高くて読みづらい」みたいなこともあります
(プログラムは書いている時間よりも読んでいる時間の方が長いので、「読みづらい」というのは思った以上のデメリット)。
とはいえ、この辺りは慣れの問題もあって、すっきり書けるプログラミング言語が増えてきた昨今、「読みづらい」判定の基準もずいぶん変わってきたと思います。</p>
<p>また、C# は基本的には空白文字の有無によって挙動を変えない言語なので、
その発想でいうと「インデント1段の差は些細な差」ではあります。
例えばまあ、別に、1ライン名前空間がなくても、以下のように書けばほぼ同じ見た目になります。</p>
<pre class="source" title="名前空間">
<code><span class="reserved">namespace</span> N
{
<span class="reserved">class</span> <span class="type">C</span>
{
}
}
</code></pre>
<p>ただ、最近は</p>
<ul>
<li>Visual Studio に限らずツールでの自動整形が当たり前</li>
<li>改行位置とか空白の数まで含めて、スタイルまできっちり決めて、スタイル違反を警告にすることもざら</li>
<li>何だったら CI テストでスタイル違反は merge できないようにはじく人までいる</li>
</ul>
<p>みたいな状態なので、「挙動が変わらないはずの言語でも空白の有無が結構大きい」みたいな感じになっています。</p>
<p>ということで C# でもついに1ライン名前空間に前向きな判定が出ていて、working set 入り(というか、すでに 10.0 (バージョン番号マイルストーン)入り)。</p>
<h3>Efficient params and string formatting</h3>
<p><a href="https://ufcpp.net/study/csharp/st_string.html#string-interpolation">文字列補間</a>は便利な構文なんですけども、
アロケーションが掛かっちゃうタイミングが早すぎてロギングとかの用途では使えなかったりします。
(例えば、ログ レベルによってはログ書き出ししない場合が大部分になるのに、書き出しもしない文字列のアロケーションをしまくってしまう。)</p>
<p><a href="https://docs.microsoft.com/ja-jp/dotnet/api/microsoft.extensions.logging.ilogger.log?view=dotnet-plat-ext-3.1#Microsoft_Extensions_Logging_ILogger_Log__1_Microsoft_Extensions_Logging_LogLevel_Microsoft_Extensions_Logging_EventId___0_System_Exception_System_Func___0_System_Exception_System_String__"><code>ILogger.Log</code> メソッド</a>が <code>formatter</code> 引数を持つ長ったらしくて使いにくそうなシグネチャになってるのもそのせいでして。</p>
<p>前述の <code>params Span&lt;T&gt;</code> とかを使ったりでアロケーションを減らそう見たいな提案はいくつか出ているんですが、今あげたロギングの例とかを考えると多分不十分じゃないかなと思います。</p>
<p>ということで「working set としてキープし続ける。都度色々な提案を見ていく」みたいな空気感。</p>
<h3>readonly classes and records</h3>
<p><a href="https://ufcpp.net/study/csharp/cheatsheet/ap_ver7_2/#readonly-struct">readonly struct</a>の参照型版。
class, record に対しても readonly 修飾(フィールド全部が readonly であることを求める)を付けたいという話。</p>
<p>今までやってない理由は大体以下の2点。</p>
<ul>
<li>あくまで shallow な read-only 性しか担保していなくて、階層すべての immutability を保証できない</li>
<li>構造体ほど切羽詰まってない(構造体の場合は<a href="https://ufcpp.net/study/csharp/resource/readonlyness/#hidden-copy">隠れたコピー</a>発生問題がある)</li>
</ul>
<p>とはいえ、あって困るものではなく、working set 入り。</p>
<h3>Target typed anonymous type initializers</h3>
<p>以下のような話。</p>
<pre class="source" title="() なし名前指定ターゲット型推論">
<code><span class="comment">// C# 9.0 で、ターゲットからの型推論で new() と書けるように</span>
<span class="type">Point</span> <span class="variable">a</span> = <span class="reserved">new</span>(1, 2);
 
<span class="comment">// 逆に(3.0 からある)ソース型推論だとこうなる</span>
<span class="reserved">var</span> <span class="variable">b</span> = <span class="reserved">new</span> <span class="type">Point</span>(1, 2);
<span class="reserved">var</span> <span class="variable">c</span> = <span class="reserved">new</span> <span class="type">Point</span> { X = 1, Y = 2 };
 
<span class="comment">// ターゲット型推論で nominal (プロパティ名指定)な初期化をするならこうなる。</span>
<span class="type">Point</span> <span class="variable">d</span> = <span class="reserved">new</span>() { X = 1, Y = 2 };
 
<span class="comment">// ↑ この () は邪魔じゃない？</span>
<span class="comment">// とはいえ…</span>
<span class="comment">// これは「匿名型」になる。</span>
<span class="reserved">var</span> <span class="variable">e</span> = <span class="reserved">new</span> { X = 1, Y = 2 };
 
<span class="comment">// ターゲット型があるときはターゲット型推論扱い</span>
<span class="comment">// (ターゲットが object とか dynamic、var の時だけ匿名型扱いするような分岐)</span>
<span class="comment">// も可能なんじゃないか？</span>
<span class="comment">// (C# 9.0 時点ではエラー。たぶん、破壊的変更にはならず上記挙動が可能)</span>
<span class="type">Point</span> <span class="variable">f</span> = <span class="reserved">new</span> { X = 1, Y = 2 };
 
<span class="reserved">record</span> Point(<span class="reserved">int</span> <span class="variable">X</span> = 0, <span class="reserved">int</span> <span class="variable">Y</span> = 0);
</code></pre>
<p><code>new() {}</code> の <code>()</code> が邪魔というか、ソース型推論の場合との整合性があんまりよくなくていまいちなのは確かだったり。</p>
<p>その一方で、<a href="https://ufcpp.net/study/csharp/sp3_inference.html#anonymous">匿名型</a>と混ざる怖さを払しょくできるほど欲しい構文かと言われると微妙で。
Backlog 入り。</p>
<h3>Static local functions in base calls</h3>
<p>以下のように、初期化子でローカル関数を呼びたいという話が出ていまして。</p>
<pre class="source" title="初期化子でローカル関数を呼びたい">
<code><span class="reserved">class</span> <span class="type">Base</span>
{
    <span class="reserved">public</span> <span class="type">Base</span>(<span class="reserved">int</span> <span class="variable">x</span>) { }
}
 
<span class="reserved">class</span> <span class="type">Derive</span> : <span class="type">Base</span>
{
    <span class="reserved">public</span> <span class="type">C</span>() : <span class="reserved">base</span>(init())
    {
        <span class="reserved">static</span> <span class="reserved">int</span> <span class="method">init</span>()
        {
            <span class="comment">// 何かそれなりの処理</span>
        }
    }
}
</code></pre>
<p>まあ割と「わからなくはない」という感じで Working set 入りしてるんですが。
ただ、C# チーム的にはもうちょっと汎用的に、「スコープの拡張」みたいなのを考えているみたいです。</p>
<p>例えば、</p>
<ul>
<li>上記のようにローカル関数のスコープを広げるのであれば、メソッド内で定義した <a href="https://ufcpp.net/study/csharp/sp_const.html#const"><code>const</code></a> も同様に使いたい場面はある</li>
<li>
初期化子だけじゃなくて、属性とかからも参照したい
<ul>
<li><code>[return: NotNullIfNotNull(nameof(p))] string? M(string? p)</code> みたいなのとか、実際、スコープを広げたい要求は出てきてる</li>
</ul>
</li>
</ul>
 ]]></description>
				<pubDate>Sat, 31 Oct 2020 00:17:21 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn: C# 10.0 トリアージ</title>
				<link>http://ufcpp.net/blog/2020/10/pickuproslyncs10triage/</link>
				<description><![CDATA[ <p><a href="https://ufcpp.net/blog/2020/10/pickuproslynlowlevel10/">前回</a>、<a href="https://ufcpp.net/blog/2020/10/pickuproslynrecord10/">前々回</a>の続きというか、大きくなりすぎたので分けたのの続き。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-09-23.md">C# Language Design Meeting for September 23rd, 2020</a></li>
<li><a href="https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-09-28.md">C# Language Design Meeting for September 28th, 2020</a></li>
<li><a href="https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-09-30.md">C# Language Design Meeting for September 30th, 2020</a></li>
<li><a href="https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-10-05.md">C# Language Design Meeting for October 5th, 2020</a></li>
<li><a href="https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-10-07.md">C# Language Design Meeting for October 7th, 2020</a></li>
</ul>
<p>ここ数週、C# 10.0 向けの検討が続いていて、
そのうち大きなものは<a href="https://ufcpp.net/blog/2020/10/pickuproslynrecord10/">前々回の record struct</a>と<a href="https://ufcpp.net/blog/2020/10/pickuproslynlowlevel10/">前回の低水準機能</a>で、残りはこまごまとしたトリアージ作業になります。</p>
<p>今回でやっと最後、その残りのトリアージの話。</p>
<h2>NaN 比較</h2>
<p>C# では、というか、IEEE 754 (浮動小数点数の標準規格)では、
NaN (Not a Number)との比較は常に false ということになっています。</p>
<pre class="source" title="NaN との比較">
<code><span class="reserved">bool</span> <span class="method">m</span>(<span class="reserved">double</span> <span class="variable">x</span>) =&gt; <span class="variable">x</span> == <span class="reserved">double</span>.NaN;
 
<span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="method">m</span>(1.0)); <span class="comment">// 当然 false</span>
<span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="method">m</span>(<span class="reserved">double</span>.NaN)); <span class="comment">// これですら false</span>
</code></pre>
<p>最近の C# では「常に false な式」に対して警告を出すことが結構あるんで、
過去の文法に対しても「常に false 警告」を足してもいいんじゃないかという話があります。</p>
<p>ただ、これまでの C# だと、「警告であっても追加すると破壊的変更になりうる」ということで消極でした。</p>
<p>これに対して C# 9.0/.NET 5.0 では警告ウェーブ(AnalysisLevel オプション。<a href="https://www.youtube.com/watch?v=VQLtwak8W0U&amp;feature=youtu.be">RC 1 記念ライブ配信</a>のときに口頭説明はしてる)が入るので、今後は警告の追加もしていきたいということになっています。</p>
<p>で、NaN との比較の話に戻りますが、
実はすでに FxCop Analyzer (Roslyn 標準ではないものの、Visual Studio ではデフォルトで有効になっているアナライザー)が NaN 比較に対する修正を提案してきます。
「Roslyn 標準に置き換えるほどではない」ということで、「特に何もしない」とのこと。</p>
<h2>null 許容参照型の改善</h2>
<p>C# 8.0 で <a href="https://ufcpp.net/study/csharp/resource/nullablereferencetype/">null 許容参照型</a>が入りましたが、最初から完全なものを作るのは無理なので段階的に改善していくという計画になっていて、C# 9.0 でもいくつか改善が入っています。</p>
<ul>
<li><code>MemberNotNull</code> 属性</li>
</ul>
<pre class="source" title="MemberNotNull 属性">
<code><span class="reserved">class</span> <span class="type">X</span>
{
    <span class="reserved">public</span> <span class="reserved">string</span> NotNull;
    <span class="reserved">public</span> <span class="type">X</span>() =&gt; <span class="method">Init</span>();
 
    <span class="comment">// このメソッドの呼び出し後、NotNull プロパティの非 null を保証</span>
    [<span class="type">MemberNotNull</span>(<span class="reserved">nameof</span>(NotNull))]
    <span class="reserved">private</span> <span class="reserved">void</span> <span class="method">Init</span>() =&gt; NotNull = <span class="string">&quot;&quot;</span>;
}
</code></pre>
<ul>
<li>制約なしジェネリック型に対する <code>T?</code></li>
</ul>
<pre class="source" title="制約なしジェネリック型に対する T?">
<code><span class="inactive">#nullable</span> <span class="inactive">enable</span>
 
<span class="reserved">class</span> <span class="type">X</span>
{
    <span class="comment">// where T を書かないときも T? が利用できるように。</span>
    <span class="comment">// ただし、意味的には nullable というよりも &quot;defaultable&quot; で…</span>
    <span class="reserved">static</span> <span class="type">T</span>? <span class="method">M</span>&lt;<span class="type">T</span>&gt;() =&gt; <span class="reserved">default</span>;
 
    <span class="reserved">static</span> <span class="reserved">void</span> <span class="method">Main</span>()
    {
        <span class="reserved">string</span>? <span class="variable">s1</span> = <span class="method">M</span>&lt;<span class="reserved">string</span>?&gt;(); <span class="comment">// string? → string?</span>
        <span class="reserved">string</span>? <span class="variable">s2</span> = <span class="method">M</span>&lt;<span class="reserved">string</span>&gt;();  <span class="comment">// string → string?</span>
        <span class="reserved">int</span>?    <span class="variable">i1</span> = <span class="method">M</span>&lt;<span class="reserved">int</span>?&gt;();    <span class="comment">// int? → int?</span>
        <span class="reserved">int</span>     <span class="variable">i2</span> = <span class="method">M</span>&lt;<span class="reserved">int</span>&gt;();     <span class="comment">// int → int で 0 が返る</span>
    }
}
</code></pre>
<p>で、C# 9.0 にも漏れたものがいくつかあって、引き続き 10.0 向けに検討していくとのこと。</p>
<ul>
<li>
<a href="https://github.com/dotnet/csharplang/issues/3950"><code>Task&lt;T&gt;</code> の改善</a>
<ul>
<li>共変性を認めたい(<code>Task&lt;T&gt;</code> を <code>Task&lt;T?&gt;</code> に代入できるようにしたい&gt;)</li>
</ul>
</li>
<li>
<a href="https://github.com/dotnet/csharplang/issues/3951">LINQ の改善</a>
<ul>
<li>特に <code>source.Where(x =&gt; x != null).Select(x =&gt; xは非null扱い)</code> ができるようにできないものか</li>
</ul>
</li>
<li>未初期フィールド(今のところ良案なし)</li>
</ul>
<h2>required プロパティ</h2>
<p><a href="https://ufcpp.net/blog/2020/10/pickuproslynrecord10/">前々回</a>、少し nominal record (オブジェクト初期化子で初期化する前提のレコード型)の話をしましたが、
C# 9.0 時点では nominal に(プロパティで)定義したメンバーは初期化を必須にできません。
常に省略可能で、省略した場合は 0/null に自動的に初期化されます。</p>
<pre class="source" title="nominal record のプロパティは現状、明示的な初期化が不要">
<code><span class="reserved">var</span> <span class="variable">p</span> = <span class="reserved">new</span> <span class="type">Point</span>
{
    <span class="comment">// X, Y ともに何も書かなくても別に構わない</span>
};
 
<span class="reserved">record</span> Point
{
    <span class="reserved">public</span> <span class="reserved">int</span> X { <span class="reserved">get</span>; <span class="reserved">init</span>; }
    <span class="reserved">public</span> <span class="reserved">int</span> Y { <span class="reserved">get</span>; <span class="reserved">init</span>; }
}
</code></pre>
<p>これに対して、明示的な初期化を義務付けたいという話があって、
1案としては以下のような書き方が提案されています。
これを required プロパティといいます。</p>
<pre class="source" title="required プロパティ(の1案)">
<code><span class="reserved">var</span> <span class="variable">p</span> = <span class="reserved">new</span> <span class="type">Point</span>
{
    X = 1, <span class="comment">// X は書かないとコンパイル エラー</span>
    <span class="comment">// Y はなくてもいい</span>
};
 
<span class="reserved">record</span> Point
{
    <span class="reserved">public</span> <span class="reserved">int</span> X { <span class="reserved">get</span>; req; }
    <span class="reserved">public</span> <span class="reserved">int</span> Y { <span class="reserved">get</span>; <span class="reserved">init</span>; }
}
</code></pre>
<p>元々「間に合う物なら C# 9.0 で」くらいの感じで提案が出ていたものなので、引き続き 10.0 候補として検討していくとのこと。</p>
<h2>匿名型に対する with 式</h2>
<p>これも<a href="https://ufcpp.net/blog/2020/10/pickuproslynrecord10/">前々回</a>書きましたが、
レコード型は「名前付きの匿名型」という側面があります。</p>
<p>となると逆に、「匿名型は名前なしのレコード型」という扱いになっている方が自然で、
この一貫性を取るために、匿名型にも <code>with</code> 式を認めたいという話が出ています。</p>
<pre class="source" title="匿名型に対する with 式">
<code><span class="reserved">var</span> <span class="variable">a</span> = <span class="reserved">new</span> { X = 1, Y = 2 };
<span class="reserved">var</span> <span class="variable">b</span> = <span class="variable">a</span> <span class="reserved">with</span> { X = 3 }; <span class="comment">// 9.0 時点ではできないものの、10.0 で検討</span>
</code></pre>
<p><a href="https://github.com/dotnet/csharplang/discussions/3952">discussion</a>では「匿名型自体どうなの？」とか言われたりもしますが…</p>
<p>C# チーム的には前向き(たぶん、変更コストがそんなに高くなく、レコード型との一貫性を重要視してる)みたいで、10.0 候補になっています。
元々 <code>with</code> 式には 10.0 向け残作業(ユーザー定義の <code>Clone</code> メソッドとか)があるので、それと合わせて検討。</p>
<h2>shebang</h2>
<p>C# でも shebang (Unix シェルでよくある、1行目に <code>#!</code> を書いてスクリプトを何で実行するか指定するやつ)を認めよう(C# コンパイラー的には単にコメント扱いで無視)という話があります。</p>
<pre class="source" title="shebang">
<code><span class="inactive">#! dotnet run</span>
 
System.<span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="string">&quot;Hello&quot;</span>);
</code></pre>
<p>ただ、これはどちらかというと <a href="https://docs.microsoft.com/ja-jp/dotnet/core/tools/?WT.mc_id=DT-MVP-4028921">donet CLI</a>側の問題なので、C# チーム的には「X.0」(いつやるか未定)扱い。
「CLI 側が dotnet run でスクリプト実行できるようになったら本気出す」みたいな感じみたいです。</p>
<h2>リスト パターン</h2>
<p>配列とか <code>List&lt;T&gt;</code> とか(あるいはもしかしたら汎用に <code>IEnumerable&lt;T&gt;</code> も)を <code>[]</code> を使った<a href="https://ufcpp.net/study/csharp/datatype/patterns/">パターン</a>でマッチングできるようにしたいという話があります。</p>
<pre class="source" title="リスト パターン">
<code>
<span class="reserved">var</span> <span class="variable">x</span> = <span class="reserved">new</span>[] { 1, 2, 3 };
 
<span class="control">if</span> (<span class="variable">x</span> <span class="reserved">is</span> [1, 2, var i])
{
    ...
}
</code></pre>
<p>(すでにコミュニティ貢献でプロトタイプ実装があったりします。)</p>
<p>これに対して C# チーム的には「リスト パターンは辞書パターンと一緒に考えたい」、
「ただ、プロパティ パターンの <code>{}</code> と明確に区別がついて、かつ、辞書らしい文法を思いつかない」という感じ。</p>
<p>「C# 10.0 に入れれる気はしないけども」という補足付きで「10.0 で検討」とのこと。</p>
<h2>global using</h2>
<p>今、<a href="https://docs.microsoft.com/ja-jp/dotnet/csharp/tutorials/intro-to-csharp/hello-world?tutorial-step=1&amp;WT.mc_id=DT-MVP-4028921">マイクロソフトによる公式 C# チュートリアル</a>とかでは、「ブラウザーでコードを試す」という機能があって、ブラウザー内で C# コードを書いてその場で実行できたりします。</p>
<p>ここでは C# のスクリプト文法を使えるので、例えば、以下のような1行のコードが「実行」ボタン1つで実行できます。</p>
<pre class="source" title="チュートリアル上ではこの1ライナーが有効">
<code><span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="string">&quot;Hellow World!&quot;</span>);
</code></pre>
<p>これ、実は <code>using System;</code> なしで <code>Console</code> クラスにアクセスできたりします。
スクリプト文法限定なんですが、いくつかの名前空間は「デフォルトで <code>using</code> 済み扱い」みたいにする機能があるということだったりします。</p>
<p>一方で、C# 9.0 からは<a href="https://ufcpp.net/study/csharp/misc/miscentrypoint/#top-level-statements">トップ レベル ステートメント</a>という機能が入ります。
プロジェクト(csproj)を作ってコンパイルする通常の C# 文法とスクリプト文法の差を縮めたいという意図で、
ファイル直下にステートメントを書いて <code>Main</code> メソッドを省略できるという機能です。</p>
<p>ここで、「通常文法とスクリプト文法の差を縮めたい」という意図があるので、
前述の「デフォルトで <code>using</code> 済み扱い」も通常文法に入れたいという議題が上がります。
これを指して global using といっていて、コンパイラー オプションとか csproj 中のタグで、プロジェクト全体に「<code>using</code> した状態にする」というオプションを提供したいそうです。</p>
<p><a href="https://devblogs.microsoft.com/dotnet/net-interactive-preview-3-vs-code-insiders-and-polyglot-notebooks/">.NET Notebooks</a>とか、 .NET 6 辺りをターゲットにした「C# インタラクティブ実行環境」があったりするので、その辺りのユーザーの使用感のフィードバックをもらいつつ、C# 10.0 で検討とのこと。</p>
<h2>closed enum</h2>
<p>enum 型に対して、「メンバー定義してない値は取らない」という保証を与えて、
<code>switch</code> の網羅性チェックが働くようにしたいという話があります。</p>
<p>例えば以下のコードは現状では警告が出るんですが、「警告をなくせる enum が欲しい」というのが closed enum です(ここでいう close (閉じる)というのは、「これ以上のメンバー追加はない」という意味です)。</p>
<pre class="source" title="enum の網羅性">
<code><span class="reserved">int</span> <span class="method">m</span>(<span class="type">X</span> <span class="variable">x</span>) =&gt; <span class="variable">x</span> <span class="warning"><span class="control">switch</span></span>
{
    <span class="type">X</span>.A =&gt; 1,
    <span class="type">X</span>.B =&gt; 2,
    <span class="type">X</span>.C =&gt; 4,
    <span class="comment">// 今の enum の仕様だと (X)100 とか書けるので、A, B, C だけでは「網羅した」判定を受けない。</span>
    <span class="comment">// 警告が出る。</span>
};
 
<span class="reserved">enum</span> <span class="type">X</span>
{
    A, B, C
}
</code></pre>
<p>この辺りの網羅性のロジックは、別途 C# 10.0 で検討されている <a href="https://github.com/dotnet/csharplang/issues/113">discriminated union</a> でも同様なので、それと一緒に考えたいとのこと。</p>
<h2>トップ レベル関数</h2>
<p>C# 9.0 で入った<a href="https://ufcpp.net/study/csharp/misc/miscentrypoint/#top-level-statements">トップ レベル ステートメント</a>で、トップ レベルにメソッドを書いた場合、
それはトップ レベルからのみアクセスできます。</p>
<pre class="source" title="トップ レベルにメソッドを書いた場合の挙動">
<code><span class="reserved">using</span> System;
 
<span class="comment">// トップ レベルでメソッドを書く。</span>
<span class="reserved">void</span> <span class="method">m</span>() =&gt; <span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="string">&quot;m&quot;</span>);
 
<span class="comment">// トップ レベルから呼ぶのは OK。</span>
<span class="method">m</span>();
 
<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="comment">// トップじゃない場所から呼ぶとコンパイル エラー。</span>
    <span class="comment">// ちなみにエラー内容は「m が見つからない」じゃなくて、
    // 「トップ レベルの m はトップ レベルからだけ呼べる」。</span>
    <span class="reserved">static</span> <span class="reserved">void</span> <span class="method">M</span>() =&gt; <span class="method">m</span>();
}
</code></pre>
<p>少なくとも C# 9.0 時点では意図的にこういう仕様になっているんですが、
「将来、この <code>m</code> をプロジェクト内のどこからでも呼んでいい global 関数的なものとして認めてもいいんじゃないか」という議題は残っていました
(今エラーになるものを将来エラーじゃなくすというのは破壊的変更にはならないので検討の余地がある)。</p>
<p>とはいえ元々「可能性はある」と言っていただけなので、あまり積極的ではなく。
「もし C# を1から再設計するんなら入れるけど、今から入れるのはちょっと」みたいな意見の人が多いそうです。
今回やっぱりばっさりと「rejected」とのことです。</p>
<h2>プライマリ コンストラクター</h2>
<p><a href="https://ufcpp.net/blog/2020/10/pickuproslynrecord10/">前々回</a>触れたとおり。
今、レコード型にだけ許されている <code>record Point(int X, int Y)</code> みたいな書き方(型名直後に <code>()</code> で引数リスト)をクラス、構造体にも認めようという話。</p>
<p>引き続き 10.0 目標で検討。</p>
<h2>パラメーターの null 検証の簡素化</h2>
<p>null 許容参照型による null 検証はあくまでコンパイル時の検証で、
unsafe とか<a href="https://ufcpp.net/study/csharp/resource/nullablereferencetype/?p=3#null-forgiving">抑止演算子の <code>!</code></a>とかを使うとコンパイル時検証をすり抜けられます。
また、構造体や配列要素の規定値とか、フロー解析がしにくくて、今のところ検証をすり抜けてしまう穴があります。</p>
<p>そこで、必要であればやっぱり実行時の検証、要するに以下のようなコードも必要だろうという空気感。</p>
<pre class="source" title="実行時 null 検証">
<code><span class="reserved">void</span> <span class="method">M</span>(<span class="reserved">string</span> <span class="variable">s</span>)
{
    <span class="control">if</span> (<span class="variable">s</span> <span class="reserved">is</span> <span class="reserved">null</span>)
        <span class="control">throw</span> <span class="reserved">new</span> <span class="type">ArgumentNullException</span>(<span class="reserved">nameof</span>(<span class="variable">s</span>));
 
    ...
}
</code></pre>
<p>これを、<code>string s!</code> とかで簡素化したいという案も出ています。
「文法は <code>!</code> でいいのか」みたいな部分で合意が取れておらず 9.0 では流れましたが、10.0 で再検討とのこと。</p>
<h2>generic type alias</h2>
<p><code>using</code> エイリアスで以下のような書き方をしたいという話はずっと昔からたびたび出ています。</p>
<pre class="source" title="using エイリアスでジェネリック型引数を書きたい">
<code><span class="reserved">using</span> List&lt;T&gt; = System.Collections.Generic.<span class="type">List</span>&lt;T&gt;;
</code></pre>
<p>「欲しいけど、他にたくさんある C# 10.0 候補を押しのけてまでは…」という感じみたいで、
「X.0」(いつやるか不明)行き。</p>
<h2>パラメーターに対する nameof</h2>
<p>null 許容参照型の <a href="https://ufcpp.net/study/csharp/resource/nullablereferencetype/?p=4#sec-generated-title-6"><code>NutNullIfNotNull</code></a> とかの登場で急に需要が高まったんですが、
属性内で、メソッドの引数を <code>nameof</code> 参照したいという要求があります。</p>
<pre class="source" title="パラメーターを nameof 参照したい例">
<code><span class="reserved">using</span> System.Diagnostics.CodeAnalysis;
 
<span class="reserved">class</span> <span class="type">Path</span>
{
    <span class="comment">// 今、nameof(path) とは書けない。</span>
    [<span class="reserved">return</span>: <span class="type">NotNullIfNotNull</span>(<span class="string">&quot;path&quot;</span>)]
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">string</span>? <span class="method">GetFileName</span>(<span class="reserved">string</span>? <span class="variable">path</span>);
}
</code></pre>
<p>まあ、C# 8.0 時点でこれの需要が急増することはわかっていて、
単に優先度的に 9.0 に入らなかっただけです。
すでに実装は始めているそうなので、10.0 候補。</p>
<h2>Span<T> パターン</h2>
<p>今や普通に <code>string</code> と <code>Span&lt;char&gt;</code>、<code>ReadOnlySpan&lt;char&gt;</code> を比較することがあるわけで、
だったら、<code>Span&lt;chat&gt;</code> を <code>switch</code> 式に掛けたいという要求が当然あります。</p>
<pre class="source" title="Span に対して文字列リテラルで switch">
<code><span class="comment">// string に対してこんな感じの switch していたものを…</span>
<span class="reserved">int</span> <span class="method">M</span>(<span class="reserved">string</span> <span class="variable">s</span>) =&gt; <span class="variable">s</span> <span class="control">switch</span>
{
    <span class="string">&quot;Id&quot;</span> =&gt; 1,
    <span class="string">&quot;Name&quot;</span> =&gt; 2,
    <span class="string">&quot;Age&quot;</span> =&gt; 3,
    <span class="reserved">_</span> =&gt; 0,
};
 
<span class="comment">// Span や ReadOnlySpan でもやりたい。</span>
<span class="reserved">int</span> <span class="method">M</span>(<span class="type">ReadOnlySpan</span>&lt;<span class="reserved">char</span>&gt; <span class="variable">s</span>) =&gt; <span class="variable">s</span> <span class="control">switch</span>
{
    <span class="string">&quot;Id&quot;</span> =&gt; 1,
    <span class="string">&quot;Name&quot;</span> =&gt; 2,
    <span class="string">&quot;Age&quot;</span> =&gt; 3,
    <span class="reserved">_</span> =&gt; 0,
};
</code></pre>
<p>これは「Any Time」(C# チーム的には乗り気じゃないけど、コミュニティ貢献は受け付ける)扱いなんですが、
実際にコミュニティ貢献の Pull Request が出ていたりします。
それに対する細かい判断:</p>
<ul>
<li>
<code>Span&lt;char&gt;</code>、<code>ReadOnlySpan&lt;char&gt;</code> に対する特殊対応なので気持ち悪いものの…
<ul>
<li>実のところ <code>Span</code> に対しては <code>foreach</code> とかですでに特別扱いしているので今更</li>
</ul>
</li>
<li>
後から足すと破壊的変更にならないか…
<ul>
<li><code>Span</code> は <a href="https://ufcpp.net/study/csharp/resource/refstruct/">ref 構造体</a>で <code>object</code> に代入できないとかの制限が幸いして、破壊的変更を避けれそう</li>
</ul>
</li>
<li>
<code>ReadOnlySpan&lt;char&gt;</code> だけ？
<ul>
<li><code>ReadOnlySpan&lt;char&gt;</code> を受け付けるんなら <code>Span&lt;char&gt;</code> も受け付けてよさそう</li>
</ul>
</li>
<li>
<code>Memory&lt;char&gt;</code> と <code>ReadOnlyMemory&lt;char&gt;</code> は？
<ul>
<li>それはなしで。<code>m.Span</code> と書くだけでいいし、<code>Span</code> 限定で</li>
</ul>
</li>
<li>
<code>switch</code> だけ認める？
<ul>
<li>パターンを掛ける任意のコンテキスト(<code>is</code> とかでも)で認めてよさそう</li>
</ul>
</li>
<li>
ジャンプ テーブル化
<ul>
<li>内部実装的なことをいうと、今、<code>string</code> に対する <code>switch</code> は <code>case</code> が6個以上あるときハッシュ値を使ったジャンプ テーブル化する最適化を掛けてる</li>
<li><code>Span&lt;char&gt;</code>、<code>ReadOnlySpan&lt;char&gt;</code> でも同様の最適化が要る。アロケーション除けによるメリットを打ち消すくらい遅くなる実装は避けたい</li>
</ul>
</li>
</ul>
 ]]></description>
				<pubDate>Mon, 12 Oct 2020 23:02:47 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn: C# 10.0 での低水準機能改善(ref フィールドなど)</title>
				<link>http://ufcpp.net/blog/2020/10/pickuproslynlowlevel10/</link>
				<description><![CDATA[ <p><a href="https://ufcpp.net/blog/2020/10/pickuproslynrecord10/">前回書いたの</a>の続き。</p>
<p>ここ数週間くらいの Language Design Meeting 議事録は C# 10.0 (今年11月に正式リリースされるのが 9.0 で、すでにその次のデザイン)話になっていています。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-09-23.md">C# Language Design Meeting for September 23rd, 2020</a></li>
<li><a href="https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-09-28.md">C# Language Design Meeting for September 28th, 2020</a></li>
<li><a href="https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-09-30.md">C# Language Design Meeting for September 30th, 2020</a></li>
<li><a href="https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-10-05.md">C# Language Design Meeting for October 5th, 2020</a></li>
<li><a href="https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-10-07.md">C# Language Design Meeting for October 7th, 2020</a></li>
</ul>
<p>このうち、<a href="https://ufcpp.net/blog/2020/10/pickuproslynrecord10/">前回</a>はレコード型関連の話を書きましたが、
今日は低水準機能の改善の話です。(<a href="https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-09-23.md">9/23 議事録分</a>)</p>
<p>(残り、細かいトリアージ話もあるんですが、それはまたさらに回を改めて。)</p>
<h2>低水準 (low level) 機能</h2>
<p>.NET Core 2.1 くらいの世代で .NET のパフォーマンスが劇的に向上したわけですが、その原動力になっているのは<a href="https://ufcpp.net/study/csharp/resource/span/"><code>Span&lt;T&gt;</code>構造体</a>です。
関連する C# の言語機能としては以下のものがあります。</p>
<ul>
<li><a href="https://ufcpp.net/study/csharp/cheatsheet/ap_ver7/#ref-returns">参照戻り値と参照ローカル変数</a></li>
<li><a href="https://ufcpp.net/study/csharp/cheatsheet/ap_ver7_2/#span-safety">ref 構造体</a></li>
</ul>
<p>C# のような「生産性と安全性重視」なプログラミング言語にとっては珍しく、パフォーマンス優先の機能です。
C# だと普段あまり意識しなくていいはずのメモリ管理を強く意識した機能なので、低水準(low-level: ハードウェア寄りという意味)機能というくくりになります。</p>
<p>今回、C# 10.0 向けに検討されているのもこの手の低水準機能で、以下のようなものです。</p>
<ul>
<li>ref 構造体が ref フィールドを持てるようにする</li>
<li><code>ByReferenct&lt;T&gt;</code> という特殊な型を使うのをやめて、ref フィールドに移行する</li>
<li>構造体が、そのフィールドを ref 戻り値で返せるようにする</li>
<li>safe な文脈で、<a href="https://ufcpp.net/study/csharp/sp_unsafe.html#unmanaged-types">managed な型</a>に対しても<a href="https://ufcpp.net/study/csharp/sp_unsafe.html#fixed-buffer">固定長バッファー</a>を使えるようにする</li>
</ul>
<h2>Span 構造体の内部と「ref フィールド」</h2>
<p><a href="https://ufcpp.net/study/csharp/resource/span/"><code>Span&lt;T&gt;</code>構造体</a>は、<em>論理的には</em>以下のような構造体だと説明されます。</p>
<pre class="source" title="Span の中身">
<code><span class="reserved">struct</span> <span class="type">Span</span>&lt;<span class="type">T</span>&gt;
{
    <span class="reserved">ref</span> <span class="type">T</span> <span class="method">_pointer</span>;
    <span class="reserved">int</span> _length;
}
</code></pre>
<p>フィールドとして <code>T</code> への参照と長さを持っています。
この「フィールドとして <code>T</code> への参照を持っている」(以下、これを「ref フィールド」と呼びます)というのが <code>Span&lt;T&gt;</code> 構造体の肝で、
パフォーマンス向上のポイントになっています。</p>
<p>ただ、「論理的には」と書いたのは、これまでの .NET (.NET 5.0/ C# 9.0 時点でも)にはこの ref フィールド機能がなくて、 .NET Core 2.1 の <code>Span&lt;T&gt;</code> 実装当時には、以下のような特殊処理をすることにしました。</p>
<pre class="source" title="ref フィールド代わりに ByReference という特殊な型で特殊対応">
<code><span class="reserved">struct</span> <span class="type">ByReference</span>&lt;<span class="type">T</span>&gt;
{
    <span class="comment">// .NET ランタイムが特別扱いする前提なので、C# では書けない</span>
}
 
<span class="reserved">struct</span> <span class="type">Span</span>&lt;<span class="type">T</span>&gt;
{
    <span class="type">ByReference</span>&lt;<span class="type">T</span>&gt; _pointer;
    <span class="reserved">int</span> _length;
}
</code></pre>
<p><code>ByReference&lt;T&gt;</code> がやりたいことはまさに ref フィールドなんですが、
.NET に本格的に ref フィールドを導入するよりは、この特殊処理で実装した方が楽だったそうです。</p>
<p>そして、ref フィールドが欲しくなるような状況の大半は <code>Span&lt;T&gt;</code> がカバーしているので、
この時点では以下のような方針になりました。</p>
<ul>
<li>将来、本格的に ref フィールドを導入するときまで <code>ByReference&lt;T&gt;</code> は public にしない</li>
<li><code>Span&lt;T&gt;</code> に関する escape analysis (メソッド外に漏らしてまずいものを return してないかのフロー解析)だけ実装する</li>
</ul>
<p>そして、この先送りにしていた ref フィールドの話が本格的に検討される段階になったみたいです。
.NET ランタイムにも手を入れる必要がありますし、
C# コンパイラー的にも escape analysis の改善が必要で、
<a href="https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-09-23.md">9/23 の議事録</a>では ref フィールドに対する escape analysis の案が書かれています。</p>
<p>当然、ref フィールドが入れば、<code>ByReference&lt;T&gt;</code> という特殊な構造体は必要なくなるので、
<code>Span&lt;T&gt;</code> も素直に ref フィールドで実装したいという話にもなります。</p>
<pre class="source" title="Span の本来やりたかった実装方法">
<code><span class="reserved">readonly</span> <span class="reserved">ref</span> <span class="reserved">struct</span> <span class="type">Span</span>&lt;<span class="type">T</span>&gt;
{
    <span class="reserved">ref</span> <span class="reserved">readonly</span> <span class="type">T</span> <span class="method">_field</span>;
    <span class="reserved">readonly</span> <span class="reserved">int</span> _length;
 
    <span class="comment">// 今までありそうでなかったコンストラクター。</span>
    <span class="comment">// 今回の提案はこれをできるようにするのも目標の1つ。</span>
    <span class="reserved">public</span> <span class="type">Span</span>(<span class="reserved">ref</span> <span class="type">T</span> <span class="variable">value</span>)
    {
        <span class="reserved">ref</span> _field = <span class="reserved">ref</span> <span class="variable">value</span>;
        _length = 1;
    }
}
</code></pre>
<h2>構造体のフィールドを ref 戻り値で返す</h2>
<p><a href="https://ufcpp.net/study/csharp/sp_ref.html?p=2#ref-returns">ref 戻り値</a>では、構造体のフィールドの参照を返せなかったりします。
例えば、以下のコードはコンパイル エラーになります。</p>
<pre class="source" title="C# 9.0 時点ではフィールドの参照を ref 戻り値で返せない">
<code><span class="reserved">struct</span> <span class="type">S</span>
{
    <span class="reserved">int</span> _field;
    <span class="reserved">public</span> <span class="reserved">ref</span> <span class="reserved">int</span> Prop =&gt; <span class="reserved">ref</span> _field; <span class="comment">// _field の参照を返せない</span>
}
</code></pre>
<p>以下のような、インターフェイス実装とジェネリックなメソッド呼び出しをしたときに、
外に漏れてはいけない参照を漏らしてしまうことがあるので禁止されています。</p>
<pre class="source" title="外に漏れてはいけない参照が漏れる状況">
<code><span class="reserved">interface</span> <span class="type">I1</span>
{
    <span class="reserved">ref</span> <span class="reserved">int</span> Prop { <span class="reserved">get</span>; }
}
 
<span class="reserved">struct</span> <span class="type">S1</span> : <span class="type">I1</span>
{
    <span class="reserved">int</span> _field;
    <span class="reserved">public</span> <span class="reserved">ref</span> <span class="reserved">int</span> Prop =&gt; <span class="reserved">ref</span> _field;
 
    <span class="comment">// p の寿命は M 内で閉じてるはずなものの、その p の中身が ref 戻り値で返ってしまう。</span>
    <span class="reserved">static</span> <span class="reserved">ref</span> <span class="reserved">int</span> <span class="method">M</span>&lt;<span class="type">T</span>&gt;(<span class="type">T</span> <span class="variable">p</span>) <span class="reserved">where</span> <span class="type">T</span> : <span class="type">I1</span> =&gt; <span class="reserved">ref</span> <span class="variable">p</span>.Prop;
}
</code></pre>
<p>これに対する対処は、結局、</p>
<ul>
<li>
フィールドの参照を返すメソッドには <code>ThisRefEscapes</code> 属性を付ける
<ul>
<li>専用の C# 文法を用意してコンパイラー生成にするか、明示的にこの属性を書かせるかはまだ要検討</li>
</ul>
</li>
<li>
この属性が付いているメソッドには制限を掛ける
<ul>
<li>インターフェイス実装できなくする</li>
<li>以下のようなメソッド呼び出しも制限する</li>
</ul>
</li>
</ul>
<pre class="source" title="">
<code><span class="reserved">struct</span> <span class="type">S1</span>
{
    <span class="reserved">public</span> <span class="reserved">ref</span> <span class="reserved">int</span> <span class="method">GetValue</span>() =&gt; ...
}
 
<span class="reserved">class</span> <span class="type">Example</span>
{
    <span class="reserved">ref</span> <span class="reserved">int</span> <span class="method">M</span>()
    {
        <span class="comment">// このコードは今現在有効 (破壊的変更したくないので今後も有効)</span>
        <span class="type">S1</span> <span class="variable">local</span> = <span class="reserved">default</span>;
        <span class="control">return</span> <span class="reserved">ref</span> <span class="variable">local</span>.<span class="method">GetValue</span>();
    }
}
</code></pre>
<h2>safe な固定長バッファー</h2>
<p><code>Span&lt;T&gt;</code> が出た当初にも、この構造体があれば<a href="https://ufcpp.net/study/csharp/sp_unsafe.html#fixed-buffer">固定長バッファー</a>を safe に実装できるんじゃないかという話は出ていたんですが。</p>
<p>実際には、固定長バッファーを safe にしたいときに問題になるのは前節の「構造体のフィールドの参照を返す」の方なので、これまで実装が止まっていました。
前述の <code>ThisRefEscapes</code> 属性があれば問題が解決するので、一緒に検討に上がっているみたいです。</p>
 ]]></description>
				<pubDate>Sun, 11 Oct 2020 22:30:21 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn: C# 10.0 でのレコード話</title>
				<link>http://ufcpp.net/blog/2020/10/pickuproslynrecord10/</link>
				<description><![CDATA[ <p><a href="https://ufcpp.net/blog/2020/9/csharp9final/">先月書いた</a>通り、C# 9.0 がらみはほぼ確定(バグ修正レベルの変更しかしない状態)になっています。</p>
<p>(そういえば<a href="https://youtu.be/VQLtwak8W0U">ライブ配信</a>はやったもののブログ化していなかった話題として、.NET 5.0 の RC 1 到達というのもあります。
RC (リリース候補)が付くと、もう大きな変更はできません。
あと、<a href="https://www.dotnetconf.net/">.NET Conf</a> のページに「.NET Conf 2020 は11月10日開始」、「.NET 5 launch」の文字が入ったので、.NET 5.0 のリリース日も決まりました。アメリカ西海岸時間で11月10日なので、日本だと11月11日に朝起きたらリリースされているくらいのタイミング。)</p>
<p>そうなると、今デザイン作業が行われているのはすでにその次、C# 10.0 の話になります。</p>
<p>ということでここ2週間ほどの C# の Language Design Meeting はC# 10.0 がらみが議題になります。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-09-23.md">C# Language Design Meeting for September 23rd, 2020</a></li>
<li><a href="https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-09-28.md">C# Language Design Meeting for September 28th, 2020</a></li>
<li><a href="https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-09-30.md">C# Language Design Meeting for September 30th, 2020</a></li>
<li><a href="https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-10-05.md">C# Language Design Meeting for October 5th, 2020</a></li>
</ul>
<p>10/8 に1件、10/7 日付の議事録の話を追記:</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-10-07.md">C# Language Design Meeting for October 7th, 2020</a></li>
</ul>
<p>一番大きな話題は C# 9.0 で導入されるレコードに関するものです。
C# 9.0 時点では仕様を詰め切れていなくて「9.0 リリース後に再検討」となっていた項目がいくつかあって、
この2週ほどのミーティングではまさにその再検討な話が結構な割合を占めています。</p>
<p>ちょっと長くなりそうなので、今日はこのレコード関連の話だけを書こうかと思います。</p>
<p>他に、構造体(特に ref フィールド、ref 構造体の改善など)の話題とか、細かいトリアージ作業とかもあったりするんですが、この辺りは後日改めて。</p>
<h2>前提知識: C# 9.0 レコード型</h2>
<p>レコード型は、以下のように <code>record</code> キーワードを使って宣言する新しい型で、</p>
<pre class="source" title="record 型宣言">
<code><span class="reserved">record</span> <span class="type">Point</span>(<span class="reserved">int</span> <span class="variable">X</span>, <span class="reserved">int</span> <span class="variable">Y</span>);
</code></pre>
<p>内部的には以下のようなクラスの生成になります。</p>
<pre class="source" title="Point レコードからのクラス生成">
<code><span class="reserved">class</span> <span class="type">Point</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> X { <span class="reserved">get</span>; <span class="reserved">init</span>; }
    <span class="reserved">public</span> <span class="reserved">int</span> Y { <span class="reserved">get</span>; <span class="reserved">init</span>; }
    <span class="reserved">public</span> <span class="type">Point</span>(<span class="reserved">int</span> <span class="variable">X</span>, <span class="reserved">int</span> <span class="variable">Y</span>) <span class="comment">// X, Y プロパティに代入</span>
    <span class="reserved">public</span> <span class="reserved">void</span> <span class="method">Deconstruct</span>(<span class="reserved">out</span> <span class="reserved">int</span> <span class="variable">X</span>, <span class="reserved">out</span> <span class="reserved">int</span> <span class="variable">Y</span>) <span class="comment">// X, Y プロパティから値取得</span>
    <span class="reserved">public</span> <span class="reserved">override</span> <span class="reserved">bool</span> <span class="method">Equals</span>(<span class="reserved">object</span>? <span class="variable">obj</span>) <span class="comment">// X, Y の値の比較</span>
    <span class="reserved">public</span> <span class="reserved">override</span> <span class="reserved">int</span> <span class="method">GetHashCode</span>() <span class="comment">// X, Y からハッシュ値生成</span>
    <span class="reserved">public</span> <span class="reserved">override</span> <span class="reserved">string</span> <span class="method">ToString</span>() <span class="comment">// Point { X = ... } の書式で文字列化</span>
    <span class="reserved">public</span> <span class="type">Point</span> <span class="method">Clone</span>() <span class="comment">// shallow コピー (実際には通常の C# から参照できない名前で生成)</span>
}
</code></pre>
<p>いくつかのとらえ方がありますが、以下のようなものとして説明されます。</p>
<ul>
<li>プレーンなデータを簡潔に書けるようにするための型</li>
<li><a href="https://ufcpp.net/study/csharp/sp3_inference.html#anonymous">匿名型</a> (<code>new { X = 1, Y = 2 }</code> みたいなやつ)の名前付き版</li>
<li>
value semantics (値による比較やコピー生成)を持つクラス
<ul>
<li>C# の場合は構造体が元から value semantics 的な挙動を持っているので、「レコードは構造体的な性質を持つ参照型」ともいえる</li>
</ul>
</li>
</ul>
<p>ちなみに、この手の型は immutable にしないとまずかったりします。
わかりやすくまずいのは例えば以下のような場合。
ハッシュ値が変わってしまうことで <code>HashSet</code> や <code>Dictionary</code> の挙動を壊します。</p>
<pre class="source" title="値比較を持っている参照型は immutable でないとまずい">
<code><span class="reserved">using</span> System;
<span class="reserved">using</span> System.Collections.Generic;
 
<span class="reserved">var</span> <span class="variable">p</span> = <span class="reserved">new</span> <span class="type">Point</span> { X = 1, Y = 2 };
 
<span class="comment">// HashSet (ハッシュ値で等値比較してる)にインスタンスを渡す</span>
<span class="type">HashSet</span>&lt;<span class="type">Point</span>&gt; <span class="variable">set</span> = <span class="reserved">new</span>();
<span class="variable">set</span>.<span class="method">Add</span>(<span class="variable">p</span>);
 
<span class="comment">// その後、値を書き換え</span>
<span class="variable">p</span>.X = 3;
 
<span class="comment">// ハッシュ値が変わってしまってるので判定が狂う</span>
<span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="variable">set</span>.<span class="method">Contains</span>(<span class="variable">p</span>)); <span class="comment">// false</span>
 
<span class="comment">// Remove もできなくなる</span>
<span class="variable">set</span>.<span class="method">Remove</span>(<span class="variable">p</span>);
<span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="variable">set</span>.Count); <span class="comment">// Remove できてないので 1 が返る</span>
 
<span class="reserved">class</span> <span class="type">Point</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> X { <span class="reserved">get</span>; <span class="reserved">set</span>; }
    <span class="reserved">public</span> <span class="reserved">int</span> Y { <span class="reserved">get</span>; <span class="reserved">set</span>; }
    <span class="reserved">public</span> <span class="reserved">bool</span> <span class="method">Equals</span>(<span class="type">Point</span> <span class="variable">other</span>) =&gt; (X, Y) == (<span class="variable">other</span>.X, <span class="variable">other</span>.Y);
    <span class="reserved">public</span> <span class="reserved">override</span> <span class="reserved">bool</span> <span class="method">Equals</span>(<span class="reserved">object</span>? <span class="variable">obj</span>) =&gt; <span class="variable">obj</span> <span class="reserved">is</span> <span class="type">Point</span> <span class="variable">other</span> &amp;&amp; <span class="method">Equals</span>(<span class="variable">other</span>);
    <span class="reserved">public</span> <span class="reserved">override</span> <span class="reserved">int</span> <span class="method">GetHashCode</span>() =&gt; X ^ Y;
}
</code></pre>
<p>レコード型から生成されるクラスの例に <code>init</code> というキーワードが入っていますが、
これも C# 9.0 の新機能で、プロパティがオブジェクト初期化子までは書き換え可能、その後は書き換え不能になるという機能です。
既存のプロパティと比べて、</p>
<ul>
<li>set 可能プロパティ(<code>int X { get; set; }</code> みたいなの): どこでも書き換えできる</li>
<li>get-only プロパティ (<code>int X { get; }</code> みたいなの): コンストラクター内でだけ書き換えできる</li>
<li>init プロパティ (<code>int X { get; init; }</code> みたいなの): コンストラクター内とオブジェクト初期化子でだけ書き換えできる</li>
</ul>
<pre class="source" title="init プロパティ">
<code><span class="reserved">var</span> <span class="variable">p</span> = <span class="reserved">new</span> <span class="type">Point</span>
{
    Settable = 1, <span class="comment">// OK</span>
    <span class="error">GetOnly</span> = 1,  <span class="comment">// ✖</span>
    Init = 1,     <span class="comment">// OK</span>
};
 
<span class="variable">p</span>.Settable = 1; <span class="comment">// OK</span>
<span class="error"><span class="variable">p</span>.GetOnly</span> = 1; <span class="comment">// ✖</span>
<span class="error"><span class="variable">p</span>.Init</span> = 1; <span class="comment">// ✖</span>
 
<span class="reserved">class</span> <span class="type">Point</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> Settable { <span class="reserved">get</span>; <span class="reserved">set</span>; }
    <span class="reserved">public</span> <span class="reserved">int</span> GetOnly { <span class="reserved">get</span>; }
    <span class="reserved">public</span> <span class="reserved">int</span> Init { <span class="reserved">get</span>; <span class="reserved">init</span>; }
 
    <span class="reserved">public</span> <span class="type">Point</span>()
    {
        Settable = 1; <span class="comment">// OK</span>
        GetOnly = 1;  <span class="comment">// OK</span>
        Init = 1;     <span class="comment">// OK</span>
    }
}
</code></pre>
<p>というものです。
C# の場合、<a href="https://ufcpp.net/study/csharp/oo_construct.html#member_initializer">初期化子</a>が C# 3.0 からの後付けなせいでちょっと使いにくかったんですが、その改善案になります。</p>
<p>immutable なデータを書き換えて使いたい場合、
shallow コピーを作ってからそのコピーの方を書き換えるというのが推奨される方式になります。
これに関しても C# 9.0 で「<code>with</code> 式」という新しい文法が追加されていて、
以下のような書き方でコピー＆ <code>init</code> プロパティの書き換えができます。</p>
<pre class="source" title="with 式で immutable データの書き換え(コピー後にプロパティ書き換え)">
<code><span class="reserved">using</span> System;
 
<span class="reserved">var</span> <span class="variable">p1</span> = <span class="reserved">new</span> <span class="type">Point</span>(1, 2);
<span class="reserved">var</span> <span class="variable">p2</span> = <span class="variable">p1</span> <span class="reserved">with</span> { X = 3 };
 
<span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="variable">p1</span>); <span class="comment">// Point { X = 1, Y = 2 } (元のまま)</span>
<span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="variable">p2</span>); <span class="comment">// Point { X = 3, Y = 2 } (新インスタンスで X が書き換わってる)</span>
 
<span class="reserved">record</span> Point(<span class="reserved">int</span> <span class="variable">X</span>, <span class="reserved">int</span> <span class="variable">Y</span>);
</code></pre>
<h2>C# 10.0 に持ち越されたレコード関連議題</h2>
<p>いくつか、レコードにはいくつか議題が残っていて、「10.0 で改めて検討」となっているものがあります。</p>
<ul>
<li>
レコードは参照型である
<ul>
<li>値型版 (仮称 record struct)をどうするか</li>
</ul>
</li>
<li>
既存の構造体との兼ね合い
<ul>
<li>「record struct」を新設すべきなのか、既存の構造体に手を入れるべきなのか</li>
<li>プロパティ生成とかはしないとしても、既存の構造体の時点で <code>with</code> 式を使える条件はそろってるはず</li>
</ul>
</li>
<li>
プライマリ コンストラクター
<ul>
<li>通常のクラスにも <code>class Point(int X, int Y)</code> みたいな書き方を認めたい
‐ その場合、単にコンストラクターの簡易記法であってプロパティなどのコンパイラー生成はしない</li>
</ul>
</li>
</ul>
<p>以下、
 <a href="https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-09-30.md">9/30</a>と<a href="https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-10-05.md">10/5</a>と<a href="https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-10-07.md">10/7</a>での検討事項。</p>
<h3>構造体の等値比較</h3>
<p>レコードでは「クラスに対して <code>Equals</code> メソッドをコンパイラー生成する」という仕組みで「値比較」を実現しています。</p>
<p>構造体の場合、<code>object.Equals(object)</code> の中で、.NET ランタイムが「値比較」に相当する処理を行っています。
なので、挙動としてはレコードと構造体の <code>Equals</code> はどちらも同じ「値比較」なんですが、
現状の構造体の <code>Equals</code> はちょっとパフォーマンスが悪いです。
これは、<code>Equals(object)</code>を介しているせいで<a href="https://ufcpp.net/study/csharp/RmBoxing.html">ボックス化</a>が起こるのと、.NET ランタイム内での処理が<a href="https://ufcpp.net/study/csharp/sp_reflection.html#reflection">リフレクション</a>的になっているからです。</p>
<p>そこで、レコードと同じく構造体に対してもコンパイラー生成で「値比較」の <code>Equals</code> メソッドを生成すべきかどうかというのが議題になっていました。</p>
<p>これに関しては以下のような結論。</p>
<ul>
<li>
コンパイラー生成の <code>Equals</code> は作らない方がいい
<ul>
<li>コンパイラー生成してしまうとコンパイル結果のバイナリ サイズが膨らむ</li>
<li>既存の構造体に対して <code>Equals</code> 生成すると既存コードを壊す
‐ かといって、新しい「record struct (仮)」だけが高パフォーマンスみたいな状態になると、既存の構造体が忌むべきものになってしまう(それは望まない)</li>
</ul>
</li>
<li>
既存の構造体と record struct (仮)は明確に別
<ul>
<li>プライマリ コンストラクターからのプロパティ生成、型付きの <code>==</code> 演算子・<code>Equals</code>メソッド生成、<code>IEquatable&lt;T&gt;</code> 実装するのは record struct (仮)だけ</li>
</ul>
</li>
<li>
.NET ランタイムのレベルで構造体の <code>Equals(object)</code> を最適化すべき
<ul>
<li><a href="https://ufcpp.net/blog/2018/12/jitintrinsics/">.NET Core  2.1 のときに <code>enum</code> とかに対してやったの</a>と同じで、 .NET ランタイムが構造体の <code>Equals</code> を特別扱いして最適化できるはず</li>
</ul>
</li>
</ul>
<h3>構造体に対する with 式</h3>
<p>構造体は元から shallow コピーを持っている(単に代入するだけでコピー発生。<a href="https://ufcpp.net/study/il/">.NET の中間言語</a>的にも dup 命令ってのを持ってて、1命令でコピーになる)ので、<code>with</code> 式を使える条件を満たしています。</p>
<p>また、C# 9.0 で入るレコード(クラスで生成されるやつ)は、現状、コピーのカスタマイズ性がない(通常の C# からは参照できない(<code>$Clone&lt;&gt;</code>みたいな)名前でコピー メソッドが生成されていて、手書きでの上書きができないようにしてある)状態です。
これは「将来改めて検討する」ということになっていて、とりあえず、カスタマイズ性がある状態からない状態には戻せないけれど、できないものをできるようにすることは簡単だからいったん「ない」仕様にしてあります。</p>
<p>これに対して、C# 10.0 では以下のような方針(決定ではない)で進めていきたいようです。</p>
<ul>
<li>すべての構造体は <code>with</code> 式利用可能にする</li>
<li>
ただ、既存の構造体は <code>with</code> 時のコピーのカスタマイズ性は提供しない
<ul>
<li>デフォルト動作の「dup 命令でコピー」を常に使う</li>
</ul>
</li>
<li>
record struct (仮) の場合は、レコード (9.0 で入るクラスのやつ)と合わせて再検討することになるけども…
  ‐ record struct (仮)のコピーのカスタマイズは認めない方がよさそう
<ul>
<li>でないと、ジェネリック型引数で <code>where T : struct</code> なものの挙動がおかしくなりそう</li>
</ul>
</li>
</ul>
<h3>プライマリ コストラクター</h3>
<p>C# 9.0 のレコードでは、プライマリ コンストラクターの引数(<code>record Point(int X, int Y)</code> の <code>X</code>、<code>Y</code>)から public な init プロパティ(<code>public int X { get; init; }</code> とか)が生成されます。</p>
<p>C# 10.0 で検討している record struct (仮) でも同様であるべきかという話があります。</p>
<ul>
<li>record (参照型のレコード) と record struct (値型のレコード)という見方をすると、
同じ挙動であった方がいい</li>
<li>
「record は名前付きの匿名型」に対して、「<a href="https://ufcpp.net/study/csharp/datatype/tuples/">タプル</a>の名前付き版」が欲しいという話もあって、record struct (仮) をその位置に据えたいという見方もある
<ul>
<li>この場合、タプルのメンバーは public フィールドになっているので、record struct (仮)は public フィールドを生成した方が合う</li>
</ul>
</li>
<li>
immutable でないと問題を起こすのは参照型だけ
<ul>
<li>値型の場合は代入で常にコピーが作られるので前述の <code>HashSet</code> みたいな問題を起こさない</li>
</ul>
</li>
</ul>
<p>そして検討の結果、現状、record struct (仮)に関しては以下のような方向性になりそうみたいです。</p>
<ul>
<li>デフォルトで public で <em>mutable</em> なプロパティ(<code>public int X { get; set;}</code> みたいなの)を生成する</li>
<li>手書きでカスタマイズ可能なので必要であれば `public int X { get; init; } を自分で足してもらう</li>
<li>あるいは構造体の場合元から<a href="https://ufcpp.net/study/csharp/cheatsheet/ap_ver7_2/#readonly-struct">readonly struct</a>があるので、immutable にしたければ <code>readonly record struct Point(int X, int Y)</code> みたいに書いてもらう</li>
<li>C# 9.0 時点のレコードには「プロパティかフィールドか」のカスタマイズ権はない(プロパティでないとダメ)ので、フィールドでも上書きできるように変更する</li>
</ul>
<h2>record struct</h2>
<p>10/8 追記:</p>
<p>record struct (仮) と、(仮) を付けて書いていたのは、具体的な文法をどうするかが決まっていなかったからです。
10/5 のものまでは、原文でも theoretical (理論上の)とか hypothetical (仮説上の)という前置き付きで record structs と言っていました。</p>
<p><a href="https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-10-07.md">10/7</a> で具体的な文法が検討されて、以下のような方向性になりました。</p>
<ul>
<li><code>record struct</code> (構造体に <code>record</code> 修飾)と <code>struct record</code> (レコードに <code>struct</code> 修飾)だと前者の方を選ぶメンバーが多かった</li>
<li>となると、<code>record</code> 修飾子と考える方が自然</li>
<li><code>record class</code> も認めたい</li>
<li><code>record</code> は、そのうちよく使う方の <code>record class</code> の短縮形だという風に考えたい</li>
<li>なので、<code>record struct</code> という文法を足すと同時に、<code>record class</code> も認める</li>
</ul>
<h3>data メンバー</h3>
<p>プライマリ コンストラクター (<code>record Point(int X, int Y)</code> みたいなの)からのプロパティ生成は、
常にコンストラクター生成がセットで、コンストラクターでの初期化が前提になります。</p>
<p>必然的に以下のような書き方になって、コンストラクター呼び出しには引数順序に意味があるので、
これを「位置によるレコード」(positional record)と呼んだりします。</p>
<pre class="source" title="positional record">
<code><span class="reserved">var</span> <span class="variable">p</span> = <span class="reserved">new</span> <span class="type">Point</span>(1, 2);
</code></pre>
<p>これに対して、init プロパティだけを書いて、</p>
<pre class="source" title="プライマリ コンストラクターは使わず init プロパティを定義">
<code><span class="reserved">record</span> <span class="type">Point</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> X { <span class="reserved">get</span>; <span class="reserved">init</span>; }
    <span class="reserved">public</span> <span class="reserved">int</span> Y { <span class="reserved">get</span>; <span class="reserved">init</span>; }
}
</code></pre>
<p>オブジェクト初期化子を前提にした書き方をすることもできます。
こちらはプロパティ名指定が必須で、逆に順序には意味がなくなるので、「名前によるレコード」(nominal record)と呼んだりします。</p>
<pre class="source" title="nominal record">
<code><span class="reserved">var</span> <span class="variable">p</span> = <span class="reserved">new</span> <span class="type">Point</span> { X = 1, Y = 2 };
</code></pre>
<p>これはこれで便利なんですが、レコード型の「プレーンなデータを簡潔に書けるようにする」という目的からすると、
<code>public int X { get; init; }</code>という書き方はちょっと煩雑過ぎます。</p>
<p>そこで提案されているのが <code>data</code> メンバーで、以下のようなコードから <code>public int X { get; init; }</code> をコンパイラー生成したいというものです。</p>
<pre class="source" title="data キーワードで nominal record を定義">
<code><span class="reserved">record</span> <span class="type">Point</span>
{
    <span class="reserved">data</span> <span class="reserved">int</span> X;
    <span class="reserved">data</span> <span class="reserved">int</span> Y;
}
</code></pre>
<p>この案自体はちょっと前からあって、単純に案が出たのがギリギリ過ぎて C# 9.0 には入れなかったという状態です。</p>
<p>ここで改めて record struct (仮)が議題になるんですが、</p>
<ul>
<li>
プライマリ コンストラクターからのプロパティ生成の仕方が違うけど、data メンバーの場合はどうするべきか
<ul>
<li>C# 9.0 の参照型レコードは immutable (<code>get; init;</code>)</li>
<li>record struct (仮) は mutable (<code>get; set;</code>)</li>
</ul>
</li>
</ul>
<p>という問題があります。</p>
<p>ここはまだだいぶ悩んでいるようで、以下の3案が全部まだ候補だそうです。</p>
<ul>
<li>positional に合わせるべきで、値型の場合は mutable (<code>get; set;</code>)、参照型の場合は immutable (<code>get; init;</code>)</li>
<li><code>data</code> の挙動は一致しているべきで、値型だろうと参照型だろうと immutable (<code>get; init;</code>)</li>
<li><code>data</code> メンバーという提案自体をあきらめる</li>
</ul>
<p>10/8 追記:</p>
<p><a href="https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-10-07.md">10/7</a> では「<code>public int X { get; init; }</code> を <code>data int X</code> に縮める」という案が本当に有効かどうか、具体的なシナリオを検討したみたいです。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/discussions/2962">discriminated union</a> を考えるとき、例1みたいなのには魅力を感じるけども、例2みたいなのはいまいちで、だったら <code>data</code> メンバーはそんなに「求めていたもの」じゃない</li>
</ul>
<pre class="source" title="単一行 discriminated union">
<code><span class="comment">// 例1: discriminated union (仮) として単一行メンバーなら書きたいモチベーションになる</span>
<span class="reserved">record</span> <span class="type">Union</span>
{
    <span class="type">A</span>;
    <span class="type">B</span>(<span class="reserved">int</span> <span class="variable">X</span>);
}
</code></pre>
<pre class="source" title="単一行 discriminated union">
<code><span class="comment">// 例2: data メンバーを使って書く場合複数行に。これは魅力的か？</span>
<span class="reserved">record</span> <span class="type">Union</span>
{
    <span class="type">A</span>;
    <span class="type">B</span>
    {
        <span class="reserved">data int</span> <span class="variable">X</span>;
    }
}
</code></pre>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/3630">required property</a> を考えるとき、<code>data</code> メンバーが required (オブジェクト初期化子で値を渡すことが必須)かどうかを変更できる追加のキーワードが必要(なので、記述が短くならないか、もしくは、<code>data</code> とは別のさらに追加のキーワードが必要)</li>
<li>通常のクラスにもプライマリ コンストラクターを定義できるように当たって、<code>class X(int X, data int Y)</code> みたいな書き方で、「<code>X</code> は単なるパラメーター、<code>Y</code> はレコードと同じくパラメーターからのプロパティなどの生成を行う」みたいなキーワードにしたいという案もある</li>
</ul>
<p>この辺りが悩ましくて、C# 10.0 のタイミングでは <code>data</code> メンバーはやめておこうという雰囲気みたいです。
discriminated union、required property、通常クラスのプライマリ コンストラクターの3つはいずれも C# 10.0 で検討している機能で、それが具体的に決まった後でないと、<code>data</code> キーワードの有効性がどうなるかわからないということで、C# 10.0 の後に再検討した方がいいだろうという感じ。</p>
 ]]></description>
				<pubDate>Wed, 07 Oct 2020 23:43:24 +0900</pubDate>
			</item>
			<item>
				<title>C# 9.0 最終版</title>
				<link>http://ufcpp.net/blog/2020/9/csharp9final/</link>
				<description><![CDATA[ <p>いくつかライブ配信では言ってたんですが、C# 9.0 がそろそろ機能確定しそうな感じ。
11月リリースと言ってるわけなので、まあ、時期的にもこの辺りで確定していないとまずいでしょう。</p>
<p>ということで、先日、 What's new in C# 9.0 もドキュメント化されて docs 上に公開されました。</p>
<ul>
<li><a href="https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-9?WT.mc_id=DT-MVP-4028921">What's new in C# 9.0</a></li>
</ul>
<p>見出しに載るようなレベルでの機能の増減はもうありません。</p>
<p>Records とか Function pointers とか、一部の機能はまだちょっと修正が入るかと思います。
それに関しては9月9日の Design Meeting 議事録にまとまっています。
(同日の議題には C# 10.0 の話題というか、C# 10.0 に流れてしまったものの話もあり。)</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-09-09.md">C# Language Design Meeting for September 9th, 2020</a></li>
</ul>
<p>ちなみに先日のライブ配信:</p>
<div>
<iframe width="560" height="315" src="https://www.youtube.com/embed/nJ1TMNfmllA" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div>
<h2>Visual Studio 16.8 Preview 2</h2>
<p><a href="https://youtu.be/Uc04x0eZBBM">16.8 Preview 2 が出た時点でのライブ配信</a>では気づいてなかったんですが、
以下の2つの機能、この時点で入っていました。
(これらが最後の C# 9.0 機能です。)</p>
<ul>
<li>Covariant return types</li>
<li>Extension GetEnumerator</li>
</ul>
<h3>Covariant return types</h3>
<p>いわゆる共変戻り値。virtual メソッドの override 側で、戻り値の型を共変にできるようになりました。
要するに、以下のようなやつです。</p>
<pre class="source" title="クラスの共変戻り値">
<code><span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">class</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(111, 66, 193);">Base</span>
{
    <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">public</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">virtual</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(111, 66, 193);">Base</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(111, 66, 193);">Clone</span>() <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">=&gt;</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">new</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(111, 66, 193);">Base</span>();
}

<span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">class</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(111, 66, 193);">Derived</span> : <span class="pl-en" style="box-sizing: border-box; color: rgb(111, 66, 193);">Base</span>
{
    <span class="comment">// これの戻り値、C# 8.0 までは Base でないとダメだった</span>
    <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">public</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">override</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(111, 66, 193);">Derived</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(111, 66, 193);">Clone</span>() <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">=&gt;</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">new</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(111, 66, 193);">Derived</span>();
}
</code></pre>
<p>デリゲートや、<code>out</code> 修飾付きのジェネリック型引数などではこれまでもできていたことですし、
認めてまずいことは何1つありません。
これができないことは割かしずっと問題として認識はされていて、
今になってようやく実装されたのは単に優先度の問題です。</p>
<p>C# 9.0 の機能のメジャーな機能の中では唯一、 .NET Runtime 側の修正が必須
(C# コンパイラーによる小手先のトリックだけでは実現不能)な機能です。
要するに、「.NET Core への移行だけで手一杯(C# 7.0 付近)」 → 「<a href="https://ufcpp.net/study/csharp/oo_interface.html?p=5#dim">インターフェイスのデフォルト実装</a>の方が優先(C# 8.0)」 → 「共変戻り値に着手(今ここ)」という感じ。</p>
<p>(インターフェイスのデフォルト実装同様、というかそれよりさらにだいぶ昔から、Java にはこの機能があったり。
Android での Java との相互運用のためもあって、.NET Core と Xamarin (Mono) との統合を目指している今このタイミングで共変戻り値も採用になりました。)</p>
<h3>Extension GetEnumerator</h3>
<p><code>GetEnumerator</code> が拡張メソッドであっても <a href="https://ufcpp.net/study/csharp/sp_foreach.html"><code>foreach</code> ステートメント</a>で使えるようになりました。</p>
<p>例えば以下のような拡張メソッドを用意することで、2-<a href="https://ufcpp.net/study/csharp/datatype/tuples/">tuple</a> に対する <code>foreach</code> が使えます。</p>
<pre class="source" title="2-tuple を foreach するための拡張メソッド">
<code><span class="reserved">using</span> System;
<span class="reserved">using</span> System.Collections.Generic;
 
<span class="control">foreach</span> (<span class="reserved">var</span> <span class="variable">i</span> <span class="control">in</span> (1, 2))
{
    <span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="variable">i</span>);
}
 
<span class="reserved">static</span> <span class="reserved">class</span> <span class="type">TupleExtensions</span>
{
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="type">Tuple2Enumerator</span>&lt;<span class="type">T</span>&gt; <span class="method">GetEnumerator</span>&lt;<span class="type">T</span>&gt;(<span class="reserved">this</span> (<span class="type">T</span>, <span class="type">T</span>) <span class="variable">t</span>) =&gt; <span class="reserved">new</span>(<span class="variable">t</span>);
 
    <span class="reserved">public</span> <span class="reserved">struct</span> <span class="type">Tuple2Enumerator</span>&lt;<span class="type">T</span>&gt; : <span class="type">IEnumerator</span>&lt;<span class="type">T</span>&gt;
    {
        <span class="reserved">private</span> <span class="reserved">int</span> _i;
        <span class="reserved">private</span> (<span class="type">T</span>, <span class="type">T</span>) _tuple;
 
        <span class="reserved">public</span> <span class="type">Tuple2Enumerator</span>((<span class="type">T</span>, <span class="type">T</span>) <span class="variable">tuple</span>)
        {
            _i = 0;
            _tuple = <span class="variable">tuple</span>;
        }
 
        <span class="reserved">public</span> <span class="type">T</span> Current =&gt; _i <span class="control">switch</span>
        {
            1 =&gt; _tuple.Item1,
            2 =&gt; _tuple.Item2,
            <span class="reserved">_</span> =&gt; <span class="reserved">default</span>!,
        };
 
        <span class="reserved">public</span> <span class="reserved">bool</span> <span class="method">MoveNext</span>() =&gt; ++_i &lt; 3;
 
        <span class="reserved">object</span> System.Collections.<span class="type">IEnumerator</span>.Current =&gt; Current!;
        <span class="reserved">void</span> System.Collections.<span class="type">IEnumerator</span>.<span class="method">Reset</span>() =&gt; <span class="control">throw</span> <span class="reserved">new</span> <span class="type">NotImplementedException</span>();
        <span class="reserved">void</span> <span class="type">IDisposable</span>.<span class="method">Dispose</span>() { }
    }
}
</code></pre>
<p>まあ、実用途があるかというとそこまで有益な使い道は思いつかないんですが…</p>
<p>配信ではしゃべってるんですが、
<a href="https://github.com/ufcpp-live/UfcppLiveAgenda/issues/14#issuecomment-687748403">タプルに対しては arity ごとに別拡張メソッドが必要だったり</a>、
<a href="https://github.com/ufcpp-live/UfcppLiveAgenda/issues/14#issuecomment-687749388">Range に対しては inclusive/exclusive 問題がやっぱりだいぶ混乱しそうとか</a>あり。</p>
<p>これは、他の新しめの文法との一貫性を取るためです。
<a href="https://ufcpp.net/study/csharp/misc/miscpatternbased/#index">パターン ベースな構文一覧</a>にある通り、
<a href="https://ufcpp.net/csharp/sp3_stdquery.html">クエリ式</a>とか<a href="https://ufcpp.net/study/csharp/datatype/deconstruction/#arbitrary-types">分解</a>、
<a href="https://ufcpp.net/study/csharp/sp5_awaitable.html#awaiter">await</a> では認めていることなので、
それと揃えたいという話が前々からありました。</p>
<p>(確かそれも、実用性が低めということで着手されず、最終的にはコミュニティ貢献(C# チーム外の人の実装)だったと思います。)</p>
<h3>null 許容参照型の改善</h3>
<p><a href="https://github.com/dotnet/csharplang/issues/3297">#3297</a>のうち、たぶん、制約なしジェネリック型に対する <code>T?</code> は 16.8 Preview 2 で入ったはず。</p>
<pre class="source" title="制約なし T?">
<code><span class="reserved">class</span> <span class="type">C</span>&lt;<span class="type">T</span>&gt;
<span class="comment">//where T :class // これがあれば前からOK</span>
<span class="comment">//where T :struct // これがあれば前からOK</span>
<span class="comment">// 制約なしは今回から初めてOK</span>
{
    <span class="comment">// これだとエラー。 </span>
    <span class="comment">// T? と言いつつ、C&lt;int&gt; とかを渡すと int。int? ではない</span>
    <span class="comment">//public static T? M() =&gt; null;</span>
 
    <span class="comment">// 実は nullable じゃなくて、defaultable</span>
    <span class="comment">// LINQ の FirstOrDefault 的な奴</span>
    <span class="comment">// あまりにきもいから、当初 T?? にしようという案もあった</span>
    <span class="comment">// ? になったのは、 x ?? y の ?? と区別つかなくて困ったかららしい</span>
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="type">T</span>? <span class="method">M</span>() =&gt; <span class="reserved">default</span>;
}
</code></pre>
<p>ただこれ、少々クセはありまして。
上記コメントにもありますが、この場合の <code>T?</code> は nullable じゃなくて「defaultable」と呼んだ方がいいかもしれないようなものです。
以下のように、型引数として非 null 値型を渡すと nullable にはなりません。</p>
<pre class="source" title="defaultable な T?">
<code><span class="reserved">string</span>? <span class="variable">x1</span> = <span class="type">C</span>&lt;<span class="reserved">string</span>?&gt;.<span class="method">M</span>();
<span class="reserved">string</span>? <span class="variable">x2</span> = <span class="type">C</span>&lt;<span class="reserved">string</span>&gt;.<span class="method">M</span>(); <span class="comment">// 順当に string?</span>
<span class="reserved">int</span>?    <span class="variable">x3</span> = <span class="type">C</span>&lt;<span class="reserved">int</span>?&gt;.<span class="method">M</span>();   <span class="comment">// 順当に int?</span>
<span class="reserved">int</span>     <span class="variable">x4</span> = <span class="type">C</span>&lt;<span class="reserved">int</span>&gt;.<span class="method">M</span>();    <span class="comment">// これの戻り値は int? にならない。default(int)、つまり、0 が返る。</span>
</code></pre>
<p>「実は nullable じゃなくて defaultable」という挙動が気持ち悪すぎて C# 8.0 時点では見送られたし、
9.0 でも <code>T??</code> みたいな他の文法が検討されたりしたんですが、他の文法にもいろいろ問題があって、
結局単に「制約なしの <code>T?</code> は defaultable」ということになったみたいです。</p>
<h2>C# 9.0 最終トリアージ</h2>
<p><a href="https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-09-09.md">C# Language Design Meeting for September 9th, 2020</a>は、C# 9.0 のタイミングでやる作業の最終判断みたいな感じになっています。</p>
<p>冒頭で言った通り、
「<a href="https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-9?WT.mc_id=DT-MVP-4028921">What's new in C# 9.0</a>」みたいな記事が docs に並ぶ時点でもう、大きな変更はないんですけども、
いくつか細かい議題が。</p>
<p>とりあえず今日は 9.0 の残作業の話のみ。</p>
<p>「10.0 行き」みたいな感じで分類されているものも、
言い回しとしては「10.0 までの期間で再検討」みたいなふわっとしたものが多いので、
もうちょっと固まってきたら改めて。
その他、「Anytime (いつやるか不明。相当低優先度)」行きなものも省略。</p>
<h3>! と .? の組み合わせがおかしい</h3>
<p><a href="https://github.com/dotnet/csharplang/issues/3393">#3393</a></p>
<p>現在、<code>a?.b.c!.d.e</code> が <code>(a?.b.c)!.d.e</code> として解釈されてしまうという問題があります。</p>
<p><a href="https://ufcpp.net/study/csharp/rm_nullusage.html#key-null-conditional">null 条件演算子 <code>?.</code></a>のショートサーキットの性質上、<code>!</code> の有無によって挙動が変わります。
<a href="https://ufcpp.net/study/csharp/resource/nullablereferencetype/?p=3#null-forgiving">null 抑止演算子 <code>!</code></a>の理念としては、<code>!</code> の有無で挙動は変えたくないそうで、これは完全に想定外の仕様バグです。</p>
<p>ただ、C# 8.0 で1度この仕様で実装してしまったものはしょうがないので、「破壊的変更を許容してでも直すべきバグかどうか」が争点にはなっていました。
まあ、それでも「9.0 で直す」判定になりそうです。</p>
<h3>インターフェイスの静的メソッドが共変注釈をちゃんと見てない</h3>
<p><a href="https://github.com/dotnet/csharplang/issues/3275">#3275</a></p>
<p>これもほぼバグ。こっちは破壊的変更をするわけでもなく、単に深刻度が低くて優先度が低い状態。
Pull Request はすでに出ていて間に合うかどうかだけの問題で、
一応まだ C# 9.0 候補だそうです。</p>
<h3>record がらみ</h3>
<p><a href="https://github.com/dotnet/csharplang/issues/3226">#3226</a>、
<a href="https://github.com/dotnet/csharplang/issues/3213">#3213</a>、
<a href="https://github.com/dotnet/csharplang/issues/3137">#3137</a> など</p>
<p>結構、10.0 行きになった機能はあります。</p>
<p>ただ、いくつかは 16.8 Preview 2 時点で実装されていないけども正式リリースまでに実装されるということになっているものがあります。</p>
<ul>
<li><code>ToString</code> で単に型名だけじゃなく、<code>Point { X = 1, Y = 2 }</code> みたいな文字列化されるようになる</li>
<li>
<code>==</code> 演算子が生成されるようになる
<ul>
<li>reference equal じゃなくて、<code>Equals</code> メソッド呼び出しの「値による比較」になる</li>
</ul>
</li>
<li><code>Equals</code> と <code>GetHashCode</code> (コンパイラーが自動生成してくれるものの、手書きで挙動を上書き可能)のうち、片方だけ手動上書きすると警告になる</li>
</ul>
 ]]></description>
				<pubDate>Sun, 13 Sep 2020 09:41:23 +0900</pubDate>
			</item>
			<item>
				<title>Visual Studio 16.7 &amp; 16.8 Preview 1 リリース / C# 9.0 の新機能3つ(module initializers, static lambda, target-typed conditional)</title>
				<link>http://ufcpp.net/blog/2020/8/vs168p1/</link>
				<description><![CDATA[ <p>5日に、Visual Studio 2019 の 16.7 と、16.8 Preview 1 がリリースされました。</p>
<ul>
<li><a href="https://devblogs.microsoft.com/visualstudio/visual-studio-2019-v16-7-releases/">Visual Studio 2019 v16.7 and v16.8 Preview 1 Release Today!</a></li>
</ul>
<p>ということで、先週、ライブ配信もしていました。</p>
<div>
<iframe width="560" height="315" src="https://www.youtube.com/embed/-_QGGvT5FEw" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div>
<p>16.7 が正式リリースになった記念に、Preview の頃に触れてた話題を改めてちょこっと振り返ったのと、16.8 Preview 1 で新たに追加された C# 9.0 の3つの機能の話でした。</p>
<p>C# 9.0 に今回追加されたのは以下の3つです。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/blob/master/proposals/csharp-9.0/module-initializers.md">Module Initializers</a></li>
<li><a href="https://github.com/dotnet/csharplang/blob/master/proposals/csharp-9.0/static-anonymous-functions.md">Static anonymous functions</a></li>
<li><a href="https://github.com/dotnet/csharplang/blob/master/proposals/csharp-9.0/target-typed-conditional-expression.md">Target-Typed Conditional Expression</a></li>
</ul>
<p>今日は主にこの3つについて説明。</p>
<h2>Module Initializers</h2>
<p>モジュール(exe (アプリ)や dll (ライブラリ))が読み込まれた時点で必ず1回呼ばれるメソッドを書けるようになりました。</p>
<p>以下のように、<code>ModuleInitializer</code> 属性を付けた静的メソッドが、モジュール読み込み時に呼ばれます。</p>
<pre class="source" title="ModuleInitializer">
<code><span class="reserved">using</span> System;
<span class="reserved">using</span> System.Runtime.CompilerServices;

<span class="reserved">class</span> <span class="type">Init</span>
{
    [ModuleInitializer]
    <span class="reserved">internal</span> <span class="reserved">static</span> <span class="reserved">void</span> M1() =&gt; Console.WriteLine(<span class="string">"Init.M1"</span>);

    [ModuleInitializer]
    <span class="reserved">internal</span> <span class="reserved">static</span> <span class="reserved">void</span> M2() =&gt; Console.WriteLine(<span class="string">"Init.M2"</span>);
}
</code></pre>
<p><a href="/study/csharp/oo_static.html#ctor">静的コンストラクター</a>でも近いことができるんですが、</p>
<ul>
<li>
静的コンストラクター
<ul>
<li>そのクラスのメンバーに触れた時点で初めて呼ばれる
  ‐ 1度も使っていないクラスの静的コンストラクターは結局呼ばれない</li>
<li>1つのクラスに1つ限り</li>
</ul>
</li>
<li>Module Initializers
  ‐ クラスのメンバーを使っていようが使っていまいが、モジュール読み込み時に必ず呼ばれる
  ‐ 1クラスに複数持てる</li>
</ul>
<p>みたいな差があります。
確実に、確定タイミングで呼ばれるというのもメリットですし、個別に静的コンストラクターを持つよりはちょっとだけパフォーマンス的にも都合がいいみたいです。</p>
<p>今、<a href="https://ufcpp.net/blog/2020/5/sourcegenerator/">Source Generator</a>って機能の実装も進められていて、これが入ると、たぶん「各クラスについて1回限り走らせたい処理」みたいなものは結構あると思います。
例えば自分が必要に迫られているものだと、<a href="https://github.com/ufcpp-live/UfcppLiveAgenda/issues/12#issuecomment-669958700">リフレクションが使えない環境で自前でリフレクションに代わる型情報を持つ</a>みたいなコードなんですけども、
これが「確実に、確定タイミング」になってくれるのは結構ありがたかったりします。</p>
<h2>Static anonymous functions</h2>
<p><a href="/study/csharp/functional/fun_localfunctions/#anonymous-function">匿名関数</a> (<a href="/study/csharp/sp_delegate.html#lambda">ラムダ式</a>と<a href="/study/csharp/sp_delegate.html#anonymous-method">匿名メソッド式</a>)に対して <code>static</code> 修飾を付けて、<a href="/study/csharp/sp2_anonymousmethod.html#closure">キャプチャ</a>の抑止ができるようになりました。</p>
<pre class="source" title="静的匿名関数">
<code><span class="reserved">using</span> System;

<span class="comment">// OK</span>
Action staticLambda = <span class="reserved">static</span> () =&gt; { };
Action staticAnonymousMethod = <span class="reserved">static</span> <span class="reserved">delegate</span> () { };

<span class="comment">// コンパイル エラー</span>
<span class="reserved">int</span> local = 1;
Action badStaticLambda = <span class="reserved">static</span> () =&gt; Console.WriteLine(<span class="error">local</span>);
Action badStaticAnonymousMethod = <span class="reserved">static</span> <span class="reserved">delegate</span> () { Console.WriteLine(<span class="error">local</span>); };
</code></pre>
<p>これは割かし、「工数的な問題で 8.0 に入らなかっただけ」系の機能です。
C# 8.0 時点で<a href="/study/csharp/functional/fun_localfunctions/#static-local-function">ローカル関数に関しては同様の機能</a>が入っていて、
匿名関数でも同様の需要があることはわかっていましたが、
文法的にちょっとめんどくさいので後回しになっていたものです。</p>
<h2>Target-Typed Conditional Expression</h2>
<p>条件演算子 (<code>? :</code>)で、第2項と第3項で共通の型を決められないときに、<a href="/study/csharp/start/misctyperesolution/#target-type">ターゲット型</a>を見て型を決定できるようになりました。</p>
<pre class="source" title="target-typed conditional exrpression">
<code><span class="reserved">void</span> targetTypedConditional(<span class="reserved">bool</span> x)
{
    <span class="comment">// target-typed で、1 : null の部分がちゃんと int? になる。</span>
    <span class="reserved">int</span>? v1 = x ? 1 : <span class="reserved">null</span>;

    <span class="comment">// あくまで target-typed で判定してるので、以下のような推論は働かない(コンパイル エラー)。</span>
    <span class="comment">// 1 と null の「共通型」は確定できない。</span>
    <span class="comment">//var v2 = x ? 1 : null;</span>
}
</code></pre>
<p><a href="/study/csharp/datatype/typeswitch/?p=5#switch-expression"><code>switch</code> 式</a>の場合には C# 8.0 時点であった機能です。新しい文法である <code>switch</code> 式と違って、既存の文法に手を入れるのはリスクもある(というか、実際、ちょっと破壊的変更を起こしてる)ので 8.0 には間に合わなかった機能です。</p>
 ]]></description>
				<pubDate>Mon, 10 Aug 2020 21:02:46 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 7/21: 引き続き C# 10.0 向けトリアージ</title>
				<link>http://ufcpp.net/blog/2020/7/pickuproslyn0721/</link>
				<description><![CDATA[ <p><a href="https://ufcpp.net/blog/2020/7/pickuproslyn0719/">先週に続き</a>トリアージ。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-07-20.md">C# Language Design Meeting for July 20th, 2020</a></li>
</ul>
<p>あと、records がらみの残作業整理。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/3707">Remaining design work in and around records #3707</a></li>
</ul>
<p>こちらも 9.0 (今年11月リリース)よりも先の話になります。
records の「残作業」というのも「9.0 からは削ったけども」という話です。</p>
<h2>トリアージ</h2>
<ul>
<li><a href="https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-07-20.md">C# Language Design Meeting for July 20th, 2020</a></li>
</ul>
<h3>Extend with expression to anonymous type</h3>
<ul>
<li>匿名型は record 的な性質がある(immutable で、<a href="/study/csharp/oo_construct.html#member_initializer">オブジェクト初期化子</a>を使ってインスタンス生成)型なので、record と同じく <code>with</code> 式を使いたい</li>
<li>そもそも「<code>with</code> 式の汎用化」自体「records の残作業」なので、それと合わせて C# 10.0 に向けて考えたい</li>
</ul>
<h3>Required properties</h3>
<ul>
<li>init プロパティ(<code>var a = new A { X = 1 }</code> みたいに初期化子での書き換えはできるけど、その後 <code>a.X = 2;</code> みたいな書き換えは認めないプロパティ)に対して、「初期化子での初期化を義務付け」みたいな制約を足したい</li>
<li>C# 10.0 で考える</li>
</ul>
<h3>Shebang support</h3>
<ul>
<li>Shebang = スクリプトでよく見る <code>#!/bin/sh</code> みたいなやつのこと(sharp + bang を縮めた造語)
  ‐ シェルに解釈してもらって、「このスクリプトファイルをどのインタープリターに掛けるか」みたいなのの指定に使う
  ‐ インタープリター側からすると単に無視してる</li>
<li>
これまで C# は、ランタイムのバージョンとか、依存するパッケージ、ツールとかの指定は C# ソースコード内には書かず、外部(csproj とか)に置いてた
<ul>
<li>C# のスクリプト用途を次のステップに進めるために、C# でも「単一 cs ファイルでこの手の情報を持てるようにしたい」という話に</li>
</ul>
</li>
<li>C# 10.0 のタイミングでディスカッションしたい
  ‐ 10.0 に入れれないかもしれないけど、「ディスカッション開始自体に何年もかかる」みたいにはしたくなくて、「何か月かかかる」程度に収めたい</li>
</ul>
<h3>Private fields in structs with SkipLocalsInit</h3>
<ul>
<li><a href="/blog/2020/7/pickuproslyn0719/">前回</a>も書いた「private フィールド持ちの構造体の<a href="/study/csharp/resource/rm_struct/#definite-assignment">確実な初期化</a>が実は漏れてる」問題、やっぱりまずいという話に</li>
<li><a href="/blog/2020/4/begginingcs9/">SkipLocalsInit</a>と組み合わさると、セキュリティ的にもガベコレ的にも危ないコードになる</li>
<li>
native compiler (C# 5.0 以前の、C++ 実装の C# コンパイラー)時代からの負の遺産が残っているだけで、ちゃんと未初期化を検知して警告にできる実装にはなってる
<ul>
<li>警告の追加も破壊的変更になるので、警告ウェーブ(言語バージョンとは別に警告のバージョニングを追加する)とともに有効にする予定だった
-でも、SkipLocalsInit 指定があるときには有無を言わさず警告を出すように修正することにした</li>
</ul>
</li>
</ul>
<h2>records がらみの残作業</h2>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/3707">Remaining design work in and around records #3707</a></li>
</ul>
<h3>More initialization functionality</h3>
<p>reocrds は、これまでの C# の「immutable なオブジェクトの初期化がとにかくめんどくさい」という問題に対する解決策だったりするので、初期化回りの機能が多いです。
9.0 で入れれなくて引き続き課題になっているものも結構残っていたり。</p>
<h4>Init fields</h4>
<ul>
<li>init-only プロパティ(<code>T Property { get; init; }</code> みたいなやつ)だけじゃなく、フィールドにも <code>init</code> 修飾をつけて、オブジェクト初期化子で書き換え可能にしたい</li>
</ul>
<h4>Init members</h4>
<ul>
<li>init-only プロパティはコンストラクターか他の <code>init</code>アクセサーからも書き換えできるけど、9.0 時点ではその他のメソッドからは書き換えできない</li>
<li>メソッドに <code>init</code> 修飾を付けることで、コンストラクターか <code>init</code> アクセサー内からだけ呼び出せて、init-only プロパティの書き換えができるメソッドを定義したい</li>
</ul>
<h4>Final initializers</h4>
<ul>
<li>
オブジェクト初期化子での初期化が一通り終わったあとに呼ばれるメソッドが欲しい
<ul>
<li>コンストラクターはオブジェクト初期化子よりも前になっちゃう</li>
</ul>
</li>
<li>今のところ <code>init { ... }</code> みたいな構文を考えてる</li>
<li>この機能自体は欲しい。初期化が一通り終わったあとに、オブジェクトの状態が不正じゃないかの確認をしたいことは多々ある</li>
<li>ただ、「オブジェクト初期化子の後に呼ぶ」っていうタイミングは古いコンパイラーには強制できない</li>
</ul>
<h4>Required members</h4>
<p>トリアージでも出てきてるので省略。</p>
<h4>Factories</h4>
<ul>
<li>ファクトリーメソッドも records の一部として考慮
  ‐ 「必ず新しいインスタンスを作って返す」みたいなのを強制する仕組みが要る</li>
</ul>
<h4>What about collection initializers?</h4>
<ul>
<li>
init-only なコレクション初期化子は可能？
<ul>
<li><code>new T { a, b }</code> みたいなのは、<code>var x = new T(); x.Add(a); x.Add(b);</code> に展開しちゃうし、通常、この <code>Add</code> は mutation (状態の書き換え)を起こしちゃう
‐ 前述の init members を使って、init-only (初期化子のタイミングまでは呼び出し可能)な <code>Add</code> メソッドを作れればいける？</li>
</ul>
</li>
</ul>
<h3>Generalizing away record magic</h3>
<p>今、records (<code>record</code> キーワードを使って型を宣言)専用になってしまっている機能が結構あるものの、普通のクラスや構造体に対しても適用できそうな文法も結構あります。
records と他の複合型の差は小さい方が、互いに乗り換えがしやすくて好ましいので、
できる限り「records 専用な構文」は作りたくありません。</p>
<h4>Allowing users to define cloning</h4>
<ul>
<li><code>with</code> 式は「クローン → 部分書き換え」を行う構文</li>
<li>現状、このクローンは records から生成される通常定義・通常呼び出し不可の専用メソッドでやってる</li>
<li>前述の Factories も入れた上で、ユーザー定義の <code>Clone</code> メソッドを受け付けるようにしたい</li>
</ul>
<h4>Cross-inheritance between records and non-records</h4>
<ul>
<li>現状、records は records から、クラスはクラスからしか派生できない</li>
<li>「records の基底クラスとして使える条件」みたいなのをしっかりと定義することで、「異種派生」を認められるようにしたい</li>
</ul>
<h4>Primary constructors</h4>
<ul>
<li><code>record T(int X, int Y);</code> みたいな書き方、クラスと構造体でも使えるようにしたい
  ‐ records の場合はこのコンストラクター引数からプロパティ <code>X</code>、<code>Y</code> の生成までやっちゃってるけど
  ‐ クラス、構造体ではコンストラクターの簡易記法としてだけ使って、プロパティの生成まではやらない</li>
</ul>
<h4>Bodies and attributes for primary constructors</h4>
<ul>
<li>現状、プライマリ コンストラクターには属性を付けれないし、本体を持てない</li>
<li><code>record T(int X) { T { ... } }</code> みたいな記法(引数なしコンストラクター)で、プライマリ コンストラクターの本体を与えたい</li>
<li>Final initializers (<code>init { ... }</code>) と用途がちょっと被り気味だけど、完全に一本化できなくて、どっちも必要</li>
</ul>
<h4>Automatic with-ing on all structs?</h4>
<ul>
<li>構造体は常に <code>with</code> 式で使える要件を満たせてはいる
  ‐ 暗黙的にメンバーごとのコピー機能を持ってる
  ‐ これをそのまま使って <code>with</code> 式を認めるべき？</li>
</ul>
<h3>More record functionality</h3>
<p>いくつか、records として予定されていた機能は C# 9.0 に間に合ってなくて未実装。</p>
<h4>Struct records</h4>
<ul>
<li>現状、records は参照型</li>
<li>records のセマンティクスは構造体にインスパイアされてるものなのに、records の機能のいくつかは当の構造体では使えない
  ‐ positional members (プライマリ コンストラクターからのプロパティ生成)とか、strongly-typed な <code>Equals</code>/<code>IEquatable&lt;T&gt;</code>  生成したりとか</li>
<li>「値型の records」みたいなのを定義する構文が別途必要</li>
</ul>
<h4>Data properties</h4>
<ul>
<li><code>data string Name</code> みたいな書き方で <code>public string Name { get; init; }</code> を生成したい</li>
</ul>
<h3>Discriminated unions</h3>
<p><a href="https://github.com/dotnet/csharplang/issues/113">#113</a> とか <a href="https://github.com/dotnet/csharplang/issues/2962">#2962</a> とか参照。</p>
<ul>
<li>records が落ち着いてからその先の機能として検討するつもりでいた</li>
<li>その時が来た</li>
</ul>
 ]]></description>
				<pubDate>Tue, 21 Jul 2020 23:33:07 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 7/19: そろそろ C# 9.0 機能は fix、10.0 向けトリアージ</title>
				<link>http://ufcpp.net/blog/2020/7/pickuproslyn0719/</link>
				<description><![CDATA[ <p>Visual Studio 16.7 Preview 4 が出てるのと、Design Meeting 議事録を1件紹介。</p>
<ul>
<li><a href="https://docs.microsoft.com/ja-jp/visualstudio/releases/2019/release-notes-preview#16.7.0-pre-4.0">Visual Studio 2019 バージョン 16.7 Preview 4</a></li>
<li><a href="https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-07-13.md">C# Language Design Meeting for July 13th, 2020</a></li>
</ul>
<p>16.7 Preview 4 で、<code>LangVersion</code> に <code>9.0</code> が入りました。
また、7月13日の Meeting 議事録は C# 9.0 よりも先の話が出てきています。
一部のちょっとした修正を除けば、「C# 10.0 候補として採用」、「C# 10.0 のタイミングで再検討」みたいな結論のものが多いです。</p>
<h2>16.7 Preview 4 と C# 9.0</h2>
<p><a href="https://ufcpp.net/blog/2020/6/cs9vs16_7p3/">16.7 Preview 3 のとき</a>から目立った新機能はないんですが、Preview 3 の時に気になっていたバグは治っていました。</p>
<p>特に、Top-level statements が安心して使えるようになったのは結構な嬉しさがあります。
(Preview 3/3.1 の時は、誤判定で「未使用 private メソッド扱い」されて挙動不審だった。)</p>
<p>以下のような、<code>class Program</code> も <code>static void Main</code> も要らないコードが書けます。</p>
<pre class="source" title="Top-level statements">
<code><span class="reserved">using</span> System;

<span class="reserved">foreach</span> (var r <span class="reserved">in</span> <span class="string">"🥺😍🙄"</span>.EnumerateRunes())
{
    Console.WriteLine(<span class="string">$"</span>{r.Value:<span class="string">X</span>}<span class="string">"</span>);
}
</code></pre>
<p><img src="/media/1180/toplevel-statements.png" alt="ぴえん" /></p>
<p>これまで、C# 9.0 候補の機能は Preview としてだけ提供されていて、<code>LangVersion</code> に <code>preview</code> を指定しないと使えませんでした。</p>
<pre class="xsource" title="LangVersion preview">
<code><span class="attvalue">&lt;</span><span class="element">Project</span><span class="attvalue"> </span><span class="attribute">Sdk</span><span class="attvalue">=</span>"<span class="attvalue">Microsoft.NET.Sdk</span>"<span class="attvalue">&gt;</span>

<span class="attvalue">  &lt;</span><span class="element">PropertyGroup</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">OutputType</span><span class="attvalue">&gt;</span>Exe<span class="attvalue">&lt;/</span><span class="element">OutputType</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">TargetFramework</span><span class="attvalue">&gt;</span>net5.0<span class="attvalue">&lt;/</span><span class="element">TargetFramework</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">LangVersion</span><span class="attvalue">&gt;</span><em>preview</em><span class="attvalue">&lt;/</span><span class="element">LangVersion</span><span class="attvalue">&gt;</span>
<span class="attvalue">  &lt;/</span><span class="element">PropertyGroup</span><span class="attvalue">&gt;</span>

<span class="attvalue">&lt;/</span><span class="element">Project</span><span class="attvalue">&gt;</span>
</code></pre>
<p>これに対して、VS 16.7 Preview 4 で、「<code>9.0</code>」が追加され、以下のように言語バージョンを明示できるようになりました。</p>
<pre class="xsource" title="LangVersion 9.0">
<code><span class="attvalue">&lt;</span><span class="element">Project</span><span class="attvalue"> </span><span class="attribute">Sdk</span><span class="attvalue">=</span>"<span class="attvalue">Microsoft.NET.Sdk</span>"<span class="attvalue">&gt;</span>

<span class="attvalue">  &lt;</span><span class="element">PropertyGroup</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">OutputType</span><span class="attvalue">&gt;</span>Exe<span class="attvalue">&lt;/</span><span class="element">OutputType</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">TargetFramework</span><span class="attvalue">&gt;</span>net5.0<span class="attvalue">&lt;/</span><span class="element">TargetFramework</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">LangVersion</span><span class="attvalue">&gt;</span><em>9.0</em><span class="attvalue">&lt;/</span><span class="element">LangVersion</span><span class="attvalue">&gt;</span>
<span class="attvalue">  &lt;/</span><span class="element">PropertyGroup</span><span class="attvalue">&gt;</span>

<span class="attvalue">&lt;/</span><span class="element">Project</span><span class="attvalue">&gt;</span>
</code></pre>
<p>また、 .NET 5 がターゲット(<code>TargetFramework</code> が <code>net5.0</code>)の場合、
デフォルト挙動(<code>LangVersion</code> を省略、もしくは、<code>default</code> 指定)が C# 9.0 になりました。
なので、以下の書き方(<code>net5.0</code> で <code>LangVersion</code> 省略)でも C# 9.0 になります。</p>
<pre class="xsource" title="">
<code><span class="attvalue">&lt;</span><span class="element">Project</span><span class="attvalue"> </span><span class="attribute">Sdk</span><span class="attvalue">=</span>"<span class="attvalue">Microsoft.NET.Sdk</span>"<span class="attvalue">&gt;</span>

<span class="attvalue">  &lt;</span><span class="element">PropertyGroup</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">OutputType</span><span class="attvalue">&gt;</span>Exe<span class="attvalue">&lt;/</span><span class="element">OutputType</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">TargetFramework</span><span class="attvalue">&gt;</span>net5.0<span class="attvalue">&lt;/</span><span class="element">TargetFramework</span><span class="attvalue">&gt;</span>
<span class="attvalue">  &lt;/</span><span class="element">PropertyGroup</span><span class="attvalue">&gt;</span>

<span class="attvalue">&lt;/</span><span class="element">Project</span><span class="attvalue">&gt;</span>
</code></pre>
<h2>10.0 向けトリアージ</h2>
<ul>
<li><a href="https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-07-13.md">C# Language Design Meeting for July 13th, 2020</a></li>
</ul>
<p>スケジュール的に、今年11月リリースを予定されている .NET 5/C# 9.0 にはこれ以上大き目の機能は追加されない状態になりました。
(いくつか小さめの機能が入る可能性や、現状入っている機能に対して修正が加わる可能性はまだまだあります。)
なので、C# Language Design Meeting ではそろそろ「10.0」(来年11月)を見据えた話になっています。</p>
<h3>Generics and generic type parameters in aliases</h3>
<ul>
<li><code>using MyList&lt;T&gt; = System.Collections.Generic.List&lt;T&gt;;</code> みたいに、using エイリアスに型引数を書きたいという話</li>
<li>その他、タプルとかにもエイリアスを書けるようにしたい</li>
<li>(ファイル単位じゃなく)グローバルに影響する using も検討の対象</li>
<li>C# 10.0 に向けて検討</li>
</ul>
<h3>&quot;closed&quot; enum types</h3>
<ul>
<li><code>enum</code> に対して、<code>switch</code> で網羅性チェックが効く(その代わり、後からのメンバー追加が破壊的変更(<code>switch</code> に警告・エラーが出る)ようにしたいという話</li>
<li>元々 C# 10.0 として検討されていた Discriminated Union (Record の延長戦上)と一緒に検討したい</li>
</ul>
<h3>Allow ref assignment for switch expressions</h3>
<ul>
<li><code>switch</code> 式で <code>ref</code> 戻り値を返したい</li>
<li><code>ref var r = ref x switch { 0 =&gt; ref a, _ =&gt; ref b };</code> みたいなの</li>
<li>ちなみに、条件演算子の場合は今でも <code>ref var r = ref (x ? ref a : ref b);</code> と書ける</li>
<li>「Any Time」(優先度低め。コミュニティ貢献があれば実現するかも、くらい)扱い</li>
</ul>
<h3>Null suppressions nested under propagation operators</h3>
<ul>
<li>null 抑止の後起き <code>!</code> の挙動がちょっと怪しいらしい</li>
<li>「<code>!</code> の有無によって実行時の挙動は変わらない」(あくまで警告抑止の効果しかない)ということになっているのに、挙動を変えちゃうことがあるみたい</li>
<li><code>a?.b.c!.d.e</code> が <code>(a?.b.c)!.d.e</code> として解釈されてて、このせいで、<code>?.</code> のショートサーキットの掛かり方が変わるとのこと</li>
<li>この挙動はまずそうなので、破壊的変更になってでも直したい</li>
<li>C# 9.0 のタイミングで検討</li>
</ul>
<h3>Relax rules for trailing whitespaces in format specifier</h3>
<ul>
<li><code>$&quot;{date:yyyy-MM-dd}</code> と <code>$&quot;{date:yyyy-MM-dd }</code> みたいに、文字列補間のフォーマット指定で、<code>{}</code> 内の空白の有無で挙動が変わるのは変じゃないか</li>
<li>Rejcted。変じゃない。意図的。元から、<code>date.ToString(&quot;yyyy-MM-dd&quot;)</code> と <code>date.ToString(&quot;yyyy-MM-dd &quot;)</code> で出力が変わるので</li>
</ul>
<h3>Private field consideration in structs during definite assignment analysis</h3>
<ul>
<li><code>struct Result { public object Value { get; } }</code> みたいに、自動実装プロパティから生成されてるはずの private フィールドが、構造体の「<a href="/study/csharp/resource/rm_struct/#definite-assignment">確実な初期化</a>」解析から漏れるバグがあるらしい</li>
<li>native compiler (C# 5.0 以前の、C++ 実装の C# コンパイラー)時代からのバグで、「バグまで含めて破壊的変更を起こさないように移植した結果」とのこと</li>
<li>でも、結構まずいバグなので変更することに前向き</li>
<li>「来週しっかり検討」という扱い(たぶん、C# 9.0 で修正しそう)</li>
</ul>
<h3>Remove restriction that optional parameters must be trailing</h3>
<ul>
<li><code>void M(int x, int y = 0, int z)</code> みたいに、末尾以外にオプション引数を認めたいという話</li>
<li>.NET のメタデータ的には許される構造で、C# が禁止してるだけ</li>
<li>まあ、制限を緩めてもいいかも</li>
<li>Any Time (あまり積極的ではない)</li>
</ul>
<h3>List patterns</h3>
<ul>
<li>パターン マッチングで、<code>x is [1, 2, 3]</code> みたいな書き方で配列/リストに対するマッチングをしたいという話</li>
<li>コミュニティ貢献ですでにプロトタイプがある</li>
<li>それを元に詳細を検討する必要がある</li>
<li>C# 10.0 に向けて検討</li>
</ul>
<h3>Property-scoped fields and the <code>field</code> keyword</h3>
<ul>
<li>プロパティの <code>get</code>/<code>set</code>/<code>init</code> 内でだけアクセスできるフィールドを定義したいという話</li>
<li>ものすごく昔からたびたび似た要求が上がっては「そのうちね」な空気感だったやつ</li>
<li>ついに C# 10.0 で検討</li>
</ul>
<h3>File-scoped namespaces</h3>
<ul>
<li><code>namespace X { ... }</code> みたいに <code>{}</code> でくくってインデントが1段下がる書き方じゃなく、<code>namespace X;</code> みたいな1行でインデントを下げずに名前空間定義したいという話</li>
<li>同上、これもついに C# 10.0 で検討</li>
</ul>
<h3>Allowing ref/out on lambda parameters without explicit type</h3>
<ul>
<li><code>(ref x, ref y) =&gt; {}</code> みたいなラムダ式を書きたいという話</li>
<li>実装できない大きな問題もなさそうだけど、優先度が付くほど需要もない</li>
<li>Any Time</li>
</ul>
<h3>Using declarations with a discard</h3>
<ul>
<li><code>using var _ = new X();</code> とか <code>using (new X()) { }</code> とかは書けるんだから、<code>using _ = new X();</code> とか <code>using new X();</code> を認めてほしいという話</li>
<li><code>X.X</code> (「いつかは取り組む」くらい。Any Time よりは多分前向き)</li>
</ul>
<h3>Allow null-conditional operator on the left hand side of an assignment</h3>
<ul>
<li><code>x?.Value = 1;</code> みたいなので、<code>if (x != null) x.Value = 1;</code> 扱いしてほしいという話</li>
<li><code>X.X</code></li>
</ul>
<h3>Top level statements and functions</h3>
<ul>
<li>Top level statements 自体は C# 9.0 に入る</li>
<li>まだ検討課題として残っているものとして、top level に書いたメソッドはプロジェクト全体から呼べるべきかどうかという話がある</li>
<li>9.0 ではあくまで「生成される Main メソッド内のローカル関数扱い」、「top level メソッドは top level statement からしか呼べない」という実装で行く</li>
<li>「プロジェクト全体から呼べるかどうか」は「top level statements part 2」としてC# 10.0 で再度ディスカッションを設ける</li>
</ul>
<h3>Implicit usings</h3>
<ul>
<li>プロジェクト全体にしたして影響する <code>using</code> ディレクティブが欲しい</li>
<li>C# スクリプト構文だとこれに類するものが認められてて、例えば Visual Studio の C# Interactive では <code>using System;</code> はなくても <code>System</code> 名前空間の型を使える</li>
<li>top level statements 文法とスクリプト文法の差異を少しでも減らすためには、通常 C# でもこの手の暗黙的な <code>using</code> があった方がいいのではないか</li>
<li>現状、csc のオプションとして <code>csc -using:System</code> みたいな与え方を検討</li>
<li>C# 10.0 のタイミングでディスカッション</li>
</ul>
 ]]></description>
				<pubDate>Sun, 19 Jul 2020 17:41:32 +0900</pubDate>
			</item>
			<item>
				<title>C# 9.0 in Visual Studio 16.7 preview 3</title>
				<link>http://ufcpp.net/blog/2020/6/cs9vs16_7p3/</link>
				<description><![CDATA[ <p>先週の話にはなってしまうんですが、Visual Studio 16.7 が Preview 3.1 になっています。
.NET 5 も Preview 6 に。</p>
<ul>
<li><a href="https://devblogs.microsoft.com/dotnet/announcing-net-5-0-preview-6/">Announcing .NET 5.0 Preview 6</a></li>
<li><a href="https://docs.microsoft.com/ja-jp/visualstudio/releases/2019/release-notes-preview#16.7.0-pre.3.1">リリース ノート: Visual Studio 2019 バージョン 16.7 Preview 3</a></li>
</ul>
<p>で、今回も C# 9.0 の新機能がいくつか入っています。</p>
<ul>
<li>Records</li>
<li>Top-level statements</li>
<li>Function pointers</li>
</ul>
<div>
<iframe width="560" height="315" src="https://www.youtube.com/embed/cxdZyFBxZws" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div>
<p>昨日、このネタでライブ配信してたりするんですが、
今回、ついに配信時間が3時間の大台に…</p>
<p>配信時間が長くなっているのはチャット欄での応答が盛り上がりすぎたというのが原因です。
(「新機能が多くて長引いた」みたいなのではなく。)
特に Function pointers の話とか、そもそも付いてくる人がいると思っていなかったので、
Function pointers だけで相当な時間しゃべることになったのがだいぶ意外…</p>
<p>インタラクションが欲しくて始めたライブ配信だし、
タイム キーピングを気にしなくていいのも楽なので、
うれしい悲鳴なんですけども、</p>
<h2>!is 問題</h2>
<p>最初に取り上げるのは C# 9.0 でもなんでもないんですけども。</p>
<p><a href="https://docs.microsoft.com/ja-jp/visualstudio/releases/2019/release-notes-preview#16.7.0-pre.3.1">VS 16.7 p3 のリリース ノート</a>を見ていて、null 抑制演算子の <code>!</code> に対するリファクタリングが入っていてなんとも言えない気持ちになったという話。</p>
<p>以下のコード、解釈の仕方を間違う人があまりにも多いらしく。</p>
<pre class="source" title="!is">
<code><span class="reserved">if</span> (x !<span class="reserved">is</span> 0) { }
</code></pre>
<p><code>!x</code> が「x の否定」、not x の意味なせいで、それで勘違いしちゃう人がいたりします。
上記のコードは正しくは <code>(x!) is 0</code> の意味で、この <code>!</code> は後置きの <code>x!</code>。
否定の意味の <code>!</code> ではなくて、<a href="https://ufcpp.net/study/csharp/cheatsheet/ap_ver8/#nullable-reference-type">C# 8.0 の null 許容参照型</a> がらみの機能で、効果としては<a href="https://ufcpp.net/study/csharp/resource/nullablereferencetype/?p=3#null-forgiving">単なる null 警告の抑止</a>です。</p>
<p>挙句の果てに、<code>is 0</code> と書いた時点で「null ではないことが確定」なので、null 警告の抑止をする意味すらないという。</p>
<p>つまるところ、<code>!is</code> を not is と勘違いして使ってしまうと、真逆の挙動になるというひどいバグを生む原因です。
なのでしょうがないので…</p>
<p>リファクタリング1: 意味がないので <code>!</code> を消す</p>
<pre class="source" title="!is → is">
<code><span class="reserved">if</span> (x <span class="reserved">is</span> 0) { }
</code></pre>
<p>リファクタリング2: “ちゃんと”真逆に直す</p>
<pre class="source" title="!is → is">
<code><span class="reserved">if</span> (x <span class="reserved">is not</span> 0) { }
</code></pre>
<h2>is not T x</h2>
<p><a href="https://ufcpp.net/blog/2020/5/cs9net5p4/"><code>not</code> パターン自体は先月の時点で入っていたんですが</a>、
微妙に今回の 16.7 Preview 3 リリースで入った修正もあります。
以下のようなコードが有効になりました。</p>
<pre class="source" title="is not T x">
<code><span class="reserved">static</span> <span class="reserved">void</span> <span class="method">M</span>(<span class="reserved">object</span> x)
{
    <span class="comment">// not パターンでも変数宣言できる</span>
    <span class="reserved">if</span> (x <span class="reserved">is</span> <span class="reserved">not</span> <span class="reserved">string</span> s)
    {
        <span class="comment">// ちなみに、ここで s の中身を読もうとすると「未初期化」エラー</span>
 
        s = <span class="string">&quot;&quot;</span>;
 
        <span class="comment">// s を読めるのはこの行以降</span>
    }
 
    <span class="comment">// ここは絶対 s が初期化されている保証あり</span>
    <span class="type">Console</span>.<span class="method">WriteLine</span>(s);
}
</code></pre>
<h2>Top-level statements</h2>
<p><code>Program.Main</code> が要らなくなります。
C# スクリプト モードじゃなくても以下のように、Top-level  (クラスとか名前空間の外)にコードが書けます。</p>
<pre class="source" title="Top-level にステートメントを書けるように">
<code><span class="reserved">using</span> System;
 
<span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="string">&quot;Hellow World!&quot;</span>);
</code></pre>
<p>ちなみに、「C# スクリプト モード」とはまたちょっと挙動が違ったりします。</p>
<p>Top-level の場合</p>
<ul>
<li>
あくまで <code>Main</code> メソッドの自動生成
<ul>
<li>変数やメソッドを書くと、ローカル変数、ローカル関数の意味になる</li>
<li><code>args</code> (暗黙的変数)でコマンドライン引数を受け取れるし、<code>return</code> で終了コードを返せる</li>
</ul>
</li>
<li><a href="https://ufcpp.net/study/csharp/cheatsheet/apscripting/#script-syntax"><code>#r</code> や  <code>#load</code> などのスクリプト専用機能</a>は使えない</li>
</ul>
<p>スクリプトの場合</p>
<ul>
<li>
ラッパー クラスが作られる
<ul>
<li>変数はフィールドに、メソッドはインスタンス メソッドになる</li>
</ul>
</li>
<li>逆に、<code>return</code> とか <code>namespace</code> とか「通常モード」専用の構文は使えない</li>
</ul>
<p>ちなみに、Top-level に普通に <code>await</code> も書けます。
<code>await</code> があれば <code>async Task Main</code>、なければ <code>void Main</code> みたいな扱いです。</p>
<p>Top-level ステートメントを書いた上で、さらにどこかのクラスに <code>Main</code> メソッドを書いてしまった場合、
Top-level ステートメントの方が優先されます(書いてしまった <code>Main</code> は呼ばれない)。
警告だけは出ます。</p>
<p>また、複数のファイルに Top-level ステートメントを書いたり、
名前空間やクラスよりも後ろに書いた場合はコンパイル エラーになります。
あくまで、1ファイルの先頭にだけ Top-level ステートメントを書けます。</p>
<h2>Function pointer</h2>
<p>関数ポインターを C# 上で書けるようになりました。</p>
<p>まあ、正直、大多数の人にとって直接触れる機能ではないです。
実質的には P/Invoke 専用機能になると思います(どうひねり出そうと思っても他の用途が思いつかない)。</p>
<p>以下のように、<code>delegate*</code> で「関数ポインター型」を作って、
<code>&amp;</code> でメソッドのアドレスを取得できる機能です。</p>
<pre class="source" title="関数ポインター">
<code><span class="reserved">using</span> System;
 
<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">unsafe</span> <span class="reserved">static</span> <span class="reserved">void</span> <span class="method">Main</span>()
    {
        <span class="reserved">delegate</span>*&lt;<span class="reserved">int</span>, <span class="reserved">void</span>&gt; f = &amp;<span class="method">M</span>;
        f(1);
    }
 
    <span class="reserved">static</span> <span class="reserved">void</span> <span class="method">M</span>(<span class="reserved">int</span> x) =&gt; <span class="type">Console</span>.<span class="method">WriteLine</span>(x);
}
</code></pre>
<p>.NET の仕様上は上記コードに相当する命令(ldftn, calli)が元々あったりします。
ただ、C# からこれらの命令を使う手段が全くなくて、
これまでは IL アセンブラーや <a href="https://docs.microsoft.com/ja-jp/dotnet/api/system.reflection.emit"><code>Reflection.Emit</code></a> を使う必要がありました。</p>
<p>今、iOS や WebAssembly 対応のために、
<code>Reflection.Emit</code> による実行時コード生成を、
<a href="https://ufcpp.net/blog/2020/5/sourcegenerator/">Source Generator</a> によるコンパイル時コード生成に置き換えたいという話もあったりします。
P/Invoke の類も、 .NET Runtime の中で特殊対応するよりも、事前にソースコード生成したいみたいな話もあって、
そのために必要になる機能です。</p>
<p>「ないと困るから入れた」という類であって、
「便利に使いたい、簡単に使いたい」という動機はないので、
構文的に結構複雑だったりします。</p>
<p>ただ、関数ポインターで <code>&lt;void&gt;</code> を認めてくれるんなら、普通のデリゲートでも同じように書きたい…
(書けないし、今後もたぶんずっと無理)</p>
<pre class="source" title="要望としてはある(たぶん今後も無理)">
<code><span class="reserved">using</span> System;
 
<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> <span class="method">Main</span>()
    {
        <span class="type">Func</span>&lt;<span class="reserved">int</span>, <span class="error"><span class="reserved">void</span></span>&gt; f = <span class="method">M</span>; <span class="comment">// こう書きたい(無理)</span>
        <span class="type">Action</span>&lt;<span class="reserved">int</span>&gt; a = <span class="method">M</span>; <span class="comment">// 戻り値が void かどうかで型が違う</span>
    }
 
    <span class="reserved">static</span> <span class="reserved">void</span> <span class="method">M</span>(<span class="reserved">int</span> x) =&gt; <span class="type">Console</span>.<span class="method">WriteLine</span>(x);
}
</code></pre>
<h2>Records</h2>
<p>待望(？)の Records。
概ね、<a href="https://ufcpp.net/blog/2020/6/record0609/">6月9日にブログに書いた</a>状態で実装されていそうな感じ。</p>
<p>一番シンプルな書き方をすると以下のようになります。
プライマリ コンストラクター構文。
引数の順序(position, 位置)に意味があるので positional record と言ったりもします。</p>
<pre class="source" title="プライマリ コンストラクターを使った “positional” record">
<code><span class="reserved">using</span> System;
 
<span class="comment">// 一番シンプルな書き方はこうなる</span>
<span class="reserved">record</span> Point(<span class="reserved">int</span> X, <span class="reserved">int</span> Y);
 
<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> <span class="method">Main</span>()
    {
        <span class="reserved">var</span> p = <span class="reserved">new</span> <span class="type">Point</span>(1, 2);
        <span class="type">Console</span>.<span class="method">WriteLine</span>(p.X);
    }
}
</code></pre>
<p><code>class</code> や <code>struct</code> と並んで、<code>record</code> という型定義用のキーワードが増えます。</p>
<p>ちなみに上記コードは以下のコードとほぼ同じ意味になります。</p>
<pre class="source" title="プライマリ コンストラクターの展開結果">
<code><span class="comment">// プライマリ コンストラクターの展開結果</span>
<span class="reserved">record</span> Point
{
    <span class="reserved">public</span> <span class="reserved">int</span> X { <span class="reserved">get</span>; <span class="reserved">init</span>; }
    <span class="reserved">public</span> <span class="reserved">int</span> Y { <span class="reserved">get</span>; <span class="reserved">init</span>; }
 
    <span class="reserved">public</span> <span class="type">Point</span>(<span class="reserved">int</span> X, <span class="reserved">int</span> Y)
    {
        <span class="reserved">this</span>.X = X;
        <span class="reserved">this</span>.Y = Y;
    }
}
</code></pre>
<p>残念ながら、今のところ(というか、おそらく C# 9.0 リリース時点では)、
プライマリ コンストラクターを書けるのは <code>record</code> だけになりそうです。</p>
<p>一方、<code>init</code> は <code>class</code> や <code>struct</code> でも使えます。
例えば、以下のようなコードは有効な C# 9.0 コードになります。</p>
<pre class="source" title="init アクセサー">
<code><span class="comment">// init に関しては çlass でも struct でも使える</span>
<span class="reserved">class</span> <span class="type">Point</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> X { <span class="reserved">get</span>; <span class="reserved">init</span>; }
    <span class="reserved">public</span> <span class="reserved">int</span> Y { <span class="reserved">get</span>; <span class="reserved">init</span>; }
 
    <span class="reserved">public</span> <span class="type">Point</span>(<span class="reserved">int</span> X, <span class="reserved">int</span> Y)
    {
        <span class="reserved">this</span>.X = X;
        <span class="reserved">this</span>.Y = Y;
    }
}
</code></pre>
<p>ということで、Records の説明をする上での本質は以下の2点からなります。</p>
<ul>
<li>じゃあ、 <code>class</code> と <code>record</code> は何が違うか</li>
<li>プロパティの <code>init</code> は何か</li>
</ul>
<h3>補足: IsExternalInit 属性</h3>
<p><code>init</code> プロパティを表現するために <code>IsExternalInit</code> という名前の属性を使っているんですが、
これは、</p>
<ul>
<li>現時点では .NET 5 にも入っていない</li>
<li>リリース時点では .NET 5 には入る予定</li>
<li>古い .NET ランタイムに対するポーティングとかは提供せず「C# 9.0 をフルにサポートするのは .NET 5 のみ」という扱いにしたい</li>
</ul>
<p>ということになっています。
ただ、以下のコードを自前で用意すれば、現時点の .NET 5 Preview や古い .NET ランタイムでも <code>record</code> や <code>init</code> を使えます。</p>
<pre class="source" title="IsExternalInit 属性">
<code><span class="reserved">namespace</span> System.Runtime.CompilerServices
{
    <span class="reserved">internal</span> <span class="reserved">class</span> <span class="type">IsExternalInit</span> { }
}
</code></pre>
<p>ちなみにこの型、中身空っぽでマーカー的に用意された型ですが、
実際の使われ方は <a href="https://github.com/ufcpp-live/UfcppLiveAgenda/issues/4">modreq</a> になります。</p>
<p>後述する <code>init</code> が、古い C# コンパイラーから触られるとまずい機能なので、触れなくするために modreq を使っています。</p>
<h3>record と class</h3>
<p>現状だと、プライマリ コンストラクターを書けるのは <code>record</code> だけなんですが、
<code>class</code> や <code>struct</code> に対しても後々追加される可能性は結構高いです。</p>
<p>で、前述の通り、<code>init</code> プロパティを使うのであれば、<code>class</code>、<code>struct</code>、<code>record</code> でほぼ同じ書き方ができます。
じゃあ、<code>class</code>、<code>struct</code> と <code>record</code> の何が違うかと言うと…</p>
<ul>
<li><code>struct</code> みたいな、全フィールドの memberwise 比較を元にした <code>Equals</code>、<code>GetHashCode</code>、<code>Clone</code> がコンパイラー生成される</li>
<li><code>record</code> は参照型</li>
</ul>
<p>みたいな感じです。
要するに、<code>struct</code> 的な「値セマンティクス」を持つ参照型が <code>record</code>。</p>
<p>これだけ書いてしまうと大したことをしていないように聞こえますけども、
immutable なデータ構造を簡単に書けるようにするという意義があります。</p>
<p>参照型の「値比較」(memberwise に <code>Equals</code>、<code>GetHashCode</code> 実装)は <a href="https://gist.github.com/ufcpp/6336a4c1033e431c6732e82e03029bc7">immutable に作らないとまずい</a>です。
一方で、immutable なクラスを真面目に書くのはすさまじく大変で、その負担を減らしてくれるのが <code>record</code> です。</p>
<p>あと、派生が絡んだ時の <code>Equals</code> 実装も意外とめんどくさくて、そこも <code>record</code> からのコード生成が頑張ってくれています。</p>
<h3>with 式</h3>
<p>immutable なクラスの部分書き換えをする場合、基本的には Clone してから所望のメンバーだけを上書きと言う処理が必要になります。</p>
<p>それをやってくれるのが <code>with</code> 式で、<code>record</code> に対して以下のような書き方ができます。</p>
<pre class="source" title="with 式">
<code><span class="reserved">using</span> System;
 
<span class="reserved">record</span> Point(<span class="reserved">int</span> X, <span class="reserved">int</span> Y);
 
<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> <span class="method">Main</span>()
    {
        <span class="reserved">var</span> p = <span class="reserved">new</span> <span class="type">Point</span>(1, 2);
 
        <span class="comment">// p を部分書き換え(この場合 X だけ書き換え)</span>
        <span class="reserved">var</span> p1 = p <span class="reserved">with</span> { X = 3 };
 
        <span class="type">Console</span>.<span class="method">WriteLine</span>((p.X, p.Y));   <span class="comment">// (1, 2)。元の p は不変</span>
        <span class="type">Console</span>.<span class="method">WriteLine</span>((p1.X, p1.Y)); <span class="comment">// (3, 2)。p を Clone した上で X だけ書き換えてる</span>
    }
}
</code></pre>
<p>これと同じことを <code>class</code> の手書きでやろうとすると、以下のように、Clone 後の書き換えで immutable であることが破たんします。</p>
<pre class="source" title="with 式を使わず手書きしようとすると…">
<code><span class="reserved">using</span> System;
 
<span class="reserved">class</span> <span class="type">Point</span>
{
    <span class="comment">// 本当は set できるとまずいけど、Clone 後の書き換えのために必須になってしまう。</span>
    <span class="comment">// これを回避するために init アクセサー(後述)がある。</span>
    <span class="reserved">public</span> <span class="reserved">int</span> X { <span class="reserved">get</span>; <span class="reserved">set</span>; }
    <span class="reserved">public</span> <span class="reserved">int</span> Y { <span class="reserved">get</span>; <span class="reserved">set</span>; }
    <span class="reserved">public</span> <span class="type">Point</span>(<span class="reserved">int</span> x, <span class="reserved">int</span> y) =&gt; (X, Y) = (x, y);
    <span class="reserved">public</span> <span class="type">Point</span> <span class="method">Clone</span>() =&gt; <span class="reserved">new</span> <span class="type">Point</span>(X, Y);
}
 
<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> <span class="method">Main</span>()
    {
        <span class="reserved">var</span> p = <span class="reserved">new</span> <span class="type">Point</span>(1, 2);
 
        <span class="comment">// p を部分書き換え(この場合 X だけ書き換え)</span>
        <span class="reserved">var</span> p1 = p.<span class="method">Clone</span>();
 
        <span class="comment">// Clone 後の書き換えのためにやむを得ず public set。</span>
        <span class="comment">// init とか with とか、新構文が必要になる理由。</span>
        p1.X = 3;
 
        <span class="type">Console</span>.<span class="method">WriteLine</span>((p.X, p.Y));   <span class="comment">// (1, 2)。元の p は不変</span>
        <span class="type">Console</span>.<span class="method">WriteLine</span>((p1.X, p1.Y)); <span class="comment">// (3, 2)。p を Clone した上で X だけ書き換えてる</span>
    }
}
</code></pre>
<p>(もっと複雑で、実行時コストも高い方法でよければもうちょっとやり様はあるんですが。
後述する <code>init</code> プロパティで一応、実行時コストは掛けずにこの問題を解決できるので、それを採用することになりました。)</p>
<p>ちなみに、原理的には <code>with</code> 式は <code>init</code> プロパティを持つ <code>class</code> や <code>struct</code> に対しても使えるはずなんですが、
C# 9.0 時点では <code>record</code> 専用構文になりそうです。
(スケジュールの問題。あとで <code>class</code> や <code>struct</code> に対する <code>wth</code> 式追加が検討される。)</p>
<h3>init アクセサー</h3>
<p>プロパティのアクセサーに、<code>set</code> の代わりに <code>init</code> を使うことで、
初期化子や <code>with</code> 式でだけ書き換え可能なプロパティができます。</p>
<pre class="source" title="init アクセサー">
<code><span class="reserved">class</span> <span class="type">InitOnly</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> X { <span class="reserved">get</span>; <span class="reserved">init</span>; }
}
 
<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> <span class="method">Main</span>()
    {
        <span class="reserved">var</span> p = <span class="reserved">new</span> <span class="type">InitOnly</span>
        {
            X = 1, <span class="comment">// 初期化子を使える</span>
        };
 
        <span class="error">p.X</span> = 2; <span class="comment">// これはコンパイル エラー</span>
 
        <span class="comment">// with 式での書き換え(Clone 後の書き換え)もできる</span>
        <span class="reserved">var</span> p1 = p <span class="reserved">with</span> { X = 3 };
    }
}
</code></pre>
<p><code>init</code> アクセサーは以下の場所からだけ呼び出せる制限付きの <code>set</code> みたいなものです。</p>
<ol>
<li>そのクラスのコンストラクター内</li>
<li>オブジェクト初期化子</li>
<li><code>with</code> 式</li>
<li>他の <code>init</code> アクセサー内</li>
</ol>
<p>1だけでよければ <a href="https://ufcpp.net/study/csharp/oo_property.html#get-only">get-only プロパティ</a>でも実現できるんですが、残りの3つのために <code>init</code> アクセサーが新設されました。</p>
<p>ちなみに、<code>set</code> と <code>init</code> を同時に書くことはできません。
というか、<code>init</code> アクセサーは内部的には「特殊な属性を付けた <code>set</code> アクセサー」として実現されています。</p>
 ]]></description>
				<pubDate>Mon, 29 Jun 2020 22:14:14 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 6/9: record</title>
				<link>http://ufcpp.net/blog/2020/6/record0609/</link>
				<description><![CDATA[ <p>先月くらいからじわじわと、C# Language Design Meeting で Records がらみの議題が上がっています。
最近やっとまとまってきた感じがするのでまとめて紹介。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/3443">LDM notes for May 4</a></li>
<li><a href="https://github.com/dotnet/csharplang/issues/3470">LDM notes for May 11</a></li>
<li><a href="https://github.com/dotnet/csharplang/issues/3526">LDM Notes for May 27</a></li>
<li><a href="https://github.com/dotnet/csharplang/issues/3529">LDM notes for June 1</a></li>
</ul>
<h2>record 型の新設</h2>
<p>まず、基本方針として、record は class/struct に対する修飾子ではなくて、enum とか delegate とかと同じく1種の型みたいな扱いにしたみたいです。
なので、以下のような書き方に。</p>
<pre class="source" title="record 型">
<code><span class="reserved">record</span> <span class="type">Point</span>(<span class="reserved">int</span> X, <span class="reserved">int</span> Y);
</code></pre>
<p>とりあえず初期実装としては結構やることを絞るみたいで、</p>
<ul>
<li>
record は参照型
<ul>
<li>値型なものは既存の struct に手を入れるか、&quot;record struct&quot; を新設するかになると思うもののまだ未定</li>
</ul>
</li>
<li>
プライマリ コンストラクターを持てるのは record だけ
<ul>
<li><code>class Point(int X, int Y)</code> とか <code>struct Point(int X, int Y)</code> とかは未実装</li>
<li>
検討はされてるものの、record と同じコード生成をすべきかどうかでまだ迷ってそう
<ul>
<li>record の場合はプライマリ コンストラクター引数から <code>public int X { get; init; }</code> プロパティを作ることが決まってる</li>
<li>通常の class, struct の場合はプロパティまでは作らない、キャプチャが掛からない限りフィールドにすらしないという案あり</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>みたいな実装のようです。</p>
<p>この辺りは issue のコメントでの反発も結構大きいんですが…
修飾子じゃなくて型のカテゴリーの新設な点とか、当初実装に値型版がない点とか…</p>
<h2>構造体との一貫性</h2>
<p>今はいったん未定な状態になってるんですが、
仮に、普通の class/struct にもプライマリ コンストラクターを持てて、
record のものと近いコード生成をすることになったとします
(1案としてはそういう実装も考えられます)。</p>
<p>じゃあ、class と record の本質的な差は何になるかと言うと、</p>
<ul>
<li>メンバーごとの(shallow な)比較による <code>Equasl</code>/<code>GetHashCode</code> が生成される</li>
<li>メンバーごとの(shallow な)コピーによる clone メソッドが生成される</li>
</ul>
<p>という点になります。
で、この2つ、struct の場合は標準で作られます。</p>
<pre class="source" title="struct には自動的に Equals が作られてる">
<code><span class="reserved">using</span> System;
 
<span class="reserved">struct</span> <span class="type">Point</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> X;
    <span class="reserved">public</span> <span class="reserved">int</span> Y;
}
 
<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> <span class="method">Main</span>()
    {
        <span class="reserved">var</span> p1 = <span class="reserved">new</span> <span class="type">Point</span> { X = 1, Y = 2 };
        <span class="reserved">var</span> p2 = <span class="reserved">new</span> <span class="type">Point</span> { X = 1, Y = 2 };
        <span class="type">Console</span>.<span class="method">WriteLine</span>(p1.<span class="method">Equals</span>(p2)); <span class="comment">// true</span>
 
        p2.X = 3;
        <span class="type">Console</span>.<span class="method">WriteLine</span>(p1.<span class="method">Equals</span>(p2)); <span class="comment">// false</span>
    }
}
</code></pre>
<p>ということで、コンセプト上は、「record は struct のような振る舞いを持つ参照型」みたいに考えることもできます。
なので、今の struct の挙動とあまりに違うものにはしたくないし、
今の struct が非効率な実装になっちゃってる部分は record に合わせて struct の方にも改善を入れてもいいかもとか、
そういう感じの話は出ています。</p>
<h2>data 修飾子</h2>
<p>プライマリ コンストラクター前提の構文は「positional record」と呼ばれています。
引数の並びに意味があって、<code>new Point(1, 2)</code> みたいに、positional(位置指定) で初期化ができるためこう呼びます。</p>
<p>一方で、プロパティを元にして、<code>new Point { X = 1, Y = 2 }</code> みたいに書く想定のものを「nominal record」と呼びます。
nominal record のために、data 修飾子も用意する流れのようです。
以下のような書き方ができます。一見、data 修飾子を付けたフィールドっぽい書き方ですが、<code>get; init;</code> な public プロパティが生成されます。</p>
<pre class="source" title="data 修飾子による「nominal record」">
<code><span class="reserved">record</span> <span class="type">Point</span>
{
    <span class="reserved">data</span> <span class="reserved">int</span> X;
    <span class="reserved">data</span> <span class="reserved">int</span> Y;
}
</code></pre>
<h2>base 呼び出しとか、プライマリ コンストラクター引数のスコープとか</h2>
<p>あとは細かい話。
record 型は派生もできるんですが、その場合、以下のような書き方ができます。</p>
<pre class="source" title="record の派生">
<code><span class="reserved">record</span> <span class="type">Person</span>(<span class="reserved">string</span> FirstName, <span class="reserved">string</span> LastName)
{
    <span class="reserved">public</span> <span class="reserved">string</span> Fullname =&gt; <span class="string">$&quot;</span>{FirstName}<span class="string"> </span>{LastName}<span class="string">&quot;</span>;
    <span class="reserved">public</span> <span class="reserved">override</span> <span class="reserved">string</span> <span class="method">ToString</span>() =&gt; <span class="string">$&quot;</span>{FirstName}<span class="string"> </span>{LastName}<span class="string">&quot;</span>;
}
 
<span class="reserved">record</span> <span class="type">Student</span>(<span class="reserved">string</span> FirstName, <span class="reserved">string</span> LastName, <span class="reserved">int</span> Id)
    : <span class="type">Person</span>(FirstName, LastName)
{
    <span class="reserved">public</span> <span class="reserved">override</span> <span class="reserved">string</span> <span class="method">ToString</span>() =&gt; <span class="string">$&quot;</span>{FirstName}<span class="string"> </span>{LastName}<span class="string"> (</span>{ID}<span class="string">)&quot;</span>;
}
</code></pre>
<p>このとき、以下のような点が検討に上がっています。</p>
<ul>
<li>
コンストラクター引数に対して、それと同名のプロパティと、引数からプロパティへの代入コードが自動生成される
<ul>
<li>代入のタイミングは base コンストラクターより前であるべきか後であるべきか</li>
<li>今のところ「前」案優勢</li>
</ul>
</li>
<li>
基底クラスのコンストラクターを呼んでいる部分(この例だと <code>Person(FirstName, LastName)</code> の引数の部分のスコープはどうなるべきか
<ul>
<li>クラス内の全メンバーがスコープ</li>
<li>ただ、通常コンストラクターの<a href="/study/csharp/oo_inherit.html#base-access">base アクセス</a>と同様に、インスタンス メンバーに触わろうとするとエラー</li>
</ul>
</li>
<li>
自動生成されるのと同名のメンバーを手書きすると、手書きの方を優先して使う
<ul>
<li>Equals とか</li>
<li>その手書き Equals とかが sealed だったりするとエラーにする</li>
</ul>
</li>
<li><code>object.Equals(object)</code> じゃなくて <code>Equals(T)</code> は作るべきか？ → そうする予定だし、<code>IEquatable&lt;T&gt;</code> の実装も需要が高いことは認識してて検討の範囲内</li>
</ul>
 ]]></description>
				<pubDate>Tue, 09 Jun 2020 21:21:48 +0900</pubDate>
			</item>
			<item>
				<title>partial メソッドの拡張 (C# 9.0 候補機能)</title>
				<link>http://ufcpp.net/blog/2020/6/extendingpartialmethod/</link>
				<description><![CDATA[ <p>もう1週間近く経過しちゃってるんですけども、Visual Studio 16.7 Preview 2 が出ています。</p>
<ul>
<li><a href="https://devblogs.microsoft.com/visualstudio/visual-studio-2019-v16-7-preview-2/">Visual Studio 2019 v16.7 Preview 2 Available Today!</a></li>
</ul>
<p>で、今日はこの Preview 2 で追加された C# 9.0 候補の話です。
<a href="/blog/2020/5/sourcegenerator/">先月追加された Srouce Generator</a>関連の機能で、
<a href="/study/csharp/oo_class.html#partial_method">partial メソッド</a>の亜種が追加されました。</p>
<p><a href="/blog/2020/5/pickuproslyn0503/">先月、Design Notesの時点で軽く触れていた機能</a>が、この度実際に触れる状態になっています。</p>
<h2>(既存の) partial メソッド</h2>
<p>意外と知られていない機能みたいなので改めて、既存の <a href="/study/csharp/oo_class.html#partial_method">partial メソッド</a>自体についても説明。</p>
<p>一番の用途としては、自動生成されているコードに、一部分だけ手動で処理をカスタマイズしたいみたいなときに使います。
例えば、以下のようなソースコードを T4 テンプレートなどを使って生成していると考えてください。</p>
<pre class="source" title="自動生成されている想定のコード">
<code><span class="comment">// T4 テンプレートとか XAML とかから自動生成されている想定のコード</span>
<span class="reserved">partial</span> <span class="reserved">class</span> <span class="type">Sample</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> X
    {
        <span class="reserved">get</span> =&gt; _x;
        <span class="reserved">set</span>
        {
            <span class="method">OnXChanging</span>();
            _x = <span class="reserved">value</span>;
            <span class="method">OnXChanged</span>();
        }
    }
    <span class="reserved">private</span> <span class="reserved">int</span> _x;
 
    <span class="comment">// 既定動作としては何もしたくない。</span>
    <span class="comment">// 人手で、何かしら _x = value; の前後に処理を挟みたいときにはこれに実装を持たせる。</span>
    <span class="reserved">partial</span> <span class="reserved">void</span> <span class="method">OnXChanging</span>();
    <span class="reserved">partial</span> <span class="reserved">void</span> <span class="method">OnXChanged</span>();
}
</code></pre>
<p>一部分だけカスタマイズしたいからといって、このコードに手作業で修正を加えてしまうと、
再度自動生成がかかったタイミングで上書きされて消えてしまいます。
そこで、カスタマイズする可能性のある部分に partial メソッド(<code>partial</code> 修飾子を付けて、中身を持たない空っぽのメソッド)を挟んでおきます。</p>
<p>もしも、手作業カスタマイズが必要なら、以下のように、別ファイルで partial メソッドに実装を与えます。</p>
<pre class="source" title="手書きする想定のコード">
<code><span class="comment">// 手書きする想定のコード</span>
<span class="reserved">partial</span> <span class="reserved">class</span> <span class="type">Sample</span>
{
    <span class="reserved">partial</span> <span class="reserved">void</span> <span class="method">OnXChanged</span>()
    {
        System.<span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="string">&quot;X: &quot;</span> + X);
    }
}
</code></pre>
<p>今回上げた例では、<code>OnXChanging</code> と <code>OnXChanged</code> という2つの partial メソッドがありますが、
そのうち <code>OnXChanged</code> の方にだけ実装を与えています。
<code>virtual</code> とか <code>abstract</code> とかとは違って、以下のような挙動をします。</p>
<ul>
<li>必要ないなら実装を与えなくていい</li>
<li>
実装を与えていない場合、コンパイル結果から完全に消滅する
<ul>
<li>メタデータ(リフレクションで取れるメソッド情報)すら残さないのでノーコスト</li>
</ul>
</li>
<li>
実装を与えた場合でも、通常のメソッド扱い
<ul>
<li><code>virtual</code> を付けた場合と違って、インライン展開が効いたりして負担が少ない</li>
</ul>
</li>
</ul>
<p>C# 2.0 の頃からある機能なんですけども、
言われてみると利用場面が少ないというか。
T4 なりなんなり、コード生成を多用している人にしか目につかないのかなと思います。
Entity Framework の Scaffolding とかで使われているはず…</p>
<p>ただ、まあ、<a href="https://github.com/dotnet/runtime">dotnet/runtime</a>とかで用例を探してみたものの、テストを除けば数十件くらいしか出てこないんですよね。確かにレア機能。
しかも、自動生成のコードと手書きコードの橋渡しと言うよりも、プラットフォーム依存な処理の分離に使われてることの方が多そう。</p>
<pre class="source" title="プラットフォーム依存処理の分離">
<code><span class="reserved">partial</span> <span class="reserved">class</span> <span class="type">Sample</span>
{
    <span class="reserved">public</span> <span class="reserved">void</span> <span class="method">M</span>()
    {
        <span class="method">OnMBegin</span>();
 
        <span class="comment">// 全プラットフォーム共通処理</span>
    }
 
    <span class="reserved">partial</span> <span class="reserved">void</span> <span class="method">OnMBegin</span>();
}
 
<span class="comment">// Sample.Windows.cs みたいなファイル</span>
<span class="reserved">partial</span> <span class="reserved">class</span> <span class="type">Sample</span>
{
    <span class="reserved">partial</span> <span class="reserved">void</span> <span class="method">OnMBegin</span>()
    {
        <span class="comment">// Windows 限定処理</span>
    }
}
</code></pre>
<h2>新 partial メソッド</h2>
<p>で、C# 9.0 で追加されるのは逆向きの用途で使うものです。
手書きの方が先にあって、その実装は Source Generator に埋めてもらうという想定。</p>
<p>例えば以下のような書き方をします。</p>
<pre class="source" title="手書きする想定のコード">
<code><span class="comment">// 手書きコード側</span>
<span class="reserved">using</span> System;
 
<span class="reserved">partial</span> <span class="reserved">class</span> <span class="type">Sample</span>
{
    [<span class="type">Utf8</span>(<span class="string">&quot;abcd&quot;</span>)]
    <span class="reserved">public</span> <span class="reserved">partial</span> <span class="type">ReadOnlySpan</span>&lt;<span class="reserved">byte</span>&gt; <span class="method">M</span>();
}
</code></pre>
<p>2.0 の頃からある partial との違いは以下の通りです。</p>
<ul>
<li>
<a href="/study/csharp/oo_conceal.html#level">アクセシビリティ</a>の指定をする
<ul>
<li>アクセシビリティの有無でどちらの partial メソッドなのかの分岐をしてる</li>
</ul>
</li>
<li>
戻り値が <code>void</code> でなくてもいい
<ul>
<li>アクセシビリティなしの partial メソッドは <code>void</code> しか受け付けない</li>
</ul>
</li>
<li>
<a href="/study/csharp/sp_ref.html#sec-byref"><code>ref</code> 引数</a>や <a href="/study/csharp/sp_ref.html#out"><code>out</code> 引数</a>を持てる
<ul>
<li>同上</li>
</ul>
</li>
<li>
必ず1個、実装を与えないといけない
<ul>
<li>手書きの C# コードを起点にして、Source Generator で実装を生成する想定</li>
</ul>
</li>
</ul>
<p>例えば上記の例は、Source Generator を使って以下のようなコードを生成する想定で書いています。</p>
<pre class="source" title="Source Generator で生成する想定のコード">
<code><span class="comment">// Source Generator で生成する想定のコード</span>
<span class="reserved">partial</span> <span class="reserved">class</span> <span class="type">Sample</span>
{
    <span class="reserved">public</span> <span class="reserved">partial</span> <span class="type">ReadOnlySpan</span>&lt;<span class="reserved">byte</span>&gt; <span class="method">M</span>()
        =&gt; <span class="reserved">new</span> <span class="reserved">byte</span>[] { 0x41, 0x42, 0x43, 0x44, };
}
</code></pre>
<p>アクセシビリティの有無で挙動が違うっていうのはそこそこ気持ち悪くはあるんですが。
元々の partial メソッド自体がほとんど使われていませんし、
このためだけに新しいキーワードを追加するほどではないのかなと思います。</p>
<h2>おまけ</h2>
<p>ちなみに、今回例に挙げている Source Generator のコードなんですが、
実際に作ってみたもので、
文字列を .NET の文字列リテラル(UTF-16 になる)ではなくて、UTF-8 のバイト列としてプログラムに埋め込むための Source Generator です。
(ちょっとコード整理して、GitHub に上げたら改めてブログに書こうかと思っています。)</p>
<p>昨日、こいつの紹介でちょっと動画配信したりしてたんですけども。</p>
<div>
<iframe width="560" height="315" src="https://www.youtube.com/embed/1Ic2VN3I5vI" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div>
<p>三人寄れば文殊の知恵というか、主に<a href="https://twitter.com/aetos382">あえとすさん</a>がすごい気もするものの、
ライブ配信中にこの新 partial メソッドの<a href="https://github.com/dotnet/roslyn/issues/44930">バグを見つけたり</a>。</p>
<p>みんなで寄ってたかって新機能を試してみるっていうのはライブ配信に対して求めていたことの1つなので、
非常によい回になったのではないかと思います。</p>
 ]]></description>
				<pubDate>Mon, 08 Jun 2020 21:39:51 +0900</pubDate>
			</item>
			<item>
				<title>C# 9.0 in .NET 5 Preview 4 (Build でのリリース)</title>
				<link>http://ufcpp.net/blog/2020/5/cs9net5p4/</link>
				<description><![CDATA[ <p>一昨日、C# 9.0 の話を動画配信してたわけですが。</p>
<div>
<iframe width="560" height="315" src="https://www.youtube.com/embed/fZxRZgWYqq0" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div>
<p><a href="https://mybuild.microsoft.com/">Microsoft Build</a> に合わせていろいろとブログ公開が公開されてました。</p>
<ul>
<li><a href="https://devblogs.microsoft.com/dotnet/announcing-net-5-preview-4-and-our-journey-to-one-net/">Announcing .NET 5 Preview 4 and our journey to one .NET</a></li>
<li>
<a href="https://devblogs.microsoft.com/visualstudio/visual-studio-2019-v16-6-and-v16-7-preview-1-ship-today/">Releasing Today! Visual Studio 2019 v16.6 &amp; v16.7 Preview</a>
<ul>
<li><a href="https://docs.microsoft.com/en-us/visualstudio/releases/2019/release-notes#16.6.0">16.6 Release Notes</a></li>
<li><a href="https://docs.microsoft.com/en-us/visualstudio/releases/2019/release-notes-preview#16.7.0-pre.1.0">16.7 Preview 1 Release Notes</a></li>
</ul>
</li>
<li><a href="https://devblogs.microsoft.com/dotnet/introducing-net-multi-platform-app-ui/">Introducing .NET Multi-platform App UI</a></li>
<li><a href="https://devblogs.microsoft.com/dotnet/windows-forms-designer-for-net-core-released/">Windows Forms Designer for .NET Core Released</a></li>
<li><a href="https://devblogs.microsoft.com/dotnet/announcing-entity-framework-core-5-0-preview-4/">Announcing Entity Framework Core 5.0 Preview 4</a></li>
<li><a href="https://devblogs.microsoft.com/dotnet/ml-net-model-builder-is-now-a-part-of-visual-studio/">ML.NET Model Builder is now a part of Visual Studio</a></li>
<li><a href="https://devblogs.microsoft.com/commandline/windows-terminal-1-0/">Windows Terminal 1.0</a></li>
<li><a href="https://devblogs.microsoft.com/commandline/windows-package-manager-preview/">Windows Package Manager Preview</a></li>
<li><a href="https://blogs.windows.com/windowsdeveloper/2020/05/19/introducing-winui-3-preview-1/">Introducing WinUI 3 Preview 1</a></li>
<li><a href="https://devblogs.microsoft.com/commandline/the-windows-subsystem-for-linux-build-2020-summary/">The Windows Subsystem for Linux BUILD 2020 Summary</a></li>
<li><a href="https://devblogs.microsoft.com/directx/directx-heart-linux/">DirectX is coming to the Windows Subsystem for Linux</a></li>
<li><a href="https://devblogs.microsoft.com/visualstudio/expanding-visual-studio-2019-support-for-visual-studio-codespaces/">Expanding Visual Studio 2019 support for Visual Studio Codespaces</a></li>
<li><a href="https://devblogs.microsoft.com/visualstudio/live-share-now-with-chat-and-audio-support/">Live Share, now with chat and audio support!</a></li>
</ul>
<p>結構いろんな方向に手を出してるなぁという感じで、あんまり事細かに全部は見れていないんですが。
というか、全部見てるといくらでも時間が溶けるというか。
C# 9.0の話だけでもお腹いっぱいというか。
動画配信でも当然のようにほぼ C# 9.0 の話だけで2時間くらいになっています。</p>
<p>C# チームによる C# 9.0 のブログも投稿されています。</p>
<ul>
<li><a href="https://devblogs.microsoft.com/dotnet/welcome-to-c-9-0/">Welcome to C# 9.0</a></li>
</ul>
<p>ちなみに、C# チームのブログは「C# 9.0 は最終的にこうなる予定」という内容で、
今現在は動かない機能が結構あります。
(というか、9.0 の主役なのでブログのボリュームを割かれている Records が、
まだまだ絶賛作業中で仕様レベルでも完成形になっていないです。)</p>
<p>一方で、配信で話した＆今日ここで書くのは .NET 5 Preview 4 に merge された新機能についてです:</p>
<ul>
<li>native int</li>
<li>target-typed new</li>
<li>pattern V3</li>
</ul>
<p>これらを動かすためには相変わらず <a href="https://ufcpp.net/study/csharp/cheatsheet/langversionoption/#langversion"><code>LangVersion</code></a> preview 指定が必要になります。
(9.0 指定はまだできません。)</p>
<p>配信前に用意したコード:</p>
<div>
<script src="https://gist.github.com/ufcpp/3b0f78de250dc94243bd8015250779b0.js"></script>
</div>
<p><a href="https://github.com/ufcpp-live/UfcppLiveAgenda/issues/7#issuecomment-631462252">配信中に書きちらかした結果</a></p>
<h2>native int</h2>
<p>native int は、
32ビットCPUでは32ビット整数(<code>int</code>, <code>uint</code>)、
64ビットCPUでは64ビット整数(<code>long</code>, <code>ulong</code>)
になる整数型です。</p>
<p>これまでも <code>IntPtr</code> と <code>UIntPtr</code> がそういう性質を持つ型だったんですが、
名前通り<a href="https://ufcpp.net/study/csharp/sp_unsafe.html#about-pointer">ポインター用</a>であって、
普通の整数演算(加減乗除とか)には使いにくかったです。
それが C# 9.0 で、</p>
<ul>
<li><code>nint</code>、<code>nuint</code> というキーワードを用意</li>
<li>このキーワードを使って作った変数の場合、<code>int</code> とかと同じ整数演算が使えるようになる</li>
</ul>
<p>という状態になります。
ちなみに、実体(コンパイル結果)としては <code>IntPtr</code> と <code>UIntPtr</code> に翻訳されるみたいです。</p>
<p>まあ、CPU の違いを意識したコードを書かないといけない人と言うのはあまり多くないはずなので、
<code>nint</code>、<code>nuint</code> もあまり多くの人が使う機能ではないと思います。</p>
<h2>target-typed new</h2>
<p>ターゲットの型から推論できる場合、<code>new T()</code> の <code>T</code> を省略できて、<code>new()</code> と書ける機能です。
ちょっとした機能ですが、もしかするとこれからお世話になる度合いでいうと C# 9.0 の中で一番多いかもしれません。
(C# 7 世代でも、個人的には<a href="https://ufcpp.net/study/csharp/rm_default.html#default-expr">target-typed default</a>の利用頻度が非常に高かったです。)</p>
<p><code>var</code> (ソース側からの推論)よりもターゲット側からの推論が有効なのは以下のような場面です。</p>
<p>1つはフィールドとかプロパティの初期化子。</p>
<pre class="source" title="フィールド/プロパティ初期化子での new">
<code><span class="reserved">using</span> System.Collections.Generic;
 
<span class="reserved">class</span> <span class="type">Sample</span>
{
    <span class="reserved">private</span> <span class="reserved">static</span> <span class="type">Dictionary</span>&lt;<span class="reserved">int</span>, <span class="reserved">string</span>&gt; _cache = <span class="reserved">new</span>();
}
</code></pre>
<p>もう1つはメソッドの引数。</p>
<pre class="source" title="">
<code><span class="reserved">static</span> <span class="reserved">void</span> <span class="method">M</span>(<span class="type">Dictionary</span>&lt;<span class="reserved">string</span>, <span class="reserved">string</span>&gt; <span class="variable">options</span>) { }
 
<span class="reserved">static</span> <span class="reserved">void</span> <span class="method">Main</span>()
{
    <span class="method">M</span>(<span class="reserved">new</span>()
    {
        { <span class="string">&quot;define&quot;</span>, <span class="string">&quot;DEBUG&quot;</span> },
        { <span class="string">&quot;o&quot;</span>, <span class="string">&quot;true&quot;</span> },
        { <span class="string">&quot;w&quot;</span>, <span class="string">&quot;4&quot;</span> },
    });
}
</code></pre>
<p>特に、ジェネリックな型でフルネームを書くと長ったらしくなるものに対して有効で、
ここで挙げた例みたいに <code>Dictionary</code> に対して使うことが多くなるんじゃないかなと思います。</p>
<h2>pattern V3</h2>
<p>C# 7.0 から脈々と、ちょっとずつ拡充されてきた<a href="https://ufcpp.net/study/csharp/datatype/patterns/">パターン マッチング</a>なんですが、一応、9.0 で最終形になります。</p>
<p>まあ、7.0 と 8.0 では見送られる程度には<em>複雑な割に需要が低い</em>パターンなので、
そんなに使う機会はないかもしれません。</p>
<p>そもそも、パターン自体が Roslyn チームの「内需」なんじゃないかという感じもありますし。
(コンパイラーとか書いてるとパターン マッチが欲しい場面が多々あります。
<code>is T</code> 分岐だらけですし、[<code>A</code>～<code>z</code>の <code>case</code> が並んでいる嫌な感じの <code>switch</code>] とかが平然と出てくるので。)</p>
<p>ただ、C# 9.0 の主役である <a href="https://github.com/dotnet/csharplang/issues/39">Records</a> の発展形として、</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/113">Discriminated Unions</a></li>
<li><a href="https://github.com/dotnet/csharplang/issues/485">&quot;Closed&quot; type hierarchies</a></li>
</ul>
<p>みたいな話があって、これが入るとパターン マッチングの需要がちょっと上がるかもしれません。</p>
<p>また、複雑なパターンはたぶん書かないという人にとっても、以下の2つのパターンは便利だと思います。</p>
<ul>
<li>simplified type pattern</li>
<li>not pattern</li>
</ul>
<p>前者は、以下のように、<code>_</code> なしで型パターンを使えるというもの。</p>
<pre class="source" title="simplified type patter">
<code><span class="reserved">static</span> <span class="reserved">int</span> <span class="method">M</span>(<span class="reserved">object</span> <span class="variable">obj</span>) =&gt; <span class="variable">obj</span> <span class="control">switch</span>
{
    <span class="comment">// C# 8.0 までだと _ が必須だった。</span>
    <span class="comment">// 型名だけだと定数パターンとの区別がつかないため。</span>
    <span class="reserved">short</span> <span class="reserved">_</span> =&gt; 1,
    <span class="reserved">int</span> <span class="reserved">_</span> =&gt; 1,
    <span class="reserved">long</span> <span class="reserved">_</span> =&gt; 1,
 
    <span class="comment">// C# 9.0 では型名だけで型パターンにできるようになった。</span>
    <span class="comment">// 文脈を読んでくれてる(型名だったら型パターン、型がなければ定数パターンとして解釈)。</span>
    <span class="reserved">ushort</span> =&gt; 2,
    <span class="reserved">uint</span> =&gt; 2,
    <span class="reserved">ulong</span> =&gt; 2,
};
</code></pre>
<p>後者は名前通り「パターンを満たさないとき」用の構文です。
たぶん、<code>not null</code> が一番使うと思います。</p>
<pre class="source" title="not pattern">
<code><span class="reserved">static</span> <span class="reserved">int</span> <span class="method">M</span>(<span class="reserved">object</span> <span class="variable">obj</span>) =&gt; <span class="variable">obj</span> <span class="control">switch</span>
{
    <span class="comment">// string 型のインスタンスじゃないとき</span>
    <span class="reserved">not</span> <span class="reserved">string</span> =&gt; 1,
    <span class="comment">// null じゃないとき</span>
    <span class="reserved">not</span> <span class="reserved">null</span> =&gt; 2,
};
</code></pre>
<p>ちなみに、「こんな変な文法を追加しなくても、既存の構文で <code>if</code> とか <code>when</code> とか並べればいいんじゃないのか？」と思うかもしれませんが、パターン マッチングは結構賢くて、
ちゃんと条件が網羅的かどうかの判定をやってくれます。</p>
<pre class="source" title="条件の網羅性チェック">
<code><span class="reserved">static</span> <span class="reserved">int</span> <span class="method">Invalid</span>(<span class="reserved">object</span> <span class="variable">obj</span>)
{
    <span class="control">if</span> (!(<span class="variable">obj</span> <span class="reserved">is</span> <span class="reserved">string</span>)) <span class="control">return</span> 1;
    <span class="control">if</span> (!(<span class="variable">obj</span> <span class="reserved">is</span> <span class="reserved">null</span>)) <span class="control">return</span> 2;
 
    <span class="comment">// null の時は1つ目の if に引っかかっているはずで、</span>
    <span class="comment">// 2つめ if と合わせると全条件網羅してる。</span>
    <span class="comment">// なので、ここには到達できないはずだけど、if だと到達判定が効かない。</span>
    <span class="comment">// このメソッドはコンパイル エラーを起こす。</span>
}
 
<span class="comment">// パターンを使うと網羅性の判定が正しく動く。</span>
<span class="comment">// このメソッドはエラーにもならないし警告も出ない。</span>
<span class="comment">// 逆に、網羅できてない場合は警告が出る。</span>
<span class="reserved">static</span> <span class="reserved">int</span> <span class="method">Valid</span>(<span class="reserved">object</span> <span class="variable">obj</span>) =&gt; <span class="variable">obj</span> <span class="control">switch</span>
{
    <span class="reserved">not</span> <span class="reserved">string</span> =&gt; 1,
    <span class="reserved">not</span> <span class="reserved">null</span> =&gt; 2,
};
</code></pre>
<p>あと、数値の範囲を表すパターンとして <code>min..max</code> を使いたいという意見も結構あるんですが…
「両端を含む・含まない」の区別が紛らわしすぎるということで愚直に <code>&lt;</code>、<code>&lt;=</code>、<code>&gt;</code>、<code>&gt;=</code> を使うということになりました。</p>
<pre class="source" title="両端含む・含まない問題の回避策としての比較パターン">
<code><span class="reserved">static</span> <span class="reserved">int</span> <span class="method">M</span>(<span class="reserved">byte</span> <span class="variable">b</span>) =&gt; <span class="variable">b</span> <span class="control">switch</span>
{
    &gt;= 0 <span class="reserved">and</span> &lt;= 10 =&gt; 1, <span class="comment">// 0 も 10 も含んで [0, 10] の範囲</span>
    &gt; 10 <span class="reserved">and</span> &lt;= 20 =&gt; 2, <span class="comment">// 10 は含まず 20 は含んで (10, 20] の範囲</span>
    &gt; 20 <span class="reserved">and</span> &lt; 30 =&gt; 3, <span class="comment">// 20 も 30 も含まず (20, 30) の範囲</span>
    &gt;= 30 <span class="reserved">and</span> &lt; 40 =&gt; 4, <span class="comment">// 30 は含んで 40 は含まず [30, 40) の範囲</span>
    <span class="reserved">_</span> =&gt; 0,
};
</code></pre>
<p>ちなみに、比較パターンでも網羅性のチェックが働いています。</p>
<pre class="source" title="">
<code><span class="comment">// これは無警告</span>
<span class="reserved">static</span> <span class="reserved">int</span> <span class="method">M</span>(<span class="reserved">byte</span> <span class="variable">b</span>) =&gt; <span class="variable">b</span> <span class="control">switch</span>
{
    &gt;= 0 <span class="reserved">and</span> &lt;= 250 =&gt; 1,
    251 <span class="reserved">or</span> 252 <span class="reserved">or</span> 253 <span class="reserved">or</span> 254 =&gt; 2,
    255 =&gt; 3,
};
 
<span class="comment">// 例えば以下の3つには警告が出る</span>
<span class="reserved">static</span> <span class="reserved">int</span> <span class="method">M1</span>(<span class="reserved">byte</span> <span class="variable">b</span>) =&gt; <span class="variable">b</span> <span class="control">switch</span>
{
    &gt;= 0 <span class="reserved">and</span> &lt; 250 =&gt; 1, <span class="comment">// &lt;= と間違えて &lt; を書いて、250 が漏れてる</span>
    251 <span class="reserved">or</span> 252 <span class="reserved">or</span> 253 <span class="reserved">or</span> 254 =&gt; 2,
    255 =&gt; 3,
};
<span class="reserved">static</span> <span class="reserved">int</span> <span class="method">M2</span>(<span class="reserved">byte</span> <span class="variable">b</span>) =&gt; <span class="variable">b</span> <span class="control">switch</span>
{
    &gt;= 0 <span class="reserved">and</span> &lt;= 250 =&gt; 1,
    251 <span class="reserved">or</span> 253 <span class="reserved">or</span> 254 =&gt; 2, <span class="comment">// 252 が漏れてる </span>
    255 =&gt; 3,
};
<span class="reserved">static</span> <span class="reserved">int</span> <span class="method">M3</span>(<span class="reserved">byte</span> <span class="variable">b</span>) =&gt; <span class="variable">b</span> <span class="control">switch</span>
{
    &gt;= 0 <span class="reserved">and</span> &lt;= 250 =&gt; 1,
    251 <span class="reserved">or</span> 252 <span class="reserved">or</span> 253 <span class="reserved">or</span> 254 =&gt; 2,
    <span class="comment">// 255 が漏れてる</span>
};
</code></pre>
<p>この辺りのパターンの最適化の掛け方とか網羅性のチェックは、
先達となるプログラミング言語があって割と十分に検証されているらしく、
「需要は高くないけど、検討コストも低いから go サインが出た」という類になります。</p>
 ]]></description>
				<pubDate>Fri, 22 May 2020 20:54:03 +0900</pubDate>
			</item>
			<item>
				<title>見た目で区別できない変数</title>
				<link>http://ufcpp.net/blog/2020/5/variationselectoridentifier/</link>
				<description><![CDATA[ <p>ちょっとしたネタ投稿をしてみたわけですが。</p>
<p><a href="https://paiza.io/projects/WMu7W_PPTqkZRV5iGztJtg">https://paiza.io/projects/WMu7W_PPTqkZRV5iGztJtg</a></p>
<pre class="source" title="見た目で区別できない変数">
<code>import java.util.*;

public class Main {
    public static void main(String[] args) throws Exception {
        int a = 1;
        int a︀ = 2;
        int a︁ = 4;
        int a︂ = 8;
        int a︃ = 16;
        int a︄ = 32;
        int a︅ = 64;
        int a︆ = 128;
        int a︇ = 256;
        int a︈ = 512;
        int a︉ = 1024;
        int a︊ = 2048;
        int a︋ = 4096;
        int a︌ = 8192;
        int a︍ = 16384;
        int a︎ = 32768;
        int a️ = 65536;

        System.out.println(a + a︀ + a︁ + a︂ + a︃ + a︄ + a︅ + a︆ + a︇ + a︈ + a︉ + a︊ + a︋ + a︌ + a︍ + a︎ + a️);
    }
}
</code></pre>
<p>ぱっと見は同じ「<code>a</code>」という名前の変数が17個並んでいますが、これ、全部別変数です。
名前被りでコンパイル エラーになったりもしません。</p>
<p>まあ、種を明かすと<a href="https://ja.wikipedia.org/wiki/%E7%95%B0%E4%BD%93%E5%AD%97%E3%82%BB%E3%83%AC%E3%82%AF%E3%82%BF">異体字セレクター</a>っていう不可視の文字をくっつけてるだけで、この異体字セレクターが16種類あるので(何もつけてない1個と併せて)17個の「<code>a</code>」を作れているという状態。</p>
<h2>元々同じ見た目で別の文字</h2>
<p>特に難しいことをしなくても、元々、見た目が同じ別の文字は結構あります。
分かりやすい例で言うと、</p>
<ul>
<li><a href="https://www.fileformat.info/info/unicode/char/0041/index.htm">A (U+0041)</a> : ラテン文字の大文字の a</li>
<li><a href="https://www.fileformat.info/info/unicode/char/0391/index.htm">Α (U+0391)</a> : ギリシャ文字の大文字の α</li>
<li><a href="https://www.fileformat.info/info/unicode/char/0410/index.htm">А (U+0410)</a> : キリル文字の大文字の а</li>
</ul>
<p>とか。
全部出自が同じだし、発音も同系統(「あ」系統)なので似てて当然なんですが。
「出自が同じで字形も近い文字をまとめるかどうか」と言うのは結構根が深い問題になります。
Unicode ではこれらの文字を別文字扱いしています。</p>
<p>(別の文字なので当然字形が違ってもいいんですけども、
たいていのフォントでは同じ字形で表示されて区別がつかないと思います。)</p>
<p>こいつらを使えば、割と簡単に「ぱっと見で区別がつかない変数」を作れます。</p>
<pre class="source" title="ラテン文字、ギリシャ文字、キリル文字な変数">
<code><span class="reserved">using</span> System;
 
<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> <span class="method">Main</span>()
    {
        <span class="reserved">var</span> <span class="variable">A</span> = 1;
        <span class="reserved">var</span> <span class="variable">Α</span> = 2;
        <span class="reserved">var</span> <span class="variable">А</span> = 4;
 
        <span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="variable">A</span> + <span class="variable">Α</span> + <span class="variable">А</span>); <span class="comment">// 7</span>
        <span class="type">Console</span>.<span class="method">WriteLine</span>((<span class="reserved">int</span>)<span class="reserved">nameof</span>(<span class="variable">A</span>)[0]); <span class="comment">// U+0041 (10進 65)</span>
        <span class="type">Console</span>.<span class="method">WriteLine</span>((<span class="reserved">int</span>)<span class="reserved">nameof</span>(<span class="variable">Α</span>)[0]); <span class="comment">// U+0391 (10進 913)</span>
        <span class="type">Console</span>.<span class="method">WriteLine</span>((<span class="reserved">int</span>)<span class="reserved">nameof</span>(<span class="variable">А</span>)[0]); <span class="comment">// U+0410 (10進 1040)</span>
    }
}
</code></pre>
<p>今時、意図的に排除<sup>※</sup>でもしていない限り non-ASCII な文字も変数名に使えるので、たいていの言語で同じことができると思います。
まあ、わざわざ non-ASCII な文字でソースコードを書く人も少ないので、悪意を持ってやらない限りは起きないと思いますが。</p>
<p>(<sup>※</sup> 例えば <a href="https://doc.rust-lang.org/reference/identifiers.html">Rust</a> は ASCII 文字しか受け付けない意思を感じる。)</p>
<h2>アクセント</h2>
<p>もう少し悪意を高めてみます。</p>
<p>Unicode はそれ以前の各国個別の文字コードとの互換性のために、
いくつか、全く同じ文字を別のコードで表現できてしまいます。
分かりやすいのがアクセント記号の類(<a href="https://ja.wikipedia.org/wiki/%E3%83%80%E3%82%A4%E3%82%A2%E3%82%AF%E3%83%AA%E3%83%86%E3%82%A3%E3%82%AB%E3%83%AB%E3%83%9E%E3%83%BC%E3%82%AF">ダイアクリティカルマーク</a>)で、
例えば、「á」の文字は以下の2通りの表現方法があります。</p>
<ul>
<li>á (<a href="https://www.fileformat.info/info/unicode/char/00E1/index.htm">U+00E1</a>) : 元々西欧向け文字コードに入っていた文字</li>
<li>á (<a href="https://www.fileformat.info/info/unicode/char/0061/index.htm">U+0061</a> <a href="https://www.fileformat.info/info/unicode/char/0301/index.htm">U+0301</a>) : 無印の a の上に acute アクセントを結合</li>
</ul>
<p>Unicode にはこの手の「同じ文字の別表現」を互いに変換するための仕様も入っているんですが、
その手の変換まで書けるプログラミング言語はまずありません。</p>
<p>結果的に、この手の文字も「ぱっと見で区別がつかない変数」に使えます。</p>
<pre class="source" title="アクセント記号を含む変数">
<code><span class="reserved">using</span> System;
 
<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> <span class="method">Main</span>()
    {
        <span class="reserved">var</span> <span class="variable">á</span> = 1;
        <span class="reserved">var</span> <span class="variable">á</span> = 2;
 
        <span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="variable">á</span> + <span class="variable">á</span>); <span class="comment">// 3</span>
        <span class="type">Console</span>.<span class="method">WriteLine</span>((<span class="reserved">int</span>)<span class="reserved">nameof</span>(<span class="variable">á</span>)[0]); <span class="comment">// U+00E1 (10進 225)</span>
        <span class="type">Console</span>.<span class="method">WriteLine</span>((<span class="reserved">int</span>)<span class="reserved">nameof</span>(<span class="variable">á</span>)[0]); <span class="comment">// [0] は `a` が拾える。U+0061 (10進 97)</span>
        <span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="reserved">nameof</span>(<span class="variable">á</span>).Length); <span class="comment">// 実は2文字なので Length が 2</span>
    }
}
</code></pre>
<p>アクセント記号(この例で言うと U+0301)を変数名に使えるかどうかはプログラミング言語によります。
例えば <a href="https://golang.org/ref/spec#Identifiers">Go は letter (a とかの可読文字)しか受け付けません</a>。
<a href="https://docs.oracle.com/javase/jp/7/api/java/lang/Character.html#isJavaIdentifierPart(int)">Java</a> とか <a href="https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/language-specification/lexical-structure#identifiers">C#</a> とかは、2文字目以降にはアクセント記号の類を受け付けます。</p>
<h2>0幅不可視文字</h2>
<p>Unicode にはいくつか、以下のような、0幅でまったく見えない文字が存在します。</p>
<ul>
<li><a href="https://www.fileformat.info/info/unicode/char/200d/index.htm">Zero Width Joiner (U+200D)</a> : 前後の文字をくっつける(改行とかで分割されることが絶対起きないようにするための文字)</li>
<li><a href="https://www.fileformat.info/info/unicode/char/200f/index.htm">Right-to-Left Mark U+200F</a> : この文字以降、右書きにする</li>
</ul>
<p>まあでも、この手の文字はほとんどのプログラミング言語が受け付けません。
Java と C# はちょっと特殊で、「<a href="https://docs.oracle.com/javase/jp/7/api/java/lang/Character.html#isIdentifierIgnorable(int)">受け付けるけど完全に無視</a>」という挙動をしたりします。</p>
<p>いずれにしても、0幅不可視な文字がソースコードに紛れていて困ることはほとんどない…
と思っていたんですけども…</p>
<h2>異体字セレクター</h2>
<p>そういえばあったわ、Java と C# が変数名として受け付けて、無視もせず、0幅不可視の文字…
というのが<a href="https://ja.wikipedia.org/wiki/%E7%95%B0%E4%BD%93%E5%AD%97%E3%82%BB%E3%83%AC%E3%82%AF%E3%82%BF">異体字セレクター</a>。</p>
<p><a href="https://ja.wikipedia.org/wiki/%E6%96%9C%E7%B7%9A%E4%BB%98%E3%81%8D%E3%82%BC%E3%83%AD">数字の 0 を斜線付きで表示</a>したりするために使う文字なんですけども、カテゴリーが <a href="https://www.compart.com/en/unicode/category/Mn">Nonspacing Mark</a> (アクセント記号とかと同じカテゴリー)だったりします。</p>
<p>ほとんどの文字が異体字なんて持ってないので、異体字セレクターがくっついていても、テキスト レンダリング上は単に無視されます。
要するに、実質、0幅不可視文字。
なのに、カテゴリー的には変数として受け付けられるし、別の文字として扱われます。</p>
<p>このうち U+FE00〜U+FE0F の16文字を使って書いたコードが冒頭の Java コードになります。</p>
<p>再掲: <a href="https://paiza.io/projects/WMu7W_PPTqkZRV5iGztJtg">https://paiza.io/projects/WMu7W_PPTqkZRV5iGztJtg</a></p>
<p>ちなみにこの文字、後ろにいくらでもつなげられるので、16個と言わず、文字列長を増やしていけばいくらでも「<code>a</code>」を増やせます。</p>
<h2>ちなみに、背景</h2>
<p>これ、<a href="https://github.com/ufcpp/roslyn/commit/94557f7e5bc0804c308b0af98f734e1d3f99592a#diff-92ef870ff9496ca561e057580a939742R24-R55">単体テストのテストケース</a>を検討しているときに思いついたものの、
以下の2つの理由で没ったものだったりします。</p>
<ul>
<li>
簡単に入力できない
<ul>
<li>普通の状況で絶対に現れない文字列</li>
<li>日本語 IME を使って入力できちゃう「葛󠄀」(葛󠄀城市の葛󠄀。葛飾区の葛の異体字。U+845B U+E0100)の方が適任</li>
</ul>
</li>
<li>
プログラム的には難しい処理をしていない
<ul>
<li>厄介なのは人の目に見えないという点だけ</li>
<li>プログラム的には  á (<a href="https://www.fileformat.info/info/unicode/char/0061/index.htm">U+0061</a> <a href="https://www.fileformat.info/info/unicode/char/0301/index.htm">U+0301</a>) と同じパターンなので、á だけで十分</li>
</ul>
</li>
</ul>
<p>というか、「葛󠄀」と「葛」は区別されるのかどうかが気になったのが先で、
異体字セレクター (U+E0100 とか)のカテゴリーがアクセント記号の類と同じ(Nonspacing Mark)なことに気付いたというのが実際の流れ。
(しかも、この <a href="https://www.fileformat.info/info/unicode/category/Mn/list.htm">Nonspacing Mark カテゴリー</a>の文字一覧を眺めてみてるに、完全に不可視なのは異体字セレクターだけっぽい。)</p>
<p>ちなみに、どうやって上記 Java コードを書いたかと言うと…
<a href="https://paiza.io/projects/MN1P7UTSayHYhpkJ6Reuow"><code>&quot;a\uFE00a\uFE01a\uFE02a\uFE03...&quot;</code> みたいなエスケープ シーケンスを使ってプログラムで出力して</a>、それをコピペして書いています。</p>
 ]]></description>
				<pubDate>Mon, 18 May 2020 00:02:03 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn: C# 9.0 向け Design Notes</title>
				<link>http://ufcpp.net/blog/2020/5/pickuproslyn0503/</link>
				<description><![CDATA[ <p>C# Language Design Notes が3件に、</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-04-15.md">C# Language Design Notes for Apr 15, 2020</a></li>
<li>
<a href="https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-04-20.md">C# Language Design Meeting for March 20, 2020</a>
<ul>
<li><a href="https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-04-27.md">C# Language Design Meeting for April 27, 2020</a></li>
</ul>
</li>
</ul>
<p>提案ドキュメントのアップロードが3件。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/blob/master/proposals/extending-partial-methods.md">Extending Partial Methods</a></li>
<li><a href="https://github.com/dotnet/csharplang/blob/master/proposals/covariant-returns.md">covariant return types</a></li>
<li><a href="https://github.com/dotnet/csharplang/blob/master/proposals/module-initializers.md">Module Initializers</a></li>
</ul>
<p>特に partial メソッドの拡張の話は Source Generator 関連です。
最初、Source Generator ネタでまとめて投稿しようかと思っていたものの、ちょっとまとまり悪くなりそうだったので1日3件ブログに。</p>
<ul>
<li>1個前: <a href="/blog/2020/5/featureswitch/">.NET 5 への Xamarin 統合に向けて</a></li>
<li>2個前: <a href="/blog/2020/5/sourcegenerator/">C# Source Generator (first preview)を試してみる</a></li>
</ul>
<h2>partial メソッドの拡張</h2>
<p>コンパイル時のソースコード生成ができるようになると、</p>
<ul>
<li>手書きで <code>int M();</code> みたいなメソッド宣言だけを書く</li>
<li>それに反応して、何らかの <code>M</code> の実装をコード生成したい</li>
</ul>
<p>みたいな要件が出てきます。</p>
<p>こういう、コード生成物と手書きコードのつなぎ用の機能として、
C# には 2.0 の頃から <a href="/study/csharp/ap_ver2.html#partial">partial type</a>、
3.0 の頃から <a href="/study/csharp/ap_ver3.html#partial_method">partial method</a> という機能があったりします。
ですがこれは、</p>
<ul>
<li>Windows Forms とかが生成する中身が空っぽのメソッドが先にある</li>
<li>手書きコードを足す必要がないのであれば、一切痕跡を残さず消す</li>
<li>手書きコードを足した場合、コード生成物の中から呼ばれるようになる</li>
</ul>
<p>みたいな機能で、以下のような制限があります。</p>
<ul>
<li><a href="/study/csharp/oo_conceal.html#level">アクセス修飾子</a>は付けれない(暗黙的に private)</li>
<li>戻り値は <code>void</code> 出ないとダメ</li>
<li><a href="/study/csharp/sp_ref.html#out"><code>out</code> 引数</a>は使えない</li>
</ul>
<p>これに対して、今出ている要件は逆方向のつなぎ(手書きが先にあって、コード生成物が後)になります。
微妙に挙動に差があるんですが、同じ <code>partial</code> というキーワードを使いまわしたいみたいです。</p>
<ul>
<li>手書きコードで中身が空っぽのメソッドを先に書く</li>
<li>コード生成でメソッドの中身を埋める、埋めないとコンパイル エラー</li>
<li>アクセス修飾子を付けたら(private であっても)この挙動になる</li>
<li>この場合は <code>void</code> 以外の戻り値と、<code>out</code> 引数を持てる</li>
</ul>
<p>という感じ。
<code>partial void M();</code> と <code>private partial void M();</code> で挙動が違うのがなかなか気持ち悪いですけども、
新しいキーワードを足すよりはこの方がマシだろいうという判断みたいです。</p>
<h2>トップレベルのステートメント</h2>
<p><code>Program.Main</code> を書かなくても、ステートメントを直接ファイル直下に書けるようにするという話。
今回の議題は、</p>
<ul>
<li>
スクリプト方言みたいに式だけ書く(<code>;</code> を付けない式を書く)とそれが戻り値になるべきか
<ul>
<li>→ やらない</li>
</ul>
</li>
<li>
トップレベルに書いた変数などの名前はどう扱うべきか
<ul>
<li>プログラム全域がその名前のスコープになる(= 同名別変数を定義するとエラーになる)</li>
<li>かといって、今の仕様だとその変数を参照して使おうとするとエラーになる</li>
<li>使えない変数はスコープから外すべき？</li>
<li>→ 今は使ってないけども将来はわからないのでいったんこの仕様で行きたい</li>
</ul>
</li>
<li>
コマンドライン引数の受け取り方
<ul>
<li><code>void Main(string[] args)</code> みたいな部分が消えるので、コマンドライン引数の <code>args</code> はどう受け取ればいいか</li>
<li>案1: 暗黙の変数 (プロパティの <code>set</code> 中の <code>value</code> みたいなもの)を用意する(名前はおそらく <code>args</code> 変数になる)</li>
<li>案2: <code>Environment.Args</code> なりなんなり、何らかの API を用意する</li>
<li>→ もうちょっと要検討。どっちの案にするかはともかく、こういう手段は必要</li>
</ul>
</li>
<li>
<a href="/study/csharp/sp5_async.html#async"><code>await</code></a> の扱い
<ul>
<li>
今の仕様
<ul>
<li>トップレベル ステートメント中に <code>await</code> が1つでもあれば、生成されるのは <code>Task Main()</code></li>
<li>1つもなければ、生成されるのは <code>void Main()</code></li>
</ul>
</li>
<li>これでいい？常に <code>Task Main()</code> で生成するとかしなくていい？</li>
<li>→ とりあえず今の仕様で行く</li>
</ul>
</li>
</ul>
<h2>Records がらみ</h2>
<h3>with 式の Clone</h3>
<p><code>with</code> 式ではオブジェクトの Clone → 特定のプロパティだけ書き換え みたいな処理になります。
で、このクローンをどうするか。</p>
<ul>
<li>現状、ユーザー定義の Clone メソッドには対応していない</li>
<li>将来的にはユーザー定義で Clone の挙動を自由に変えれるようにしたい</li>
<li>C# 9.0 時点では、将来の拡張性だけつぶさないように気を付けつつ、いったん現状の実装で進める</li>
</ul>
<h3>Records: positional</h3>
<p><a href="/blog/2020/4/pickuproslyn0419/">4/13の Design Notes での検討</a>によれば、
positional な Records (プライマリ コンストラクター)の優先度は低めになったんですが。
それでも、これに関していろいろ検討しているみたいです。</p>
<h3>プライマリ コンストラクター</h3>
<ul>
<li>
プライマリ コンストラクターは常に呼ばれないといけない
<ul>
<li>手書きのコンストラクターがある場合、<code>Point () : this(0, 0)</code> みたいにプライマリ コンストラクター呼び出しが必要</li>
</ul>
</li>
<li>
positional な Records にはコピー コンストラクターも自動生成したい
<ul>
<li><code>Point(Point other) : this(other.X, other.Y) { }</code> みたいなプライマリ コンストラクター呼び出しをしたい</li>
</ul>
</li>
<li>
プライマリ コンストラクターでは、
<ul>
<li><code>class MyClass(int x, int y) { public int P =&gt; x + y; }</code> みたいにキャプチャが発生したときには自動的にフィールドを生成する</li>
<li>そうでないときは何も生成しない(単なるコンストラクターの引数扱い)</li>
</ul>
</li>
<li>positional な Records では、init-only なプロパティを生成する</li>
<li>
Records でない普通のクラスでプライマリ コンストラクターを認める場合と、positional な Records とで不整合は起きないか
<ul>
<li>→ 生成されるものがフィールドか init-only プロパティかの差があるけど、それくらいは許容する</li>
</ul>
</li>
</ul>
<h3>プライマリ コンストラクター本体とバリデーター</h3>
<p>プライマリ コンストラクターに対してコンストラクター本体を持ちたい場合、
以下のような構文になるみたいです。</p>
<pre class="source" title="プライマリ コンストラクター本体とバリデーター">
<code><span class="reserved">class</span> <span class="type">TypeName</span>(<span class="reserved">int</span> X, <span class="reserved">int</span> Y) <span class="comment">// プライマリ コンストラクター</span>
{
    <span class="comment">// 引数リストなしの型名 = プライマリ コンストラクターの本体</span>
    <span class="reserved">public</span> <span class="type">TypeName</span>
    {
        <span class="comment">// new TypeName(x, y) の時点で呼ばれる処理</span>
    }
 
    <span class="comment">// init キーワード = バリデーター</span>
    init
    {
        <span class="comment">// new TypeName { X = x, Y = y } みたいな、初期化子での初期化の後に呼ばれる</span>
    }
}
</code></pre>
<p>元々はこの2つを区別していなかったものの、結局は両方必要そうで、両方を認めそう。</p>
<h3>プライマリ コンストラクターからの基底クラス コストラクター呼び出し</h3>
<p>2種類の書き方ができるけども、どちらも認めてしまえとのこと。</p>
<pre class="source" title="">
<code><span class="reserved">class</span> <span class="type">TypeName</span>(<span class="reserved">int</span> X, <span class="reserved">int</span> Y) : <span class="type">BaseType</span>(X, Y);
 
<span class="reserved">class</span> <span class="type">TypeName</span>(<span class="reserved">int</span> X, <span class="reserved">int</span> Y) : BaseType
{
    <span class="reserved">public</span> <span class="type">TypeName</span> : <span class="reserved">base</span>(X, Y) { }
}
</code></pre>
<h2>共変戻り値</h2>
<p>要は以下のようなやつ。</p>
<pre class="source" title="共変戻り値">
<code><span class="reserved">class</span> <span class="type">Compilation</span> ...
{
    <span class="reserved">virtual</span> <span class="type">Compilation</span> <span class="method">WithOptions</span>(Options <span class="variable">options</span>)...
}
<span class="reserved">class</span> <span class="type">CSharpCompilation</span> : <span class="type">Compilation</span>
{
    <span class="comment">// 戻り値の型が Compilation.WithOptions と違う</span>
    <span class="comment">// けど、派生型で共変なので問題ないはず。</span>
    <span class="reserved">override</span> <span class="type">CSharpCompilation</span> <span class="method">WithOptions</span>(Options <span class="variable">options</span>)...
}
</code></pre>
<p>これも需要は非常に高いものの、
「.NET ランタイム側の修正が必要なので C# だけでできなくて重たい」みたいに言われ続けてたやつ。</p>
<p>.NET 5 で実装するみたいです。今まさに作業中:</p>
<ul>
<li><a href="https://github.com/dotnet/runtime/pull/35308">Covariant Returns Feature</a></li>
</ul>
<p>ということで、C# 的にも C# 9.0 で入ります。
ただ、 .NET Core 3.1 以前のバージョンでは動かないです。</p>
<h2>モジュール初期化子</h2>
<p>モジュール(dll とか)が読み込まれたタイミングで1回だけ呼ばれる処理を書きたいという要望が以前からあります。</p>
<p>似たようなものとして、クラスの静的コンストラクターがあるんですが…</p>
<pre class="source" title="静的コンストラクター">
<code><span class="reserved">class</span> <span class="type">Initializer</span>
{
    <span class="reserved">static</span> <span class="type">Initializer</span>()
    {
        <span class="comment">// 初めてこのクラスの何らかのメンバーを使おうとしたタイミングで呼ばれる</span>
    }
}
</code></pre>
<p>こいつだと、このクラスに一切触れなかった場合には全く呼ばれませんし、
「初めて触ったとき」という読めないタイミングでの呼び出しになります。</p>
<p>なのでモジュール読み込み時に確定で呼ばれるメソッドを用意したいというのがモジュール初期化子(module initializer)です。</p>
<p>今のところ、属性 + 静的コンストラクターで実装したいみたいです。</p>
<pre class="source" title="モジュール初期化子">
<code><span class="reserved">using</span> System.Runtime.CompilerServices;
 
[<span class="reserved">module</span>: <span class="type">ModuleInitializer</span>(<span class="reserved">typeof</span>(<span class="type">MyModuleInitializer</span>))]
 
<span class="reserved">internal</span> <span class="reserved">static</span> <span class="reserved">class</span> <span class="type">MyModuleInitializer</span>
{
    <span class="reserved">static</span> <span class="type">MyModuleInitializer</span>()
    {
        <span class="comment">// モジュール読み込み時に実行される</span>
    }
}
</code></pre> ]]></description>
				<pubDate>Sun, 03 May 2020 20:01:09 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn: .NET 5 への Xamarin 統合に向けて</title>
				<link>http://ufcpp.net/blog/2020/5/featureswitch/</link>
				<description><![CDATA[ <p>1つ前のブログで話した <a href="/blog/2020/5/sourcegenerator/">Source Generator</a> の動機の1つは、
リフレクションが使えない環境でのコード生成をある程度カバーできるようにというものです。</p>
<p>今、 .NET Core と Xamarin の統合作業真っ最中で、
その結果、iOS とか Web Assembly とかで使いにくい機能をどうしようかという話になっていて、リフレクションもその1つです。</p>
<p>その他にもいくつか、対応プラットフォームが増えることで必要な作業がちらほらと。</p>
<h2>Feature Switch</h2>
<p>iOS とかの AOT (事前ネイティブ コンパイル)シナリオだと使わない機能はコンパイル時に削ってしまいたいわけですが、
そのためのスイッチを用意したいみたいな話も出ていたりします。</p>
<ul>
<li><a href="https://github.com/dotnet/designs/blob/master/accepted/2020/feature-switch.md">Feature Switch</a></li>
</ul>
<p><code>Regex</code> の <code>RegexOptions.Compiled</code> とか、めったに使わず、使わない場合削ってしまえればコード量が結構多いみたいです。
あと、暗号系のアルゴリズムとかは、アプリごとに1度「これ」と決めてしまえばほとんどの場合その1個だけしか使わないと思いますが、この場合、使わないものを軒並み決してしまいたかったり。</p>
<p>こういう特定機能のスイッチは、 Target Framework の亜種を増やすのではなくて、
以下のような感じの <code>bool</code> フラグでソースコード中で切り替え処理をしてほしそうです。
(<a href="/blog/2018/12/hdintrinsic/">Hardware Intrinsics</a>とかでやっているのと同じ方式です。)</p>
<pre class="source" title="FeatureSwitch">
<code><span class="reserved">internal</span> <span class="reserved">static</span> <span class="reserved">class</span> <span class="type">FeatureDefiningType</span>
{
    [<span class="type">FeatureSwitch</span>(<span class="string">&quot;System.Runtime.OptionalFeatureBehavior&quot;</span>)]
    <span class="reserved">internal</span> <span class="reserved">static</span> <span class="reserved">bool</span> IsOptionalFeatureEnabled { <span class="reserved">get</span>; }
}
</code></pre>
<h2>国際化対応</h2>
<p>カレンダーや時刻とかの国ごとに違う書式(2020年5月3日 か 3 May, 2020 か)とか、
文字ごとの Unicode カテゴリー、文字列のどこで改行していいかとか、
アルファベットの大文字・小文字の対応付けとか、
どれも結構大きなテーブルデータを必要とします。</p>
<p>これに対して、.NET Core の国際化対応は <a href="http://site.icu-project.org/home">ICU</a> (International Components for Unicode) に依存していたりします。</p>
<p>で、これも iOS とかでどうしようかという話に。</p>
<ul>
<li><a href="https://github.com/dotnet/designs/pull/102">Globalization support in .NET 5</a></li>
</ul>
<p>デスクトップやサーバーOSには今どき大体 ICU が同梱されていたりするんですが。
Android も、API level 24 移行は <a href="https://developer.android.com/guide/topics/resources/internationalization#relation">ICU4J</a> を持っていたりします。
問題が iOS と Web Assembly で、この辺りは OS/プラットフォーム側に ICU がないのでどうしようかという状態。</p>
<p>案としては、いっそ国際化対応を捨てるという方法。
どのカルチャーを取得しようとしても常に <a href="https://docs.microsoft.com/ja-jp/dotnet/api/system.globalization.cultureinfo.invariantculture"><code>InvariantCulture</code></a>を返してしまうというモードがあるみたいです。</p>
<ul>
<li><a href="https://github.com/dotnet/runtime/blob/master/docs/design/features/globalization-invariant-mode.md">.NET Core Globalization Invariant Mode</a></li>
</ul>
<p>別案としては、ICU をアプリ単位で同梱する方法。
これは、「OS のバージョンに依らず、所望の ICU バージョン(≒ Unicode バージョン)に依存したい」という場合にも使えます。</p>
<ul>
<li><a href="https://github.com/dotnet/runtime/pull/35383">Add app-local support for ICU</a></li>
</ul>
<p>ちなみに、ICU はテーブルデータを全部持とうとすると16MBくらいのサイズになるらしく、
アプリ1個1個に全部含めてしまうには少々でかいです。
ICU 自体には「必要な分だけ残してテーブルを削る」みたいな仕組みもあるらしくて、
iOS とか Web Assembly みたいな AOT シナリオのコンパイルにもテーブル削減の仕組みを組み込みたいというような話もあります。</p>
<ul>
<li><a href="https://github.com/dotnet/runtime/issues/35092">Prototype ICU size reduction tooling</a></li>
</ul>
 ]]></description>
				<pubDate>Sun, 03 May 2020 18:24:27 +0900</pubDate>
			</item>
			<item>
				<title>C# Source Generator (first preview)を試してみる</title>
				<link>http://ufcpp.net/blog/2020/5/sourcegenerator/</link>
				<description><![CDATA[ <p>C# で、ビルド時にソースコード生成してくれる仕組みが入りそうです。</p>
<ul>
<li><a href="https://devblogs.microsoft.com/dotnet/introducing-c-source-generators/">Introducing C# Source Generators</a></li>
</ul>
<p>案自体は C# 6.0 時代からある話です。
まあ、ソースコード生成はいろいろと大変なのでなかなか手付かずだったんですが、
やっと最初の1歩が公開されたという段階。</p>
<p>とりあえず、昨日、軽く試してみるライブ配信してました:</p>
<div>
<iframe width="560" height="315" src="https://www.youtube.com/embed/aZENYVSEpIY" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div>
<p>ほんとに「first preview」(最初だからこんなもんでしょ)という状態ではあります。
あんまりブログに「まだあれもない、これもない」と書いてもしょうがないので、
ここでは「そんな状態のものを試して貢献したい」という人柱の募集だけしておきます。</p>
 ]]></description>
				<pubDate>Sun, 03 May 2020 18:05:52 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 4/19: C# 9.0 機能の仕様ドキュメントいくつか</title>
				<link>http://ufcpp.net/blog/2020/4/pickuproslyn0419/</link>
				<description><![CDATA[ <p>今回は先にブログを書いてから、それを追う形でライブ配信(この部分は後からの追記):</p>
<div>
<iframe width="560" height="315" src="https://www.youtube.com/embed/STKZNnauJjo?start=304" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div>
<p>ここ1週間くらいで、C# 9.0 で入るであろう機能がちゃんとした仕様ドキュメントに起こされ始めました。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/pull/3361">Add draft spec for C# pattern-matching changes. #3361</a></li>
<li><a href="https://github.com/dotnet/csharplang/pull/3363">Add proposal for target-typed conditional expression. #3363</a></li>
<li>
<a href="https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-04-13.md">C# Language Design for April 13, 2020 (Roadmap for records)</a>
<ul>
<li><a href="https://github.com/dotnet/csharplang/pull/3367">Init only proposal document #3367</a></li>
</ul>
</li>
</ul>
<h2>パターン マッチング v3</h2>
<p>パターン マッチングも3世代目になります。
最初 <a href="/study/csharp/cheatsheet/ap_ver7/">C# 7.0</a> に入ったころは単に「<code>is</code> がちょっと便利になった」、
「<code>switch</code> で型分岐ができるようになった」程度の機能でしたが、
3世代目ともなるとずいぶんいろいろなものが増えています。</p>
<p>詳細は動くものが出てきてからちゃんとした記事化しようかと思いますが、以下のようなパターンが追加される予定です。</p>
<ul>
<li>
型パターン
<ul>
<li>今、<code>int i</code> とか <code>int _</code> とか書かないといけないものを <code>int</code> だけで型パターン扱いする修正</li>
</ul>
</li>
<li>
括弧パターン
<ul>
<li>パターンを <code>()</code> でくくれるようにする</li>
<li>下記 <code>and</code> や <code>or</code> の結合優先度がよくわからなくなるのを防ぐために追加</li>
</ul>
</li>
<li>
conjunctive <code>and</code> (論理積) パターン
<ul>
<li><code>and</code> で繋いだ2つのパターンのどちらにもマッチする</li>
</ul>
</li>
<li>
disjunctive <code>or</code> (論理和) パターン
<ul>
<li><code>or</code> で繋いだ2つのパターンの少なくともどちらか片方にマッチする</li>
</ul>
</li>
<li>
negated <code>not</code> (論理否定) パターン
<ul>
<li><code>not</code> の後ろのパターンを満たさない時にマッチする</li>
</ul>
</li>
<li>
relational (比較) パターン
<ul>
<li>数値(<code>int</code> 系、<code>float</code> 系、<code>decimal</code>)型に対して、<code>&lt;</code>、<code>&gt;</code>、<code>&lt;=</code>、<code>&gt;=</code> で大小比較する</li>
</ul>
</li>
</ul>
<p>パターン マッチングv3がらみは割とすでに実装が動いてるんですが、
いくつか最近検討されたばかり・まだ検討中の項目もあります。</p>
<ul>
<li>
<code>x is byte and &lt; 100</code> みたいに書くと、<code>and</code> の左側の型に合わせて右側の型が決まる (<a href="https://github.com/dotnet/roslyn/issues/42207">roslyn #42207</a>)
<ul>
<li>この場合、<code>&lt; 100</code> 判定は <code>byte</code> 扱いで比較</li>
</ul>
</li>
<li><code>or</code> の場合は左右の型の間の暗黙的な型変換(派生型 → 基底型みたいなやつ)だけ考慮 (<a href="https://github.com/dotnet/roslyn/pull/43419">roslyn #43419</a>)</li>
<li><code>x is not string ns</code> みたいに、<code>not</code> パターンを使った場合でもその後 <code>ns</code> 変数を使える (<a href="https://github.com/dotnet/csharplang/issues/3369">csharplang #3369</a>)</li>
</ul>
<h2>target-typed 条件演算子</h2>
<p><code>Base x = b ? new A() : new B();</code> みたいな条件演算子を書いた時、
左辺の <code>Base</code> 型から型決定して、<code>A</code>, <code>B</code> 違う型でもこの式が有効になるようにしようという話です。</p>
<p><a href="/study/csharp/datatype/typeswitch/?p=5#target-typed"><code>switch</code> 式</a>の場合、導入時の C# 8.0 の時点からこの手の型決定機構が働いています。
<code>switch</code> 式でだけ有効なのも変な話なので条件演算子でも同様のことをしたいという案はずっとあったんですが、
問題は、以下のような場合に既存のコードを壊してしまうこと。</p>
<pre class="source" title="target-typed 条件演算子の悩みどころ">
<code><span class="comment">// 既存のルールだと long の方が選ばれる。</span>
<span class="comment">// switch 式と同じルールの target-typed を導入すると short が優先されるようになる。</span>
M(b ? 1 : 2);

<span class="reserved">void</span> M(<span class="reserved">short</span> x) { }
<span class="reserved">void</span> M(<span class="reserved">long</span> x) { }
</code></pre>
<p>ということで、</p>
<ul>
<li><code>switch</code> 式の場合は target-typed による型決定 → 共通型の判定</li>
<li>条件演算子の場合は 共通型の判定 → target-typed による型決定</li>
</ul>
<p>という不整合は起こすけどしょうがなく、このルールで実装するとのこと。</p>
<p>ちなみに、こういう特殊な実装をしてもなお、<code>M(b ? 1 : 2, 1);</code> みたいなメソッド呼び出しに対して破壊的変更になる可能性は残っているけども、これくらいなら許容範囲だろうということで破壊的変更を認める方向だそうです。</p>
<h2>Records のロードマップ</h2>
<p>最近何度か書いてますが(例えば <a href="https://ufcpp.net/blog/2020/2/pickuproslyn0203/">2/3 のブログ</a>)、
Records として検討されている機能は結構たくさんあります。</p>
<p>パターン マッチング同様、最終形を意識しつつも段階的に実装して行こうということで、
何を優先的に実装するかの検討に入ったみたいです。
現状、以下のような順序。</p>
<p>今取り組む(= C# 9.0 時点で入る):</p>
<ul>
<li>
nominal だけ
<ul>
<li>要するに、init-only プロパティだけまず実装して、プライマリ コンストラクターは入らない</li>
</ul>
</li>
<li>派生は認めない(<code>object</code> からの直派生だけにする)</li>
<li><code>with</code> 式は <code>Clone</code> メソッドからの init-only プロパティの書き換えという決め打ち実装だけ認める</li>
<li>value equality はちゃんと実装する</li>
</ul>
<p>次の段階として以下のものを検討:</p>
<ul>
<li>派生</li>
<li>プライマリ コンストラクター</li>
<li><code>with</code> 式をカスタマイズできるようにする</li>
</ul>
<p>同時に要検討:</p>
<ul>
<li>ファクトリ メソッドの生成</li>
<li>validator</li>
<li>任意のプロパティを Records と同じ value quality/with 等のコード生成に含める</li>
<li>Records 外でのプライマリ コンストラクターを認めるかどうか</li>
</ul>
<p>ということで、直近(= C# 9.0)ではまず init-only プロパティってものが主役になりそうです。
(逆に、プライマリ コンストラクターはまた流れました。)
これ単体の提案ドキュメントも上がりました。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/pull/3367">Init only proposal document #3367</a></li>
</ul>
<p>内部的には <code>set</code> アクセサーに対して <code>modreq</code> (ちょっと強制力の強い属性みたいなもの)を付ける方向で実装するみたいです。</p>
<p>(C# 7.2 移行、ちょくちょくこの <code>modreq</code> ってやつの話が出てくるので、
そろそろちゃんとこの話も記事化しようかと画策中: <a href="https://github.com/ufcpp/UfcppSample/issues/295">tracking issue</a>。)</p>
 ]]></description>
				<pubDate>Sun, 19 Apr 2020 11:43:34 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 4/8</title>
				<link>http://ufcpp.net/blog/2020/4/pickuproslyn0408/</link>
				<description><![CDATA[ <p><a href="https://ufcpp.net/blog/2020/4/begginingcs9/">前回話したことの続き</a>。
<a href="https://youtu.be/JXa0JbfiYpw">ライブ配信で話したことの後半</a>。</p>
<p>C# Language Design Meetingの議事録がいくつか上がっています。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-03-23.md">March 23rd, 2020</a></li>
<li><a href="https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-03-25.md">March 25, 2020</a></li>
<li><a href="https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-03-30.md">March 30, 2020</a></li>
<li><a href="https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-04-01.md">April 1, 2020</a></li>
</ul>
<p>この前後に2月頃の議事録も一気に上がっていて、
C# 9.0 がらみのデザイン決定も大詰めなんだなぁという感じがしています。
(実装期間を考えると、デザイン決定は今の時期が最も活発。)</p>
<p>ちなみに、<a href="https://github.com/dotnet/csharplang/issues/2850">パターン マッチングの改善</a>の話とかは全然出てきませんが、
この辺りはデザインがすでに割と固まってるという話であって、立ち消えたとかではありません。</p>
<h2>トリアージ</h2>
<p>いくつか、そもそも採用するかどうかの検討。</p>
<h3>ref struct 制約</h3>
<p>今、<a href="/study/csharp/resource/refstruct/">ref 構造体</a>にはインターフェイスを実装できないわけですが、
これは、ref 構造体は <a href="/study/csharp/RmBoxing.html">box 化</a>してはいけないという制約を守るためです。</p>
<p>一方で、ジェネリック型引数に <code>ref struct</code> 制約を付けれるなら、ref 構造体がインターフェイスを実装していても box 化を避けれるんじゃないかという話が上がっています。</p>
<p>ただ、検討の結果、<code>ref struct</code> 制約は必要として、それだけでも不十分だろうとのこと。
.NET ランタイムの方にも手を入れないと安全性を確保できないし、
<a href="https://github.com/dotnet/csharplang/issues/164">Shapes</a>っていう C# 10.0 (次の次)で検討している機能とも領域が被るので、
<code>ref struct</code> 制約は 10.0 のタイミングで改めて検討しようという流れ。</p>
<h3>デリゲートのオーバーロード解決の改善</h3>
<p><a href="/study/csharp/cheatsheet/ap_ver7_3/#overload-resolution">C# 7.3 でメソッドのオーバーロード解決の改善</a>をやってるんですが、
デリゲートの場合にはこの手の解決をしてないみたいです。</p>
<p>とりあえず C# 9.0 でデリゲートに対しても同様の改善を入れたいとのこと。
あと、同じく C# 9.0 目標で作業が進んでいる<a href="https://github.com/dotnet/csharplang/blob/master/proposals/function-pointers.md">関数ポインター</a> (この後、今日のブログでも少し話題あり)でも同様のオーバーロード解決をしたいとのこと。</p>
<h3>拡張メソッドの GetEnumerator</h3>
<p>C# の <a href="/study/csharp/sp_foreach.html"><code>foreach</code></a>は <code>GetEnumerator</code> メソッドの呼び出しに展開されるわけですが、
現状だと、インスタンス メソッドしか認めていなかったりします。
<a href="https://ufcpp.net/study/csharp/misc/miscpatternbased/#index">この手の構文一覧</a>を見てもらえるとわかるんですが、新しめの構文との一貫性が取れなくなっていたりします。
(新しいほど、拡張メソッドでも OK になってる。)</p>
<p>ただ、検討に上がってなかったわけではなくて、
終始「破壊的変更になりかねないからうかつに触りたくない」という雰囲気。</p>
<p>今回もそういう姿勢です。
「破壊的変更を起こさない限りにおいて歓迎」。
(ちなみに、<a href="https://github.com/dotnet/roslyn/pull/43050">外部からの Pull Request</a> が来ているので、これに関する検討だと思います。
で、今、破壊的変更を起こしてないかの確認中。)</p>
<h2>native int</h2>
<p>前々から、いわゆる「native int」(32ビットCPU上では３２ビット、64ビットCPU上では64ビットになるような整数型)が欲しいという話があります。</p>
<p>実のところ、今でも<a href="https://docs.microsoft.com/ja-jp/dotnet/api/system.intptr"><code>IntPtr</code></a>型がそういう挙動をしているんですが、
こいつは名前通りポインター扱いなので、算術・論理演算とかを全面的には認めていなかったりします。
そこで、算術・論理演算をちゃんと認めた native int 型として <code>nint</code> と <code>nuint</code> を足す流れになっています。</p>
<p>ただ、内部的には <code>nint</code> は <code>IntPtr</code> 構造体で、<code>nuint</code> は <code>UIntPtr</code> 構造体に展開する
(似て非なる型を追加することはしない)という方向で決定済み。
破壊的変更を起こさないように、
<code>nint</code> とかのキーワードを使って宣言しているときは算術・論理演算を認めて、
そうでないときはこれまで通り認めないという、セマンティクスを見た挙動変化をします。</p>
<p>今回は、じゃあ、<code>nint</code> を LangVersion 8 以前で動かす(<code>IntPtr</code> に見える)ときにどういう挙動をすべきかという話。
まあ、普通にコンパイル エラーにすべきだろうという感じ。</p>
<p>あと、<code>nint</code> の<a href="/study/csharp/sp_const.html">定数</a>はどう扱うべきかという話も。
32ビットCPUでもちゃんと動くようにするために、以下のようにするみたいです。</p>
<ul>
<li>32ビットに収まる値は const 扱い</li>
<li>それを超える場合は readonly static 的なものに展開</li>
</ul>
<h2>target-typed new</h2>
<p>target-typed new、要するに、<code>List&lt;T&gt; x = new ();</code> みたいな書き方でコンストクター呼び出しできるようにしようという話です。</p>
<p>この構文、「ライブラリ側で新たにコンストラクターが足された時に、利用側に破壊的変更が起きる可能性がある」っていう意味ではちょっと怖いんですが。
それを言うと、今でも <code>null</code> とか <code>default</code> が似たような状態なのでしょうがないだろうと。</p>
<p><code>new ()</code> 自体は型を持っていないものの、<code>default</code> とかと同じで、ターゲットの型を見て具体的な型を決定して、その型のコンストラクターを呼びたいとのこと。
機械的にこの作業をすると、<code>enum</code> に対して <code>new ()</code> も書けてしまうことになるけども、
それは認めようという感じ。</p>
<p>あと、<a href="/study/csharp/sp2_nullable.html">null 許容値型</a>に対して <code>T? x = new ();</code> と書いたときには
<code>null</code> 扱いじゃなくて <code>new T()</code> 扱い(<code>T?</code> の元になる型(underlying type) <code>T</code> の既定値)扱いすべきだろうという話も。</p>
<p>あと、<a href="/study/csharp/sp4_dynamic.html"><code>dynamic</code></a>に関しては、
今も <code>new dynamic()</code> を認めていないんだし、<code>dynamic x = new ();</code> は認めないようです。</p>
<h2>Record</h2>
<p>Record 型周りは、<a href="/blog/2020/2/pickuproslyn0203/">以前書いたんですが</a>、
init-only プロパティというのを足す方向で議論が進んでいます。
これに対して、init-only よりも、ビルダーパターンを使った実装にしてほしいという話が出ていたのでそれを検討。
結局は、init-only で行くみたいです。</p>
<p>あと、Record 型の仕様には <code>Equals</code>や<code>GetHashCode</code>メソッドの自動実装も含まれるわけですが、どういうコードを生成すべきかというのも議題になっています。
等値比較は複雑なカスタマイズをしたい要件が結構あります。
(例えば、配列だったら <code>SequenceEquals</code> すべきかとか、
文字列だったらカルチャー配慮した比較をすべきかとか。)
まあ、Record 的には、「手書きの <code>Equals</code> があればそっちを使う」という仕様なので、
カスタマイズが必要なら手書きしてほしい。
コンパイラーが自動生成する比較はシンプルな shallow 比較にしたいとのこと。</p>
<h2>関数ポインター</h2>
<p>元々は <a href="https://github.com/dotnet/csharplang/blob/master/proposals/static-delegates.md">static delegate</a> とか言われていたやつなんですが、
今はもう、完全に「関数ポインター」扱いになっています。
ポインターという名があらわす通り、<a href="/study/csharp/sp_pinvoke.html">native 相互運用</a>向けで、<a href="/study/csharp/sp_unsafe.html">unsafe</a> な機能になります。</p>
<p>相互運用の際には呼び出し規約(引数とか戻り値を、どういう順番でどこに置くかみたいなルール)の指定が必要になるんですが、<code>cdecl</code> とか <code>stdcall</code> とか <code>fastcall</code> みたいな、今現在明確に決まっていて名前があるものだけじゃなく、
将来の規約追加にも耐えれる作りにしたいので、属性での指定もできるようにしたいとのこと。</p>
<p>あと、関数ポインター自体に属性を付けたい場合、<code>delegate* cdecl[属性]&lt;void&gt; ptr;</code> みたいな文法にするようです。</p>
<h2>プロパティ内の field キーワード</h2>
<p>以下のようなやつ。</p>
<pre class="source" title="プロパティ内の field キーワード">
<code><span class="reserved">public</span> <span class="reserved">int</span> P
{
    <span class="reserved">get</span> =&gt; <span class="reserved">field </span>;
    <span class="reserved">set</span>
    {
        <span class="method">PropertyChanged</span>();
        <span class="reserved">field </span> = <span class="reserved">value</span>;
    }
}
</code></pre>
<p>プロパティに対する<a href="/study/csharp/oo_property.html#auto_prop">バック フィールド</a>にアクセスするためのキーワードが欲しいと。</p>
<p>これ、<a href="https://github.com/dotnet/roslyn/blob/master/docs/features/source-generators.md">Source Generator</a>が入れば需要が激減するだろうし、
キーワード追加する割にはそこまで利便性が上がるわけでもないしで、
提案が出ては「今のところ取り組むつもりはない」みたいな返答を繰り返してた機能なんですが。</p>
<p>「重複提案があまりにも多い」と言って、今回ついに Design Meeting の議題に乗ったという。
ちなみに、僕が把握してる範囲でも重複 issue は20個くらいあります。
(その中の一番古い issue: <a href="https://github.com/dotnet/csharplang/issues/133">#133</a>。
「これと重複してるよ」リンクがあまりに多いので、「被リンク」通知だらけです。)</p>
<p>とはいえ、「取り組みます」と言っているわけではなくて、
「誰も取り組んでない機能の中で最も頻繁に要求が来るものであることを認めた」みたいなノリ。</p>
 ]]></description>
				<pubDate>Thu, 09 Apr 2020 09:45:42 +0900</pubDate>
			</item>
			<item>
				<title>.NET 5 Preview 2 と C# Next</title>
				<link>http://ufcpp.net/blog/2020/4/begginingcs9/</link>
				<description><![CDATA[ <p>先週末に .NET 5 Preview 2 が出ています。</p>
<ul>
<li><a href="https://devblogs.microsoft.com/dotnet/announcing-net-5-0-preview-2/">Announcing .NET 5.0 Preview 2</a></li>
</ul>
<p>昨日、これ絡みでまたライブ配信したりしてました。</p>
<div>
<iframe width="560" height="315" src="https://www.youtube.com/embed/JXa0JbfiYpw" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div>
<p>ブログ的にはあんまり長くなってもしんどいので2回に分けようかと思います。
今日は前半の話で、「ひそかに C# Next がちょっと動いてた」という話になります。</p>
<h2>.NET 5 Preview 2</h2>
<p><a href="https://devblogs.microsoft.com/dotnet/announcing-net-5-0-preview-2/">アナウンス</a>上は、Preview 1 との差分がほぼパフォーマンス改善だけになっています。</p>
<p>が、まあ、アナウンスするほどでもない細かい修正はいろいろあると思います。
ひそかに C# コンパイラーも更新されてるみたいですね。</p>
<p><a href="https://docs.microsoft.com/ja-jp/visualstudio/releases/2019/release-notes-preview">Visual Studio 16.6 の方は2週間くらい前に Preview 2 になってる</a>んですけど、
最近の C# コンパイラーは .NET SDK に同梱されているものが使われているようなので、
更新が掛かるとしたら .NET SDK の方に合わせて。
で、大体は、roslyn リポジトリ中の <a href="https://github.com/dotnet/roslyn/blob/master/docs/Language%20Feature%20Status.md">Language Feature Status</a>のページの State が Merged になっているものは動くはずなので、
物は試しにやってみたらやっぱり入ってたという感じ。</p>
<p>まあ、アナウンスに含まれないくらいなのでお察しだとは思いますが、小さな機能が3つほど追加されただけです。</p>
<h2>LangVersion preview</h2>
<p>ちなみに、まだ一応正式には「C# 9.0」とは言っていません。</p>
<p>まあ、Pull Request タイトルとかにはすでに普通に 9.0 の文字が入っていたりする
(例: <a href="https://github.com/dotnet/roslyn/issues/42368">#42368</a>)ので、
雰囲気的にはもう次のバージョンは 9.0 になるかと思いますが、正式決定ではないです。</p>
<p>なので、コンパイラー オプション的にもまだ LangVersion <code>9</code> とか <code>9.0</code> というものはない状態です。
一方で、<a href="https://ufcpp.net/study/csharp/cheatsheet/langversionoption/#langversion">LangVersion</a>に<code>preview</code>を指定すると、今日話すような新機能が使えるようになります。</p>
<p>ちなみに、この<code>preview</code>指定ができるようになったことが、7.X 世代みたいな細かいアップデートをしなくなった要因の1つだと思われます。
「新しい機能を早期に試してほしい」というのが目的だったわけで、そのためにはマイナーバージョンを積み重ねるよりも、単にpreviewチャンネルを用意する方が好ましいということなんだと思います。</p>
<p>まあ、現状、9.0 らしい機能は1つも入ってないんですが。
今入っている3つの機能は「8.0 の時に間に合わなかっただけ」みたいな感じのものです。
ちなみに、本格的に 9.0 っぽい機能が入り出すのは、<a href="https://github.com/dotnet/roslyn/milestone/67">マイルストーンを覗き見してる感じでは Visual Studio 16.7 のタイミング</a>みたいです。</p>
<h2>.NET 5 Preview 2 での C# 新機能</h2>
<p>ということで、今回入った機能は以下の3つ。</p>
<ul>
<li>Lambda discard parameters</li>
<li>Attributes on local functions</li>
<li>Skip locals init</li>
</ul>
<h3>Lambda discard parameters</h3>
<p>C# 8.0 では <a href="https://ufcpp.net/study/csharp/datatype/patterns/?p=1#discard">discard (値の破棄)</a>という機能が入ったわけですが、
これを使える場所がちょっと増えて、ラムダ式の引数でも使えるようになっています。</p>
<pre class="source" title="discard をラムダ式の引数に使う">
<code><span class="type">Func</span>&lt;<span class="reserved">int</span>, <span class="reserved">int</span>, <span class="reserved">int</span>&gt; <span class="variable">f</span> = (<span class="variable">_</span>, <span class="variable">_</span>) =&gt; 0;
</code></pre>
<p>ぱっと見ではわかりにくいかもしれませんが、2つある引数が両方同じ <code>_</code> です。
普通の変数だと <code>(x, x) =&gt; 0</code> みたいな書き方はできないんですが(名前被りはダメ)、
<code>_</code> は「一切使われない引数」という意味になって、
2か所以上の場所でも使えるようになります。
当然、一切使われないことが前提なので、<code>(_, _) =&gt; _</code> みたいなコードを書くとコンパイル エラーになります。</p>
<p>ちなみに、C# 8.0 以前のコードが壊れないように、「1引数」の場合には discard ではなく通常の変数扱いになります。
要するに、<code>_ =&gt; _</code> というコードは今まで通り合法です。</p>
<h3>Attributes on local functions</h3>
<p>これも名前通りで、ローカル関数に属性を付けれるようになります。</p>
<pre class="source" title="ローカル関数に属性を付ける">
<code><span class="reserved">static</span> <span class="reserved">void</span> <span class="method">Main</span>()
{
    [<span class="reserved">return</span>: <span class="type">NotNullIfNotNull</span>(<span class="string">&quot;s&quot;</span>)]
    <span class="reserved">int</span>? <span class="method">f</span>(<span class="reserved">string</span>? <span class="variable">s</span>) =&gt; <span class="variable">s</span>?.Length;
 
    <span class="comment">// f(null).Value だと警告が出る</span>
    <span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="method">f</span>(<span class="string">&quot;&quot;</span>).Value);
}
</code></pre>
<p>メソッドの内側に属性を書く構文がこれまでの C# にはなかったので、
<a href="https://ufcpp.net/study/csharp/functional/fun_localfunctions/#local-function">ローカル関数</a>の実装当初(C# 7.0 時点)では保留になっていました。</p>
<p>C# 8.0 で <a href="https://ufcpp.net/study/csharp/resource/nullablereferencetype/">null 許容参照型</a>が追加されたことで、ローカル関数に対しても属性を付けたいという欲求が急に膨れ上がったので、9.0 で実装することにしたみたいです。</p>
<h3>Skip locals init</h3>
<p>最後は <a href="https://ufcpp.net/study/csharp/sp_unsafe.html">unsafe</a> 限定機能です。
<a href="https://ufcpp.net/study/csharp/rm_default.html#uninitialized">値が不定になることをほとんど認めない</a> C# にしては珍しく、
初期化をさぼるための機能。
<code>SkipLocalsInit</code> という属性をメソッドに付けることで、
その中ではローカル変数の0初期化が行われなくなります。
影響があるのは <a href="https://ufcpp.net/study/csharp/sp_unsafe.html#safe-stackalloc"><code>stackalloc</code></a> を使うときくらいです。</p>
<pre class="source" title="0 初期化のスキップ">
<code><span class="reserved">void</span> <span class="method">safe</span>()
{
    <span class="type">Span</span>&lt;<span class="reserved">byte</span>&gt; <span class="variable">span</span> = <span class="reserved">stackalloc</span> <span class="reserved">byte</span>[4];
 
    <span class="comment">// 通常、 stackalloc した時点で確保した領域は 0 初期化される。</span>
    <span class="comment">// なので、以下のコードは常に 0。</span>
    <span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="variable">span</span>[0]);
}
 
<span class="comment">// unsafe 限定</span>
[System.Runtime.CompilerServices.<span class="type">SkipLocalsInit</span>]
<span class="reserved">void</span> <span class="method">skipInit</span>()
{
    <span class="type">Span</span>&lt;<span class="reserved">byte</span>&gt; <span class="variable">span</span> = <span class="reserved">stackalloc</span> <span class="reserved">byte</span>[4];
 
    <span class="comment">// SkipLocalsInit 属性を付けた場合、0 初期化を行わない。</span>
    <span class="comment">// span の中身はプログラマーが責任を持って初期化しないとダメ。</span>
    <span class="comment">// 今、初期化をさぼってしまったので、以下のコードは不定な値を表示する。</span>
    <span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="variable">span</span>[0]);
}
</code></pre>
<p>不定な値を返すというのはそれだけで安全性を脅かすので unsafe オプション必須です。</p>
<p>0初期化をさぼりたいというのはパフォーマンス改善のためです。
プログラマーが責任を持ってちゃんと初期化するのであれば、
コンパイラーが自動的に挿入する 0 初期化コードは無駄にしかならないので。
その安全性を得るためのちょっとしたペナルティすら避けたい場合にこの属性を使います。</p>
 ]]></description>
				<pubDate>Mon, 06 Apr 2020 20:30:07 +0900</pubDate>
			</item>
			<item>
				<title>.NET 5 の Target Framework と Optional SDK Workload</title>
				<link>http://ufcpp.net/blog/2020/3/net5optionalworkload/</link>
				<description><![CDATA[ <p>まだ提案ドキュメントが出たばかりな段階ですが、 .NET 5 の方向性を決めるドキュメントが2件出ています。</p>
<ul>
<li><a href="https://github.com/terrajobst/designs/blob/master/accepted/2020/net5/net5.md">Target Framework Names in .NET 5</a> (割かし最近 Merge されたて)</li>
<li><a href="https://github.com/dotnet/designs/pull/100">.NET Optional SDK Workloads</a> (Pull Request 出たて)</li>
</ul>
<p>ちなみに、Target Framework Name と言いつつ略称が TFM なのは最後が Moniker (あだ名)だからです。
.NET Core に対して <code>netcoreapp</code>、 .NET Standard に対して <code>netstandard</code> みたいな記号的な名前を振っていたわけですが、これが Moniker です。</p>
<h2>標準ライブラリ統合</h2>
<p>まず背景おさらい的な話になりますが、
紆余曲折経て、 .NET が単一系統に統合されます。</p>
<p>.NET Framework (Windows 専用)ででしかできないことはほとんどなくなり、こちらは保守モードに入って、 .NET Framework 4.8 が最終バージョンになります。</p>
<p>ランタイムとしては .NET Core 系と Xamarin (Mono)系がまだ残っていますが、
少なくとも標準ライブラリのコードは統合する方向で動いています。</p>
<p>そのため、かつて混とんを極めた Portable Class Library の頃の <code>portable-net40+sl5+win8</code> (サポートしたいターゲットを全列挙)みたいなものも、
.NET Standard (.NET Core, .NET Framework, Xamarin の最大公約数を取ったもの)みたいなものも必要なくなる予定です。</p>
<p>そこで、名称も「.NET 5」(Core も Framework も Standard も付かず、バージョン番号は 5)となりますし、
TargetFramework 名もシンプルに <code>net5.0</code> を使う予定です。</p>
<p>(提案されたばかりなので今はまだ実装されていません。
今現在出ている .NET 5 Preview 1 ではまだ <code>netcoreapp5.0</code> という TFM を使っています。)</p>
<h2>TargetFramework 名</h2>
<p>ということで、どのプラットフォームでも使える基礎的な部分を指して <code>net5.0</code> という TargetFramework を使います。
これまででいう <code>netstandard2.1</code> みたいなものが無印の <code>netX.Y</code> みたいな形式になります。</p>
<p>(.NET Framework の方では <code>.</code> を入れずに <code>net472</code> とか書いていたので、 .NET 10 が来たら(6年は先の話ですが)ちょっとだけ混乱を生みそうですが、
おそらく <code>net10</code> だけを 1.0 使いする特殊処理(10にしたければ <code>net10.0</code> と書かないとダメ)が入りそうです。)</p>
<p>一方で、 .NET Core 3.1 でも WPF や Windows Forms は Windows 限定の機能ですし、
Xamarin を統合するということは Android 限定機能や iOS 限定機能が入ることになります。</p>
<p>これら特定プラットフォーム限定機能向けに、<code>net5.0-android</code>, <code>net5.0-ios</code>, <code>net5.0-windows</code> みたいな TargetFramwork 名を与えるみたいです。
ちゃんと <code>-</code> の前後で分離して解釈するそうで、例えば、<code>net5.0</code> (.NET 5.0 汎用)なライブラリを、<code>net6.0-android</code> (.NET 6.0 + Android 限定機能)から参照できます。
さすがに。PCL の時のようにはならないように。</p>
<p>ちなみに、<code>-</code> の後ろのプラットフォーム名の方にもバージョン番号を指定できるそうです。
例えば、<code>net5.0-ios14.0</code> みたいな書き方で「 .NET 5.0 で、 iOS のバージョン 14.0」という意味になります。
プラットフォームの方のバージョンがないときは「その .NET がサポートしているもっとも低いバージョン」扱いになるみたいです。</p>
<h2>Optional SDK Workload</h2>
<p>.NET SDK も分割したいようです。
今でも、「コンソール アプリしか使わないのに」、「WPF しか使わないのに」、「ASP.NET しか使わないのに」みたいに思うことは多いと思います。
ここに Xamarin.Android や Xamarin.iOS も加わるわけで、そろそろ、必要な分だけを追加インストールする仕組みが欲しい段階です。</p>
<p>ということで、特定プラットフォーム向けの SDK 機能を workload と呼んでいて、
workload は optional (オプション指定しない限りインストールされない)な状態にしたいそうです。</p>
<p>さすがに時代的に、最初からゴールとして「できる限り CI/CD フレンドリーにしたい」というものが含まれています。
「使う分だけインストールすればいい」というサイズ削減の意味でも分けた方が CI/CD 的にやさしいですし、
インストールをできる限り簡単にしたいという目標もあるみたいです。
最終的には、<code>dotnet bundle install [bundle name]</code> とか、<code>dotnet bundle restore [project name]</code> みたいな1コマンドで Optional SDK Workload をインストールできるようにしたいそうです。
(同様の仕組みは workload よりも広い用途に使えるかもしれないので、サブコマンド名はより広い名前、まだ決めかねてるそうですが仮に bundle と呼んでいます。)</p>
<p>ここで、<code>dotnet bundle restore</code> の方は、前節で説明したような TargetFramework を見て、
例えば、<code>net5.0-android</code> なら Android 向けの、<code>net5.0-ios</code> なら iOS 向けの workload (bundle)の復元できるようにしたいそうです。</p>
<p>要は、今現在、ライブラリ参照のために NuGet を使ってやっているのと同程度の手軽さで、SDK workload の参照ができるようにしたいそうです。</p>
<h3>.NET 5 次点での目標</h3>
<p>.NET 5 次点では、
workload のインストールは Visual Studio (for Windows と for Mac)でだけになるかもとのこと。
<code>dotnet bundle restore</code> みたいなコマンドは一部分だけ。</p>
<p>また、 .NET 5 から追加されることになる Xamarin 系統(要するに Android、iOS、Web Assembly など)の workload が Optional 提供になる予定です。
(まだこの時点では ASP.NET や WPF などの分離作業は手付かず。)</p>
<h3>もっと先の目標</h3>
<p>最終的には、
<code>dotnet</code> コマンドラインツールのフル機能を提供したいし、
apt-get などの Linux 向けインストール ツールの類を使った workload インストールができるようにもしたいみたいです。</p>
<p>また、 .NET Core 3.1 次点ではモノリシックな SDK 提供になってしまっている ASP.NET や WPF、Windows Forms などの workload も Optional 提供に変更したいそうです。</p>
 ]]></description>
				<pubDate>Wed, 25 Mar 2020 23:03:08 +0900</pubDate>
			</item>
			<item>
				<title>.NET 5 Preview 1 / VS 16.6 Preview 1 公開記念</title>
				<link>http://ufcpp.net/blog/2020/3/net5p1/</link>
				<description><![CDATA[ <p>.NET 5 Preview 1 や、Visual Studio 16.5 正式版、Visual Studio 16.6 Preview 1 がアナウンスされました。</p>
<ul>
<li><a href="https://devblogs.microsoft.com/dotnet/announcing-net-5-0-preview-1/">Announcing .NET 5 Preview 1</a></li>
<li>
Visual Studio Release Note(相変わらず ja-jp ページは古そうなので、en-us にリンク)
<ul>
<li><a href="https://docs.microsoft.com/en-us/visualstudio/releases/2019/release-notes#16.5.0">16.5</a></li>
<li><a href="https://docs.microsoft.com/en-us/visualstudio/releases/2019/release-notes-preview#16.6.0-pre.1.0">16.6 Preview 1</a></li>
</ul>
</li>
</ul>
<p>最近、ブログだと、C# 関連に絞って書いていて、
そうすると今回のアナウンスに関しては別に大して書くことはないんですけども。</p>
<p>今回から、ちょっと動画配信してみることにしました。</p>
<div>
<iframe width="560" height="315" src="https://www.youtube.com/embed/a5Qs7u6CoqM" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div>
<h2>C# 8.0 fix</h2>
<p>ちなみに、アナウンスや Release Note 上は全く触れられていませんが、C# 8.0 にサイレントに修正が入っているはず。
昔、Gist に上げてあった以下のような修正が入っています。</p>
<ul>
<li><a href="https://gist.github.com/ufcpp/5dde1abd877c16c0e8f45e02c3858fe7">16.5 で修正される null 許容参照型がらみの問題</a></li>
</ul>
<p>Roslyn チームの中の人が「16.5 では間に合わなくて 16.6 になるよ」みたいなことをツイートしていた気もするんですけど、16.5 の方でも警告が消えていました。
ちゃんと確認できていなくて自信はないんですが、もしかしたらもうちょっと前から治っていたかもしれません。
16.6 Preview 1 を入れたことで .NET Core SDK が更新されて、それで治ったとかもあるかもしれません(未確認)。</p>
<h2>動画配信</h2>
<p>さて、ブログとしては以上。</p>
<p>Visual Studio の新しいリファクタリング機能とか、スクショぽとぺたブログを書くのもしんどいんですよね。
その点に関しては昨日、動画配信をやってよかったかなと思っています。
まあ、配信に使ったアプリ(<a href="https://obsproject.com/ja">OBS</a>)が、右クリック メニューとか Quick Action の電球アイコンとかリファクタリング結果のプレビューとか、ポップアップする UI を移してくれなくてちょっと困っていますが…</p>
<p>動画配信はまだまだ黙々と環境を整えたりしている真っ最中で、
昨日も少々見切り発車な感じはあります。
とはいえ、こういうのは見切り発車であっても取り合えず始めてしまうことが大事なタイミングがありまして、うちの場合はそれが昨日の「Preview 1」かなと思って急ぎ配信することにしました。
「動画配信も Preview 1 だ」とか言っちゃえる年に1度のタイミングですからね。</p>
<p>動画配信に関しても「High-Level Goals」みたいなものはあるんですが、
その辺りはまた日を改めて話すと思います。</p>
 ]]></description>
				<pubDate>Wed, 18 Mar 2020 09:38:17 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 2/3: Records総まとめ、トップ レベル ステートメント</title>
				<link>http://ufcpp.net/blog/2020/2/pickuproslyn0203/</link>
				<description><![CDATA[ <p>2件ほど。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/3117">Top-level statements and functions #3117</a></li>
<li><a href="https://github.com/dotnet/csharplang/issues/3137">Records as a collection of features #3137</a></li>
</ul>
<p>どちらも、散発的にアイディアが出てたもののまとめであるとか、現状報告的なものです。</p>
<h2>Top-level statements and functions</h2>
<p>まず短い方から。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/3117">Top-level statements and functions #3117</a></li>
</ul>
<p>前々から、<a href="https://github.com/dotnet/csharplang/issues/2765">普通の C# の文法と、スクリプト向けの文法を統合したい</a>みたいな話はって、それの再考というか、
シナリオの整理とどのシナリオを優先するかみたいな話。</p>
<p>ちなみに、まだマイルストーンも決まっていないので、おそらく C# 9.0 よりは先の話になると思います。</p>
<p>要は、以下のような「いつものおまじない」なしでいきなり(トップレベル、あるいは、名前空間直下のレベルに)ステートメントとかメソッドを書きたいという話になります。</p>
<pre class="source" title="いつものおまじない">
<code><span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> Main()
    {
    }
}
</code></pre>
<p>主たる目的として3つのシナリオが上がっています。</p>
<p>1つ目は単にプログラムをシンプルに書きたいというもの。
普通に「おまじない」でボイラープレートなコードを減らしたい。
この意味では、トップレベルに書いたコードは <code>Program.Main</code> メソッドの中に自動的に組み込まれてほしい。</p>
<p>2つ目はグローバル関数的なものを定義したいという話。
<code>Math.Sin</code> みたいなものは元々「グローバルでも特に問題はないけど、名前の衝突を避けるために <code>Math</code> クラス配下にまとめらている」みたいなものです。
単に名前分けなら、名前空間直下に関数を書けても別にいいはず。
この意味では、何かラッパークラスを1個作って、その中の静的メソッドに変換して、自動的に  <a href="/study/csharp/sp_namespace.html"><code>using</code></a> される扱いすればいい。</p>
<p>3つ目はスクリプト用途。
今現在、<a href="https://www.nuget.org/packages/Microsoft.CodeAnalysis.CSharp.Scripting/">Microsoft.CodeAnalysis.CSharp.Scripting</a>で提供されているやつで、微妙に<a href="https://ufcpp.net/study/csharp/cheatsheet/apscripting/">通常の C# 文法と違う文法</a>を受け付けます。
通常の文法と統合したいといいつつ、1つ目のシナリオとは競合します。
スクリプトの場合、実行するたびに別の状態を持たせたく、静的な <code>Main</code> メソッド内に展開されるような方式よりは、クラスを1個作ってそのメンバー扱い(ローカル変数のように書いたものが、実際にはフィールド扱い)する方が好ましかったりします。</p>
<p>今回の決定では、1つ目のシナリオ、要するに「トップレベルのステートメントを <code>Main</code> メソッドに自動的に組み込む」という方向で行きたいとのこと。
トップレベルのメソッドも、<code>Main</code> メソッド内のローカル関数扱いしようという感じみたいです。</p>
<p>結局、「通常モード」と「スクリプト モード」の統合はあきらめていて、
「2つのモードの差をあまり開かないようにしたい」くらいの方針。</p>
<h2>Records as a collection of features</h2>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/3137">Records as a collection of features #3137</a></li>
</ul>
<p>ここ数か月くらい散発的には話題に上がっていましたが(<a href="/blog/2019/10/pickuproslyn1025/">10/25</a>、<a href="/blog/2019/11/pickuprolsyn1116/">11/16</a>、<a href="/blog/2019/12/pickuproslyn1221/">12/21</a>)、Records がらみの総まとめ。</p>
<p>こちらは C# 9.0 向け。なのでそろそろ具体性を帯びてきています。</p>
<p>まだ全部の提案に Strawman (藁人形。C# リポジトリ内では「いろいろ叩かれることを前提に、まずは C# チーム内で決めた案を公開」くらいの意味)という言葉が入っているので最終決定からはまだ遠い段階ですが、今までの中では一番まとまっていて、一番具体的な文法が出ています。</p>
<p>タイトルの通り、Records をいくつかの機能の組み合わせに分割したいという話なんですが、
いくつかは不可分みたいな話もしています。</p>
<h3>Value-based equality</h3>
<p>値による比較(value-based equality)を楽に書きたいという要望が常々あります。</p>
<p><a href="/blog/2019/12/pickuproslyn1221/">12/21</a>のブログでは「<code>key</code> 修飾子」案が出ていましたが、
今回は <code>value</code> 修飾子になっています。
意味的には12/21の頃と同じ。この修飾子を付けたフィールドの値比較を持って、その型の <code>Equals</code> メソッドや <code>==</code> 演算子を生成したいというものです。</p>
<h4>value members</h4>
<p>差分としては、<code>EqualityContract</code> というプロパティも生成して、以下のような比較をした方がいいだろうという話が増えています。</p>
<p>例えば以下のような <code>Point</code> クラスがあったとして</p>
<pre class="source" title="value 修飾が付いたプロパティを元に Equals を生成">
<code><span class="reserved">public</span> <span class="reserved">class</span> <span class="type">Point</span>
{
    <span class="reserved">public</span> <span class="reserved">value</span> <span class="reserved">int</span> X { <span class="reserved">get</span>; <span class="reserved">set</span>; }
    <span class="reserved">public</span> <span class="reserved">value</span> <span class="reserved">int</span> Y { <span class="reserved">get</span>; <span class="reserved">set</span>; }
}
</code></pre>
<p>以下のようなコード扱いしたいそうです。</p>
<pre class="source" title="value 修飾からの生成結果">
<code><span class="reserved">public</span> <span class="reserved">class</span> <span class="type">Point</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> X { <span class="reserved">get</span>; <span class="reserved">set</span>; }
    <span class="reserved">public</span> <span class="reserved">int</span> Y { <span class="reserved">get</span>; <span class="reserved">set</span>; }

    <span class="reserved">protected</span> <span class="reserved">virtual</span> Type EqualityContract =&gt; <span class="reserved">typeof</span>(Point);
    <span class="reserved">public</span> <span class="reserved">override</span> <span class="reserved">bool</span> Equals(<span class="reserved">object</span>? other) =&gt;
        other <span class="reserved">is</span> Point that
        &amp;&amp; <span class="reserved">this</span>.EqualityContract == that.EqualityContract
        &amp;&amp; <span class="reserved">this</span>.X == that.X
        &amp;&amp; <span class="reserved">this</span>.Y == that.Y;
    <span class="reserved">public</span> <span class="reserved">override</span> <span class="reserved">int</span> GetHashCode() =&gt; ... X ... Y ... ;
}
</code></pre>
<p><code>EqualityContract</code> プロパティを用意しているのは、
対称性の確保のため。
このプロパティがないと、基底クラスのインスタンス <code>b</code> と派生クラスのインスタンス <code>d</code> があるとき、<code>b.Equals(d)</code> は true だけど <code>d.Equals(b)</code> は false みたいなことがあり得ます。</p>
<p>単に <code>GetType()</code> メソッドで型判定しないのは、
以下のような、追加のメンバーを持っていない派生クラスは互いに一致判定できるようにです。</p>
<pre class="source" title="派生クラスの一致">
<code><span class="reserved">class</span> <span class="type">Base</span>
{
    <span class="reserved">public</span> <span class="reserved">value</span> <span class="reserved">int</span> Id { <span class="reserved">get</span>; }
}

<span class="comment">// 以下の2つの型は特に追加で value 修飾の付いたメンバーを持っていないので、</span>
<span class="comment">// Id さえ一致していれば互いに Equals 判定できる。</span>
<span class="comment">// EqualityContract はどちらも typeof(Base) を返す。</span>
<span class="reserved">class</span> <span class="type">Derived1</span> : Base { }
<span class="reserved">class</span> <span class="type">Derived2</span> : Base { }
</code></pre>
<h4>value types</h4>
<p>また、<code>value class Point</code> みたいに型自体に value 修飾を付けることで、全メンバーに value 修飾を付けたのと同じ扱いにするという話も。</p>
<p>上記 <code>Derived1</code> と <code>Derived2</code> を、「<code>Id</code> が同じでも型が違えば <code>Equals</code> は false にしてほしい」(ようするに discriminated union 的な挙動)にしたいときはそれぞれ <code>value class Derived1</code>、<code>value class Derived2</code> と書く(逆に、true にしたいときは value 修飾を付けない)という話もあります。</p>
<h3>Removing construction boilerplate</h3>
<p>長らく、以下のようなコードの冗長性が嫌だという話がずっと言われ続けています。</p>
<pre class="source" title="冗長なコード">
<code><span class="comment">// プロパティ、コンストラクター引数、代入の左右の4か所で同じ名前を書くのが冗長</span>
<span class="reserved">public</span> <span class="reserved">abstract</span> <span class="reserved">class</span> <span class="type">Person</span>
{
    <span class="reserved">public</span> <span class="reserved">string</span> Name { <span class="reserved">get</span>; }
    <span class="reserved">public</span> <span class="type">Person</span>(<span class="reserved">string</span> name)
    {
        Name = name;
    }
}
</code></pre>
<p>これを、最終的には <code>class Person(string Name);</code> くらいまで縮めたいというのが Records の肝なんですが、これも、いくつかの段階に分けて考えようとしているみたいです。</p>
<h4>direct constructor parameters</h4>
<p>まず、direct constructor parameters という案。
以下のように、コンストラクター引数に対応するプロパティだけを書くという方式。</p>
<pre class="source" title="direct constructor parameters">
<code><span class="reserved">public</span> <span class="reserved">abstract</span> <span class="reserved">class</span> <span class="type">Person</span>
{
    <span class="reserved">public</span> <span class="reserved">string</span> Name { <span class="reserved">get</span>; }
    <span class="reserved">public</span> <span class="type">Person</span>(Name) <span class="comment">// 型名なしで、プロパティ名だけ指定</span>
    {
        <span class="comment">// this.Name = Name 的なコードが追加される</span>
 
        <span class="comment">// 追加で、値の検証コードとか書くのは自由にできる</span>
        <span class="control">if</span> (Name <span class="reserved">is</span> <span class="reserved">null</span>) <span class="control">throw</span> <span class="reserved">new</span> <span class="type">ArgumentNullException</span>(<span class="reserved">nameof</span>(Name));
    }
}
</code></pre>
<h4>primary constructors</h4>
<p>次が primary constructors で、以下のように、クラス宣言の行に直接引数を書けるようにするもの。
検証コードの類は「<code>()</code> なしのコンストラクター」みたいな構文が提案されています。</p>
<pre class="source" title="primary constructors">
<code><span class="reserved">public</span> <span class="reserved">abstract</span> <span class="reserved">class</span> <span class="type">Person</span>(<span class="reserved">string</span> name)
{
    <span class="reserved">public</span> <span class="reserved">string</span> Name { <span class="reserved">get</span>; } = name;
 
    <span class="reserved">public</span> <span class="type">Person</span> <span class="comment">// () なしのコンストラクター構文</span>
    {
        <span class="comment">// primary constructor に対する検証コードはここに書く</span>
        <span class="reserved">if</span> (name <span class="reserved">is</span> <span class="reserved">null</span>) <span class="reserved">throw</span> <span class="reserved">new</span> <span class="type">ArgumentNullException</span>(<span class="reserved">nameof</span>(Name));
    }
}
</code></pre>
<p>primary constructors は先ほどの direct constructor parameters と相乗効果あり。</p>
<pre class="source" title="primary constructors + direct constructor parameters">
<code><span class="reserved">public</span> <span class="reserved">abstract</span> <span class="reserved">class</span> <span class="type">Person</span>(Name) <span class="comment">// primary constructors + direct constructor parameters</span>
{
    <span class="reserved">public</span> <span class="reserved">string</span> Name { <span class="reserved">get</span>; }
 
    <span class="reserved">public</span> <span class="type">Person</span>
    {
        <span class="reserved">if</span> (Name <span class="reserved">is</span> <span class="reserved">null</span>) <span class="reserved">throw</span> <span class="reserved">new</span> <span class="type">ArgumentNullException</span>(<span class="reserved">nameof</span>(Name));
    }
}
</code></pre>
<h4>primary constructor member declarations</h4>
<p>プロパティと direct constructor parameters の重複も避けたいということで、さらに踏み込んだ文法として primary constructor member declarations があります。
primary constructor の引数の部分に直接メンバー宣言を書いてしまうもの。</p>
<pre class="source" title="direct constructor parameters">
<code><span class="reserved">public</span> <span class="reserved">abstract</span> <span class="reserved">class</span> <span class="type">Person</span>(<span class="reserved">public</span> <span class="reserved">string</span> Name { <span class="reserved">get</span>; });
</code></pre>
<h3>Improvements for object inititalizers</h3>
<p><code>new Point { X = 1, Y = 2 }</code> みたいな初期化の方法を<a href="/study/csharp/oo_construct.html#member_initializer">オブジェクト初期化子</a>と呼びます。
ただ、現状だと mutable なフィールド、もしくは、プロパティにしか使えないので、
immutable が重宝されるこのご時世にはつらいと言われています。
それに対する改善案がいくつか。</p>
<h4>Strawman: Init-only properties</h4>
<p>オブジェクト初期化子では書き換えられるけど、それ以外の場所では書き換え不能という意味で、set の代わりに init アクセサーを持つプロパティ(init-only properties)を認めようというもの。</p>
<pre class="source" title="init アクセサー">
<code><span class="reserved">public</span> <span class="reserved">class</span> <span class="type">Point</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> X { <span class="reserved">get</span>; <span class="reserved">init</span>; }
    <span class="reserved">public</span> <span class="reserved">int</span> Y { <span class="reserved">get</span>; <span class="reserved">init</span>; }
}
 
<span class="reserved">var</span> p = <span class="reserved">new</span> <span class="type">Point</span> { X = 5, Y = 3 }; <span class="comment">// OK</span>
p.Y = 7; <span class="comment">// エラー。初期化子以外での Y の書き換えは認めない</span>
</code></pre>
<h4>validation accessors for auto-properties</h4>
<p>「get だけ<a href="/study/csharp/oo_property.html#auto">自動実装</a>して、set 内の検証コードは普通に書きたい」ということがあるので、それを認めようかという話。</p>
<pre class="source" title="validation accessors">
<code><span class="reserved">public</span> <span class="reserved">string</span> Name
{
    <span class="comment">// get の実装を省略</span>
    <span class="reserved">get</span>;
 
    <span class="comment">// set には検証コードだけ書く</span>
    <span class="reserved">set</span> { <span class="control">if</span> (<span class="reserved">value</span> <span class="reserved">is</span> <span class="reserved">null</span>) <span class="control">throw</span> <span class="reserved">new</span> <span class="type">ArgumentNullException</span>(<span class="reserved">nameof</span>(Name)); }
}
</code></pre>
<p>前述の init アクセサーでも同様。</p>
<h4>object initializers for direct constructor parameters</h4>
<p>前節の direct constructor parameters を持っている場合には、
オブジェクト初期化子の構文(<code>new Point { X = 1, Y = 2 }</code> みたいなの)をコンストラクター呼び出し(<code>new Point(1, 2)</code>)に置換しようかという案。</p>
<p><a href="/study/csharp/sp3_inference.html#implicit">匿名型</a>に対してはこういう類の変換をすることで immutable を実現しているので、匿名型と名前付きの型の不整合をなくそうという話になります。</p>
<h3>Non-destructive mutation and data classes</h3>
<p>immutable な型のインスタンスに対して、非破壊な書き換え(non-destructive mutation)、すなわち、「コピーを作って一部のメンバーだけ書き換えたインスタンスを作りたい」ということが結構あります。
これに対して、以下のような with 構文を導入したいという話は前々からありました。</p>
<pre class="source" title="with 構文">
<code><span class="reserved">var</span> <span class="variable">p2</span> = p1 <span class="reserved">with</span> { X = 4 };
</code></pre>
<p>問題は、この with 構文をどう解釈(どうコード生成)すべきかという点です。</p>
<h4>withers through virtual factories</h4>
<p>with は、以下のような <code>With</code> メソッドとそれの呼び出しに展開しようという案になっています。
<code>With</code> メソッドの生成トリガーにするために、クラスには data 修飾を求めようという話も。</p>
<pre class="source" title="With メソッドの生成元には data 修飾を付ける">
<code><span class="reserved">public</span> <span class="reserved">data</span> <span class="reserved">class</span> <span class="type">Point</span>(X, Y)
{
    <span class="reserved">public</span> <span class="reserved">int</span> X { <span class="reserved">get</span>; }
    <span class="reserved">public</span> <span class="reserved">int</span> Y { <span class="reserved">get</span>; }
}
<span class="reserved">var</span> p2 = p1 <span class="reserved">with</span> { Y = 2 };
</code></pre>
<p>以下のように展開されます。</p>
<pre class="source" title="data class, with 構文の展開結果">
<code><span class="reserved">public</span> <span class="reserved">class</span> <span class="type">Point</span>(X, Y)
{
    <span class="reserved">public</span> <span class="reserved">int</span> X { <span class="reserved">get</span>; }
    <span class="reserved">public</span> <span class="reserved">int</span> Y { <span class="reserved">get</span>; }
 
    <span class="reserved">public</span> <span class="reserved">virtual</span> <span class="type">Point</span> <span class="method">With</span>(<span class="reserved">int</span> <span class="variable">X</span>, <span class="reserved">int</span> <span class="variable">Y</span>) =&gt; <span class="reserved">new</span> <span class="type">Point</span>(<span class="variable">X</span>, <span class="variable">Y</span>);
}
<span class="reserved">var</span> p2 = p1.<span class="method">With</span>(p1.X, 2);
</code></pre>
<p>この案では、どのプロパティがどのコンストラクター引数と対応しているのかがわかっていないといけないので、data class には前述の primary constructor が必須みたいです。</p>
<p>virtual なファクトリ メソッドを必要とするのは、以下のように、派生型のメンバーのコピーがちゃんと働くようにするためです。</p>
<pre class="source" title="data class の派生">
<code><span class="reserved">public</span> <span class="reserved">data</span> <span class="reserved">class</span> <span class="type">Person</span>(Name)
{
    <span class="reserved">public</span> <span class="reserved">string</span> Name { <span class="reserved">get</span>; }
}
<span class="reserved">public</span> <span class="reserved">data</span> <span class="reserved">class</span> <span class="type">Student</span>(ID) : <span class="type">Person</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> ID { <span class="reserved">get</span>; }
}
</code></pre>
<p>以下のように展開されます。</p>
<pre class="source" title="data class の派生の展開結果">
<code><span class="reserved">public</span> <span class="reserved">abstract</span> <span class="reserved">class</span> <span class="type">Person</span>(Name)
{
    <span class="reserved">public</span> <span class="reserved">string</span> Name { <span class="reserved">get</span>; }
    <span class="reserved">public</span> <span class="reserved">virtual</span> <span class="type">Person</span> <span class="method">With</span>(<span class="reserved">string</span> <span class="variable">Name</span>) =&gt; <span class="reserved">new</span> <span class="type">Person</span>()
}
<span class="reserved">public</span> <span class="reserved">class</span> <span class="type">Student</span>(ID) : <span class="type">Person</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> ID { <span class="reserved">get</span>; }
 
    <span class="reserved">public</span> <span class="reserved">sealed</span> <span class="reserved">override</span> <span class="type">Person</span> <span class="method">With</span>(<span class="reserved">string</span> <span class="variable">Name</span>) =&gt; <span class="method">With</span>(<span class="variable">Name</span>, <span class="reserved">this</span>.ID);
    <span class="reserved">public</span> <span class="reserved">virtual</span> <span class="type">Student</span> <span class="method">With</span>(<span class="reserved">string</span> <span class="variable">Name</span>, <span class="reserved">int</span> <span class="variable">ID</span>) =&gt; <span class="reserved">new</span> <span class="type">Student</span>(<span class="variable">Name</span>, <span class="variable">ID</span>);
}
</code></pre>
<h4>Auto-generated deconstructors</h4>
<p>data class では「どのプロパティがどのコンストラクター引数と対応しているのかがわかっていないといけない」、「primary constructor 必須」なので、
だったら<a href="/study/csharp/datatype/deconstruction/">分解</a>用の <code>Deconstruct</code> メソッドも(プロパティと引数の結び付け、コンストラクターの逆パターンなので)自動生成できる状況になります。</p>
<p><code>With</code> メソッドだけ、<code>Deconstruct</code> メソッドだけをそれぞれ別々に生成したいという要件はあまり重い浮かばず、「data 修飾を付ければ <code>With</code> も <code>Deconstruct</code> も生成」でいいだろうというような雰囲気。</p>
<h4>Abbreviated data members</h4>
<p>with 構文に data 修飾と primary constructor の引数が必須なのであれば、
data class はもう常に前述の「primary constructor member declarations」的な挙動をするという扱いでよさそうです。</p>
<p>要するに、以下のような書き方で、</p>
<pre class="source" title="data class + primary constructor member declarations">
<code><span class="reserved">public</span> <span class="reserved">data</span> <span class="reserved">class</span> <span class="type">Point</span>(<span class="reserved">int</span> X, <span class="reserved">int</span> Y);
</code></pre>
<p>プロパティ <code>public int X { get; }</code> と <code>public int Y { get; }</code> を生成したいという話に。</p>
<h3>data classes as value classes</h3>
<p>value 修飾(値による比較、<code>Equals</code> の生成が目的)と data 修飾(非破壊な書き換え、<code>With</code>/<code>Deconstruct</code> の生成が目的)の2つの案が出たわけですが、割と似て非なる感があります。ただ、必ずしも同じではない。</p>
<p>とはいえ、data と value の2個の修飾子を常に両方書かないといけないというのが快適化というと微妙な感じ。</p>
<p>ただ、「value class は常に data class か」と言われるとおそらく違います。
data class の方が「primary constructor 必須」とかの制約が強くて、
値による比較だけが欲しくて使いにくいという場面は十分想定されます。
with 構文が求めている「インスタンスのコピー」自体を禁止したい場合もあると思います。</p>
<p>逆に、「data class は常に value class か」の方はたぶんその方が都合がよさそうです。</p>
<h3>結論</h3>
<p>Records がらみを小さな機能の集まりに分けたいという話でいろいろと検討していますが、
結局、いくつかの機能は不可分(data class には primary constructor が必須だったり、<code>With</code> 生成と <code>Deconstruct</code> 生成は常にセットだったり)なところはあります。
それでも、抜き出せる部分はちゃんと抜き出して個別の機能としたいし、特に、値による比較(value class)は個別に切り出すことが有用そうです。</p>
<p>まだ詳細を詰めないといけない部分は残っていますが、今回挙げた案で Records として求めらているものは大筋実現できそうな感じにはなっていると思います。</p>
 ]]></description>
				<pubDate>Mon, 03 Feb 2020 21:29:57 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 1/13: null 許容参照型改善、式ブロック</title>
				<link>http://ufcpp.net/blog/2020/1/pickuproslyn0113/</link>
				<description><![CDATA[ <p>1件、Design Note 追加。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-01-06.md">C# Language Design Meeting for Jan. 6, 2020</a></li>
</ul>
<p>C# 9.0 に向けた <a href="/study/csharp/resource/nullablereferencetype/">null 許容参照型</a>の改善と、「式ブロック」の話。</p>
<h2>null 許容参照型</h2>
<h3>属性のメソッド内への適用</h3>
<p>C# 8.0 だと、以下のような感じのコードの null 警告は <a href="/study/csharp/resource/nullablereferencetype/?p=3#null-forgiving"><code>!</code> 演算子</a> で無視する以外に消す方法がありません。</p>
<pre class="source" title="属性がメソッド内に効いてない">
<code><span class="reserved">bool</span> <span class="method">TryGetValue</span>&lt;<span class="type">T</span>&gt;([<span class="type">NotNullWhen</span>(<span class="reserved">true</span>)]<span class="reserved">out</span> <span class="type">T</span> <span class="variable">t</span>) <span class="reserved">where</span> <span class="type">T</span>: <span class="reserved">class</span>
{
    <span class="variable">t</span> = <span class="warning"><span class="reserved">null</span></span>; <span class="comment">// 今、警告が出る</span>
    <span class="control">return</span> <span class="reserved">false</span>;
}
[<span class="reserved">return</span>: <span class="type">MaybeNull</span>]
<span class="type">T</span> <span class="method">GetFirstOrDefault</span>&lt;<span class="type">T</span>&gt;() <span class="reserved">where</span> <span class="type">T</span> : <span class="reserved">class</span>
{
    <span class="control">return</span> <span class="warning"><span class="reserved">null</span></span>; <span class="comment">// 今、警告が出る</span>
}
</code></pre>
<p>C# 8.0 ではスケジュール都合で放置(属性をメソッドの中にまで反映させるのは結構大変＆これを使う人(= ライブラリ作者側 &lt;&lt; 利用側)は少ない)されてたやつです。
機能要望どころか、バグだと思われてバグ報告がたびたび入ります(重複 issue がたくさんある)し、9.0 で再検討。
今回の Design Meeting でも「有益度合いの調査しないとね。有益そうなら実装したい」みたいな雰囲気。</p>
<h3>Task-like の変性</h3>
<p>Task-like (= 要は非同期メソッドの戻り値)の<a href="/study/csharp/sp4_variance.html">変性</a>も不便な場面がよくあります。</p>
<pre class="source" title="Task の null 許容共変性">
<code><span class="type">Task</span>&lt;<span class="reserved">string</span>&gt; <span class="method">A</span>() =&gt; <span class="type">Task</span>.<span class="method">FromResult</span>(<span class="string">&quot;&quot;</span>);
<span class="type">Task</span>&lt;<span class="reserved">string</span>?&gt; <span class="method">B</span>() =&gt; <span class="warning"><span class="method">A</span>()</span>; <span class="comment">// async/await が付いていればOKなものの、この書き方だと警告</span>
</code></pre>
<p>これも要望が多いわけですが…
というか、これに関してはそもそも <code>Task&lt;object&gt; x = new Task&lt;string&gt;();</code> 的な、(null 許容性関係ない)一般の共変性を認めてほしいという話もありましが、
そっちは「クラスの変性を認めるのは大変」ということでここではあくまで <code>?</code> の有無(null 許容性違いの変性)だけの話です。</p>
<p>Task-like (<code>Task</code> とか <code>ValueTask</code> とか、非同期メソッドの戻り値に使うもの)だけ特別扱いするのも気持ち悪い話なんですが、
特別扱いというなら今、どうもそもそも、<code>IEnumerable&lt;T&gt;</code> だけ特別扱いしているそうなので今更とのこと。</p>
<pre class="source" title="">
<code><span class="reserved">interface</span> <span class="type">I</span>&lt;<span class="reserved">in</span> <span class="type">T</span>&gt; { }
<span class="reserved">class</span> <span class="type">C</span>&lt;<span class="type">T</span>&gt; : <span class="type">I</span>&lt;<span class="type">T</span>&gt; { }
 
<span class="reserved">static</span> <span class="reserved">void</span> <span class="method">Main</span>()
{
    <span class="comment">// string は string? に代入可能</span>
    <span class="reserved">string</span> <span class="variable">s1</span> = <span class="string">&quot;&quot;</span>;
    <span class="reserved">string</span>? <span class="variable">s2</span> = <span class="variable">s1</span>;
 
    <span class="type">I</span>&lt;<span class="reserved">string</span>&gt; <span class="variable">x1</span> = <span class="reserved">new</span> <span class="type">C</span>&lt;<span class="reserved">string</span>&gt;();
    <span class="type">I</span>&lt;<span class="reserved">string</span>?&gt; <span class="variable">x2</span> = <span class="warning"><span class="variable">x1</span></span>; <span class="comment">// 一般にはここで警告。in が付いてても ? 違いの共変性はない</span>
 
    <span class="comment">// でも、IEnumerable だけは特別扱いして共変らしい</span>
    <span class="type">IEnumerable</span>&lt;<span class="reserved">string</span>&gt; <span class="variable">e1</span> = <span class="reserved">new</span> <span class="reserved">string</span>[1];
    <span class="type">IEnumerable</span>&lt;<span class="reserved">string</span>?&gt; <span class="variable">e2</span> = <span class="variable">e1</span>;
}
</code></pre>
<p>なので、Task-like を特別扱いするの自体はありだろうという雰囲気。
ただ、「オーバーロード解決とかで問題起こさないかとか要検証」という感じ。</p>
<h3>キャスト</h3>
<p>今、以下のようなコードは警告が出るようになっています。非 null 型にキャストしたければそれより前に null チェックが必須。</p>
<pre class="source" title="null チェックなしで非 null な型にキャスト">
<code><span class="reserved">static</span> <span class="reserved">void</span> <span class="method">M</span>(<span class="reserved">string</span>? <span class="variable">nullable</span>)
{
    <span class="reserved">string</span> <span class="variable">nonNull</span> = <span class="warning">(<span class="reserved">string</span>)<span class="variable">nullable</span></span>;
}
</code></pre>
<p>これも意図的にそうしてるんですが、「うっとおしいと思う場面と有益だと思う場面、どちらが多いか」ということで再検討。
例えば Roslyn (C# コンパイラー自身のコード)内では <code>(object)x == null</code> という書き方をよくするそうです。
ユーザー定義演算子を無視して確実に参照比較で null チェックしたいというもの。
ここで null 警告が出ちゃうので結構うっとおしいとのこと。
ただ、Roslyn 内では多くても、一般にこの書き方が多いかといわれるとそんなことはなくて少数派。</p>
<p>結論としては今のまま、警告は出す方向でいきたいとのこと。</p>
<h2>式ブロック</h2>
<p>前々から、式の中に書けるものを増やしたいという話はたびたびあります。
例えば、<a href="https://github.com/dotnet/csharplang/issues/973">宣言式</a> (<code>var x = F()</code> みたいな変数宣言を式中に書けるようにする話)と、
<a href="https://github.com/dotnet/csharplang/issues/377">シーケンス式</a> (<code>(var x = F(); x * x)</code> みたいな <code>;</code> 区切りで複数の式をつないで、最後の1個の値を返す)提案が出ていたりします。</p>
<p>C# 8.0 で <a href="/study/csharp/datatype/typeswitch/?p=5#switch-expression"><code>switch</code> 式</a>が入ったことで、その枝(<code>x switch { c1 =&gt; e1, _ =&gt; e2 }</code> とかの <code>e1</code>、<code>e2</code> の部分)にちょっと凝ったものを書きたいという欲求も増えたので、「<a href="https://github.com/dotnet/csharplang/issues/377">Block-bodied switch expression arms</a>」なんていう提案も出ています。</p>
<p>今回の Design Meeting では、この辺りの似て非なる提案はまとめて検討して、統合、もしくは、少なくとも一貫性のある文法を考えないとまずいだろうという話。</p>
<p>それに伴って、<code>switch</code> 式の枝に限らず式中のどこにでもステートメント(<code>if</code> とか <code>for</code> とか)を書けるようにする構文として「式ブロック」が提案されました。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/3086">Proposal: Expression blocks #3086</a></li>
</ul>
<p><code>{ var x = F(); x * x }</code> みたいに、<code>{}</code> 中の最後の1個を式にすることで、ブロック全体を「最後の式の値を返す式」にするというもの。</p>
<p>末尾のたった1個の <code>;</code> の有無で意味が変わるというのはだいぶ気持ち悪いんですが… 他に適切な記号もなさげ。</p>
<pre class="source" title="; の有無で意味が違う">
<code><span class="variable">f</span> = () =&gt; { <span class="method">F</span>(); <span class="method">G</span>(); }; <span class="comment">// block body</span>
<span class="variable">f</span> = () =&gt; { <span class="method">F</span>(); <span class="method">G</span>() };  <span class="comment">// expression body</span>
</code></pre>
<p><code>switch</code> 式の枝の方の話だけに留めるか、式ブロックの方までやるべきか、とりあえず C# 9.0 で何かしら実装する前提で調査は始めようという感じみたいです。</p>
 ]]></description>
				<pubDate>Mon, 13 Jan 2020 11:23:44 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn: C# 9.0での、パターン、records、switch、null チェックの改善</title>
				<link>http://ufcpp.net/blog/2019/12/pickuproslyn1221/</link>
				<description><![CDATA[ <p>この1週間で C# Design Notes が4件立て続けにアップロードされました。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/3032">Added: LDM Notes for Nov. 18, 2019 #3032</a></li>
<li><a href="https://github.com/dotnet/csharplang/issues/3027">Added: LDM notes for Dec. 11, 2019 #3027</a></li>
<li><a href="https://github.com/dotnet/csharplang/issues/3036">Added: LDM Notes for Dec. 16, 2019 #3036</a></li>
<li><a href="https://github.com/dotnet/csharplang/issues/3039">Added: LDM notes for Dec. 18, 2019 #3039</a></li>
</ul>
<p>あと、1件、提案ドキュメント追加:</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/pull/3035">Unconstrained type parameter annotation proposal #3035</a></li>
</ul>
<h2>Nov. 18: パターン マッチ</h2>
<p>C# 9.0 でいくつか「<a href="/study/csharp/datatype/patterns/">パターン</a>」の追加が検討されています。</p>
<ul>
<li>パターンの組み合わせ: <code>not</code>, <code>and</code>, <code>or</code> とかで、パターンの組み合わせたり条件を反転させたり</li>
<li>括弧つきパターン: <code>x is (pattern)</code> みたいなやつ。<code>and</code> とかの優先順位の明確化用(<code>x is (pattern1) and (pattern2)</code> とか)</li>
<li>関係パターン: <code>x is &lt; 3</code> みたいな感じで大小比較</li>
</ul>
<p>Nov. 18 の Design Meeting ではこの辺りに関する検討があったみたいです。</p>
<ul>
<li>
括弧つきパターンは 1-tuple (1要素のタプル パターン)と区別がつくか
<ul>
<li>1-tuple の方を <code>x is (Item1: var tupleVal)</code> みたいに名前(この例でいうと <code>Item1</code>)必須にすれば区別はつく</li>
</ul>
</li>
<li>
関係パターン
<ul>
<li>
正直、構文として `x is &gt;= 3 and &lt;= 5' みたいなのはきもい
<ul>
<li>2項演算子を単項的に使う構文になれてなさすぎる</li>
</ul>
</li>
<li>でも、<code>x is int 3..5</code> みたいな「range パターン」と違って「両端を含むかどうか」で悩む必要がない明瞭さがある</li>
<li>
ユーザー定義演算子をどうするかという問題もあり
<ul>
<li><code>x is null</code> みたいな「定数パターン」ではユーザー定義演算子は呼ばれない</li>
<li>でも、<code>x is &lt; 3</code> と <code>x &lt; 3</code> で挙動が違うのはいいのか</li>
</ul>
</li>
<li>
<code>x is &lt; 3</code> とかは暗黙的に <code>x is int i &amp;&amp; i &lt; 3</code> みたいな型チェックが含まれる
<ul>
<li><code>x is not &lt;3</code> と <code>x is &gt;= 3</code> が同じ意味にならない</li>
</ul>
</li>
</ul>
</li>
<li>
パターンの組み合わせ
<ul>
<li>今の提案では、今後、パターン中での <code>not</code>, <code>and,</code>or` がキーワードになる</li>
<li>これは既存のコードを壊す可能性がある</li>
<li>どこまでこの breaking change を許容できるものか要検討</li>
</ul>
</li>
</ul>
<h2>Dec. 11: Records</h2>
<h3>key 修飾(records の等価比較)</h3>
<p>Dec. 11 は Records がらみの検討があったみたいです。
<a href="/blog/2019/10/pickuproslyn1025/">以前も書いた通り</a>、「Records」と呼ばれる機能は独立した小さな機能に分解して実装が検討されています。
この日は、等価比較 (<code>Equals</code> メソッドや <code>==</code> 演算子)の生成に関して、<code>key</code> 修飾子を追加しようかという話です。</p>
<p>以下のように、<code>key</code> 修飾子を付けることで、そのメンバーの比較によってクラス自体の等価性を判定(する <code>Equals</code> メソッドなどを生成)しようという話。</p>
<pre class="source" title="key 修飾子">
<code><span class="reserved">class</span> <span class="type">C</span>
{
    <span class="reserved">public</span> <em><span class="reserved">key</span></em> <span class="reserved">string</span> Item1 { <span class="reserved">get</span>; }
    <span class="reserved">public</span> <span class="reserved">string</span> Item2 { <span class="reserved">get</span>; }
}
</code></pre>
<p>検討事項としては、これ単体では Records 的な機能としては足りていない(コンストラクターを書かなきゃいけないようでは「何度も同じ名前を書かないといけなくてつらい」問題の対処にならない)とか、
クラスの場合に mutable なプロパティで <code>Equals</code> を実装してしまうと <code>Dictionary</code>/<code>HashSet</code> の動作を狂わせてしまうので避けたいとか、
そういう問題にどう取り組もうかという感じ。
構文がこれでいいか(`key' を使うかとか、どうつけるかとか)は置いておいて、議題としては前向きに取り組みたいという様子。 </p>
<h3>nominal vs. positional</h3>
<p>nominal っていうのは <code>new C { Item1 = 1 }</code> みたいなやつで、positional っていうのは <code>new C(1)</code> みたいなやつのこと。
<a href="/blog/2019/8/pickuproslyn0803/">8月頃に原案が出ていたので紹介していますが</a>、
それぞれ init-only、primary constructor という提案が出ています。</p>
<p>今回はこれら再検討というか、それぞれバラバラに提供できるか、混ぜて使って使用感はどうか、
「primary constructor は既存の戦略(普通にコンストラクター呼び出し)の延長線上なのでいいが、init-only は大丈夫か」とかそういう話でした。</p>
<h2>Dec. 16: switch</h2>
<p>Dec. 16 は <code>switch</code> の改善が議題に。</p>
<p>旧来の C# の <a href="/study/csharp/st_branch.html#switch"><code>switch</code> ステートメント</a>は、C++ の影響を色濃く受けていて、使い勝手的にいまいちだとよく言われています。
それに対して、C# 8.0 では <a href="/study/csharp/datatype/typeswitch/?p=5#switch-expression"><code>switch</code> 式</a>を導入したわけですが、
C# 8.0 時点で未解決の問題として、戻り値がない場合をどうするかというものがありました。</p>
<p>単に、<code>switch</code> 式の各枝に void なものを認めようという提案も出ていましたが、「末尾に <code>;</code> が必須になるのがちょっと嫌」とのこと。</p>
<p>代わりに、2つ提案が出ています。</p>
<ul>
<li>
<a href="https://github.com/dotnet/csharplang/issues/3038">Proposal: Enhanced switch statements #3038</a>
<ul>
<li>ステートメントの方の <code>switch</code> でも、<code>=&gt;</code> を使った「枝」の簡素化(<code>case</code> ラベル撤廃＆<code>break</code> なしで OK にする)をしたい</li>
</ul>
</li>
<li>
<a href="https://github.com/dotnet/csharplang/issues/3037">Proposal: Block-bodied switch expression arms #3037</a>
<ul>
<li>式の方の <code>switch</code> で、各枝に <code>{ statement1; statement2; ... }</code> みたいな複文を認めたい</li>
</ul>
</li>
</ul>
<h3>トリアージ</h3>
<p>Dec. 16 ではその他ちょこっとトリアージがあったみたいです。</p>
<ul>
<li>
private なフィールドに対する<a href="/study/csharp/resource/rm_struct/#definite-assignment">確実な初期化</a>判定
<ul>
<li>先に warning waves (警告出すかどうかの選択権)が必要。それ以降ならいつでも</li>
</ul>
</li>
<li>
<code>catch</code> 付きの <code>try</code> ブロック内に <code>yield</code> を書けない問題
<ul>
<li>今もうこの制限がある意味はあまりない(<code>await</code> 導入時に解決済み)ので緩和したい</li>
<li>いつでも</li>
<li>やるなら合わせて<a href="/study/csharp/async/asyncstream/#async-iterator">非同期イテレーター</a>でもやる</li>
</ul>
</li>
<li>
<a href="https://github.com/dotnet/csharplang/issues/813">generic operators</a>
<ul>
<li>
<a href="/study/csharp/sp2_generics.html">ジェネリクス</a>がらみは「型推論に失敗するときでも、型の明示で解決できる」状態にあってほしい
<ul>
<li><code>M(x)</code> で型解決できない書けないときに、<code>M&lt;T&gt;(x)</code> と書けばいいみたいな</li>
</ul>
</li>
<li>演算子の場合、これに対するいい解決案が思い浮かばないのでリジェクト</li>
</ul>
</li>
<li>
引数に対する <code>nameof</code>
<ul>
<li>
引数のスコープは「メソッド内」なので、メソッドに付けてる属性中で参照できない問題がある
<ul>
<li><code>[return: NotNullIfNotNull(nameof(x)] T M(T x)</code> みたいなのが書けない</li>
</ul>
</li>
<li>認めたい。いつでも</li>
</ul>
</li>
</ul>
<h2>Dec.18: nullable issue</h2>
<p>Dec. 18 は <a href="/study/csharp/resource/nullablereferencetype/">null 許容参照型</a>がらみ。</p>
<h3>pure null チェック</h3>
<p>パターン マッチで、以下のような書き方は暗黙的に null チェックを含みます。</p>
<ul>
<li><code>x is { }</code></li>
<li><code>x is object</code></li>
</ul>
<p><code>x is null</code> や <code>x == null</code> と書くとそれ以降は「<code>x</code> は null ではない」判定が働くのに、これら <code>x is { }</code> や <code>x is object</code> などでは現状は判定が通っていません。
これらも null 判定に含めたいとのこと。</p>
<h3>var?</h3>
<p>型推論はしたいけど、null 許容性だけを変えたいということがあります。</p>
<pre class="source" title="">
<code><span class="reserved">var</span> <span class="variable">current</span> = myLinkedList.Head; <span class="comment">// 連結リストの先頭とかで、not-null 指定あり</span>
<span class="control">while</span> (<span class="variable">current</span> <span class="reserved">is</span> <span class="reserved">object</span>)
{
    ...
    <span class="variable">current</span> = <span class="variable">current</span>.Next; <span class="comment">// not-null と推論された current に null が渡る可能性あり。警告</span>
}
</code></pre>
<p>こういう時のために、<code>var?</code> という書き方を導入したらどうかという案が以前に検討されています。
それを再検討。</p>
<h2>Unconstrained type parameter annotation</h2>
<p><a href="/study/csharp/resource/nullablereferencetype/">null 許容参照型</a>で一番困るのが制約なしの<a href="/study/csharp/sp2_generics.html">ジェネリクス</a>です。
LINQ の <code>FirstOrDefault</code> みたいなやつの戻り値をどう扱うかで、そのために <code>T??</code> という記法を導入したいとのこと。</p>
<ul>
<li>ジェネリック型引数にだけ付けれる</li>
<li>
意味としては <code>default</code> を返す/受け付ける
<ul>
<li>結果、参照型に対しては null があり得て、非 null 値型には null があり得ない</li>
</ul>
</li>
</ul>
 ]]></description>
				<pubDate>Sat, 21 Dec 2019 17:21:07 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 11/16: Discriminated Union, Enhancing Common Type, Type pattern, Interpolated String Const など</title>
				<link>http://ufcpp.net/blog/2019/11/pickuprolsyn1116/</link>
				<description><![CDATA[ <p>10月末のと、今週の Desing Notes が3件ほど。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/2950">LDM notes for Oct. 30th, 2019 #2950</a></li>
<li><a href="https://github.com/dotnet/csharplang/issues/2953">LDM Notes for Nov 11, 2019</a></li>
<li><a href="https://github.com/dotnet/csharplang/issues/2968">LDM Notes for Nov. 13, 2019</a></li>
</ul>
<p>なんか結構一気に、C# 9.0向けと思われる議題が上がっています。</p>
<h2>Function pointer syntax</h2>
<p>C# で関数ポインター的なものというと<a href="/study/csharp/sp_delegate.html">デリゲート</a>なわけですけども、
こいつはクラスになっていて Managed なものです。
で、.NET の IL 仕様上は、デリゲートの他に生の関数ポインターもあったりします。
基本的にはネイティブ コードとの相互運用のためにあるもので、これまでは C# から直接使う方法はありませんでした。</p>
<p>関数ポインターを C# あらも直接触れるようにしようという話は前々から上がっていて、C# 9.0 向けの機能として作業も始まっていました。
今回は、作業を始めてみたら元々考えていた構文だと問題があったので変えたいという話です。</p>
<p>元々の案だと以下のような構文を考えていたんですが、これだと他の構文と不明瞭で、結構先までソースコードを先読みしないといけないのが負担になりすぎるとのこと。</p>
<pre class="source" title="関数ポインター(旧案)">
<code><span class="reserved">func</span>*(<span class="reserved">int</span>, <span class="reserved">int</span>)
</code></pre>
<p>なので、以下のような構文にしたいとのこと。
既存の文法では <code>*&lt;</code> が連続することがないので、これなら構文解析が楽というのが主な理由。</p>
<pre class="source" title="関数ポインター(新案)">
<code><span class="reserved">func</span>*&lt;<span class="reserved">void</span>&gt;
</code></pre>
<p>あと、この機能はネイティブ相互運用のためのものなので、関数の呼び出し規約
(引数や戻り値をメモリ上やレジスター中にどう並べて受け渡しするか)
の指定の仕方をどうするかも今回の議題に。</p>
<h2>Enhancing Common Type Specification</h2>
<p>ここでいう Common Type (共通型)っていうのは、<a href="/study/csharp/st_operator.html#condition">条件演算子</a>、<a href="/study/csharp/st_array.html#key-initializer">配列初期化子</a>、<a href="/study/csharp/datatype/typeswitch/?p=5#switch-expression">'switch` 式</a>などで、異なる型が同列に並んでいるときに、結果の型をどうするかという話です。</p>
<p>特に要望として大きいのが整数と null を混在させたときに <code>int?</code> などとして扱ってほしいというもの。</p>
<pre class="source" title="int と null の共通型">
<code><span class="comment">// 以下のいずれも int? になってほしいけど、現状はコンパイル エラーに</span>
<span class="reserved">var</span> x = b ? 1 : <span class="reserved">null</span>;
<span class="reserved">var</span> y = b <span class="reserved">switch</span> { <span class="reserved">true</span> =&gt; 1, <span class="reserved">false</span> =&gt; <span class="reserved">null</span> };
<span class="reserved">var</span> z = <span class="reserved">new</span>[] { 1, <span class="reserved">null</span> };
</code></pre>
<p>他にも、共通の基底クラスから派生している型 <code>A : Base</code> と <code>B : Base</code> があったとき、これらを並べたら <code>Base</code> として扱ってほしいという話もあります。
で、C# 9.0 では、ちゃんと 1 と null の共通型を <code>int?</code> と認識できるようにするつもりで作業が進んでいます。</p>
<p>この問題に対する解決策としては「Common Type」の他に、Target-Typed 型推論というものもあります。
C# 8.0 で入りたての <code>swtich</code> 式だけはこの Target-Typed 型推論を行っていて、たとえば以下のコードはコンパイル可能です。</p>
<pre class="source" title="switch 式の Target-Typed 型推論">
<code><span class="comment">// switch 式に限り、以下の書き方はコンパイルできる。</span>
<span class="comment">// 変数の型から推論(terget-typed 型推論)</span>
<span class="reserved">int</span>? targetTyped = b <span class="reserved">switch</span> { <span class="reserved">true</span> =&gt; 1, <span class="reserved">false</span> =&gt; <span class="reserved">null</span> };
</code></pre>
<p>で、今上がっている議題は以下のような感じ。</p>
<ul>
<li>Common Type 解決を改善するのは決定事項</li>
<li>
Target-Typed 型推論の方と衝突するけども…
<ul>
<li>Common Type 解決の方を優先したい</li>
<li>Common Type 解決に失敗した場合のフォールバックとして、条件演算子や配列初期化子にも Target-Typed 型推論を入れたい</li>
<li>
すでに Target-Typed 型推論を持っている <code>switch</code> 式は破壊的変更になる
<ul>
<li><code>switch</code> 式だけ「Target-Typed 型推論を優先して、フォールバック先を Common Type 解決にする」という選択肢もなくはないものの、それはそれで混乱のもと</li>
<li>このくらいの破壊的変更は許容したい(上記混乱よりはマシ)</li>
</ul>
</li>
</ul>
</li>
</ul>
<h2>[MaybeNull]T</h2>
<p>C# 8.0 だと、以下のようなコードを書くと null 警告が出ます。</p>
<pre class="source" title="MaybeNull が働いてない">
<code><span class="inactive">#nullable</span> <span class="inactive">enable</span>
[<span class="reserved">return</span>: MaybeNull]
T M&lt;<span class="type">T</span>&gt;() =&gt; <span class="reserved">default</span>;
</code></pre>
<p><a href="/study/csharp/resource/nullablereferencetype/?p=4#annotation-attributes"><code>MaybeNull</code> 属性</a>を付けると「たとえ非 null であるとされる型であっても null 許容に上書き」みたいな挙動になるものです。
ただ、現状、この属性は「メソッドの外向け」にしか機能していなくて、
メソッドの内側、この例でいうと <code>=&gt; default</code> の部分に対しては効力が及んでいません。</p>
<p>現状これは「仕様」なんですが、頻繁に「バグ報告」を受けています。
好ましい挙動でもないので「積みタスク」にはなっているんですが、C# 9.0 で直す方向で動いています。</p>
<p>ちなみに、構文解析上の問題じゃなくて、<a href="https://github.com/dotnet/csharplang/issues/2946">フロー解析に新しいステートを足さないとダメ</a>な模様。
<code>MaybeNullEvenIfNotNullable</code>ですって…</p>
<p>こんな感じなので、「他の属性も全部一斉に対応」ってのは実は難しいらしく、とりあえず <code>MaybeNull</code> だけ対応する(<code>NotNullIfNotNull</code> とかは 9.0 でも相変わらず <code>default</code> が警告を起こす)方向で考えるそうです。</p>
<h2>Allow interpolated string constant</h2>
<p><a href="/study/csharp/sp_const.html#const"><code>const</code></a> な文字列リテラルだけを使って<a href="/study/csharp/st_string.html#string-interpolation">文字列補間</a>をする場合、
その結果も <code>const</code> 扱いできるようにしようという話。</p>
<pre class="source" title="定数文字列補間">
<code><span class="reserved">const</span> <span class="reserved">string</span> A = <span class="string">"abc"</span>;
<span class="reserved">const</span> <span class="reserved">string</span> B = <span class="string">$"</span>{A}<span class="string">123"</span>; <span class="comment">// 今はエラーに。これを認めたい。</span>
</code></pre>
<p>ちなみに、数値の場合は書式によってはカルチャーの影響を受ける(小数点がコンマだったり、3桁区切りがピリオドだったりする言語が結構ある)ので、
<code>{}</code> 内に書けるのは <code>const string</code> だけになりそう。</p>
<h2>Type patterns</h2>
<p><a href="/study/csharp/datatype/typeswitch/#is"><code>is</code> 演算子</a> の場合は <code>x is Type</code> とか書けるのに、
<a href="/study/csharp/datatype/typeswitch/?p=5#switch-expression">'switch` 式</a> とかのパターンの場合は <code>x switch { Type =&gt; ... }</code> とは書けないのが思った以上にストレスなので「このパターン足すわ」という話。</p>
<p>今だと、<a href="/study/csharp/datatype/patterns/#declaration">宣言パターン</a>を使えば同じようなことはできます。
<code>x switch { Type _ =&gt; ... }</code> というように、型名の後ろに <a href="/study/csharp/datatype/patterns/#discard">discard</a> を付ければいいんですが、これも結構ストレスになるということで、
単に <code>Type</code> だけを書けばいい「型パターン」を追加したいとのこと。</p>
<p>今までこれができなかった理由は、型パターンと定数パターンが競合するからで、優先度を決めないといけません。
例えば以下のように、型名にも <code>X</code> があって、定数にも <code>X</code> があるとき、パターン中の <code>X</code> はどちらになるかという話。</p>
<pre class="source" title="型 X と定数 X">
<code><span class="reserved">class</span> <span class="type">X</span> { }
<span class="reserved">class</span> <span class="type">A</span>
{
    <span class="reserved">const</span> <span class="reserved">int</span> X = 0;

    <span class="reserved">int</span> M(<span class="reserved">object</span> x) =&gt; x <span class="reserved">switch</span>
    {
        X =&gt; 0,
        <span class="reserved">_</span> =&gt; 1,
    };
}
</code></pre>
<p>既存コードを壊さないようにするには以下のようにするしかなく、ちょっと残念感はあるものの、これで行くことになりそう。</p>
<ul>
<li><code>is</code> では型優先</li>
<li><code>switch</code> では定数優先</li>
</ul>
<h2>Name lookup with target type</h2>
<p>Target-Typed な推論は、型の決定だけじゃなくて、メンバー名のルックアップにも使えるんじゃないかという話。
要するに、以下のようなコードを認めるようにしようという話です。</p>
<pre class="source" title="Target-Typed なメンバー ルックアップ">
<code><span class="reserved">enum</span> <span class="type">E</span> { A, B }

<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">int</span> M(E e) =&gt; e <span class="reserved">switch</span>
    {
        A =&gt; 1, <span class="comment">// 今だと、E.A と書かないとダメ</span>
        B =&gt; 2, <span class="comment">// 同じく、E.B</span>
        <span class="reserved">_</span> =&gt; 3,
    };
}
</code></pre>
<p>enum だけじゃなくて、クラスの静的メンバーのルックアップでも同様。
特に、同じく C# 9.0 で Discriminated Union (後述)も考えているので、そのためにもこの機能は役立ちそうとのこと。</p>
<h2>Discriminated Union</h2>
<p>F# に同名の機能があるやつ。
他の言語で言うと <code>Ether</code> 型とか <a href="https://developers.google.com/protocol-buffers/docs/proto3#oneof"><code>oneof</code></a>とかがありますけど、
要するに「いくつかの型のうちのいずれか」みたいなやつです。</p>
<p>「いずれかの型」は、オブジェクト指向言語としては利便性を抜きにすれば単に「派生クラス」でできたりするんですが。</p>
<pre class="source" title="派生で「いずれか」を表現">
<code><span class="comment">// Base 型は A もしくは B のいずれかである</span>
<span class="reserved">class</span> <span class="type">Base</span> { }
<span class="reserved">class</span> <span class="type">A</span> : Base { }
<span class="reserved">class</span> <span class="type">B</span> : Base { }
</code></pre>
<p>問題は2つ</p>
<ul>
<li>単純に書くのが煩雑</li>
<li>網羅性 (A もしくは B 「だけ」を保証したい)が取れない</li>
</ul>
<p>煩雑さに関してはそもそもクラス自体が煩雑というのがあり、
その解決のために C# 9.0 で検討されているのが<a href="/blog/2019/10/pickuproslyn1025/">Records</a>になります。</p>
<p>ということで、その Records に合わせた文法で、網羅性も考慮に入れた構文として、以下のような案が出ています。
enum class ですって。</p>
<pre class="source" title="enum class">
<code><span class="reserved">enum</span> <span class="reserved">class</span> <span class="type">Shape</span>
{
    <span class="type">Rectangle</span>(<span class="reserved">float</span> Width, <span class="reserved">float</span> Length),
    <span class="type">Circle</span>(<span class="reserved">float</span> Radius),
}
</code></pre>
<p>ちなみに、以下のような感じで解釈されます。
(<code>data class</code> は Records で提案されている構文。)</p>
<pre class="source" title="enum class = 入れ子の data class">
<code><span class="reserved">partial</span> <span class="reserved">abstract</span> <span class="reserved">class</span> <span class="type">Shape</span>
{
    <span class="reserved">public data class</span> <span class="type">Rectangle</span>(<span class="reserved">float</span> Width, <span class="reserved">float</span> Length) : Shape,
    <span class="reserved">public data class</span> <span class="type">Circle</span>(<span class="reserved">float</span> Radius) : Shape
}
</code></pre>
<p>まあ、ほぼ F# の Discriminated Union 総統の機能です。</p>
<p>「構造体な Discriminated Union が欲しい」みたいな話もあって、検討には上がってるんですが、
とりあえず C# 9.0 のスケジュールではクラスだけを考えているみたいです。</p>
<p>ベースが Records なので、普通のクラスのメンバーを追加で差し込んだりもできるみたいです。</p>
 ]]></description>
				<pubDate>Sat, 16 Nov 2019 22:00:28 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 10/9: base(T), UTF-8 String, Discard parameters</title>
				<link>http://ufcpp.net/blog/2019/10/pickuproslyn1029/</link>
				<description><![CDATA[ <p>数日前、いくつかの新機能について、仕様書のドラフト案が上がっていました。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/2910">base(T) - Draft Specification #2910</a></li>
<li><a href="https://github.com/dotnet/csharplang/issues/2911">UTF8 String Literals - Draft Specification #2911</a></li>
</ul>
<p>どちらも、これまであった Design Meeting の議事録通りな感じ。</p>
<p>あと、ちょこっと変更が検討されて、結局元さやに納まったものが1件。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/111">Champion &quot;Lambda discard parameters&quot; #111</a></li>
</ul>
<h2>base(T)</h2>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/2910">base(T) - Draft Specification #2910</a></li>
</ul>
<p>これは、C# によるプログラミング入門に説明を書いた直後に「やっぱり C# 8.0 ではやめておく」となってしまったやつ。
(しょうがないんで「<a href="/study/csharp/oo_inherit.html#non-virtual-base-access">C# 8.0 から外れました</a>」って書き足してそのまま残してあったり。)</p>
<p>まあ、.NET ランタイムのレベルで対応してもらう予定だそうです。
<code>base(T).M()</code> と書いたとき、<code>T</code> 自体に <code>M</code> の実装がなくても基底クラスをたどって最初に見つかった <code>M</code> を呼んでもらえるという仕様。</p>
<h2>UTF-8 String Literals</h2>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/2911">UTF8 String Literals - Draft Specification #2911</a></li>
</ul>
<p>待望の。</p>
<p>といっても、<code>Utf8String</code> 自体についてはまだいくつか悩ましいポイントがあり…</p>
<ul>
<li>
<code>string</code> (今は UTF-16)自体を UTF-8 に切り替えるオプションがやっぱりほしい
<ul>
<li>とはいえ、インデクサー(UTF-16 での i 文字目を <code>s[i]</code> で定数時間アクセスできる)を期待しているコードが壊れる</li>
<li>unsafe に <code>fixed (char* p = s)</code> しているコードも壊れる</li>
</ul>
</li>
<li>
<code>System.String</code> に対して C# キーワードの <code>string</code> があるけど <code>Utf8String</code> に対してはどうするべきか
<ul>
<li>キーワード足さない？</li>
<li><code>ustring</code>？</li>
<li><code>utf8</code>？</li>
</ul>
</li>
<li>
クラス名自体まだ悩ましい
<ul>
<li>今回のドラフト案も冒頭に「corert 側が今のところその名前になってるのでそれに従う」との注釈がまだ必要な段階</li>
</ul>
</li>
</ul>
<p>というのもあって、C# vNext で検討されているのは本当に「手始め」という感じのものだけ。</p>
<ul>
<li>(今ある) <a href="/study/csharp/st_embeddedtype.html#charl">文字列リテラル</a>をそのまま使う</li>
<li>
以下のようなルールだけ C# に追加
<ul>
<li>文字列リテラルから <code>Utf8String</code> への暗黙の型変換を認める</li>
<li><code>Utf8String</code> は <code>const</code> にできて、それに渡せるのは <code>const</code> な文字列のみ</li>
<li><code>+</code> 演算子は <code>Utf8String.Concat</code> として解釈する</li>
</ul>
</li>
<li>
コンパイル結果としても <code>string</code> (UTF-16) のままプログラムにデータを埋め込む
<ul>
<li>読み込み時に .NET ランタイム組み込みのヘルパー関数を呼んで UTF-8 に変換する</li>
<li>将来的には直接 UTF-8 なデータをプログラムに埋め込めるように改修する可能性はあり</li>
</ul>
</li>
</ul>
<p>まあ、<code>Utf8String</code> クラスが標準ライブラリに入ってくれるだけでも随分助かりはするんですが…
既存のコードベースが <code>string</code> だらけなのがだいぶやっぱりネックになりそうな感じ。</p>
<h2>Discard parameters</h2>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/111">Champion &quot;Lambda discard parameters&quot; #111</a></li>
</ul>
<p>この issue の趣旨自体は、<code>Action&lt;T, T&gt; a = (_. _) =&gt; { };</code> みたいな書き方を認めたいというもの。
2個以上の引数が <code>_</code> の時、それは<a href="/study/csharp/cheatsheet/ap_ver7/#discard">discard</a>扱いにします。
ラムダ式の中で <code>_</code> を普通の変数のように触ろうとするとコンパイル エラー。
一方で、1引数の <code>_</code> は今現在有効は引数名として使えてしまっているので、破壊的変更を避けるために今のまま。</p>
<p>で、ここ数日で、一瞬、「ラムダ式以外、普通のメソッドの引数やローカル関数にも適用してもいいんじゃないか」というのが議題に上がりました。
でも、<a href="/study/csharp/sp4_optional.html#named">名前付き引数</a>がある以上、引数の名前は API の一部分であり、メソッドの外から見えてしまう情報になります。
そこを省略するのはあんまりお行儀がよくない。</p>
<p>なので結局、当初予定通り<a href="/study/csharp/functional/fun_localfunctions/#anonymous-function">匿名関数</a>(ラムダ式と匿名メソッド式)でだけ、<code>_</code> のdiscard扱いをしたいという結論に。</p>
 ]]></description>
				<pubDate>Tue, 29 Oct 2019 21:42:13 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 10/25: Records、Static lambdas</title>
				<link>http://ufcpp.net/blog/2019/10/pickuproslyn1025/</link>
				<description><![CDATA[ <p>Design Meeting でちょっと Records がらみの話があったみたいです。
あと、ついでのように「static ラムダ式」の話。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/2903">C# Language Design Meeting for Oct. 21</a></li>
</ul>
<h2>Records</h2>
<p>Records がらみは何か新アイディアが出たわけではなくて、直近、何から手を付けるか的な意思決定っぽいです。
<a href="https://ufcpp.net/blog/2019/8/pickuproslyn0803/">8月にブログに書いた</a>通り、元々 Records と呼ばれていた機能は今はいくつかの小さな機能に分割する流れになっています。</p>
<ul>
<li>
Automatic structural equality
<ul>
<li>「メンバーごとの等値判定」で <code>Equals</code> メソッドを自動生成</li>
<li>今出てる案では <code>data class DataType { ... }</code> みたいに <code>data</code> 修飾子を付けると <code>Equals</code> の自動生成をするようになる</li>
<li>キーワードは変更の可能性あり</li>
</ul>
</li>
<li>
With-er
<ul>
<li><code>obj with { X = newValue }</code> みたいな書き方で一部のメンバーだけ値を差し替える構文</li>
<li>「<code>with</code> で使う用の特別なコンストラクター」みたいなのを用意しておく想定</li>
</ul>
</li>
<li>
Object initializers for readonly
<ul>
<li>get-only なプロパティ <code>X</code> を <code>new DataType { X = 1 }</code> みたいな初期化子で上書きできるようにする案</li>
<li>プロパティに <code>initonly</code> 修飾を付けることでこの初期化を有効化</li>
<li>(今はコンストラクター内での初期化が必須なので、コンストラクター引数にする必要あり)</li>
<li>「初期化子を呼ぶタイミングまでは書き換え可能で、その後は読み取り専用」みたいな仕組みを追加予定</li>
</ul>
</li>
<li>
Primary constructors + deconstruction
<ul>
<li><code>class DataType(int X, int Y);</code> みたいな書き方からプロパティと、その初期化・分解(コンストラクター、<code>Deconstruct</code>メソッド)を自動生成</li>
</ul>
</li>
</ul>
<p>それぞれの機能が後々衝突しないように考えながら作らないといけないものの、
一応は個別に実装して行けるようには分割してあります。</p>
<p>いずれも、原則として、コンパイラーが自動生成しなくてもやろうと思えばユーザーが手書きできる範疇の機能にとどめたいそうです。</p>
<p>また、今回のミーティングでは、まず割かし仕様が固まってきてる primary constructors と structural equality の2つから実装していきたいという話をしています。</p>
<h3>init-only</h3>
<p>init-only (前節の Object initializers for readonly のこと)の懸念点についても軽くディスカッションがあったそうです。</p>
<p>基本的には、<code>initonly T X { get; }</code> みたいに書いたとき、実際にはプロパティ <code>X</code> に <code>set</code> も生成して、それを呼べる場所をコンストラクター内と初期化子だけに制限するという仕様。</p>
<p>懸念は以下のようなもの。</p>
<ul>
<li>
基底クラスのコンストラクターでの初期化
<ul>
<li>今のところ特にそれを禁止する理由は思い当たらない</li>
</ul>
</li>
<li>
required (初期化が必須)のメンバー
<ul>
<li>null 許容参照型があったりするわけで、未初期化(自動的に null になる)のはできれば避けたい</li>
<li>ただ、「初期化子での初期化をしていないとエラー」ってやってしまうと、後からプロパティを追加したときに既存コードを壊す</li>
<li>
特に、<code>initonly</code> は C# ソースコードのレベルでの機能になる予定で、コンパイル済みのメタデータには反映されない予定
<ul>
<li>後から required な <code>initonly</code> プロパティを足しても、以前からその型を使っているコードは未初期化のまま素通しになってしまう</li>
</ul>
</li>
</ul>
</li>
</ul>
<h2>static ラムダ式</h2>
<p>C# 8.0 で<a href="/study/csharp/functional/fun_localfunctions/#static-local-function">静的ローカル関数</a>が入ったわけですが、ラムダ式にも同じ制限が考えられます。</p>
<p><code>static</code> 修飾子を付けることで外の変数・引数をキャプチャできなくする機能で、
パフォーマンスへの配慮です。
キャプチャが発生してしまうと発生してないときよりもちょっとパフォーマンスが落ちるので、
意図せずキャプチャしてしまうことを避けるために、
キャプチャの必要がないならこの修飾子を付けておけという機能。</p>
<p>というか、C# 8.0 の時点でも「ラムダ式でも同様に」という話はあったんですが、
スケジュールの都合でお蔵入りしていました。
それが改めて検討に上がった状態。</p>
<p>検討に上がったというか、<a href="https://github.com/dotnet/roslyn/pull/39121">最近、すでにプロトタイプ実装があったり</a>。
元々ラムダ式に <code>async</code> 修飾子を付けれるわけで、追加で <code>static</code> を認めるのはそんなに難しくない様子。</p>
<p>ミーティングで出た議題としては、
<code>static</code> を付けたラムダ式は、生成結果的に静的メソッドであるべきかどうかという点。
詳しくは「<a href="/study/csharp/functional/miscdelegateinternal/">デリゲートの内部</a>」で書いたことがありますが、
実のところ、デリゲートとして使う場合、静的メソッドよりもインスタンス メソッドの方が高速だったりします。
なので、<code>static</code> を付けたラムダ式であっても、実体としてはインスタンス メソッドに「なってもよい」という余地を残す方が最適化が掛けやすいです。</p>
<p>ということで、仕様としては「<code>static</code> キーワードを付けても必ずしも静的メソッドが生成されるわけではない」ということにしておきたいそうです。</p>
 ]]></description>
				<pubDate>Fri, 25 Oct 2019 21:09:17 +0900</pubDate>
			</item>
			<item>
				<title>.NET Core 3.0 をもって .NET Framework からの移植作業は完結</title>
				<link>http://ufcpp.net/blog/2019/10/netcore3concludesfxporting/</link>
				<description><![CDATA[ <p>corefx で以下のようなアナウンスが。</p>
<ul>
<li><a href="https://github.com/dotnet/corefx/issues/41769">.NET Core 3.0 concludes the .NET Framework API porting project</a></li>
</ul>
<p><a href="https://ufcpp.net/blog/2019/5/build2019/">build</a>の時点で .NET を .NET Core ベースに一本化、.NET Framework は 4.8 をもって最後にするという話があったわけですが、
改めてというか、総括的なアナウンスです。</p>
<h2>API 数</h2>
<p>まず、.NET Framework から .NET Core に移植してきた API 数の総括。
メソッドのオーバーロード1個1個を「1 API」とカウントしてるんだともいますが、以下のような数字が書かれています。</p>
<ul>
<li>.NET Core 1.0 時点では1.8万個</li>
<li>.NET Standard 2.0 では .NET Framework、.NET Core、Xamarin の共通部分として3.8万個</li>
<li>
Windows 限定な機能も <a href="https://devblogs.microsoft.com/dotnet/announcing-the-windows-compatibility-pack-for-net-core/">Windows Compatibility Pack</a> として提供して、これが2.1万個
<ul>
<li>.NET Standard 2.0 と合わせて6万個</li>
</ul>
</li>
<li>
.NET Core 3.0 では WPF と WinForms を移植して、これが12万個
<ul>
<li>.NET Framework の API の約半分</li>
</ul>
</li>
<li>依然として6.2万個の API が未移植なものの、8割の API が移植済み</li>
</ul>
<h2>移植しないもの</h2>
<p>これも build の時点でアナウンス済みですが、AppDomain、remoting、Web Forms、WCF、Workflow は .NET Core への移植をしません。</p>
<p>この辺りはレガシー扱いで、
モダンなアプリ開発に必要なテクノロジーは .NET Core 3.0 をもって一通りそろったといえる段階に達したと判断されています。
今後はもう、レガシー移植よりも、新しいテクノロジーに開発リソースを割いていきます。</p>
<p>.NET Framework のコード自体は<a href="https://github.com/microsoft/referencesource">Microsoft .NET Reference Source</a> として MIT ライセンスで GitHub 上にあるので、
Microsoft が保守を止めてしまった部分も、コミュニティ ベースで保守していくことはできます。
(実際、<a href="https://github.com/UiPath/corewf">Core WF</a>や<a href="https://github.com/CoreWCF/CoreWCF">Core WCF</a>など、いくつかのコミュニティ プロジェクトがすでにあります。)</p>
<p>ちなみに、<a href="https://github.com/microsoft/referencesource">Reference Source</a>は本当にソースコードの公開のみで、ビルド基盤をもう保守していないので、
ビルドして動くものが欲しければ<a href="https://github.com/CoreWCF/CoreWCF">Core WCF</a>などのコミュニティ プロジェクトを参照(なければ立ち上げ)してほしいそうです。</p>
<h2>移植の要望 issue を close</h2>
<p>「このテクノロジーを移植してほしい」という要望 issue があって、
これまで「どれを優先的に移植するか」の判断材料として使ってきました。
しかし、.NET Core 3.0 をもってもう移植作業は打ち切りということで、issue も一通り close したそうです。</p>
<p>ただ、打ち切ったといってもあくまで WCF であるとか Web Forms であるとかのテクノロジー単位での話で、
例えば「移植済みのクラスのこのオーバーロードがないみたいだけども、あった方が便利じゃない？」くらいのものであれば追加される可能性はあります。</p>
<p>「.NET Framework にあるから」という理由だけで .NET Core に追加されることはなくなりますが、同時に、「.NET Framework にある(けどまだ .NET Core にない)から」というだけで絶対にその API が移植されないということもありません。</p>
 ]]></description>
				<pubDate>Tue, 15 Oct 2019 19:50:14 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 10/4: C# 9.0, パターン追加、switch 式ステートメント、共変戻り値</title>
				<link>http://ufcpp.net/blog/2019/10/pickuproslyn1004/</link>
				<description><![CDATA[ <p>何件か、C# 9.0 向けに提案されている機能のドラフト仕様が出てきました。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/2850">Proposed changes for Pattern Matching in C# 9.0 - Draft Specification #2850</a></li>
<li><a href="https://github.com/dotnet/csharplang/issues/2860">Draft Spec for Switch Expression as a Statement Expression in C# 9.0 #2860</a></li>
<li><a href="https://github.com/dotnet/csharplang/issues/2844">Covariant Return Types - Draft Specification #2844</a></li>
</ul>
<h2>パターン マッチ</h2>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/2850">Pattern Matching - Draft Specification #2850</a></li>
</ul>
<p><a href="/study/csharp/cheatsheet/ap_ver8/#recursive-pattern">C# 8.0 でもずいぶんとパターンが増えました</a>が、9.0 でも追加が出そうです。</p>
<ul>
<li>複数のパターンを <code>and</code> や <code>or</code> でつないだり、<code>!(x is pattern)</code> と書かなくても <code>x is not pattern</code> と書けるようにしたり</li>
<li><code>and</code> や <code>or</code> があるなら優先度を付けるために、パターンを <code>()</code> で囲えるようにしたり</li>
<li><code>x is &gt;= min and &lt;= max</code> みたいに、比較パターンを入れたり</li>
</ul>
<h2>switch 式を式ステートメントに</h2>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/2860">Switch Expression as a Statement Expression #2860</a></li>
</ul>
<p>メソッド呼び出しなど、いくつかの式は、式を単体で <code>M();</code> みたいに書いてステートメント化できます。(こういうのを「式ステートメントと言います。)</p>
<p><a href="/study/csharp/cheatsheet/ap_ver8/#switch-expression"><code>switch</code> 式</a>でも、以下のような書き方に需要があるので、式ステートメント化をしたいという話は前々からあります。</p>
<pre class="source" title="switch 式ステートメントの例">
<code><span class="reserved">static</span> <span class="reserved">void</span> <span class="method">A</span>() =&gt; <span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="string">&quot;A&quot;</span>);
<span class="reserved">static</span> <span class="reserved">void</span> <span class="method">B</span>() =&gt; <span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="string">&quot;B&quot;</span>);
<span class="reserved">static</span> <span class="reserved">void</span> <span class="method">C</span>() =&gt; <span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="string">&quot;C&quot;</span>);
 
<span class="reserved">static</span> <span class="reserved">void</span> <span class="method">M</span>(<span class="reserved">bool</span>? <span class="variable">state</span>)
{
    <span class="variable">state</span> <span class="control">switch</span>
    {
        <span class="reserved">true</span> =&gt; <span class="method">A</span>(),
        <span class="reserved">false</span> =&gt; <span class="method">B</span>(),
        <span class="reserved">null</span> =&gt; <span class="method">C</span>(),
    };
}
</code></pre>
<p>C# 8.0 には間に合わなかったので、9.0 での提案に。</p>
<h3>共変戻り値</h3>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/2844">Covariant Return Types - Draft Specification #2844</a></li>
</ul>
<p>これは要するに以下のような奴。</p>
<pre class="source" title="共変戻り値の例">
<code><span class="reserved">class</span> <span class="type">Base</span> { }
<span class="reserved">class</span> <span class="type">Derived</span> : <span class="type">Base</span> { }
 
<span class="reserved">class</span> <span class="type">A</span>
{
    <span class="reserved">public</span> <span class="reserved">virtual</span> <span class="type">Base</span> <span class="method">M</span>() =&gt; <span class="reserved">null</span>;
}
 
<span class="reserved">class</span> <span class="type">B</span>
{
    <span class="comment">// 戻り値が Base じゃなくて Derived。</span>
    <span class="comment">// 原理的には問題ないはずだけど、今までの .NET ではできなかった。</span>
    <span class="reserved">public</span> <span class="reserved">override</span> <span class="type">Derived</span> <span class="method">M</span>() =&gt; <span class="reserved">null</span>;
}
</code></pre>
<p>これはずっと「C# 上の構文糖衣ではなく、ランタイムに手を入れた方がいいので難しめ」ということでなかなか手付かずだったやつです。</p>
<p>C# 上の構文糖衣で何とかごまかせないかという検討もしていたんですが、
結局、ランタイム(.NET の型システム自体)の修正込みでやろいうという流れになっています。</p>
<p><a href="/study/csharp/cheatsheet/ap_ver8/#default-imeplementation-of-interface">インターフェイスのデフォルト実装</a>に続く2例目の「ランタイムを選ぶ新機能」になります。</p>
 ]]></description>
				<pubDate>Fri, 04 Oct 2019 22:36:29 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 9/29: Utf8String など、C# 9.0 がらみ</title>
				<link>http://ufcpp.net/blog/2019/9/pickuproslyn0929/</link>
				<description><![CDATA[ <p>C# 8.0 もリリースされたわけですし、
(リリース直前に 8.0 に関して修正も聞かないので、今月に入ったくらいから)
C# 9.0 に向けた Design Meeting が開かれているみたいです。
<a href="https://www.dotnetconf.net/">.NET Conf 2019</a> も落ち着いたところで、議事録も公開。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/2826">LDM notes for 2019-09-16 and 2019-09-18 #2826</a></li>
</ul>
<p>雰囲気的には</p>
<ul>
<li>.NET 5 向け</li>
<li>C# 9.0 を想定</li>
</ul>
<p>みたいな感じなので、たぶん来年のリリースですね。
(.NET 5 は 2020年11月と明言されてる。
C# を .NET のリリースとどう同期させるかは明言されていないものの、
議事録の雰囲気からすると .NET 5 時点で C# 9.0。
.NET Core 3.1 (今年11月)時点で何か更新しそうな気配もなし。)</p>
<p>議題については</p>
<ul>
<li>Utf8String</li>
<li>
すでに 9.0 に向けてやると決まってたことについて再確認
<ul>
<li>特に、ローカル関数への属性適用と、target-typed new</li>
</ul>
</li>
<li>
いくつかトリアージ
<ul>
<li><a href="https://github.com/dotnet/roslyn/commit/0056d765287bdc6717d38be515d3026792771f60?short_path=62d2c4c#diff-62d2c4ce577204aa80f67774438c2beb">Language Feature Status の C# vNext に5つほど項目追加</a></li>
</ul>
</li>
</ul>
<p>という感じです。</p>
<p>Design Notes とは別に、以下のドキュメントにも更新 Pull Request あり。</p>
<ul>
<li>
<a href="https://github.com/dotnet/csharplang/pull/2833">Native-sized integers proposal #2833</a>
<ul>
<li>内部的には <code>IntPtr</code>、<code>UIntPtr</code> をそのまま使って、コンパイラーのレベルでだけ <code>nint</code>、<code>nuint</code> という別の型に見せかける実装にするみたい</li>
</ul>
</li>
</ul>
<h2>Utf8String</h2>
<p>UTF-8 なバイト列を直接読み書きしたいという要望はかねてからあるというか、
C# で Web なことをするときに一番ネックになっていたのが UTF-8 (Web 上ではもうほぼこのエンコード)から UTF-16 (.NET の string の内部表現)への変換です。
なので、UTF-8 を直接読み書きするための型として <code>Utf8String</code> を追加したいという話は3・4年前くらいから出ていますし、プロトタイプ実装はすでにあります。
この型の正式リリースは .NET 5 にしたいということで、それに対する C# 言語上のサポートも C# 9.0 がターゲットになっています。</p>
<p>この <code>Utf8String</code> に関して、今回の議題は以下のようなもの。</p>
<ul>
<li>
リテラルを exe/dll にどう埋め込むか
<ul>
<li>いったんは既存の <code>string</code> リテラルの仕組みをそのまま使って UTF-16 の状態で記録して、ランタイムが読み込み時に UTF-8 変換する方式をとる</li>
<li>
ただ、どう考えても UTF-8 データを生で埋め込める方が効率的なので、将来的にその方式に変更するときに困らないかだけは要確認
<ul>
<li>今のところそういう内部的な変更が C# の破壊的変更になりそうなものは思いつかない(ので大丈夫)</li>
</ul>
</li>
</ul>
</li>
<li>
列挙をどうするか
<ul>
<li>UTF-8 な byte 列、Unicode コードポイント(あと、もしかしたら<a href="https://ufcpp.net/blog/2018/12/unicodecategory/">書記素クラスター</a>も)をそれぞれ列挙するためのプロパティはある</li>
<li>
(プロパティを介さず) <code>Utf8String</code> 自体を <code>foreach</code> に渡したいか？渡すなら何が列挙されるべきか？
<ul>
<li>プロパティを介さない列挙は認めない方が無難そう</li>
</ul>
</li>
</ul>
</li>
<li>
C# 言語上の特殊対応は必要か。以下の2点は特殊対応する利点がありそう
<ul>
<li><code>Concat</code> の最適化(n 個の文字列の <code>Concat</code> に対して O(n) 処理にする)</li>
<li>リテラル</li>
</ul>
</li>
<li>
(今の <code>string</code> リテラルと同じ) <code>&quot;&quot;</code> リテラルに対して Target-Typed な型判定をすべきか
<ul>
<li>
「UTF-8 リテラル」用の追加構文を用意しなくていいという利点はあるけども、オーバーロードで困る
<ul>
<li><code>M(string s)</code> と <code>(M Utf8String s)</code> があるとき <code>M(&quot;literal&quot;)</code> の解決ができない</li>
<li>破壊的変更にならないようにするためには、<code>string</code> 優先にせざるを得ない</li>
</ul>
</li>
<li>リテラルを Target-Typed にするのはやめた方がよさそう</li>
<li><code>u&quot;&quot;</code> みたいな構文を足すことになる</li>
</ul>
</li>
<li>
キーワード
<ul>
<li><code>System.String</code> が <code>string</code> という C# キーワードになってるのと同様、<code>Utf8String</code> に対して <code>ustring</code> などのキーワードがあった方がいいか？</li>
<li><code>u</code> だけだと <code>UTF-16</code> だって <code>Unicode</code> だって頭文字 u だから避けたいけど、他にもっと使いたい名前もない</li>
<li>リテラルとかで言語的な特殊対応をするんだから、キーワードを与えて primitive な地位を与えることはおかしくはない</li>
<li>まだ迷い気味</li>
</ul>
</li>
</ul>
<h2>ローカル関数への属性適用</h2>
<p><a href="/study/csharp/resource/nullablereferencetype/">null 許容参照型</a>とか<a href="https://ufcpp.net/study/csharp/async/asyncstream/">非同期ストリーム</a>とか、ローカル関数でも使えて、かつ、属性を付けれないと困りそうな機能がすでにいくつかあります。
なので、ローカル関数への属性適用をできるようにすること自体は確定事項。</p>
<p>今回の懸念としては、ローカル関数は C# コンパイラーが何らかの通常のメソッドに変換するわけですが、
その変換結果から属性を取れるという保証をするかどうか。
現在のコンパイラー実装では、どこかしらには絶対属性が残るようになっているものの、どこからどうすればその属性を取れるか言語仕様で保証まではしない(という提案が今回あって、その方向で行くことに決定)とのこと。</p>
<h2>Target-Typed 型推論</h2>
<p><a href="https://github.com/dotnet/csharplang/issues/100">Target-Typed new</a>は以前にもやる気になっていて、その時にデザインも終えてる。その頃から気がわかってないかだけ改めて確認。
やる気は変わらず、デザインのレビュー待ち状態に。</p>
<p>その他、Target-Typed な機能というと</p>
<ul>
<li><a href="/study/csharp/datatype/typeswitch/?p=5#switch-expression"><code>switch</code> 式</a> (C# 8.0 で実装済み)は最初から Target-Typed な型推論を持ってる</li>
<li>「<code>switch</code> でやるのなら」ということで <a href="https://github.com/dotnet/csharplang/issues/2473">?? 演算子</a>、[?: 演算子] (https://github.com/dotnet/csharplang/issues/2460)でも検討中</li>
<li>それとは別(ただし同じ課題に対する解決策)に、「<a href="https://github.com/dotnet/csharplang/issues/33">Common Type 推論の改善</a>」がある</li>
</ul>
<p>Target-Typed 型推論と Common Type 推論の改善はどちらも、
<code>flag ? 1 : null</code> みたいな式の型決定(<code>int?</code> になってほしい。今はコンパイル エラーを起こす)に対する解決策ですが、
優先度を決めないと競合します。
<code>M(int?)</code> と <code>M(short?)</code> みたいなのがあるときに、<code>M(flag ? 1 : null)</code> みたいなのがどちらのオーバーロードを呼ぶべきかが変わります。</p>
<p>Target-Typed 型推論の方が「ターゲットさえはっきりしていればいろんな型に対応できる」という利点があるものの、
「ターゲットがはっきりしない」ということも多いので Common Type 推論の方が使える場面は多くなります。</p>
<p>破壊的変更になることを避けるために、C# 8.0 の新機能の <code>switch</code> 式にだけ Target-Typed 型推論が入りました。
一方でこれから Common Type 推論も入れたいわけですが、<code>switch</code> 式とその他で違う挙動にせざるを得ないかもしれません。</p>
<p>Target-Typed 型推論に対する破壊的変更にならないように Common Type 推論を実現できないかは検討はしたい。
もし <code>switch</code> 式に対して破壊的変更が起きそうなら、その影響範囲は調査しておきたい(場合によっては破壊的変更を認めるかも)とのこと。</p>
<h2>その他のトリアージ</h2>
<ul>
<li>
<a href="https://github.com/dotnet/csharplang/issues/2145">Null parameter checking</a>
<ul>
<li>すぐにでも。9.0 に入れる</li>
</ul>
</li>
<li>
修飾子の順序緩和。特に、<a href="https://github.com/dotnet/csharplang/issues/946">ref と partial の順序</a>
<ul>
<li>9.0</li>
</ul>
</li>
<li>
<a href="https://github.com/dotnet/csharplang/issues/883">0要素、1要素のタプル</a>
<ul>
<li>決めかねてる。 X.X (いつになるかわからない)行き</li>
</ul>
</li>
<li>
<a href="https://ufcpp.net/study/csharp/datatype/deconstruction/">分解</a>での<a href="https://github.com/dotnet/csharplang/issues/125">変数と宣言の混在</a>
<ul>
<li>あると良いことはわかっているけど急ぎではない</li>
<li>Any Time (いつでもいい)行き</li>
</ul>
</li>
<li>
<a href="https://github.com/dotnet/csharplang/issues/111">ラムダ式の引数での discard</a>
<ul>
<li>Any Time</li>
<li>といいつつ、<a href="https://github.com/dotnet/roslyn/pull/38786">実装始まってたりする</a>。おそらく、「やってみて案外低コストだったら 9.0 入りを考えてもいい」みたいな状態かと</li>
</ul>
</li>
</ul>
 ]]></description>
				<pubDate>Sun, 29 Sep 2019 13:55:28 +0900</pubDate>
			</item>
			<item>
				<title>Visual Studio 16.3 &amp; 16.4 Preview 1</title>
				<link>http://ufcpp.net/blog/2019/9/vs16_3/</link>
				<description><![CDATA[ <p>(日本時間だと)昨晩深夜、<a href="https://www.youtube.com/watch?v=W8yL8vRnUnA">.NET Conf 2019</a>がありましたね。</p>
<p>キーノートはなんか<a href="https://docs.microsoft.com/ja-jp/aspnet/core/grpc/aspnetcore?view=aspnetcore-3.0&amp;tabs=visual-studio">gRPC</a>一色だった感じが…</p>
<p>要は、ASP.NET Core 3.0 の目玉の1つが gRPC 対応なんですけども。
それを、</p>
<ul>
<li>proto ファイルから ASP.NET のサーバーを作るデモ</li>
<li>同じ proto ファイルからクライアントコードを生成するデモ</li>
<li><a href="https://docs.microsoft.com/ja-jp/dotnet/framework/winforms/">WinForms</a> とか <a href="https://docs.microsoft.com/ja-jp/dotnet/framework/wpf/getting-started/">WPF</a> が .NET Core で使えるようになった → WinForms のデモでも生成した gRPC クライアントを利用</li>
<li>Xamarin にも、<a href="https://docs.microsoft.com/ja-jp/xamarin/xamarin-forms/xaml/hot-reload">hot リロード、hot デプロイ機能が入る(プレビュー)</a> → Xamarin のデモでも同じ gRPC クライアントを利用</li>
<li><a href="https://docs.microsoft.com/ja-jp/aspnet/core/blazor/?view=aspnetcore-3.0">Blazor</a> のデモでも同じ gRPC</li>
<li>生成した gRPC クライアントは C# 8.0 対応 → <a href="https://ufcpp.net/study/csharp/async/asyncstream/#await-foreach"><code>await foreach</code></a> のデモに利用</li>
</ul>
<p>という感じ。</p>
<p>ちなみに、<a href="https://twitter.com/Johnmont/status/1176410731656269825">2018年11月ごろから gRPC のチームと協力してフル managed な実装を頑張ったんですって</a>。</p>
<p>ところで、Unity だといつ使えるようになるんですかね…</p>
<h2>Visual Studio 16.3 &amp; 16.4 Preview 1</h2>
<p>とりあえず、予告通り、.NET Core 3.0 が正式リリースされました。</p>
<ul>
<li><a href="https://devblogs.microsoft.com/dotnet/announcing-net-core-3-0/">Announcing .NET Core 3.0</a></li>
</ul>
<p>予告通り。(build で発表した通りに行くか多少心配してた。)</p>
<p>伴って、Visual Studio も 16.3 になり、プレビューチャネルの方でも 16.4 Preview 1 が配信されました。</p>
<ul>
<li><a href="https://docs.microsoft.com/ja-jp/visualstudio/releases/2019/release-notes#16.3.0">Visual Studio 2019 バージョン16.3.0</a></li>
<li><a href="https://docs.microsoft.com/ja-jp/visualstudio/releases/2019/release-notes-preview#16.4.0-pre.1.0">Visual Studio 2019 バージョン 16.4 Preview 1</a></li>
</ul>
<p>(今回は ja-jp のリンクを貼れて安心してる。機械翻訳なのにやたら反映が遅かったりするんで… 前よりだいぶ改善してるのかな。)</p>
<p>ちなみに、16.4 ですが、C# 的には単にバグ修正になりそう。
既知のバグは例えば、</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/pull/38116">C# 7.3 以前にしていても 8.0 の機能が使えちゃう</a></li>
<li><a href="https://github.com/dotnet/roslyn/pull/37596"><code>t == default</code> と書いた時の <code>default</code> の型推論を間違う</a></li>
</ul>
<p>みたいなやつです。</p>
<p>あと、ひそかに inheritdoc コメントに対応するみたい。</p>
<p><img src="/media/1179/inheritdoc.png" alt="inheritdoc" /></p>
<p>こいつは、<a href="https://ewsoftware.github.io/XMLCommentsGuide/html/86453FFB-B978-4A2A-9EB5-70E118CA8073.htm">Sandcastle</a>は昔から持ってる機能だったんですけど、Visual Studio 上のコード補完では出てこなかったやつです。
「派生クラスと同じ」しか doc コメントに書くことがないときに使うもの。
ついに補完候補に。</p>
<h2>C# 8.0</h2>
<p>まあ、いつも通り、「自分は RC の頃には触りつくしてるのでリリース時点では話すことがない」状態ではあります。</p>
<p><a href="https://ufcpp.net/study/csharp/cheatsheet/ap_ver8/">「 C# によるプログラミング入門」の C# 8.0 がらみ</a>は9割5分くらいは書けてるんですけども。
今回ちょっとリリースまでに書き損ねてる項目あったり。</p>
<p>残タスク: <a href="https://github.com/ufcpp/UfcppSample/issues/255">null 許容参照型</a>、<a href="https://github.com/ufcpp/UfcppSample/issues/269">こまごまとしたやつ</a>、あと、非同期ストリームは<a href="https://ufcpp.net/study/csharp/async/asyncstream/?p=2#usage">利用例</a>を足したい</p>
<p>とりあえず、正式リリースになったので使い放題！
みんなー、もう Visual Studio 16.3 のインストールはしてくれたかな？
容赦なく C# 8.0 の機能を使ったコミット出すよ！
とか思いながら 16.3 を触ってみていたんですが…
なんか、以下のような感じで、微妙にまだ使えないかも…</p>
<ul>
<li>TargetFramework が .NET Core 3.0、.NET Standard 2.1 のプロジェクトの場合普通に default で C# 8.0 になる</li>
<li>
TargetFramework が .NET Core 2.1 とか 2.2、 .NET Standard 2.0 のプロジェクトは default が C# 7.3 のまま
<ul>
<li><a href="https://ufcpp.net/study/csharp/cheatsheet/langversionoption/#langversion">LangVersion</a> に latest を指定すると C# 8.0 になる</li>
</ul>
</li>
</ul>
<p>あれー… なんでこんな挙動なのかわからず。
単に、「古い SDK だとコンパイラーが更新されてない」というのも疑ってみてるんですけども。
それなら LangVersion は preview にしないと C# 8.0 にならないはずのような…</p>
<p>とりあえず、C# 7.3 の時も、 .NET Core SDK を更新したら 2.0 とか 1.6 でも C# 7.3 を使えるようになったので、しばらく様子見ですかね。
今の、 .NET Core SDK 2.1 と 2.2 は9月10日リリースのもののままのようなので。</p>
 ]]></description>
				<pubDate>Tue, 24 Sep 2019 21:03:40 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 8/31: トリアージ祭り</title>
				<link>http://ufcpp.net/blog/2019/8/pickuproslyn0831/</link>
				<description><![CDATA[ <p>.NET Core 3.0/C# 8.0 正式リリースがあるとされている <a href="https://www.dotnetconf.net/">.NET Conf</a> (9月23日から)も近づいてきて、さすがに最近は C# 8.0 がらみの動きはないというか、そろそろその先を見た動きになってきた感じがします。</p>
<p>ということで、こういう時期恒例のトリアージ祭りが発生中。</p>
<p>(無言でマイルストーンを変えただけのやつも、GitHub の Sort 順序「Recently updated」で浮上するんですね。
「今週何やらトリアージしてそう」って感知してたのを、今調べてなおしてて大変助かってる。)</p>
<p>ちなみに、<a href="https://github.com/dotnet/csharplang/issues/39">Records</a> は「これまでと変わらず」で 9.0 マイルストーンです。
一応、C# 9.0 はこれが主軸になるはず。6.0 時代から案だけはあったのが延々先延ばされてきましたが、ついに。</p>
<h2>優先度微ダウン(8.X → 9.0)</h2>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/100">Champion &quot;Target-typed <code>new</code> expression&quot; #100</a></li>
<li>
<a href="https://github.com/dotnet/csharplang/issues/33">Champion &quot;Nullable-enhanced common type&quot; #33</a>
<ul>
<li>ターゲットからの型推論の導入で解決できそうな問題はまとめてやりたそう</li>
<li>see also: <a href="https://github.com/dotnet/csharplang/issues/881">#881</a>, <a href="https://github.com/dotnet/csharplang/issues/2460">#2460</a>, <a href="https://github.com/dotnet/csharplang/issues/2473">#2473</a></li>
</ul>
</li>
<li>
<a href="https://github.com/dotnet/csharplang/issues/1350">Champion &quot;and, or, and not patterns&quot; #1350</a>
<ul>
<li>セットでこれも: <a href="https://github.com/dotnet/csharplang/issues/812">Proposal: allow comparison operators in switch case labels C# #812</a></li>
</ul>
</li>
<li><a href="https://github.com/dotnet/csharplang/issues/1398">Champion &quot;defer statement&quot; #1398</a></li>
<li><a href="https://github.com/dotnet/csharplang/issues/2632">Champion: Switch expression as a statement expression #2632</a></li>
<li><a href="https://github.com/dotnet/csharplang/issues/1888">Champion &quot;Permit attributes on local functions&quot; #1888</a></li>
</ul>
<p>この辺りは優先度ダウンしているといっても、9.0 自体のリリースのタイミングの方自体に関心が。</p>
<p>とりあえずわかっていることとして、</p>
<ul>
<li>
<a href="https://ufcpp.net/blog/2019/5/build2019/">build での発表</a>によれば、
<ul>
<li>来年から .NET Core は毎年11月の定期メジャー リリースになる</li>
<li>(今年末の3.1は安定として5以降) Long Term Support (LTS)は偶数番リリースのみ</li>
</ul>
</li>
<li>C# のリリースは .NET と足並みをそろえたがってる</li>
</ul>
<p>というのがありまして。
じゃあ、LTS が付いてない奇数番のとき、C# はどうするんだって話でして。
.NET 5 のタイミング、C# も 9.0 になって LTS なしなのか、このタイミングでは 8.X を出すのか…</p>
<p>自分の把握してる範囲ではどっちになるかわからず。どちらになるかによってだいぶ「マイルストーン 9.0」の意味が違いそう。</p>
<p><a href="https://github.com/dotnet/csharplang/milestone/12">8.X</a>に残っているものの少なさとか、9.0 に移動されたものがどれも小さ目な機能だとか、「C# 年次リリース」も十分あり得るような気もしつつ。でも、昔、「文法が年1メジャー アップデートするのはやりすぎ」みたいなこと言ってたし、「C# にも LTS ないバージョンがあるの？」的なこともちょっと思ったりはしつつ。</p>
<h2>優先度アップ(X.0 → 9.0)</h2>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/49">Champion &quot;Covariant Return Types&quot; #49</a></li>
<li>
<a href="https://github.com/dotnet/csharplang/issues/113">Champion &quot;Discriminated Unions&quot; #113</a>
<ul>
<li>「後から入れるにしても Records と併せて考えるべき」という口ぶりなので、マイルストーンが 9.0 になったからといって 9.0 に入るとは限らなさそうな感じ</li>
</ul>
</li>
<li><a href="https://github.com/dotnet/csharplang/issues/302">Champion &quot;Static Delegates&quot; #302</a></li>
<li><a href="https://github.com/dotnet/csharplang/issues/2608">Champion: Module Initializers #2608</a></li>
</ul>
<h2>優先度アップ(未分類 → 9.0)</h2>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/2302">Efficient Params and String Formatting #2302</a></li>
</ul>
<p>これ、参照型に対する可変長スタック確保(<code>stackalloc T[n]</code>)が GC にやさしくないから厳しいって言われてた気がするものの…
以下の関連する作業が .NET 5 マイルストーンで動いてるので整合性は取れてるのかな…</p>
<ul>
<li><a href="https://github.com/dotnet/corefx/issues/35806">API Proposal: Add Variant type to avoid boxing .NET intrinsic types #35806</a></li>
<li><a href="https://github.com/dotnet/corefx/issues/28379">API Proposal: Add a ValueStringBuilder #28379</a></li>
<li><a href="https://github.com/dotnet/corefxlab/pull/2595">Protoype for nonallocating string formatting #2595</a></li>
</ul>
<h2>優先度微ダウン(9.0 → 10.0)</h2>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/110">Champion &quot;Type Classes (aka Concepts, Structural Generic Constraints)&quot; #110</a></li>
</ul>
<h2>優先度微アップ(X.0 → 10.0)</h2>
<ul>
<li>
<a href="https://github.com/dotnet/csharplang/issues/2585">Proposal: Exponentiation operator #2585</a>
<ul>
<li>「べき乗演算子」が欲しいってやつ。C# が今までこれを考慮に入れてこなかった理由は「<code>Pow</code>関数の実装によって結果変わるのが嫌」みたいな空気</li>
<li><a href="https://github.com/dotnet/docs/blob/master/docs/core/whats-new/dotnet-core-3-0.md">.NET Core 3.0 で float がらみが軒並み IEEE コンプライアンス準拠になる</a>ので、懸念が1つ解決してるので実装してもいい空気になったみたい</li>
</ul>
</li>
</ul>
<h2>優先度ダウン(9.0 → X.0)</h2>
<ul>
<li>
<a href="https://github.com/dotnet/csharplang/issues/1314">Champion: fixed-sized buffers #1314</a>
<ul>
<li><a href="/study/csharp/resource/refstruct/">ref 構造体</a>の寿命トラッキングがちょっと大変そうで厳しいみたい</li>
</ul>
</li>
<li>
<a href="https://github.com/dotnet/csharplang/issues/99">Champion &quot;Allow no-arg constructor and field initializers in struct declarations&quot; #99</a>
<ul>
<li>6.0 の頃から候補になってたけど「既存のコードが <code>new T()</code> を <code>default(T)</code> の意味で使ってる・最適化かけてるから厳しい」って雰囲気のやつ</li>
<li>ちなみに、<a href="https://github.com/dotnet/csharplang/issues/146">Non-defaultable value types</a>はこれとセットであれば考えてくれるらしい</li>
</ul>
</li>
</ul>
<h2>優先度アップ？(未分類 → X.0)</h2>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/2304">Proposal: <code>tail return</code> recursive calls #2304</a></li>
</ul>
<h2>優先度大ダウン(8.X → Any Time)</h2>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/1881">Switching ReadOnlySpan<char> with constant strings #1881</a></li>
<li><a href="https://github.com/dotnet/csharplang/issues/1742">Champion: &quot;Permit surrogate pairs and wide Unicode-escaped code points in identifiers&quot; #1742</a></li>
</ul>
<p>ちなみに後者の Unicode なんとかというやつ、
大昔から既知の問題なんですけども、今の C# コンパイラーはサロゲート ペアな文字を識別子として受け付けません。
サロゲート ペアでも、非常用漢字とかヒエログリフとか、 Unicode 文字カテゴリー的には使えていいはずの文字があるんですが、それが使えないのは「バグ」です。</p>
<p>で、まあ、「Any Time」マイルストーンっていうのは概ね「外部からのコントリビューション待ってます」という意味。
やるとしたら自分だろうなぁとか思っていたり。</p>
<p>昔、<a href="https://ufcpp.net/blog/2018/1/getunicodecategory/">corefx に「<code>GetUnicodeCategory(int codePoint)</code>を public にしてほしい」と要望を出した</a>のはこれのためでして。
このオーバーロードがないと C# にサロゲート ペア識別子を入れるのは厳しい(きれいで、かつ、パフォーマンスをあまり落とさない手段がない)。</p>
<p>こいつは .NET Core 2.1 で無事に入ったわけですが、C# コンパイラーは今のところターゲットが .NET Standard 2.0 なので、まだこのオーバーロードを使えません。</p>
<p>というかぶっちゃけ、自分が「サロゲート ペアな文字を識別子に使えなくて困ってる人見たことないよ。ジョークでヒエログリフ使いたいって言う人の方が多いくらい。昔勉強会で『欲しい人？』って聞いてみたことあるけど誰もいなかった。それでも使えるようにする pull request 出そうと思ったことがあるけど、<code>GetUnicodeCategory(int codePoint)</code> がないのがネックだった。」的な報告をしているので、「Any Time」になったの自体たぶん自分のせい。</p>
<h2>リジェクト</h2>
<ul>
<li>
<a href="https://github.com/dotnet/csharplang/issues/414">Proposal: Dictionary Literals #414</a>
<ul>
<li>口ぶりとしては「Dictionary だけを特別扱いして検討する気はないけど、一般的な『データの初期化』に関する関心はある。Records の後で改めて考える」な雰囲気</li>
</ul>
</li>
<li><a href="https://github.com/dotnet/csharplang/issues/1828">Proposal: allow sizeof in any context #1828</a></li>
</ul>
<h2>新規(未分類)</h2>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/2765">Top level statements and member declarations (embrace scripting dialect) #2765</a></li>
</ul>
<p>今、「C# スクリプティング」が特別なモードとして存在していて、その中でだけトップ レベル(クラス、名前空間の外)にメンバー宣言を書ける状態です。</p>
<p>で、今までは「C# スクリプティング」の需要自体が低かったから特別モードの保守も平気だった(最悪、ちょっと通常の C# よりも遅れてもいい)ものの、
最近、<a href="https://github.com/dotnet/try/">Try .NET</a>によって需要が急増していてどうしようかという感じ。</p>
<p>(ちなみに、なんか最近この Try .NET、<a href="https://jupyter.org/">jupyter</a>対応してるんですよ、作業的に。)</p>
<p>なので、トップ レベル メンバーを、特別扱いではなく、通常の C# の仕様にも統合できないかという話になっています。
「<code>Main</code>メソッドはおまじない」からの脱却も、言語を学び始めたばかりの人にやさしいですし。</p>
<p>まあ、マイルストーン未分類ですが。</p>
 ]]></description>
				<pubDate>Sat, 31 Aug 2019 23:56:21 +0900</pubDate>
			</item>
			<item>
				<title>Visual Studio 16.2.2 ＆ 16.3 Preview 2</title>
				<link>http://ufcpp.net/blog/2019/8/vs16_3_p2/</link>
				<description><![CDATA[ <p>Visual Studio 2019 16.2.2 と 16.3 Preview 2 と、あと、 .NET Core 3.0 Preview 8 が出てますね。</p>
<ul>
<li><a href="https://docs.microsoft.com/ja-jp/visualstudio/releases/2019/release-notes#16.2.2">Visual Studio 2019 version 16.2.2</a></li>
<li><a href="https://docs.microsoft.com/ja-jp/visualstudio/releases/2019/release-notes-preview#16.3.0-pre.2.0">Visual Studio 2019 version 16.3 Preview 2</a></li>
<li><a href="https://devblogs.microsoft.com/dotnet/announcing-net-core-3-0-preview-8/">Announcing .NET Core 3.0 Preview 8</a></li>
</ul>
<p>16.2.2 は脆弱性の修正だけっぽいですかね、リリース ノートを見るに。
.NET Core 3.0 Preview 8 も「最終リリースに向けて磨いてるとこ」みたいなことを言っているので大きな変更はないはず。</p>
<p>16.3 Preview 2 はこまごまと結構追加が。</p>
<h2>16.3 Preview 2</h2>
<p>僕的に気になるのはまあ .NET/C# がらみくらいなわけですが、
それも今回はそこそこ差分あり。</p>
<h3>IDE 機能</h3>
<p>「<a href="https://docs.microsoft.com/ja-jp/visualstudio/releases/2019/release-notes-preview#net-productivity-163P2">.NET Productivity</a>」に書かれてる通り、</p>
<ul>
<li>1行内に大量にメソッドチェーンでつないでる奴を複数行にばらす整形</li>
<li>先に <code>new DateTime</code> みたいなインスタンス生成を書いてから IDE 機能でローカル変数を導入</li>
</ul>
<p>とかがあるみたいです。</p>
<p>あと、これは IDE 機能なのか C# 機能なのかどっちに分類していいのかわからないですけど、
<a href="/study/csharp/sp_xmldoc.html">doc コメント</a>内で <code>&lt;em&gt;</code> とか <code>&lt;strong&gt;</code> とかのスタイル変更タグが使えるようになったみたいです。</p>
<p><img src="/media/1178/quickinfostyle.png" alt="doc コメントにスタイル反映" /></p>
<p>詳しくはこの PR を参照: <a href="https://github.com/dotnet/roslyn/pull/35667">Implement Quick Info styles #35667</a></p>
<h3>target-typed switch 式</h3>
<p>C# 8.0 の変更は大部分もう<a href="/study/csharp/resource/nullablereferencetype/">null 許容参照型</a>がらみだけ…
という状況下において、1個だけ他の変更がありました。</p>
<p><a href="/csharp/datatype/typeswitch/?p=5#switch-expression">switch 式</a>でターゲットからの型推論が効くようになりました。
要するに以下のようなコードが 16.3 Preview 2 からコンパイルできるようになります。</p>
<pre class="source" title="target-typed switch">
<code><span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">class</span> <span class="type">Base</span> { }
    <span class="reserved">class</span> <span class="type">A</span> : <span class="type">Base</span> { }
    <span class="reserved">class</span> <span class="type">B</span> : <span class="type">Base</span> { }
 
    <span class="reserved">static</span> <span class="type">Base</span> <span class="method">M</span>(<span class="reserved">bool</span> <span class="variable">b</span>) =&gt; <span class="variable">b</span> <span class="control">switch</span>
    {
        <span class="comment">// 条件ごとに型が違うので、これまでは switch 式の結果の型が確定できなかった。</span>
        <span class="comment">// ターゲット(この場合戻り値の Base)からの型推論で型を確定するようになった。</span>
        <span class="reserved">true</span> =&gt; <span class="reserved">new</span> <span class="type">A</span>(),
        <span class="reserved">_</span> =&gt; <span class="reserved">new</span> <span class="type">B</span>(),
    };
}
</code></pre>
<p>まあ元々「スケジュール的に厳しいけど C# 8.0 正式リリース時点で入れておかないと後からの変更は破壊的になるので避けたい」って言ってたやつです。
ほんとにぎりぎり間に合わせて来た感じ。</p>
<h2>null 許容参照型がらみ</h2>
<p>さらっと動作確認。</p>
<ul>
<li><a href="https://gist.github.com/ufcpp/95fd288be27f0df5fae8ab5a093d36a4">16.3 Preview 2 時点でいくつか確認</a></li>
</ul>
<p><a href="https://github.com/dotnet/roslyn/issues/35816">計画に上がってたもの</a>大体一通り実装されてそうな雰囲気。
今度こそ<a href="/study/csharp/resource/nullablereferencetype/">null 許容参照型のページ</a>を埋めるの本気出さなきゃ…</p>
<p>ちなみに、<a href="/study/csharp/resource/nullablereferencetype/?p=3#null-forgiving">一昨日書いたばかりの文章</a>を<a href="https://twitter.com/ufcpp/status/1161458417598287874">さっそく書き換える</a>というタイミングのよさ。</p>
<p>「この挙動で本当にいいの？」みたいなものもあったりはするんですが…
<a href="https://github.com/dotnet/roslyn/milestone/44">「vNext」マイルストーン</a>が付いていたりするので、C# 8.0 時点ではあきらめていそうです。
例えば以下のようなやつ。</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/issues/36039">Should nullability attributes affect method bodies and OHI? #36039</a></li>
</ul>
<p>要するに、<code>MaybeNull</code> とかの属性は、外から見ると正しく働くものの、メソッドの中から見ると妥協的という感じ。
とりあえずどっちが重要かと言われると「外から」の方なので、重要なところだけは最低限実装したという。</p>
<p>ただ、<code>DoesNotReturnIf</code> が期待通り動いていないのはなんかおかしい感じが。
<a href="https://github.com/dotnet/roslyn/pull/36810">関連 Pull Request</a> も通ってるので動作してそうなものなんですけども。
マージしたタイミングの問題ですかね…</p>
 ]]></description>
				<pubDate>Wed, 14 Aug 2019 20:57:21 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 8/3: Records など</title>
				<link>http://ufcpp.net/blog/2019/8/pickuproslyn0803/</link>
				<description><![CDATA[ <p>Design Notes が3件ほど。</p>
<p>そのうち2件は7/10, 17のもので、C# 8.0 の最後の詰めっぽい感じ。</p>
<ul>
<li>
<a href="https://github.com/dotnet/csharplang/issues/2702">Added: LDM notes for July 10th and July 17th #2702</a>
<ul>
<li><a href="https://github.com/dotnet/csharplang/blob/master/meetings/2019/LDM-2019-07-10.md">7/10</a></li>
<li><a href="https://github.com/dotnet/csharplang/blob/master/meetings/2019/LDM-2019-07-17.md">7/17</a></li>
</ul>
</li>
</ul>
<p>残りは、7/22 のもので、C# 9.0 に向けて「今度こそ」という感じで Records の話。</p>
<ul>
<li>
<a href="https://github.com/dotnet/csharplang/issues/2699">Discussion: New records proposal #2699</a>
<ul>
<li><a href="https://github.com/dotnet/csharplang/blob/master/meetings/2019/LDM-2019-07-22.md">7/22</a></li>
<li><a href="https://github.com/dotnet/csharplang/blob/856c335cc584eda2178f0604cc845ef200d89f97/proposals/recordsv2.md">Records v2</a></li>
</ul>
</li>
</ul>
<h2>7/10</h2>
<ul>
<li><a href="https://github.com/dotnet/csharplang/blob/master/meetings/2019/LDM-2019-07-10.md">7/10</a></li>
</ul>
<p>議題は3点。</p>
<ul>
<li>Empty switch statement</li>
<li><code>[DoesNotReturn]</code></li>
<li><code>params!</code></li>
</ul>
<h3>Empty switch statement</h3>
<p>元々、<a href="/study/csharp/datatype/typeswitch/?p=5#switch-expression">switch</a>式を式ステートメント(式1個だけ + <code>;</code> でステートメントを作るやつ)で使えるようにしたいという話があります。
セットで、戻り値が <code>void</code> な式を <code>switch</code> 式使えるようにしたいという話もあり。</p>
<pre class="source" title="switch 式を式ステートメント化け &amp; void を認める">
<code><span class="reserved">static</span> <span class="reserved">void</span> <span class="method">M</span>(<span class="reserved">bool</span> <span class="variable">flag</span>)
{
    <span class="reserved">static</span> <span class="reserved">void</span> <span class="method">a</span>() { }
    <span class="reserved">static</span> <span class="reserved">void</span> <span class="method">b</span>() { }
 
    <span class="comment">// switch 式内で void なものを書けるようしたいという話あり。</span>
    <span class="comment">// (今 (少なくとも VS 16.3 Preview 1)は認められていない。)</span>
    <span class="variable">flag</span> <span class="control">switch</span>
    {
        <span class="reserved">true</span> =&gt; <span class="method">a</span>(),
        <span class="reserved">false</span> =&gt; <span class="method">b</span>(),
    };
}
</code></pre>
<p>(ちなみに、これの実装はまだなく、<a href="https://github.com/dotnet/roslyn/issues/30649">関連 issue</a>を今見ると<a href="https://github.com/dotnet/roslyn/milestone/44">Compiler.Next</a>という謎のマイルストーンが付けられてた…
C# 8.0 を目指してたけどスケジュール的に無理で次に回ったやつですね、たぶん。)</p>
<p>で、7/10 の議題的には、以下のような「空 switch 式」を認めるかどうか。</p>
<pre class="source" title="空 switch 式">
<code><span class="comment">// 式ステートメントに出来る前提では、空 switch を禁止する十分な理由が見当たらない。</span>
<span class="variable">flag</span> <span class="control">switch</span> { };
</code></pre>
<p>意味のあるコードではないですけども、
まあ、わざわざ禁止する十分な理由が見当たらないとのこと。</p>
<h3>DoesNotReturn</h3>
<p><code>[DoesNotReturn]</code> 属性は、<a href="/study/csharp/resource/nullablereferencetype/">null 許容参照型</a>に関連する属性です。
以下のメソッドのように、そのメソッドを呼んだ時点でそこから後ろは絶対に呼ばれないということを表すもの。</p>
<pre class="source" title="">
<code><span class="comment">// 例外を出すんで、このメソッドからは絶対に正常に戻ってこない。</span>
[<span class="type">DoesNotReturn</span>]
<span class="reserved">static</span> <span class="reserved">void</span> <span class="method">Throw</span>() =&gt; <span class="control">throw</span> <span class="reserved">new</span> <span class="type">Exception</span>();
 
<span class="comment">// 永久ループしてるんで、このメソッドからも戻ってこない。</span>
[<span class="type">DoesNotReturn</span>]
<span class="reserved">static</span> <span class="reserved">void</span> <span class="method">InfiniteLoop</span>() { <span class="control">while</span> (<span class="reserved">true</span>) ; }
 
<span class="reserved">static</span> <span class="reserved">void</span> <span class="method">M</span>(<span class="reserved">int</span> <span class="variable">i</span>)
{
    <span class="reserved">string</span>? <span class="variable">s</span> = <span class="reserved">null</span>;
 
    <span class="comment">// 絶対に戻ってこない or 非 null な値の代入ありのどちらか。</span>
    <span class="control">if</span> (<span class="variable">i</span> == 1) <span class="method">Throw</span>();
    <span class="control">else</span> <span class="control">if</span>(<span class="variable">i</span> == 2) <span class="method">InfiniteLoop</span>();
    <span class="control">else</span> { <span class="variable">s</span> = <span class="string">&quot;abc&quot;</span>; }
 
    <span class="comment">// ここに来た時点で絶対に s = &quot;abc&quot; を通ってるので、s は非 null。</span>
    <span class="comment">// 警告は出さなくていいはず。</span>
    <span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="variable">s</span>.Length);
}
</code></pre>
<p>null 許容参照型のために導入される属性ですが、
原理的には<a href="/study/csharp/resource/rm_struct/#definite-assignment">確実な初期化ルール</a>に対しても使えるはずです。
7/10 の議題はこの点についてで、とりあえずこの属性は null チェックにしか使わないという決断。</p>
<p>汎用な reachability (到達可能かどうか。到達可能なら null チェック、確実な初期化チェックが必要)判定は将来改めて考える。
その際にはおそらく別の仕組みを使うとのこと。</p>
<h3>param!</h3>
<p>引数の後ろに <code>!</code> を書くことで、その引数の実行時 null チェックを自動挿入したいという提案があります。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/2145">Champion: Simplified parameter null validation code #2145</a></li>
</ul>
<p>ちなみに、<a href="/study/csharp/resource/nullablereferencetype/">null 許容参照型</a>はコンパイル時の静的なフロー解析で、実行時には何もしません。
静的にチェックしても、null 許容参照型導入前の古いコードや、<a href="/study/csharp/resource/nullablereferencetype/#opt-in"><code>#nullable disable</code> なコンテキスト</a>で書いたコード、unsafe なコードから実行時に null が紛れ込むことがあります。
なので、実行時 null チェックの挿入にも需要が残っています。</p>
<p>機能自体はぜひ採用したいものの、詳細を詰め切れていない(いくつか問題がある)ので C# 8.0 には入れないとのこと。</p>
<p>例えば現状の文法案(引数の後ろに <code>!</code>) は、「式の後ろの <code>!</code>」と期待するものが真逆になるのでまずいです。これに対して、適切な文法を考えている余裕はもう C# 8.0 のスケジュールにはありません。</p>
<pre class="source" title="param! と expression!">
<code><span class="reserved">static</span> <span class="reserved">void</span> <span class="method">M</span>(<span class="reserved">string</span> <span class="variable">param</span>!)
{
    <span class="comment">// (C# 8.0 に入れないことが決まった。)</span>
    <span class="comment">// param! と書くと、以下のコードがコンパイラーによって挿入される</span>
    <span class="comment">// if (param is null) throw new ArgumentNullException(nameof(param));</span>
 
    <span class="comment">// つまり、暗に、本来非 null なところに null が来うることを期待してる。</span>
}
 
<span class="reserved">static</span> <span class="reserved">void</span> <span class="method">N</span>(<span class="reserved">string</span>? <span class="variable">nullable</span>)
{
    <span class="comment">// (これは C# 8.0 に入る。)</span>
    <span class="comment">// null が来てても完全に無視。</span>
    <span class="comment">// null forgiven (null の罪に目をつむる) 演算子って言ったりする。</span>
    <span class="reserved">string</span> <span class="variable">notnull</span> = <span class="variable">nullable</span>!;
 
    <span class="comment">// つまり、暗に、本来 null 許容なところに null が来ないことを期待してる。</span>
}
</code></pre>
<h2>7/17</h2>
<ul>
<li><a href="https://github.com/dotnet/csharplang/blob/master/meetings/2019/LDM-2019-07-17.md">7/17</a></li>
</ul>
<p>こっちの議題は2つ。と言っても片方は triage (細々と3つ、機能を入れるかどうか検討)。</p>
<ul>
<li>Nullability of events</li>
<li>
Triage
<ul>
<li>Support XML doc comments on local functions</li>
<li>Warn on obsoleting overrides of non-obsolete members</li>
<li>Proposals for ConfigureAwait with context</li>
</ul>
</li>
</ul>
<h3>Nullability of events</h3>
<p>C# のイベント、特に<a href="/study/csharp/sp_event.html#auto-event">自動イベント</a>は2つの側面を持ちます。</p>
<ul>
<li>外から見て <code>+=</code>/<code>-=</code> できる (add/remove アクセサー)</li>
<li>中から見てデリゲート呼び出しができる(同名のフィールドとして参照できる)</li>
</ul>
<p>これに対して null チェックをどうするかという話。
例えば、以下のようなチェックの仕方をしてほしいという要求は十分にあります。</p>
<ul>
<li>外から見て、<code>+=</code>/<code>-=</code> に null を渡すとかは許容したくない。外から見ると非 null であってほしい</li>
<li>
中からの呼び出しに関しては、null が来ることを前提としたコードを書くことが一般的
<ul>
<li>イベント <code>E</code> に対して <code>E?.Invoke(this, args)</code> とか (null 許容な前提だから <code>?.</code> を書く)</li>
</ul>
</li>
</ul>
<p>ということで、自動イベントに対するフロー解析で、アクセサーとフィールドを別扱いするべきかどうかというのが議題に。</p>
<p>結論的には、要求があることはわかるものの、イベントだけを特別扱いするのも混乱のもとなので、変なことはしないとのこと。</p>
<h3>Triage 3件</h3>
<ul>
<li>
ローカル関数に XML ドキュメント コメントを付けたい
<ul>
<li>需要はわかるし、やりたい</li>
<li>でも、それを言ったらローカル関数だけじゃなくてローカルなもの全般(変数含む)にもドキュメント コメントの需要あって、合わせて考えたい</li>
</ul>
</li>
<li>
<a href="/study/csharp/sp_attribute.html#compiler_attribute">Obsolete</a>でないメンバーを、Obsolete 付きで<a href="/study/csharp/oo_polymorphism.html#override">オーバーライド</a>したときに警告を出すかどうか
<ul>
<li>あると便利</li>
<li>でも、やるなら warning waves (既存コードを壊すような警告を足せるように、オプション指定で警告度合いを増やす)を入れる段階でやる</li>
</ul>
</li>
<li>
ConfigureAwait 問題
<ul>
<li>再三にわたって「<a href="/blog/2016/12/tipscontextfreetask/">何もつけなくても <code>ConfigureAwait(false)</code> になるような機能</a>が欲しい」と言われる。いい加減検討が必要</li>
<li>次のメジャーリリースに向けて考える</li>
</ul>
</li>
</ul>
<h2>7/22 (record V2)</h2>
<ul>
<li><a href="https://github.com/dotnet/csharplang/blob/master/meetings/2019/LDM-2019-07-22.md">7/22</a></li>
</ul>
<h3>records おさらい</h3>
<p>records は、要は純粋なデータを表すような型のこと。
現状の C# で書くと、コンストラクター引数をプロパティでほぼ同じものを何度も繰り返し書かないといけなくてしんどいやつです。</p>
<pre class="source" title="records">
<code><span class="reserved">class</span> <span class="type">Records</span>
{
    <span class="comment">// public なプロパティでデータをまとめたいというのがこの手の型(レコード)の主目的。</span>
    <span class="reserved">public</span> <span class="reserved">int</span> X { <span class="reserved">get</span>; }
    <span class="reserved">public</span> <span class="reserved">int</span> Y { <span class="reserved">get</span>; }
 
    <span class="comment">// 目的外のところで、存外書かないといけないコードが多い。</span>
    <span class="reserved">public</span> <span class="type">Records</span>(<span class="reserved">int</span> <span class="variable">x</span>, <span class="reserved">int</span> <span class="variable">y</span>) =&gt; (X, Y) = (<span class="variable">x</span>, <span class="variable">y</span>);
    <span class="reserved">public</span> <span class="reserved">void</span> <span class="method">Deconstruct</span>(<span class="reserved">out</span> <span class="reserved">int</span> <span class="variable">x</span>, <span class="reserved">out</span> <span class="reserved">int</span> <span class="variable">y</span>) =&gt; (<span class="variable">x</span>, <span class="variable">y</span>) = (X, Y);
    <span class="reserved">public</span> <span class="reserved">bool</span> <span class="method">Equals</span>(<span class="type">Records</span> <span class="variable">other</span>) =&gt; (X, Y) == (<span class="variable">other</span>.X, <span class="variable">other</span>.Y);
    <span class="comment">// その他、GetHashCode, == と !=, Equals(object) 等々…</span>
}
</code></pre>
<p>うちのブログでも何度も何度も出ている話なのでずっと読んでくれている方ならわかると思いますが、初出は C# 6.0 の頃で、7 でも 8 でも流れて、9.0 で今度こそこれを主役にしたいという雰囲気。</p>
<h3>records V1</h3>
<p>最初に提案された records (今回、records V1 とか positional records とか呼ばれるようになっています)は概ね、以下のような書き方から、上記のようなクラスを生成する機能です。</p>
<pre class="source" title="Records V1">
<code>data <span class="reserved">class</span> <span class="type">Records</span>(<span class="reserved">int</span> X, <span class="reserved">int</span> Y);
</code></pre>
<p>クラスの生成は、前述のような immutable (プロパティが get-only で、コンストラクターでの初期化が必須)なものになる(少なくともデフォルトではそうなる。get/set できるようにしたければ明示が必要にする)予定です。</p>
<p>こういう書き方自体はなくなったわけじゃなくて、これはこれで C# 9.0 のスコープに入っているんですが、問題もあって「V2」という別の書き方が提案されました。</p>
<p>問題は、V1 だとプロパティ初期化子が使えないこと。</p>
<pre class="source" title="Records に対して初期化子を使いたい">
<code><span class="reserved">class</span> <span class="type">Records</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> X { <span class="reserved">get</span>; }
    <span class="reserved">public</span> <span class="reserved">int</span> Y { <span class="reserved">get</span>; }
    <span class="reserved">public</span> <span class="type">Records</span>(<span class="reserved">int</span> <span class="variable">x</span>, <span class="reserved">int</span> <span class="variable">y</span>) =&gt; (X, Y) = (<span class="variable">x</span>, <span class="variable">y</span>);
    <span class="comment">// 以下略</span>
}
 
<span class="reserved">public</span> <span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> <span class="method">Main</span>()
    {
        <span class="comment">// こうは書ける。</span>
        <span class="reserved">var</span> <span class="variable">r1</span> = <span class="reserved">new</span> <span class="type">Records</span>(1, 2);
 
        <span class="comment">// こう書きたいけど、これが V1 だと無理。</span>
        <span class="reserved">var</span> <span class="variable">r2</span> = <span class="reserved">new</span> <span class="type">Records</span> { X = 1, Y = 2 };
 
        <span class="comment">// こんな感じで「部分書き換え」もしたい。</span>
        <span class="comment">// X は r2.X を引き継ぎつつ、Y だけ書き換えた新しいインスタンスを作りたい。</span>
        <span class="reserved">var</span> <span class="variable">r3</span> = <span class="variable">r2</span> with { Y = 3};
    }
}
</code></pre>
<h3>records V2</h3>
<p>そこで今回提案されているのが records V2 (nominal records) で、
以下のように、「initonly」なプロパティを定義できるようにするのはどうかというものです。</p>
<pre class="source" title="initonly プロパティ">
<code><span class="reserved">class</span> <span class="type">Records</span>
{
    <span class="reserved">public</span> initonly <span class="reserved">int</span> X { <span class="reserved">get</span>; }
    <span class="reserved">public</span> initonly <span class="reserved">int</span> Y { <span class="reserved">get</span>; }
}
 
<span class="reserved">public</span> <span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> <span class="method">Main</span>()
    {
        <span class="comment">// こう書けるようにする。</span>
        <span class="reserved">var</span> <span class="variable">r2</span> = <span class="reserved">new</span> <span class="type">Records</span> { X = 1, Y = 2 };
        <span class="reserved">var</span> <span class="variable">r3</span> = <span class="variable">r2</span> with { Y = 3};
    }
}
</code></pre>
<p>仕組み的には、以下のように、「<code>readonly</code>が付いてるんだけどコンストラクター以外から書き換えられる set メソッドを用意」を考えているそうです。</p>
<pre class="source" title="readonly なフィールドを書き換える set メソッド">
<code><span class="reserved">class</span> <span class="type">Records</span>
{
    <span class="comment">// public initonly int X { get; } に対して</span>
 
    <span class="comment">// コンパイラーは &lt;Backing&gt;_X みたいな C# では書けない名前でフィールドを生成してる。</span>
    <span class="comment">// ここでは、説明のために単に _X で書く。</span>
    <span class="reserved">private</span> <span class="reserved">int</span> _X;
 
    <span class="comment">// get アクセサーに相当するメソッド</span>
    <span class="reserved">public</span> <span class="reserved">int</span> <span class="method">get_X</span>() =&gt; _X;
 
    <span class="comment">// set アクセサーに相当するメソッド</span>
    [<span class="type">initonly</span>]
    <span class="reserved">public</span> <span class="reserved">void</span> <span class="method">set_X</span>(<span class="reserved">int</span> <span class="variable">x</span>) =&gt; _X = <span class="variable">x</span>;
}
</code></pre>
<p><code>[initonly]</code> 属性のところは、単なる(C# コンパイラーだけが使う)属性じゃなくて、
.NET ランタイムが解釈して特別扱いできる属性値(modreq)にしたいそうです。</p>
<p>現状の .NET の仕様では、こういう <code>readonly</code> なものの強制書き換えは unverifiable(安全性を検証できなくなる) だけど、unsafe ではないとのこと。
verifiable にするためにも、<code>[initonly]</code> が付いたメソッドには「コンストラクターの直後以外で呼べない」などの制限を掛けるという方針。</p>
<p><code>with</code> (部分書き換え)については <code>WithConstructor</code> という特別なメソッドを用意して、それに対してコンストラクター同様の制限を掛ける方式を検討中とのこと。</p>
<h3>現状の records 要約</h3>
<p>3つに分けて考えるとよさそうです。</p>
<ul>
<li>primary コンストラクター (positional records)</li>
<li>initonly プロパティ (nominal records)</li>
<li>data class/data struct</li>
</ul>
<p>1つ目の primary コンストラクターは、以下のような書き方で、
コンストラクター(の引数)とプロパティを同時に定義する書き方。</p>
<pre class="source" title="primary コンストラクター (positional records)">
<code><span class="reserved">class</span> <span class="type">Records</span>(<span class="reserved">int</span> X);
   
<span class="comment">// ↓解釈結果</span>
 
<span class="reserved">class</span> <span class="type">Records</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> X { <span class="reserved">get</span>; }
    <span class="reserved">public</span> <span class="type">Records</span>(<span class="reserved">int</span> <span class="variable">X</span>) =&gt; <span class="reserved">this</span>.X = <span class="variable">X</span>;
}
</code></pre>
<p>2つ目が今日話した initonly プロパティ。
immutable なデータ構造に対してプロパティ初期化子が使えるようにするもの。</p>
<pre class="source" title="initonly プロパティ">
<code><span class="reserved">class</span> <span class="type">Records</span>
{
    <span class="reserved">public</span> initonly <span class="reserved">int</span> X { <span class="reserved">get</span>; }
}
 
<span class="comment">// ↓解釈結果</span>
 
<span class="reserved">class</span> <span class="type">Records</span>
{
    <span class="reserved">private</span> <span class="reserved">int</span> _X;
    <span class="reserved">public</span> <span class="reserved">int</span> <span class="method">get_X</span>() =&gt; _X;
    [<span class="type">InitOnly</span>]
    <span class="reserved">public</span> <span class="reserved">void</span> <span class="method">set_X</span>(<span class="reserved">int</span> <span class="variable">x</span>) =&gt; _X = <span class="variable">x</span>;
}
</code></pre>
<p>3つ目は、<code>data class</code>/<code>data struct</code> と書くことで、プロパティから <code>Equals</code>や<code>GetHashCode</code>、<code>Deconstruct</code>などの関連メソッドを自動生成する機能。
要は、これまでの提案と比べると、primarily コンストラクター が別機能として独立したことになります。
(キーワードは仮。<code>data</code> じゃなくて <code>record</code> キーワードになったりはするかも。)</p>
<pre class="source" title="data class">
<code><span class="comment">// data が付く。</span>
data <span class="reserved">class</span> <span class="type">Records</span>
{
    <span class="comment">// 中身自体は既存の C# コード。</span>
    <span class="reserved">public</span> <span class="reserved">int</span> X { <span class="reserved">get</span>; <span class="reserved">set</span>; }
    <span class="reserved">public</span> <span class="reserved">int</span> Y { <span class="reserved">get</span>; <span class="reserved">set</span>; }
}
 
<span class="comment">// ↓解釈結果</span>
 
<span class="reserved">class</span> <span class="type">Records</span> : <span class="type">IEquatable</span>&lt;<span class="type">Records</span>&gt;
{
    <span class="reserved">public</span> <span class="reserved">int</span> X { <span class="reserved">get</span>; <span class="reserved">set</span>; }
    <span class="reserved">public</span> <span class="reserved">int</span> Y { <span class="reserved">get</span>; <span class="reserved">set</span>; }
    <span class="reserved">public</span> <span class="reserved">void</span> <span class="method">Deconstruct</span>(<span class="reserved">out</span> <span class="reserved">int</span> <span class="variable">x</span>, <span class="reserved">out</span> <span class="reserved">int</span> <span class="variable">y</span>) =&gt; (<span class="variable">x</span>, <span class="variable">y</span>) = (X, Y);
    <span class="reserved">public</span> <span class="reserved">bool</span> <span class="method">Equals</span>(<span class="type">Records</span> <span class="variable">other</span>) =&gt; (X, Y) == (<span class="variable">other</span>.X, <span class="variable">other</span>.Y);
    <span class="comment">// その他、GetHashCode, == と !=, Equals(object) 等々…</span>
}
</code></pre>
<p>primary コンストラクター を独立させたのと、今回 initonly プロパティを足したわけですが、
要するに、これらの混在もできる予定です。</p>
<pre class="source" title="3つの機能の混在">
<code><span class="comment">// primary コンストラクターと、</span>
data <span class="reserved">class</span> <span class="type">Records</span>(<span class="reserved">int</span> X)
{
    <span class="comment">// initonly プロパティと、</span>
    <span class="reserved">public</span> initonly <span class="reserved">int</span> Y { <span class="reserved">get</span>; }

    <span class="comment">// 既存の普通のプロパティが混在。</span>
    <span class="reserved">public</span> <span class="reserved">int</span> Z { <span class="reserved">get</span>; <span class="reserved">set</span>; }
 
    <span class="comment">// data が付いてるので Equals とかがコンパイラー生成される。</span>
    <span class="comment">// (X, Y, Z から生成。)</span>
}
</code></pre> ]]></description>
				<pubDate>Sat, 03 Aug 2019 19:16:49 +0900</pubDate>
			</item>
			<item>
				<title>Visual Studio 16.2 GA と 16.3 Preview 1</title>
				<link>http://ufcpp.net/blog/2019/7/vs16_3_p1/</link>
				<description><![CDATA[ <p>一昨日、Visual Studio 2019 16.2 の Generally Available と 16.3 の Preview 1 が出ました。
あと、.NET Core 3.0 Preview 7 も出ました。</p>
<ul>
<li><a href="https://devblogs.microsoft.com/visualstudio/visual-studio-2019-version-16-2-generally-available-and-16-3-preview-1/">Visual Studio 2019 version 16.2 Generally Available and 16.3 Preview 1</a></li>
<li><a href="https://devblogs.microsoft.com/dotnet/announcing-net-core-3-0-preview-7/">Announcing .NET Core 3.0 Preview 7</a></li>
</ul>
<p>16.2 の機能:</p>
<ul>
<li>テスト エクスプローラーの UI が見やすくなった</li>
</ul>
<p>16.3 Preview 1 の機能:</p>
<ul>
<li>起動画面でのプロジェクト検索や、プロジェクト テンプレートの検索がしやすくなった</li>
<li>
.NET Core 3.0 や C# 8.0 のサポート追加
<ul>
<li><code>LangVersion</code> を <code>8.0</code> や <code>preview</code> にしなくても C# 8.0 が有効</li>
</ul>
</li>
</ul>
<p>.NET Core 3.0 Preview 7</p>
<ul>
<li>Go Live (自己責任で、製品環境で使ってもいい状態)になった</li>
<li>
インストール サイズ改善
<ul>
<li>インストーラーの状態で3割減、インストール後のディスク サイズで 75%減</li>
<li>Alpine の Docker イメージのサイズが 148MB に</li>
</ul>
</li>
</ul>
<h2>.NET Core 3.0/C# 8.0</h2>
<p>ようやく、.NET Core 3.0/C# 8.0 が最終形になってきました。
前述の通り、Visual Studio 16.3 ではもう C# 8.0 が default です。
<code>LangVersion</code>の明示は要らなくなりました。</p>
<p>.NET Core 3.0 が Go Live になったので、今後、Generally Available になるまであまり変化はないはずです。</p>
<p>素直に「もう完成してる」「バグ修正を除けばもう変化はない」と言えればすっきりするんですけどね…
<a href="https://github.com/ufcpp/UfcppSample/issues/255">null 許容参照型</a>がらみがどうもまだリリースされ切っていないようで。</p>
<p>(まあ、null 許容参照型の変化は文法には関係なくて、「C# コンパイラーが属性をどう扱うか」で「警告の有無が変わる」というものです。
一応、文法自体はもうさすがに今後 C# 8.0 の正式リリースまでに変化することはないと思います。)</p>
<h3>null 許容参照型</h3>
<p>ブログ的に Visual Studio 16.2 Preview 4 (7月19日に出てた)の話はすっ飛ばしちゃいましたが、
16.2 Preview 4 辺りでだいぶ null 許容参照型の実装は進んでいました。
ただ、ちゃんと実装されているようなされていないような…</p>
<p>例えば以下のようなコード。</p>
<pre class="source" title="MabyNull/NotNull 属性">
<code><span class="reserved">using</span> System;
<span class="reserved">using</span> System.Diagnostics.CodeAnalysis;
 
<span class="reserved">public</span> <span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> <span class="method">Main</span>()
    {
        <span class="comment">// MaybeNull が付いているので、string だけど null が返ることがある</span>
        <span class="reserved">var</span> <span class="variable">a</span> = <span class="method">MaybeNull</span>&lt;<span class="reserved">string</span>&gt;();
        <span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="warning"><span class="variable">a</span></span>.Length); <span class="comment">// 警告</span>
 
        <span class="comment">// NotNull が付いているので、string? だけど null は返ってこない</span>
        <span class="reserved">var</span> <span class="variable">b</span> = <span class="method">NotNull</span>&lt;<span class="reserved">string</span>?&gt;();
        <span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="variable">b</span>.Length);
    }
 
    [<span class="reserved">return</span>: <span class="type">MaybeNull</span>]
    <span class="reserved">static</span> <span class="type">T</span> <span class="method">MaybeNull</span>&lt;<span class="type">T</span>&gt;() =&gt; <span class="warning"><span class="reserved">default</span></span>; <span class="comment">// ただ、ここで警告出ちゃう(出ないのが正しいはず)</span>
 
    [<span class="reserved">return</span>: <span class="type">NotNull</span>]
    <span class="reserved">static</span> <span class="type">T</span> <span class="method">NotNull</span>&lt;<span class="type">T</span>&gt;() <span class="reserved">where</span> <span class="type">T</span> : <span class="reserved">class</span>? =&gt; <span class="warning"><span class="reserved">default</span></span>;
}
</code></pre>
<p><code>MabyNull</code>/<code>NotNull</code> 属性、使う側は対応しているけど、メソッド定義側が対応していなかったり。
この辺りは Visual Studio 16.3 Preview 1 でも変化なし。</p>
<p><a href="/study/csharp/resource/nullablereferencetype/">C# によるプログラミング入門に null 許容参照型のページを追加</a>し始めてるんですけど、
まだリリースに含まれていない挙動が多くて書きづらい…
(先週こっそり書き始めてこっそりもうページはあるんですけど、背景説明だけで力尽きてる。)</p>
<p><a href="https://github.com/dotnet/roslyn/issues/35816">roslyn 上の issue</a> からたどるに、
実装自体はあって、結構 merge 済みのものも多いんですけども。
まだリリースには反映されていないようです。</p>
<p>あと、<a href="https://github.com/dotnet/coreclr/issues/25488">今からマイルストーンを 3.0 に変えて大丈夫なの？という issue</a>もあったり。
(型引数に対して属性を付けたい、付けれないと null 許容参照型で困るという話。)</p>
 ]]></description>
				<pubDate>Sat, 27 Jul 2019 15:50:55 +0900</pubDate>
			</item>
			<item>
				<title>Visual Studio 16.2 Preview 3、notnull 制約</title>
				<link>http://ufcpp.net/blog/2019/6/vs16_2_p3/</link>
				<description><![CDATA[ <p><a href="https://docs.microsoft.com/ja-jp/visualstudio/releases/2019/release-notes#16.1.4">Visual Studio 16.1.4</a> と <a href="https://docs.microsoft.com/en-us/visualstudio/releases/2019/release-notes-preview#16.2.0-pre.3.0">Visual Studio 16.2 Preview 3</a>が出たみたいです。</p>
<p>見た感じ、大半が不具合の修正っぽい雰囲気。</p>
<p>C# 的には、<a href="https://github.com/dotnet/roslyn/milestone/48?closed=1">16.2.P3 マイルストーン</a>の履歴的に、そろそろ <a href="/blog/2018/12/cs8nrt/">null 許容参照型</a>の作業が本格化していそうで、「<a href="/study/csharp/">C# によるプログラミング入門</a>」の対応作業もそろそろやらなきゃ… と身構えていたんですが。
実際に 16.2 Preview 3 を触ってみると、あんまり入ってなさげ。Preview 4 に繰り越されたみたいです。</p>
<p>唯一、動作確認が取れたのが以下の機能。notnull 制約。</p>
<pre class="source" title="notnull 制約">
<code><span class="reserved">using</span> System;
 
<span class="reserved">class</span> <span class="type">C</span>&lt;<span class="type">T</span>&gt;
    <span class="reserved">where</span> <span class="type">T</span> : <em>notnull</em>
{
    <span class="reserved">public</span> <span class="type">T</span> Value { <span class="reserved">get</span>; }
 
    <span class="reserved">public</span> <span class="type">C</span>(<span class="type">T</span> <span class="variable">value</span>) =&gt; Value = <span class="variable">value</span>;
}
 
<span class="reserved">public</span> <span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> <span class="method">Main</span>()
    {
        <span class="reserved">var</span> <span class="variable">c</span> = <span class="reserved">new</span> <span class="type">C</span>&lt;<span class="reserved">string</span>&gt;(<span class="string">&quot;&quot;</span>);
        <span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="variable">c</span>.Value.Length);
 
        <span class="reserved">var</span> <span class="variable">c1</span> = <span class="reserved">new</span> <span class="type">C</span>&lt;<span class="reserved">int</span>&gt;(1);
        <span class="reserved">var</span> <span class="variable">c2</span> = <span class="reserved">new</span> <span class="type">C</span>&lt;<span class="reserved">int</span>?&gt;(1); <span class="comment">// 警告あり</span>
        <span class="reserved">var</span> <span class="variable">c3</span> = <span class="reserved">new</span> <span class="type">C</span>&lt;<span class="reserved">string</span>?&gt;(<span class="string">&quot;&quot;</span>); <span class="comment">// 警告あり</span>
        <span class="reserved">var</span> <span class="variable">c4</span> = <span class="reserved">new</span> <span class="type">C</span>&lt;<span class="reserved">string</span>&gt;(<span class="reserved">null</span>); <span class="comment">// 警告あり</span>
    }
}
</code></pre>
<p>これも、Preview 3 で対応するつもりがそんなになかったのか、
コンパイルはできるものの Visual Studio 上は未対応(コード補完もハイライトも効かない)な状態です。
(一方で、特にコンパイル エラーになったりはしない。)</p>
<h2>notnull 制約</h2>
<p>そういえば、この notnull 制約の話はあんまりこのブログで取り上げていなかったはず。
null 許容参照型周りはちょっと目を離すと結構実装が変わっているんで…</p>
<p>見たまんま、「この型引数は null を認めない」の意味です。
<code>int</code> や <code>string</code> は受け付けるけども、<code>int?</code> や <code>string?</code> は受け付けない(警告のみですが)という型制約になります。
null 許容<em>値型</em>とnull 許容<em>参照型</em>を統一的に扱いたいがための仕様。</p>
<p>ただ、以下のようなコードは今のところ受け付けません。
notnull とは… (仕組み上しょうがなさそう。これを受け付けるためには .NET ランタイム側での対応が必要そうで結構な手間。)</p>
<pre class="source" title="T? とは書けない問題">
<code><span class="reserved">class</span> <span class="type">C</span>&lt;<span class="type">T</span>&gt;
    <span class="reserved">where</span> <span class="type">T</span> : notnull
{
    <span class="comment">// せっかく notnull にしても、T? とは書けない。</span>
    <span class="comment">// [return: MaybeNull] という属性ベースの回避策を取る予定。</span>
    <span class="reserved">public</span> <span class="type">T</span>? <span class="method">X</span>() =&gt; <span class="reserved">default</span>;
}
</code></pre>
<p>元々は、<code>where T : object</code> (<code>object</code> に <code>?</code> がついてないんだから非 null 扱い)でいいんじゃないかって言われてたんですが、「<code>object</code> だと参照型っぽくて値型に使えなさそうな印象がある」という理由で新規キーワード追加になりました。</p>
<p>さらに言うと<a href="https://github.com/dotnet/csharplang/blob/master/meetings/2019/LDM-2019-05-15.md">当初予定</a> では nonnull だったのが、今回の実装だと notnull (non と not の差)になっていたり。</p>
<p>C# ってあんまりこういう、2単語(not null)をつないだキーワードを採用することが少ないので、ちょっと最終的にもこのまま進むのかわからなかったりはします。荒れそう…</p>
 ]]></description>
				<pubDate>Wed, 26 Jun 2019 20:09:16 +0900</pubDate>
			</item>
			<item>
				<title>Visual Studio 16.2 Preview 2 &amp; .NET Core 3.0 Preview 6</title>
				<link>http://ufcpp.net/blog/2019/6/vs16_2_p2/</link>
				<description><![CDATA[ <p><a href="https://docs.microsoft.com/en-us/visualstudio/releases/2019/release-notes-preview#16.2.0-pre.2.0">Visual Studio 16.2 Preview 2</a> と <a href="https://devblogs.microsoft.com/dotnet/announcing-net-core-3-0-preview-6/">.NET Core 3.0 Preview 6</a> が来てますね。</p>
<p>Visual Studio 16.2 Preview 2 の方は、自分が気になったのだと、<code>switch</code>ステートメントを<a href="/study/csharp/cheatsheet/ap_ver8/#switch-expression"><code>switch</code>式</a>に書き換えてくれるリファクタリング機能が入ったとかあるみたいです。</p>
<p>.NET Core 3.0 Preview 6 は、パフォーマンス カウンターで GC とかスレッド周りの詳細な情報が取れるようになったり、AOT シナリオで「使ってなさそうなコードを消す」系の最適化が増えたり、HTTP/2 サポートが入ったみたいです。</p>
<p><a href="https://github.com/dotnet/wpf">WPFのオープンソース化</a>(リポジトリができた時点ではスカスカだった)も完了したとのこと。</p>
<p>※追記: .NET Core 3.0 Preview 6 をインストールすると、<a href="https://twitter.com/ufcpp/status/1139167755242881029">WPF アプリ(の .NET Core 版)が英語ロケールでしか動かなくなるみたいです</a>。ご注意を。</p>
<p>あと、<a href="https://github.com/dotnet/corefx/blob/master/src/Common/src/CoreLib/System/Diagnostics/CodeAnalysis/NullableAttributes.cs">null許容参照型に関連する属性</a>が標準で入ったみたいです。
ただ、これは型として存在しているだけで、C# コンパイラー側が解釈できるようになるのは 16.2 Preview 3 以降随時みたいです。</p>
<h2>C# 8.0 in 16.2 Preview 2</h2>
<p>C# 的には、<a href="/blog/2019/5/vs16_2_p1/">Preview 1の頃</a>にあったやばいバグは治りました。
(<code>stackalloc</code>を使っただけで不正な IL を生成して実行できなくなる問題。)
これで今度こそ、気兼ねなく<a href="/study/csharp/cheatsheet/ap_ver8/#nested-stackalloc">式中の stackalloc</a>を試せます。</p>
<p>あと、ひそかに今回から入ったのが、</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/pull/35756">Support re-abstraction of interface members in derived interfaces #35756</a></li>
</ul>
<p>です。
以下のようなやつ。一度デフォルト実装を持ったメソッドを、もう1度抽象メソッドに変えて、派生側での実装を必須に変える機能。</p>
<div>
<script src="https://gist.github.com/ufcpp/26d6eda8b1bdf91cc785bd7478d95b89.js"></script>
</div>
<p>前述の通り<a href="https://github.com/dotnet/corefx/blob/master/src/Common/src/CoreLib/System/Diagnostics/CodeAnalysis/NullableAttributes.cs">null許容参照型に関連する属性</a>は .NET Core 3.0 側には入ったわけですが、
C#コンパイラーが対応し出すのは次の Preview 以降みたいです。
スケジュール感は以下のページに書かれている通り。</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/issues/35816">Nullable Reference Type Changes #35816</a></li>
</ul>
<p>6/10 で終わっている作業はたぶん 16.2 Preview 3 で入ります。</p>
<p>ちなみに、以下のような issue もあります。</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/issues/36140">Change C# 8 to be the default, non-experimental language version #36140</a></li>
</ul>
<p>要するに、16.3 で C# 8.0 の preview が外れ、default が 8.0 になるという予告。
<a href="https://www.microsoft.com/en-us/build">build</a>で「7月にRC、9月にGA」という話をしていたんで、それがそれぞれ 16.2 (で C# 8.0 も RC)、16.3 (で GA)ということなんだと思います。</p>
 ]]></description>
				<pubDate>Thu, 13 Jun 2019 22:37:08 +0900</pubDate>
			</item>
			<item>
				<title>C# で、同じソースコードから常に同じバイナリを生成する</title>
				<link>http://ufcpp.net/blog/2019/5/deterministicbuilds/</link>
				<description><![CDATA[ <p>昔、<a href="https://gist.github.com/ufcpp/f3cc89e8c266997063eb2c633114668a">gist にだけ置いてて、そういえばブログに書いてなかったもの</a>を思い出したので書いておくことに。</p>
<p>(一応、部分的には言及したことがあるんですけど、ちゃんとした話はしたことがなかったはず。)</p>
<h2>決定論的ビルド</h2>
<p>3年くらい前まで、C# コードをコンパイルすると、ソースコードを一切書き換えていなくても、生成結果の exe/dll や <a href="https://docs.microsoft.com/ja-jp/visualstudio/debugger/specify-symbol-dot-pdb-and-source-files-in-the-visual-studio-debugger?view=vs-2019">pdb</a> のバイナリが変化していました(決定性(deteminism)がない)。</p>
<p>原因は以下の2つです。</p>
<ul>
<li>バイナリ中に埋め込まれる GUID にタイムスタンプと乱数から生成される値を使っていた</li>
<li>デバッグ用のファイル情報がフルパスで埋め込まれていた</li>
</ul>
<p>GUID の方はタイムスタンプと乱数なので本当に致命的で、ローカルで再コンパイルしても毎回バイナリが変化していました。</p>
<p>フルパスの方は基本的には pdb (デバッグ用シンボル情報)だけの問題なんですが、
exe/dll でも、<a href="/study/csharp/ap_ver5.html#CallerInfo"><code>CallerFilePath</code> 属性</a>を使ったりすると文字列定数でフルパスが埋め込まれます。
ローカルで再コンパイルする分には変化しないんですが、<code>C:\users\ユーザー名\Documents\</code> みたいなのが pdb 中に残ってしまってみっともないです。
また、クラウド ビルド環境では常に同じパスでコンパイルされるとは限らないので、やっぱりバイナリの一意性を確保できなくなります。</p>
<p>バイナリが決定論的でないというのは単に不格好という問題ではなく、
CI/CD 環境でキャッシュが効かなくてなってサーバー リソースを食いつぶすことにつながったりします。</p>
<p>これらに対処するための C# コンパイラー(csc)オプションは、2016年頃から提供されるようになりました(参考: <a href="https://blog.paranoidcoding.com/2016/04/05/deterministic-builds-in-roslyn.html">Deterministic builds in Roslyn</a>)。</p>
<ul>
<li>
<code>/deteministic</code>: GUID の算出にタイムスタンプと乱数を使わなくする
<ul>
<li>ソースコードなどのハッシュ値から計算するので、ソースコードに変化がない限り一意</li>
</ul>
</li>
<li>
<code>/pathmap</code>: デバッグ情報などで使うファイルのパスを所定のルールで置き換え可能にする
<ul>
<li><code>置き換え元=置き換え後</code> という形式で、単純な置換をするだけ</li>
<li>置き換え元の方に <code>$(MSBuildProjectDirectory)</code> とかを指定して、置き換え先の方を<code>/</code>とかあたりさわりのない固定の文字列にしておけば、どの環境でも同じ結果が得られる</li>
</ul>
</li>
</ul>
<h2>csproj での指定</h2>
<p>C# コンパイラー オプションとしては3年前に実装されていても、
dotnet コマンドでのビルド(csproj ファイル中にオプション記述)できるようになったのはもうちょっと後です。
それでも、Visual Studio 2017 (2年前)から、以下のオプションが指定できるようになりました。</p>
<ul>
<li><code>&lt;Deterministic&gt;</code>: csc の <code>/deteministic</code> に相当</li>
<li><code>&lt;PathMap&gt;</code>: csc の <code>/pathmap</code> に相当</li>
</ul>
<p>ちなみに、<a href="/blog/2017/5/newcsproj/">SDK-based なプロジェクト</a>の場合、
<code>&lt;Deterministic&gt;</code> がデフォルトで true になっています。
タイムスタンプ問題は何もしなくても解消済み。</p>
<p>問題は <code>&lt;PathMap&gt;</code> の方で、こちらは明示的に指定しないと今でもフルパスが入ります。</p>
<h2>Directory.Build</h2>
<p>ちなみに、<code>&lt;PathMap&gt;</code> は <a href="/blog/2018/12/directorybuild/"><code>Directory.Build.props</code></a> に書いておいても動作します。
プロジェクト1個1個に設定を入れるのも面倒なので、自分はリポジトリのルートに1個、以下のような <code>Directory.Build.props</code> を入れています。</p>
<pre class="xsource" title="">
<code><span class="attvalue">&lt;</span><span class="element">Project</span><span class="attvalue">&gt;</span>
 
<span class="attvalue">  &lt;</span><span class="element">PropertyGroup</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">LangVersion</span><span class="attvalue">&gt;</span>latest<span class="attvalue">&lt;/</span><span class="element">LangVersion</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">RepoRoot</span><span class="attvalue">&gt;</span>$([System.IO.Path]::GetFullPath(&#39;$(MSBuildThisFileDirectory)..\&#39;))<span class="attvalue">&lt;/</span><span class="element">RepoRoot</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">PathMap</span><span class="attvalue">&gt;</span>$(RepoRoot)=.<span class="attvalue">&lt;/</span><span class="element">PathMap</span><span class="attvalue">&gt;</span>
<span class="attvalue">  &lt;/</span><span class="element">PropertyGroup</span><span class="attvalue">&gt;</span>
 
<span class="attvalue">&lt;/</span><span class="element">Project</span><span class="attvalue">&gt;</span>
</code></pre>
<p><code>$(MSBuildProjectDirectory)</code> (csproj があるフォルダー)からではなく、
<code>$(MSBuildThisFileDirectory)</code> (props があるフォルダー)を基準にして、
リポジトリ内の相対パスは残すようにしています。</p>
<p>単に <code>$(MSBuildThisFileDirectory)</code> ではなく、その1つ上のフォルダーまで(git clone してきてるリポジトリ名まで)残すようにしています。</p>
<h2>PathMap の例</h2>
<p><code>&lt;Deterministic&gt;</code> の方は一応過去に少し触れたことがあるのと、
SDK-based な csproj を使う限りもう今はデフォルトで true なので、
改めて例を挙げるほどでもないかと思います。
ということで、<code>&lt;PathMap&gt;</code> の方。</p>
<ul>
<li><a href="https://github.com/ufcpp/UfcppSample/tree/master/Demo/2019/PathMap/PathMap"><code>&lt;PathMap&gt;</code> の例</a></li>
</ul>
<p>実行すると、<code>CallerFilePath</code> 属性で取ったファイル名と、例外のスタックトレースが書き換わってる(短くなってる)ことがわかります。</p>
<h4>余談</h4>
<p>2年くらい前の機能をなんで今更ブログに書くことになったかというと、
今日、ちょうど「ログ出力で <code>CallerFilePath</code> 使うか」という話になったからだったり。
「フルパス入るの嫌か」「あっ、でも、確か <code>PathMap</code> 導入してたはず」みたいな。</p>
<p>で、その <code>PathMap</code> 導入がいつかというと、このとき:</p>
<ul>
<li><a href="https://twitter.com/ufcpp/status/1106533083224788997">今年3月15日の投稿</a></li>
</ul>
<p>違う人がコンパイルするたびに差分が出て困ったところで、ネットで検索してみたら自分の gist が出てきたというよくあるやつ。</p>
 ]]></description>
				<pubDate>Fri, 24 May 2019 23:01:00 +0900</pubDate>
			</item>
			<item>
				<title>Visual Studio 16.1.0 &amp; 16.2 Preview 1</title>
				<link>http://ufcpp.net/blog/2019/5/vs16_2_p1/</link>
				<description><![CDATA[ <p>Visual Studio 16.1 のリリースと、16.2 の Preview 1 が来ていますね。</p>
<ul>
<li><a href="https://docs.microsoft.com/en-us/visualstudio/releases/2019/release-notes#16.1.0">Visual Studio 2019 version 16.1</a></li>
<li><a href="https://docs.microsoft.com/en-us/visualstudio/releases/2019/release-notes-preview#16.2.0-pre.1.0">Visual Studio 2019 version 16.2 Preview 1</a></li>
</ul>
<h2>16.1</h2>
<p>16.1 の方は、<a href="/blog/2019/5/build2019/">こないだの Preview 3</a>からそんなに変わってなくて、割かし「リリースされました」という感じ。</p>
<p><a href="/study/csharp/cheatsheet/ap_ver8/">C# 8.0</a> 的には、</p>
<ul>
<li><a href="/blog/2018/12/cs8ranges/">Ranges</a>は たぶん、今の挙動で確定</li>
<li>
<a href="/study/csharp/cheatsheet/ap_ver8/#switch-expression"><code>switch</code>式</a>
<ul>
<li>優先度が <code>+</code> よりも上になってる</li>
<li><a href="https://github.com/dotnet/csharplang/issues/2389">Target-typed switch</a> は 8.0 候補になってて、かつ、未実装</li>
</ul>
</li>
<li>
<a href="/blog/2018/12/cs8asyncstreams/">非同期イテレーター</a>
<ul>
<li><code>EnumeratorCancellation</code> 属性を付けた引数に <code>CancellationToken</code> が渡るように</li>
<li>変更が確定していて、16.2 Preview 1 ですでに挙動が違う(後述)</li>
</ul>
</li>
<li><a href="/study/csharp/cheatsheet/ap_ver8/#default-imeplementation-of-interface">インターフェイスのデフォルト実装</a>も 16.2 Preview 1 で変更あり(後述)</li>
<li><a href="/blog/2018/12/cs8nrt/">null 許容参照型</a>は相変わらず作業真っ最中</li>
</ul>
<p>という感じ。</p>
<h2>16.2 Preview 1</h2>
<p>IDE 的には以下のようなものが増えてるみたいです。</p>
<ul>
<li>プロジェクトの新規作成で、作成したいアプリのタイプで検索できるように</li>
<li>テスト エクスプローラーがだいぶ見やすく</li>
</ul>
<p>あと、Developer PowerShell (開発ツールがらみの環境変数とかパスが通った状態の PowerShell)が追加されたみたいです。
これまでもあった <a href="https://docs.microsoft.com/ja-jp/dotnet/framework/tools/developer-command-prompt-for-vs">Developer Command Prompt</a> の PowerShell 版。</p>
<p><em>ちょっと C# コンパイラーに致命的なバグがありそうなので注意</em>。
<a href="/study/csharp/resource/span/#safe-stackalloc">安全な <code>stackalloc</code></a>を使うと不正なコードを生成して、プログラムが起動できなくなります。
(正確に言うと、<code>stackalloc</code> を書いたメソッドを呼んだ瞬間、<code>InvalidProgram</code>例外発生。)
修正済みっぽいんですけど、16.2 Preview 1 には反映されていない状態。</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/issues/35764">Invalid IL generated for stackalloc assigned to Span #35764</a></li>
</ul>
<p>C# 8.0 的には、16.1 の方と以下の差があります。</p>
<ul>
<li><a href="/blog/2018/12/cs8asyncstreams/">非同期イテレーター</a>の<code>EnumeratorCancellation</code> 属性の仕様変更</li>
<li><a href="/study/csharp/oo_inherit.html#non-virtual-base-access"><code>base(T)</code></a> 削除</li>
<li><a href="https://github.com/dotnet/csharplang/issues/1412">stackalloc in nested expressions</a> の追加</li>
</ul>
<p>あと、null許容参照型をプロジェクト単位で有効化するための設定も、<code>&lt;Nullable&gt;enable&lt;/Nullable&gt;</code> に変わっています(16.1 までは <code>NullableContextOptions</code>)。</p>
<h3>非同期イテレーターの仕様変更</h3>
<p><code>X(ct1).WithCancellation(ct2)</code> みたいなのを書いたときの挙動が変わります。</p>
<pre class="source" title="">
<code><span class="reserved">using</span> System.Collections.Generic;
<span class="reserved">using</span> System.Runtime.CompilerServices;
<span class="reserved">using</span> System.Threading;
<span class="reserved">using</span> System.Threading.Tasks;
 
<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">async</span> <span class="type">Task</span> <span class="method">Main</span>()
    {
        <span class="reserved">var</span> <span class="variable">c1</span> = <span class="reserved">new</span> <span class="type">CancellationTokenSource</span>();
        <span class="reserved">var</span> <span class="variable">c2</span> = <span class="reserved">new</span> <span class="type">CancellationTokenSource</span>();
 
        <span class="comment">// キャンセルなし</span>
        <span class="reserved">await</span> <span class="control">foreach</span> (<span class="reserved">var</span> <span class="variable">x</span> <span class="control">in</span> <span class="method">X</span>()) ;
 
        <span class="comment">// AscynEnumerable 生成時に c1 が渡る</span>
        <span class="reserved">await</span> <span class="control">foreach</span> (<span class="reserved">var</span> <span class="variable">x</span> <span class="control">in</span> <span class="method">X</span>(<span class="variable">c1</span>.Token)) ;
 
        <span class="comment">// GetAsyncEnumerator 時に c2 が渡る</span>
        <span class="reserved">await</span> <span class="control">foreach</span> (<span class="reserved">var</span> <span class="variable">x</span> <span class="control">in</span> <span class="method">X</span>().<span class="method">WithCancellation</span>(<span class="variable">c2</span>.Token)) ;
 
        <span class="comment">// 旧挙動: c2 だけが渡る</span>
        <span class="comment">// 新挙動: c1, c2 の両方が渡る。内部で CreateLinkedTokenSource</span>
        <span class="reserved">await</span> <span class="control">foreach</span> (<span class="reserved">var</span> <span class="variable">x</span> <span class="control">in</span> <span class="method">X</span>(<span class="variable">c1</span>.Token).<span class="method">WithCancellation</span>(<span class="variable">c2</span>.Token)) ;
    }
 
    <span class="comment">// 新挙動: EnumeratorCancellation 属性付きの引数は1個に限る</span>
    <span class="reserved">static</span> <span class="reserved">async</span> <span class="type">IAsyncEnumerable</span>&lt;<span class="reserved">int</span>&gt; <span class="method">X</span>([<span class="type">EnumeratorCancellation</span>]<span class="type">CancellationToken</span> <span class="variable">ct</span> = <span class="reserved">default</span>)
    {
        <span class="reserved">await</span> <span class="type">Task</span>.<span class="method">Yield</span>();
        <span class="control">yield</span> <span class="control">break</span>;
    }
}
</code></pre>
<h3>base(T) 削除</h3>
<p><a href="/study/csharp/oo_inherit.html#non-virtual-base-access">base(T) アクセス</a>、いったん取りやめになりました。
(書いた記事どうしよう… 消すか、「今後入る予定です」に変えるか…)</p>
<p>C# コンパイラーだけでできる実装方法だと不満だそうで、 .NET Core ランタイム側も合せて修正変更したいそうです。
結果的に C# 8.0 には間に合わず、ランタイム修正ありなものをマイナー リリースするとは思えないので 9.0 以降での実装になります。</p>
<h3>stackalloc in nested expressions</h3>
<p>式のど真ん中に <code>stackalloc</code> を書けるようになりました。</p>
<pre class="source" title="">
<code><span class="reserved">using</span> System;
<span class="reserved">using</span> System.Threading.Tasks;
 
<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">int</span> <span class="method">M</span>(<span class="type">Span</span>&lt;<span class="reserved">int</span>&gt; <span class="variable">span</span>) =&gt; 0;
 
    <span class="reserved">static</span> <span class="reserved">void</span> <span class="method">Main</span>()
    {
        <span class="comment">// 引数にも書けたり</span>
        <span class="method">M</span>(<span class="reserved">stackalloc</span> <span class="reserved">int</span>[1]);
 
        <span class="comment">// 式のどこにでも書ける</span>
        <span class="control">if</span> (<span class="reserved">stackalloc</span> <span class="reserved">int</span>[1] <span class="method">==</span> <span class="reserved">stackalloc</span> <span class="reserved">int</span>[1]) { }
    }
 
    <span class="comment">// フィールド初期化子内にも書けたり</span>
    <span class="reserved">int</span> x = <span class="method">M</span>(<span class="reserved">stackalloc</span> <span class="reserved">int</span>[1]);
 
    <span class="reserved">static</span> <span class="reserved">async</span> <span class="type">Task</span> <span class="method">Async</span>()
    {
        <span class="comment">// 式中に書くなら、非同期メソッド内でも stackalloc が書ける</span>
        <span class="method">M</span>(<span class="reserved">stackalloc</span> <span class="reserved">int</span>[1]);
 
        <span class="reserved">await</span> <span class="type">Task</span>.<span class="method">Yield</span>();
    }
}
</code></pre>
<p>ぶっちゃけ、<a href="/study/csharp/cheatsheet/ap_ver8/#recursive-pattern">再帰パターン</a>のついでだそうです。
再帰パターンの導入で<a href="/study/csharp/sp_ref.html?p=2#flow-analysis">参照として返せるものの判定</a>が複雑になったらしく、
ちゃんとした判定に書き換えたらついでに <code>stackalloc</code> を書ける場所も増えたとのこと。</p>
 ]]></description>
				<pubDate>Wed, 22 May 2019 20:35:13 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 5/19: dotnet-try, .NET Core 3.0 パフォーマンス、null 許容参照型の仕様改善</title>
				<link>http://ufcpp.net/blog/2019/5/pickuproslyn0519/</link>
				<description><![CDATA[ <p>この1週間ほど、<a href="https://www.microsoft.com/en-us/build">build</a> で発表したことを改めてブログ化したものが投稿されたりとか、build が終わって落ち着いたところで本業に戻ったと思われる投稿とかがたくさんありました。</p>
<p>そのうち3つほど紹介</p>
<ul>
<li>dotnet-try</li>
<li>.NET Core 3.0 でのパフォーマンス改善</li>
<li>C# Design Notes 2件追加(どちらも null 許容参照型がらみ)</li>
</ul>
<h2>dotnet-try</h2>
<ul>
<li><a href="https://www.hanselman.com/blog/IntroducingTheTryNETGlobalToolInteractiveInbrowserDocumentationAndWorkshopCreator.aspx">Introducing the Try .NET Global Tool - interactive in-browser documentation and workshop creator</a></li>
<li><a href="https://devblogs.microsoft.com/dotnet/creating-interactive-net-documentation/">Create Interactive .NET Documentation with Try .NET</a></li>
</ul>
<p>以下のようなコマンドで簡単にインストールできるツール(<a href="https://docs.microsoft.com/ja-jp/dotnet/core/tools/global-tools">.NET Global Tool</a> という仕組み)として、 dotnet-try というものが公開されました。</p>
<pre class="console" title="">
<code>dotnet tool install --global dotnet-try
</code></pre>
<p>C# でいわゆる interactive workshop (ドキュメント中に直接コードが埋め込まれてて、実行結果が見れるような講習資料)を簡単に作れるようにしようというもの。
以下のような仕組み。</p>
<ul>
<li>普通に dotnet コマンドでコンパイルできるプロジェクト一式を書く</li>
<li>Markdown 中の  ```cs 行に、その C# コードを参照するオプションを付ける</li>
<li>プロジェクトを置いたフォルダー中で dotnet try ツールを起動する</li>
<li>dotnet try 自体が Web サーバーになっていて、ブラウザーが起動して localhost アクセスで書いたドキュメントが表示される</li>
<li>
ドキュメント中の C# コードは構文ハイライト表示されるし、実行ボタンがあって結果を出力できる
<ul>
<li><a href="https://dotnet.microsoft.com/apps/aspnet/web-apps/client">Blazor</a>を使ってるっぽい</li>
</ul>
</li>
</ul>
<h3>Try .NET Online</h3>
<p>2017年以降、 .NET 関連のドキュメントは<a href="https://docs.microsoft.com/en-us/dotnet/csharp/tutorials/intro-to-csharp/">docs.microsoft.com 上にある</a>わけですが、
その中ではサンプルの C# コードをブラウザー中で実行して結果を見れる機能があります。
これを指して「Try .NET Online」と言っています。</p>
<p>初期はほとんどの処理をサーバー上でやっていて常に通信してコードや実行結果を表示していました。
それを徐々に Blazor と Web Assembly 化しているそうで、
今はだいぶクライアント上での処理になっているみたいです。
(まだ完全にオフラインではなくて、コンパイルはサーバー側でやっていそう。)</p>
<h3>Try .NET Offline</h3>
<p>今回リリースされた dotnet-try ツールは、
「Try .NET Online」と同じドキュメントをローカル環境で書いて試せるという仕組みで、
「Try .NET Offline」と言っています。</p>
<p>普通の C# プロジェクトを作ってそれを参照する仕組みなので、
ちゃんとコンパイルできることが確認を取れているコードの一部分を参照して、
その部分の実行結果が正しく表示されます。</p>
<p>全部オープンソースです。</p>
<ul>
<li><a href="https://github.com/dotnet/try">dotnet/try</a></li>
</ul>
<p>現状、とりあえずアルファ リリースみたいです。フィードバック募集中。</p>
<p>そういう段階のツールなので、利便性はまだまだあまりよくありません。
作った interactive workshop の共有みたいなところまでは至っていなくて、
現状だと作る側も自前で GitHub ででも公開してもらって、
見る側も自前で以下のようにコマンドラインでツール起動してもらう作り。</p>
<pre class="console" title="">
<code>git clone 公開先
dotnet try cloneしてきたリポジトリ
</code></pre>
<h2>.NET Core 3.0 のパフォーマンス向上</h2>
<ul>
<li><a href="https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-core-3-0/">Performance Improvements in .NET Core 3.0</a></li>
</ul>
<p><a href="https://blogs.msdn.microsoft.com/dotnet/2017/06/07/performance-improvements-in-net-core/">.NET Core 2.0</a>や<a href="https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-core-2-1">.NET Core 2.1</a>の時にもブログがありましたが、.NET Core 3.0 でも改めて「こんな最適化をやったよ」というまとめブログが上がりました。</p>
<p>今回はまたものすごい長大な内容…</p>
<p>長くてまじめに読むのは大変ですが、概ね、以下のような感じ。</p>
<ul>
<li><a href="/study/csharp/resource/span/"><code>Span&lt;T&gt;</code></a>とか<code>Memory&lt;T&gt;</code>自体を最適化した</li>
<li><code>Span&lt;T&gt;</code>、<code>Memory&lt;T&gt;</code> を使うものを引き続き増やした</li>
<li>
<a href="/blog/2018/12/hdintrinsic/">Hardware Intrinsics</a>を全面的に適用開始
<ul>
<li>バイナリ操作とか文字列操作は本当に2～4倍高速化</li>
<li>ただし、現状は Intel CPU のみ(<a href="https://ja.wikipedia.org/wiki/%E3%82%B9%E3%83%88%E3%83%AA%E3%83%BC%E3%83%9F%E3%83%B3%E3%82%B0SIMD%E6%8B%A1%E5%BC%B5%E5%91%BD%E4%BB%A4">AVX2</a> が有効な環境でだけ2～4倍高速化)</li>
<li><a href="https://github.com/dotnet/corefx/issues/37199">ARM 系はまだまだこれから</a></li>
</ul>
</li>
<li>
非同期処理の最適化
<ul>
<li><a href="/blog/2018/3/pickuproslyn0323/"><code>IValueTaskSource</code></a>の適用範囲を増やしたり</li>
</ul>
</li>
<li>
その他、細かい最適化も大量
<ul>
<li><code>T?</code> から <code>Value</code> で値を取ってたところを <code>GetValueOrDefault</code> に置き換えて回ったり</li>
<li><code>new T[0]</code> を <code>Array.Empty&lt;T&gt;()</code> に置き換えて回ったり</li>
</ul>
</li>
</ul>
<h2>Design Notes 2件(null 許容参照型がらみ)</h2>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/2527">Added: LDM Notes for May 13, 2019 #2527</a></li>
<li><a href="https://github.com/dotnet/csharplang/issues/2536">Added: LDM Notes for May 15, 2019 #2536</a></li>
</ul>
<p>どちらも <a href="/blog/2018/12/cs8nrt/">null 許容参照型</a>がらみで、
だいぶ具体的な話。
先日、「<a href="/blog/2019/5/build2019/">そろそろ C# 8.0 に入れる機能を決めるタイムリミット</a>」という話をしましたが、
これもその一環だと思います。
そろそろ null 許容参照型の仕様も固めないとまずい。</p>
<h3>#nullable の書き方</h3>
<p>null 許容参照型(破壊的変更にならないように opt-in)を有効化するにあたって、
以下の2つの視点があります。</p>
<ul>
<li>annotations: ライブラリを提供する側として、null の許容・非許容のアノテーションを公開するかどうか</li>
<li>warnings: ライブラリを使う側として、コード解析をして null 参照に対して警告を出すかどうか</li>
</ul>
<p>移行段階としては、どちらか片方だけを有効化したいことがあります。</p>
<ul>
<li>差し当たってアノテーションだけは付けたいけど、中身の警告を全部消す作業まで手が回らない</li>
<li>差し当たって警告は出してほしいけど、自分が公開している API にまでは責任を持てないのでアノテーションは付けたくない</li>
</ul>
<p>結果、指定できるオプションは以下のようにまとめたいとのこと。</p>
<pre class="source" title="">
<code>#nullable (enable | disable | restore) [ warnings | annotations ]
</code></pre>
<ul>
<li>
enable、disable で有効・無効を切り替え
<ul>
<li>restore は1つ前のディレクティブの状態に復元</li>
<li>その後ろに何も書かなければ annotations も warnings もまとめて切り替え</li>
</ul>
</li>
<li>その後ろに warnings、 annotations を付けることで、どちらか片方だけを切り替え</li>
</ul>
<p>ソースコード中の <code>#nullable</code> ディレクティブ(その行移行の局所的に作用)と同じように、
<code>csproj</code> 中に書くタグ(プロジェクト全体に作用)も、以下のようにしたいみたいです。</p>
<ul>
<li>
タグ名はシンプルに <code>Nullable</code> にする
<ul>
<li>今は <code>NullableContextOptions</code> とかいう長い名前</li>
</ul>
</li>
<li>オプションの値も enable、disable、annotations、warnings にする</li>
</ul>
<h3>アノテーションの付け方</h3>
<p>前節の <code>#nullable enable</code> を指定した状態では、基本的に以下のようなアノテーションの付け方になります。</p>
<ul>
<li>参照型 <code>T</code> に対して単に <code>T</code> と書くと非 null</li>
<li><code>T?</code> と書くと null 許容</li>
</ul>
<p>ただ、これだとどうしてもうまくいかない場合があって、
そういうとき用に属性でのアノテーションを足したいという話。</p>
<h4>単純な事前・事後条件</h4>
<p><code>T</code> と書いていても null 許容に、<code>T?</code> と書いていても非 null に変えたい場合があります。</p>
<ul>
<li><a href="/study/csharp/sp2_generics.html#where">制約</a>未指定の <code>T</code> がジェネリック型引数の場合、値型と参照型で <code>T?</code> の意味が違うせいで <code>T?</code> と書けないので属性に頼るしかない</li>
<li>プロパティで、get は非 null だけど set は null 許容とかにしたい</li>
<li>
<a href="/study/csharp/sp_ref.html#sec-byref-param">参照引数</a>で、in/out 片側だけを null 許容にしたい
<ul>
<li>null を渡してもいいけど、メソッドを呼んだあとはその変数が null じゃなくなる保証あり</li>
<li>null を受け取れないけど、メソッド内で null を書き込む可能性あり</li>
</ul>
</li>
</ul>
<p>そこで、以下の属性を用意</p>
<ul>
<li>
事前条件
<ul>
<li><code>[AllowNull]</code>: <code>T</code> と書いていても、入力として null を受け付ける</li>
<li><code>[DisallowNull]</code>: <code>T?</code> と書いていても、入力として null を受け付けない</li>
</ul>
</li>
<li>
事後条件
<ul>
<li><code>[MaybeNull]</code>: <code>T</code> と書いていても、出力として null を返す可能性がある</li>
<li><code>[NotNull]</code>: <code>T?</code> と書いていても、出力として null を返さない</li>
</ul>
</li>
</ul>
<h4>相互依存のある事後条件</h4>
<p><code>TryParse</code> とか <code>IsNullOrEmpty</code> とか、何かメソッドを呼んだ結果 null かどうかが確定するものがあります。
こういうとき用に、以下のような属性を用意。</p>
<ul>
<li><code>[MaybeNullWhen(bool)]</code>: 戻り値が true/false の時に限り、指定した引数が null になる可能性がある</li>
<li><code>[NotNullWhen(bool)]</code>: 戻り値が true/false の時に限り、指定した引数が null でない保証がある</li>
</ul>
<p>「引数が null のときだけ戻り値も null」みたいなこともあります。
そのための属性もあり。</p>
<ul>
<li><code>[NotNullIfNotNull(string)]</code>: 指定した引数の nullability と戻り値の nullability が一致</li>
</ul>
<h4>コンパイラーによる特殊対応</h4>
<p><code>x == y</code> とか書くと、<code>x</code> の nullability が <code>y</code> に伝搬します。
<code>x</code> が非 null なことがわかっているなら、<code>y</code> も非 null で確定。</p>
<p><code>==</code> はいいとして、それと同様の効果があるメソッドがいくつかあります。</p>
<ul>
<li><code>Object.ReferenceEquals</code></li>
<li><code>Object.Equals</code></li>
<li><code>IEqualityComparer&lt;T&gt;.Equals</code></li>
<li><code>EqualityComparer&lt;T&gt;.Equals</code></li>
<li><code>IEquatable&lt;T&gt;.Equals</code></li>
</ul>
<p>こいつらは、数が限られているし、これら以外のメソッドで等値判定をすることはほとんどないので、コンパイラーにハードコードで実現したいそうです。
ちゃんと、<code>x.Equals(y)</code> で nullability が伝搬するものの、それは <code>Object.Equals</code> を特別扱いすることで実装。</p>
<p>同じく、<code>Interlocked.CompareExchange</code> も特別扱いで nullability 伝搬するそうです。</p>
<h4>フローがらみの属性</h4>
<p>今ある「<a href="/study/csharp/resource/rm_struct/#definite-assignment">確実な初期化ルール</a>」でもそうなんですが、到達できない場所のフロー解析はされません。</p>
<pre class="source" title="">
<code><span class="reserved">using</span> System;
 
<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> <span class="method">Main</span>()
    {
        <span class="reserved">int</span> <span class="variable">x</span>;
        <span class="control">return</span>;

        <span class="comment">// 本来「x を初期化せずに使っちゃダメ」と怒られるようなコード。</span>
        <span class="comment">// 別にエラーにならない。その代わり、「return のせいでここには絶対来ないよ」警告が出る。</span>
        <span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="variable">x</span>);
    }
}
</code></pre>
<p>nullability のフロー解析もこれと同じ挙動になります。</p>
<p>そこで困るのが、以下のような状況。</p>
<pre class="source" title="">
<code><span class="reserved">using</span> System;
 
<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="comment">// 例外を出すのでこのメソッドより後ろは絶対に実行されない。</span>
    <span class="reserved">static</span> <span class="reserved">void</span> <span class="method">Throw</span>() =&gt; <span class="control">throw</span> <span class="reserved">new</span> <span class="type">Exception</span>();
 
    <span class="reserved">static</span> <span class="reserved">void</span> <span class="method">Main</span>()
    {
        <span class="reserved">int</span> <span class="variable">x</span>;
 
        <span class="comment">// 絶対に戻ってこない。</span>
        <span class="method">Throw</span>();
 
        <span class="comment">// 以下の2行もアプリケーション クラッシュになるのでここより後ろは実行されない。</span>
        System.Diagnostics.<span class="type">Debug</span>.<span class="method">Assert</span>(<span class="reserved">false</span>);
        <span class="type">Environment</span>.<span class="method">FailFast</span>(<span class="string">&quot;fatal error&quot;</span>);
 
        <span class="comment">// でも、現状だとコンパイラーがそれを知るすべがな。</span>
        <span class="comment">// なので「到達できない」警告じゃなく「未初期化」エラーに。</span>
        <span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="variable">x</span>);
    }
}
</code></pre>
<p>ということで、以下のような属性も用意。</p>
<ul>
<li><code>[DoesNotReturn]</code>: メソッドを呼んだ時点でそこより後ろは実行されない</li>
<li><code>[DoesNotReturnIf(bool)]</code>: 指定した引数が true/false の時、そこより後ろは実行されない</li>
</ul>
 ]]></description>
				<pubDate>Sun, 19 May 2019 22:54:19 +0900</pubDate>
			</item>
			<item>
				<title>.NET 5、Visual Studio 16.1 Preview 3</title>
				<link>http://ufcpp.net/blog/2019/5/build2019/</link>
				<description><![CDATA[ <p>今年の <a href="https://www.microsoft.com/en-us/build">build</a>、思ってたよりも .NET がらみが盛沢山…</p>
<p><a href="https://www.publickey1.jp/blog/19/windows_terminalpowershellsshmicrosoft_build_2019.html">Windows Terminal</a>とか<a href="https://www.publickey1.jp/blog/19/webvisual_studio_onlinevscodeintellicodelive_sharemicrosoft_build_2019.html">Visual Studio Online</a>とかの方がさらにインパクト強そう？
ですけど、 .NET がらみもだいぶ。
まあ、3.0 が今年こそ見えてきましたからね。</p>
<ul>
<li>
<a href="https://devblogs.microsoft.com/dotnet/introducing-net-5/">Introducing .NET 5</a>
<ul>
<li>.NET Core 4 は Framework 4.X と紛らわしいから欠番にして、次は「5」</li>
<li>
徐々に .NET Core に一本化して、名前も「.NET」に
<ul>
<li><a href="https://devblogs.microsoft.com/dotnet/net-core-is-the-future-of-net/">.NET Framework は 4.8 を最後のバージョンにすると明言</a></li>
<li>
Mono の機能は徐々に取り込むとのこと
<ul>
<li>最初の目標は <a href="https://github.com/dotnet/corefx/">corefx</a>(ライブラリ部分)を<a href="https://github.com/dotnet/coreclr/">coreclr</a>と Mono VM で99%共有化とかからと言ってるので先は長そう</li>
</ul>
</li>
</ul>
</li>
<li>
これからは年に1回、毎年11月にメジャー リリースする
<ul>
<li>2019/9 に .NET Core 3.0</li>
<li>2019/11 に .NET Core 3.1</li>
<li>
2020/11 に .NET 5、以降毎年6, 7, 8, ...
<ul>
<li>5 以降、Long Term Support は偶数番だけ</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li>
<a href="https://devblogs.microsoft.com/dotnet/announcing-net-core-3-0-preview-5/">Announcing .NET Core 3.0 Preview 5</a>
<ul>
<li>Preview 4 との差分</li>
<li>差分のみだけど今回結構大きそう</li>
<li>令和対応とか混ざっててちょっと受ける</li>
</ul>
</li>
<li>
<a href="https://devblogs.microsoft.com/visualstudio/visual-studio-2019-version-16-1-preview-3/">Visual Studio 2019 version 16.1 Preview 3</a>
<ul>
<li>
<a href="https://devblogs.microsoft.com/visualstudio/announcing-the-general-availability-of-intellicode-plus-a-sneak-peek/">IntelliCode が GA</a>だって
<ul>
<li>何を持って GA なんだろう… 「16.1 Preview 3 からはオプション指定なしでデフォルトでオン」の意味？</li>
</ul>
</li>
<li>
IntelliSense、 using してない名前空間の型も補完候補に出てくるように
<ul>
<li>IntelliCode のおかげで候補が賢くなってるおかげか、候補が多過ぎてつらい問題はそこまでなさそう？</li>
</ul>
</li>
</ul>
</li>
<li>
<a href="https://online.visualstudio.com/">https://online.visualstudio.com/</a> 発表
<ul>
<li>今のところ上記 URL は<a href="https://devblogs.microsoft.com/visualstudio/intelligent-productivity-and-collaboration-from-anywhere/">発表ブログ</a>に転送</li>
<li>
将来的には「ブラウザー版 Visual Studio Code」になる予定
<ul>
<li>今もう、実は <a href="https://try.dot.net/">try.dot.net</a>とかが <a href="https://dotnet.microsoft.com/apps/aspnet/web-apps/client">Blazor</a> ベースで動いてたりするので、布石はあった</li>
<li>Blazor 自体も「プレビュー」に(早期開発版フェーズは通過)</li>
</ul>
</li>
<li>
名前の再利用やめろ… Surface といい docs といい…
<ul>
<li>ALM とか Team Services とか DevOps とか呼ばれてるやつの名称が「Visual Studio Online」だった時期がある</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>「11月って言うと、確かにホリデーシーズン直前で、アメリカ製品はその時期に出るものが一番安定してるけど」とか、「build で毎年11月とかそんなタイトな公約掲げちゃって大丈夫？」とかは思ったり思わなかったり。</p>
<p>まあ、この辺りは他の人がまとめてるので概要のみにして。</p>
<h2>C# 8.0 in Visual Studio 16.1 Preview 3</h2>
<p>最近はすっかり C# 中心の話ばっかりなわけですが。</p>
<p>今回の Preview 3 では、新機能は特に増えていないんですが、ちょこっと修正があります。
<a href="/blog/2019/4/vs2019ga/">前々から「.NET Core 3.0 依存だから安定してない」って言っていた機能</a>に、予定通り変更あり。</p>
<ul>
<li>
非同期イテレーターに <code>CancellationToken</code> を渡せる手段ができました
<ul>
<li>例を gist にアップロード: <a href="https://gist.github.com/ufcpp/ae78b9e06d77a573cd5f2fcdbefb92cd">EnumeratorCancellation.cs</a></li>
<li><code>EnumeratorCancellation</code> 属性を付ければいいらしい</li>
<li>後述しますがちょこっと挙動変更される予定がすでにあり</li>
</ul>
</li>
<li>
Index/Range がらみのコード生成結果変更
<ul>
<li><a href="/blog/2019/2/pickuproslyn0210/">2月にブログにした</a>通り</li>
<li>
変更内容に関する提案ドキュメント: <a href="https://github.com/dotnet/csharplang/blob/master/proposals/index-range-changes.md">Index and Range Changes</a>
<ul>
<li>旧仕様: コレクション側が <code>Index</code>/<code>Range</code> 構造体を受け付けるオーバーロードを用意</li>
<li>新仕様: C# コンパイラーが <code>Index.GetOffset</code> を呼んで <code>int</code> に変換</li>
</ul>
</li>
</ul>
</li>
</ul>
<h2>ピックアップ Roslyn 5/7</h2>
<p>で、3日ほど前に1個、C# の Design Notes のアップロードがありました。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/2485">Added: LDM Notes for April 29, 2019 #2485</a></li>
</ul>
<h3>base(T)</h3>
<p>一昨日、<a href="/study/csharp/oo_interface.html?p=5#dim">インターフェイスのデフォルト実装</a>の話を書いたところなんですよ。
その中には <a href="/study/csharp/oo_interface.html?p=5#multiple-inheritance"><code>base(T)</code> アクセスの話</a>もあります。
これを書いてから上記の Desing Notes に気づいたわけですが。</p>
<p>「<code>base(T)</code>、C# 8.0 からは外して、ランタイムのサポート込みで C# 9.0 に回したい」ですって。</p>
<p>書き直さなきゃ…</p>
<h3>非同期イテレーターのキャンセル</h3>
<p>この話は前述の<a href="https://gist.github.com/ufcpp/ae78b9e06d77a573cd5f2fcdbefb92cd">gist に上げた例</a>にも書いてあるんですけども。
以下のような非同期イテレーターを書いた場合、</p>
<pre class="source" title="非同期イテレーター">
<code><span class="reserved">async</span> <span class="type">IAsyncEnumerable</span>&lt;<span class="reserved">int</span>&gt; <span class="method">X</span>([<span class="type">EnumeratorCancellation</span>]<span class="type">CancellationToken</span> <span class="variable">ct</span> = <span class="reserved">default</span>)
</code></pre>
<p><code>CancellationToken</code> は、<code>X(ct)</code> というのと、<code>X().WithCancellation(ct)</code> というの、どちらで書いても最終的に <code>X</code> の引数に渡ってきます。</p>
<p>で、両方指定できちゃう。<code>X(ct1).WithCancellation(ct2)</code> が合法。
この時どういう挙動をすべきかという話です。</p>
<ul>
<li>現状: <code>ct2</code> が優先で上書きされる</li>
<li>提案: <code>ct1</code> と <code>ct2</code> を<a href="https://docs.microsoft.com/ja-jp/dotnet/api/system.threading.cancellationtokensource.createlinkedtokensource">リンク</a>させたものを新たに作る</li>
</ul>
<p><code>CancellationToken</code> だけじゃなくて <code>CancellationTokenSource</code> にも依存するとか、
コード生成が複雑になるとか、
<code>CancellationTokenSource</code> を持つためのフィールドも増えてメモリ的にも優しくないとか、
デメリットもあるんですが、さすがに上書き挙動はまずそう。</p>
<h3>トリアージュ</h3>
<p>buildで、.NET Core 3.0 のリリースが今年の7月にRC、9月にGA、11月に3.1と明言されたわけですが。
C# 8.0 はこれに追従する予定です。
要するに C# 8.0 にもスケジュールが切られました。
逆算すると、「C# 8.0 に何を入れて何を入れないか」の決断のタイムリミットが今。</p>
<p>ということで、なんかむっちゃ仕分けされてました。
仕分け結果は <a href="https://github.com/dotnet/csharplang/projects/4">csharplang 内の GitHub Project</a>にも、
<a href="https://github.com/dotnet/roslyn/blob/master/docs/Language%20Feature%20Status.md">Roslyn 内の Language Feature Status</a>にも反映済み。
多少この2つに不整合があるんで、たぶんまだもうちょっと整理中のはずです。</p>
<p>前々から「8.0 タグが付いてるけど怪しくない？」みたいに思ってたものはやっぱり外れました。
急ぎ、<a href="https://github.com/ufcpp/UfcppSample/issues/208">自分用のタスク リスト</a>にも反映。</p>
<h3>ローカル関数に対する属性</h3>
<p>非同期イテレーター、属性ベースで <code>CancellationToken</code> を渡すようになったわけですが。
そこで「ローカル関数にも属性付けれないとまずいじゃない」という話になったみたいです。</p>
<p>ということで、それも実装予定に。</p>
 ]]></description>
				<pubDate>Tue, 07 May 2019 20:32:59 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 4/27 &amp; Visual Studio 16.1 Preview 2</title>
				<link>http://ufcpp.net/blog/2019/4/pickuproslyn0427/</link>
				<description><![CDATA[ <h2>Visual Studio 16.1 Preview  2</h2>
<p><a href="https://docs.microsoft.com/ja-jp/visualstudio/releases/2019/release-notes-preview#16.1.0-pre.2.0">Visual Studio 16.1 Preview 2</a> が来てますね。</p>
<p>C# 8.0、Preview 1 からの差分だと、以下の2つの機能が追加されました。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/blob/master/proposals/default-interface-methods.md">インターフェイスのデフォルト実装</a></li>
<li><a href="https://github.com/dotnet/csharplang/issues/1710">readonly 関数メンバー</a></li>
</ul>
<h3>インターフェイスのデフォルト実装</h3>
<p>インターフェイスに、実装を持った関数メンバー(メソッド、プロパティ、インデクサーなど)を持てるようになりました。</p>
<p>どちらかというとライブラリ実装者向けの機能で、多くの開発者(大体はライブラリは使う側)にとってはそこまで大きなインパクトのある機能ではないんですが。
<a href="https://www.slideshare.net/ufcpp/c-80-preview-in-visual-studio-2019-160/27">先日のイベント登壇</a>でも話した通り、この機能の重要な点は、「.NET ランタイム側の修正が必須」という部分です。</p>
<p>古いランタイムでは動かない機能追加というのがいつ以来かというと、<a href="/study/csharp/ap_ver2.html">C# 2.0</a>、つまり、2005年以来14年ぶりの出来事です。</p>
<p>状況的に言うと、</p>
<ul>
<li>.NET Core が単なる「.NET Framework からの移行期」をやっと超えた</li>
<li>
.NET Core なら新しいランタイムを採用しやすい
<ul>
<li>side by side インストールができるので、新旧ランタイムの混在ができる</li>
<li>インストーラーも小さい</li>
</ul>
</li>
<li>WPF や WinForsm など、Windows 限定機能も .NET Core 3.0 で動くようになって、 .NET Framework にこだわる必要性が減った(少なくとも新規案件では採用理由がない)</li>
</ul>
<p>という感じで、ランタイム側の修正がやりやすい状況がやっと来ました。
この3・4年の間、「それは C# コンパイラーだけでは無理だから採用できない」と言われて実装されてこなかったような機能が、今後は採用される可能性が高まっています。</p>
<h3>readonly 関数メンバー</h3>
<p>「<a href="/study/csharp/sp_ref.html#in-copy">in 引数を使ってもコピーが発生する場合</a>」で説明している「隠れたコピー」(hidden copy)を回避するための機能です。</p>
<p>関数メンバーに readonly 修飾を付けることで、その実装内でフィールドを書き換えていないという保証をします。結果的に、「書き換わったら困るので防衛的にコピーしてからメソッドを呼ぶ」みたいな挙動がなくなって、パフォーマンスが向上します。</p>
<p>とりあえず、フィールドの書き換えをしていないメソッドとかには readonly を付けておけばいいです。
特に、構造体に対してはこの隠れたコピーがよく問題を起こすので、意外と重要な機能です。</p>
<p>ただ、<a href="/study/csharp/sp_ref.html?p=2#ref-readonly">ref readonly</a> と似てて、ちょっとした語順の差で別の機能になったりするので注意が必要です。
<code>readonly ref T M&lt;T&gt;()</code> なら readonly 関数メンバーで、<code>ref readonly T M&lt;T&gt;()</code> なら参照戻り値です。</p>
<h2>Design Notes</h2>
<p>また2件、C# Design Notes 追加。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/2471">Added: LDM Notes for April 22 and April 24, 2019 #2471</a></li>
</ul>
<p>null 許容参照型(NRT)がらみの話3件と、switch 式の「target-typed」の話、非同期イテレーターへの <code>CancellationToken</code> の渡し方の話。</p>
<h3>null 許容参照型がらみ</h3>
<ul>
<li>
<a href="/study/csharp/oo_exception.html#try">finally ブロック</a>内での null チェックの結果は、その後ろでも有効かどうか
<ul>
<li>有効であるべきなんだけど、フロー解析が複雑になる(= コンパイル時間が増える)</li>
<li>簡単にできる範囲でフロー解析に手を加えることに</li>
</ul>
</li>
<li>
<a href="/study/csharp/oo_class.html#partial">partial 定義</a>で nullability が違う指定をしてしまったとき、どう扱うべきか
<ul>
<li>違う nullability  指定をしてたらエラーにする</li>
</ul>
</li>
<li>
ジェネリック型引数では <code>MaybeNull</code> 属性が必要そう
<ul>
<li><code>T FirstOrDefault&lt;T&gt;(IEnumerable&lt;T&gt;)</code> の戻り値が代表例で、制約なしのジェネリックなので <code>T?</code> とは書けないけど、null を返す可能性があるものに付ける</li>
</ul>
</li>
</ul>
<h3>switch 式がらみ</h3>
<p><a href="/study/csharp/datatype/typeswitch/?p=5#switch-expression">switch 式</a>に関しては、</p>
<pre class="source" title="terget-typed switch 式">
<code><span class="reserved">byte</span> <span class="method">M</span>(<span class="reserved">bool</span> <span class="variable">b</span>) =&gt; <span class="variable">b</span> <span class="control">switch</span> { <span class="reserved">false</span> =&gt; 0, <span class="reserved">true</span> =&gt; 1 };
</code></pre>
<p>みたいに書いたとき、この 0, 1 をちゃんと <code>byte</code> と判定できるようにしたいという話。
(現在(16.1 Preview 1時点)では、switch の戻り値が <code>int</code> になって、<code>int</code> から <code>byte</code> への暗黙の型変換はダメと怒られる。)
戻り値側からの型推論なので「target-typed」。</p>
<p>同じことは条件演算子 <code>b ? 0 : 1</code> でもやりたいけども、既存のコードを壊さないようにするために、switch 式ほどは自由度効かなさそう(それでも、影響を最小限に抑えられそうな範囲で検討中)とのこと。</p>
<h3>非同期イテレーターがらみ</h3>
<p><a href="https://github.com/dotnet/csharplang/issues/2447">ちょっと前</a>からの決定事項なんですが、
非同期イテレーター(<code>await</code>と<code>yield return</code>の混在)に対する <code>CancellationToken</code> の渡し方は、引数に属性を付けることでやりたい、(属性名は本決定してないけど仮に)以下のような書き方をするという話があります。</p>
<pre class="source" title="非同期イテレーターへの CancellationToken の渡し方">
<code><span class="reserved">async</span> <span class="type">IAsyncEnumerable</span>&lt;<span class="type">T</span>&gt; <span class="method">M</span>&lt;<span class="type">T</span>&gt;([<span class="type">DefaultCancellation</span>] <span class="type">CancellationToken</span> <span class="variable">cancellationToken</span>)
{
    ...
}
</code></pre>
<p>これに関して、</p>
<ul>
<li>
非同期イテレーターになっている実装自体でないものに属性が付いていると警告を出す
<ul>
<li>要するに、abstract で <code>IAsyncEnumerable&lt;T&gt;</code> を返しているメソッドとかに属性が付いていると警告になる</li>
</ul>
</li>
<li>複数の <code>CancellationToken</code> 引数に属性が付いていても警告は出さない</li>
<li>1つも<code>CancellationToken</code> 引数に属性が付いていない場合は警告を出す</li>
</ul>
<p>みたいにしたいみたい。</p>
 ]]></description>
				<pubDate>Sat, 27 Apr 2019 19:11:38 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn &amp; Visual Studio 16.1 Preview 1</title>
				<link>http://ufcpp.net/blog/2019/4/pickuproslyn0420/</link>
				<description><![CDATA[ <h2>Visual Studio 16.1 Preview 1</h2>
<p><a href="https://docs.microsoft.com/ja-jp/visualstudio/releases/2019/release-notes-preview#16.1.0-pre.1.0">Visual Studio 16.1 Preview 1</a> が来てたことに今更気付くなど…</p>
<p>先日の<a href="/blog/2019/4/vs2019ga/">Visual Studio 2019 GA の話</a>で書いた通り、これまで「Visual Studio 2019 Preview」をインストールしていた人のところには 16.1 Preview 1 が配信されているはずです。
GA 版にかまけてしばらく Preview チャネルの方を見てなかった…
(4/10 の配信)</p>
<p><a href="https://github.com/dotnet/roslyn/blob/master/docs/Language%20Feature%20Status.md">Language Feature Status</a>によれば、16.0 から 16.1 Preview 1 での差分は以下の1点のみです。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/1744">unmanaged generic structs</a></li>
</ul>
<p>ジェネリックな構造体でも条件さえ満たせば<a href="/study/csharp/sp_unsafe.html">ポインターとか stackalloc とか</a>使えるようになりました。
C# によるプログラミング入門にも反映させてあります。</p>
<ul>
<li><a href="/study/csharp/cheatsheet/ap_ver8/#unmanaged-generic-struct">アンマネージなジェネリック構造体</a></li>
</ul>
<p><a href="/blog/2018/12/cs8notyet/">using の話</a>とか<a href="/blog/2018/12/cs8asyncstreams/">非同期ストリームの話</a>とか、先に埋めた方がいいだろと思うものもちらほらあったりはするんですが、なかなか手付かずに…</p>
<h2>Design Notes</h2>
<p>また一気に大量アップロード…</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/compare/c0edd6fcb7...34e86a1702">3月6日～4月1日分まとめて</a></li>
<li><a href="https://github.com/dotnet/csharplang/issues/2414">Added: LDM notes for April 3rd, 2019 #2414</a></li>
<li><a href="https://github.com/dotnet/csharplang/issues/2447">Added: LDM Notes from Apr 15, 2019 #2447</a></li>
</ul>
<p>ちょっと一気に来過ぎて自分も大筋しか見れてないんですが…
興味の引かれたところだけ抜粋:</p>
<h3>switch</h3>
<ul>
<li>
<a href="/study/csharp/cheatsheet/ap_ver8/#switch-expression">switch 式</a>の優先度変えたいって
<ul>
<li>今: 比較演算子の辺り。<code>&lt;</code> とかの近く</li>
<li>変更後: 単項演算子の直後。インデクサー、キャスト、<code>await</code> とかよりは下で、掛け算の <code>*</code> とかよりは上。</li>
</ul>
</li>
<li>
やっぱ <code>{}</code> が暗黙的に「null ではない」の意味なの混乱しそう
<ul>
<li>でも、<code>is</code> での挙動と合わせないと変だし</li>
</ul>
</li>
<li>
将来の <a href="https://github.com/dotnet/csharplang/issues/1350">or パターン</a>のために、今、<code>case X or</code> みたいなのは警告出すべき？
<ul>
<li>今もう動くコードなので、破壊的変更になっちゃうから無理そう</li>
</ul>
</li>
</ul>
<h3>非同期ストリーム</h3>
<ul>
<li>
非同期イテレーターへの <code>CancellationToken</code> の渡し方どうしよう？
<ul>
<li>引数に所定の属性を付けたら、生成されるイテレーターに伝搬するようにしたい</li>
</ul>
</li>
</ul>
<h3>??= 演算の戻り値の型</h3>
<p>以下のコードを書いたとき、 <code>c</code> の型はどうあるべきか</p>
<pre class="source" title="">
<code><span class="reserved">int</span>? <span class="variable">b</span> = <span class="reserved">null</span>;
<span class="reserved">var</span> <span class="variable">c</span> = <span class="variable">b</span> ??= 5;
</code></pre>
<ul>
<li>
今(16.1 Preview 1)の実装は <code>int?</code> になる
<ul>
<li><code>b ??= 5</code> と <code>b = b ?? 5</code> が同じ意味になるように</li>
</ul>
</li>
<li>今後、<code>int</code> になるように変える</li>
</ul>
<h3>Index/Range</h3>
<ul>
<li><a href="/blog/2019/4/pickuproslyn0402/">先日書いた</a>「パターン ベースにする」という話、確定</li>
<li>
<code>Length</code> があればまずそれを、なければ <code>Count</code> を調べる
<ul>
<li><code>Length</code> の戻り値が <code>int</code> でなければそれは無視して <code>Count</code> を調べる</li>
<li><code>Count</code> の実装が O(1) じゃない場合の心配とかはしない(それは .NET のデザイン ガイドライン違反)</li>
</ul>
</li>
<li><code>[Range r]</code> なインデクサーよりも、<code>Slice(int start, int length)</code> の方が優先される</li>
<li>インスタンス メンバーしか追わない(拡張メソッドは調べない)</li>
<li><code>int</code> 以外のインデクサーは認めない(暗黙の型変換とかは追わない)し、引数も1個だけのしか調べない</li>
<li><code>Slice</code> も<code>int</code>が2引数のものしか調べない</li>
</ul>
<h3>null 解析(null 許容参照型)</h3>
<ul>
<li>
到達不能なコード(<code>return</code> の後ろとか)の null 解析はしない
<ul>
<li>今ある「<a href="/study/csharp/resource/rm_struct/#definite-assignment">確実な初期化</a>の解析」がそうだから</li>
</ul>
</li>
<li>匿名型のメンバーの nullability は追うべき？ → yes</li>
<li>以下のコード、実装側で区別できなくて困らない？</li>
</ul>
<pre class="source" title="">
<code><span class="reserved">interface</span> <span class="type">I</span>
{
    <span class="reserved">void</span> <span class="method">Foo</span>&lt;<span class="type">T</span>&gt;(<span class="type">T</span> <span class="variable">value</span>) <span class="reserved">where</span> <span class="type">T</span> : <span class="reserved">class</span>;
    <span class="reserved">void</span> <span class="method">Foo</span>&lt;<span class="type">T</span>&gt;(<span class="type">T</span>? <span class="variable">value</span>) <span class="reserved">where</span> <span class="type">T</span> : <span class="reserved">struct</span>;
}
</code></pre>
<p>→ 困る。実装側に <code>where</code> 制約を付けて区別できるようにしないといけない。</p>
<ul>
<li><a href="/study/csharp/sp4_dynamic.html">dynamic</a> な変数の nullability は追う？ → yes</li>
</ul>
<h3>インターフェイスのデフォルト実装</h3>
<ul>
<li>
reabstraction は認めるか
<ul>
<li><code>abstract</code> を付けて、デフォルト実装があるメソッドを再び「派生クラスでの実装が必須」の状態に戻す話</li>
<li>もし実装が楽そうならやるべき理由はある。実現性を要調査 → 十分できそう</li>
</ul>
</li>
<li>
デフォルト実装ないから object のメンバー、特に <code>MemberwiseClone</code> のアクセスを認めるか
<ul>
<li>たぶん yes。でも問題起こしそう。object の protected メンバーはアクセスできないようにするかも → できなくするほうがだいぶ好ましそう</li>
</ul>
</li>
<li>クラス同様、<a href="/study/csharp/oo_class.html#partial">partial メソッド</a>は暗黙的に private？ → yes</li>
</ul>
<h2>Better Obsoletion (Obsolete 属性をよりよくしたい)</h2>
<p>C# 側ではなくて <a href="https://github.com/dotnet/designs">dotnet/designs</a> の方に出ている話ですがもう1個。</p>
<ul>
<li><a href="https://github.com/dotnet/designs/pull/62">Better Obsoletion #62</a></li>
</ul>
<p>.NET の基本ライブラリには、廃止予定にしてしまいたい(<code>Obsolete</code> 属性を付けてしまいたい) API がもう結構大量にあるわけですが。
今の <code>Obsolete</code> 属性の仕様だと「全部抑止」か「全部警告」の all or nothing で困るという話。</p>
<p>「ある特定の <code>Obsolete</code> 属性は無視して、それ以外の <code>Obsolete</code> 属性はちゃんと警告になる」みたいなグルーピング機能が欲しく、そのために <code>Obsolete</code> 属性に <code>DiagnosticId</code> プロパティを追加しようという提案になっています。</p>
<p>新しい属性を作ることも考えたけど、そしたら皮肉なことに <code>Obsolete</code> 属性自体に <code>Obsolete</code> 属性がついてしまうという問題。</p>
 ]]></description>
				<pubDate>Sat, 20 Apr 2019 20:21:37 +0900</pubDate>
			</item>
			<item>
				<title>Visual Studio 2019 GA</title>
				<link>http://ufcpp.net/blog/2019/4/vs2019ga/</link>
				<description><![CDATA[ <p><a href="https://visualstudio.microsoft.com/vs2019-launch/">Visual Studio 2019 の発表イベント</a>に合わせて、Visual Studio 2019 が GA (general available)になりました。</p>
<p>そういえば、Visual Studio も「GA」って言い方するようになったっぽいですね。
今まで「正式リリース」を指して RTM (Release To Manufacturing、ソフトウェアが CD とか DVD で売られてた頃の名残)とか言っていたんですが。</p>
<p>まあ、どうせドキュメントにもしばらく RTM と GA が混在すると思いますが。</p>
<h2>インストール</h2>
<p>相変わらず日本語検索で「Visual Studio 2019」だけで GA 版のインストーラーにたどり着くのがちょっと大変臭く…</p>
<p>同僚は「<a href="https://www.publickey1.jp/blog/19/visual_studio_201941live_shareaiintellicodemac.html">Publickey</a>経由で行けばダウンロードできた」と言ってました。</p>
<p>自分は先月すでに <a href="/blog/2019/2/vs2019rc/">RC (Release Candidate)版</a>をインストールしていたので、アップデートの自動配信で GA 版にアップデートされました。</p>
<h2>言いたいことは RC の時点で言った</h2>
<p>毎度恒例なんですけども、「言いたいことは RC 版の時に行っちゃったので、GA 版で今更言うことはない」状態です。
RC ってのはそういうもの(バグ修正を除いて変更はしない)なので。</p>
<p>ということで、詳細は以前の RC 版のブログ</p>
<ul>
<li><a href="/blog/2019/2/vs2019rc/">Visual Studio 2019 RC と Preview 4</a></li>
</ul>
<p>を参照してください。</p>
<h3>Visual Studio の配信チャネル</h3>
<p>先日の RC の時点でも書きましたが、今、Visual Studio Installer は「RC → GA」配信のチャネルと、Preview のチャネルに分かれています。</p>
<p>今は、</p>
<ul>
<li>RC だったもの → GA にアップデート</li>
<li>Preview の方 → 16.0.0 Preview 5.0 が配信される(GA 相当と同じ機能)</li>
<li>ついでに、Visual Studio 2017 の方にも 15.9.11 の配信あり</li>
</ul>
<p>という状態。
Preview の方にはいずれ 16.1 Preview 1 の配信があると思います。</p>
<p>ちなみに、C# 8.0 にはいくつか 16.1 で初めて実装される機能があるんですが、
「<a href="https://github.com/dotnet/roslyn/blob/master/docs/Language%20Feature%20Status.md">Language Feature Status</a>」を眺めている感じ、それが提供されるのは 16.1 Preview 2 かららしいです。
Preview 1 時点ではおそらく何の変化もありません。</p>
<h2>C# 8.0 有効化したった</h2>
<p>ということで、自分にとっては「言うことは先月言った。インストールも RC からのアップデートだけ」という状態なわけですが。</p>
<p>一応、職場でチーム全員が Visual Studio 2019 になったのをいいことに、 C# 8.0 を仕事でも有効化してしまいました。</p>
<p><a href="https://github.com/dotnet/roslyn/blob/master/docs/compilers/CSharp/Compiler%20Breaking%20Changes%20-%20VS2019.md">いくつか破壊的変更も報告されています</a>が、職場のコードで踏み抜いた変更はなかったです。</p>
<p>ただし、その際には以下の注釈付き。</p>
<p>状況:</p>
<ul>
<li>Visua Studio 2019 (16.0)が GA (general available)になったけど、C# 8.0 は preview という扱い</li>
<li>LangVersion preview とかを指定しないと使えない</li>
<li>正式リリースは .NET Core 3.0 に合わせるはずで、 .NET Core 3.0 は「今年後半」とだけ言われてる</li>
<li>preview と言っても、現状で実装されてる機能は機能ごとにほんと安定度が違うので、使ってよさそうなのとダメそうなのが明確に分かれてる</li>
</ul>
<p>以下の機能は遠慮なく使おうかと:</p>
<ul>
<li><a href="https://ufcpp.net/blog/2018/12/cs8patterns/">再帰パターン</a></li>
<li><a href="https://ufcpp.net/blog/2018/12/cs8switchexpr/">switch 式</a></li>
<li><a href="https://ufcpp.net/blog/2019/1/vs2019p2/">静的ローカル関数</a></li>
<li><a href="https://ufcpp.net/blog/2018/12/cs8misc/"><code>??=</code></a></li>
<li><a href="https://ufcpp.net/blog/2018/12/cs8notyet/">using 改善</a></li>
</ul>
<p>switch 式だけは注意が必要で、16.1 で演算子の優先順位が変わる予定。単品でだけ使う方が無難(<code>x + y switch { ... }</code> みたいな書き方は避ける)。</p>
<p>.NET Core 3.0 依存な機能(<a href="/blog/2018/12/cs8ranges/">Range</a>とか<a href="/blog/2018/12/cs8asyncstreams/">非同期ストリーム</a>は当然使えないし、<a href="/blog/2018/12/cs8nrt/">null 許容参照型</a>もまだ手を出さない。</p>
 ]]></description>
				<pubDate>Wed, 03 Apr 2019 20:35:01 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 4/2: corefx 側とのミーティング</title>
				<link>http://ufcpp.net/blog/2019/4/pickuproslyn0402/</link>
				<description><![CDATA[ <p>3/25 に、corefx 側の design review チームと C# チームで C# 8.0 絡みの折衝をしていたみたいです。その議事録が上がりました。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/blob/master/meetings/2019/LDM-2019-03-25.md">C# Design Review Notes for Mar 25, 2019</a></li>
</ul>
<p>当然、corefx (.NET の基本ライブラリ)依存があったり、corefx 側での作業が必要になる機能の話になるので、話題は以下の3つ</p>
<ul>
<li><a href="/blog/2018/12/cs8nrt/">null 許容参照型</a> … ライブラリ側にどうやって null 許容注釈をつけて、どうやってリリースしていくか</li>
<li><a href="/blog/2018/12/cs8ranges/">Index/Range</a> … ライブラリ側に <code>Index</code>/<code>Range</code> 型引数のオーバーロードを足すんじゃなくて、パターン ベースに変えたい</li>
<li><a href="/blog/2018/12/cs8asyncstreams/">非同期ストリーム</a> … <code>async foreach</code> で、<code>GetAsyncEnumerator</code> にどうやって <code>CancellationToken</code> を渡すか</li>
</ul>
<h2>null 許容参照型</h2>
<p>null 許容参照型は後付けで検証を足すので、オプション指定したり <code>#nullable</code> ディレクティブを書いたりしない限り、検証が有効になりません(でないと既存コードを壊す)。</p>
<p>で、検証をオンにして初めて「null 許容かどうかの注釈」(nullability annotation)が入るわけですが、この null 許容注釈をどうやってリリースしていくかが問題になります。</p>
<p>かつて、案としては「sidecar 配布」って呼ばれる方式も検討されていました。
これはバイクにサイドカーをくっつけるみたいに、既存の dll/exe に後付けで(別ファイルで)注釈を足せるようにしたいという方式です。
でも、そういう特別な処理を保守するのは、得られるメリットよりもコストの方が大きいだろうということで、検討から外れたみたいです。</p>
<p>となると、corefx 自体にちまちまと <code>#nullable</code> ディレクティブを足して、ちょっとずつ注釈を入れていくことになります。
corefx みたいな大規模なもの対してに一斉作業はできないわけで、
.NET Core のアップデートのたびにちょっとずつ注釈が増えて、使ってる側にはちょっとずつ警告が増えます。</p>
<p>null 許容参照型が普及しきるまでの過渡期には、この「ちょっとずつ警告が増える」を覚悟しておく必要があります。
(その覚悟ができないなら、null 許容参照型を有効化するオプションは指定できない。
というのを、C# チームや .NET チームが周知しておかないとまずい。)</p>
<h2>Index/Range</h2>
<p>これは<a href="/blog/2019/2/pickuproslyn0210/">以前にも取り上げている</a>んですが、</p>
<ul>
<li>
今まで
<ul>
<li>C# 側ではあくまで、<code>^i</code> みたいな書き方から <code>Index</code> 構造体を、<code>i..j</code> みたいな書き方から <code>Range</code> 構造体を作るだけ</li>
<li><code>Index</code> や <code>Range</code> を受け取つけるオーバーロードはライブラリ側の責任で作る</li>
</ul>
</li>
<li>
これから/変えたい内容
<ul>
<li>パターン ベースで、<code>int</code>のインデクサーや <code>Slice</code> メソッドに展開</li>
<li><code>Index</code> 型の <code>i</code> に対して <code>x[i]</code> みたいなのを、<code>x[i.GetOffset(x.Length)]</code> に</li>
<li><code>Range</code> 型の <code>r</code> に対して <code>x[r]</code> みたいなのを、<code>var (offset, length) = r.GetOffsetAndLength(x.Length); x.Slice(offset, length)</code> に</li>
</ul>
</li>
</ul>
<p>みたいな話。
csharplang 側と corefx 側にそれぞれ issue が立っていたりしますが、この日に決まった話みたいです。</p>
<h2>非同期ストリーム</h2>
<p><code>await foreach</code> の展開結果では <code>GetAsyncEnumeartor(CancellationToken cancellationToken)</code> メソッドが呼ばれるようになります。
これまで、この、引数の <code>CancellationToken</code> に値を渡す手段がなくて、問答無用に <code>default</code> (キャンセルはしない)が渡っていました。</p>
<p>で、結局、プロパティの <code>set</code> やイベントの <code>add</code>/<code>remove</code> の <code>value</code> 変数(暗黙的に定義済みになってる)と同様に、<code>cancellationToken</code> という名前の暗黙的な変数を用意して、それを介して渡そうかという流れになっているみたいです。</p>
 ]]></description>
				<pubDate>Tue, 02 Apr 2019 20:22:37 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップ Roslyn 3/12</title>
				<link>http://ufcpp.net/blog/2019/3/pickuproslyn0312/</link>
				<description><![CDATA[ <p>Visual Studio 2019 (16.0)が RC までいってちょっと落ち着いたのか、csharplang にちょっと動きが。
(もう、次に C# 8.0 絡みの新機能実装がマージされるとしたら 16.1 になるので、C# チーム的には今ちょっと落ち着ける時期のはず。)
<a href="https://github.com/dotnet/csharplang/issues/2326">Designe Notes 3件</a>追加。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/blob/master/meetings/2019/LDM-2019-02-25.md">Feb 25th, 2019</a></li>
<li><a href="https://github.com/dotnet/csharplang/blob/master/meetings/2019/LDM-2019-02-27.md">Feb. 27, 2019</a></li>
<li><a href="https://github.com/dotnet/csharplang/blob/master/meetings/2019/LDM-2019-03-04.md">March 4th, 2019</a></li>
</ul>
<p>いくつかの話題はすでに個別の issue が立っています。</p>
<h2>インターフェイスのデフォルト実装</h2>
<p>半分くらいはインターフェイスのデフォルト実装がらみ。
<code>base</code> 呼び出しをどうしようかという話と、アクセシビリティをどうしようかという話。</p>
<h3>base</h3>
<p><code>base</code> 呼び出しって言うのは以下のようなやつのこと。</p>
<pre class="source" title="base 呼び出し">
<code><span class="reserved">using</span> System;
 
<span class="reserved">class</span> <span class="type">A</span>
{
    <span class="reserved">protected</span> <span class="reserved">virtual</span> <span class="reserved">void</span> <span class="method">M</span>() =&gt; <span class="type">Console</span>.<span class="method">WriteLine</span>(<span class="string">&quot;A&quot;</span>);
}
 
<span class="reserved">class</span> <span class="type">B</span> : <span class="type">A</span>
{
    <span class="comment">// この、B の M は後から足したり消したり</span>
    <span class="comment">//protected override void M() =&gt; Console.WriteLine(&quot;B&quot;);</span>
}
 
<span class="comment">// A, B とは別アセンブリにあるとして</span>
<span class="reserved">class</span> <span class="type">C</span> : <span class="type">B</span>
{
    <span class="comment">// C から基底クラスの M() を呼ぶ</span>
    <span class="reserved">protected</span> <span class="reserved">override</span> <span class="reserved">void</span> <span class="method">M</span>() =&gt; <span class="reserved">base</span>.<span class="method">M</span>();
}
</code></pre>
<p>この書き方で、<code>C.M</code> から基底クラスの <code>M</code> を呼び出せるわけですが、</p>
<ul>
<li>
基底クラスを1つずつたどっていって、最初に見つかったやつが呼ばれる
<ul>
<li>コンパイル時に <code>B.M</code> があったけど、実行時に読み込んだものからは消えていたら <code>A.M</code> が呼ばれる</li>
<li>コンパイル時に <code>B.M</code> はなかったけど、実行時に読み込んだものには足されていたら <code>B.M</code> が呼ばれる</li>
</ul>
</li>
</ul>
<p>みたいな挙動です。
これは C# の仕様というか、 .NET ランタイム(<a href="/study/il/">IL</a> 命令)のレベルでそういう仕様だそうです。</p>
<p>で、インターフェイスの場合はダイアモンド継承があり得るので、この仕様便りだと、規定をたどっていく経路が複数あって困る。
なので、<code>base(B).M()</code> みたいに、具体的にどの型の <code>M</code> を呼びたいのかを明示できる構文が導入される予定です。これについて、</p>
<ul>
<li>この書き方、(C# 8.0 でこれから実装される)インターフェイスのデフォルト実装だけじゃなく、クラスに対しても認める</li>
<li>
フィールドだろうがなんだろうが、この <code>base(BaseClass).Member</code> みたいな書き方が使える
<ul>
<li>ただし、(overrideさえなければ)元々 <code>this.Member</code> でアクセスできるものに限る</li>
</ul>
</li>
<li>
<code>base(B).M()</code> と書いたら <code>B</code> だけを見る。実行時に消えて時たら実行時エラーを起こす
<ul>
<li>「<code>B</code> になければ <code>B</code> から上をたどって探す」みたいなのは現状の .NET ランタイムでは不可能</li>
<li>将来的に、 .NET ランタイム自体に改修を入れる余地はある</li>
</ul>
</li>
</ul>
<p>とのこと。</p>
<h3>アクセシビリティ</h3>
<p><a href="/study/csharp/oo_conceal.html#level">アクセシビリティ</a>は <code>public</code> とか <code>private</code> とかのこと。</p>
<p>C# 7.3 までのインターフェイスは無条件に全部のメンバーが <code>public</code> (明示的に指定はできない)でしたが、
デフォルト実装とともに、アクセシビリティの指定ができるようになります。
これまでも、<code>public</code>、<code>protected</code>、<code>private</code> は提供するつもりでしたが、
残りの <code>internal</code>、<code>protected internal</code>、<code>private protected</code> も提供することに決めたそうです。</p>
<p>あと、インターフェイスの<a href="/study/csharp/oo_interface.html?p=3#explicit-impl">明示的実装</a>、↓みたいなやつもあるわけですが。</p>
<pre class="source" title="インターフェイスの明示的実装">
<code><span class="reserved">interface</span> <span class="type">I</span>
{
    <span class="reserved">void</span> <span class="method">M</span>();
}
 
<span class="reserved">class</span> <span class="type">A</span> : <span class="type">I</span>
{
    <span class="reserved">void</span> <span class="type">I</span>.<span class="method">M</span>() { }
}
</code></pre>
<p>デフォルト実装が入ることで、「インターフェイスが基底のメンバーを明示的実装」という状況が発生します。
この場合、その明示的実装は <code>protected</code> 扱いにするそうです。
(前節の「<code>base</code> は基底をたどって最初に見つかったものを呼ぶ」挙動との兼ね合いだそうです。)</p>
<h2>null 許容参照型</h2>
<h3>値型の default</h3>
<p>null 許容“参照型”と言っているわけですから、名前通り、参照型に関する機能です。
でも、じゃあ、クラスとか参照型を含む構造体が絡んだとき、<code>default(T)</code> はどうするんだという問題が残ります。
(<code>default</code> <a href="/study/csharp/rm_default.html">既定値</a>は 0/null での初期化になります。nullが絡む。)</p>
<p>なんか今のところ、<code>var y = default(参照型をフィールドとして持つ構造体)</code> みたいなのに対する警告は出さないみたいです。
(もちろん、「null を認めてないつもりのものに null が混ざる」という落とし穴でしかないので、相当な妥協。)</p>
<p>ただ、C# 8.0 では無理としても、構造体の “defaultability” については今後取り組みたい姿勢はある模様。
3年前(roslyn リポジトリ側に文法に関する提案も混ざってた頃含む)に自分が書いた「<code>default</code> を認めない値型を作らせてくれ」という issue:</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/146">Championed: Non-defaultable value types #146</a></li>
</ul>
<p>が急に championed (C# チームの誰かが興味を持って取り組む)状態に変わりました。
ある意味こいつは「値型版の null 許容参照型」です。</p>
<h3>利用調査</h3>
<p>null 許容参照型のフロー解析をオンにしてどうなるか、
それなりの規模なライブラリを調べてみたみたいです(作者に直接聞いたのか、クローンしてきて自分たちでやってみたのか、ブログとかを見ただけなのかとかはわからず)。
<a href="https://www.nuget.org/packages/Telegram.Bot.Framework/">Telegram bot</a>とか<a href="https://www.nuget.org/packages/Jil/">Jil</a>とか。
そこで起きてた問題のまとめ。</p>
<ul>
<li>メンバー定義で困ることが多い。メソッド内部での問題はむしろ少ない</li>
<li>インターフェイス側の定義を変えたときの、実装を全部変えて回る作業がやばい</li>
<li><a href="/study/csharp/oo_construct.html#member_initializer">初期化子</a>での初期化を前提としているものに対して警告が消せない</li>
<li>コンストラクター連鎖 (<code>A() : this(0) { }</code> みたいなやつ)もフロー解析しきれてない</li>
<li>null 許容値型(既存の、値型に対する <code>?</code>) が null 許容参照型との挙動差でよく問題起こす</li>
<li>診断のクオリティがまだまだ。ジェネリックな型でよく混乱するし、特にタプルに対してつらい</li>
<li>自動 code fix 機能欲しい</li>
</ul>
<h2>プロパティの get/set に Obsolete</h2>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/2152">Champion: &quot;Allow Obsolete attribute on getters and setters&quot; #2152</a></li>
</ul>
<p>プロパティの get/set <a href="/study/csharp/oo_property.html#accessor">アクセサー</a>には、それぞれ属性が付けれます(メソッド扱い。<code>AttributeTargets.Method</code> が入ってる属性だけ)。
でも、<code>Obsolete</code>、<code>Conditional</code>、<code>CLSComliant</code> の3つは get/set に付けることは禁止されていました。</p>
<p>で、まあ、<code>Obsolete</code>だけは認めてもいいんじゃないかという話に。
(あと、Xamarin iOS のやつかな、たぶん、<code>Deprecated</code> 属性も。)
<code>Conditional</code>、<code>CLSComliant</code> は今後もノータッチとのこと。</p>
<h2>params と文字列補間の効率</h2>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/2302">Efficient Params and String Formatting #2302</a></li>
</ul>
<p>提案ドキュメントの背景説明に「MSBuildログ最小限にしてもstringで236MBメモリ食っててその半分がFormatがらみ」とか書かれてて、あっ、はい…そうですよね…</p>
<p>文字列の整形絡みは一時的な小さい文字列インスタンスが大量にできちゃって、結構遅かったりします。
なので、自分も結構仕事で、<code>string.Format</code> とかを避けて、<code>stackalloc</code> したりプールした <code>char[]</code> とかを使って自前で文字列整形することがあったり。</p>
<p>あと、<a href="/study/csharp/sp_params.html"><code>params</code></a> が必ず配列を <code>new</code> しちゃうのも、<code>string.Format</code> を重たくしている原因。</p>
<p>ということで、corefxlab の方で文字列整形をアロケーションなしでできないか、みたいな実験コードが出ていまして。</p>
<ul>
<li><a href="https://github.com/dotnet/corefxlab/pull/2595">Protoype for nonallocating string formatting #2595</a></li>
</ul>
<p>C# 側で対応しないといけないこともあるので Design Meeting でも議題に。
概ね、</p>
<ul>
<li><code>params</code> に <code>Span&lt;T&gt;</code> を認めて、スタックに値を置いて可変長引数呼び出ししたい</li>
<li>値型の<a href="/study/csharp/RmBoxing.html">ボックス化</a>避けたいから <code>Variant</code> 型作るか</li>
</ul>
<p>みたいな話。</p>
<p>まあでも、付いたコメント的には</p>
<ul>
<li>なんで <a href="/study/csharp/resource/span/#safe-stackalloc"><code>stackalloc</code></a> に参照型使えないの？ → それを認めようとすると<a href="/study/computer/MemoryManagement.html#garbage-collection">ガベコレ</a>のコードがだいぶ複雑になる(パフォーマンスにも悪影響)</li>
<li><code>Span&lt;TypedReference&gt;</code> を認められるようにしようよ</li>
</ul>
<p>みたいな感じ。</p>
<h2>switch 式の優先度</h2>
<p>今回の Designe Notes にはないんですけど、もう1個、割と最近立った提案 issue:</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/2331">Propose to change precedence of switch expression from relational to primary #2331</a></li>
</ul>
<p>現時点 (Visual Studio 2019 RC でのことなので、たぶん、RC が外れても)での <a href="/study/csharp/datatype/typeswitch/?p=5#switch-expression"><code>switch</code> 式</a>の結合優先度は関係演算子(<code>==</code> とか)と同じだそうです。
関係演算子って結構優先度が低くいですし、
<code>&amp;</code> よりは上で <code>+</code> よりは下みたいな位置です。</p>
<ul>
<li><code>x switch { ... } + 1</code> みたいなものが、<code>} + 1</code> の方を先に見ちゃってエラーに</li>
<li><code>a + b switch {...}</code> は <code>+</code> が先だけど、<code>a &amp; b switch {...}</code> は <code>switch</code> が先</li>
</ul>
<p>とかいう嫌な状態。</p>
<p>なので、プライマリな優先度(<code>x.M()</code> の <code>.</code> とか、<code>[]</code> とかと同じ)に変えようかという提案。</p>
<p>大体、<code>x switch { ... }</code> が後置き演算子みたいな見た目ですからね。
<code>[]</code> とか <code>++</code> とか <code>.</code> とか、後ろに置くものは大体がプライマリ。
それに合わせた方が自然だろうという意図もあり。</p>
<h2>Index/Range の実装再考</h2>
<p>もう1つは C# 側じゃなくて、corefx 側から出ている要望。</p>
<ul>
<li><a href="https://github.com/dotnet/corefx/issues/35972">Revisit Index/Range API requirements #35972</a></li>
</ul>
<p>今現在の仕様だと、C# の姿勢としては、</p>
<ul>
<li><code>^a</code> とか とか <code>a..b</code> とかの構文はそれぞれ <code>Index</code>/<code>Range</code> 構造体を作るだけ</li>
<li><code>x[a..b]</code> みたいなのを使いたければ、コレクション クラスの実装側に <code>Index</code>/<code>Range</code> を受け付けるオーバーロードを増やせ</li>
</ul>
<p>です。</p>
<p>これに対して、要するに、</p>
<ul>
<li>インデクサーを持つコレクション クラス全部に対してオーバーロードを増やして回るのは大変だし、パフォーマンスが出ない実装になることがある</li>
<li>それよりは、<code>collection[i.GetOffset(collection.Count)]</code> みたいな、<code>int</code> のオーバーロードを使うコードに展開する実装に変えてほしい</li>
</ul>
<p>という流れ。
まあ、そりゃ、コレクション作ってる側からするとそうですよね。
corefx (中の人同士)ですらそうなんだから、ましてコミュニティ実装なコレクションだとなおのこと。</p>
 ]]></description>
				<pubDate>Tue, 12 Mar 2019 22:28:03 +0900</pubDate>
			</item>
			<item>
				<title>.NET Core 3.0 Preview 3</title>
				<link>http://ufcpp.net/blog/2019/3/netcore3p3/</link>
				<description><![CDATA[ <p><a href="/blog/2019/2/vs2019rc/">こないだ出た Visual Studio 2019 RC1 / Preview 4</a>に対応したバージョンの .NET Core 3 Preview が出たみたいですね。</p>
<ul>
<li><a href="https://devblogs.microsoft.com/dotnet/announcing-net-core-3-preview-3/">Announcing .NET Core 3 Preview 3</a></li>
</ul>
<p>.NET Core 3.0、最近なんかずっと、Visual Studio より結構遅れてのリリースですよね…
おかげで、C# 8.0 のコードがエラーになってたり(今回は、<code>Range</code>構造体の仕様変更が原因)。</p>
<h2>Preview 3 での更新点</h2>
<p>さらっと内容まとめると、</p>
<ul>
<li>.NET Core 3.0 の正式リリースは今年後半っぽい。詳しくは今年の <a href="https://www.microsoft.com/en-us/build">build</a> で</li>
<li>
細かいインストールは上書きになる。パッチ バージョンの百のけたが同じものを同一視
<ul>
<li>3.0.100 があるときに 3.0.101 を入れると 100 は消える</li>
<li>3.0.200 を入れると 3.0.100 とか 3.0.101 とかは残る</li>
</ul>
</li>
<li>Docker がらみ、おかしかったの/不便だったの修正</li>
<li>Visual Studio 2019 RC1 / Preview 4 の C# 8.0 の <code>Range</code> がちゃんと動くように</li>
<li>.NET Standard 2.1 を使えるように</li>
<li>F# 4.6 に。dotnet fsi コマンドで F# Intaractive 起動</li>
<li><code>AssemblyDependencyResolver</code> とか <code>NativeLibrary</code> とか、native 相互運用してる人にはうれしそうなもの追加</li>
<li>WPF/WinForms とか Entity Framework とか更新</li>
<li>他は、<a href="https://devblogs.microsoft.com/dotnet/announcing-net-core-3-preview-1-and-open-sourcing-windows-desktop-frameworks/">Preview 1のとき</a>と<a href="https://devblogs.microsoft.com/dotnet/announcing-net-core-3-preview-2/">Preview 2のとき</a>の告知を見て</li>
</ul>
<p>とか。</p>
<h2>C# 8.0</h2>
<p>ちなみに、<code>TargetFramework</code> を <code>netcoreapp3.0</code> か <code>netstandard2.1</code> にすると、
デフォルトの状態で C# 8.0 になるみたいです。
<code>TargetFramework</code> だけで、ビルド ツールも .NET Core 3.0 のものに切り替わる模様。
(.NET Core 3.0 が正式リリースされた暁には C# 8.0 も正式リリースになる予定なので、
.NET Core SDK 3 にとっては C# 8.0 がデフォルトになります。)</p>
<p>ということで、ターゲットが .NET Core 3.0 か .NET Standard 2.1 のときは、特に <code>&lt;LangVersion&gt;preview&lt;/LangVersion&gt;</code> とか書かなくてもよくなります。
(netcoreapp2.2 とかがターゲットだとやっぱりこのタグが必要。あくまで新しいターゲットの時だけの切り替わり。)</p>
<p>RC1 の方だと「<a href="/blog/2019/2/vs2019rc/#add0301">プレビューの .NET Core SDK を使用</a>」オプションをオンにしないといけないのだけはご注意を。</p>
<h2>.NET Standard 2.1</h2>
<p>やっと、 .NET Standard も 2.1 になったわけですが。詳細は以下のページで見れます。</p>
<ul>
<li><a href="https://github.com/dotnet/standard/blob/master/docs/versions/netstandard2.1.md">.NET Standard 2.1</a></li>
</ul>
<p>大体は、「.NET Core の方に追いついた」って感じの API 追加です。</p>
<p>.NET Core 3.0 がらみも結構ちゃんと入っています。
C# 8.0 に必要な <code>Range</code>/<code>Index</code> や、<code>IAsyncEnumerable</code>/<code>IAsyncDisposable</code> も含む。
でも、.NET Standard 的にはバージョン 2.1。</p>
<p>ただ、<a href="/blog/2018/12/hdintrinsic/">Hardware Intrinsics</a>は入れないとのこと。
なんせ、Intrinsics はランタイムのサポートがあって初めて成り立つものなので、「どのランタイムで動かすかわからない .NET Standard にとっては意味がないから」とのこと。</p>
<p>ちなみに、追加が多いのは以下の辺り。</p>
<ul>
<li>
<a href="/study/csharp/resource/span/"><code>Span&lt;T&gt;</code></a> がらみ
<ul>
<li><code>System</code> とか <code>System.IO</code> とかの更新点は半分くらいは <code>Span</code> がらみ</li>
</ul>
</li>
<li><code>System.MathF</code> とか、浮動小数点数がらみの追加結構あり</li>
<li>
これまで NuGet 提供だったものがいくつか標準入り
<ul>
<li><a href="https://www.nuget.org/packages/System.Memory/">System.Memory</a>, <a href="https://www.nuget.org/packages/System.Buffers/">System.Buffers</a>, <a href="https://www.nuget.org/packages/System.Numerics.Vectors/">System.Numerics.Vectors</a>, <a href="https://www.nuget.org/packages/System.Threading.Tasks.Extensions/">System.Threading.Tasks.Extensions</a> 辺り</li>
<li>要は、<code>Span&lt;T&gt;</code>, <code>ArrayPool&lt;T&gt;</code>, <code>Vector</code>, <code>Matrix</code>, <code>ValueTask</code> とか</li>
</ul>
</li>
<li>
動的コード生成(<code>System.Reflection.Emit</code>) の辺りは丸々新規追加
<ul>
<li>もちろん、動的コード生成できないプラットフォームはあるわけで、その辺りは<a href="/blog/2018/12/runtimefeature/"><code>RuntimeFeature</code> クラス</a>の<code>IsDynamicCodeCompiled</code>, <code>IsDynamicCodeSupported</code> で判定</li>
</ul>
</li>
<li>
<code>System.Drawing</code> にやたらと差分が多いのは、たぶん <code>SystemColors</code> をサポートしたせい
<ul>
<li>enum 値1個1個が「追加 API」にカウントされてそう</li>
</ul>
</li>
</ul>
 ]]></description>
				<pubDate>Thu, 07 Mar 2019 20:11:50 +0900</pubDate>
			</item>
			<item>
				<title>Visual Studio 2019 RC と Preview 4</title>
				<link>http://ufcpp.net/blog/2019/2/vs2019rc/</link>
				<description><![CDATA[ <p>Visual Studio 2019 がリリース候補版(RC) になりました。</p>
<ul>
<li><a href="https://devblogs.microsoft.com/visualstudio/visual-studio-2019-release-candidate-rc-now-available/">Visual Studio 2019 Release Candidate (RC) now available</a></li>
</ul>
<p>※ <a href="#add0301">3月1日、ちょっと追記しました</a></p>
<h2>リリース チャネルとプレビュー チャネル</h2>
<p>同時に、Visual Studio 2019 Preview 4 も出ています。
これまで Preview 版を使っていた人は単にアップデートを掛ければ Preview 4 になります。
一方で、RC の方は、その後正式リリース版にそのままアップデートできます。</p>
<p>出た時期的に、RC と Preview 4 は内容的には大差ないと思います。
(といいつつ、なんか RC の方だと C# 8.0 がちゃんと使えなかったり、.NET Core 3.0 を参照できなかったりしてるんですが… 自分の手元だけなのか、.NET Core 3.0 の更新が来れば治るのか、本格的にバグなのかは不明…)</p>
<p>この2つは、単に配信チャネルの差。
要するに、</p>
<ul>
<li>
RC は、正式リリースが出た際にはそのまま正式リリース版にアップデートできる
<ul>
<li>その後も、正式リリースなものだけがアップデートとして流れてくる</li>
<li>これが「リリース チャネル」</li>
</ul>
</li>
<li>
Preview 4 は、Visual Studio 2019 (16.0)正式リリース後も、16.1 Preview 1 みたいなやつが流れてくる
<ul>
<li>これが「プレビュー チャネル」</li>
</ul>
</li>
</ul>
<p>という状態。
もちろん、Visual Studio 2017 との共存もできるので、インストーラーが以下のような状態になります。</p>
<p><img src="/media/1169/vsinstaller2019rc.png" alt="VS Installer 2019 RC" /></p>
<h2>C# がらみ</h2>
<p>基本的には <a href="https://ufcpp.net/blog/2019/1/vs2019p2/">Preview 2</a>の頃から機能としては変わっていません。
その辺りは <a href="https://ufcpp.net/blog/2019/2/vs2019p3/">Preview 3</a>の時と同じ。</p>
<p>RC になったわけですから、Visual Studio 2019のリリース版でも、使える機能は今あるものまでとなります。</p>
<h3>C# 8.0 Preview</h3>
<p>これまでにも書いていますが、Visual Studio 2019 リリース時点では、C# 8.0 の扱いは「プレビュー版」です。
言語バージョンに <code>8.0</code> か、後述する <code>preview</code> を明示的に指定しないと使えません。</p>
<p>まだ実装すらされていない機能もたくさんありますし、 .NET Core 3.0 依存な機能はこれから変化する可能性もまだかなり高いです。</p>
<p>(1) 例えば、割かし需要がありそうな機能でまだ実装がないものは</p>
<ul>
<li><a href="https://www.buildinsider.net/column/iwanaga-nobuyuki/013">インターフェイスのデフォルト実装</a></li>
<li><a href="https://github.com/dotnet/csharplang/issues/1710">readonly インスタンス メンバー</a></li>
</ul>
<p>(2) 実装はあるものの、 .NET Core 3.0 依存なので今使うのはちょっと怖いかもしれないものは</p>
<ul>
<li><a href="https://ufcpp.net/blog/2018/12/cs8asyncstreams/">非同期ストリーム</a></li>
<li><a href="https://ufcpp.net/blog/2018/12/cs8ranges/">Ranges</a></li>
</ul>
<p>(3) 実装があって .NET Core 3.0 依存もないものは</p>
<ul>
<li><a href="https://ufcpp.net/blog/2018/12/cs8nrt/">null 許容参照型</a></li>
<li><a href="https://ufcpp.net/blog/2018/12/cs8patterns/">再帰パターン</a></li>
<li><a href="https://ufcpp.net/blog/2018/12/cs8switchexpr/">switch 式</a></li>
<li><a href="https://ufcpp.net/blog/2019/1/vs2019p2/">静的ローカル関数</a></li>
<li><a href="https://ufcpp.net/blog/2018/12/cs8misc/">文字列リテラルの <code>$</code> と <code>@</code> の順序緩和</a></li>
<li><a href="https://ufcpp.net/blog/2018/12/cs8misc/"><code>??=</code> 演算子</a></li>
<li><a href="https://ufcpp.net/blog/2018/12/cs8notyet/">pattern-based な <code>using</code>/<code>foreach</code></a></li>
</ul>
<p>という感じ。</p>
<p>私見ですが、(3) のやつはプレビュー版であってもそんなにリスクなく使えると思います。</p>
<p>null 許容参照型はまだまだいろいろ作業が残っている節があるので、
「後からどんどん警告が増える」というのは覚悟して使う必要があるかもしれません。
その他は、これからそこまでいきなり大きく仕様変更があるとは思えないので、割かし使っても平気かと思います。</p>
<h3>.NET Core 3.0</h3>
<p>まあ、とりあえず、C# 8.0 を試したいなら .NET Core 3.0 の更新も待った方がいいかも…</p>
<p>今また、Visual Studio だけリリースして、それに対応する .NET Core 3.0 がまだ出ていないので、<a href="https://ufcpp.net/blog/2018/12/cs8ranges/">Ranges</a> がコンパイル エラーを起こしたりします。
(僕が気づいた範囲ではその Ranges の問題だけですが。)</p>
<h3>バグはだいぶ取れてる</h3>
<p>前に書いた、</p>
<ul>
<li><a href="https://ufcpp.net/blog/2018/12/pickuproslyn1221/">デリゲートに対する null 検証がおかしくて即落ち</a></li>
<li><a href="https://ufcpp.net/blog/2019/2/vs2019p3/">switch 式で IntelliSense が狂う・フリーズする</a></li>
<li><a href="https://github.com/dotnet/roslyn/issues/33039"><code>foreach</code> の色がおかしい</a></li>
</ul>
<p>とかのバグは治っていました。</p>
<p>まあ、RC ということは、特に問題が出なければそのままリリース版になるものですからね。
Visual Studio 2019 リリース版の時点でもまだ「C# 8.0 はプレビュー版」という扱いであっても、さすがにフリーズとかクラッシュとかの問題は残さないようです。</p>
<h3>言語バージョン</h3>
<p>言語バージョンの仕様がちょっと変わっているので注意が必要です。</p>
<p>補足: ↓これのこと。csproj を直接編集するなら <code>LangVersion</code> タグになっているやつです。</p>
<p><img src="/media/1170/langversion.png" alt="言語バージョン" /></p>
<p>これまでの挙動は</p>
<ul>
<li>
無指定(あるいは <code>default</code> を指定): 「最新のメジャー バージョン」になる
<ul>
<li>要するに、ずっと C# 7.0 だった</li>
</ul>
</li>
<li><code>latest</code> 指定: 「最新のバージョン(マイナー バージョン含む)」になる</li>
</ul>
<p>今後の挙動は</p>
<ul>
<li>無指定(あるいは <code>default</code> を指定): 「最新のバージョン(マイナー バージョン含む)」になる</li>
<li>
<code>latest</code> 指定: 「最新のバージョン(マイナー バージョン含む)」になる
<ul>
<li>これは今まで通り</li>
<li>プレビューなものにはならない</li>
</ul>
</li>
<li>
<code>latestMajor</code> 指定: 「最新のメジャー バージョン」になる
<ul>
<li>今までの <code>default</code> の挙動が欲しければこれを使う</li>
</ul>
</li>
<li>
<code>preview</code> 指定: 「プレビューを含めて最新」になる
<ul>
<li>C# 8.0 を今試したければ、<code>8.0</code> の直接指定に加えて、これを指定してもいい</li>
</ul>
</li>
</ul>
<p>となります。</p>
<p>これまで無指定でやってきた人は、いきなり C# 7.3 になるのでご注意を。
破壊的変更はほぼないはずなので、それで問題は起こさないと思いますが、一応。</p>
<h2><a id="add0301">追記 3月1日</a></h2>
<p>いくつか追記を。</p>
<h3>ダウンロード ページ</h3>
<p>よく考えたら昨日のうちに書いておくべきだったんですけども…
相変わらず、翻訳システムが大変まずい状態でして、以下のようになっています。</p>
<p><a href="https://twitter.com/ufcpp/status/1101018021047332864">https://twitter.com/ufcpp/status/1101018021047332864</a></p>
<p>要するに、</p>
<ul>
<li>ダウンロード ページへのリンクは <a href="https://visualstudio.microsoft.com/downloads/">https://visualstudio.microsoft.com/downloads/</a> になっている</li>
<li>ただ、日本語ロケールで上記リンクを踏むと、<a href="https://visualstudio.microsoft.com/ja/downloads/?rr=https%3A%2F%2Fdevblogs.microsoft.com%2Fvisualstudio%2Fvisual-studio-2019-release-candidate-rc-now-available%2F">https://visualstudio.microsoft.com/ja/downloads/</a> に転送される(ja が挟まる)</li>
<li>で、その ja なページには RC のダウンロード リンクがまだない</li>
</ul>
<p>というやつ。ページの左下にある言語選択メニュー(↓みたいなやつ)から、言語を英語に変えないと RC のインストーラーがダウンロードできないのでご注意ください。</p>
<p><img src="/media/1171/selectlang.png" alt="言語選択メニュー" /></p>
<h3>Roslyn 自体が C# 8.0 化</h3>
<p>Roslyn の master に、LangVersion を 8.0 にするプルリクが出ていてマージされたみたいです。</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/pull/33742">Enable C# 8.0 in the code base #33742</a></li>
</ul>
<p>で、そのプルリク コメントに、使っていい機能に関する補足が。</p>
<ul>
<li><code>switch</code> expressions</li>
<li>recursive pattern matching</li>
<li><code>using</code> declarations</li>
<li><code>static</code> local functions</li>
<li>local / parameter shadowing in local functions / lambdas</li>
<li><code>null</code> coalescing assignment</li>
<li><code>async</code> streams: keep this out of our public API surface for now as we don't want to block unification with netcoreapp in the future.</li>
</ul>
<p>昨日僕が「使ってもまあ大丈夫かなぁ」と書いたのから null 許容参照型を引いた感じ。
あと、非同期ストリームは「使ってもいいけど public なところに書くのは避けて」という感じ。</p>
<p>null 許容参照型に関してはそれのドッグフーディング用のブランチ(<a href="https://github.com/dotnet/roslyn/tree/features/NullableDogfood">features/NullableDogfood</a>)があるからそっちで試してとのこと。</p>
<h3>RC 版で .NET Core 3.0</h3>
<p>昨日、「なんか RC の方だと C# 8.0 がちゃんと使えなかったり、.NET Core 3.0 を参照できなかったり」って書きましたが、解決方法見つかりました。
というか、<a href="https://github.com/dotnet/roslyn/issues/33756">バグ？と思って報告したら解決方法が速攻で返って来ました</a>。</p>
<p>どうも、「プレビューの .NET Core SDK を使用」というオプションがあるみたいです。
これにチェックを入れておかないと、プレビューは使わない → .NET Core 2.2 を選ぶ という流れになってしまってエラーになる模様。</p>
<p><img src="/media/1172/usepreviews.png" alt="プレビューの .NET Core SDK を使用" /></p>
<p>それはわかる… わかるんだけど、それとわかるエラー メッセージになってないのはきつい…</p>
<p>ということで、Preview 4 の方ではなくて RC で C# 8.0 や .NET Core 3.0 を試したい方はこのオプションをオンにしましょう。</p>
 ]]></description>
				<pubDate>Thu, 28 Feb 2019 21:43:27 +0900</pubDate>
			</item>
			<item>
				<title>Visual Studio 2019 Preview 3</title>
				<link>http://ufcpp.net/blog/2019/2/vs2019p3/</link>
				<description><![CDATA[ <p><a href="https://docs.microsoft.com/en-us/visualstudio/releases/2019/release-notes-preview#VS2019_Preview3">Visual Studio 2019 Preview 3</a> 出てますね。</p>
<p>C# がらみは特にアナウンスもないんですが、<a href="https://github.com/dotnet/roslyn/milestone/37?closed=1">Roslyn の 16.0.P3 マイルストーン</a>を見るに、大体は IDE がらみと null 許容参照型がらみを中心としたバグ修正っぽいです。</p>
<p>Preview 2 からあんまり期間が開いていませんし、元からバグ修正のみな予定だったのかも。</p>
<h2>switch 式のバグ</h2>
<p>その割に、<a href="https://github.com/dotnet/roslyn/issues/33378"><code>switch</code> 式を書くと IntelliSense が狂って最終的に Visual Studio がフリーズするバグ</a>が増えちゃってるみたいですが…
(コンパイルはできる。あくまで IDE だけの問題。)</p>
<p>ちょうど最近、「<a href="/study/csharp/">C# によるプログラミング入門</a>」以下に C# 8.0 の話を書き足し始めていて、今週<a href="/study/csharp/datatype/patterns/">パターンの話</a>を書き終えて、次は<code>switch</code>式かなぁとか思っていたところなんで、このフリーズはタイミングが悪すぎる…</p>
<h2>その他細かい修正</h2>
<p>まあ、バグ修正の範囲内ですが、C# の言語機能にも多少変更がありました。</p>
<ul>
<li>
<a href="https://github.com/dotnet/roslyn/issues/32292"><code>switch</code> 式の最後の項の後ろに余計な <code>,</code> を付けても平気になった</a>
<ul>
<li>ついでに、<a href="https://ufcpp.net/study/csharp/datatype/patterns/?p=2#property">プロパティ パターン</a>でも末尾 <code>,</code> を受け付けるようになったらしい</li>
</ul>
</li>
<li><a href="https://github.com/dotnet/roslyn/pull/32640"><code>foreach</code> ステートメントで pattern-based な <code>Dispose</code> 呼び出しが働くようになった</a></li>
<li><a href="https://github.com/dotnet/roslyn/issues/32707">pattern-based な <code>await using</code> で、<code>DisposeAsync</code> メソッドの戻り値が <code>ValueTask</code> 以外の awaitable も受け付けるようになった</a></li>
</ul>
<p>サンプル: <a href="https://github.com/ufcpp/UfcppSample/tree/master/Demo/2019/Csharp80/Preview3">Csharp80/Preview3</a></p>
 ]]></description>
				<pubDate>Thu, 14 Feb 2019 21:27:29 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 2/10 変数のshadowing、関数ポインター、実行時nullチェック、Index/Rangeの仕様変更</title>
				<link>http://ufcpp.net/blog/2019/2/pickuproslyn0210/</link>
				<description><![CDATA[ <p>しばらくちょっと忙しくて紹介できてなかった話をいくつかまとめて。</p>
<h2>匿名関数の変数 shadowing</h2>
<p><a href="/blog/2019/1/vs2019p2/">こないだの VS 2019 Preview 2</a> から、
1段外側の変数と同じ名前で、
ローカル関数内の引数・変数を宣言できるようになったみたいです。</p>
<p>外側の <code>x</code> を隠すので shadowing と呼ばれます。</p>
<pre class="source" title="shadowing">
<code><span class="reserved">static</span> <span class="reserved">int</span> <span class="method">M</span>()
{
    <span class="reserved">int</span> <span class="variable">x</span> = 1;
 
    <span class="comment">// C# 8.0 で、1段外側の変数の x と同名の引数が使えるように</span>
    <span class="reserved">int</span> <span class="method">m</span>(<span class="reserved">int</span> <span class="variable">x</span>) =&gt; <span class="variable">x</span> * <span class="variable">x</span>;
 
    <span class="control">return</span> <span class="method">m</span>(<span class="variable">x</span>);
}
</code></pre>
<p>きっかけとしては、静的ローカル関数が入ったからみたいです。
要するに、</p>
<ul>
<li>外の変数をキャプチャしてるのかどうかぱっと見で分かりにくくなるのは怖いから許してなかった</li>
<li>静的ローカル関数ならキャプチャすることを許さないのでその問題は解消する</li>
<li>とはいえ、静的ローカル関数でだけ shadowing を認めるのも気持ち悪い</li>
</ul>
<p>という流れ。
この決定自体は<a href="https://github.com/dotnet/csharplang/blob/master/meetings/2018/LDM-2018-09-10.md">結構前(去年の9月10日)にやってたみたい</a>です。</p>
<p>ちなみに、現時点ではローカル関数のみ。ラムダ式では shadowing されません。
けども、<a href="https://github.com/dotnet/csharplang/blob/master/meetings/2019/LDM-2019-01-16.md">1月16日の Designs Meeting</a>で、ラムダ式でも認めよう、クエリ式でも検討してみようという話が出ていたり。</p>
<h2>関数ポインター</h2>
<p>C# で<a href="/blog/2018/8/pickuproslyn0822/">デリゲートではなく生で関数ポインターを使いたい</a>という話があったわけですが。
<a href="https://github.com/dotnet/csharplang/blob/master/proposals/function-pointers.md">最近ちょっと検討が進んだみたいで、ちょっと文法が具体化してきました</a>。</p>
<p><code>func* int(string);</code> みたいな書き方になるみたいで、
unsafe コード必須。</p>
<h2>実行時の null チェックの挿入</h2>
<p>C# 8.0 で導入される予定の<a href="/blog/2018/12/cs8nrt/">null 許容参照型</a>は、
基本的にコンパイル時のチェックであって、
(unsafe とかを使って)コンパイル時に拾えないような null が来ても、実行時には何もしません。</p>
<p>一方で、<a href="https://github.com/dotnet/csharplang/pull/2144">実行時の null チェックを挿入するような簡易文法も足したい</a>という話が出ているようです。</p>
<p>これまで、C# では結構以下のようなコードを書いたと思います。</p>
<pre class="source" title="引数の null チェック">
<code><span class="reserved">static</span> <span class="reserved">int</span> <span class="method">M</span>(<span class="reserved">string</span> <span class="variable">x</span>)
{
    <span class="control">if</span> (<span class="variable">x</span> == <span class="reserved">null</span>)
    {
        <span class="control">throw</span> <span class="reserved">new</span> <span class="type">ArgumentNullException</span>(<span class="reserved">nameof</span>(<span class="variable">x</span>));
    }
 
    <span class="control">return</span> <span class="variable">x</span>.Length;
}
</code></pre>
<p>これを、以下のように書くだけで同様の実行時 null チェックを挿入するようにしたいというものです。</p>
<pre class="source" title="実行時 null チェック構文">
<code><span class="reserved">static</span> <span class="reserved">int</span> <span class="method">M</span>(<span class="reserved">string</span> <span class="variable">x</span>!)
{
    <span class="control">return</span> <span class="variable">x</span>.Length;
}
</code></pre>
<p>ただ、null-forgiving (コンパイル時チェックも実行時チェックもなくす)の <code>x!</code> と、この実行時 null チェックの <code>x!</code> で同じ書き方なのが結構気持ち悪く…
その辺りはまだちょっと悩んでいるみたいです。</p>
<h2>Index 型、Range 型の仕様変更</h2>
<p><a href="/blog/2018/12/cs8ranges/">Range 構文</a>の内部実装として使われる<code>Index</code>構造体と<code>Range</code>構造体ですが、
<a href="https://github.com/dotnet/coreclr/pull/22331">coreclr 側の API レビューの結果、実装がだいぶ変更されそうです</a></p>
<p><code>Index</code>構造体</p>
<ul>
<li><code>Start</code>, <code>End</code> 静的プロパティ追加</li>
<li><code>int GetOffset(int length)</code> メソッド追加</li>
</ul>
<p><code>Range</code> 構造体</p>
<ul>
<li><code>FromStart</code>を<code>StartAt</code>に、<code>ToEnd</code>を<code>EndAt</code>にリネーム</li>
<li><code>Create(Index start, Index end)</code> 静的メソッドは削除(普通にコンストラクターを使う)</li>
<li>
<code>OffsetAndLength GetOffsetAndLength(int length)</code> を追加
<ul>
<li><code>OffsetAndLength</code> は <code>(int offset, int length)</code> な構造体 </li>
</ul>
</li>
</ul>
<p>ここまでは確定。
で、これらを使う側(配列とか <code>Span&lt;T&gt;</code> とか)側は、
<code>Range</code> 構造体を受け付けるオーバーロードを足すのではダメなんじゃないかという話も。理由は大体、</p>
<ul>
<li><code>int</code>版と<code>Index</code>版、<code>(int offset, int length)</code>版と<code>Range</code>版の2重保守が大変になる</li>
<li>JIT時最適化を掛けにくくなる</li>
</ul>
<p>みたいな感じ。
これに対して、以下のように <code>int</code> 引数なメソッドに属性を付けて、</p>
<pre class="source" title="属性ベースの Index/Range 受付">
<code><span class="reserved">interface</span> <span class="type">ISomeCollection</span>&lt;<span class="type">T</span>&gt;
{
    [<span class="type">IndexMethod</span>]
    <span class="type">T</span> <span class="reserved">this</span>[<span class="reserved">int</span> <span class="variable">index</span>] { <span class="reserved">get</span>; <span class="reserved">set</span>; }
 
    [<span class="type">RangeMethod</span>]
    <span class="type">ISomeCollection</span>&lt;<span class="type">T</span>&gt; <span class="method">Slice</span>(<span class="reserved">int</span> <span class="variable">start</span>, <span class="reserved">int</span> <span class="variable">length</span>);

    <span class="reserved">int</span> Length { <span class="reserved">get</span>; }
}
</code></pre>
<p>以下のようなコードを、</p>
<pre class="source" title="">
<code><span class="type">ISomeCollection</span>&lt;<span class="type">T</span>&gt; <span class="variable">x</span>;
<span class="reserved">var</span> <span class="variable">y</span> = <span class="variable">x</span>[^1];
<span class="reserved">var</span> <span class="variable">z</span> = <span class="variable">x</span>.Slice(1..^1);
</code></pre>
<p>コンパイラーが以下のように置き換える実装を提案しています。
(ただし、<code>Length</code> や <code>Count</code> をどうやって取るかが課題。)</p>
<pre class="source" title="">
<code><span class="reserved">var</span> <span class="variable">y</span> = <span class="variable">x</span>[^1.GetOffset(<span class="variable">x</span>.Length)];
<span class="reserved">var</span> (<span class="variable">offset</span>, <span class="variable">length</span>) = 1..^1.GetOffsetLength(<span class="variable">x</span>.Length);
<span class="reserved">var</span> <span class="variable">z</span> = <span class="variable">x</span>.Slice(<span class="variable">offset</span>, <span class="variable">length</span>);
</code></pre>
<h2>LangVersion default の変更</h2>
<p>今、LangVersion のデフォルト値(default)は、「最新のメジャー バージョン」になっています。
要するに、現在(最新は 7.3)のところ、default を指定すると 7.0 が選択されます。</p>
<p>これを、今更なんですが、<a href="https://github.com/dotnet/roslyn/pull/33089">以下のように変える pull request</a> が通っていたり。</p>
<ul>
<li>latest はこれまで通り「最新 (マイナー バージョン含む)」</li>
<li>default は latest と同じ意味、つまり、最新</li>
<li>「最新のメジャー バージョン」を表す latestMajor を追加</li>
<li>「プレビュー版」を表す preview を追加</li>
</ul>
 ]]></description>
				<pubDate>Sun, 10 Feb 2019 19:59:01 +0900</pubDate>
			</item>
			<item>
				<title>bool 型の false, true, それ以外</title>
				<link>http://ufcpp.net/blog/2019/1/falsetrueother/</link>
				<description><![CDATA[ <p>これまで(C# 7.3 まで)、C# の <code>switch</code> ステートメントで <code>bool</code> 型を使う場合、以下のように、<code>default</code> 句が必須になることが多々ありました。</p>
<pre class="source" title="true, false, default...">
<code><span class="reserved">static</span> <span class="reserved">int</span> <span class="method">X</span>(<span class="reserved">bool</span> <span class="variable">b</span>)
{
    <span class="control">switch</span> (<span class="variable">b</span>)
    {
        <span class="control">case</span> <span class="reserved">false</span>: <span class="control">return</span> 0;
        <span class="control">case</span> <span class="reserved">true</span>: <span class="control">return</span> 1;
        <span class="control">default</span>: <span class="control">return</span> -1;
    }
}
</code></pre>
<p><code>bool</code> 型には <code>false</code> と <code>true</code> しかないはずなのにこれはおかしいと言われ続けていたんですが、C# 8.0 では <code>default</code> 句が要らなくなるというか、<code>default</code> 句を絶対に通らなくなるよう、コード生成の仕方を変更するみたいです。</p>
<p>今日はこの辺りの、要するに「<code>false</code> でも <code>true</code> でもない <code>bool</code> 値」の話。</p>
<p>サンプルコード: <a href="https://github.com/ufcpp/UfcppSample/tree/master/Demo/2019/BoolExhaustiveness">BoolExhaustiveness</a></p>
<h2>bool とは</h2>
<h3>ドキュメント上</h3>
<p>まず、ドキュメント上、<code>bool</code> がどうなっているかというと…</p>
<ul>
<li>
<a href="https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/bool">C# Language Reference での <code>bool</code> の説明</a>
<ul>
<li><code>System.Boolean</code> 型のエイリアスで、真偽値、すなわち、<code>true</code> か <code>false</code> を格納できる</li>
</ul>
</li>
<li>
<a href="https://docs.microsoft.com/en-us/dotnet/api/system.boolean"><code>Boolean</code> 構造体の説明</a>
<ul>
<li><code>true</code> か <code>false</code> のいずれかの2値を取れる型</li>
</ul>
</li>
</ul>
<p>大体は2つの値だけを取れる型として説明されています。</p>
<h3>実装上: Boolean 構造体</h3>
<p>その <code>Boolean</code> 構造体(<code>System</code> 名前空間)の内部実装がどうなっているかというと、</p>
<ul>
<li>1バイトの構造体</li>
<li><code>true</code> の内部表現は 1</li>
<li><code>false</code> の内部表現は 0</li>
</ul>
<p>です。
1バイトだけども0と1しか必要としないので、残り254個の値は基本的には使われません。</p>
<h2>0 でも 1 でもない bool を作る</h2>
<p>普通にリテラルの <code>true</code>, <code>false</code> や、<code>==</code> などの条件式から <code>bool</code> 値を得る限り、本当に0と1以外の値は発生しません。</p>
<p>ただ、C# は unsafe な手段を使って任意に値を書き換えれちゃうので、無理やりやると 0 でも 1 でもない <code>bool</code> 値を作れます。</p>
<p>具体的にはいくつか書き方があるんですが、1つ目は素直にポインターを使うもの。</p>
<pre class="source" title="ポインターを使って変な bool を作る">
<code><span class="reserved">unsafe</span> <span class="reserved">bool</span> toBool(<span class="reserved">byte</span> b) =&gt; *((<span class="reserved">bool</span>*)&amp;b);
Console.WriteLine(toBool(2));
</code></pre>
<p>もう1つは、<a href="https://ufcpp.net/blog/2018/12/unsafe/"><code>Unsafe</code> クラス</a>を使う書き方。
これもまあ、書き方が違うだけでポインターと大差ないです。</p>
<pre class="source" title="Unsafe クラスを使って変な bool を作る">
<code><span class="reserved">bool</span> toBool(<span class="reserved">byte</span> b) =&gt; Unsafe.As&lt;<span class="reserved">byte</span>, <span class="reserved">bool</span>&gt;(<span class="reserved">ref</span> b);
Console.WriteLine(toBool(2));
</code></pre>
<p>最後に、<code>StructLayout</code> を使う(C 言語の union 風な使い方する)方法。
<code>LayoutKind.Explicit</code> は、ポインター並みに変なことができちゃう機能なので、
そもそも unsafe コードなしで使えること自体が疑問視されていたりもします。
要するに、実質 unsafe。</p>
<pre class="source" title="LayoutKind.Explicit を使って変な bool を作る">
<code><span class="reserved">static</span> <span class="reserved">void</span> Main()
{
    <span class="reserved">bool</span> toBool(<span class="reserved">byte</span> b)
    {
        Union u = <span class="reserved">default</span>;
        u.Byte = b;
        <span class="reserved">return</span> u.Boolean;
    }

    Console.WriteLine(toBool(2));
}

[StructLayout(LayoutKind.Explicit)]
<span class="reserved">private</span> <span class="reserved">struct</span> <span class="type">Union</span>
{
    [FieldOffset(0)]
    <span class="reserved">public</span> <span class="reserved">byte</span> Byte;
    [FieldOffset(0)]
    <span class="reserved">public</span> <span class="reserved">bool</span> Boolean;
}
</code></pre>
<h2>0 でも 1 でもない bool を使うとどうなるか</h2>
<p>x86 などの CPU では、条件分岐命令が以下のような方法で実現されています。</p>
<ul>
<li>直前の命令の結果が 0 になったら立つフラグが CPU 内に存在する</li>
<li>そのフラグを見て分岐する</li>
</ul>
<p>要するに、「0 かどうか」しか見ません。
この意味では、「true とは 0 以外の全ての値を指す」と言えます。</p>
<h3>C# の if ステートメント</h3>
<p>.NET の中間言語もそういう挙動をします。
<a href="https://docs.microsoft.com/ja-jp/dotnet/api/system.reflection.emit.opcodes.brtrue">brtrue 命令</a>ってのを持ってるんですが、
こいつは「value が 0 でなければ分岐」という挙動。</p>
<p>C# の <code>if</code> ステートメントはこの命令(もしくはその逆の <a href="https://docs.microsoft.com/ja-jp/dotnet/api/system.reflection.emit.opcodes.brfalse">brfalse</a>)に変換されるので、
「0 以外の値」は全て <code>true</code> 扱いになります。
実際、前述の方法で作った「中身が2の<code>bool</code>値」を <code>if</code> に渡すと <code>true</code> 側に分岐します。</p>
<pre class="source" title="中身が2のboolは、if 中では true 扱い">
<code><span class="reserved">using</span> System;

<span class="reserved">class</span> <span class="type">Pointer</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> Main()
    {
        <span class="reserved">unsafe</span> <span class="reserved">bool</span> toBool(<span class="reserved">byte</span> b) =&gt; *((<span class="reserved">bool</span>*)&amp;b);

        Branch(<span class="reserved">false</span>);     <span class="comment">// if (false)</span>
        Branch(<span class="reserved">true</span>);      <span class="comment">// if (true)</span>
        Branch(toBool(2)); <span class="comment">// if (true)</span>
    }

    <span class="reserved">static</span> <span class="reserved">void</span> Branch(<span class="reserved">bool</span> b)
    {
        <span class="reserved">if</span> (b) Console.WriteLine(<span class="string">"if (true)"</span>);
        <span class="reserved">else</span> Console.WriteLine(<span class="string">"if (false)"</span>);
    }
}
</code></pre>
<pre class="console" title="中身が2のboolは、if 中では true 扱い">
<code>if (false)
if (true)
if (true)
</code></pre>
<h3>C# 7.3 までの switch ステートメント</h3>
<p>問題はここからなんですが…</p>
<p><code>if</code> ステートメントとは違って、(C# 7.3 までの) <code>switch</code> ステートメントは中身の値を見ます。
すなわち、普通の <code>true</code> と、「中身が2の<code>bool</code>値」は別の値という扱い。</p>
<p>これが、冒頭のコードで <code>default</code> 句が必須になる理由です。
<a href="https://github.com/ufcpp/UfcppSample/blob/master/Demo/2019/BoolExhaustiveness/BoolOtherThan01/Program.cs">実際、<code>case true</code> を通らないようなコード</a>を書けます。</p>
<pre class="source" title="case false も case true も通らない bool 値">
<code><span class="reserved">static</span> <span class="reserved">void</span> Main()
{
    <span class="comment">// 0 → false</span>
    <span class="comment">// 1 → true</span>
    <span class="comment">// それ以外 → if (b) は通るんだけど、switch (b) { case true: } は通らない(C# 7.3 までは)変な値になる。</span>
    <span class="reserved">for</span> (<span class="reserved">byte</span> i = 0; i &lt; 3; i++)
    {
        Console.WriteLine(<span class="string">$"value = </span>{i}<span class="string">"</span>);
        Branch(Pointer(i));
        Branch(UnsafeAs(i));
        Branch(UnionStruct(i));
    }
}

<span class="inactive">///</span><span class="comment"> </span><span class="inactive">&lt;summary&gt;</span>
<span class="inactive">///</span><span class="comment"> false (0) の時は何も表示されない。</span>
<span class="inactive">///</span><span class="comment"> true (1) の時は if(b) switch(b) の両方が表示される。</span>
<span class="inactive">///</span><span class="comment"> 「それ以外の値」を作って渡すと、if(b) だけが表示される。</span>
<span class="inactive">///</span><span class="comment"> </span><span class="inactive">&lt;/summary&gt;</span>
<span class="reserved">static</span> <span class="reserved">void</span> Branch(<span class="reserved">bool</span> b)
{
    <span class="reserved">if</span> (b) Console.WriteLine(<span class="string">"    if(b)"</span>);
    <span class="reserved">switch</span> (b) { <span class="reserved">case</span> <span class="reserved">true</span>: Console.WriteLine(<span class="string">"    switch(b)"</span>); <span class="reserved">break</span>; }
}
</code></pre>
<h3>型 switch</h3>
<p>ちなみにこの「中身の値を見て分岐」挙動は、<code>case</code> が全部定数の場合(= 古き良き昔からある <code>switch</code>) の場合だけの挙動です。</p>
<p>C# 7.0 から入った、<a href="/study/csharp/datatype/typeswitch/?p=2#switch">パターン マッチングを使った <code>switch</code></a>(いやゆる「型 switch」)の場合には brtrue 命令が使われるようになって、<a href="https://github.com/ufcpp/UfcppSample/blob/master/Demo/2019/BoolExhaustiveness/BoolOtherThan01/TypeSwitch.cs"><code>if</code> ステートメントと同じ挙動になります</a>。</p>
<pre class="source" title="型 switch は brtrue と同じ挙動">
<code><span class="reserved">using</span> System;

<span class="reserved">class</span> <span class="type">TypeSwitch</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> Main()
    {
        Branch(0);
        Branch(1);
        Branch(2);
    }

    <span class="reserved">static</span> <span class="reserved">unsafe</span> <span class="reserved">void</span> Branch(<span class="reserved">byte</span> x)
    {
        <span class="reserved">var</span> b = *((<span class="reserved">bool</span>*)&amp;x);

        Console.WriteLine(<span class="string">$"value = </span>{x}<span class="string">"</span>);
        Console.Write(<span class="string">"    traditional switch: "</span>);
        <span class="reserved">switch</span> (b)
        {
            <span class="reserved">case</span> <span class="reserved">false</span>:
                Console.WriteLine(<span class="string">"false"</span>);
                <span class="reserved">break</span>;
            <span class="reserved">case</span> <span class="reserved">true</span>:
                Console.WriteLine(<span class="string">"true"</span>);
                <span class="reserved">break</span>;
            <span class="reserved">default</span>:
                <span class="comment">// 0でも1でもないbool値の時にここに来る</span>
                Console.WriteLine(<span class="string">"other"</span>);
                <span class="reserved">break</span>;
        }

        Console.Write(<span class="string">"    type switch: "</span>);
        <span class="reserved">switch</span> (b)
        {
            <span class="reserved">case</span> <span class="reserved">false</span> <em><span class="reserved">when</span> <span class="reserved">true</span></em>:
                Console.WriteLine(<span class="string">"false"</span>);
                <span class="reserved">break</span>;
            <span class="reserved">case</span> <span class="reserved">true</span>:
                Console.WriteLine(<span class="string">"true"</span>);
                <span class="reserved">break</span>;
            <span class="reserved">default</span>:
                <span class="comment">// 絶対ここは通らない</span>
                Console.WriteLine(<span class="string">"other"</span>);
                <span class="reserved">break</span>;
        }
    }
}
</code></pre>
<pre class="console" title="型 switch は brtrue と同じ挙動">
<code>value = 0
    traditional switch: false
    type switch: false
value = 1
    traditional switch: true
    type switch: true
value = 2
    traditional switch: <em>other</em>
    type switch: true
</code></pre>
<h3>マーシャリング</h3>
<p>ちなみに、<a href="/study/csharp/sp_pinvoke.html#pinvoke">P/Invoke</a>を使う際には、マーシャリング時に「0でも1でもない<code>bool</code>値」を<code>true</code>(内部的に1の<code>bool</code>値)に置き換える処理が掛かるみたいです。</p>
<p>例えば、以下のような Rust コードを lib.dll 中で定義しておいて、</p>
<pre class="source" title="8ビット整数値を素通しする Rust 関数">
<code>#[no_mangle]
<span class="reserved">pub extern fn</span> <span class="method">id</span>(<span class="variable">x</span>: <span class="type">i8</span>) -> <span class="type">i8</span> { <span class="variable">x</span> }
</code></pre>
<p>これを C# 側から以下のように呼び出します。</p>
<pre class="source" title="id 関数を C# から呼び出し">
<code><span class="reserved">using</span> System;
<span class="reserved">using</span> System.Runtime.InteropServices;

<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> Main(<span class="reserved">string</span>[] args)
    {
        <span class="comment">// 素通し。当然、2。</span>
        <span class="reserved">byte</span> a = Id(2);
        Console.WriteLine(a);

        <span class="comment">// 素通しじゃなくて、bool で値を受け取り。true。</span>
        <span class="reserved">bool</span> b = ToBool(2);
        Console.WriteLine(b);

        <span class="reserved">unsafe</span>
        {
            <span class="comment">// 内部表現を見てみると、1 になってる。</span>
            <span class="reserved">byte</span> b1 = *(<span class="reserved">byte</span>*)&amp;b;
            Console.WriteLine(b1);
        }
    }

    <span class="inactive">///</span><span class="comment"> </span><span class="inactive">&lt;summary&gt;</span>
    <span class="inactive">///</span><span class="comment"> rust 側の id 関数は i8 を素通しするだけ。</span>
    <span class="inactive">///</span><span class="comment"> それを DllImport で呼んでるので、このメソッドも素通し。</span>
    <span class="inactive">///</span><span class="comment"> </span><span class="inactive">&lt;/summary&gt;</span>
    [DllImport(<span class="string">"lib.dll"</span>, EntryPoint = <span class="string">"id"</span>)]
    <span class="reserved">private</span> <span class="reserved">static</span> <span class="reserved">extern</span> <span class="reserved">byte</span> Id(<span class="reserved">byte</span> x);

    <span class="inactive">///</span><span class="comment"> </span><span class="inactive">&lt;summary&gt;</span>
    <span class="inactive">///</span><span class="comment"> マーシャリングで、byte な戻り値を bool で受け取ることができる。</span>
    <span class="inactive">///</span><span class="comment"> ただ、この場合、素通しではなくて、ちゃんと 戻り値 != 0 で bool に変換されているみたい。</span>
    <span class="inactive">///</span><span class="comment"> </span><span class="inactive">&lt;/summary&gt;</span>
    [DllImport(<span class="string">"lib.dll"</span>, EntryPoint = <span class="string">"id"</span>)]
    <span class="reserved">private</span> <span class="reserved">static</span> <span class="reserved">extern</span> <span class="reserved">bool</span> ToBool(<span class="reserved">byte</span> x);
}
</code></pre>
<p><code>id</code>関数の戻り値は <code>i8</code> (C# でいう <code>sbyte</code>)ですが、マーシャリング時に <code>bool</code> への変換をしてくれます。
変換の仕方は、<code>!= 0</code> になっているみたいで、「0 でない値」だったら普通の <code>true</code> (内部的に1の<code>bool</code>値)が返ってきます。</p>
<h3>C# 8.0 での switch ステートメントの変更</h3>
<p>まあ、要するに、<code>switch</code> ステートメントだけがきもいです。</p>
<p>たびたび「<code>case false</code> と <code>case true</code> があれば <code>default</code> 要らないだろ」と言われ続け、
そのたびに「内部的に <code>false</code> でも <code>true</code> でもない値があり得るから」という回答が返って来続けていたんですが。</p>
<p>この度、「ドキュメント上も 『<code>true</code> と <code>false</code> の2値』と明記されているんだから、それ以外の値を想定して非効率なコードを生成するのはおかしいだろ」という突っ込みがあって、「それは確かに」的な空気になったみたいです。</p>
<p>また、C# 8.0 では <a href="/blog/2018/12/cs8switchexpr/"><code>switch</code> 式</a>も入るので、網羅性のチェック(「<code>true</code> と <code>false</code> で全パターン網羅している」という判定)をしたい需要が高まったので、ついに折れて、<code>bool</code> に対する <code>switch</code> の挙動を変えることにしたみたいです。</p>
<pre class="source" title="bool に対する switch の仕様変更">
<code><span class="reserved">using</span> System;

<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> Main()
    {
        Console.WriteLine(X(<span class="reserved">false</span>)); <span class="comment">// -1</span>
        Console.WriteLine(X(<span class="reserved">true</span>)); <span class="comment">// 1</span>

        <span class="reserved">unsafe</span>
        {
            <span class="reserved">byte</span> x = 2;
            <span class="reserved">bool</span> y = *(<span class="reserved">bool</span>*)&amp;x;
            Console.WriteLine(X(y)); <span class="comment">// C# 7.0 までは 0 だった。C# 8.0 で 1 になるように。</span>
        }
    }

    <span class="reserved">static</span> <span class="reserved">int</span> X(<span class="reserved">bool</span> b)
    {
        <span class="reserved">switch</span> (b)
        {
            <span class="reserved">case</span> <span class="reserved">false</span>: <span class="reserved">return</span> -1;
            <span class="reserved">case</span> <span class="reserved">true</span>: <span class="reserved">return</span> 1;
            <span class="reserved">default</span>: <span class="reserved">return</span> 0;     <span class="comment">// C# 7.0 までは何も言われなかった。C# 8.0 で「到達できないコード」警告出るように。</span>
        }
    }
}
</code></pre>
<p>内部的には <code>if</code> 相当のコードへの置き換えです。</p>
<p>ちなみに、Visual Studio 2019 Preview 2だと、「<a href="https://github.com/dotnet/roslyn/issues/32806">LangVersion を 7.3 以下にしてても新しい方の挙動になってしまう</a>」というバグがあったりします。
バグ認定はされていて、正式版までには「C# 8.0 以上にした場合だけ新しい挙動になる」に変更されるはずです。</p>
 ]]></description>
				<pubDate>Mon, 28 Jan 2019 14:50:18 +0900</pubDate>
			</item>
			<item>
				<title>Visual Studio 2019 Preview 2</title>
				<link>http://ufcpp.net/blog/2019/1/vs2019p2/</link>
				<description><![CDATA[ <p>なんか、<a href="https://docs.microsoft.com/en-us/visualstudio/releases/2019/release-notes-preview#VS2019_Preview2">Visual Studio 2019 Preview 2</a>が出てますね。</p>
<p>リリースノート上は、.NET 関連はまた「<a href="https://docs.microsoft.com/en-us/visualstudio/releases/2019/release-notes-preview#net-productivity">リファクタリング機能が増えたよ</a>」みたいな感じのアナウンス。</p>
<p>あとは、自分が手元で確認してみた感じ、<a href="/blog/2018/12/vs2019p1/">Preview 1</a>の頃から3つほど C# 8.0 の実装が増えてました。</p>
<ul>
<li>再帰パターン</li>
<li>using の改善</li>
<li>静的ローカル関数</li>
</ul>
<p>動作確認で使ったコード: <a href="https://github.com/ufcpp/UfcppSample/tree/master/Demo/2019/Csharp80/Preview2">Demo/2019/Csharp80/Preview2</a></p>
<h2>再帰パターン</h2>
<p>これは Preview 1 で入ると思ってたのに入らなかったというくらいなので、
前に、<a href="https://sharplab.io/">sharplab.io</a>で動作確認しながら書いた以下の2つのブログほぼそのまま。</p>
<ul>
<li><a href="/blog/2018/12/cs8patterns/">再帰パターン</a></li>
<li><a href="/blog/2018/12/cs8switchexpr/">switch 式</a></li>
</ul>
<p>一応、0引数・1引数での <code>Deconstruct</code> ができるようになったりしているみたいです。</p>
<pre class="source" title="0, 1引数 Deconstructと再帰パターン">
<code><span class="reserved">using</span> System;
 
<span class="reserved">struct</span> <span class="type">X</span>
{
    <span class="reserved">public</span> <span class="reserved">void</span> <span style="color:#74531f;">Deconstruct</span>() { }
    <span class="reserved">public</span> <span class="reserved">void</span> <span style="color:#74531f;">Deconstruct</span>(<span class="reserved">out</span> <span class="reserved">int</span> <span style="color:#1f377f;">x</span>) =&gt; <span style="color:#1f377f;">x</span> = 0;
    <span class="reserved">public</span> <span class="reserved">void</span> <span style="color:#74531f;">Deconstruct</span>(<span class="reserved">out</span> <span class="reserved">int</span> <span style="color:#1f377f;">x</span>, <span class="reserved">out</span> <span class="reserved">int</span> <span style="color:#1f377f;">y</span>) =&gt; (<span style="color:#1f377f;">x</span>, <span style="color:#1f377f;">y</span>) = (0, 0);
}
 
<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> <span style="font-weight:bold;color:#74531f;">Main</span>()
    {
        <span class="reserved">var</span> <span style="color:#1f377f;">x</span> = <span class="reserved">new</span> <span class="type">X</span>();
        <span style="font-weight:bold;color:#2b91af;">Console</span>.<span style="font-weight:bold;color:#74531f;">WriteLine</span>(<span style="color:#1f377f;">x</span> <span class="reserved">is</span> ());      <span class="comment">// 0引数</span>
        <span style="font-weight:bold;color:#2b91af;">Console</span>.<span style="font-weight:bold;color:#74531f;">WriteLine</span>(<span style="color:#1f377f;">x</span> <span class="reserved">is</span> <span class="reserved">var</span> (<span class="reserved">_</span>)); <span class="comment">// 1引数のだけは、() 式とかキャストとかとの弁別のために var 必須</span>
        <span style="font-weight:bold;color:#2b91af;">Console</span>.<span style="font-weight:bold;color:#74531f;">WriteLine</span>(<span style="color:#1f377f;">x</span> <span class="reserved">is</span> (<span class="reserved">_</span>, <span class="reserved">_</span>));  <span class="comment">// 2引数</span>
    }
}
</code></pre>
<h2>using の改善</h2>
<p>2つほど。</p>
<ul>
<li><code>ref struct</code> に限り、<code>IDisposable</code> インターフェイスを実装していなくても、パターン ベースで<code>Dispose</code>メソッドを呼んでくれるようになった</li>
<li><code>using var</code> で、ローカル変数のスコープに紐づいたリソースの破棄(<code>Dispose</code> メソッド呼び出し)ができるようになった</li>
</ul>
<p>はい、残念なお知らせ。パターン ベースでの<code>Dispose</code>呼び出しが<a href="https://ufcpp.net/study/csharp/resource/refstruct/"><code>ref struct</code></a>限定になりました。
そうしないと破壊的変更を起こす可能性があってやむなく限定したそうです。</p>
<pre class="source" title="パターン ベースの using">
<code><span class="reserved">using</span> System;
 
<span class="comment">// インターフェイスなし、ref なし</span>
<span class="reserved">struct</span> <span class="type">A</span> { <span class="reserved">public</span> <span class="reserved">void</span> <span style="color:#74531f;">Dispose</span>() { } }
 
<span class="comment">// インターフェイスあり</span>
<span class="reserved">struct</span> <span class="type">B</span> : <span class="type">IDisposable</span> { <span class="reserved">public</span> <span class="reserved">void</span> <span style="color:#74531f;">Dispose</span>() { } }
 
<span class="comment">// ref あり</span>
<span class="reserved">ref</span> <span class="reserved">struct</span> <span class="type">C</span> { <span class="reserved">public</span> <span class="reserved">void</span> <span style="color:#74531f;">Dispose</span>() { } }
 
<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> <span style="font-weight:bold;color:#74531f;">Main</span>()
    {
        <span class="reserved">using</span> <span class="reserved">var</span> <span style="color:#1f377f;">a</span> = <span class="reserved">new</span> <span class="type">A</span>(); <span class="comment">// ダメ</span>
        <span class="reserved">using</span> <span class="reserved">var</span> <span style="color:#1f377f;">b</span> = <span class="reserved">new</span> <span class="type">B</span>(); <span class="comment">// 元々 OK</span>
        <span class="reserved">using</span> <span class="reserved">var</span> <span style="color:#1f377f;">c</span> = <span class="reserved">new</span> <span class="type">C</span>(); <span class="comment">// C# 8.0 で OK に</span>
    }
}
</code></pre>
<h2>静的ローカル関数</h2>
<p>ローカル関数に <code>static</code> 修飾を付けることで、<a href="/study/csharp/sp2_anonymousmethod.html#closure">ローカル変数のキャプチャ</a>をしないということを明示できるようになります。</p>
<pre class="source" title="">
<code><span class="comment">// ローカル関数に static を付けると、ローカル変数をキャプチャできなくなる。</span>
<span class="reserved">static</span> <span class="reserved">int</span> <span style="color:#74531f;">a</span>(<span class="reserved">int</span> <span style="color:#1f377f;">x</span>) =&gt; 2 * <span style="color:#1f377f;">x</span>;
 
<span class="comment">// 以下のコードは2行目の n のところでエラーに。</span>
<span class="reserved">int</span> <span style="color:#1f377f;">n</span> = 0;
<span class="reserved">static</span> <span class="reserved">int</span> <span style="color:#74531f;">b</span>(<span class="reserved">int</span> <span style="color:#1f377f;">x</span>) =&gt; <span style="color:#1f377f;">n</span> * <span style="color:#1f377f;">x</span>;
</code></pre>
<h2>Preview 1 からのその他の修正</h2>
<p><a href="/blog/2018/12/cs8asyncstreams/">Async streams</a>はいまだに動きません…
これは、たぶん、 .NET Core 3.0 の方の Preview 2が来れば解消される気がします。</p>
<p>あと、<a href="/blog/2018/12/cs8nrt/">null許容参照型</a>は、以下のような変更が掛かってそう</p>
<ul>
<li>
プロジェクト全体に対して null 解析をオンにするためのオプションが以下のように変更されてそう
<ul>
<li>旧: <code>&lt;NullableReferenceTypes&gt;true&lt;/NullableReferenceTypes&gt;</code></li>
<li>新: <code>&lt;NullableContextOptions&gt;Enable&lt;/NullableContextOptions&gt;</code></li>
</ul>
</li>
<li>
解析が走るタイミングが変わっていそう(たぶん)
<ul>
<li>旧: 常時</li>
<li>新: ファイルを開いているとき</li>
</ul>
</li>
</ul>
 ]]></description>
				<pubDate>Thu, 24 Jan 2019 19:58:52 +0900</pubDate>
			</item>
			<item>
				<title>null かどうかを判定</title>
				<link>http://ufcpp.net/blog/2019/1/fasternullchecks/</link>
				<description><![CDATA[ <p>C# では、無効な値として <a href="/study/csharp/rm_nullusage.html">null</a> をよく使うので、
「値が有効かどうか」「無効だったら何もしない」みたいな判定のために null チェックを結構書きます。
で、C# の null は「全ビットが0」で表されるので、通常、null チェックは非常に軽い処理(単なる 0 との比較)になります。</p>
<p>通常は。</p>
<p>問題は、<code>==</code> 演算子のオーバーロードがある場合。
その場合、<code>x == null</code> は、演算子(を表すメソッド)の呼び出しになります。
もしその <code>==</code> 演算子が<a href="/study/csharp/structured/miscinlining/">インライン展開</a>できないものだった場合、「単なる0比較」と比べると大幅に遅いコードになります。</p>
<p>なので元々、<code>==</code> 演算子のオーバーロードがある場合には、<code>x == null</code> ではなくて、
<code>(object)x == null</code> や、<code>ReferenceEquals(x, null)</code> を使えという話もあったりします。
ですが、これらはちょっと長ったらしくてつらい。</p>
<p>一方、C# 7.0 で<a href="/study/csharp/datatype/typeswitch/">パターン マッチング</a>が入って、定数パターンを使った <code>x is null</code> であれば、
たとえ演算子オーバーロードがあったとしても、必ず「単なる0比較」で null チェックが掛かります。</p>
<p>そこで最近、<code>==</code> 演算子をオーバーロードしちゃっているクラスに対して <code>x == null</code> しているところを、<code>x is null</code> に置き換える最適化を掛けることが多かったりします。</p>
<p>そして、<a href="https://github.com/dotnet/coreclr">coreclr</a>内で大々的にこの最適化をやろうとした痕跡が。</p>
<ul>
<li><a href="https://github.com/dotnet/coreclr/pull/21736">Faster null checks #21736</a></li>
</ul>
<p>日付的に、ホリデーシーズンの余暇でやってみたんですかね。</p>
<p>ただ、あまりにも数が多過ぎてちまちま置き換える作業は結局断念したみたいです。
400ファイル、4千行とかですからね、差分。</p>
<p>で、別の解決策として挙がっているのがこちら。</p>
<ul>
<li><a href="https://github.com/dotnet/coreclr/pull/21765">Support faster null checks #21765</a></li>
</ul>
<p><code>==</code> 演算子オーバーロードの実装の方に手を入れて、</p>
<ul>
<li>インライン展開が掛かるサイズに収める</li>
<li><code>x == null</code> (右辺が null )の時には <code>x is null</code> だけが残る構造にする</li>
</ul>
<p>となるようにしたという修正。
<code>==</code> 演算子の実装は、具体的には概ね以下のような構造です。</p>
<pre class="source" title="インライン展開可能、かつ、== null の最適化が掛かるように == を実装">
<code><span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">bool</span> <span class="reserved">operator</span> ==(<span class="type">MyClass</span> left, <span class="type">MyClass</span> right)
    =&gt; (right <span class="reserved">is</span> <span class="reserved">null</span>) ? (left <span class="reserved">is</span> <span class="reserved">null</span>) : right.Equals(left);
</code></pre>
<p>最後が <code>right is null</code> を先に判定して、後ろが <code>right.Equals(left)</code> なのがポイント。
<code>null == x</code> だと最適化は掛からない構造。
(C# ではあまり見ませんけども、「リテラルは左辺にあるべき」派の人はご注意を。)</p>
<p>あと、「<a href="/study/csharp/rm_nullusage.html#user-defined-null">null じゃないのに null を自称する邪悪なクラス</a>」なんかにはこの最適化は使えないので、<a href="https://docs.unity3d.com/ja/2017.4/ScriptReference/Object.html">そういう残念なやつ</a>はあきらめましょう…</p>
 ]]></description>
				<pubDate>Fri, 04 Jan 2019 19:54:25 +0900</pubDate>
			</item>
			<item>
				<title>Hardware Intrinsics</title>
				<link>http://ufcpp.net/blog/2018/12/hdintrinsic/</link>
				<description><![CDATA[ <p>今日は、おそらく .NET Core 3.0 で正式リリースとなるであろう最適化の話。
Hardware Intrinsics といって、特定 CPU の専用命令を利用するための機能の話になります。</p>
<p>元々は .NET Core 2.1 の頃に作業が始まっているんですが、2.1 リリースのタイミングには間に合いませんでした。
しかし、内部的な対応はすでに入っていて、<a href="https://dotnet.myget.org/feed/dotnet-core/package/nuget/System.Runtime.Intrinsics.Experimental">daily ビルドなパッケージ</a>を参照すれば、今現在の .NET Core 2.1 でも利用可能です。
というか、<a href="https://docs.microsoft.com/ja-jp/dotnet/api/system.runtime.intrinsics.x86?view=dotnet-plat-ext-2.1">ドキュメントはすでにあります</a>。</p>
<h2>CPU 専用命令</h2>
<p>いろいろなプログラミング言語で書かれたプログラムを比較したとき、
傾向として言うと、C 言語や C++ で書かれたものが最速です。</p>
<p>C# は、これら C や C++ と比較してどこがボトルネックでしょう。
印象としては<a href="/study/computer/MemoryManagement.html#garbage-collection">ガベージ コレクション</a>が遅そうに思われるかもしれませんが、案外、別のところにも原因があります。
(C# でもヒープ アロケーションを避けるコードは書けます。
それに、ヒープをどうしても避けれない場合だけに限定していうと、
ガベージ コレクションによるヒープ管理はものすごく高速です。)</p>
<p>高速化の行き着く先は、特定の CPU の専用命令をどれだけうまく使えるかになったりします。</p>
<p>例えば、32ビット整数の中から、特定のビットだけを抜き出すことを考えてみます。
普通に C# で書くと以下のような感じ。</p>
<pre class="source" title="uint 中の特定のビットを抜き出し">
<code><span class="reserved">struct</span> <span class="type">SingleView</span>
{
    <span class="reserved">public</span> <span class="reserved">uint</span> Value;
 
    <span class="inactive">///</span><span class="comment"> </span><span class="inactive">&lt;</span><span class="inactive">summary</span><span class="inactive">&gt;</span>
    <span class="inactive">///</span><span class="comment"> Value のうち、23～31ビット目の値を抜き出す。</span>
    <span class="inactive">///</span><span class="comment"> </span><span class="inactive">&lt;/</span><span class="inactive">summary</span><span class="inactive">&gt;</span>
    <span class="reserved">public</span> <span class="reserved">uint</span> Exponent
    {
        <span class="reserved">get</span> =&gt; (Value &amp; 0x7F800000) &gt;&gt; 23;
        <span class="reserved">set</span> =&gt; Value = (<span class="reserved">uint</span>)((Value &amp; ~0x7F800000) | ((<span class="reserved">value</span> &lt;&lt; 23) &amp; 0x7F800000));
    }
}
</code></pre>
<p>AND とか OR とかシフト演算がいくつか必要です。</p>
<p>ところが、これ、たいていの CPU で1命令で実行できる命令があったりします。
<a href="http://www.felixcloutier.com/x86/BEXTR.html">x86 CPU だと BEXTR 命令</a>、
<a href="http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0489f/Cjahjhee.html">ARM だと UBFX 命令</a>というのがそれです。</p>
<p>理想をいうと、先ほどの AND とシフトな C# コードから、ちゃんと最適化でこれらの専用命令に翻訳されてほしいんですが、そんなにうまく行かないことが多いです。</p>
<p>そこで行き着く先は、「<a href="https://ja.wikipedia.org/wiki/%E3%82%A4%E3%83%B3%E3%83%A9%E3%82%A4%E3%83%B3%E3%82%A2%E3%82%BB%E3%83%B3%E3%83%96%E3%83%A9">インライン アセンブラ</a>を書かせろ」となったりします。
実際、速いといわれている C/C++ コードは、CPU 専用命令を使ってガチガチに最適化していたりします。</p>
<p>実のところ、C/C++ と比べたときに C# (や、Java, Go, Swift 辺りの「そこそこ速い」言語)が遅い理由の結構な割合が、こういう専用命令利用に関する部分だったりします。</p>
<h2>Intrinsics</h2>
<p>ということで、C# 内にもインライン アセンブラを書きたいという要望はあるんですが。</p>
<p>しかし、「C# の中で別の言語を保守する」というのは、コンパイラーを作る側にとっても使う側にとってもかなりのハードル・足かせになります。
そこで最近よく取られる手法が、「intrinsic 関数の提供」です。</p>
<p>「<a href="/blog/2018/12/jitintrinsics/">JIT Intrinsics</a>」でも書きましたが、
intrinsic というのは固有の、内在的な、内因的な、本質的なという意味の単語で、
概ね、「内部的に特別扱いして最適化しているもの」という意味で使われています。</p>
<p>そして、intrinsic 関数(あるいは単に intrinsics)というのは、</p>
<ul>
<li>普通に関数(C# だと静的メソッド)としてライブラリ提供する</li>
<li>その関数を見たら特定の CPU 命令に置き換える</li>
</ul>
<p>というようなもののことです。</p>
<p>例えば C++ でも、有名なものでは、<a href="https://software.intel.com/sites/landingpage/IntrinsicsGuide/">Intel Intrinsics</a> というものがあります。
名前通り Intel CPU 向けのものですが、Visual C++, GCC, clang など、Intel 製以外の C/C++ コンパイラーでも大体利用できます。
<code>mmintrin.h</code> とかで検索してもらうとサンプル コードがすぐに見つかると思います。
以下のような感じで、普通の C++ コードを書くと、それが特定の Intel CPU 命令に置き換わります。</p>
<pre class="source" title="C++ での Intel Intrisics">
<code><span class="reserved">#include</span> <span class="string">&lt;immintrin.h&gt;</span>
<span class="comment">// 中略</span>
<span class="type">__m128</span> c = _mm_mul_ps(a, b);
</code></pre>
<p>いわゆる SIMD 演算というやつで、
複数の積和演算を1命令で実行するので、うまく使えば数値計算が4～8倍速くなったりします。</p>
<p>ただし、注意点もあります。
特定 CPU の専用命令を使うための手法なので当然なんですが、
特定の CPU に依存します。
上記の Intel Intrinsics であれば当然 Intel CPU でしか動きません。
同じ Intel 系の CPU でも、世代を追うごとに命令がどんどん追加されているわけで、
古い CPU では対応していない命令が大量にあります。</p>
<p>その結果どうなるかというと、ガチガチに最適化するなら <code>#ifdef</code> だらけになります。
例え古い CPU のサポートを切ったとしても、Intel 系と ARM 系の2種類は保守が必要になったりします。</p>
<h2>.NET でも Hardware Intrinsics</h2>
<p>ということで、 .NET Core 2.1 くらいの頃から、.NET にも Hardware Intrinsics を入れたいという話が出ます。</p>
<p>実際、実は内部的にはもうその対応が入っていて、以下のパッケージを参照すれば .NET Core 2.1 で Hardware Intrinsics を使えます。</p>
<ul>
<li><a href="https://dotnet.myget.org/feed/dotnet-core/package/nuget/System.Runtime.Intrinsics.Experimental">System.Runtime.Intrinsics.Experimental</a></li>
</ul>
<p>現状は、nuget.org からは落とせません。
MyGet (daily ビルド用の CI サーバー)からのみ取得できます。
また、正式リリースされた暁には Experimental が外れて、System.Runtime.Intrinsics パッケージになると思われます(もしかしたら、X86 と Arm で別パッケージになるかも)。</p>
<p>例えば、最初に出した「特定のビットだけを抜き出す」コードは以下のように書けます。</p>
<pre class="source" title="System.Runtime.Intrinsics">
<code><span class="reserved">using</span> System.Runtime.Intrinsics.X86;
 
<span class="reserved">struct</span> <span class="type">SingleView</span>
{
    <span class="reserved">public</span> <span class="reserved">uint</span> Value;
 
    <span class="reserved">public</span> <span class="reserved">uint</span> Exponent
    {
        <span class="reserved">get</span>
        {
            <span class="reserved">if</span> (<span class="type">Bmi1</span>.IsSupported) <span class="reserved">return</span> <span class="type">Bmi1</span>.BitFieldExtract(Value, 23, 8);
            <span class="reserved">else</span> <span class="reserved">return</span> (Value &amp; 0x7F800000) &gt;&gt; 23;
        }
        <span class="comment">// set 割愛</span>
    }
}
</code></pre>
<p>他にも、先ほど挙げた Intel Intrinsics 相当のメソッドもあります。</p>
<p>ちなみに、ここで出てくる <code>IsSupported</code> プロパティは JIT 時定数になります。
このコードは、JIT が掛かるタイミングで、
この CPU 命令セットを持っている環境なら <code>if</code> 側、
持っていない環境なら <code>else</code> 側だけが残ります。</p>
<p>なのでパフォーマンス的にはかなりいいものに仕上がるんですが、
見ての通り、同じ意味のコードを2回書く必要があります。
もちろん、ARM 系 CPU にも対応したければ3回に。</p>
<p>要するに、C/C++ でよくある「ガチガチに最適化するなら <code>#ifdef</code> だらけ」が、C# でも書けるようになります…
大変さと引き換えに、数倍高速なコードが手に入ります。</p>
 ]]></description>
				<pubDate>Mon, 31 Dec 2018 10:17:34 +0900</pubDate>
			</item>
			<item>
				<title>段階コンパイル (Tiered Compilation)</title>
				<link>http://ufcpp.net/blog/2018/12/tieredcompilation/</link>
				<description><![CDATA[ <p>今日は .NET Core 2.1 の頃に実装されて(有効にするには設定が必要)、
<strike>.NET Core 2.2 からは既定で有効になる</strike>ランタイムの最適化の話。</p>
<p>(※ Preview の頃にいったん規定で有効になったものの、結局、リリースでは opt-in に戻した模様。後述する gen0 最適化問題とかがあるせいかも。)</p>
<p>.NET Core 2.1 の頃に以下のようなブログが出ていました。</p>
<ul>
<li><a href="https://blogs.msdn.microsoft.com/dotnet/2018/08/02/tiered-compilation-preview-in-net-core-2-1/">Tiered Compilation Preview in .NET Core 2.1</a></li>
</ul>
<p>これも今までそんなにここで取り上げていないので、
.NET Core 2.2 が出た今、「在庫処分」的に取り上げようかと思います。</p>
<h2>JIT コンパイルの段階化</h2>
<p>Java とか C# みたいな Just-In-Time コンパイル方式の言語では、常に以下のようなジレンマを持っています。</p>
<ul>
<li>中間コードからネイティブ コードに実行時にコンパイルするので、あんまりコンパイルに時間をかけるとかえって遅くなる</li>
<li>かといってコンパイル時の最適化がしょぼいと、出てくるネイティブ コードが遅い</li>
</ul>
<p>長期的に動かすのであれば、最適化に時間をかけてでも良いネイティブ コードを生成する方が得になったりはします。
ただし、それは最終的にトータルでは速くなるという話で、起動にかかる時間は最適化を頑張ろうとするほど遅くなります。
また、そんなに頑張って最適化した結果が報われるような「よく通る経路」は、全体の一部分でしかありません。</p>
<p>そこで、以下のように、段階的な最適化を考えます。</p>
<ul>
<li>初めて呼ばれるメソッドは一律「最適化なし」でJITコンパイルする</li>
<li>呼ばれた回数をカウントして、一定数を越えたら「最適化あり」でJITコンパイルしなおして差し替える</li>
</ul>
<p>こういう手法を段階コンパイル(tiered compilaition)と言います。</p>
<h2>coreclr の段階コンパイル</h2>
<p>段階コンパイルは、例えば Java は Java 7 の時に導入したそうで、そんなに目新しい手法でもありません。
.NET Core でも、2016 にはプロトタイプ実装があったそうです。
ただ、.NET はもともと NGEN (事前ネイティブ化)や MulticoreJit (並列コンパイル)などで起動時間の短縮に取り組んできていました。
それに、<a href="/study/csharp/resource/span/"><code>Span&lt;T&gt;</code>構造体</a>による最適化とか、違う角度でのパフォーマンス改善などもいろいろあって、
なかなか段階コンパイルの優先度が上がらなかったみたいです。</p>
<p>それでも、.NET Core 2.1 には組み込まれて、.NET Core 2.2 ではついに既定動作として段階コンパイルが有効になりました。</p>
<p>技術的には以下のような実装になっているそうです。</p>
<ul>
<li>
肝となるのは、実行時に、すでにJITコンパイル済みのコードを改めてJITコンパイルしなおして差し替える機能
<ul>
<li>それ単体で <a href="https://github.com/dotnet/coreclr/blob/master/Documentation/design-docs/code-versioning.md">CodeVersionManager</a> という名前がついていてドキュメントがある</li>
<li>段階コンパイル以外にも、あまり使われていないコードを破棄することで省メモリ化したり、診断ログを採るためのコードを動的に差し込むのに使えます</li>
</ul>
</li>
<li>
初期状態を Tier0、頻繁に呼ばれていて最適化したいコードを Tier1 という名前で分類
<ul>
<li>ただ、現状では、元々デバッグ用にある最適化のオン・オフをそのまま使って、Tier0 なら最適化なし、Tier1 なら最適化ありでコンパイルしているだけ</li>
</ul>
</li>
<li>
差し替えは並列動作可能
<ul>
<li>メソッド A から別のメソッド B を呼んでいる最中に、A が Tier1 に昇格・再 JIT した場合、B からの戻り先アドレスに補正をかけるような処理がちゃんと働く</li>
</ul>
</li>
</ul>
<h2>今後</h2>
<p><a href="https://blogs.msdn.microsoft.com/dotnet/2018/08/02/tiered-compilation-preview-in-net-core-2-1/">上記のブログ</a>が書かれた頃から、
さらに改善も始まっているみたいです。</p>
<p>計画としては例えば、メソッドが呼ばれた回数のカウントは今の実装はあまり効率的なものじゃないことがわかっているそうなので、そこは直したいとのこと。
あと、Tier1 コンパイルはシングル スレッドで行われているそうなので、ここを並列化したいという話もあります。</p>
<h3>Tier0 最適化</h3>
<p>単純な「Tier0 なら最適化なし」という実装に問題があることも分かっていて、修正が必要です。</p>
<p>例えば、ジェネリックなメソッド <code>M&lt;T&gt;</code> で、以下のように、<code>T</code> が値型かどうかを判別するハックがあったりします。</p>
<pre class="source" title="型引数が値型かどうかを判別する方法">
<code><span class="reserved">void</span> M&lt;<span class="type">T</span>&gt;()
{
    <span class="reserved">if</span> (<span class="reserved">default</span>(<span class="type">T</span>) == <span class="reserved">null</span>) <span class="type">Console</span>.WriteLine(<span class="string">&quot;T は参照型&quot;</span>);
    <span class="reserved">else</span> <span class="type">Console</span>.WriteLine(<span class="string">&quot;T は値型&quot;</span>);
}
</code></pre>
<p>この C# コードで、<code>T</code> が値型のとき、IL 上は、<code>default(T) == null</code> のところでボックス化が起きるコードになっています。
<code>default(T)</code> を一度 <code>object</code> 型にした上で null と比較するような IL が生成されます。
しかし、最適化ありでJITコンパイルすると、このボックス化はちゃんと消える(それどころかJIT時定数扱いで条件分岐自体が消える)ので、
<code>default(T) == null</code> は <code>T</code> が値型かどうかを判別する最速の手段だったりします。</p>
<p>その一方で、今、Tier0 JIT ではこの最適化が働かないそうです。
その結果、Tier0 の時にはボックス化が発生して、かえって遅くなることがわかっています。
(それで、<a href="https://github.com/dotnet/coreclr/pull/19904">せっかく入れた最適化を戻されかけたこともあったりします</a>。)
なので、<a href="https://github.com/dotnet/coreclr/issues/14474">Tier0 でも、手間のかからない範囲の最低限の最適化はかけるべき</a>だろうという話になっています。</p>
<h3>AggressiveOptimization</h3>
<p>ちなみに、NET Core 3.0 では、段階コンパイルを制御するためのオプションが追加されます。</p>
<p>今でも、<code>MethodImpl</code>属性(<code>System.Runtime.CompilerServices</code>名前空間)を使ってメソッドの最適化を制御できます。
例えばこれに、<code>MethodImplOptions.AggressiveInlining</code>オプションを指定すると、通常よりもインライン化されやすくなります。
.NET Core 3.0 では、この<code>MethodImplOptions</code>列挙型に<code>AggressiveOptimization</code>が追加されていて、
このオプションを指定すると最初から Tier1 扱いでJITコンパイルするようになるみたいです。</p>
 ]]></description>
				<pubDate>Sun, 30 Dec 2018 00:43:31 +0900</pubDate>
			</item>
			<item>
				<title>仮想テーブルの中身をのぞき見</title>
				<link>http://ufcpp.net/blog/2018/12/unsaferuntime/</link>
				<description><![CDATA[ <p>しばらくやってた <code>Unsafe</code> シリーズですが、今日は特に凶悪な奴です。</p>
<p>割かし最近なんですが、coreclr にこんなプルリクが出ていました。</p>
<ul>
<li><a href="https://github.com/dotnet/coreclr/pull/20386">Improve performance of <code>Memory&lt;T&gt;.Span</code> property getter</a></li>
</ul>
<p>これがまあ、なかなか凄いコードを含んでいます。仮想テーブルの中身を覗いて、「特定のビットが立っていたら配列」みたいなコードを書いています。</p>
<h2>該当箇所</h2>
<p>まず、<a href="https://github.com/dotnet/coreclr/blob/ef93a727984dbc5b8925a0c2d723be6580d20460/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.cs#L222">仮想テーブルのポインターを取得</a></p>
<pre class="source" title="仮想テーブルのポインターを取得">
<code><span class="reserved">private</span> <span class="reserved">static</span> <span class="type">IntPtr</span> GetObjectMethodTablePointer(<span class="reserved">object</span> obj)
{
    <span class="reserved">return</span> <span class="type">Unsafe</span>.Add(<span class="reserved">ref</span> <span class="type">Unsafe</span>.As&lt;<span class="reserved">byte</span>, <span class="type">IntPtr</span>&gt;(<span class="reserved">ref</span> <span class="type">JitHelpers</span>.GetPinningHelper(obj).m_data), -1);
}
</code></pre>
<ul>
<li>Managed なオブジェクトのアドレスを取得</li>
<li>その場所の1ワード手前に仮想テーブルへのポインターが入っているはず</li>
</ul>
<p>で、それを使って「配列かどうか」を判定。</p>
<pre class="source" title="仮想テーブルの中身を見て配列かどうかを判定">
<code><span class="reserved">internal</span> <span class="reserved">static</span> <span class="reserved">unsafe</span> <span class="reserved">bool</span> ObjectHasComponentSize(<span class="reserved">object</span> obj)
{
    <span class="reserved">return</span> *(<span class="reserved">int</span>*)GetObjectMethodTablePointer(obj) &lt; 0;
}
</code></pre>
<ul>
<li>仮想テーブルの最初の4バイトはヘッダーになっている</li>
<li>ヘッダーの最上位ビットは「クラスが可変長かどうか」のフラグになっている</li>
<li>.NET のクラスで可変長なのは配列と文字列だけ</li>
</ul>
<p>とまあ、今現在の実装としてはこれで確かに「配列、もしくは、文字列かどうか」を判定できます。</p>
<h2>もちろん実装依存</h2>
<p>当然ですが、今現在の実装としてできるからといって、将来もそうと言う保証はありません。
仕様として明言されているわけではなく、凄くきわどいコードです。</p>
<p>ギリギリ許されているのは、「coreclr 内の internal コードなので、もしランタイムに手を入れて仮想テーブルの実装が変わるようならその時に併せてここも直せばいい」という感じです。
coreclr の外で真似していいコードではないでしょう。</p>
<p>このプルリク内でも、「一旦はこれでマージしちゃっていいけど、<code>Unsafe</code>クラスを使った実装じゃなくて、ちゃんとランタイム側で判定用の intrinsic な API を提供すべき」という話の流れにはなっています。
さすがにいずれは消えると思われます。</p>
 ]]></description>
				<pubDate>Sat, 29 Dec 2018 10:38:59 +0900</pubDate>
			</item>
			<item>
				<title>Unsafe クラス(保証のある利用例)</title>
				<link>http://ufcpp.net/blog/2018/12/unsafegarantee/</link>
				<description><![CDATA[ <p>「<a href="/blog/2018/12/unsafenogarantee/">Unsafe クラス(保証外)</a>」ではわざわざ動作保証のない相当に邪悪なコードを紹介しました。</p>
<p>とはいえ、別に <code>Unsafe</code>クラスを使った瞬間に動作保証がなくなるわけではありません。
単に、開発者の裁量に任されるというだけで、正しく使えば問題は起こしません。</p>
<p>例えば、<code>Unsafe.As</code>メソッドは型チェックをせずに型を強制変換するメソッドですが、
最初から(<code>As</code>メソッドよりも前に予めチェックして)型がわかっているなら何も問題ありません。</p>
<h2>Union 型</h2>
<p>例として、「<code>A</code> または <code>B</code> のどちらか」を表す型を作ってみましょう。
単なる例にそんなに凝っても仕方がないので、今回は「<code>string</code> または <code>char[]</code>」で作ります。</p>
<h3>is 演算子実装</h3>
<p>素直に実装すると以下のようになります。</p>
<pre class="source" title="object に対して is で型判定">
<code><span class="reserved">using</span> System;
 
<span class="reserved">public</span> <span class="reserved">readonly</span> <span class="reserved">struct</span> <span class="type">StringOrCharArray</span>
{
    <span class="reserved">private</span> <span class="reserved">readonly</span> <span class="reserved">object</span> _value;

    <span class="reserved">public</span> StringOrCharArray(<span class="reserved">string</span> s) =&gt; _value = s;
    <span class="reserved">public</span> StringOrCharArray(<span class="reserved">char</span>[] array) =&gt; _value = array;

    <span class="reserved">public</span> <span class="type">ReadOnlySpan</span>&lt;<span class="reserved">char</span>&gt; Span
        =&gt; _value <span class="reserved">is</span> <span class="reserved">string</span> s ? s.AsSpan() :
        _value <span class="reserved">is</span> <span class="reserved">char</span>[] a ? a.AsSpan() :
        <span class="reserved">default</span>;
}
</code></pre>
<p>見てほしいのは<code>Span</code>プロパティの部分です。
この中で使っている<a href="/study/csharp/datatype/typeswitch/#is"><code>is</code>演算</a>は、
実際のところ、以下のような <code>as</code> + null チェックと等価です。</p>
<pre class="source" title="is は as + null チェック">
<code><span class="reserved">var</span> s = _value <span class="reserved">as</span> <span class="reserved">string</span>;
<span class="reserved">if</span> (s != <span class="reserved">null</span>) ...
</code></pre>
<p>で、<code>as</code> 演算子は IL 的には <a href="https://docs.microsoft.com/ja-jp/dotnet/api/system.reflection.emit.opcodes.isinst">isinst 命令</a>になってます。</p>
<p>isinst 命令は要は実行時型情報を調べる命令です。
実行時型情報と言っても、動的コード生成をしない(単に型を調べるだけ)ならそこまで高コストではありません。
なので、動的コード生成みたいに「静的なコードに比べて2桁遅い」みたいな事態にはなりません。</p>
<h2>型弁別用の enum 値</h2>
<p>しかし、今日は「ちょっとのコスト」も避けようという話なので、
この isinst 命令を消すことを考えます。</p>
<p><code>object</code> 型のフィールドに加えて、型弁別用の enum 値を別途持ってみることにします。
ただ、素直な実装をしてしまうと「コスト避け」の試みは失敗します。</p>
<pre class="source" title="型弁別用の enum を追加">
<code><span class="reserved">using</span> System;
 
<span class="reserved">public</span> <span class="reserved">readonly</span> <span class="reserved">struct</span> <span class="type">StringOrCharArray</span>
{
    <span class="reserved">public</span> Discriminator Type { <span class="reserved">get</span>; }
    <span class="reserved">private</span> <span class="reserved">readonly</span> <span class="reserved">object</span> _value;
 
    <span class="reserved">public</span> StringOrCharArray(<span class="reserved">string</span> s) =&gt; (Type, _value) = (Discriminator.String, s);
    <span class="reserved">public</span> StringOrCharArray(<span class="reserved">char</span>[] array) =&gt; (Type, _value) = (Discriminator.CharArray, array);
 
    <span class="reserved">public</span> <span class="type">ReadOnlySpan</span>&lt;<span class="reserved">char</span>&gt; Span
    {
        <span class="reserved">get</span>
        {
            <span class="comment">// せっかく Type を見て switch してるのに…</span>
            <span class="reserved">switch</span> (Type)
            {
                <span class="reserved">default</span>: <span class="reserved">return</span> <span class="reserved">default</span>;
                <span class="comment">// この2行のキャストが余計。</span>
                <span class="reserved">case</span> Discriminator.String: <span class="reserved">return</span> ((<span class="reserved">string</span>)_value).AsSpan();
                <span class="reserved">case</span> Discriminator.CharArray: <span class="reserved">return</span> ((<span class="reserved">char</span>[])_value).AsSpan();
            }
        }
    }
}
</code></pre>
<p>enum 値を見て switch していますが、分岐の先で結局キャストしています。
キャストの方は <a href="https://docs.microsoft.com/ja-jp/dotnet/api/system.reflection.emit.opcodes.castclass">caltclass 命令</a>になるんですが、
この命令は内部的に isinst 命令と大差ないみたいで、実行時間もほとんど同じです。</p>
<p>これがこのクラスの失敗理由で、
「せっかく事前に enum 値で型を判定してるのに、castclass 命令で改めて型チェックをしてて、単に2重の負担がかかってるだけ」
という状態になっています。
結果的に、先ほどの is 演算子実装よりもちょっとだけよりも遅くなります。</p>
<h2>Unsafe 実装</h2>
<p>ということで、<code>Unsafe</code>。
先ほどの <code>Span</code> プロパティを以下のように書き換えます。</p>
<pre class="source" title="Unsafe.As はチェックをすっ飛ばすので高速">
<code><span class="reserved">using</span> System;
<span class="reserved">using</span> System.Runtime.CompilerServices;
 
<span class="reserved">public</span> <span class="reserved">readonly</span> <span class="reserved">struct</span> <span class="type">StringOrCharArray</span>
{
    <span class="comment">// 先ほどと同じところは割愛</span>
 
    <span class="reserved">public</span> <span class="type">ReadOnlySpan</span>&lt;<span class="reserved">char</span>&gt; Span
    {
        <span class="reserved">get</span>
        {
            <span class="comment">// せっかく Type を見て switch してるんだから</span>
            <span class="reserved">switch</span> (<span class="type">Type</span>)
            {
                <span class="reserved">default</span>: <span class="reserved">return</span> <span class="reserved">default</span>;
                <span class="comment">// キャストを Unsafe.As で置き換えれば高速。</span>
                <span class="reserved">case</span> Discriminator.String: <span class="reserved">return</span> <span class="type">Unsafe</span>.As&lt;<span class="reserved">object</span>, <span class="reserved">string</span>&gt;(<span class="reserved">ref</span> <span class="type">Unsafe</span>.AsRef(_value)).AsSpan();
                <span class="reserved">case</span> Discriminator.CharArray: <span class="reserved">return</span> <span class="type">Unsafe</span>.As&lt;<span class="reserved">object</span>, <span class="reserved">char</span>[]&gt;(<span class="reserved">ref</span> <span class="type">Unsafe</span>.AsRef(_value)).AsSpan();
            }
        }
    }
}
</code></pre>
<p><code>Unsafe.As</code>メソッドは型チェックをすっとばしてるので高速です。
名前通り unsafe ではありますが、今回の場合、事前に enum 値で型を調べているので問題は起こしません。</p>
<p>この実装であれば、当初目的である isinst 命令を避けることができます。
前述の通り桁違いな速度差が出るわけではないんですが、
元の is 演算子実装より数割程度速くなります。</p>
<p>ベンチマーク: <a href="https://github.com/ufcpp/UfcppSample/tree/master/Demo/2018/PerformanceTips/DiscriminatedUnion">DiscriminatedUnion</a></p>
<h2>フィールドが増えてる</h2>
<p>今回の例では、型チェックの負担は減りますが、
代わりにフィールドが1つ増えています。
構造体サイズも倍になってしまい、コピーのコストが発生してしまいます。
(<code>Span</code>プロパティのアクセスよりも、変数のコピーの頻度が圧倒的に多い場合、むしろ遅くなる可能性があります。)</p>
<p>ということで使いどころには注意が必要です。
ただ、実装によってはこのコストは避けれます。
例えば、標準ライブラリ中の<code>Memory&lt;T&gt;</code>構造体(<code>System</code>名前空間)は以下のような構造になっています。</p>
<pre class="source" title="Memory&lt;T&gt; 構造体の中身">
<code><span class="reserved">public</span> <span class="reserved">readonly</span> <span class="reserved">struct</span> <span class="type">Memory</span>&lt;<span class="type">T</span>&gt;
{
    <span class="reserved">private</span> <span class="reserved">readonly</span> <span class="reserved">object</span> _object;
    <span class="reserved">private</span> <span class="reserved">readonly</span> <span class="reserved">int</span> _index;
    <span class="reserved">private</span> <span class="reserved">readonly</span> <span class="reserved">int</span> _length;
}
</code></pre>
<p><code>Memory</code>構造体は、以下のような前提で、フィールドを増やさずに isinst 命令を避けたりしています。</p>
<ul>
<li><code>_index</code>(配列の開始インデックス)も<code>_length</code>(そこから何要素抜き出すか)も、負にはならない</li>
<li>負にならないのなら、最上位ビットが 1 になることはあり得ない</li>
<li>その最上位ビットを、型弁別用に使う</li>
</ul>
 ]]></description>
				<pubDate>Fri, 28 Dec 2018 09:40:24 +0900</pubDate>
			</item>
			<item>
				<title>Unsafe クラス(保証外)</title>
				<link>http://ufcpp.net/blog/2018/12/unsafenogarantee/</link>
				<description><![CDATA[ <p>今日は <code>Unsafe</code> クラスがらみの話で、
特にきわどい(動作保証外)やつ。
.NET Core 2.0 ～ 2.1 くらいでは動くことを確認していますが、
仕様として保証がなく、古いランタイムや将来、また、Mono などの他の .NET 環境で動く保証がないものです。</p>
<h2>メモリレイアウトが同じもの</h2>
<p>まず、元々 unsafe コードを使ってできるし、
<code>Unsafe</code>クラスを使っても動作保証があるものから説明。</p>
<p>ポインターを使ったり、<code>Unsafe.As</code>メソッドを使うと、
全然違う型・C# では本来変換できない型同士の間で強制変換ができます。
強制しているだけなので、それがちゃんと意味あるコードになるかどうかは unsafe、
すなわち、書いている人の責任の範疇になります。</p>
<p>どういう場合なら大丈夫かというと、要するに、
メモリ上でのフィールドなどのレイアウトが同じ場合です。
例えば、以下のような、サイズが同じで参照型を含まない構造体同士は強制変換しても大丈夫です。</p>
<pre class="source" title="レイアウトがわかっている構造体に対して Unsafe">
<code><span class="reserved">using</span> System;
<span class="reserved">using</span> System.Runtime.CompilerServices;
<span class="reserved">using</span> System.Runtime.InteropServices;
 
<span class="comment">// 構造体サイズが4バイトになるようにフィールドを並べる</span>
<span class="comment">// この場合は別に StructLayout 属性がなくても4バイトになるものの、</span>
<span class="comment">// サイズをピッタリ調整したい場合には明示した方がいいかも。</span>
[<span class="type">StructLayout</span>(<span class="type">LayoutKind</span>.Sequential, Pack = 1)]
<span class="reserved">struct</span> <span class="type">A</span>
{
    <span class="reserved">public</span> <span class="reserved">byte</span> X;
    <span class="reserved">public</span> <span class="reserved">byte</span> Y;
    <span class="reserved">public</span> <span class="reserved">short</span> Z;
}
 
<span class="comment">// int 1個なので当然4バイト。</span>
<span class="reserved">struct</span> <span class="type">B</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> X;
}
 
<span class="reserved">public</span> <span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> Main()
    {
        <span class="comment">// サイズが同じで参照型を含まない構造体間での強制変換は、</span>
        <span class="comment">// 普通にポインターを使ってできる操作なので</span>
        <span class="comment">// unsafe ではあってもまだ動作保証はある。</span>
        <span class="type">B</span> b = <span class="reserved">new</span> <span class="type">B</span> { X = 0x01020304 };
        <span class="type">A</span> a = <span class="type">Unsafe</span>.As&lt;<span class="type">B</span>, <span class="type">A</span>&gt;(<span class="reserved">ref</span> b);
 
        <span class="comment">// 4, 3, 102</span>
        <span class="type">Console</span>.WriteLine(<span class="string">$&quot;</span>{a.X}<span class="string">, </span>{a.Y}<span class="string">, </span>{a.Z:<span class="string">x</span>}<span class="string">&quot;</span>);
    }
}
</code></pre>
<h2>保証外な利用方法</h2>
<p><code>Unsafe.As</code>メソッドを使うと、
こういった強制型変換を参照型に対しても行えます。</p>
<p>ただ、これは動作保証がないようです。
少なくとも .NET Core 2.1 では動いているんですが、
将来にわたってもそのまま動くかと言われると何も保証されていません。</p>
<h3>共変クラス</h3>
<p>C# の<a href="/study/csharp/sp4_variance.html">変性</a>はインターフェイスとデリゲートに対してしか働かないわけですが、それを強制的にクラスに対しても適用できたりします。</p>
<pre class="source" title="共変クラス(動作保証なし)">
<code><span class="comment">// string → object の代入が合法なんだったら…</span>
<span class="reserved">string</span> s = <span class="string">&quot;abc&quot;</span>;
<span class="reserved">object</span> o = s;
 
<span class="comment">// Task&lt;string&gt; → Task&lt;object&gt; も OK にしてほしい</span>
<span class="type">Task</span>&lt;<span class="reserved">string</span>&gt; ts = <span class="type">Task</span>.FromResult(<span class="string">&quot;abc&quot;</span>);
 
<span class="comment">// 実際は無理</span>
<span class="comment">// Task&lt;object&gt; to = ts;</span>
 
<span class="comment">// が、Unsafe.As ならできてしまう。</span>
<span class="type">Task</span>&lt;<span class="reserved">object</span>&gt; to = <span class="type">Unsafe</span>.As&lt;<span class="type">Task</span>&lt;<span class="reserved">string</span>&gt;, <span class="type">Task</span>&lt;<span class="reserved">object</span>&gt;&gt;(<span class="reserved">ref</span> ts);
 
<span class="comment">// await でちゃんと &quot;abc&quot; が取れる</span>
<span class="reserved">var</span> result = <span class="reserved">await</span> to;
<span class="type">Console</span>.WriteLine(result);
</code></pre>
<p>ただ、これは <code>Task&lt;TResult&gt;</code>クラス(<code>System.Threading.Tasks</code>名前空間)の<code>TResult</code>が戻り値にしか使われていないから大丈夫なのであって、
例えば以下のように、読み書き両方できるとまずいです。</p>
<pre class="source" title="ほんとに挙動が壊れるダメな Unsafe">
<code><span class="reserved">using</span> System;
<span class="reserved">using</span> System.Runtime.CompilerServices;
 
<span class="reserved">class</span> <span class="type">Box</span>&lt;<span class="type">T</span>&gt; { <span class="reserved">public</span> <span class="type">T</span> Value; }
 
<span class="reserved">public</span> <span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> Main()
    {
        <span class="comment">// string → object の代入が合法なんだったら…</span>
        <span class="type">Box</span>&lt;<span class="reserved">string</span>&gt; s = <span class="reserved">new</span> <span class="type">Box</span>&lt;<span class="reserved">string</span>&gt; { Value = <span class="string">&quot;abc&quot;</span> };
        <span class="type">Box</span>&lt;<span class="reserved">object</span>&gt; o = <span class="type">Unsafe</span>.As&lt;<span class="type">Box</span>&lt;<span class="reserved">string</span>&gt;, <span class="type">Box</span>&lt;<span class="reserved">object</span>&gt;&gt;(<span class="reserved">ref</span> s);
 
        <span class="comment">// 読み出しはまだ大丈夫。&quot;abc&quot; が表示される。</span>
        <span class="type">Console</span>.WriteLine(o.Value);
 
        <span class="comment">// 書き込みはアウト。</span>
        o.Value = 10;
        <span class="comment">// ダメなことをやっちゃったあとなので、何か動作がおかしい。</span>
        <span class="comment">// 最悪の場合死に至るのでダメ、絶対！</span>
        <span class="type">Console</span>.WriteLine(o.Value);
    }
}
</code></pre>
<p>また、<code>string</code> → <code>object</code> が大丈夫だから <code>Task&lt;string&gt;</code> → <code>Task&lt;object&gt;</code> も大丈夫だったのであって、互換性がない型同士での <code>Task&lt;T&gt;</code> 間の変換はもちろんダメです。</p>
<pre class="source" title="ヤバい(ヤバい)">
<code><span class="reserved">using</span> System.Runtime.CompilerServices;
<span class="reserved">using</span> System.Threading.Tasks;
 
<span class="comment">// 無関係のクラス</span>
<span class="reserved">class</span> <span class="type">C1</span> { }
<span class="reserved">class</span> <span class="type">C2</span> { }
 
<span class="comment">// A, B は同じ4バイト</span>
<span class="comment">// C は1バイト</span>
<span class="reserved">struct</span> <span class="type">A</span> { <span class="reserved">public</span> <span class="reserved">int</span> X; }
<span class="reserved">struct</span> <span class="type">B</span> { <span class="reserved">public</span> <span class="reserved">short</span> X, Y; }
<span class="reserved">struct</span> <span class="type">C</span> { <span class="reserved">public</span> <span class="reserved">byte</span> X; }
 
<span class="reserved">public</span> <span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> Main()
    {
        <span class="comment">// ヤバい(無関係のクラス)</span>
        <span class="type">Task</span>&lt;<span class="type">C1</span>&gt; c1 = <span class="type">Task</span>.FromResult&lt;<span class="type">C1</span>&gt;(<span class="reserved">null</span>);
        <span class="type">Task</span>&lt;<span class="type">C2</span>&gt; c2 = <span class="type">Unsafe</span>.As&lt;<span class="type">Task</span>&lt;<span class="type">C1</span>&gt;, <span class="type">Task</span>&lt;<span class="type">C2</span>&gt;&gt;(<span class="reserved">ref</span> c1);
 
        <span class="comment">// 保証外だけどギリ動く(サイズが同じ)</span>
        <span class="type">Task</span>&lt;<span class="type">A</span>&gt; a = <span class="type">Task</span>.FromResult(<span class="reserved">new</span> <span class="type">A</span>());
        <span class="type">Task</span>&lt;<span class="type">B</span>&gt; b = <span class="type">Unsafe</span>.As&lt;<span class="type">Task</span>&lt;<span class="type">A</span>&gt;, <span class="type">Task</span>&lt;<span class="type">B</span>&gt;&gt;(<span class="reserved">ref</span> a);
 
        <span class="comment">// ヤバい(サイズが違う)</span>
        <span class="type">Task</span>&lt;<span class="type">C</span>&gt; c = <span class="type">Unsafe</span>.As&lt;<span class="type">Task</span>&lt;<span class="type">A</span>&gt;, <span class="type">Task</span>&lt;<span class="type">C</span>&gt;&gt;(<span class="reserved">ref</span> a);
    }
}
</code></pre>
<h3>シグネチャが同じデリゲート</h3>
<p>デリゲートは、引数・戻り値の型が完全に一致していても、
別個に定義したものは別の型扱いを受けます。</p>
<p>そして、引数・戻り値の型が完全に一致しているデリゲート型は山ほどあります。
例えば以下のような。</p>
<ul>
<li><a href="https://source.dot.net/#System.Runtime/System.Runtime.cs,e847f170291a7c6f,references"><code>IValueTaskSource</code></a> … <code>Action&lt;object&gt;</code> を使用。<code>object</code>引数、<code>void</code>戻り値。</li>
<li><a href="https://source.dot.net/#System.Private.CoreLib/src/System/Threading/Timer.cs,814"><code>Timer</code></a> … <code>TimerCallback</code> を使用。<code>object</code>引数、<code>void</code>戻り値。</li>
<li><a href="https://source.dot.net/#System.Private.CoreLib/src/System/Threading/SynchronizationContext.cs,98"><code>SynchronizationContext</code></a> … <code>SendOrPostCallback</code> を使用。<code>object</code>引数、<code>void</code>戻り値。</li>
</ul>
<p>そして、これらのデリゲート間の変換では、以下のように <code>new</code> が挟まってしまって、無駄にメモリを食います。</p>
<pre class="source" title="デリゲートの残念さ">
<code><span class="reserved">using</span> System;
<span class="reserved">using</span> System.Threading;
<span class="reserved">using</span> System.Threading.Tasks.Sources;
 
<span class="reserved">class</span> <span class="type">MyValueTaskSource</span> : <span class="type">IValueTaskSource</span>
{
    <span class="reserved">private</span> <span class="type">SynchronizationContext</span> _context;
    <span class="reserved">public</span> <span class="reserved">void</span> GetResult(<span class="reserved">short</span> token) { }
    <span class="reserved">public</span> <span class="type">ValueTaskSourceStatus</span> GetStatus(<span class="reserved">short</span> token) =&gt; <span class="type">ValueTaskSourceStatus</span>.Succeeded;
    <span class="reserved">public</span> <span class="reserved">void</span> OnCompleted(<span class="type">Action</span>&lt;<span class="reserved">object</span>&gt; continuation, <span class="reserved">object</span> state, <span class="reserved">short</span> token, <span class="type">ValueTaskSourceOnCompletedFlags</span> flags)
    {
        <span class="comment">// こういう書き方は無理。</span>
        <span class="comment">// _context.Post(continuation, state);</span>
 
        <span class="comment">// こうなる。</span>
        _context.Post(continuation.Invoke, state);
 
        <span class="comment">// ↑これは意味的には↓と同じ。1段 new が挟まってて、ヒープも確保される。</span>
        <span class="comment">// _context.Post(new SendOrPostCallback(continuation.Invoke), state);</span>
    }
}
</code></pre>
<p>でも、<code>Unsafe.As</code>メソッドを使えば無駄な <code>new</code> なしで強制変換できます。</p>
<pre class="source" title="Unsafe で無理やり変換(動作保証なし)">
<code><span class="comment">// でも、これで行けたりする。</span>
_context.Post(Unsafe.As&lt;<span class="type">Action</span>&lt;<span class="reserved">object</span>&gt;, <span class="type">SendOrPostCallback</span>&gt;(<span class="reserved">ref</span> continuation), state);
</code></pre>
<p>引数・戻り値の型が一致している限りには、
少なくとも .NET Core 2.1 とかでは動きます
(再三いうけども動作保証があるわけじゃない)。</p>
<pre class="source" title="Unsafe で無理やり変換(動作保証なし)">
<code><span class="reserved">using</span> System;
<span class="reserved">using</span> System.Runtime.CompilerServices;
<span class="reserved">using</span> System.Threading;
 
<span class="reserved">public</span> <span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> Main()
    {
        <span class="type">Action</span>&lt;<span class="reserved">object</span>&gt; action = x =&gt; <span class="type">Console</span>.WriteLine(x);
        <span class="type">SendOrPostCallback</span> callback = <span class="type">Unsafe</span>.As&lt;<span class="type">Action</span>&lt;<span class="reserved">object</span>&gt;, <span class="type">SendOrPostCallback</span>&gt;(<span class="reserved">ref</span> action);
 
        callback(<span class="string">&quot;abc&quot;</span>); <span class="comment">// ちゃんと Console.WriteLine(&quot;abc&quot;) が呼ばれる</span>
    }
}
</code></pre>
<h2>静的な型と動的な型</h2>
<p>ちなみに、<code>Unsafe.As</code>メソッドでの共生型変換を、互いに無関係なクラスでやってしまうと結構変な動作になります。
以下のように、全然無関係なメソッドが呼ばれてしまうことがあり得ます。
(<a href="/study/csharp/oo_vftable.html">仮想呼び出し</a>が狂います。本来参照すべきものと違う仮想テーブルをひいちゃうので当然。)</p>
<pre class="source" title="Unsafe.As の強制変換をすると仮想呼び出しが狂う">
<code><span class="reserved">using</span> System;
<span class="reserved">using</span> System.Runtime.CompilerServices;
 
<span class="reserved">class</span> <span class="type">A</span>
{
    <span class="reserved">public</span> <span class="reserved">void</span> M() =&gt; <span class="type">Console</span>.WriteLine(<span class="string">&quot;A non-virtual M&quot;</span>);
    <span class="reserved">public</span> <span class="reserved">virtual</span> <span class="reserved">void</span> X() =&gt; <span class="type">Console</span>.WriteLine(<span class="string">&quot;A virtual X&quot;</span>);
}
 
<span class="reserved">class</span> <span class="type">B</span>
{
    <span class="reserved">public</span> <span class="reserved">void</span> M() =&gt; <span class="type">Console</span>.WriteLine(<span class="string">&quot;B non-virtual M&quot;</span>);
 
    <span class="comment">// 仮想テーブル的に、A.X と同じ場所にポインターが入る</span>
    <span class="reserved">public</span> <span class="reserved">virtual</span> <span class="reserved">void</span> Y() =&gt; <span class="type">Console</span>.WriteLine(<span class="string">&quot;B virtual Y&quot;</span>);
}
 
<span class="reserved">public</span> <span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> Main()
    {
        <span class="type">A</span> a = <span class="reserved">new</span> <span class="type">A</span>();
        <span class="type">B</span> b = <span class="type">Unsafe</span>.As&lt;<span class="type">A</span>, <span class="type">B</span>&gt;(<span class="reserved">ref</span> a);
 
        <span class="comment">// non-virtual なメソッドは静的な型(B)に基づいて呼ばれる。</span>
        <span class="comment">// なので、これは普通に B.M が呼ばれる</span>
        b.M(); <span class="comment">// B non-virtual M</span>
 
        <span class="comment">// virtual なメソッドは動的な型(A)に基づいて呼ばれる。</span>
        <span class="comment">// 型の強制変換のせいで変な挙動に。</span>
        <span class="comment">// 仮想テーブル上、B.Y と同じ位置に A.X のポインターがあるので、</span>
        <span class="comment">// B.Y を呼んだつもりが A.X が呼ばれる。</span>
        b.Y(); <span class="comment">// A virtual X</span>
    }
}
</code></pre>
<p>この例ではたまたまクラッシュせずに動作しますが
(というか、ならないように気を使って書いています)、
無神経にやるとまずクラッシュします。</p>
 ]]></description>
				<pubDate>Thu, 27 Dec 2018 09:53:16 +0900</pubDate>
			</item>
			<item>
				<title>将来のメモリ管理</title>
				<link>http://ufcpp.net/blog/2018/12/futurememorymanagement/</link>
				<description><![CDATA[ <p>今日はまたちょっと将来の話。
リリース時期・本当にリリースされるか未定の機能で、メモリ管理がらみの話をまとめて。</p>
<h2>ヒープ確保の負担を減らしたい</h2>
<p>メモリの管理方法には<a href="/study/computer/MemoryManagement.html#stack">スタック</a>と<a href="/study/computer/MemoryManagement.html#heap">ヒープ</a>があって、
一般的にはスタックの方が高速です。
スタックの方が制限がきついので、遅くてもしょうがなくヒープを使う場面がでてきます。</p>
<p>ヒープ管理は結構大きな負担なので、これを減らせば結構なパフォーマンス改善になります。
いくつか方向性があって、以下のような最適化が考えられます。</p>
<ul>
<li>
ヒープ管理自体を賢くする
<ul>
<li>→ <a href="/study/computer/MemoryManagement.html#garbage-collection">ガベージ コレクション</a></li>
<li>→ Arena Allocation (後述)</li>
</ul>
</li>
<li>
ヒープを避ける
<ul>
<li>
手作業でヒープを避ける
<ul>
<li>C# が構造体とかの「<a href="/study/csharp/oo_reference.html">値型</a>」を持っているのはこのため</li>
<li>→ 先日書いた「<a href="Spanify.md"><code>Span&lt;T&gt;</code> 利用による最適化</a>」とかもまさにこれ</li>
</ul>
</li>
<li>
自動でヒープを避ける
<ul>
<li>→ Object Stack Allocation (後述)</li>
</ul>
</li>
</ul>
</li>
</ul>
<h2>ガベージ コレクション</h2>
<p>一般的に、こまごまと個別に処理をするよりも、ある程度まとまった単位でごっそり処理する方が効率がよかったりします。
<a href="/study/computer/MemoryManagement.html#garbage-collection">ガベージ コレクション</a>というメモリ管理手法はまさにそんな感じで、
「ごみはしばらくほったらかし」→「定期的にごっそりまとめてゴミ集め」とかやっていて、
これがスループット的には結構有利だったりします。
「まとめてゴミ集め」の瞬間に負荷が集中するという問題はあるものの、
トータルでみると低負荷なメモリ管理手法です。</p>
<p>メモリ管理が手動(<code>alloc</code> したものは開発者が責任をもって <code>free</code> しないといけない)な言語でも、内部的にガベージ コレクション的な挙動をしているものがあるくらいです。
<a href="https://github.com/gperftools/gperftools">gperftools</a>の tcmalloc なんかはそうみたいです。
小さいオブジェクトの場合だけですが、<code>free</code>した瞬間に即座にその領域を解放するのではなくて、
メモリが足りなくなってきたときにまとめて解放処理をします。</p>
<p>ガベージ コレクション以外のヒープ管理手法は、
たびたび提案されては、
そのたび「<a href="/study/computer/MemoryManagement.html#generational">世代別 GC</a>に性能で勝てなかった」的な結論に達したりします。
.NET でも、<a href="https://www.infoq.com/jp/news/2017/10/snowflake">Project Snowflake</a>という研究プロジェクトがありました
(<a href="https://www.rust-lang.org/">Rust</a>みたいに、メモリの所有権をはっきりさせればヒープ管理が速くなるんじゃないかという原理に基づく提案)。
結構賢そうなことをやっているんですが、それでも結論は「<a href="https://github.com/dotnet/coreclr/issues/20074#issuecomment-423199088">利益がコストに見合わない</a>」でした。</p>
<h2>Arena Allocation</h2>
<p>Project Snowflake に代わって1つ有望視されているのは、
Arena Allocation という手法です。</p>
<p><a href="https://developers.google.com/protocol-buffers/docs/reference/arenas">Protocol Buffers の C++ 版</a>がこの手法によるメモリ管理を提供しているんですが、それを .NET にも導入できないかという調査をしているみたいです。
まだあんまりドキュメントがなく、<a href="https://qconsf.com/">QConSF</a>の登壇で軽く紹介された程度ですが。</p>
<ul>
<li><a href="https://qconsf.com/sf2018/presentation/clrcoreclr-how-we-got-here-where-were-going">CLR/CoreCLR: How We Got Here &amp; Where We're Going</a> (<a href="https://qconsf.com/system/files/presentation-slides/coreclr_today_tomorrow.pptx">ppt</a>)</li>
</ul>
<p>これも、「ある程度まとまった単位でごっそり処理する方が高効率」という原理に則ったものです。
以下のように、「ごっそり消す」タイミングを明示するような方式。
メモリ放棄のまとまった単位を指して arena (舞台、競技場、界)と呼んでいます。</p>
<pre class="source" title="Arena メモリ管理">
<code><span class="type">Arena</span> arena = <span class="reserved">new</span> <span class="type">Arena</span>();
<span class="reserved">using</span> (arena.Activate())
{
    <span class="comment">// この内側で new したものは「arena」内に確保される</span>
}
<span class="comment">// arena 内のオブジェクトは arena の Dispose 時にまとめて解放</span>
arena.Dispose();
</code></pre>
<p>この方式はトランザクションのスコープがはっきりしているものに対して有効です。
Protocol Buffers が採用していることからわかるように、シリアライズ・デシリアライズが好例です。
シリアライズの途中でしか使わない一時的なバッファーを Arena 中に確保して、
シリアライズ完了時にまとめて解放すれば効率よくゴミを片付けられます。</p>
<h2>Object Stack Allocation</h2>
<p>クラスのインスタンスは基本的にはヒープ上に確保するものなんですが、
「メソッド内で完結している」(引数にも渡さないし、戻り値にも返さない)という状況に限って、
スタック上に領域確保しても問題なく動いたりします。</p>
<p>そこで、JITコンパイラーが「メソッド内で完結している」かどうかを判定して、
完結していればクラスのインスタンスであってもスタック上に確保する最適化手法(Object Stack Allocation)があります。
「メソッド内から逃げ出していないかを解析する」という意味で、Escape Analysis と呼ばれたりもします。</p>
<p>Java SE では Java SE 6 の頃から Escape Analysis を実装しています。
Go なんかは最初から Escape Analysis ありきで作られています。
(要するに、結構昔からある最適化手法。)
それがこの度、.NET にも入りそうです。</p>
<ul>
<li><a href="https://github.com/dotnet/coreclr/pull/20814">Initial implementation of object stack allocation #20814</a></li>
</ul>
<p>Java と比べてずいぶん採用が遅いですが、
要は、C# は値型を持っているのでそもそも手作業でヒープを避ける手段があるからです。
挙句、「<a href="/blog/2018/12/spanify/"><code>Span&lt;T&gt;</code> 利用による最適化</a>」で説明したような手動最適化がの方が断然効果的なので、そっちの方が優先されています。
(Escape Analysis は「メソッド内から逃げ出していない」という条件が思いのほか厳しいので、適用できる割合はそんなに高くない。)</p>
<p>「コンパイラーとかランタイムが頑張るよりも手作業の方がまだまだ高効率」という話なので、
あんまり夢はない感じ…
(<code>Span&lt;T&gt;</code>も、「<a href="/study/computer/MemoryManagement.html#garbage-collection">ガベコレ</a>で追えるものを増やす」という作業は必要だったので、
ランタイムが何もしていないわけではないんですが。)</p>
 ]]></description>
				<pubDate>Wed, 26 Dec 2018 09:39:07 +0900</pubDate>
			</item>
			<item>
				<title>Span&lt;T&gt; 利用による最適化</title>
				<link>http://ufcpp.net/blog/2018/12/spanify/</link>
				<description><![CDATA[ <p>このブログではたびたび「.NET Core 2.1 上で動かすだけで、アプリ側には何も手を加えなくても 2.0 の頃より1・2割高速になる」みたいな話をしています。</p>
<p>今月に入ってからは、<a href="/blog/2018/12/devirtualization/">Devirtualization</a>みたいなJIT時の最適化手法や、
逆にもっと<a href="/blog/2018/12/arrayindex/">小手先の細かな最適化</a>の話も書いてきました。
.NET Core 2.1 ではこういういろいろな最適化が入っているんですが、
その中でも一番パフォーマンス改善に効いていそうなのが<a href="/study/csharp/resource/span/"><code>Span&lt;T&gt;</code>構造体</a>の導入です。</p>
<p><code>Span&lt;T&gt;</code>構造体自体の説明は何度かしていますが、
<code>Span&lt;T&gt;</code>を使ってどういう修正をしているかについてはあんまり書いていないので、
今日は実例をいくつか挙げていこうかと。</p>
<h2>ヒープ使用量の削減</h2>
<p><code>Span&lt;T&gt;</code> を使うと速くなる理由は単純で、
ヒープの使用量を減らせるからです。</p>
<ul>
<li><code>string.Substring</code> などで新しい文字列を作らなくて済む</li>
<li><code>stackallock</code> で、一時バッファーにヒープを使わなくて済む</li>
<li>ネイティブ メモリを直接読めるようになったことで、マネージ配列にコピーしなくて済む</li>
</ul>
<p>いずれも、unsafe コードでポインターを使えばこれまでも十分に実現できたものです。
しかし、安全性・生産性を犠牲にしたコードは書くのも使うのも神経を使うので大規模には導入しにくですし、
<a href="/blog/2018/12/unsafe/">ガベコレ都合</a>の制限もあって、
<code>Span&lt;T&gt;</code> なしでは難しい最適化です。</p>
<p><code>Span&lt;T&gt;</code> もいろいろと制限の掛かった特殊な型(<a href="/study/csharp/resource/refstruct/">ref struct</a>)ですが、それでもポインターよりは適用可能な範囲が広いです。</p>
<h2>Substring</h2>
<p>.NET の <code>string.Substring</code> は、新しい <code>string</code> 型インスタンス(もちろんヒープを使う)を作ってそれを戻り値に返します。</p>
<p><a href="https://github.com/ufcpp/UfcppSample/blob/master/Demo/2018/SpanPerformance/SubstringBenchmark/AbstractString.cs">下手に仮想呼び出しが増えるよりは、無駄にヒープを使っちゃう方が高速</a>だからそういう作りなんですが、
<code>Span&lt;char&gt;</code> があればヒープを使わず似たようなことができます。</p>
<p>ということで、<code>Substring</code>を<code>AsSpan</code>にちまちま変更していくようなプルリクエストが。</p>
<ul>
<li><a href="https://github.com/dotnet/corefx/pull/29402">Avoid substring allocations in WebUtility.HtmlDecode #29402</a></li>
<li><a href="https://github.com/dotnet/coreclr/pull/17916">Replace easy Substrings with AsSpan/Slices #17916</a></li>
</ul>
<p><code>Substring</code> に限らず文字列操作がらみはかなり<code>Span&lt;T&gt;</code>の恩恵を受けていて、
倍以上速くなったメソッド何かもあるみたいです。</p>
<h2>stackalloc</h2>
<p>極々短い範囲で、小さいデータを持っておくだけの一時バッファーを必要とすることは結構あります。
そんな時、これまでだと配列(ヒープを使う)を使っていたんですが、
<code>Span&lt;T&gt;</code> があれば <a href="/study/csharp/resource/span/#safe-stackalloc"><code>stackalloc</code>が安全になる</a>ので、
ヒープ利用を避けることができます。</p>
<p>以下の修正では、固定長で2文字の<code>char</code>のために<code>new char[2]</code>していたものを<code>stackalloc</code>に置き換えています。</p>
<ul>
<li><a href="https://github.com/dotnet/corefx/pull/33641">Remove char[] allocation in CheckIriUnicodeRange #33641</a></li>
</ul>
<pre class="source" title="配列を stackalloc に置き換え">
<code><span class="comment">//before</span>
<span class="reserved">char</span>[] chars = <span class="reserved">new</span> <span class="reserved">char</span>[2] { highSurr, lowSurr };
 
<span class="comment">//after</span>
<span class="type">ReadOnlySpan</span>&lt;<span class="reserved">char</span>&gt; chars = <span class="reserved">stackalloc</span> <span class="reserved">char</span>[2] { highSurr, lowSurr };
</code></pre>
<p>ただし、.NET の実装では、メモリのスタック領域は固定長で 1MB くらい(確か)なので、
あんまり大きなデータをスタックに置こうとすると簡単に stack overflow を起こしたりします。
先ほどのような固定長で短いデータはいいんですが、可変長の場合にはひと工夫必要です。</p>
<p>具体的には、要するに「一定サイズ以下の時にだけ<code>stackalloc</code>を使う」という分岐を挟むだけなんですが。
以下のプルリクエストなんかはわかりやすいです。</p>
<ul>
<li><a href="https://github.com/dotnet/corefx/pull/31044">Add datetime read span path for netcore #31044</a></li>
<li><a href="https://github.com/dotnet/corefx/pull/25353">Improve performance of BigInteger.ToString(&quot;x&quot;) #25353</a></li>
</ul>
<p>以下のような条件演算子は結構頻出です。</p>
<pre class="source" title="データが短い時だけ stackalloc">
<code><span class="type">Span</span>&lt;<span class="reserved">byte</span>&gt; datetimeBuffer = ((<span class="reserved">uint</span>)length &lt;= 16) ? <span class="reserved">stackalloc</span> <span class="reserved">byte</span>[16] : <span class="reserved">new</span> <span class="reserved">byte</span>[length];
</code></pre>
<p>ちなみに、以下のような型もあります(今のところ internal ですが)。
<a href="https://source.dot.net/#System.Private.CoreLib/shared/System/Text/StringBuilder.cs,adf60ee46ebd299f"><code>StringBuilder</code></a>相当の処理を、
初期バッファーを<code>stackalloc</code>、その後容量を増やすときには<a href="https://source.dot.net/#System.Private.CoreLib/shared/System/Buffers/ArrayPool.cs,87992df74cbf00ad"><code>ArrayPool</code></a>を使う実装。
これも、「一定サイズ以下の時にだけ<code>stackalloc</code>を使う」最適化の一種です。</p>
<ul>
<li><a href="https://github.com/dotnet/corefx/blob/df442de5b68264d7d129f3a11a265f88edef3fb0/src/Common/src/CoreLib/System/Text/ValueStringBuilder.cs">ValueStringBuilder</a></li>
</ul>
<h2>ネイティブ メモリを直接</h2>
<p><code>Span&lt;T&gt;</code> を使うと、は配列でも、<code>stackalloc</code> で確保したスタック領域でも、
ネイティブ メモリでも共通処理が書けます。
なので、<a href="/study/csharp/sp_pinvoke.html">ネイティブ相互運用</a>時に、
C# 側で一時配列を確保してネイティブ コードにポインターを渡す以外に、
ネイティブ側からポインターを返してもらってそれを C# 側で<code>Span&lt;T&gt;</code> を介して処理するということもできます。</p>
<p>これも、一時バッファーの確保が不要になるのでパフォーマンス改善につながったりします。</p>
<ul>
<li><a href="https://github.com/dotnet/corefx/commit/e118304d264163f03e79965e4f2ab1d5c1a43961#diff-f302191909b0568b3dca0f6f6b2f7de1R62">Use FORMAT_MESSAGE_ALLOCATE_BUFFER with FormatMessage</a></li>
</ul>
<p>最近だと、<a href="https://github.com/dotnet/machinelearning">ML.NET</a>内で、
<a href="https://github.com/dotnet/machinelearning/blob/e2e1aa8a2b43aa0b5ea5d8b3851b6a0d175f7916/src/Microsoft.ML.TensorFlow/TensorflowTransform.cs">TensorFlorとの相互運用</a>でもネイティブ メモリの読み書きに <code>Span&lt;T&gt;</code> を使っていたりします。</p>
 ]]></description>
				<pubDate>Tue, 25 Dec 2018 09:27:42 +0900</pubDate>
			</item>
			<item>
				<title>書記素分割/Unicode カテゴリー判定</title>
				<link>http://ufcpp.net/blog/2018/12/unicodecategory/</link>
				<description><![CDATA[ <p>なんか、昔作った<a href="https://github.com/ufcpp/GraphemeSplitter">GraphemeSplitter</a>が<a href="https://qiita.com/yumetodo/items/54e1a8230dbf513ea85b">C++方面のUnicodeがらみのブログ</a>から参照されてたので、ちょっと補足。</p>
<h2>UNICODE TEXT SEGMENTATION</h2>
<p>「書記素って何？」って話は詳しくは<a href="https://www.buildinsider.net/language/csharpunicode/01">昔書いた記事</a>でも見てもらうとして。
とりあえず、「人間が見て1文字と思うようなもの」を指して書記素(grapheme)といいます。複数の Unicode コードポイントが結合しまくるので、可変長。</p>
<p>いつも例に出すのが家族絵文字(<a href="http://ufcppfree.azurewebsites.net/Grapheme?s=%F0%9F%91%A9%F0%9F%8F%BB%E2%80%8D%F0%9F%91%A6%F0%9F%8F%BC%F0%9F%91%A8%F0%9F%8F%BD%E2%80%8D%F0%9F%91%A6%F0%9F%8F%BE%E2%80%8D%F0%9F%91%A6%F0%9F%8F%BF%F0%9F%91%A9%F0%9F%8F%BC%E2%80%8D%F0%9F%91%A8%F0%9F%8F%BD%E2%80%8D%F0%9F%91%A6%F0%9F%8F%BC%E2%80%8D%F0%9F%91%A7%F0%9F%8F%BD%F0%9F%91%A9%F0%9F%8F%BB%E2%80%8D%F0%9F%91%A9%F0%9F%8F%BF%E2%80%8D%F0%9F%91%A7%F0%9F%8F%BC%E2%80%8D%F0%9F%91%A7%F0%9F%8F%BE">👩🏻‍👦🏼👨🏽‍👦🏾‍👦🏿👩🏼‍👨🏽‍👦🏼‍👧🏽👩🏻‍👩🏿‍👧🏼‍👧🏾</a>とか)ですが、1書記素で11コードポイント、UTF-8で41バイトになったりします。</p>
<p>で、問題は、書記素の機械的な判定方法。
コンピューター上でもちゃんと書記素単位で処理してくれないと、人間の感覚からすると「backspace/delete を押すたびに文字が変わる」みたいな変な感じになります。</p>
<p>Unicode 標準としては、「あくまで参考。もっといいアルゴリズムにしてもらってもいいけど」という但し書き付きですが、以下のようなドキュメントがあります。</p>
<ul>
<li><a href="https://www.unicode.org/reports/tr29/">Unicode® Standard Annex #29 UNICODE TEXT SEGMENTATION</a></li>
</ul>
<p>書記素の区切り(grapheme cluster boundary)だけじゃなくて、単語区切り(word boundary)や文区切り(sentence boundary)についても言及。</p>
<p>基本的には、「このカテゴリーのコードポイントの後ろにこのカテゴリーが来たら繋げろ(あるは、そこで区切れ)」というルールが示されていて、そのルール自体は割と単純です。カテゴリーさえわかっていれば。
<a href="https://github.com/ufcpp/GraphemeSplitter/blob/master/GraphemeSplitter/StringSplitter.Grapheme.cs">自分が書いた実装</a>でも、コメント・空行を除けば16行。</p>
<h2>コードポイントのカテゴリー</h2>
<p>真の問題はカテゴリー判定。</p>
<p>Unicode では、コードポイント1つ1つにいろいろな属性が定義されています。
例えば、C# で<a href="https://docs.microsoft.com/ja-jp/dotnet/api/system.globalization.charunicodeinfo.getunicodecategory"><code>GetUnicodeCategory</code></a>で取れるやつは「<a href="http://www.unicode.org/reports/tr44/#General_Category_Values">general category</a>」というやつで、
「<a href="https://www.unicode.org/Public/11.0.0/ucd/UnicodeData.txt">UnicodeData.txt</a>」(<code>;</code>区切り)の3列目に定義があります。</p>
<p>UnicodeData.txt の中身を見れば何がきついかわかっていただけると思います。
こいつ、(Version 11 時点で)32292行もあります。
何らかの計算式があるとかではなく、愚直にテーブル。
そりゃまあ、それしかやりようがないのはわかりますが…</p>
<p>UnicodeData.txt 1個でもでかいのに、さらに追加で別の定義ファイルを参照せざるを得ない処理なんかもあったりします。
書記素区切りはその1つで、<a href="https://www.unicode.org/Public/11.0.0/ucd/auxiliary/GraphemeBreakProperty.txt">GraphemeBreakProperty.txt</a>内のデータが必要になったり。</p>
<p>この問題は別に絵文字とか書記素分割だけのものでもなくて、
例えば <code>ToLower</code>/<code>ToUpper</code>の実装とかでも問題になります。</p>
<h3>テーブルの引き方(自分の実装)</h3>
<p><code>GetUnicodeCategory</code>で取れるカテゴリーだけで判別できるんだったら楽なんですけどね。
<a href="https://github.com/ufcpp/GraphemeSplitter/blob/master/GraphemeSplitter/Character.GetGraphemeBreakPropertyV10.cs">自分が書いたコードが3千行近くなった</a>理由は、GraphemeBreakProperty.txt で定義されたカテゴリーが必要だったからです。</p>
<p>当たり前ですけど、こんなのコード生成で作ってます。</p>
<p>実行速度とか生成されるDLLサイズとかを比較するために数パターンのコード生成をやってみていて、全部 <a href="https://github.com/ufcpp/GraphemeSplitter/blob/master/GraphemeBreakPropertyCodeGeneratorTest/Benchmark.switch.cs">switch case に展開したやつ(約2万行)</a>とかもあったりします(コンパイルするだけで1分くらいかかります。)。結局、まあ、二分探索でやるパターンを採用したのが上記の3千行近いコード。</p>
<h3>テーブルの引き方(.NET Core の実装)</h3>
<p>.NET 標準の<a href="https://docs.microsoft.com/ja-jp/dotnet/api/system.globalization.charunicodeinfo.getunicodecategory"><code>GetUnicodeCategory</code></a> とか <a href="https://docs.microsoft.com/ja-jp/dotnet/api/system.globalization.charunicodeinfo.getnumericvalue"><code>GetNumericValue</code></a>とかも、
やっぱりテーブルを引く実装になっています。
テーブルのデータは以下のコード中にあり。</p>
<ul>
<li><a href="https://github.com/dotnet/coreclr/blob/master/src/System.Private.CoreLib/shared/System/Globalization/CharUnicodeInfoData.cs">CharUnicodeInfoData.cs</a></li>
</ul>
<p>13万文字以上もあるものを愚直にテーブル化するわけにもいかないので、11:5:4ビットに区切った3段テーブルになっています。
(同じカテゴリーが連続していることが多いので、こういう分け方をするとデータ量が減る。
それでも23KBほどのサイズ。)</p>
<p>もちろんこいつもコード生成。
UnicodeData.txt からこのテーブルを生成するコードも coreclr 内にあります。</p>
<ul>
<li><a href="https://github.com/dotnet/coreclr/tree/master/src/System.Private.CoreLib/Tools/GenUnicodeProp">GenUnicodeProp</a></li>
</ul>
<h2>バージョン</h2>
<p>テーブル実装のなお悪いところは、バージョンが変わるとテーブル自体を作り直すしかないところでして。</p>
<p>例えば先ほどの CharUnicodeInfoData.cs ですが、Unicode 11 にアップデートした時のプルリクエストがこちら:</p>
<ul>
<li><a href="https://github.com/dotnet/coreclr/pull/20589">Get the real update for Unicode 11 data #20589</a></li>
</ul>
<p>まあ、「Files changed」で差分を見てみてください。結構な分量。</p>
<p>しかも、Unicode、ほとんどの場合は「追加」なんですが、
たまーに破壊的変更もやるんですよね。
Unicode 標準に追従すると、そのフレームワークも破壊的変更を起こすことが。</p>
<p><a href="http://d.hatena.ne.jp/masanobuimai/20140623/1403530870">Java</a>も<a href="/study/csharp/misc_unicode.html#katakana-middle-dot">C#</a>やられてますが、Unicode のカテゴリー変更のあおりを受けています。</p>
<p>そうなると、指定したバージョンの Unicode 文字カテゴリーを取れる API も欲しいところなんですが…
1バージョン辺り23KBとかのサイズになるわけで、それを10以上あるバージョンすべてで持つのも結構な負担です。</p>
<h2>char と CharUnicodeInfo</h2>
<p>ちなみに、<a href="https://docs.microsoft.com/ja-jp/dotnet/api/system.char.getunicodecategory"><code>char.GetUnicodeCategory</code></a>と<a href="https://docs.microsoft.com/ja-jp/dotnet/api/system.globalization.charunicodeinfo.getunicodecategory"><code>CharUnicodeInfo.GetUnicodeCategory</code></a> で結果が違うという邪悪なおまけつき。</p>
<p>どうも、昔からある <code>char</code> の方の実装は Unicode 4.0 がベース、
<code>CharUnicodeInfo</code> は Unicode 5.0 がベース(最近 11.0 ベースに更新)だそうです。</p>
<p><code>char</code> の方を「破壊的変更になるし変えれない」とか中途半端にやった結果こうなったとか。
しかも、完全に Unicode 4.0 のままなんじゃなくて、
<a href="https://gist.github.com/ufcpp/1573a1a453bce1827b6b5025f79ed18a">Latin-1 の文字だけ 4.0 の時のカテゴリーのままで、残りは更新されていそうという</a>。</p>
<h2>International Components for Unicode</h2>
<p>そんな感じで、Unicode のカテゴリー判定は結構つらい作業です。
なので、OS に <a href="http://site.icu-project.org/home">ICU</a> が入ってることを期待して、それを参照するのがいいのかも…
(自前で ICU のバイナリを同梱しようとすると20MBを超えます。)</p>
<p><a href="http://userguide.icu-project.org/boundaryanalysis">書記素、単語、文、行の区切り</a>の実装もあります。</p>
<p>ちなみに、<a href="https://docs.microsoft.com/en-us/windows/desktop/intl/international-components-for-unicode--icu-">Windows 10 には標準で ICU が組み込まれてる</a>そうです。</p>
 ]]></description>
				<pubDate>Mon, 24 Dec 2018 20:39:22 +0900</pubDate>
			</item>
			<item>
				<title>静的な typeof/sizeof</title>
				<link>http://ufcpp.net/blog/2018/12/statictypeof/</link>
				<description><![CDATA[ <p><a href="/blog/2018/12/jitintrinsics/">JIT Intrinsics</a>で少し触れましたが、
.NET Core 2.1では<code>Enum.HasFlag</code>に対する最適化が掛かります。
.NET Core 2.0と2.1で<code>Enum.HasFlag</code>の実行速度が1桁違うわけですが、
古いランタイムでも何とかする手段がなくもないです(ただし、<code>Unsafe</code>)。</p>
<p>今日はそんな、.NET Core 2.0以前でも使える最適化の話。</p>
<h2>定数最適化</h2>
<p>例えば、以下のようなコードを考えます。</p>
<pre class="source" title="if (true) は else 側が消える">
<code><span class="reserved">static</span> <span class="reserved">int</span> X()
{
    <span class="reserved">if</span> (<span class="reserved">true</span>) <span class="reserved">return</span> 1;
    <span class="reserved">else</span> <span class="reserved">return</span> 0;
}
</code></pre>
<p><code>if</code> の条件式が定数なので、これは C# のコンパイル時に最適化が掛かって、 <code>return 1</code>だけが残ります。<code>if</code>相当のコードは出力されません。
このように、コンパイル時に確定している値や条件分岐などは、きれいさっぱり消えることがあります。</p>
<h2>JIT 時定数</h2>
<p>中には、C# コンパイル結果としては定数にならないものの、
JIT のタイミングでは定数と判明して、最適化が掛かるものがあります。</p>
<p>ジェネリック型引数に対する<code>typeof(T)</code>や<code>sizeof(T)</code>はまさにそういう「JIT 時に定数になるもの」です。
例えば以下のようなコードは C# コンパイラーは条件分岐を生成しますが、
 JIT 時の最適化が掛かって、条件式が一致している行だけを残して消えてくれます。</p>
<pre class="source" title="静的に解決できる typeof は JIT 時に消える">
<code><span class="reserved">static</span> <span class="reserved">long</span> MaxValue&lt;<span class="type">T</span>&gt;()
{
    <span class="reserved">if</span> (<span class="reserved">typeof</span>(<span class="type">T</span>) == <span class="reserved">typeof</span>(<span class="reserved">byte</span>)) <span class="reserved">return</span> <span class="reserved">byte</span>.MaxValue;
    <span class="reserved">else</span> <span class="reserved">if</span> (<span class="reserved">typeof</span>(<span class="type">T</span>) == <span class="reserved">typeof</span>(<span class="reserved">short</span>)) <span class="reserved">return</span> <span class="reserved">short</span>.MaxValue;
    <span class="reserved">else</span> <span class="reserved">if</span> (<span class="reserved">typeof</span>(<span class="type">T</span>) == <span class="reserved">typeof</span>(<span class="reserved">int</span>)) <span class="reserved">return</span> <span class="reserved">int</span>.MaxValue;
    <span class="reserved">else</span> <span class="reserved">if</span> (<span class="reserved">typeof</span>(<span class="type">T</span>) == <span class="reserved">typeof</span>(<span class="reserved">long</span>)) <span class="reserved">return</span> <span class="reserved">long</span>.MaxValue;
    <span class="comment">// お好みで、sbyte, ushort, uint, ulong もどうぞ</span>
    <span class="reserved">else</span> <span class="reserved">throw</span> <span class="reserved">new</span> <span class="type">InvalidOperationException</span>();
}
</code></pre>
<h2>Enum.HasFlag の代わり</h2>
<p>ということで、この手の分岐を書いて、ジェネリックな <code>HasFlag</code> を書いてみましょう。</p>
<pre class="source" title="sizeof が JIT 時定数なのを利用した HasFlag 最適化">
<code><span class="reserved">using</span> System;
<span class="reserved">using</span> System.Runtime.CompilerServices;
 
<span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">class</span> <span class="type">EnumExtensions</span>
{
    [<span class="type">MethodImpl</span>(<span class="type">MethodImplOptions</span>.AggressiveInlining)]
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">bool</span> UnsafeHasFlag&lt;<span class="type">T</span>&gt;(<span class="type">T</span> x, <span class="type">T</span> y)
        <span class="reserved">where</span> <span class="type">T</span> : <span class="reserved">unmanaged</span>, <span class="type">Enum</span>
    {
        <span class="reserved">if</span> (<span class="type">Unsafe</span>.SizeOf&lt;<span class="type">T</span>&gt;() == 1) <span class="reserved">return</span> (<span class="type">Unsafe</span>.As&lt;<span class="type">T</span>, <span class="reserved">byte</span>&gt;(<span class="reserved">ref</span> x) &amp; <span class="type">Unsafe</span>.As&lt;<span class="type">T</span>, <span class="reserved">byte</span>&gt;(<span class="reserved">ref</span> y)) != 0;
        <span class="reserved">else</span> <span class="reserved">if</span> (<span class="type">Unsafe</span>.SizeOf&lt;<span class="type">T</span>&gt;() == 2) <span class="reserved">return</span> (<span class="type">Unsafe</span>.As&lt;<span class="type">T</span>, <span class="reserved">ushort</span>&gt;(<span class="reserved">ref</span> x) &amp; <span class="type">Unsafe</span>.As&lt;<span class="type">T</span>, <span class="reserved">ushort</span>&gt;(<span class="reserved">ref</span> y)) != 0;
        <span class="reserved">else</span> <span class="reserved">if</span> (<span class="type">Unsafe</span>.SizeOf&lt;<span class="type">T</span>&gt;() == 4) <span class="reserved">return</span> (<span class="type">Unsafe</span>.As&lt;<span class="type">T</span>, <span class="reserved">uint</span>&gt;(<span class="reserved">ref</span> x) &amp; <span class="type">Unsafe</span>.As&lt;<span class="type">T</span>, <span class="reserved">uint</span>&gt;(<span class="reserved">ref</span> y)) != 0;
        <span class="reserved">else</span> <span class="reserved">if</span> (<span class="type">Unsafe</span>.SizeOf&lt;<span class="type">T</span>&gt;() == 8) <span class="reserved">return</span> (<span class="type">Unsafe</span>.As&lt;<span class="type">T</span>, <span class="reserved">ulong</span>&gt;(<span class="reserved">ref</span> x) &amp; <span class="type">Unsafe</span>.As&lt;<span class="type">T</span>, <span class="reserved">ulong</span>&gt;(<span class="reserved">ref</span> y)) != 0;
        <span class="reserved">else</span> { Throw(); <span class="reserved">return</span> <span class="reserved">default</span>; }
    }
 
    <span class="reserved">private</span> <span class="reserved">static</span> <span class="reserved">void</span> Throw() =&gt; <span class="reserved">throw</span> <span class="reserved">new</span> <span class="type">InvalidOperationException</span>();
}
</code></pre>
<p>このコードで、非ジェネリックな場合の、</p>
<pre class="source" title="参考: 非ジェネリック実装">
<code><span class="reserved">static</span> <span class="reserved">bool</span> HasFlag(A x, A y) =&gt; (((<span class="reserved">int</span>)x) &amp; ((<span class="reserved">int</span>)y)) != 0;
</code></pre>
<p>みたいなコードとそこまで差がない性能が出ます。
さすがに最適化をちょっと阻害されるみたいで全く同じとは行きませんが、
少なくとも <code>Enum.HasFlag</code> みたいに1桁遅くなることはありません。
せいぜい数割差です。</p>
<p><code>Unsafe.SizeOf&lt;T&gt;()</code> は内部的に <code>sizeof(T)</code> を呼んでいるだけです。
単にジェネリック型引数に対して掛けるようにしただけ。
(C# 7.3 移行で unsafe コードであれば、普通にジェネリック型引数に対しても <code>sizeof(T)</code> を掛けるようになりました。一方、C# 7.2 以前だと <code>Unsafe.SizeOf&lt;T&gt;</code> メソッドが必須です。)</p>
<p>先ほどの説明の通り、<code>sizeof(T)</code>はJIT時定数になるので、
この<code>UnsafeHasFlag</code>メソッドは、ちゃんと1行だけ残して残りのサイズが違うコードはきれいさっぱり消えます。
この最適化は結構昔から掛かっているものなので、.NET Core 2.0以前でも働きます。
(と言っても、<a href="https://www.nuget.org/packages/System.Runtime.CompilerServices.Unsafe/"><code>Unsafe</code>クラス</a>が対応している必要があるので、.NET Framework 3.5とかでは動かせません。
<code>Unsafe.As</code>相当のILコードを自分で書けば使えますが…)</p>
<p>ちなみに、<code>Unsafe.As&lt;T, byte&gt;(ref x)</code> の方は変数の型を無理やり変更するもので、通常の C# ではどうやっても書けません。
メソッドの中身は IL で書かれています。
(また、<code>Intrinsic</code>属性が付いているので、おそらく .NET Core 2.1移行ではJITレベルでの最適化も何か掛けていそうです。)</p>
 ]]></description>
				<pubDate>Mon, 24 Dec 2018 10:43:48 +0900</pubDate>
			</item>
			<item>
				<title>JIT Intrinsics</title>
				<link>http://ufcpp.net/blog/2018/12/jitintrinsics/</link>
				<description><![CDATA[ <p>.NET Core 2.1 では、いくつか、JIT 時の特殊対応によるパフォーマンス改善を行っています。</p>
<p>そういう「特殊対応」を intrinsic (固有の、内在的な、内因的な、本質的な)と呼びます。
「JIT 時の特殊対応」であれば「JIT intrinsic expansions」(固有展開)とか「JIT intrinsics」(s が付くことで名詞化してる。economics とかの s と同じ)と言います。</p>
<h2>Intrinsic 属性</h2>
<p>JIT 時特殊対応をしているクラスやメソッドには <a href="https://source.dot.net/#System.Private.CoreLib/shared/System/Runtime/CompilerServices/IntrinsicAttribute.cs,0b1553fdd9183e62"><code>Intrinsic</code> 属性</a>が付いています。
この属性を参照しているものを検索することで、どこで特殊対応が行われているかを追うことができます。</p>
<h3><code>Vector</code></h3>
<p>記憶にある限り、<code>Intrinsic</code> 属性が最初に使われたのは
<a href="https://source.dot.net/#System.Private.CoreLib/shared/System/Numerics/Vector.cs"><code>Vector&lt;T&gt;</code> 構造体</a>(<code>System.Numerics</code>名前空間)です。</p>
<p>この型は SIMD 演算を行うためのもので、</p>
<ul>
<li>SIMD に対応している環境では、SIMD 命令を使った実装に差し替える</li>
<li>そうでない場合、<code>vector1.X * vector2.X + vector1.Y * vector2.Y + ...</code> というような通常の C# コードを使う</li>
</ul>
<p>と言うような処理をしています。</p>
<h2>.NET Core 2.1 での最適化</h2>
<p>.NET Core 2.1 でいくつか intrinsic なものが増えています。
そのうちいくつかを紹介。</p>
<h3>EqualityComparer.Default</h3>
<p><a href="/blog/2018/12/devirtualization/">Devirtualize 処理</a>で説明した通り、.NET Core 2.1 では<code>EqualityComparer&lt;T&gt;.Default</code>に対して具象型を返す用ような最適化が入っています。</p>
<p>なので、例えば、<code>EqualityComparer&lt;int&gt;.Default.Equals(1, 2)</code>みたいなコードは、.NET Core 2.0 よりも、2.1 の方が1桁高速です。</p>
<h3>Enum.HasFlag</h3>
<p><code>Enum.HasFlag</code> も .NET Core 2.1 で intrinsic な最適化が掛かったものの1つです。</p>
<p><code>HasFlag</code>相当の処理は、具体的な列挙型がわかっていれば以下のような書き方ができます。
ただの <code>&amp;</code> と0比較なので、かなり高速です。</p>
<pre class="source">
<code><span class="reserved">static</span> <span class="reserved">bool</span> HasFlag(<span class="type">A</span> x, <span class="type">A</span> y) =&gt; (((<span class="reserved">int</span>)x) &amp; ((<span class="reserved">int</span>)y)) != 0;

</code></pre>
<p>ところが、任意の列挙型に対して使えるようにしようとすると途端に面倒になります。
<code>Enum</code>クラス(<code>System</code>名前空間)の<code>HasFlag</code>メソッドで機能としては提供されているんですが、
この<code>HasFlag</code>メソッドはむちゃくちゃ遅いです。</p>
<p>そこで、.NET Core 2.1ではJIT時に特殊対応するようにしました。
<code>HasFlag</code>メソッドを見たら単なる<code>&amp;</code>に置き換える処理が掛かっています。
「<a href="/study/csharp/oop/miscimplictinherit/#enum-hasflag">Enum.HasFlag でのボックス化</a>」で説明しているように、
.NET Core 2.0以前と2.1以降で実行速度に20倍以上の差があります。</p>
<h3>Span のインデクサー</h3>
<p><a href="/study/csharp/resource/span/"><code>Span&lt;T&gt;</code>構造体</a>のインデクサーにも JIT 時特殊対応が入っています。</p>
<p>これは、配列の<code>array[i]</code>と同じような最適化です。
「<a href="/blog/2018/12/arrayindexer/">配列のインデクサー</a>」で説明したように、配列のインデクサーには</p>
<ul>
<li>何もしなければ、<code>array[i]</code> のところに暗黙的な範囲チェックを追加する</li>
<li>明示的な範囲チェックがあれば、余計な範囲チェックの追加はしない</li>
</ul>
<p>と言うような処理が掛かっています。
これと同じことを、.NET Core 2.1では<code>Span&lt;T&gt;</code>のインデクサーに対しても行っています。
特殊対応なしだと、<code>Span&lt;T&gt;</code>のインデクサーは常に範囲チェックを必要としますが、
.NET Core 2.1 以降だと、必要に応じて範囲チェックの削除が行われます。</p>
 ]]></description>
				<pubDate>Sun, 23 Dec 2018 11:16:04 +0900</pubDate>
			</item>
			<item>
				<title>配列インデックスは0以上</title>
				<link>http://ufcpp.net/blog/2018/12/arrayindex/</link>
				<description><![CDATA[ <p>今日は corefx (.NET の標準ライブラリ)の実装レベルの最適化の話。</p>
<p>.NET Core 2.0 とか 2.1 リリースの頃にブログも出ていましたが、
.NET Core 2.X 世代は結構パフォーマンス改善を頑張っています。</p>
<ul>
<li><a href="https://blogs.msdn.microsoft.com/dotnet/2017/06/07/performance-improvements-in-net-core/">Performance Improvements in .NET Core</a></li>
<li><a href="https://blogs.msdn.microsoft.com/dotnet/2018/04/18/performance-improvements-in-net-core-2-1/">Performance Improvements in .NET Core 2.1</a></li>
</ul>
<p>実際、 .NET Framework で動かしていたアプリを、 .NET Core 2.1 で動かすようにするだけで、アプリ側では何もしなくても1～2割くらいは高速化します。</p>
<p>改善の方法としては、<a href="/study/csharp/resource/span/"><code>Span&lt;T&gt;</code>構造体</a>を使ってアロケーションを減らしたり、<a href="/blog/2018/12/devirtualization/">Devirtualize 処理</a>を掛けたりといったなんか上等そうな最適化もたくさんやっています。
でも、今日はそんな高尚なものの話ではなく、「.NET の配列のインデックスは0以上の整数 (<code>int</code> なのに負の値は絶対来ない)」と言う前提での細かい最適化の話です。</p>
<h2>負のインデックス？</h2>
<p>corefx/coreclr のプルリクエストで、ここ1年くらいの間、頻出する最適化がありまして。
配列操作で以下のようなコードはよく書くと思います。</p>
<pre class="source" title="配列の範囲チェック(書き換え前)">
<code><span class="reserved">if</span> (index &lt; 0 || index &gt;= length)
    <span class="reserved">throw</span> <span class="reserved">new</span> <span class="type">IndexOutOfRangeException</span>();
</code></pre>
<p>これを、以下のように書き換えるだけ。</p>
<pre class="source" title="配列の範囲チェック(書き換え後)">
<code><span class="reserved">if</span> ((<span class="reserved">uint</span>)index &gt;= (<span class="reserved">uint</span>)length)
    <span class="reserved">throw</span> <span class="reserved">new</span> <span class="type">IndexOutOfRangeException</span>();
</code></pre>
<p>比較と OR が1回ずつ減っているので速くなるという理屈。
<a href="https://github.com/dotnet/coreclr/search?q=uint+length&amp;unscoped_q=uint+length">corefx 内で「uint length」で検索</a>してもらえばわかりますけど、割かし大量に出てきます。</p>
<p>これは、でも、配列のインデックスが0開始の<code>int</code>だからできる最適化になります。
(元からインデックスが<code>uint</code>だった場合、<code>int.MaxValue</code>より大きいインデックスの時の挙動が狂う。)</p>
<h3>Array.CreateInstance</h3>
<p>.NET の配列のインデックスは必ず0以上。いいね？</p>
<p>ところで、以下のコードはどう思います。</p>
<pre class="source" title="Array.CreateInstance なら、lower bound 指定可能">
<code><span class="reserved">using</span> System;
 
<span class="reserved">public</span> <span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> Main()
    {
        <span class="reserved">var</span> array = <span class="type">Array</span>.CreateInstance(<span class="reserved">typeof</span>(<span class="reserved">string</span>),
            lengths: <span class="reserved">new</span>[] { 4 },
            lowerBounds: <span class="reserved">new</span>[] { -4 });
 
        array.SetValue(<span class="string">&quot;a&quot;</span>, -4);
        array.SetValue(<span class="string">&quot;b&quot;</span>, -3);
        array.SetValue(<span class="string">&quot;c&quot;</span>, -2);
        array.SetValue(<span class="string">&quot;d&quot;</span>, -1);
 
        <span class="reserved">foreach</span> (<span class="reserved">var</span> x <span class="reserved">in</span> array)
        {
            <span class="type">Console</span>.WriteLine(x);
        }
    }
}
</code></pre>
<p>ちゃんと動きます。
VB 6 時代の名残っぽいんですけども、
.NET では、0以外の開始インデックスを持つ配列を作る機能があります。
上記の例は、-4 開始。</p>
<p>ということで、先ほどの「配列長は0以上」を前提にしたコードがいいのかどうか、という話になったりもするんですが。
どうも、<code>T[]</code> 型にキャストすることができなくなるから大丈夫みたいです。</p>
<pre class="source" title="0開始じゃない配列は T[] じゃない">
<code><span class="comment">// 開始インデックス 0 を明示して CreateInstance</span>
<span class="comment">// それを string[] にキャスト。</span>
<span class="comment">// これは問題なく動きます。</span>
<span class="reserved">var</span> a1 = (<span class="reserved">string</span>[])<span class="type">Array</span>.CreateInstance(<span class="reserved">typeof</span>(<span class="reserved">string</span>),
    lengths: <span class="reserved">new</span>[] { 4 },
    lowerBounds: <span class="reserved">new</span>[] { 0 });
 
<span class="comment">// 0 以外を指定した上で、全く同じく string[] にキャスト。</span>
<span class="comment">// InvalidCastException が発生。</span>
<span class="reserved">var</span> a2 = (<span class="reserved">string</span>[])<span class="type">Array</span>.CreateInstance(<span class="reserved">typeof</span>(<span class="reserved">string</span>),
    lengths: <span class="reserved">new</span>[] { 4 },
    lowerBounds: <span class="reserved">new</span>[] { -4 });
</code></pre>
<p>ちなみに、例外メッセージは以下のような感じ。</p>
<p><code>txt
Unable to cast object of type 'System.String[*]' to type 'System.String[]'.</code></p>
<p><code>String[*]</code> 型… だと…
つまるところ、開始インデックスが型情報の一部…
(実際には、「0開始のやつ」と「0じゃないやつ」の2つの型しかなくて、1開始と-1開始みたいなやつはどちらも <code>T[*]</code> 型になって、同じ型みたいです。)</p>
<p>配列だけ特殊対応してもらってていいなぁ…
C++ の template みたいに、C# のジェネリクスでも型引数に整数を渡したいのに… (できない)</p>
<p>まあ、それはさておき、とりあえず、.NET の <code>T[]</code> で書かれる配列のインデックスは0以上の整数と思っていいみたいです。</p>
<h2>最上位ビットを流用</h2>
<p>配列のインデックスをフィールドに持つような型がちらほらあります。</p>
<h3>Memory</h3>
<p>例えば、<a href="https://source.dot.net/#q=System.Private.CoreLib%20System.Memory%3CT%3E"><code>Memory&lt;T&gt;</code>構造体</a>がそうなんですが、これの中身は以下のような感じ。
(<code>_object</code>には配列、もしくは、<code>MemoryManager&lt;T&gt;</code>型が入ります。)</p>
<pre class="source" title="Memory構造体">
<code><span class="reserved">public</span> <span class="reserved">readonly</span> <span class="reserved">struct</span> <span class="type">Memory</span>&lt;<span class="type">T</span>&gt;
{
    <span class="reserved">private</span> <span class="reserved">readonly</span> <span class="reserved">object</span> _object;
    <span class="reserved">private</span> <span class="reserved">readonly</span> <span class="reserved">int</span> _index;
    <span class="reserved">private</span> <span class="reserved">readonly</span> <span class="reserved">int</span> _length;
}
</code></pre>
<p>ここで、<code>_index</code>と<code>_length</code>、つまり、配列のインデックスと長さは絶対に負にならない保証があります。
負にならないということは、<code>int</code>の内部構造的には、最上位ビットが常に0です。</p>
<p>ということで、<code>Memory&lt;T&gt;</code>構造体では、この最上位ビットを別の用途に流用することで最適化していたりします。
具体的には、<code>_object</code>の中に実際に何が入っているかを弁別するために<code>_length</code>の最上位ビットを使っていたりします
(配列がpinned済みかどうか(<a href="https://docs.microsoft.com/ja-jp/dotnet/api/system.runtime.interopservices.gchandletype"><code>GCHandleType.Pinned</code></a>指定で<a href="https://docs.microsoft.com/ja-jp/dotnet/api/system.runtime.interopservices.gchandle.alloc"><code>GCHandle.Alloc</code></a>されているかどうか)を記録しています)。</p>
<h3><code>Index</code></h3>
<p>C# 8.0 では、以下のような構文で、
配列の一部分を<code>Span&lt;T&gt;</code>として切り出すことができるようになります。</p>
<pre class="source" title="C# 8.0 の range 構文">
<code><span class="reserved">int</span>[] array = { 1, 2, 3, 4, 5 };
<span class="reserved">var</span> sub = array[1..^1]; <span class="comment">// 先頭から1 ～ 末尾から1 の範囲</span>
 
<span class="comment">// 2, 3, 4</span>
<span class="reserved">foreach</span> (<span class="reserved">var</span> x <span class="reserved">in</span> sub)
{
    <span class="type">Console</span>.WriteLine(x);
}
</code></pre>
<p>この、インデックスの値が先頭からなのか末尾からなのかを表すために、
以下のような <a href="https://github.com/dotnet/coreclr/blob/3464b60b85c8e10d69d8da86d2eb3f9e7aaa7c4b/src/System.Private.CoreLib/shared/System/Index.cs"><code>Index</code> 構造体</a>が追加されています(主要部分のみ抜き出し)。</p>
<pre class="source" title="Index 構造体">
<code><span class="reserved">public</span> <span class="reserved">readonly</span> <span class="reserved">struct</span> <span class="type">Index</span>
{
    <span class="reserved">private</span> <span class="reserved">readonly</span> <span class="reserved">int</span> _value;
 
    <span class="reserved">public</span> Index(<span class="reserved">int</span> value, <span class="reserved">bool</span> fromEnd)
    {
        _value = fromEnd ? ~value : value;
    }
 
    <span class="reserved">public</span> <span class="reserved">int</span> Value =&gt; _value &lt; 0 ? ~_value : _value;
    <span class="reserved">public</span> <span class="reserved">bool</span> FromEnd =&gt; _value &lt; 0;
}
</code></pre>
<p>これも、配列のインデックスは0以上という前提で、
「末尾から」の方を負の数で表すことで、追加の bool フラグを持たないようにしています。</p>
 ]]></description>
				<pubDate>Sat, 22 Dec 2018 10:25:16 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 12/21 &amp; Connect() Japan フォローアップ</title>
				<link>http://ufcpp.net/blog/2018/12/pickuproslyn1221/</link>
				<description><![CDATA[ <p>昨日、<a href="https://connpass.com/event/111254/">Connect(); Japan 2018</a>でちょっとだけですけども、C# 8.0の話をしたりしました。
7分(ちょっと超過したけど)だとあんまり大したことを話せず…</p>
<p>とりあえず、昨日やったデモは、1機能1コミットでプルリクを作って GitHub においてあるのでそちらも参照してみてください。</p>
<ul>
<li><a href="https://github.com/ufcpp/connect-japan-2018/pull/2">C# 8.0 デモ用</a> … 昨日やれたデモ。Preview 1 で入った機能の紹介。</li>
<li><a href="https://github.com/ufcpp/connect-japan-2018/pull/1">UfcppSample</a> … <a href="/study/csharp/">C# によるプログラミング入門</a>で書いてるコードに対して NullableReferenceTypes true にするとどうなるか、どう書き換えるかというデモ。時間なかった。</li>
</ul>
<p>で、今日は、<a href="/blog/2018/12/vs2019p1/">Visual Studio 2019 Preview 1</a>のその後のピックアップRoslynでパターン マッチングがらみの話が1件と、
機能やれなかった<a href="https://github.com/ufcpp/connect-japan-2018/pull/1">UfcppSample</a>デモのフォローアップ。</p>
<h2>パターン マッチング</h2>
<p>v2。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/2095">Open LDM Issues in Pattern-Matching (v2)</a></li>
</ul>
<p><a href="https://github.com/dotnet/csharplang/issues/1054">元々あった issue</a>が長大になりすぎたので、今残ってる作業だけを抜き出して新しくissueを立てた模様。</p>
<p><a href="/blog/2018/12/cs8patterns/">今月1回書いてますけども</a>、
パターン マッチングは Preview 1 に入ると思ってたけど入ってなかったって感じなんですが。
上記 issue はその現状で残ってる課題の一覧。</p>
<ul>
<li>
switch 式を、void も認めて、「式ステートメント」も認めたい
<ul>
<li><code>void M1()</code>、<code>void M2()</code> に対して、<code>x switch { 1 =&gt; M1(), 2 =&gt; M2() };</code> みたいなのを認めたい</li>
</ul>
</li>
<li>
switch 式、末尾 <code>,</code> を認めたい
<ul>
<li>今の実装だと <code>x switch { 1 =&gt; M1(), 2 =&gt; M2(), }</code> (<code>M2()</code>の後ろの<code>,</code>) を書くとエラー</li>
</ul>
</li>
<li>
0, 1要素分解を認めたい
<ul>
<li><code>if (o is (3) _)</code> みたいなの</li>
<li>キャスト+定数パターン <code>o is (int)0</code> みたいなのとの弁別で悩み中</li>
</ul>
</li>
<li>
名前付き引数でのオーバーロード解決を認めるかどうか
<ul>
<li><code>Deconstruct(int X, int Y)</code>と<code>Deconstruct(double Angle, double Length)</code>があるとき、<code>p is (X: 3, Y: 4)</code>で前者を呼べるようにするかどうか</li>
</ul>
</li>
<li>プロパティ パターンで、インデクサーとかイベントとかを認めるか</li>
<li>
ref構造体のトラッキングがバグってる
<ul>
<li>今、パターン マッチングを使うと、本来返せないはずの <code>Span&lt;T&gt;</code> を返せちゃうバグあり</li>
</ul>
</li>
<li><code>ITuple</code>インターフェイス越しの分解と、<code>Deconstruct</code>メソッド越しの分解の優先度をどうするか</li>
</ul>
<h2>UfcppSample に対して NullableReferenceTypes true</h2>
<p><a href="/blog/2018/12/cs8nrt/">null許容参照型</a>は待望の機能なわけですが、
1つ懸念としては、既存コードに対して適用するとどうなるかでしょう。
一応は、既存コードを壊さないようにopt-in (明示的にオプション指定しないと有効にならない)になっているわけですが、
「問答無用に全体に opt-in してしまうとどうなるか」は気になるところだと思います。</p>
<p>ということで、昨日は、時間が許せば<a href="/study/csharp/">C# によるプログラミング入門</a>で書いてるコードに対して opt-in してみる話もしたかったんですが。
特に、うちのサイトは結構 C# 1.0 とか 2.0 の頃からある古いコードも残っていますし。
それに対して opt-in してみようと。</p>
<p>まあ、時間的に無理だったのでここで改めて。</p>
<h2>普通な範囲</h2>
<p>大半は、「意図して null を受け付けているところにちまちまと <code>?</code> を付けていく作業になります。</p>
<ul>
<li><a href="https://github.com/ufcpp/connect-japan-2018/pull/1/commits/bc8ea6661a38fde76fcc4930719cb693786f3c63">割と納得いく範囲で直せるやつ</a></li>
</ul>
<p>これで、51件あった警告が、28件減って23件に。</p>
<h2>ジェネリクス</h2>
<p>Preview 1の実装では、結構ジェネリクス周りの実装が抜けています。
これに関しては、最近、Roslyn 上で generics がどうこうみたいなプルリクをよく見かけるので、Preview 2までにはだいぶ改善するかもしれません。</p>
<p>とりあえず、今はあきらめて(Preview 2で良くなることを祈って)、無視します。</p>
<ul>
<li><a href="https://github.com/ufcpp/connect-japan-2018/pull/1/commits/5de947a08873d0c420f48dbaacc781e24efe904d">ジェネリクスがらみはdefault!でごまかすしかなさそう</a></li>
</ul>
<p>基本的に、後置き<code>!</code>演算子を付けると、forgiving (警告もみ消しを容赦してもらう)になります。
ジェネリクスがらみにはこいつを使って対処。</p>
<h2>ローカル関数に変更</h2>
<p>ラムダ式に対して再帰したり、自分自身を参照したりするとき、以下のように、デリゲートをいったん空初期化した上で改めてラムダ式を代入する必要があります。</p>
<pre class="source" title="ラムダ式の再帰">
<code><span class="type">Func</span>&lt;<span class="reserved">int</span>, <span class="reserved">int</span>&gt; f = <span class="reserved">null</span>;
f = x =&gt; x &lt;= 1 ? 1 : f(x - 1);
</code></pre>
<p>この、最初の <code>= null</code> がよくない。</p>
<p>で、これは単に、ラムダ式をローカル関数に書き換えるだけで解消します。</p>
<ul>
<li><a href="https://github.com/ufcpp/connect-japan-2018/pull/1/commits/0ea3ca59b868c36fca1a4ea7d1b08d5fa1082de6">そもそもラムダ式の限界。ローカル関数に変える</a></li>
</ul>
<h2>あと片付け</h2>
<p><a href="/study/computer/MemoryManagement.html">ガベコレ</a>で少しでも早く不要メモリを回収してもらうために、もう要らない変数に null を代入することもあったりします。</p>
<p>これに関しては、</p>
<ul>
<li>要らなくなる(Dispose する)までは絶対に null にならないので、<code>T</code> で使いたい</li>
<li>要らなくなった後だけのために <code>T?</code> に変えるのはちょっと嫌</li>
</ul>
<p>という感じ…</p>
<p>ちょっと迷ったんですが、結局は <code>!</code> に頼ることにしました。</p>
<ul>
<li><a href="https://github.com/ufcpp/connect-japan-2018/pull/1/commits/ad94f956e75f74da18d7e220e9c4e253aedfc981">こういう後処理のためのnull代入はnull!でいい気がする</a></li>
</ul>
<h2>バグ</h2>
<p>まあ、バグっててどうしようもない奴は <code>#pragma warning disable</code> で黙殺。</p>
<ul>
<li><a href="https://github.com/ufcpp/connect-japan-2018/pull/1/commits/1fa623ba4494ace9e6d7fb5a29ce09e614ad8421">バグってて対処不能なやつ</a></li>
</ul>
<p>バグ報告済みなので、Preview 2までに治ってるといいなぁ…</p>
<p>ちなみに、このバグは Visual Studio 自体を落とします。</p>
<pre class="source" title="カリー化デリゲートバグ">
<code><span class="reserved">static</span> <span class="reserved">class</span> <span class="type">Ex</span>
{
    <span class="comment">// こういう、カリー化デリゲート(拡張メソッドを使ったデリゲート構築)に対する null 検証がバグってる。</span>
    <span class="comment">// 非 null なインスタンスを渡していても、なぜか null 警告が出る。</span>
    <span class="comment">// バグを黙殺するために ! を付けようとすると Visual Studio が落ちる。</span>
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="type">Action</span> a = <span class="reserved">new</span> <span class="reserved">object</span>().M;
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> M(<span class="reserved">this</span> <span class="reserved">object</span> x) { }
}
</code></pre>
<h2>デモ都合</h2>
<p><a href="/study/csharp/">C# によるプログラミング入門</a>内には、「null がダメなのは百も承知で、もしそれでも null を渡してしまったらどうなるか」を示すデモがいくつかあります。</p>
<p>百も承知でわざとやってるんだからうるせー(おもむろに <code>#pragma warning disable</code>)。</p>
<ul>
<li><a href="https://github.com/ufcpp/connect-japan-2018/pull/1/commits/5b021ecdb380d1f721ee8aec2ff69e09037cd65d">デモ都合で無視したい奴</a></li>
</ul>
<h2>どうしていいのかわからなかった奴…</h2>
<p>で、6件ほど、ほんとにどう対処すべきなのかわからなくてとりあえず <code>!</code> とか <code>#pragma warning disable</code> とかでやっつけたのが6件ほど。</p>
<ul>
<li><a href="https://github.com/ufcpp/connect-japan-2018/pull/1/commits/06138cf31e78b7cc701b8c5faa32357193213a27">デリゲートの += はどう対処すべきなんだろう</a></li>
<li><a href="https://github.com/ufcpp/connect-japan-2018/pull/1/commits/2047730635b94cf3551141c818e6aa1dde1080ec">Rx はほんとどうしたらいいのかわからない</a></li>
</ul>
<p>デリゲートがらみはほんとに鬼門かも…</p>
 ]]></description>
				<pubDate>Fri, 21 Dec 2018 15:22:53 +0900</pubDate>
			</item>
			<item>
				<title>foreach の掛け方いろいろ</title>
				<link>http://ufcpp.net/blog/2018/12/howtoenumerate/</link>
				<description><![CDATA[ <p><a href="/blog/2018/12/FastEnumerator/">IEnumerator の別実装</a>で、
インターフェイス越しの <code>foreach</code> には仮想呼び出しのコストが結構掛かっているという話を書きました。
(そちらでの主題は「なので、<code>MoveNext</code>/<code>Current</code>の2つに分かれているのはちょっともったいない」という話でした。
もちろん、それを気にしないといけないのは大体パフォーマンス最優先のエクストリームな状況だけです。)</p>
<p>あと、<a href="/blog/2018/12/arrayindexer/">配列のインデクサー</a>では、配列と<a href="/study/csharp/resource/span/"><code>Span&lt;T&gt;</code>構造体</a>の列挙には C# のレベルでも JIT のレベルでも最適化が掛かっていて、かなり速いという話をしました。</p>
<p>今回はその辺りを踏まえて、列挙の仕方をいろいろ比較。</p>
<p>参考コード: <a href="https://github.com/ufcpp/UfcppSample/tree/master/Demo/2018/PerformanceTips/ArrayEnumeration">ArrayEnumeration</a></p>
<h2>内部的には配列なコレクション</h2>
<p><code>List&lt;T&gt;</code> (<code>System.Collections.Generic</code> 名前空間)とか、
<code>ImmutableArray&lt;T&gt;</code> (<code>System.Collections.Immutable</code> 名前空間)とか、
内部的に配列を持っていて、その上に何か機能を重ねたり(あるいは逆に書き換えを制限したり)している型は結構あります。
今回はその手の型の列挙について考えます。</p>
<p>とりあえず以下のような型を用意。参考にするために、配列を生列挙するコードも書いておきます。</p>
<pre class="source" title="配列の生列挙">
<code><span class="reserved">using</span> BenchmarkDotNet.Attributes;
 
<span class="reserved">public</span> <span class="reserved">partial</span> <span class="reserved">struct</span> <span class="type">ArrayWrapper</span>&lt;<span class="type">T</span>&gt;
{
    <span class="comment">// 比較のために生列挙をしたいので public (本来は不要というかむしろダメ)</span>
    <span class="reserved">public</span> <span class="reserved">readonly</span> <span class="type">T</span>[] Array;
    <span class="reserved">public</span> ArrayWrapper(<span class="type">T</span>[] array) =&gt; Array = array;
}
 
<span class="reserved">public</span> <span class="reserved">partial</span> <span class="reserved">class</span> <span class="type">ArrayEnumerationBenchmark</span>
{
    <span class="reserved">public</span> <span class="type">ArrayWrapper</span>&lt;<span class="reserved">int</span>&gt; _array;

    <span class="comment">// 比較のための生列挙。</span>
    [<span class="type">Benchmark</span>(Baseline = <span class="reserved">true</span>)]
    <span class="reserved">public</span> <span class="reserved">int</span> RawEnumeration()
    {
        <span class="reserved">var</span> sum = 0;
        <span class="reserved">foreach</span> (<span class="reserved">var</span> x <span class="reserved">in</span> _array.Array) sum += x;
        <span class="reserved">return</span> sum;
    }
}
</code></pre>
<p>とりあえず、結果:</p>
<table>
<thead>
<tr>
	<th>Method</th>
	<th align="right">Mean</th>
	<th align="right">Error</th>
	<th align="right">StdDev</th>
	<th align="right">Ratio</th>
	<th align="right">RatioSD</th>
</tr>
</thead>
<tbody>
<tr>
	<td>RawEnumeration</td>
	<td align="right">385.6 ns</td>
	<td align="right">1.031 ns</td>
	<td align="right">0.9646 ns</td>
	<td align="right">1.00</td>
	<td align="right">0.00</td>
</tr>
</tbody>
</table>
<h2>IEnumerable の実装</h2>
<p><code>foreach</code>で使いたいというのが主題なので、とりあえず先ほどの型に <code>IEnumerable&lt;T&gt;</code> インターフェイスを実装してみます。</p>
<p>とはいえ、インターフェイスを介した <code>GetEnumerator</code>/<code>MoveNext</code>/<code>Current</code> はちょっとオーバーヘッドが掛かるので、以下のような作りにします。
(<code>List&lt;T&gt;</code> なんかはまさにこの作りになっています。)</p>
<pre class="source" title="IEnumerable 化">
<code><span class="reserved">public</span> <span class="reserved">partial</span> <span class="reserved">struct</span> <span class="type">ArrayWrapper</span>&lt;<span class="type">T</span>&gt; : <span class="type">IEnumerable</span>&lt;<span class="type">T</span>&gt;
{
    <span class="comment">// 専用の型を作って、それを具象型のまま公開する</span>
    <span class="reserved">public</span> <span class="type">Enumerator</span> GetEnumerator() =&gt; <span class="reserved">new</span> <span class="type">Enumerator</span>(Array);
 
    <span class="comment">// インターフェイスは明示的実装にして別実装</span>
    <span class="type">IEnumerator</span>&lt;<span class="type">T</span>&gt; <span class="type">IEnumerable</span>&lt;<span class="type">T</span>&gt;.GetEnumerator() =&gt; <span class="reserved">new</span> <span class="type">EnumeratorObject</span>(Array);
    <span class="type">IEnumerator</span> <span class="type">IEnumerable</span>.GetEnumerator() =&gt; <span class="reserved">new</span> <span class="type">EnumeratorObject</span>(Array);
}
</code></pre>
<h3>専用実装(構造体)</h3>
<p>まずは専用実装の方。
配列の全要素を列挙するような <code>IEnumerator&lt;T&gt;</code> 実装は以下のようになります。
無駄なアロケーションが発生しないように構造体製。</p>
<pre class="source" title="構造体で専用実装">
<code><span class="reserved">public</span> <span class="reserved">partial</span> <span class="reserved">struct</span> <span class="type">ArrayWrapper</span>&lt;<span class="type">T</span>&gt;
{
    <span class="comment">// 「仮想呼び出しは遅い」ということがわかっているわけで、</span>
    <span class="comment">// こんな感じで具象型を返す GetEnumerator を作った方が高速。</span>
    <span class="comment">// 構造体にした方が最適化が効く。</span>
    <span class="reserved">public</span> <span class="type">Enumerator</span> GetEnumerator() =&gt; <span class="reserved">new</span> <span class="type">Enumerator</span>(Array);
 
    <span class="reserved">public</span> <span class="reserved">struct</span> <span class="type">Enumerator</span> : <span class="type">IEnumerator</span>&lt;<span class="type">T</span>&gt;
    {
        <span class="reserved">private</span> <span class="reserved">readonly</span> <span class="type">T</span>[] _array;
        <span class="reserved">private</span> <span class="reserved">int</span> _i;
        <span class="reserved">internal</span> Enumerator(<span class="type">T</span>[] array) =&gt; (_array, _i) = (array, -1);
 
        <span class="reserved">public</span> <span class="type">T</span> Current =&gt; _array[_i];
        <span class="reserved">public</span> <span class="reserved">bool</span> MoveNext() =&gt; ((<span class="reserved">uint</span>)++_i) &lt; (<span class="reserved">uint</span>)_array.Length;
        <span class="comment">// 残りは省略</span>
    }
}
 
<span class="reserved">public</span> <span class="reserved">partial</span> <span class="reserved">class</span> <span class="type">ArrayEnumerationBenchmark</span>
{
    <span class="comment">// 構造体の Enumerator 越しの列挙</span>
    <span class="comment">// 構造体で返してるとほんとにきっちり最適化が効くみたいで、</span>
    <span class="comment">// ほぼ配列生列挙と同じ速度が出る。</span>
    [<span class="type">Benchmark</span>]
    <span class="reserved">public</span> <span class="reserved">int</span> StructEnumeration()
    {
        <span class="reserved">var</span> sum = 0;
        <span class="reserved">foreach</span> (<span class="reserved">var</span> x <span class="reserved">in</span> _array) sum += x;
        <span class="reserved">return</span> sum;
    }
}
</code></pre>
<p>これを使って <code>foreach (var x in _array)</code> とすると、
<code>MoveNext</code>も<code>Current</code>もインライン展開されて、
最適化でほとんど配列の生列挙と同じコードに展開されます。
誤差の範囲内で生列挙と同じ速度が出ます。</p>
<table>
<thead>
<tr>
	<th>Method</th>
	<th align="right">Mean</th>
	<th align="right">Error</th>
	<th align="right">StdDev</th>
	<th align="right">Ratio</th>
	<th align="right">RatioSD</th>
</tr>
</thead>
<tbody>
<tr>
	<td>RawEnumeration</td>
	<td align="right">385.6 ns</td>
	<td align="right">1.031 ns</td>
	<td align="right">0.9646 ns</td>
	<td align="right">1.00</td>
	<td align="right">0.00</td>
</tr>
<tr>
	<td>StructEnumeration</td>
	<td align="right">386.3 ns</td>
	<td align="right">1.100 ns</td>
	<td align="right">0.9751 ns</td>
	<td align="right">1.00</td>
	<td align="right">0.00</td>
</tr>
</tbody>
</table>
<h3>インターフェイス実装</h3>
<p>構造体実装なものだけでは <code>IEnumerable&lt;T&gt;</code> インターフェイスの要件を満たさないので、
別途明示的実装を足します。</p>
<p>このとき、実装要件を満たすだけなら <code>IEnumerator&lt;T&gt; IEnumerable&lt;T&gt; GetEnumerator() =&gt; GetEnumerator();</code> (構造体実装の <code>GetEnumerator</code> を素通しするだけ)でも構いません。
ただ、構造体をインターフェイス化して使うとかえって遅くて、
少しでもパフォーマンスを上げたりならクラスで作り直す方がよかったりします。</p>
<pre class="source" title="インターフェイス実装">
<code><span class="reserved">public</span> <span class="reserved">partial</span> <span class="reserved">struct</span> <span class="type">ArrayWrapper</span>&lt;<span class="type">T</span>&gt; : <span class="type">IEnumerable</span>&lt;<span class="type">T</span>&gt;
{
    <span class="type">IEnumerator</span>&lt;<span class="type">T</span>&gt; <span class="type">IEnumerable</span>&lt;<span class="type">T</span>&gt;.GetEnumerator() =&gt; <span class="reserved">new</span> <span class="type">EnumeratorObject</span>(Array);
    <span class="type">IEnumerator</span> <span class="type">IEnumerable</span>.GetEnumerator() =&gt; <span class="reserved">new</span> <span class="type">EnumeratorObject</span>(Array);
 
    <span class="comment">// 構造体の Enumerator と中身は全く同じで、ただクラスになってるだけ。</span>
    <span class="comment">// 構造体をインターフェイス越しに返すとかえって遅くなるので、こんなクラスが別途必要に…</span>
    <span class="reserved">public</span> <span class="reserved">class</span> <span class="type">EnumeratorObject</span> : <span class="type">IEnumerator</span>&lt;<span class="type">T</span>&gt;
    {
        <span class="reserved">private</span> <span class="reserved">readonly</span> <span class="type">T</span>[] _array;
        <span class="reserved">private</span> <span class="reserved">int</span> _i;
        <span class="reserved">internal</span> EnumeratorObject(<span class="type">T</span>[] array) =&gt; (_array, _i) = (array, -1);
 
        <span class="reserved">public</span> <span class="type">T</span> Current =&gt; _array[_i];
        <span class="reserved">public</span> <span class="reserved">bool</span> MoveNext() =&gt; ((<span class="reserved">uint</span>)++_i) &lt; (<span class="reserved">uint</span>)_array.Length;
 
        <span class="reserved">object</span> <span class="type">IEnumerator</span>.Current =&gt; Current;
        <span class="reserved">public</span> <span class="reserved">void</span> Dispose() { }
        <span class="reserved">public</span> <span class="reserved">void</span> Reset() =&gt; <span class="reserved">throw</span> <span class="reserved">new</span> <span class="type">NotImplementedException</span>();
    }
}
 
<span class="reserved">public</span> <span class="reserved">partial</span> <span class="reserved">class</span> <span class="type">ArrayEnumerationBenchmark</span>
{
    <span class="comment">// インターフェイス越し列挙になるように、IEnumerable&lt;T&gt; にキャストして使ってる。</span>
    <span class="comment">// びっくりするくらい遅い。</span>
    <span class="comment">// StructEnumeration とかに比べて10倍遅い。</span>
    [<span class="type">Benchmark</span>]
    <span class="reserved">public</span> <span class="reserved">int</span> InterfaceEnumeration()
    {
        <span class="reserved">var</span> sum = 0;
        <span class="reserved">foreach</span> (<span class="reserved">var</span> x <span class="reserved">in</span> (<span class="type">IEnumerable</span>&lt;<span class="reserved">int</span>&gt;)_array) sum += x;
        <span class="reserved">return</span> sum;
    }
}
</code></pre>
<p>構造体/具象型実装が配列生列挙とそん色ないのに対して、
こいつは10倍以上遅いです。
それでも、別途クラスで実装した方がちょっとだけマシ。</p>
<table>
<thead>
<tr>
	<th>Method</th>
	<th align="right">Mean</th>
	<th align="right">Error</th>
	<th align="right">StdDev</th>
	<th align="right">Ratio</th>
	<th align="right">RatioSD</th>
</tr>
</thead>
<tbody>
<tr>
	<td>RawEnumeration</td>
	<td align="right">385.6 ns</td>
	<td align="right">1.031 ns</td>
	<td align="right">0.9646 ns</td>
	<td align="right">1.00</td>
	<td align="right">0.00</td>
</tr>
<tr>
	<td>StructEnumeration</td>
	<td align="right">386.3 ns</td>
	<td align="right">1.100 ns</td>
	<td align="right">0.9751 ns</td>
	<td align="right">1.00</td>
	<td align="right">0.00</td>
</tr>
<tr>
	<td>InterfaceEnumeration</td>
	<td align="right">4,407.3 ns</td>
	<td align="right">14.790 ns</td>
	<td align="right">13.8350 ns</td>
	<td align="right">11.43</td>
	<td align="right">0.05</td>
</tr>
</tbody>
</table>
<h2>出来合いの型</h2>
<p>おまけで、出来合いの型を被せて返すのもやっておきます。</p>
<h3>ReadOnlyCollection</h3>
<p>配列を生で返したくない状況の1つが、書き換えを認めたくない場合です。
そういう場合、
<code>ReadOnlyCollection&lt;T&gt;</code> クラス(<code>System.Collections.ObjectModel</code> 名前空間)を使ったりします。</p>
<p>ただ、このクラス、<code>IList&lt;T&gt;</code> 向けなので、
配列だけでいいときには余計(繰り返しますが、インターフェイス越しは遅い)ですし、
.NET Framework 2.0 時代からあってパフォーマンスへの考慮はあんまりない型です。
要するに、遅い…</p>
<pre class="source" title="ReadOnlyCollection 越しの列挙">
<code><span class="reserved">public</span> <span class="reserved">partial</span> <span class="reserved">struct</span> <span class="type">ArrayWrapper</span>&lt;<span class="type">T</span>&gt;
{
    <span class="reserved">public</span> <span class="type">ReadOnlyCollection</span>&lt;<span class="type">T</span>&gt; AsReadOnlyCollection() =&gt; <span class="reserved">new</span> <span class="type">ReadOnlyCollection</span>&lt;<span class="type">T</span>&gt;(Array);
}
 
<span class="reserved">public</span> <span class="reserved">partial</span> <span class="reserved">class</span> <span class="type">ArrayEnumerationBenchmark</span>
{
    <span class="comment">// ReadOnlyCollection&lt;T&gt; 列挙。</span>
    <span class="comment">// InterfaceEnumeration 以上に遅い。とにかく遅い。</span>
    <span class="comment">// ReadOnlyCollection&lt;T&gt; は内部的に IList&lt;T&gt; 越しに配列アクセスするので、それがほんとに遅い。</span>
    [<span class="type">Benchmark</span>]
    <span class="reserved">public</span> <span class="reserved">int</span> ReadOnlyCollectionEnumeration()
    {
        <span class="reserved">var</span> sum = 0;
        <span class="reserved">foreach</span> (<span class="reserved">var</span> x <span class="reserved">in</span> _array.AsReadOnlyCollection()) sum += x;
        <span class="reserved">return</span> sum;
    }
}
</code></pre>
<table>
<thead>
<tr>
	<th>Method</th>
	<th align="right">Mean</th>
	<th align="right">Error</th>
	<th align="right">StdDev</th>
	<th align="right">Ratio</th>
	<th align="right">RatioSD</th>
</tr>
</thead>
<tbody>
<tr>
	<td>RawEnumeration</td>
	<td align="right">385.6 ns</td>
	<td align="right">1.031 ns</td>
	<td align="right">0.9646 ns</td>
	<td align="right">1.00</td>
	<td align="right">0.00</td>
</tr>
<tr>
	<td>StructEnumeration</td>
	<td align="right">386.3 ns</td>
	<td align="right">1.100 ns</td>
	<td align="right">0.9751 ns</td>
	<td align="right">1.00</td>
	<td align="right">0.00</td>
</tr>
<tr>
	<td>InterfaceEnumeration</td>
	<td align="right">4,407.3 ns</td>
	<td align="right">14.790 ns</td>
	<td align="right">13.8350 ns</td>
	<td align="right">11.43</td>
	<td align="right">0.05</td>
</tr>
<tr>
	<td>ReadOnlyCollectionEnumeration</td>
	<td align="right">5,199.8 ns</td>
	<td align="right">21.591 ns</td>
	<td align="right">20.1960 ns</td>
	<td align="right">13.48</td>
	<td align="right">0.07</td>
</tr>
</tbody>
</table>
<h3>Span</h3>
<p>まあ、今なら、特に .NET Core を使えるのであれば、
<code>ReadOnlySpan&lt;T&gt;</code> 構造体 (<code>System</code> 名前空間)を使うのがいいと思います。
<code>Span&lt;T&gt;</code> と同様最適化が掛かるので、
書き換えを防止しつつ、配列の生列挙とそん色ない速度が出ます。</p>
<pre class="source" title="ReadOnlySpan 越しの列挙">
<code><span class="reserved">public</span> <span class="reserved">partial</span> <span class="reserved">struct</span> <span class="type">ArrayWrapper</span>&lt;<span class="type">T</span>&gt;
{
    <span class="comment">// インデクサーも使いたいとき用、その2。</span>
    <span class="comment">// Span&lt;T&gt; を介してみる。</span>
    <span class="comment">// パフォーマンスに焦点が当たってた .NET Core 2.1 世代の型だけあって、かなり速い。</span>
    <span class="reserved">public</span> <span class="type">ReadOnlySpan</span>&lt;<span class="type">T</span>&gt; AsSpan() =&gt; Array;
}
 
<span class="reserved">public</span> <span class="reserved">partial</span> <span class="reserved">class</span> <span class="type">ArrayEnumerationBenchmark</span>
{
    <span class="comment">// Span&lt;T&gt; 列挙</span>
    <span class="comment">// こいつも配列生列挙とほぼ同じ性能。速い。</span>
    [<span class="type">Benchmark</span>]
    <span class="reserved">public</span> <span class="reserved">int</span> SpanEnumeration()
    {
        <span class="reserved">var</span> sum = 0;
        <span class="reserved">foreach</span> (<span class="reserved">var</span> x <span class="reserved">in</span> _array.AsSpan()) sum += x;
        <span class="reserved">return</span> sum;
    }
}
</code></pre>
<table>
<thead>
<tr>
	<th>Method</th>
	<th align="right">Mean</th>
	<th align="right">Error</th>
	<th align="right">StdDev</th>
	<th align="right">Ratio</th>
	<th align="right">RatioSD</th>
</tr>
</thead>
<tbody>
<tr>
	<td>RawEnumeration</td>
	<td align="right">385.6 ns</td>
	<td align="right">1.031 ns</td>
	<td align="right">0.9646 ns</td>
	<td align="right">1.00</td>
	<td align="right">0.00</td>
</tr>
<tr>
	<td>StructEnumeration</td>
	<td align="right">386.3 ns</td>
	<td align="right">1.100 ns</td>
	<td align="right">0.9751 ns</td>
	<td align="right">1.00</td>
	<td align="right">0.00</td>
</tr>
<tr>
	<td>InterfaceEnumeration</td>
	<td align="right">4,407.3 ns</td>
	<td align="right">14.790 ns</td>
	<td align="right">13.8350 ns</td>
	<td align="right">11.43</td>
	<td align="right">0.05</td>
</tr>
<tr>
	<td>ReadOnlyCollectionEnumeration</td>
	<td align="right">5,199.8 ns</td>
	<td align="right">21.591 ns</td>
	<td align="right">20.1960 ns</td>
	<td align="right">13.48</td>
	<td align="right">0.07</td>
</tr>
<tr>
	<td>SpanEnumeration</td>
	<td align="right">385.0 ns</td>
	<td align="right">1.612 ns</td>
	<td align="right">1.5079 ns</td>
	<td align="right">1.00</td>
	<td align="right">0.00</td>
</tr>
</tbody>
</table>
<h2><code>Span&lt;T&gt;</code> の利用率アップ</h2>
<p>ここまでの説明の通り下手すると10倍性能が違ったりするので、
.NET Core 2.1 が出て以降、
<code>Span&lt;T&gt;</code>や<code>ReadOnlySpan&lt;T&gt;</code>を引数に取るAPIが増えていたりします。
<code>IEnumerable&lt;T&gt;</code>や<code>IList&lt;T&gt;</code>が減って。</p>
<p>そうなると、既存のコレクションに対しても、「可能なもの(内部的に配列とか連続したデータになってるやつ)は<code>Span</code>で取りたい」という要求がかなり高くなっています。</p>
<p>が、既存の型を改修してもらえるまで待てないという人も… 
<code>Unsafe</code> な手段で無理やり中身の配列を取得して、
無理やり <code>Span</code> にしてしまったり…</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/pull/31785">Add Span and Memory conversion methods for ImmutableArray</a></li>
</ul>
<p>過渡的な手段とはいえ、結構邪悪です。
以下のようなコード。</p>
<pre class="source" title="ImmurableArray を無理やり配列に変換">
<code>[<span class="type">StructLayout</span>(<span class="type">LayoutKind</span>.Sequential)]
<span class="reserved">private</span> <span class="reserved">struct</span> <span class="type">ImmutableArrayProxy</span>&lt;<span class="type">T</span>&gt;
{
    <span class="reserved">internal</span> <span class="type">T</span>[] MutableArray;
}
 
<span class="reserved">internal</span> <span class="reserved">static</span> <span class="type">T</span>[] DangerousGetUnderlyingArray&lt;<span class="type">T</span>&gt;(<span class="reserved">this</span> <span class="type">ImmutableArray</span>&lt;<span class="type">T</span>&gt; array)
     =&gt; <span class="type">Unsafe</span>.As&lt;<span class="type">ImmutableArray</span>&lt;<span class="type">T</span>&gt;, <span class="type">ImmutableArrayProxy</span>&lt;<span class="type">T</span>&gt;&gt;(<span class="reserved">ref</span> array).MutableArray;
</code></pre>
<p>また、<code>Span</code>を使うと、中身を参照で外に漏らしちゃうことになるので、
ちょっと変な挙動をすることがあります。
以下のようなコードには注意を。</p>
<pre class="source" title="Span で中身を返す場合の注意点">
<code><span class="reserved">using</span> System;
 
<span class="comment">// System.Collections.Generic.List&lt;T&gt; と同じような実装 + AsSpan</span>
<span class="reserved">class</span> <span class="type">List</span>&lt;<span class="type">T</span>&gt;
{
    <span class="reserved">private</span> <span class="type">T</span>[] _buffer;
    <span class="reserved">private</span> <span class="reserved">int</span> _count;
    <span class="reserved">public</span> List(<span class="reserved">int</span> capacity) =&gt; _buffer = <span class="reserved">new</span> <span class="type">T</span>[capacity];
 
    <span class="reserved">public</span> <span class="reserved">ref</span> <span class="type">T</span> <span class="reserved">this</span>[<span class="reserved">int</span> index] =&gt; <span class="reserved">ref</span> _buffer[index];
    <span class="reserved">public</span> <span class="type">ReadOnlySpan</span>&lt;<span class="type">T</span>&gt; AsSpan() =&gt; _buffer.AsSpan(0, _count);
 
    <span class="reserved">public</span> <span class="reserved">void</span> Add(<span class="type">T</span> item)
    {
        <span class="reserved">if</span>(_count == _buffer.Length)
        {
            <span class="reserved">var</span> newBuffer = <span class="reserved">new</span> <span class="type">T</span>[_buffer.Length * 2];
            _buffer.AsSpan().CopyTo(newBuffer);
            _buffer = newBuffer;
        }
        _buffer[_count++] = item;
    }
}
 
<span class="reserved">public</span> <span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> Main()
    {
        <span class="reserved">var</span> list = <span class="reserved">new</span> <span class="type">List</span>&lt;<span class="reserved">int</span>&gt;(2);
        list.Add(1);
        list.Add(2);
        <span class="comment">// この時点で容量満杯</span>
 
        <span class="comment">// Span 取得してから…</span>
        <span class="reserved">var</span> span = list.AsSpan();
 
        list.Add(3);  <span class="comment">// Add で内部バッファーの再確保が発生</span>
        list[0] = 99; <span class="comment">// 新しいバッファーへの書き込み</span>
 
        <span class="type">Console</span>.WriteLine(span[0]); <span class="comment">// 古いバッファーを参照してるので 1 のまま</span>
        <span class="type">Console</span>.WriteLine(list[0]); <span class="comment">// 新しいバッファーを参照してるので 99</span>
    }
}
</code></pre>
<h2>まとめ</h2>
<ul>
<li><code>GetEnumerator</code> を実装するなら、専用の構造体をまず考える</li>
<li>それとは別に、<code>IEnumerable&lt;T&gt;.GetEnumerator</code> を明示的実装</li>
<li>
<code>Span&lt;T&gt;</code>/<code>ReadOnlySpan&lt;T&gt;</code> 速い
<ul>
<li>ので、パフォーマンス的には <code>Span</code> を使いたい</li>
<li>でも、参照が外に漏れるので注意</li>
</ul>
</li>
</ul>
 ]]></description>
				<pubDate>Thu, 20 Dec 2018 10:06:39 +0900</pubDate>
			</item>
			<item>
				<title>IEnumerator の別実装</title>
				<link>http://ufcpp.net/blog/2018/12/fastenumerator/</link>
				<description><![CDATA[ <p><a href="/blog/2018/12/devirtualization/">Devirtualization 最適化</a>の話で仮想呼び出しのコストの話もしました。
そこでもう1つ思い出してほしいのが、<a href="/blog/2018/12/cs8asyncstreams/">C# 8.0 Async streams</a>で書いた、
<code>IAsyncEnumerator&lt;T&gt;</code>インターフェイスの話。
最終的な決定としては以下のような API を持っています。</p>
<pre class="source" title="最終決定時の IAsyncEnumerator">
<code><span class="reserved">public</span> <span class="reserved">interface</span> <span class="type">IAsyncEnumerator</span>&lt;<span class="reserved">out</span> <span class="type">T</span>&gt;
{
    <span class="type">T</span> Current { <span class="reserved">get</span>; }
    <span class="type">ValueTask</span>&lt;<span class="reserved">bool</span>&gt; MoveNextAsync();
}
</code></pre>
<p>一方で、検討段階では以下のような API も考えられていました。</p>
<pre class="source" title="検討段階の IAsyncEnumerator">
<code><span class="reserved">public</span> <span class="reserved">interface</span> <span class="type">IAsyncEnumerator</span>&lt;<span class="reserved">out</span> <span class="type">T</span>&gt;
{
    <span class="type">ValueTask</span>&lt;<span class="reserved">bool</span>&gt; WaitForNextAsync();
    <span class="type">T</span> TryGetNext(<span class="reserved">out</span> <span class="reserved">bool</span> success);
}

</code></pre>
<p>今日はこの後者のメリットについての話。</p>
<p>参考コード: <a href="https://github.com/ufcpp/UfcppSample/tree/master/Demo/2018/PerformanceTips/FastEnumeration">FastEnumeration</a></p>
<h2>IEnumerator 版</h2>
<p>同様の話は実は <code>IEnumerator&lt;T&gt;</code> にも言えます。
正確に言えば <code>IAsyncEnumerator&lt;T&gt;</code> の方が <code>WaitForNextAsync</code> を持っている分だけ複雑なんですが、とりあえず単純化のために <code>IEnumerator&lt;T&gt;</code> で話を進めます。</p>
<p><code>IEnumerator&lt;T&gt;</code> インターフェイス(<code>System.Collections.Generic</code>名前空間)は、
歴史的経緯から非ジェネリックな <code>IEnumerator</code> インターフェイス(<code>System.Collections</code>名前空間)からの派生になっていますが、
そういう歴史的経緯を抜いて考えれば以下のような API を持つインターフェイスです。</p>
<pre class="source" title="IEnumerator インターフェイスの本質">
<code><span class="reserved">public</span> <span class="reserved">interface</span> <span class="type">IEnumerator</span>&lt;<span class="reserved">out</span> <span class="type">T</span>&gt;
{
    <span class="reserved">bool</span> MoveNext();
    <span class="type">T</span> Current { <span class="reserved">get</span>; }
}
</code></pre>
<p>一方、冒頭で上げた検討段階の <code>IAsyncEnumerator&lt;T&gt;</code> と同じ考え方で、
以下のような API での実装が考えられます。
(区別のために名前をちょっと変えて、<code>IFastEnumerator</code> にしています。)</p>
<pre class="source" title="IEnumerator の構造はこっちの方がよかったかもしれない">
<code><span class="reserved">interface</span> <span class="type">IFastEnumerator</span>&lt;<span class="reserved">out</span> <span class="type">T</span>&gt;
{
    <span class="type">T</span> TryMoveNext(<span class="reserved">out</span> <span class="reserved">bool</span> success);
}
</code></pre>
<p>要するに、<code>MoveNext</code>と<code>Current</code>に分かれている機能を、1つのメソッドにまとめた方がいいのではないかという話です。</p>
<p>(.NET のジェネリクスでは、<a href="/study/csharp/sp_ref.html#out">out 引数</a>を<a href="/study/csharp/sp4_variance.html#covariance">共変</a>にできないという嫌な制限があるので、<code>success</code> の方が out 引数になっています。
可能であれば <code>bool TryMoveNext(out T current)</code> にしたいものです。
とりあえずそこは今回関係なく、あくまで「メソッドを1つにしたい」というところが今回の話の本質です。)</p>
<h2>仮想呼び出しのコスト</h2>
<p>まあ、冒頭で仮想呼び出しのコストの話を振っているのでどういう問題なのか察してもらえると思います。
単純に、そこそこコストが掛かる仮想呼び出しを2回に分けたくないという話です。</p>
<p><code>foreach</code> が含まれるメソッドはたいてい<a href="/study/csharp/structured/miscinlining/">インライン展開</a>されません。
そうなると devirtualization 最適化は大体かからなくなるんですが、
なので、<code>MoveNext</code>/<code>Current</code> には普通に仮想呼び出しのコストが掛かります。
結果、仮想呼び出しが2回。
一方の <code>IFastEnumerator&lt;T&gt;</code> であれば、仮想呼び出しは <code>TryMoveNext</code> の1回だけです。</p>
<p>ということで、どのくらい変わるか<a href="https://github.com/ufcpp/UfcppSample/tree/master/Demo/2018/FastEnumeration/FastEnumeration">ベンチマーク</a>を用意しました。</p>
<p>配列の中身を列挙するだけのクラスを2つ用意します。
片方は <code>IEnumerator&lt;T&gt;</code> 実装(本題に関係するところだけ抜き出し)。</p>
<pre class="source" title="IEnumerator 実装">
<code><span class="reserved">class</span> <span class="type">NormalEnumerator</span> : <span class="type">IEnumerator</span>&lt;<span class="reserved">int</span>&gt;
{
    <span class="reserved">private</span> <span class="reserved">readonly</span> <span class="reserved">int</span>[] _data;
    <span class="reserved">private</span> <span class="reserved">int</span> _i = -1;
 
    <span class="reserved">public</span> <span class="reserved">int</span> Current =&gt; _data[_i];
    <span class="reserved">public</span> <span class="reserved">bool</span> MoveNext() =&gt; ++_i &lt; _data.Length;
}
</code></pre>
<p>もう一方は <code>IFastEnumerator&lt;T&gt;</code> 実装。</p>
<pre class="source" title="IFastEnumerator 実装">
<code><span class="reserved">class</span> <span class="type">FastEnumerator</span> : <span class="type">IFastEnumerator</span>&lt;<span class="reserved">int</span>&gt;
{
    <span class="reserved">private</span> <span class="reserved">readonly</span> <span class="reserved">int</span>[] _data;
    <span class="reserved">private</span> <span class="reserved">int</span> _i = -1;
 
    <span class="reserved">public</span> <span class="reserved">int</span> TryMoveNext(<span class="reserved">out</span> <span class="reserved">bool</span> success)
    {
        <span class="reserved">var</span> i = ++_i;
        <span class="reserved">var</span> data = _data;
        <span class="reserved">if</span> ((<span class="reserved">uint</span>)i &lt; (<span class="reserved">uint</span>)data.Length)
        {
            success = <span class="reserved">true</span>;
            <span class="reserved">return</span> data[i];
        }
        <span class="reserved">else</span>
        {
            success = <span class="reserved">false</span>;
            <span class="reserved">return</span> <span class="reserved">default</span>;
        }
    }
}

</code></pre>
<p>これに対して以下のようなループを回します。
(<code>IEnumerator</code> 版の方は、まんま、<code>foreach</code> の展開結果です。)</p>
<pre class="source" title="インターフェイスを介して呼ぶと MoveNext/Current のコストが気になる">
<code><span class="reserved">static</span> <span class="reserved">int</span> VirtualSum(<span class="type">IEnumerator</span>&lt;<span class="reserved">int</span>&gt; e)
{
    <span class="reserved">var</span> sum = 0;
    <span class="reserved">while</span> (e.MoveNext())
    {
        <span class="reserved">var</span> x = e.Current;
        sum += x;
    }
    <span class="reserved">return</span> sum;
}

<span class="comment">// IFastEnumerator の方が1.5倍くらい速い。</span>
<span class="reserved">static</span> <span class="reserved">int</span> VirtualSum(<span class="type">IFastEnumerator</span>&lt;<span class="reserved">int</span>&gt; e)
{
    <span class="reserved">var</span> sum = 0;
    <span class="reserved">while</span> (<span class="reserved">true</span>)
    {
        <span class="reserved">var</span> x = e.TryMoveNext(<span class="reserved">out</span> <span class="reserved">var</span> success);
        <span class="reserved">if</span> (!success) <span class="reserved">break</span>;
        sum += x;
    }
    <span class="reserved">return</span> sum;
}

</code></pre>
<p>これの結果は、<code>IFastEnumerator</code> 版の方が1.5倍くらい高速です。
<code>TryMoveNext</code> の方が複雑なコードになりがちなので最適化も効きにくいんですが、
それ以上に仮想呼び出しのコストが高くて、<code>TryMoveNext</code> の方が速くなります。</p>
<h2>インターフェイスをやめてしまえば…</h2>
<p>ちなみに、あくまでこれは仮想呼び出しのコストの問題なので、
以下のように、インターフェイスを介さず具象クラスで呼ぶと、
むしろ <code>MoveNext</code>/<code>Current</code> 型の方が速くなります。</p>
<pre class="source" title="具象型で呼ぶと別に MoveNext/Current のコストは気にならない">
<code><span class="comment">// さっきとの違いは引数の型だけ。</span>
<span class="comment">// IEnumerator インターフェイスだったのを、NormalEnumerator クラスに変えただけ。</span>
<span class="comment">// この場合は普通にこっちの方が速い。</span>
<span class="reserved">static</span> <span class="reserved">int</span> NonVirtualSum(<span class="type">NormalEnumerator</span> e)
{
    <span class="reserved">var</span> sum = 0;
    <span class="reserved">while</span> (e.MoveNext())
    {
        <span class="reserved">var</span> x = e.Current;
        sum += x;
    }
    <span class="reserved">return</span> sum;
}
 
<span class="comment">// 同じく、IFastEnumerator インターフェイスを FastEnumerator クラスに変えただけ。</span>
<span class="reserved">static</span> <span class="reserved">int</span> NonVirtualSum(<span class="type">FastEnumerator</span> e)
{
    <span class="reserved">var</span> sum = 0;
    <span class="reserved">while</span> (<span class="reserved">true</span>)
    {
        <span class="reserved">var</span> x = e.TryMoveNext(<span class="reserved">out</span> <span class="reserved">var</span> success);
        <span class="reserved">if</span> (!success) <span class="reserved">break</span>;
        sum += x;
    }
    <span class="reserved">return</span> sum;
}
</code></pre>
<p>とはいえ、汎用性がなくなるので具象クラスで受け渡しするのはちょっとつらいです。
ジェネリクスを使えば多少緩和はされるんですが…</p>
<pre class="source" title="ジェネリック版">
<code><span class="comment">// ジェネリクスを使えば、構造体の時には仮想呼び出しが消える。</span>
<span class="comment">// (構造体限定。クラスの時は別に仮想呼び出しは消えない。)</span>
<span class="reserved">static</span> <span class="reserved">int</span> GenericSum&lt;<span class="type">T</span>&gt;(<span class="type">T</span> e)
    <span class="reserved">where</span> <span class="type">T</span> : <span class="type">IEnumerator</span>&lt;<span class="reserved">int</span>&gt;
{
    <span class="reserved">var</span> sum = 0;
    <span class="reserved">while</span> (e.MoveNext())
    {
        <span class="reserved">var</span> x = e.Current;
        sum += x;
    }
    <span class="reserved">return</span> sum;
}
</code></pre>
<p>速くなる(仮想呼び出しが消える)のは構造体限定です。
しかもなお悪いことに、<code>foreach</code> は、<code>GetEnumerator</code> を介する構造なので、
普通にやるとどうやっても仮想呼び出しが消えません。</p>
<pre class="source" title="foreach はどうやっても仮想呼び出しが残る">
<code><span class="reserved">static</span> <span class="reserved">int</span> Sum&lt;<span class="type">T</span>&gt;(<span class="type">T</span> items)
    <span class="reserved">where</span> <span class="type">T</span> : <span class="type">IEnumerable</span>&lt;<span class="reserved">int</span>&gt;
{
    <span class="reserved">var</span> sum = 0;
    <span class="reserved">foreach</span> (<span class="reserved">var</span> x <span class="reserved">in</span> items) sum += x;
    <span class="reserved">return</span> sum;
} 
<span class="comment">// ↑は↓みたいに展開される</span>
<span class="reserved">static</span> <span class="reserved">int</span> Sum_&lt;<span class="type">T</span>&gt;(<span class="type">T</span> items)
    <span class="reserved">where</span> <span class="type">T</span> : <span class="type">IEnumerable</span>&lt;<span class="reserved">int</span>&gt;
{
    <span class="reserved">var</span> sum = 0;
 
    <span class="comment">// この GetEnumerator の仮想呼び出しは消える可能性があるものの…</span>
    <span class="type">IEnumerator</span>&lt;<span class="reserved">int</span>&gt; e = items.GetEnumerator();
    <span class="reserved">try</span>
    {
        <span class="comment">// 結局ここの MoveNext/Current はインターフェイス越し。</span>
        <span class="comment">// 必ず仮想呼び出しになる。</span>
        <span class="reserved">while</span> (e.MoveNext())
        {
            <span class="reserved">var</span> x = e.Current;
            sum += x;
        }
    }
    <span class="reserved">finally</span>
    {
        <span class="reserved">if</span> (e <span class="reserved">is</span> <span class="type">IDisposable</span> d) d.Dispose();
    }
    <span class="reserved">return</span> sum;
}
</code></pre>
<p>ということで、<code>foreach</code> 中の <code>MoveNext</code>/<code>Current</code> の仮想呼び出しはなかなか消せなかったりします。
なのでなおのこと、1回で済む <code>TryMoveNext</code> 型のインターフェイスがよかったかもしれない、という話になったりします。</p>
 ]]></description>
				<pubDate>Wed, 19 Dec 2018 10:00:28 +0900</pubDate>
			</item>
			<item>
				<title>Guarded Devirtualization</title>
				<link>http://ufcpp.net/blog/2018/12/guardeddevirtualization/</link>
				<description><![CDATA[ <p>今日はちょっと将来の話。
提案ドキュメントとか予備実験的な実装はあるんですが、
リリースされる時期については未定のものです。</p>
<p>Guarded Devirtualization という最適化手法。</p>
<ul>
<li>参考: <a href="https://github.com/dotnet/coreclr/issues/14223">JIT: see if guarded devirtualization for EqualityComparer methods pays off</a></li>
</ul>
<p>(余談ですが、<a href="https://github.com/AndyAyersMS/coreclr/blob/d35d4dd64a4e1b1ba67f3c804cabcfaa1094b678/Documentation/design-docs/GuardedDevirtualization.md">この提案に当たっての調査レポート</a>、ものすごく丁寧で良い内容です。
何かを提案する際の理想形。)</p>
<h2>Devirtualization の実情</h2>
<p>昨日の<a href="/blog/2018/12/devirtualization/">Devirtualization 最適化</a>の話で書きましたが、
仮想呼び出しを通常のメソッド呼び出しに置き換える最適化があって、これを devirtualization といいます。</p>
<p>ただ、devirtualization できる状況はかなり限られています。
coreclr 内で統計を取ってみたところ、クラスの仮想メソッドの呼び出ししているところのうち15%程度しか、devirtualization 最適化が掛からないそうです。
インターフェイスを介しているものについてはもっときつくて、5%程度だそうです。</p>
<p>なんせ、devirtualization が有効になるためには、「メソッド内をさかのぼれば静的な型が1つに確定している」という状態でないといけない。
それに対して、実際のところ多い状況は、
「ほとんどの場合には決まったある1つの型のが来るものの、まれに別の型が来る」というものです。</p>
<h2>if + Devirtualization</h2>
<p>そこで、最頻で来てそうな1つ(あるいはせいぜい数個)の型に対してだけ <code>if</code> を挟んでしまうという最適化が考えられます。</p>
<p>例えば、以下のようないくつかの型があったとして</p>
<pre class="source">
<code><span class="reserved">interface</span> <span class="type">I</span> { <span class="reserved">void</span> M(); }
<span class="reserved">struct</span> <span class="type">A1</span> : <span class="type">I</span> { <span class="reserved">public</span> <span class="reserved">void</span> M() { } }
<span class="reserved">struct</span> <span class="type">A2</span> : <span class="type">I</span> { <span class="reserved">public</span> <span class="reserved">void</span> M() { } }
<span class="reserved">struct</span> <span class="type">A3</span> : <span class="type">I</span> { <span class="reserved">public</span> <span class="reserved">void</span> M() { } }
<span class="reserved">struct</span> <span class="type">A4</span> : <span class="type">I</span> { <span class="reserved">public</span> <span class="reserved">void</span> M() { } }
</code></pre>
<p>以下のような呼び出しを考えます。</p>
<pre class="source">
<code><span class="reserved">static</span> <span class="reserved">void</span> M(<span class="type">I</span>[] items)
{
    <span class="reserved">foreach</span> (<span class="reserved">var</span> i <span class="reserved">in</span> items)
    {
        i.M();
    }
}
</code></pre>
<p>何の前提もないと、このコードは最適化のやりようがないんですが、
例えば、
「ほとんどの場合に<code>A1</code>～<code>A4</code>の構造体が来る。他の型が来る率は低い」、
「その中でも<code>A1</code>の頻度が特に高い」みたいな前提が入ると、
以下のようなコードが速くなったりします。</p>
<pre class="source">
<code><span class="reserved">static</span> <span class="reserved">void</span> M(<span class="type">I</span>[] items)
{
    <span class="reserved">foreach</span> (<span class="reserved">var</span> i <span class="reserved">in</span> items)
    {
        <span class="reserved">if</span> (i.GetType() == <span class="reserved">typeof</span>(<span class="type">A1</span>)) ((<span class="type">A1</span>)i).M();
        <span class="reserved">else</span> <span class="reserved">if</span> (i.GetType() == <span class="reserved">typeof</span>(<span class="type">A2</span>)) ((<span class="type">A2</span>)i).M();
        <span class="reserved">else</span> <span class="reserved">if</span> (i.GetType() == <span class="reserved">typeof</span>(<span class="type">A3</span>)) ((<span class="type">A3</span>)i).M();
        <span class="reserved">else</span> <span class="reserved">if</span> (i.GetType() == <span class="reserved">typeof</span>(<span class="type">A4</span>)) ((<span class="type">A4</span>)i).M();
        <span class="reserved">else</span> i.M();
    }
}
</code></pre>
<p>数個程度の <code>if</code> 分岐であれば仮想呼び出しのコストよりも安くなります。
特に、発生確率に偏りがある場合には分岐予測が効くので、
「ほとんどが<code>A1</code>」みたいな状況では分岐のコストがほぼ消えます。
また、メソッド <code>M</code> の実装がインライン展開可能なものだった場合、
インライン展開の効果でかなり速くなります。</p>
<p><a href="https://github.com/ufcpp/UfcppSample/blob/master/Demo/2018/GuardedDevirt/GuardedDevirt/CallBenchmark.cs#L94">ベンチマーク</a>を取ってみた感じ、
普通に <code>i.M()</code> で仮想呼び出しするよりも、3倍くらい高速です。</p>
<p>ということで、こういう「よく来る型」を実行時に検出して、上記のような<code>if</code>分岐を生成するような最適化を CoreCLR に入れたいみたいです。
「ほとんどが <code>A1</code>」という予想が外れたときのための“防護策”(guard)として<code>if</code>挿入するので、
Guarded Devirtualization と呼ばれます。</p>
 ]]></description>
				<pubDate>Tue, 18 Dec 2018 09:32:09 +0900</pubDate>
			</item>
			<item>
				<title>Devirtualization (脱仮想化)</title>
				<link>http://ufcpp.net/blog/2018/12/devirtualization/</link>
				<description><![CDATA[ <p>今日は一般論として「仮想メソッドは避けれるなら避けたい」という話と、
.NET Core 2.1 で仮想メソッドの「devirtualization」(脱仮想化)のための最適化が入っているという話。</p>
<h2>仮想メソッドのコスト</h2>
<p>多くのプログラミング言語で、
いわゆる<a href="/study/csharp/oo_polymorphism.html">多態的な動作</a>の実現のために、
仮想呼び出し(virtual call)という機能が提供されています。
仮想呼び出しは、<a href="/study/csharp/oo_vftable.html">仮想関数テーブル</a>を使った実装が一般的です。</p>
<p>テーブルを使った実装には以下のような利点があります。</p>
<ul>
<li>後からクラスが増えても呼び出し側コードには変更が必要ない</li>
<li>分岐の数がどれだけ増えても呼び出しにかかる時間が一定</li>
</ul>
<p>ただし、仮想呼び出しには以下のようなコストがかかります。</p>
<ul>
<li>
テーブルを引くために間接参照が増える
<ul>
<li>ちなみに、今の .NET Coreの実装だとテーブルは2段構造になってるらしく、間接参照は2回</li>
</ul>
</li>
<li><a href="/study/csharp/structured/miscinlining/">インライン展開</a>が効かなくなる</li>
</ul>
<p>特に、インライン展開が効くか効かないかで、だいぶパフォーマンスが変わります。</p>
<p>例えば以下のようなコードを考えます。</p>
<pre class="source" title="インターフェイス越しかどうかの差">
<code><span class="reserved">interface</span> <span class="type">IValue</span> { <span class="reserved">int</span> Value { <span class="reserved">get</span>; } }
<span class="reserved">class</span> <span class="type">Impl</span> : <span class="type">IValue</span> { <span class="reserved">public</span> <span class="reserved">int</span> Value =&gt; 0; }
 
<span class="reserved">public</span> <span class="reserved">class</span> <span class="type">VirtualCallBanchmark</span>
{
    <span class="comment">// インターフェイス越し</span>
    <span class="type">IValue</span> A { <span class="reserved">get</span>; } = <span class="reserved">new</span> <span class="type">Impl</span>();
 
    <span class="comment">// クラスを直公開</span>
    <span class="type">Impl</span> B { <span class="reserved">get</span>; } = <span class="reserved">new</span> <span class="type">Impl</span>();
 
    [<span class="type">Benchmark</span>]
    <span class="reserved">public</span> <span class="reserved">int</span> Interface() =&gt; A.Value;
 
    [<span class="type">Benchmark</span>]
    <span class="reserved">public</span> <span class="reserved">int</span> Class() =&gt; B.Value;
}
</code></pre>
<p><code>Interface</code>メソッドの方は<code>IValue</code>インターフェイス越しに<code>Value</code>プロパティを参照(仮想呼び出しになるので遅い)で、
<code>Class</code>メソッドの方は具象型である<code>Impl</code>クラスを直接参照しています(仮想呼び出しが必要ないので速い)。</p>
<p>このベンチマークを実行すると、<code>Class</code>メソッドの方は「計測できないくらい何もしてない」と言われるくらい「ほぼ0時間」です。
一方、<code>Interface</code>メソッドの方には、手元の環境では 1.4ns くらいの時間が掛かりました。</p>
<p>この差はインライン展開によるもので、<code>Class</code>の方は、<code>int Class() =&gt; 0;</code> という単に定数を返すだけのメソッドに最適化されて、ほとんど何もコードが残りません。</p>
<p>1.4ns も微々たる時間ですが、このコストすらも避けたいことはよくあります。
それに、多態動作が特に必要ないなら仮想呼び出しはただ無駄なコストなので、できれば消したいものです。
なので、仮想メソッドであっても、必要がなければただのメソッド呼び出しに変換して、
インライン展開が効くようにする最適化を「devirtualization」(脱仮想化)と呼びます。</p>
<h2>.NET Core 2.1 の devirtualize 最適化</h2>
<p>ということで、.NET Core 2.1 から devirtulization 最適化が入っているみたいです。
(単純な最適化がいくつか 2.0 に対してマージされていて、ドキュメント上も 2.0 的な記述を見かけるんですが、
ベンチマークを取ってみてる感じは 2.0 ではあんまり有効じゃなさそう…)</p>
<p>以下のようなコードを書いた時、 .NET Core 2.0 以前と 2.1 以降で実行時間が大きく変わります。</p>
<pre class="source" title="devirtualization の例">
<code><span class="reserved">public</span> <span class="reserved">interface</span> <span class="type">IX</span> { <span class="reserved">void</span> M(); }
<span class="reserved">public</span> <span class="reserved">class</span> <span class="type">X</span> : <span class="type">IX</span> { <span class="reserved">public</span> <span class="reserved">void</span> M() { } }

<span class="reserved">public</span> <span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">public</span> <span class="reserved">void</span> M()
    {
        <span class="type">IX</span> x = <span class="reserved">new</span> <span class="type">X</span>();
        x.M();
    }
}
</code></pre>
<p>基本的には、この例のように、メソッド内でさかのぼれば具体的な型がわかる場合にだけ devirtualization 最適化が掛かります。
(この例の場合、<code>new X()</code>を呼んでいるところがすぐに見つかるので、<code>M</code>は<code>IX.M</code>の仮想呼び出しではなく、<code>X.M</code>を直接呼び出します。)</p>
<p>.NET Core 2.1 以降なら、このコードは devirtualization された結果、インライン展開も効きます。<code>X.M()</code> の中身が空っぽなので何も残らず、実行時間が完全に0になります。</p>
<p>また、.NET Core 2.1 では devirtualization に関係する特殊な最適化もいくつか入っています。</p>
<h3>値型のインターフェイス明示的実装</h3>
<p>devirtualization が掛かって特にうれしいのは構造体です。
構造体に対してインターフェイスを介したメソッド呼び出しをする場合、
仮想呼び出しのコストに加えて、<a href="/study/csharp/RmBoxing.html">ボックス化</a>のコストも掛かります(こっちは仮想呼び出しよりもさらにはるかに高コスト)。
devirtualization が掛かれば、ボックス化のコストももろとも最適化で消せます。</p>
<p>なので、以前にも書いたんですが、<a href="/blog/2018/3/jitoptimization2_1/">.NET Core 2.1 で、構造体のインターフェイス メソッド呼び出しに最適化が掛かりました</a>。</p>
<p>以下のような構造体があったとします。</p>
<pre class="source" title="IDisposable を実装した構造体">
<code><span class="reserved">struct</span> <span class="type">X</span> : <span class="type">IDisposable</span>
{
    <span class="reserved">public</span> <span class="reserved">bool</span> IsDisposed;
    <span class="reserved">void</span> <span class="type">IDisposable</span>.Dispose() =&gt; IsDisposed = <span class="reserved">true</span>;
}
</code></pre>
<p>で、この <code>Dispose</code> メソッドを以下のように呼び出してみます。</p>
<pre class="source" title="X 構造体の Dispose メソッド呼び出し">
<code><span class="comment">// (1) インターフェイス引数で受け取って呼ぶ</span>
<span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> Interface(<span class="type">IDisposable</span> x) =&gt; x.Dispose();
 
<span class="comment">// (2) X のまま受け取って、メソッド内でインターフェイスにキャストして呼ぶ</span>
<span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> NonGeneric(<span class="type">X</span> x) =&gt; ((<span class="type">IDisposable</span>)x).Dispose();
 
<span class="comment">// (3) ジェネリックなメソッドで受け取って呼ぶ</span>
<span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> Generic&lt;<span class="type">T</span>&gt;(<span class="type">T</span> x) <span class="reserved">where</span> <span class="type">T</span> : <span class="type">IDisposable</span> =&gt; x.Dispose();
</code></pre>
<p>(1)と(3)に関しては今も昔も変わらず、(1)が遅くて(3)が速いです。(2)についてが .NET Core 2.0 以前か 2.1 以降かで変わります。</p>
<p>.NET Core 2.0 以前だと、(2)の呼び出し方にはボックス化が掛かって遅かったんですが、
これが、.NET Core 2.1 からは devirtualization されて、(3) と同じ速度が出るようになりました。</p>
<h3>EqualityComparer.Default</h3>
<p>ジェネリックな型のインスタンスに対して等値比較する際、
<code>EqualityComparer&lt;T&gt;.Default</code>をよく使います。</p>
<pre class="source" title="EqualityComparer&lt;T&gt;.Default">
<code><span class="reserved">public</span> <span class="reserved">abstract</span> <span class="reserved">class</span> <span class="type">EqualityComparer</span>&lt;<span class="type">T</span>&gt; : <span class="type">IEqualityComparer</span>, <span class="type">IEqualityComparer</span>&lt;<span class="type">T</span>&gt;
{
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="type">EqualityComparer</span>&lt;<span class="type">T</span>&gt; Default { <span class="reserved">get</span>; } <span class="comment">// ← こいつ</span>
    <span class="reserved">public</span> <span class="reserved">abstract</span> <span class="reserved">bool</span> Equals(<span class="type">T</span> x, <span class="type">T</span> y);
    <span class="reserved">public</span> <span class="reserved">abstract</span> <span class="reserved">int</span> GetHashCode(<span class="type">T</span> obj);
}
</code></pre>
<p><code>EqualityComparer&lt;T&gt;.Default.Equals(x, y)</code>の呼び出しは、
冒頭で出した<code>IValue.Value</code>の呼び出し同様、
仮想呼び出しのコストが掛かります
(インターフェイス越しの呼び出しと同様に、抽象クラス越しの呼び出しも、仮想呼び出しが必須になります)。</p>
<p>こういう抽象クラスで戻り値を返しているものは、
通常、devirtualization 最適化の対象になりません。
これに対して、.NET Core 2.1 では、
「<code>EqualityComparer&lt;T&gt;.Default</code>を見かけたら、抽象クラスの <code>EqualityComparer&lt;T&gt;</code>ではなくて、具象クラスに差し替えて処理する」というような特殊処理が入っていて、
その結果、devirtualization が掛かります。</p>
<p>例えば以下のようなベンチマークは、手元の環境で、
.NET Core 2.0 では 0.95ns、
.NET Core 2.1 では 0.05ns と、1桁実行速度が違います。</p>
<pre class="source" title="EqualityComparer&lt;T&gt;.Default のベンチマーク">
<code><span class="reserved">public</span> <span class="reserved">class</span> <span class="type">EqualityComparerDefaultBenchmark</span>
{
    [<span class="type">Benchmark</span>]
    <span class="reserved">public</span> <span class="reserved">bool</span> IntEquals() =&gt; <span class="type">EqualityComparer</span>&lt;<span class="reserved">int</span>&gt;.Default.Equals(1, 2);
}
</code></pre> ]]></description>
				<pubDate>Mon, 17 Dec 2018 09:22:52 +0900</pubDate>
			</item>
			<item>
				<title>静的なデータの ReadOnlySpan 最適化</title>
				<link>http://ufcpp.net/blog/2018/12/staticdatareadonlyspan/</link>
				<description><![CDATA[ <p>今日は C# コンパイラーのレベルの最適化(割と最近の追加)。</p>
<p>静的な byte データ列をプログラム中で使いたいとき、どう書くのが効率良いかといいかという話になります。</p>
<h2>静的な byte データ</h2>
<p>例えば、以下のようなコードを考えます。</p>
<pre class="source" title="静的な byte データ">
<code><span class="reserved">using</span> System;
 
<span class="reserved">public</span> <span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> Main()
    {
        <span class="reserved">var</span> data = <span class="reserved">new</span> <span class="reserved">byte</span>[] { 65, 66, 67, 68, 69, 70, 71, 72 };
 
        <span class="reserved">foreach</span> (<span class="reserved">var</span> x <span class="reserved">in</span> data)
            <span class="type">Console</span>.WriteLine(x);
    }
}
</code></pre>
<p><code>data</code> の中身は全て定数です。
なので、コンパイルすると、定数として DLL 中に埋め込まれます。
コンパイル結果の DLL を適当にエディターででも開いてみると、以下のような文字列が見つかると思います。
(65～72 は <code>'A'</code>～<code>'H'</code> の文字コードです。)</p>
<p><img src="/media/1168/staticdata.png" alt="静的なデータは DLL 中に埋め込まれる" /></p>
<h2>無駄な配列生成</h2>
<p>そして、配列自体も書き換えているわけではなく、その定数を読みだしているだけです。
にもかかわらず、このコードは配列のインスタンスが作られます(ヒープを使っちゃう)。
<code>data</code> を初期化する行は、概ね以下のような命令列になります。</p>
<pre class="source">
<code><span style="color:purple">IL_0000:</span> <span style="color:blue">ldc.i4.8</span>
<span style="color:purple">IL_0001:</span> <span style="color:blue">newarr</span> [mscorlib]System.Byte
<span style="color:purple">IL_0007:</span> <span style="color:blue">ldtoken</span> field int64 フィールド名割愛
<span style="color:purple">IL_000c:</span> <span style="color:blue">call</span> void 中略::InitializeArray(略)
</code></pre>
<p>上から順に、</p>
<ul>
<li>配列長の8をロード</li>
<li>配列を作成</li>
<li>読み込みたいデータ(65～72) が書かれた場所のアドレスをロード</li>
<li>配列の中身をその65～72で上書き</li>
</ul>
<p>という感じ。</p>
<p>書き換えもしないのに配列を new した上にコピーが走るのはもったいないです。</p>
<h2>ReadOnlySpan 最適化</h2>
<p>これに対して、割と最近(Visual Studio 15.7、C# 7.3 世代で)実装された最適化があります。
先ほどのコードを、以下のように書き換えてみましょう。</p>
<pre class="source" title="ReadOnlySpanに変える">
<code><span class="reserved">using</span> System;
 
<span class="reserved">public</span> <span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> Main()
    {
        <span class="type">ReadOnlySpan</span> data = <span class="reserved">new</span> <span class="reserved">byte</span>[] { 65, 66, 67, 68, 69, 70, 71, 72 };
 
        <span class="reserved">foreach</span> (<span class="reserved">var</span> x <span class="reserved">in</span> data)
            <span class="type">Console</span>.WriteLine(x);
    }
}
</code></pre>
<p><code>data</code>の型を<code>ReadOnlySpan&lt;byte&gt;</code>に変えただけです。
しかしこれで、<code>data</code>の中身を書き換えないという保証ができたので、
最適化が掛かります。
C# 7.3 以降でコンパイルすると、結果は以下のようになります。</p>
<pre class="source">
<code><span style="color:purple">IL_0000:</span> <span style="color:blue">ldsflda</span> int64 フィールド名割愛
<span style="color:purple">IL_0005:</span> <span style="color:blue">ldc.i4.8</span>
<span style="color:purple">IL_0006:</span> <span style="color:blue">newobj</span> instance void valuetype 中略.ReadOnlySpan`1<uint8>::.ctor(void*, int32)
</code></pre>
<p>上から順に、</p>
<ul>
<li>読み込みたいデータ(65～72) が書かれた場所のアドレスをロード</li>
<li>配列長の8をロード</li>
<li><code>ReadOnlySpan&lt;byte&gt;</code> のコンストラクター呼び出し</li>
</ul>
<p>です。<code>ReadOnlySpan&lt;byte&gt;</code>は構造体なので、ヒープは使いません。
直接、DLL 中に埋め込まれた ABCDEFGH のところを参照します。</p>
<p>ちなみに、この最適化が効くのは<code>ReadOnlySpan&lt;byte&gt;</code>と<code>ReadOnlySpan&lt;sbyte&gt;</code>だけみたいです。
<code>byte</code>と<code>sbyte</code>以外の値はダメですし、書き換え可能な<code>Span&lt;T&gt;</code>を使ってもダメです。</p>
<h2>実用例</h2>
<p>つい最近なんですが、coreclr で、この最適化を適用する Pull Request が出ていたりします。</p>
<ul>
<li><a href="https://github.com/dotnet/coreclr/pull/20768">Use C# compiler's static data support in Encoding.Preamble</a></li>
</ul>
<p>preamble ってのはいわゆる BOM (Byte Order Mark)です。
Unicode テキストが Big Endian か Little Endian かを判定するための文字ですが、
それを流用して文字コードの判定自体に使われてしまうあれ。
テキストの先頭に以下のような byte 列(code point U+FEFF をエンコードしたもの)を入れるやつ。</p>
<ul>
<li>UTF-8 → EF, BB, BF</li>
<li>Big Endian UTF-16 → FE, FF</li>
<li>Little Endian UTF-16 → FF, FE</li>
<li>Big Endian UTF-32 → 00, 00, FE, FF</li>
<li>Little Endian UTF-32 → FF, FE, 00, 00</li>
</ul>
<p>この静的な byte 列に対して、上記の <code>ReadOnlySpan&lt;byte&gt;</code> 最適化を適用しています。</p>
 ]]></description>
				<pubDate>Sun, 16 Dec 2018 14:34:59 +0900</pubDate>
			</item>
			<item>
				<title>配列のダウンキャスト</title>
				<link>http://ufcpp.net/blog/2018/12/arraydowncast/</link>
				<description><![CDATA[ <p>今日は <a href="/blog/2018/12/unsafe/"><code>Unsafe</code> クラス</a>を使った配列の最適化の話。</p>
<h2><code>object[]</code></h2>
<p>.NET Framework 1.x 時代からある古い API の中にはいくつか、
本当は <code>T</code> 型の配列なのに <code>object[]</code> で戻り値を返してくるようなメソッドがいくつかあります。
<code>object[]</code>とまでは言わないものの、基底クラスの配列で返すメソッドは多いです。</p>
<p>1.x 時代には<a href="/study/csharp/sp2_generics.html">ジェネリクス</a>がなかったせいなんですが、今となっては不便ではあります。</p>
<h3>例: マルチキャスト デリゲート</h3>
<p>例を1個。
C# のデリゲートは、複数のメソッドを <code>+=</code> で繋いで、一斉に呼び出すという機能があり、
これを<a href="/study/csharp/sp_delegate.html#malticast">マルチキャスト デリゲート</a>と言います。
例えば以下のコードは、</p>
<pre class="source" title="マルチキャスト デリゲート">
<code><span class="type">Action</span> f = <span class="reserved">null</span>;
 
<span class="reserved">foreach</span> (<span class="reserved">var</span> i <span class="reserved">in</span> <span class="reserved">new</span>[] { 1, 2, 3, 4, 5 })
{
    f += () =&gt; <span class="type">Console</span>.WriteLine(<span class="string">$&quot;lambda </span>{i}<span class="string"> invoked&quot;</span>);
}
 
f();
</code></pre>
<p>以下のような結果を出力します。</p>
<pre class="source" title="実行結果">
<code>lambda 1 invoked
lambda 2 invoked
lambda 3 invoked
lambda 4 invoked
lambda 5 invoked
</code></pre>
<p>基本的には<a href="/study/csharp/sp_event.html">イベント</a>のための機能で、
戻り値は想定していません。<code>void</code>戻り値以外のメソッドに使おうとするとトラブります。
以下のようなコードを書いたとすると、</p>
<pre class="source" title="マルチキャスト デリゲートの戻り値">
<code><span class="type">Func</span>&lt;<span class="reserved">int</span>&gt; f = <span class="reserved">null</span>;
 
<span class="reserved">foreach</span> (<span class="reserved">var</span> i <span class="reserved">in</span> <span class="reserved">new</span>[] { 1, 2, 3, 4, 5 })
{
    f += () =&gt;
    {
        <span class="type">Console</span>.WriteLine(<span class="string">$&quot;lambda </span>{i}<span class="string"> invoked&quot;</span>);
        <span class="reserved">return</span> i;
    };
}
 
<span class="type">Console</span>.WriteLine(<span class="string">$&quot;f returns </span>{f()}<span class="string">&quot;</span>);
</code></pre>
<p>最後の行の出力は</p>
<pre class="source" title="実行結果">
<code>f returns 5
</code></pre>
<p>になります。要するに、最後の1個の戻り値以外は消えてなくなります。
全ての戻り値を取りたければ以下のように、
個々のデリゲートを配列で受け取って、1つ1つ呼び出すようなコードを書きます。</p>
<pre class="source" title="マルチキャスト デリゲートから、個別のデリゲートを取り出す">
<code><span class="type">Delegate</span>[] list = f.GetInvocationList();
<span class="reserved">foreach</span> (<span class="type">Func</span>&lt;<span class="reserved">int</span>&gt; item <span class="reserved">in</span> list)
    <span class="type">Console</span>.WriteLine(<span class="string">$&quot;f returns </span>{item()}<span class="string">&quot;</span>);
</code></pre>
<p><code>f</code> が <code>Func&lt;int&gt;</code> なんだから、<code>Func&lt;int&gt;[]</code> で一覧を取りたいところなんですが、
残念ながら <code>GetInvocationList</code> の結果は <code>Delegate[]</code> で帰ってきます。
それを再び <code>Func&lt;int&gt;</code> にダウンキャストして使うことになります。</p>
<p>特に、<a href="https://gist.github.com/ufcpp/a72f63d11962f7a5a9a5981b6be31f74"><code>Task</code>戻り値のデリゲートを <code>await</code> したいとき</a>とかに必須の手段です。</p>
<h2>配列ダウンキャスト</h2>
<p>そしてここからが本題。</p>
<p>基底クラスの配列から、元の派生クラスの要素を列挙したい場合、どうするのが最速でしょうか。
<code>string[]</code> と <code>object[]</code> でベンチマークを取ってみます。</p>
<p>ベンチマーク全体は <a href="https://gist.github.com/ufcpp/efb726420adc6f8183a5c7a92ff17a61">Gist</a> に置いておきます。
要点を抜き出すと…</p>
<p>比較用データ: 同じ <code>string</code> 配列を、<code>string[]</code> のフィールドと <code>object[]</code> にフィールドに格納して使います。</p>
<pre class="source" title="ベンチマークに使うデータ">
<code><span class="reserved">string</span>[] _stringData = <span class="reserved">new</span> <span class="reserved">string</span>[] { <span class="string">&quot;a&quot;</span>, <span class="string">&quot;ab&quot;</span>, <span class="string">&quot;abc&quot;</span>, <span class="string">&quot;abcd&quot;</span>, <span class="string">&quot;abcde&quot;</span>, <span class="string">&quot;abcdef&quot;</span>, <span class="string">&quot;abcdefg&quot;</span> };
<span class="reserved">object</span>[] _objectData = <span class="reserved">new</span> <span class="reserved">string</span>[] { <span class="string">&quot;a&quot;</span>, <span class="string">&quot;ab&quot;</span>, <span class="string">&quot;abc&quot;</span>, <span class="string">&quot;abcd&quot;</span>, <span class="string">&quot;abcde&quot;</span>, <span class="string">&quot;abcdef&quot;</span>, <span class="string">&quot;abcdefg&quot;</span> };
</code></pre>
<p>これを、以下の3パターン(+ 参考までに1パターン)のコードに与えてみます。</p>
<p>(1) MemberwiseCast: 要素ごとにダウンキャスト</p>
<pre class="source" title="MemberwiseCast">
<code><span class="reserved">foreach</span> (<span class="reserved">string</span> s <span class="reserved">in</span> _objectData)
    sum += s.Length;
</code></pre>
<p>(2) ArrayCast: 最初に配列自体をダウンキャスト</p>
<pre class="source" title="ArrayCast">
<code><span class="reserved">var</span> data = (<span class="reserved">string</span>[])_objectData;
<span class="reserved">foreach</span> (<span class="reserved">var</span> s <span class="reserved">in</span> data)
    sum += s.Length;
</code></pre>
<p>(3) UnsafeStructCast: 謎の最適化</p>
<pre class="source" title="謎の最適化に使う謎の構造体">
<code><span class="reserved">public</span> <span class="reserved">struct</span> <span class="type">Wrap</span>&lt;<span class="type">T</span>&gt; { <span class="reserved">public</span> <span class="type">T</span> Value; }
</code></pre>
<pre class="source" title="UnsafeStructCast">
<code><span class="reserved">var</span> data = <span class="type">Unsafe</span>.As&lt;<span class="reserved">object</span>[], Wrap&lt;<span class="reserved">string</span>&gt;[]&gt;(<span class="reserved">ref</span> _objectData);
<span class="reserved">foreach</span> (<span class="reserved">var</span> s <span class="reserved">in</span> data)
    sum += s.Value.Length;
</code></pre>
<p>(参考) Static: 最初から <code>string[]</code> の方を列挙</p>
<pre class="source" title="Static">
<code><span class="reserved">foreach</span> (<span class="reserved">var</span> s <span class="reserved">in</span> _stringData)
    sum += s.Length;
</code></pre>
<p>比較の結果、以下のような感じになります。</p>
<table>
<thead>
<tr>
	<th>Method</th>
	<th align="right">Mean</th>
	<th align="right">Error</th>
	<th align="right">StdDev</th>
	<th align="right">Scaled</th>
	<th align="right">ScaledSD</th>
</tr>
</thead>
<tbody>
<tr>
	<td>MemberwiseCast</td>
	<td align="right">8.552 ns</td>
	<td align="right">0.1170 ns</td>
	<td align="right">0.1094 ns</td>
	<td align="right">2.56</td>
	<td align="right">0.04</td>
</tr>
<tr>
	<td>ArrayCast</td>
	<td align="right">7.074 ns</td>
	<td align="right">0.0952 ns</td>
	<td align="right">0.0844 ns</td>
	<td align="right">2.11</td>
	<td align="right">0.03</td>
</tr>
<tr>
	<td>UnsafeStructCast</td>
	<td align="right">3.589 ns</td>
	<td align="right">0.0200 ns</td>
	<td align="right">0.0167 ns</td>
	<td align="right">1.07</td>
	<td align="right">0.01</td>
</tr>
<tr>
	<td>Static</td>
	<td align="right">3.346 ns</td>
	<td align="right">0.0249 ns</td>
	<td align="right">0.0233 ns</td>
	<td align="right">1.00</td>
	<td align="right">0.00</td>
</tr>
</tbody>
</table>
<p>お分かりいただけるだろうか。
1要素ごとにキャストのオーバーヘッドが掛かっていそうな (1) が遅いのは当然として。
最初に1回だけオーバーヘッドが掛かってあとは大丈夫そうに見える (2) がだいぶ遅いという。
そして、「謎の最適化」を自称しているだけあって (3) が倍くらい速い。</p>
<h2>謎の最適化 <code>Wrap&lt;T&gt;</code></h2>
<p>ということで、この謎の最適化が速くなる原理について。</p>
<p><a href="/study/csharp/sp4_variance.html?p=2#covariant-array">.NET の配列には共変性</a>があります。</p>
<pre class="source" title="配列の共変性">
<code><span class="reserved">string</span>[] derivedItems = { <span class="string">&quot;Aleph&quot;</span>, <span class="string">&quot;Beth&quot;</span>, <span class="string">&quot;Gimel&quot;</span> };
<span class="reserved">object</span>[] baseItems = derivedItems; <span class="comment">// この代入は明示的なキャストなしでできる</span>
</code></pre>
<p>だいたいこいつが犯人。</p>
<p>この状況で、<code>baseItems[i] = 10;</code> とか書いてしまうとまずいことになります。
なので、<code>baseItems[i]</code> に対していちいち型チェックが挿入されていて、
本来の型と違う型の値を代入しようとすると例外が飛びます。
その型チェックのコストが、前節の (2) が遅くなる原因。</p>
<p>ちなみに、共変性は参照型にしか働かないので、例えば以下のようなコードはコンパイル エラーになります。<code>int</code> は値型なので、共変ではなくなります。</p>
<pre class="source" title="値型の配列には共変性が働かない">
<code><span class="reserved">int</span>[] derivedItems = { 1, 2, 3 };
<span class="reserved">object</span>[] baseItems = derivedItems; <span class="comment">// この代入は(キャストの有無によらず)認められない</span>
</code></pre>
<p>謎の最適化 (3) が速くなる理由はここにあります。
<code>Wrap&lt;T&gt;</code>構造体を介することで、共変性がなくなっています。
そして、共変じゃないことがわかっているので、型チェックが挟まらなくなる。
結果的に速い。
ただし、本来変換できないはずの <code>object[]</code> から <code>Wrap&lt;string&gt;[]</code> への嘘ダウンキャストが必要になるので、<code>Unsafe</code> クラスが必須です。</p>
<p>(ちなみに、<code>Wrap&lt;T&gt;</code>構造体は<code>T</code>型のフィールド1つだけの構造体なので、
<code>object</code>と<code>Wrap&lt;object&gt;</code>のメモリ上での構造は全く同じになります。
なので、今回のような嘘ダウンキャストしても「メモリ上の配置が同じだから同じコードで動く」みたいな感じになります。)</p>
<p>割かしひどい話です。
<code>Unsafe</code> クラスを避けれるなら避けたいわけでして。
最初から「共変性は使わないから型チェックしないでくれ」と指示できるような、
配列に代わる手段が求められます。
ということで出ている提案が以下のようなもの。</p>
<ul>
<li><a href="https://github.com/dotnet/corefx/issues/23689">Invariant Arrays</a></li>
</ul>
<p>まあ、採用される気配ないんですけども…
普通に coreclr 内にさっきの「謎の最適化」と同種のコード入ってたりするんですけども。</p>
 ]]></description>
				<pubDate>Sat, 15 Dec 2018 12:21:16 +0900</pubDate>
			</item>
			<item>
				<title>System.Runtime.CompilerServices.Unsafe</title>
				<link>http://ufcpp.net/blog/2018/12/unsafe/</link>
				<description><![CDATA[ <p>昨日から始まった在庫一掃処分セール的なブログなんですが、結構な頻度で「<code>Unsafe</code> クラス」ってのが出てきます。</p>
<p>以下のパッケージに含まれているもので、こいつをを参照すれば、通常の C# では書けないようなどぎつい unsafe な真似がし放題になります。</p>
<ul>
<li><a href="https://www.nuget.org/packages/System.Runtime.CompilerServices.Unsafe/">System.Runtime.CompilerServices.Unsafe</a></li>
</ul>
<p>これの登場はもう結構前なんですけども、そういえばちゃんとした説明をしたことなかったなと。</p>
<h2>.NET の IL は意外とやりたい放題</h2>
<p>上記パッケージにはパッケージ名と同じ<code>Unsafe</code>というクラスが入っています。
この<code>Unsafe</code>クラス、ソースコードはこんな感じ:</p>
<ul>
<li><a href="https://github.com/dotnet/corefx/blob/64c6d9fe5409be14bdc3609d73ffb3fea1f35797/src/System.Runtime.CompilerServices.Unsafe/src/System.Runtime.CompilerServices.Unsafe.il">System.Runtime.CompilerServices.Unsafe.il</a></li>
</ul>
<p>ILアセンブリ実装です。</p>
<p>C# では書けなくても、IL なら何も特別なことをしなくてもやりたい放題。
要するに、.NET における「安全」は、結構 C# のレベルで保証しています。</p>
<p>とはいえ、unsafe でもいいので、C# でできないのは困るということで提供されるようになったのがこの<code>Unsafe</code>クラスです。
C# の文法を拡張するよりは、こういう IL 実装なクラスを提供する方が手っ取り早かったのでこんなことになりました。</p>
<h2>ポインターの方がまだマシ疑惑</h2>
<p>とはいえ、この<code>Unsafe</code>クラスをフル活用すると、こんなコードになります。</p>
<pre class="source" title="Unsafe クラス">
<code><span class="reserved">using</span> System.Runtime.CompilerServices;
 
<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">int</span> UnsafeClass(<span class="reserved">int</span>[] array)
    {
        <span class="reserved">var</span> sum = 0;
        <span class="reserved">ref</span> <span class="reserved">var</span> begin = <span class="reserved">ref</span> array[0];
        <span class="reserved">ref</span> <span class="reserved">var</span> p = <span class="reserved">ref</span> <span class="type">Unsafe</span>.As&lt;<span class="reserved">int</span>, <span class="reserved">byte</span>&gt;(<span class="reserved">ref</span> begin);
        <span class="reserved">var</span> length = array.Length * 4;
        <span class="reserved">for</span> (<span class="reserved">int</span> i = 0; i &lt; length; i++, p = <span class="reserved">ref</span> <span class="type">Unsafe</span>.Add(<span class="reserved">ref</span> p, 1))
            sum += p;
        <span class="reserved">return</span> sum;
    }
}
</code></pre>
<p>ちなみに、普通に C# で unsafe コードを使って同じものを書くと以下のようになります。</p>
<pre class="source" title="unsafe コードで同じもの">
<code><span class="reserved">unsafe</span> <span class="reserved">static</span> <span class="reserved">int</span> UnsafeContext(<span class="reserved">int</span>[] array)
{
    <span class="reserved">var</span> sum = 0;
    <span class="reserved">fixed</span> (<span class="reserved">int</span>* begin = &amp;array[0])
    {
        <span class="reserved">var</span> p = (<span class="reserved">byte</span>*)begin;
        <span class="reserved">var</span> length = array.Length * 4;
        <span class="reserved">for</span> (<span class="reserved">int</span> i = 0; i &lt; length; i++, p++)
            sum += *p;
    }
    <span class="reserved">return</span> sum;
}
</code></pre>
<p>見た目に関しては、ポインターを使った後者の方がまだマシなんじゃないでしょうか。</p>
<p>だったら素直に unsafe コードを使う方がいいんじゃないかという話になるとは思いますが、
いくつか、<code>Unsafe</code>クラスでしかできないことがあります。</p>
<ul>
<li>ポインターの代わりに <a href="/study/csharp/sp_ref.html"><code>ref</code></a> で操作できる</li>
<li>ジェネリックな型をポインター化できる</li>
</ul>
<h3>ポンターの代わりに ref</h3>
<p>ポインターと <code>ref</code> は内部的には似たようなものです。
大体同じ命令を使って間接参照します。
ですが、
1つ決定的に違うのが、<code>ref</code>なら<a href="/study/csharp/rm_gc.html#garbage-collection">ガベコレ</a>が追えるという点があります。</p>
<pre class="source" title="ref とガベコレ">
<code><span class="comment">// ref 戻り値ならこんなコードを書いても平気。</span>
<span class="comment">// 戻り値が「参照」されている限り、配列自体の参照がガベコレにトラッキングされる。</span>
<span class="reserved">ref</span> <span class="reserved">int</span> X()
{
    <span class="reserved">var</span> array = <span class="reserved">new</span> <span class="reserved">int</span>[1];
    <span class="reserved">return</span> <span class="reserved">ref</span> array[0];
}
 
<span class="comment">// 一方、これはダメ。</span>
<span class="comment">// ガベコレが走ったら、もはやポインターが有効な場所を指さなくなる。</span>
<span class="reserved">unsafe</span> <span class="reserved">int</span>* Y()
{
    <span class="reserved">var</span> array = <span class="reserved">new</span> <span class="reserved">int</span>[1];
    <span class="reserved">fixed</span> (<span class="reserved">int</span>* p = array)
        <span class="reserved">return</span> p;
}
</code></pre>
<p>ということで、<code>ref</code>を使って unsafe なことをしたいときに使うのが
<code>Unsafe</code> クラスです。</p>
<p>例としては<a href="/study/csharp/resource/span/"><code>Span&lt;T&gt;</code>構造体</a>があります。
(というか、<code>Unsafe</code>クラスを導入するに至った最初の動機は<code>Span&lt;T&gt;</code>構造体を作るためでした。)</p>
<p><code>Span&lt;T&gt;</code>は、以下のように、配列でもポインターでも統一的に扱える型です。</p>
<pre class="source" title="Span&lt;T&gt;">
<code><span class="reserved">using</span> System;
<span class="reserved">using</span> System.Runtime.InteropServices;
 
<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> Main()
    {
        <span class="comment">// 配列</span>
        <span class="type">Span</span>&lt;<span class="reserved">int</span>&gt; array = <span class="reserved">new</span> <span class="reserved">int</span>[8].AsSpan().Slice(2, 3);
 
        <span class="comment">// 文字列</span>
        <span class="type">ReadOnlySpan</span>&lt;<span class="reserved">char</span>&gt; str = <span class="string">&quot;abcdefgh&quot;</span>.AsSpan().Slice(2, 3);
 
        <span class="comment">// スタック領域</span>
        <span class="type">Span</span>&lt;<span class="reserved">int</span>&gt; stack = <span class="reserved">stackalloc</span> <span class="reserved">int</span>[8];
 
        <span class="reserved">unsafe</span>
        {
            <span class="comment">// ガベコレ管理外メモリ</span>
            <span class="reserved">var</span> p = <span class="type">Marshal</span>.AllocHGlobal(<span class="reserved">sizeof</span>(<span class="reserved">int</span>) * 8);
            <span class="type">Span</span>&lt;<span class="reserved">int</span>&gt; unmanaged = <span class="reserved">new</span> <span class="type">Span</span>&lt;<span class="reserved">int</span>&gt;((<span class="reserved">int</span>*)p, 8);
 
            <span class="comment">// 他の言語との相互運用</span>
            <span class="reserved">var</span> q = malloc((<span class="type">IntPtr</span>)(<span class="reserved">sizeof</span>(<span class="reserved">int</span>) * 8));
            <span class="type">Span</span>&lt;<span class="reserved">int</span>&gt; interop = <span class="reserved">new</span> <span class="type">Span</span>&lt;<span class="reserved">int</span>&gt;((<span class="reserved">int</span>*)q, 8);
 
            <span class="type">Marshal</span>.FreeHGlobal(p);
            free(q);
        }
    }
 
    [<span class="type">DllImport</span>(<span class="string">&quot;msvcrt.dll&quot;</span>, CallingConvention = <span class="type">CallingConvention</span>.Cdecl)]
    <span class="reserved">static</span> <span class="reserved">extern</span> <span class="type">IntPtr</span> malloc(<span class="type">IntPtr</span> size);
 
    [<span class="type">DllImport</span>(<span class="string">&quot;msvcrt.dll&quot;</span>, CallingConvention = <span class="type">CallingConvention</span>.Cdecl)]
    <span class="reserved">static</span> <span class="reserved">extern</span> <span class="reserved">void</span> free(<span class="type">IntPtr</span> ptr);
}

</code></pre>
<p>こういう型を作ろうと思うと、通常なら unsafe コードだらけ・ポインターだらけになるんですが、
<code>Span&lt;T&gt;</code>構造体はその代わりに <a href="https://source.dot.net/#System.Private.CoreLib/shared/System/Span.Fast.cs,d2517139cac388e8"><code>Unsafe</code> クラスだらけ・<code>ref</code>だらけ</a>です。</p>
<h3>ジェネリックな型をポインター化</h3>
<p>C# の unsafe コードの仕様では、ジェネリックな型はポインター化できません。
とはいえ、この制限は実はちょっと厳しすぎです。</p>
<pre class="source" title="ジェネリック構造体とポインター">
<code><span class="comment">// 値型しか含まない構造体はポインター化 (A*) できる。</span>
<span class="reserved">struct</span> <span class="type">A</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> X;
}
 
<span class="comment">// 1つでも参照型を含んでいる場合、ポインター化されるとガベコレが追えなくなって困る。</span>
<span class="comment">// なので、ポインター化できない仕様もやむなし。</span>
<span class="reserved">struct</span> <span class="type">B</span>
{
    <span class="reserved">public</span> <span class="reserved">string</span> X;
}
 
<span class="comment">// ならこのジェネリックな場合はどうか。</span>
<span class="comment">// T に値型を渡したとき、値型しか含まない構造体になり得る。</span>
<span class="comment">// T 次第でポインター化できるかどうか変えてもよかったのではないか。</span>
<span class="comment">// (現状は無条件にポインター化 (C&lt;int&gt;* とかも) 不可)</span>
<span class="reserved">struct</span> <span class="type">C</span>&lt;<span class="type">T</span>&gt;
{
    <span class="type">T</span> X;
}
</code></pre>
<p>C# 7.3 で <a href="/study/csharp/sp_unsafe.html#unmanaged-types">unmanaged 制約</a>が入って、
多少は制限が緩和したんですが、いまだこの例の <code>C&lt;T&gt;</code> のような型はポインター化できません。
(C# 8.0 で緩和される可能性あり。遅くとも C# 8.x の間には緩和されると思われます。)</p>
<p>が、<code>Unsafe</code>クラスを使えば(今でも)そんな制限をガン無視できます。</p>
<pre class="source" title="ジェネリック構造体からポインターを取得">
<code><span class="reserved">using</span> System;
<span class="reserved">using</span> System.Runtime.CompilerServices;
 
<span class="reserved">struct</span> <span class="type">C</span>&lt;<span class="type">T</span>&gt;
{
    <span class="reserved">public</span> <span class="type">T</span> X;
}
 
<span class="reserved">public</span> <span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">unsafe</span> <span class="reserved">static</span> <span class="reserved">void</span> Main()
    {
        <span class="reserved">var</span> c = <span class="reserved">new</span> <span class="type">C</span>&lt;<span class="reserved">int</span>&gt;();
        <span class="reserved">int</span>* p = (<span class="reserved">int</span>*)<span class="type">Unsafe</span>.AsPointer(<span class="reserved">ref</span> c);
        *p = 1;
        <span class="type">Console</span>.WriteLine(c.X); <span class="comment">// 1</span>
    }
}
</code></pre>
<h2>Unsafe クラスを safe なところから呼べる</h2>
<p>もちろん、<code>Unsafe</code> クラス悪用すると、unsafe コード以上に unsafe になります。</p>
<p>にもかかわらず、<code>Unsafe</code>クラスのメソッドの引数・戻り値は大半が <code>ref</code> になっているので、unsafe コードなしで呼び出せます。
ある意味、これが一番の欠陥で、言語機能の不足を感じます
(「ポインターは使っていないけども unsafe コードからしか呼べない」みたいな制約を付けれる機能が欲しい)。
(実際、corefx/coreclr 内でも度々そういう話題は上がっています。
そもそも利用頻度が低いクラスなので需要はあんまりありませんが…)</p>
 ]]></description>
				<pubDate>Fri, 14 Dec 2018 09:35:46 +0900</pubDate>
			</item>
			<item>
				<title>配列のインデクサー</title>
				<link>http://ufcpp.net/blog/2018/12/arrayindexer/</link>
				<description><![CDATA[ <p>C# 8.0 がらみの話も一段落してしまったので、
今日からしばらく予告通り、Gist に書き捨ててたもののブログ化になります。
ぶっちゃけ、在庫一掃処分セールみたいなものなので過度な期待はしないでください。</p>
<p>今日は C# コンパイラーと JIT レベルの最適化の話。</p>
<h2>配列の範囲チェック</h2>
<p>.NET の配列は、バッファオーバーランとかのメモリ破壊を避けるべく、範囲チェックがかかっています。</p>
<pre class="source" title="">
<code><span class="reserved">using</span> System;
 
<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> Main()
    {
        <span class="reserved">var</span> a = <span class="reserved">new</span> <span class="reserved">int</span>[4];
        <span class="reserved">var</span> x = a[5]; <span class="comment">// 範囲外なのでここで IndexOutOfRangeException が飛ぶ</span>
        <span class="type">Console</span>.WriteLine(x);
    }
}
</code></pre>
<p><code>a[5]</code> のところのコンパイル結果は以下のようになります。</p>
<p>IL:</p>
<pre class="source">
<code><span style="color:purple">IL_0006:</span> <span style="color:blue">ldc.i4.5</span>  <span style="color:green"> // 5 をロード
</span><span style="color:purple">IL_0007:</span> <span style="color:blue">ldelem.i4</span> <span style="color:green"> // 配列要素の読み込み命令
</span></code></pre>
<p>IL には配列の要素を読み書きする命令があります。
この時点では <code>ldelem</code> 命令が出力されているだけで、
例外を飛ばすコードはありません。
範囲チェックが挿入されるのはその次の、JIT でネイティブ コード化される段階になります。</p>
<p>x86 コード:</p>
<pre class="source">
<code><span style="color:purple">L000f:</span> <span style="color:blue">cmp</span> dword [eax+0x4], 0x5<span style="color:green"> ; 配列長と 5 を比較
</span><span style="color:purple">L0013:</span> <span style="color:blue">jbe</span> L001e               <span style="color:green"> ; 例外を投げるコードにジャンプ
</span><span style="color:purple">L0015:</span> <span style="color:blue">mov</span> ecx, [eax+0x1c]     <span style="color:green"> ; a[5] の場所のデータを読み込み
</span></code></pre>
<p>元のコードにはない比較・ジャンプ命令が挟まっています。</p>
<h2>配列の列挙</h2>
<p>今度は、全要素列挙することを見てみましょう。
以下のようなコードを考えます。</p>
<pre class="source" title="">
<code><span class="reserved">void</span> M(<span class="reserved">int</span>[] array)
{
    <span class="reserved">for</span> (<span class="reserved">var</span> i = 0; i &lt; array.Length; ++i)
    {
        <span class="reserved">var</span> x = array[i];
        <span class="type">Console</span>.WriteLine(x);
    }
}
</code></pre>
<p>この場合は、ループ付近が以下のようにコンパイルされます。</p>
<p>IL:</p>
<pre class="source">
<code><span style="color:purple">IL_0004:</span> <span style="color:blue">ldarg.1</span>
<span style="color:purple">IL_0005:</span> <span style="color:blue">ldloc.0</span>
<span style="color:purple">IL_0006:</span> <span style="color:blue">ldelem.i4</span>                 <span style="color:green"> // array[i]</span>
<span style="color:purple">IL_0007:</span> <span style="color:blue">call</span> void WriteLine(int32)
<span style="color:purple">IL_000c:</span> <span style="color:blue">ldloc.0</span>
<span style="color:purple">IL_000d:</span> <span style="color:blue">ldc.i4.1</span>
<span style="color:purple">IL_000e:</span> <span style="color:blue">add</span>
<span style="color:purple">IL_000f:</span> <span style="color:blue">stloc.0</span>
<span style="color:purple">IL_0010:</span> <span style="color:blue">ldloc.0</span>
<span style="color:purple">IL_0011:</span> <span style="color:blue">ldarg.1</span>
<span style="color:purple">IL_0012:</span> <span style="color:blue">ldlen</span>
<span style="color:purple">IL_0013:</span> <span style="color:blue">conv.i4</span>                   <span style="color:green"> // i < Length</span>
<span style="color:purple">IL_0014:</span> <span style="color:blue">blt.s</span> IL_0004
</code></pre>
<p>x86 コード:</p>
<pre class="source">
<code><span style="color:purple">L0008:</span> <span style="color:blue">xor</span> esi, esi
<span style="color:purple">L000a:</span> <span style="color:blue">mov</span> ebx, [edi+0x4]
<span style="color:purple">L000d:</span> <span style="color:blue">test</span> ebx, ebx
<span style="color:purple">L000f:</span> <span style="color:blue">jle</span> L001f
<span style="color:purple">L0011:</span> <span style="color:blue">mov</span> ecx, [edi+esi*4+0x8] <span style="color:green"> ; array[i]</span>
<span style="color:purple">L0015:</span> <span style="color:blue">call</span> WriteLine(Int32)
<span style="color:purple">L001a:</span> <span style="color:blue">inc</span> esi
<span style="color:purple">L001b:</span> <span style="color:blue">cmp</span> ebx, esi             <span style="color:green"> ; i < Length</span>
<span style="color:purple">L001d:</span> <span style="color:blue">jg</span> L0011
</code></pre>
<p><code>for</code> ステートメント中の <code>i &lt; Length</code> 相当のコードはありますが、
その他の比較はありません。
要するに、単品だと<code>array[i]</code>のところに挟まっていた範囲チェックが、このループでは消えています。</p>
<p>これは JIT が行っている最適化で、要するに、</p>
<ul>
<li>何もしなければ、<code>array[i]</code> のところに暗黙的な範囲チェックを追加する</li>
<li>明示的な範囲チェックがあれば、余計な範囲チェックの追加はしない</li>
</ul>
<p>という挙動になります。
なので、安全性は保たれつつ、ループの速度は落としません。</p>
<h2>foreach 最適化</h2>
<p>次に以下のコードを考えます。
先ほどの <code>for</code> を使ったコードとやっていることは全く一緒です。
配列の全要素の列挙。</p>
<pre class="source" title="">
<code><span class="reserved">void</span> M(<span class="reserved">int</span>[] array)
{
    <span class="reserved">foreach</span> (<span class="reserved">var</span> x <span class="reserved">in</span> array)
    {
        <span class="type">Console</span>.WriteLine(x);
    }
}
</code></pre>
<p>こいつは以下のようにコンパイルされます。</p>
<p>IL:</p>
<pre class="source">
<code><span style="color:purple">IL_0006:</span> <span style="color:blue">ldloc.0</span>
<span style="color:purple">IL_0007:</span> <span style="color:blue">ldloc.1</span>
<span style="color:purple">IL_0008:</span> <span style="color:blue">ldelem.i4</span>                 <span style="color:green"> // array[i]</span>
<span style="color:purple">IL_0009:</span> <span style="color:blue">call</span> void WriteLine(int32)
<span style="color:purple">IL_000e:</span> <span style="color:blue">ldloc.1</span>
<span style="color:purple">IL_000f:</span> <span style="color:blue">ldc.i4.1</span>
<span style="color:purple">IL_0010:</span> <span style="color:blue">add</span>
<span style="color:purple">IL_0011:</span> <span style="color:blue">stloc.1</span>
<span style="color:purple">IL_0012:</span> <span style="color:blue">ldloc.1</span>
<span style="color:purple">IL_0013:</span> <span style="color:blue">ldloc.0</span>
<span style="color:purple">IL_0014:</span> <span style="color:blue">ldlen</span>
<span style="color:purple">IL_0015:</span> <span style="color:blue">conv.i4</span>                   <span style="color:green"> // i < Length</span>
<span style="color:purple">IL_0016:</span> <span style="color:blue">blt.s</span> IL_0006
</code></pre>
<p><code>ldloc</code> (ローカル変数読み込み)の後ろの番号とかが違うだけで、
他は先ほどの <code>for</code> のコードと全く同じです。
(要するに、「変数名が違うけど同じロジック」程度の差です。)</p>
<p><code>GetEnumerator</code>とか<code>MoveNext</code>、<code>Current</code>は一切出てきません。
代わりにインデックスの <code>++i</code> とか <code>array[i]</code> 相当のコードが出てきます。</p>
<p>要するに、C# コンパイラーは、配列の <code>foreach</code> を見たら <code>for (var i ...</code> 相当のコードに変換します。</p>
<h2>配列の一部分を列挙</h2>
<p>配列全体の列挙に対して結構よい最適化がかかっていることはわかりました。
次は、一部分だけ列挙することを考えます。</p>
<pre class="source" title="">
<code><span class="reserved">void</span> M(<span class="reserved">int</span>[] array, <span class="reserved">int</span> start, <span class="reserved">int</span> count)
{
    <span class="reserved">var</span> end = start + count;
    <span class="reserved">for</span> (<span class="reserved">var</span> i = start; i &lt; end; ++i)
    {
        <span class="reserved">var</span> x = array[i];
        <span class="type">Console</span>.WriteLine(x);
    }
}
</code></pre>
<p>これを同じようにコンパイルすると…
ループ近辺だけ抜き出すと以下のようになります。</p>
<p>x86 コード:</p>
<pre class="source">
<code><span style="color:purple">L0017:</span> <span style="color:blue">mov</span> eax, [edi+0x4]
<span style="color:purple">L001a:</span> <span style="color:blue">mov</span> [ebp-0x10], eax
<span style="color:purple">L001d:</span> <span style="color:blue">mov</span> eax, [ebp-0x10]
<span style="color:purple">L0020:</span> <span style="color:blue">cmp</span> esi, eax       <span style="color:green"> ; ここの比較は array[i] に対して暗黙的に追加されるもの</span>
<span style="color:purple">L0022:</span> <span style="color:blue">jae</span> L003a          <span style="color:green"> ; 例外を投げるコードへのジャンプ</span>
<span style="color:purple">L0024:</span> <span style="color:blue">mov</span> ecx, [edi+esi*4+0x8]
<span style="color:purple">L0028:</span> <span style="color:blue">call</span> System.Console.WriteLine(Int32)
<span style="color:purple">L002d:</span> <span style="color:blue">inc</span> esi
<span style="color:purple">L002e:</span> <span style="color:blue">cmp</span> esi, ebx       <span style="color:green"> ; ここの比較は i < end</span>
<span style="color:purple">L0030:</span> <span style="color:blue">jl</span> L001d           <span style="color:green"> ; これはループを抜ける・抜けないの分岐</span>
</code></pre>
<p>さすがに、<code>array.Length</code> 以外のものまで見て最適化は掛けてくれないみたいです。
ちなみに、事前に <code>start</code>、<code>end</code>の範囲チェックをしてもダメ。</p>
<h2>そこで <code>Span&lt;T&gt;</code></h2>
<p>C# 7.2 では、<a href="/study/csharp/resource/span/"><code>Span&lt;T&gt;</code></a>がらみの対応がいろいろ入ったわけですが、このタイミングで、<code>Span&lt;T&gt;</code>に対する列挙の最適化も入っています。</p>
<p>まず、配列同様、<code>Span&lt;T&gt;</code>に対する<code>foreach</code>は<code>for</code>に最適化されます。
例えば、以下の2つのメソッドはほぼ同じ IL にコンパイルされます。</p>
<pre class="source" title="">
<code><span class="reserved">public</span> <span class="reserved">void</span> M1(<span class="type">Span</span>&lt;<span class="reserved">int</span>&gt; array)
{
    <span class="reserved">for</span> (<span class="reserved">var</span> i = 0; i &lt; array.Length; ++i)
    {
        <span class="reserved">var</span> x = array[i];
        <span class="type">Console</span>.WriteLine(x);
    }
}
 
<span class="reserved">public</span> <span class="reserved">void</span> M2(<span class="type">Span</span>&lt;<span class="reserved">int</span>&gt; array)
{
    <span class="reserved">foreach</span> (<span class="reserved">var</span> x <span class="reserved">in</span> array)
    {
        <span class="type">Console</span>.WriteLine(x);
    }
}
</code></pre>
<p>また、JIT 時の最適化で、「暗黙の範囲チェック」も消えてくれるようです。
要するに、先ほどの <code>for (var i = start; i &lt; end; ++i)</code> なループよりも、
以下のような、<code>Span&lt;T&gt;</code>を介したコードの方が最適化がかかりやすいです。</p>
<pre class="source" title="">
<code><span class="reserved">public</span> <span class="reserved">void</span> M2(<span class="reserved">int</span>[] array, <span class="reserved">int</span> start, <span class="reserved">int</span> count)
{
    <span class="reserved">foreach</span> (<span class="reserved">var</span> x <span class="reserved">in</span> array.AsSpan(start, count))
    {
        <span class="type">Console</span>.WriteLine(x);
    }
}
</code></pre>
<p>ちなみに、今のところこういう最適化がかかるのは配列と <code>Span&lt;T&gt;</code> だけです。
<code>Span&lt;T&gt;</code> だけ特別扱いするのもちょっと嫌な話で、
もっと汎用的に、所定のパターンを満たした型なら <code>foreach</code> を <code>for (var i ...</code> に変換できるような仕組みも一応検討はされています。
(<code>Span&lt;T&gt;</code>以外に対する需要はそこまで高くないので、優先度は低め。)</p>
 ]]></description>
				<pubDate>Thu, 13 Dec 2018 10:52:27 +0900</pubDate>
			</item>
			<item>
				<title>C# 8.0 その他 (Preview 1での未実装機能)</title>
				<link>http://ufcpp.net/blog/2018/12/cs8notyet/</link>
				<description><![CDATA[ <p>これまで紹介してきたもの以外にも、C# 8.0での導入が予定されている機能はいくつかあります。
ただ、Visual Studio 2019 Preview 1でまだ実装されていない機能・ちゃんと動いていない機能はまとめて軽く紹介して終わりにしようかと思います。
次以降のPreviewで実装されたらまた改めて紹介します。</p>
<h2>インターフェイスのデフォルト実装</h2>
<p>インターフェイス中のメソッドに実装を持てるようになります。
これに関しては昔書いた記事があるのでそちらを参照:</p>
<ul>
<li><a href="https://www.buildinsider.net/column/iwanaga-nobuyuki/013">「インターフェースのデフォルト実装」の導入（前編）</a></li>
<li><a href="https://www.buildinsider.net/column/iwanaga-nobuyuki/014">「インターフェースのデフォルト実装」の導入（中編）</a></li>
<li><a href="https://www.buildinsider.net/column/iwanaga-nobuyuki/015">「インターフェースのデフォルト実装」の導入（後編）</a></li>
</ul>
<p>先日「<a href="/blog/2018/12/runtimefeature/">RuntimeFeature クラス</a>」で紹介した通り、
ランタイムの修正が必須の機能です。</p>
<h2>pattern-base な using/foreach</h2>
<p><a href="/blog/2018/7/pickuproslyn0711/">前に1度書いていますが</a>、C# には単なるメソッド呼び出しに置き換えるような、シンタックスシュガーな文法が結構あります。
例えば、クエリ式の場合、以下の2行は全く同じ意味になります。</p>
<pre class="source" title="">
<code><span class="reserved">var</span> q1 =
    <span class="reserved">from</span> x <span class="reserved">in</span> source
    <span class="reserved">where</span> x &gt; 5
    <span class="reserved">select</span> x * x;
 
<span class="reserved">var</span> q2 = source
    .Where(x =&gt; x &gt; 5)
    .Select(x =&gt; x * x);
</code></pre>
<p>問題はここから先。
クエリ式の場合は、この<code>Where</code>や<code>Select</code>メソッドにかなり自由が効きます。</p>
<ul>
<li>特にインターフェイスの実装等は必要なく、所定のパターンを満たしていれば何でもいい</li>
<li>インスタンス メソッドでも拡張メソッドでもいい</li>
<li>オプション引数や params があってもいい</li>
</ul>
<p>一方で、<code>foreach</code>の場合だと以下の制限が掛かります。</p>
<ul>
<li>インスタンス メソッドでないとダメ</li>
<li>オプション引数や params があるとダメ</li>
</ul>
<p>さらに、<code>using</code>ステートメントに至ってはもっと厳しい制限が掛かっています。</p>
<ul>
<li><code>IDisposable</code>インターフェイスを実装していないとダメ</li>
</ul>
<p>これに対して、C# 8.0 では、<code>foreach</code>と<code>using</code>でもクエリ式と同程度の緩さで「パターンでの(pattern-based)実装」が認められるようになります。
<a href="/blog/2018/12/cs8asyncstreams/">昨日</a>紹介した非同期版の <code>foreach</code> も同様です。</p>
<p>ちなみに、提案では「enhanced using」と呼ばれていて、
次節の「using declarationとセット」、かつ、「<code>using</code>の方が主役で<code>foreach</code>の方はおまけ」です。</p>
<h2>using declaration</h2>
<p><code>using</code>ステートメントに対して、以下のような要望は多いです。</p>
<ul>
<li><code>using</code>のネストがしんどい、</li>
<li><code>Dispose</code>したいタイミングはほとんどの場合、変数のスコープと同じ</li>
</ul>
<p>ということで、以下のように、変数に対する修飾子として<code>using</code>を書くことで、
その変数のスコープから抜けるときに<code>Dispose</code>を呼ぶという機能を追加する予定です。</p>
<pre class="source" title="">
<code><span class="reserved">struct</span> <span class="type">A</span>
{
    <span class="reserved">void</span> Dispose() =&gt; <span class="type">Console</span>.WriteLine(<span class="string">&quot;A Disposed&quot;</span>);
}
 
<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> Main()
    {
        <span class="reserved">using</span> <span class="reserved">var</span> a = <span class="reserved">new</span> <span class="type">A</span>();
        <span class="reserved">using</span> <span class="reserved">var</span> b = <span class="reserved">new</span> <span class="type">A</span>();
 
        {
            <span class="reserved">using</span> <span class="reserved">var</span> c = <span class="reserved">new</span> <span class="type">A</span>();
            <span class="comment">// c のスコープはここまでなので、ここで c.Dispose()</span>
        }
 
        <span class="comment">// ここで b.Dispose(); a.Dispose();</span>
        <span class="comment">// ちなみに、宣言とは逆順で呼ばれる</span>
    }
}
</code></pre>
<h2>Target-typed new</h2>
<p>C# 7.1で入った<a href="/study/csharp/cheatsheet/ap_ver7_1/#default-expr"><code>default</code>式</a>と同様に、<code>new</code>に対しても左辺からの型推論が効くようになります。</p>
<pre class="source" title="">
<code><span class="comment">// これは 右→左 の推論。C# 3.0 の頃から使える。</span>
<span class="reserved">var</span> a1 = <span class="reserved">new</span> <span class="type">A</span>(1, 2);
 
<span class="comment">// C# 8.0 では、左→右 の推論が入る。</span>
<span class="type">A</span> a2 = <span class="reserved">new</span>(1, 2);
</code></pre>
<h2>caller expression attribute</h2>
<p>C# 5.0で、<a href="/study/csharp/ap_ver5.html#CallerInfo">Caller Info 属性</a>というものがいくつか入っています。
以下のように、コンパイラーによって呼び出し元のメソッド名などを挿入してもらう機能です。</p>
<pre class="source" title="">
<code><span class="reserved">using</span> System;
<span class="reserved">using</span> System.Runtime.CompilerServices;
 
<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> M([<span class="type">CallerMemberName</span>]<span class="reserved">string</span> callerName = <span class="reserved">null</span>)
        =&gt; <span class="type">Console</span>.WriteLine(callerName);
 
    <span class="reserved">static</span> <span class="reserved">void</span> Main()
    {
        <span class="comment">// M には何も引数を渡していないものの、</span>
        <span class="comment">// CallerMemberName が付いているので null ではなく、呼び出し元のメソッド名</span>
        <span class="comment">// (この場合は &quot;Main&quot;)がコンパイラーによって挿入される。</span>
        M();
    }
}
</code></pre>
<p>C# 8.0で、この手の属性が1つ増えます。
<code>CallerArgumentExpression</code>属性を付けることで、
引数に渡した式全体を受け取れます。</p>
<pre class="source" title="">
<code><span class="reserved">using</span> System;
<span class="reserved">using</span> System.Runtime.CompilerServices;
 
<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> M(<span class="reserved">int</span> x, [<span class="type">CallerArgumentExpression</span>(<span class="string">&quot;x&quot;</span>)]<span class="reserved">string</span> xExpression = <span class="reserved">null</span>)
        =&gt; <span class="type">Console</span>.WriteLine(xExpression);
 
    <span class="reserved">static</span> <span class="reserved">void</span> Main()
    {
        M(1 + 2 + 3); <span class="comment">// &quot;1 + 2 + 3&quot; が xExpression に渡る</span>
        M(2 * 3);     <span class="comment">// 同上、&quot;2 * 3&quot;</span>
    }
}
</code></pre>
<p>わかりやすい用途は、例えば<code>XUnit.Assert</code>とかです。
単体テストが失敗したときに、失敗の原因になった式をログに表示できます。</p>
<h2>generic attributes</h2>
<p>属性にジェネリックなクラスを使えるようになります。</p>
<pre class="source" title="">
<code><span class="reserved">using</span> System;
 
<span class="reserved">class</span> <span class="type">MyAttribute</span>&lt;<span class="type">T</span>&gt; : <span class="type">Attribute</span> { }
 
[My&lt;<span class="reserved">int</span>&gt;]
<span class="reserved">class</span> <span class="type">Target</span> { }
</code></pre>
<h2>機能一覧</h2>
<p>ここで紹介したのは、roslyn リポジトリにある<a href="https://github.com/dotnet/roslyn/blob/master/docs/Language%20Feature%20Status.md">Language Feature Status</a>を元に選んだものです。
一方で、csharplang の方の <a href="https://github.com/dotnet/csharplang/milestone/8">8.0 candidate</a> マイルストーンの方には他にもいくつか並んでいます。</p>
<p>7.0 の時の経験からいうと、
基本的には<a href="https://github.com/dotnet/roslyn/blob/master/docs/Language%20Feature%20Status.md">Language Feature Status</a>に並んでいるものが実装されていきますが、
多少の入れ替わりはあったりします。
急にLanguage Feature Statusに追加されるものもあれば、
今並んでいても8.xに回されることもあります。</p>
<p>例えば、実装状況を見るに、以下の2つなんかはLanguage Feature Statusに並んでいませんが、8.0 に入るんじゃないかという感じがします。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/1744">Champion: Unmanaged constructed types #1744</a></li>
<li><a href="https://github.com/dotnet/csharplang/issues/882">Champion &quot;Negated-condition if statement&quot; #882</a></li>
</ul>
 ]]></description>
				<pubDate>Wed, 12 Dec 2018 09:39:14 +0900</pubDate>
			</item>
			<item>
				<title>C# 8.0 Async streams</title>
				<link>http://ufcpp.net/blog/2018/12/cs8asyncstreams/</link>
				<description><![CDATA[ <p>一応、Preview 1で実装されてはいるんですが、ちょっと不具合があって動かない機能が1つあったりします。</p>
<p>非同期ストリーム(async streams)と呼ばれていて、具体的には以下の2つの機能からなります。</p>
<ul>
<li>非同期イテレーター … 戻り値を<code>IAsyncEnumerable&lt;T&gt;</code>インターフェイスにすることで、<code>await</code>と<code>yield</code>を混在させることができる</li>
<li>非同期 <code>foreach</code> … <code>await foreach</code>という書き方で、<code>IAsyncEnumerable&lt;T&gt;</code>から値を列挙できる</li>
</ul>
<p>要は、一連のデータ(data stream)を、非同期に生成(イテレーター)して非同期に消費(foreach)する機能です。</p>
<h2>非同期 foreach</h2>
<p>消費側の方が簡単なので先に非同期 <code>foreach</code> の方を。
<code>IEnumerable&lt;T&gt;</code>の非同期版である<code>IAsyncEnumerable&lt;T&gt;</code>に対して要素の列挙ができる機能です。
(実際には同名のメソッドを持っていればインターフェイスの実装は不問なところも、同期版<code>foreach</code>と一緒。)</p>
<p>文法の候補は <code>async foreach</code>、<code>foreach async</code>、<code>foreach await</code>など他にもあったんですが、
現状は以下のような<code>await foreach</code>が採用されました。</p>
<pre class="source" title="">
<code><span class="comment">// 非同期 foreach … IAsyncEnumerable からの列挙</span>
<span class="reserved">static</span> <span class="reserved">async</span> <span class="type">Task</span> AsyncForeach(<span class="type">IAsyncEnumerable</span>&lt;<span class="reserved">int</span>&gt; items)
{
    <span class="reserved">await</span> <span class="reserved">foreach</span> (<span class="reserved">var</span> item <span class="reserved">in</span> items)
    {
        <span class="type">Console</span>.WriteLine(item);
    }
}
</code></pre>
<p>これまでの<code>await</code>同様、これが書けるのは非同期メソッド(<code>async</code>修飾付きのメソッド)内だけです。</p>
<p>こいつは、同期版の<code>foreach</code>と似たような感じで、以下のように展開されます。
同期版と比べて、<code>MoveNext</code>と<code>Dispose</code>が非同期になっただけです。</p>
<pre class="source" title="">
<code><span class="reserved">private</span> <span class="reserved">static</span> <span class="reserved">async</span> <span class="type">Task</span> AsyncForeach(<span class="type">IAsyncEnumerable</span>&lt;<span class="reserved">int</span>&gt; items)
{
    <span class="type">IAsyncEnumerator</span>&lt;<span class="reserved">int</span>&gt; e = items.GetAsyncEnumerator();
    <span class="reserved">try</span>
    {
        <span class="reserved">while</span> (<span class="reserved">await</span> e.MoveNextAsync())
        {
            <span class="reserved">int</span> item = e.Current;
            <span class="type">Console</span>.WriteLine(item);
        }
    }
    <span class="reserved">finally</span>
    {
        <span class="reserved">if</span> (e != <span class="reserved">null</span>)
        {
            <span class="reserved">await</span> e.DisposeAsync();
        }
    }
}

</code></pre>
<h2>非同期イテレーター</h2>
<p>続いて生成側の非同期イテレーター。
要は、<code>await</code>と<code>yield</code>を混在できる機能です。</p>
<p>非同期メソッドと同様に <code>async</code>修飾が必須で、
戻り値は<code>IAsyncEnumerable&lt;T&gt;</code>である必要があります。</p>
<pre class="source" title="">
<code><span class="comment">// 非同期イテレーター … await/yield混在</span>
<span class="reserved">static</span> <span class="reserved">async</span> <span class="type">IAsyncEnumerable</span>&lt;<span class="reserved">int</span>&gt; AsyncIterator()
{
    <span class="reserved">await</span> <span class="type">Task</span>.Delay(1);
    <span class="reserved">yield</span> <span class="reserved">return</span> 1;
    <span class="reserved">await</span> <span class="type">Task</span>.Delay(1);
    <span class="reserved">yield</span> <span class="reserved">return</span> 2;
}
</code></pre>
<p>非同期イテレーターから生成されるコードは、
やっぱり<a href="/study/csharp/sp2_iterator.html#complied">同期版のイテレーター</a>と<a href="/study/csharp/sp5_awaitable.html">非同期メソッド</a>を組み合わせたようなコードになります。
イテレーターも非同期メソッド元々結構複雑なので、非同期イテレーターはもっと複雑です。</p>
<p>後述するバグのせいで今のところコンパイルが通らないので、詳細はバグが治ったら(Preview 2？)改めて書こうかと思います。</p>
<h2>IAsyncEnumerable</h2>
<p>非同期<code>foreach</code>でも非同期イテレーターでも、<code>IAsyncEnumerable&lt;T&gt;</code>インターフェイス(<code>System.Collections.Generic</code>名前空間)が出てきます。
これも、割と素直に「<code>IEnumerable&lt;T&gt;</code>の非同期版」という感じのインターフェイスになりました。</p>
<p>以下のようなインターフェイスになる予定です。
(割かし最近変更があって、Preview 1 の時点では <code>CancellationToken</code> を受け取る引数がまだないです。)</p>
<pre class="source" title="">
<code><span class="reserved">using</span> System.Threading;
<span class="reserved">using</span> System.Threading.Tasks;
 
<span class="reserved">namespace</span> System.Collections.Generic
{
    <span class="reserved">public</span> <span class="reserved">interface</span> <span class="type">IAsyncEnumerable</span>&lt;<span class="reserved">out</span> <span class="type">T</span>&gt;
    {
        <span class="type">IAsyncEnumerator</span>&lt;<span class="type">T</span>&gt; GetAsyncEnumerator(<span class="type">CancellationToken</span> cancellationToken = <span class="reserved">default</span>);
    }
    <span class="reserved">public</span> <span class="reserved">interface</span> <span class="type">IAsyncEnumerator</span>&lt;<span class="reserved">out</span> <span class="type">T</span>&gt; : <span class="type">IAsyncDisposable</span>
    {
        <span class="type">T</span> Current { <span class="reserved">get</span>; }
        <span class="type">ValueTask</span>&lt;<span class="reserved">bool</span>&gt; MoveNextAsync();
    }
}
</code></pre>
<p><a href="/blog/2018/10/pickuproslyn1014/">前にちょっと書きましたが</a>、
以下のような構造もちょっと検討されました。</p>
<pre class="source" title="">
<code><span class="reserved">public</span> <span class="reserved">interface</span> <span class="type">IAsyncEnumerator</span>&lt;<span class="reserved">out</span> <span class="type">T</span>&gt; : <span class="type">IAsyncDisposable</span>
{
    <span class="type">ValueTask</span>&lt;<span class="reserved">bool</span>&gt; WaitForNextAsync();
    <span class="type">T</span> TryGetNext(<span class="reserved">out</span> <span class="reserved">bool</span> success);
}
</code></pre>
<p>こちらの没案の方が、うまく使えばパフォーマンスがよくなります。
ただ、ちょっと使いにくい構造なので、ちょっと複雑なことをしようと思うと、パフォーマンスの良いコードを書くのが結構大変になったりします。
なので、「シンプルさにこだわりたい」とのことで、結局、現在の素直な構造になったみたいです。</p>
<h2>Preview 1 でのバグ</h2>
<p>非同期 foreach の方はPreview 1でも問題なく動きます。
一方で、非同期イテレーターの方は、文法上はエラーなく解釈できるんですが、
実行ファイルを生成する段階で「<code>ManualResetValueTaskSourceLogic</code>構造体が存在しない」というエラーを起こします。</p>
<p>どうも、Preview 1としてリリースするブランチが、Roslyn側とcoreclr側で食い違っているみたいです。
非同期イテレーターが内部的に使う型があって、
その型の仕様は最近ちょっと変更されています。
元々は<code>ManualResetValueTaskSourceLogic</code>という名前で実装されていたんですが、
名前も<code>ManualResetValueTaskSourceCore</code>に変更されました。
そして、Roslynの方は変更前のままで、corefxの方は変更後のブランチでPreview 1をリリースしてしまったみたいです。</p>
<p>ソースコードを取ってきて名前だけ&quot;Logic&quot;に戻して動くなら良かったんですが、
ちょっと実装も変わっていて、無理やり動かすのもそこそこ面倒そうでした。
まあ、Preview 2では治っていると思うので、治ったら本気出します。</p>
 ]]></description>
				<pubDate>Tue, 11 Dec 2018 07:54:51 +0900</pubDate>
			</item>
			<item>
				<title>C# 8.0 パターン マッチング</title>
				<link>http://ufcpp.net/blog/2018/12/cs8patterns/</link>
				<description><![CDATA[ <p>今日はパターン マッチングの話。
昨日の<a href="/blog/2018/12/cs8switchexpr/"><code>switch</code>式</a>に引き続き、
真っ先に実装されてそうなものなのに Preview 1 には入っていなかったやつ。
というか、<code>switch</code>式自体、このパターン マッチングの一部として提案されているものです。</p>
<h2>パターン マッチング “完全版”</h2>
<p>パターン マッチングは、元々は C# 7.0 で検討されていたものの、
結局、一部分だけが C# 7.0 に入り、複雑なものは C# 8.0 に回りました。</p>
<table>
<thead>
<tr>
	<th>パターン</th>
	<th>C# のバージョン</th>
	<th>概要</th>
	<th>例</th>
</tr>
</thead>
<tbody>
<tr>
	<td>discard</td>
	<td>C# 7.0</td>
	<td>何にでもマッチ・無視</td>
	<td><code>_</code></td>
</tr>
<tr>
	<td>var</td>
	<td>C# 7.0</td>
	<td>何にでもマッチ・引数で受け取り</td>
	<td><code>var x</code></td>
</tr>
<tr>
	<td>定数パターン</td>
	<td>C# 7.0</td>
	<td>定数との比較</td>
	<td><code>null</code>、<code>1</code></td>
</tr>
<tr>
	<td>型パターン</td>
	<td>C# 7.0</td>
	<td>型の判定</td>
	<td><code>int i</code>、<code>string s</code></td>
</tr>
<tr>
	<td>位置パターン</td>
	<td>C# 8.0</td>
	<td><a href="/study/csharp/datatype/deconstruction/">分解</a>と同じ要領で、<code>Deconstruct</code>を元に(引数の位置に応じて)再帰的にマッチングする</td>
	<td><code>(1, var i, _)</code></td>
</tr>
<tr>
	<td>プロパティ パターン</td>
	<td>C# 8.0</td>
	<td>プロパティに対して再帰的にマッチングする</td>
	<td><code>{ A: 1, B: var i }</code></td>
</tr>
</tbody>
</table>
<p>要するに、再帰的に使える下の2つが C# 8.0 での新機能になります。</p>
<p>まあ、C# 7.0 のやつだと「“パターン”って言うほど複雑なマッチングしてない」感がありました。
(実際、なので C# 7.0 リリース当時は「型スイッチ」みたいな呼び方もされていました。
結局、まあ、C# 8.0 を見越してあくまで「パターン マッチングのうち、型パターンだけは先にリリース」みたいな感じでアナウンスされています。)</p>
<p>例えば以下のような感じ。</p>
<pre class="source" title="">
<code><span class="reserved">public</span> <span class="reserved">class</span> <span class="type">Point</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> X { <span class="reserved">get</span>; }
    <span class="reserved">public</span> <span class="reserved">int</span> Y { <span class="reserved">get</span>; }
    <span class="reserved">public</span> Point(<span class="reserved">int</span> x, <span class="reserved">int</span> y) =&gt; (X, Y) = (x, y);
    <span class="reserved">public</span> <span class="reserved">void</span> Deconstruct(<span class="reserved">out</span> <span class="reserved">int</span> x, <span class="reserved">out</span> <span class="reserved">int</span> y) =&gt; (x, y) = (X, Y);
}
 
<span class="reserved">public</span> <span class="reserved">class</span> <span class="type">C</span>
{
    <span class="reserved">static</span> <span class="reserved">int</span> M(<span class="reserved">object</span> obj)
        =&gt; obj <span class="reserved">switch</span>
        {
            0 =&gt; 1,
            <span class="reserved">int</span> i =&gt; 2,
            <span class="type">Point</span>(1, _) =&gt; 4, <span class="comment">// new!</span>
            <span class="type">Point</span> { X: 2, Y: <span class="reserved">var</span> y } =&gt; y, <span class="comment">// new!</span>
            _ =&gt; 0
        };
}
</code></pre>
<h2>何に使うかと言われると</h2>
<p>まあ、再帰パターンなわけで、再帰的なデータ構造相手なら便利そうではあります。
(再起データ構造自体どのくらいの頻度で使われるかという話を置いておけば…)</p>
<p>例えば、<code>x + 1</code> みたいな式を <code>Add(Variable(x), Const(1))</code> みたいなツリー構造で表す奴とか。
そのツリーに対して、<code>x + 0</code> は <code>x</code> と等しいとか、<code>x * 1</code> は <code>x</code> と等しいとかその手の簡単化をするやつは、以下のように書けるようになります。</p>
<pre class="source" title="">
<code><span class="reserved">public</span> <span class="reserved">static</span> <span class="type">Node</span> Simplify(<span class="reserved">this</span> <span class="type">Node</span> n)
    =&gt; n <span class="reserved">switch</span>
        {
            <span class="type">Add</span>(<span class="reserved">var</span> l, <span class="reserved">var</span> r) =&gt; (l.Simplify(), r.Simplify()) <span class="reserved">switch</span>
            {
                (<span class="type">Const</span>(0), <span class="reserved">var</span> r1) =&gt; r1,
                (<span class="reserved">var</span> l1, <span class="type">Const</span>(0)) =&gt; l1,
                (<span class="reserved">var</span> l1, <span class="reserved">var</span> r1) =&gt; <span class="reserved">new</span> <span class="type">Add</span>(l1, r1)
            },
            <span class="type">Mul</span>(<span class="reserved">var</span> l, <span class="reserved">var</span> r) =&gt; (l.Simplify(), r.Simplify()) <span class="reserved">switch</span>
            {
                (<span class="type">Const</span>(0) c, _) =&gt; c,
                (_, <span class="type">Const</span>(0) c) =&gt; c,
                (<span class="type">Const</span>(1), <span class="reserved">var</span> r1) =&gt; r1,
                (<span class="reserved">var</span> l1, <span class="type">Const</span>(1)) =&gt; l1,
                (<span class="reserved">var</span> l1, <span class="reserved">var</span> r1) =&gt; <span class="reserved">new</span> <span class="type">Mul</span>(l1, r1)
            },
            _ =&gt; n
        };
</code></pre>
<p>(<a href="https://gist.github.com/ufcpp/37702d99a7c0148b3b0d0f8b82e46414">コード全体はGist上に</a>)</p>
<p>ちなみに、単に「複数の値を同時にマッチング」という使い方もできます。
以下のように、<code>(x, y) switch { }</code> でスイッチ。</p>
<pre class="source" title="">
<code><span class="reserved">static</span> <span class="reserved">int</span> Compare(<span class="reserved">int</span>? x, <span class="reserved">int</span>? y)
    =&gt; (x, y) <span class="reserved">switch</span>
    {
        (<span class="reserved">null</span>, <span class="reserved">null</span>) =&gt; 0,
        (<span class="reserved">null</span>, _) =&gt; -1,
        (_, <span class="reserved">null</span>) =&gt; 1,
        ({} ix, {} iy) =&gt; ix.CompareTo(iy)
    };
</code></pre>
<p>要するに、このコードは「タプルに対する位置パターン」なんですが、
それが「<code>x</code>, <code>y</code> に対して多値マッチング」っぽく使えます。</p>
<p>(あと、<code>{}</code>は後述しますが、「プロパティ パターン」(の、中身空っぽ)です。)</p>
<p>ちなみに、<code>switch</code> ステートメントでも以下のような書き方ができます。</p>
<pre class="source" title="">
<code><span class="reserved">static</span> <span class="reserved">int</span> Compare(<span class="reserved">int</span>? x, <span class="reserved">int</span>? y)
{
    <span class="reserved">switch</span> (x, y)
    {
        <span class="reserved">case</span> (<span class="reserved">null</span>, <span class="reserved">null</span>): <span class="reserved">return</span> 0;
        <span class="reserved">case</span> (<span class="reserved">null</span>, _): <span class="reserved">return</span> -1;
        <span class="reserved">case</span> (_, <span class="reserved">null</span>): <span class="reserved">return</span> 1;
        <span class="reserved">case</span> ({ } ix, { } iy): <span class="reserved">return</span> ix.CompareTo(iy);
        }
    }
}
</code></pre>
<p>先ほど書いた通り、これは実際には「タプルに対する位置パターン」なんですが、
だったら、本来は <code>switch ((x, y))</code> という書き方(内側の<code>()</code>がタプル構築、外側の<code>()</code>が<code>switch</code>ステートメントのもの)をする必要があります。
これも C# 8.0 の新機能で、「タプルだったら<code>()</code>を1個省略して、多値 <code>switch</code> っぽく書けるようにした」というものです。</p>
<h2>非 null マッチング</h2>
<p>ちなみに、プロパティ パターンの <code>{}</code> は、
プロパティを調べる前に本体が null ではないことをチェックします。
中身が空っぽのプロパティ パターンでも null チェックだけは挿入されるので、
<code>x is {}</code>で、「<code>x</code>はnullではない」の意味で使えます。</p>
<p>C# 7.0 までのパターンだと、null チェックを楽に書く手段がなかったです。</p>
<pre class="source" title="">
<code><span class="reserved">struct</span> <span class="type">LongLongNamedStruct</span> { }
 
<span class="reserved">void</span> M1(<span class="type">LongLongNamedStruct</span>? x)
{
    <span class="comment">// こういう書き方だと null チェックになる。</span>
    <span class="reserved">if</span> (x <span class="reserved">is</span> <span class="type">LongLongNamedStruct</span> nonNull)
    {
        <span class="comment">// obj が null じゃない時だけここが実行される。</span>
        <span class="comment">// でも、x の型が既知なのに、長いクラス名をわざわざ書くのはしんどい…</span>
    }
}
 
<span class="reserved">void</span> M2(<span class="type">LongLongNamedStruct</span>? x)
{
    <span class="comment">// が、var パターンは null にもマッチしちゃう。</span>
    <span class="comment">// (var は「何にでもマッチ」。null でも true になっちゃう。)</span>
    <span class="reserved">if</span> (x <span class="reserved">is</span> <span class="reserved">var</span> nullable)
    {
        <span class="comment">// obj が null でもここが実行される。</span>
    }
}
</code></pre>
<p>もちろん、単に null チェックだけなら <code>!(x is null)</code> とか <code>x.HasValue</code> でいいんですけども、
値を使いたければその後ろで <code>var nonNull = x.GetValueOrDefault();</code> を書かないと行けないのがしんどく。</p>
<p>そこで、プロパティ パターンが使えます。
以下のように、「空のプロパティ パターン」を書けば、「非 null のときだけ」判定ができます。</p>
<pre class="source" title="">
<code><span class="reserved">void</span> M3(<span class="type">LongLongNamedStruct</span>? x)
{
    <span class="comment">// (C# 8.0) プロパティ パターンであれば、null チェックを含む。</span>
    <span class="reserved">if</span> (x <span class="reserved">is</span> {} nonNull)
    {
        <span class="comment">// obj が null じゃない時だけここが実行される。</span>
    }
}
</code></pre>
<p>ちょっと「知ってないと使えない仕様」ですけども…
覚えておくと便利です。</p>
<h2>対称性</h2>
<p>C# 7.0 の時、タプルとか分解の構文を決めるにあたって、C# チームは結構「対称性」を気にしていました。</p>
<p>まず、タプルは「引数と対になるもの」として考えられています。</p>
<pre class="source" title="">
<code><span class="comment">// タプル型宣言と引数宣言は同じような見た目。</span>
(<span class="reserved">int</span> x, <span class="reserved">int</span> y) tup0;
<span class="reserved">int</span> method(<span class="reserved">int</span> x, <span class="reserved">int</span> y) =&gt; x + y;
 
<span class="comment">// タプル構築はメソッド呼び出しみたいな書き方になる。</span>
<span class="comment">// 位置指定:</span>
<span class="reserved">var</span> tup1 = (1, 2);
<span class="reserved">var</span> ret1 = method(1, 2);
 
<span class="comment">// 名前指定:</span>
<span class="reserved">var</span> tup2 = (x: 1, y: 2);
<span class="reserved">var</span> ret2 = method(x: 1, y: 2);
 
<span class="comment">// タプル戻り値は、引数と同じような書き方に。</span>
(<span class="reserved">int</span> x, <span class="reserved">int</span> y) swap(<span class="reserved">int</span> x, <span class="reserved">int</span> y) =&gt; (y, x);
</code></pre>
<p>また、分解は「コンストラクターと対になるもの」です。</p>
<pre class="source" title="">
<code><span class="reserved">public</span> <span class="reserved">class</span> <span class="type">Point</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> X { <span class="reserved">get</span>; <span class="reserved">set</span>; }
    <span class="reserved">public</span> <span class="reserved">int</span> Y { <span class="reserved">get</span>; <span class="reserved">set</span>; }
 
    <span class="comment">// 複数の値を組み合わせて1つの型にまとめるのが構築(construct)。</span>
    <span class="reserved">public</span> Point(<span class="reserved">int</span> x = 0, <span class="reserved">int</span> y = 0) =&gt; (X, Y) = (x, y);
 
    <span class="comment">// 1つにまとまっている値をバラバラに戻すのが分解(deconstruct)。</span>
    <span class="reserved">public</span> <span class="reserved">void</span> Deconstruct(<span class="reserved">out</span> <span class="reserved">int</span> x, <span class="reserved">out</span> <span class="reserved">int</span> y) =&gt; (x, y) = (X, Y);
}
</code></pre>
<pre class="source" title="">
<code><span class="reserved">var</span> p = <span class="reserved">new</span> <span class="type">Point</span>(1, 2); <span class="comment">// contruct</span>
<span class="reserved">var</span> (x, y) = p;          <span class="comment">// deconstruct</span>
</code></pre>
<p>C# 8.0 の再帰パターンもこの話の延長にあります。</p>
<pre class="source" title="">
<code><span class="comment">// 位置指定で構築できるんなら、位置指定でマッチングできるべき</span>
<span class="reserved">var</span> p1 = <span class="reserved">new</span> <span class="type">Point</span>(1, 2);
<span class="reserved">var</span> r1 = p1 <span class="reserved">is</span> (1, 2);
 
<span class="comment">// 名前指定で構築できるんなら、名前指定でマッチングできるべき</span>
<span class="reserved">var</span> p2 = <span class="reserved">new</span> <span class="type">Point</span>(x: 1, y: 2);
<span class="reserved">var</span> r2 = p2 <span class="reserved">is</span> (x: 1, y: 2);
 
<span class="comment">// 初期化子でプロパティ指定できるんなら、プロパティ指定でマッチングできるべき</span>
<span class="reserved">var</span> p3 = <span class="reserved">new</span> <span class="type">Point</span> { X = 1, Y = 2 };
<span class="reserved">var</span> r3 = p3 <span class="reserved">is</span> { X: 1, Y: 2 };
 
<span class="comment">// 混在構築できるんなら、混在マッチングできるべき</span>
<span class="reserved">var</span> p4 = <span class="reserved">new</span> <span class="type">Point</span>(x: 1) { Y = 2 };
<span class="reserved">var</span> r4 = p4 <span class="reserved">is</span> (1, _) { Y: 2 };
</code></pre>
<h2>最近の変更</h2>
<p>冒頭で言ったように、再帰パターンも元々は C# 7.0 で考えられていました。
それに、C# 8.0 機能の中では相当早い段階から実装済みで、
確か今年の初めくらいにはすでに実装がありました。</p>
<p>(なので、<a href="https://sharplab.io/#v2:EYLgZgpghgLgrgJwgZwLRIMaOQSwG4SoAOsMECAdsgD4ACADAAS0CMA3ALABQ3tAzMxYA2ZgCZGAYW4Bvbo3nMBrETgoxJUADZZNsCAAoYACxzJGAOQD2AEwiMKAGkar1ADwCUchd4C8APntGZAB3HBgMIy9veVkuaPjGADUoBEY8Rn9GVwcohPkJSyp1DAyAjAA6ZM04CBy4vIUAQWtrfTwUxk0ndtSEd1LO8oktHT19D0YAakYEIZG4XTJx9zqGhQBZBbaOrrSOvoHNOe0FsYmAKhnj0aWPVbXGAH0B4wRLYPsID4BJCnbNHDWADyRHIsBwhQAoq4MBAiDAIRR9J56vEAL6cHioxSCERWWyMADKOAAtkQAWAAJ6GExmfF2CgovKZChBULhSLY7yxB6MZqtHqdbr7fqZfRHYlkinUlZXSXknBU5H9EJhCK5PI83kKfQFIr6eiywUIFiigIm+7axjbVKaFhOPXIGAG9xmzr2jUPG3u4W9U0DChfPktcX2mamz3oy0NTaab27Y1u8XleXS5FOWapxUylXs9VchJaq26wpOl2MDBOR5uyuRhr6R4O0vOw0VmvR3kl/Wm33ht0Wut5eNhx3O01uu0dr2Cyd7P1uwMfWOhjMRgtRwcKZ4susY7i5ZTMAAsjHWUFUyNyReigtcGQsNgg5QAGpi8qwAJzjRiXO/TU1vgkn76CBLA/lkUyMEwv79JcpopqSCpKq6gHxMBIF/owoiwdamF8K61ynEs46oYwaLcORWL8IwUDAE6CBQBg6i0OI9IyAeSjCDM0DWIUmiUg+BLPvei5JCkyKkdRh6IQCGBhIwliggxMCWKk9L6C4ezVBAC5BqO2zae4kmcXij4KUpsCqZM+j0p0EBgDATi2QgOAAOZGDAukfPy4r2Y5MxuR5Rkcbigl2IpYIqQg5w2WZmh+U5Zkue5nkBkGy7xQ5GaBZ5mKUbwSjiMkqQgGFjDSDilgEAgLkEqwTAACqWISMAuRQrnIgMABErhdWwZH7lwUniKOjClWxXDXtRmlVDU5WMK5EAwP1lHeNR+maf8NT9BVs12D4Wk1CtIW0CeAAiEAYM2CBwEx+iWHA6ibVo20DFt+1idpxkKdVtV2PVjBNS1bUdW6e3lEDrWqKDeWDcNwbWGNYXsdi1G2QAMn582LctA2owItkAEo5djS3HfjCOxQSmX+c5OVJpjWWMMTKWitaNPZaz32nYwF1XUUN13Q96i2RzCmPWVyVBQMvlM1LqUHfojP+SzQXfVV5B/YIjXNVD7WdZkAAkXX6NIysQ7rIPImikHSKrMAW8D0PW+4fUUXDhWngsSMTVNBNmcrpO46tCho2Z9tB+Ta0CMuosJZL9My8rTj22zsv+fLwUUzzfPXbdzrC2VYuF3TrMy2Lmf3kr8ep+rv2Av9LA607+tusbZt+Y7eugzblx2zlXdW+4aJu1waJAA==">sharplab.io</a>で割かし安定して試せたりします。
Visual Studio 2019 Preview 1 で実装されていなくても割と細かくブログを書けるのはこれのおかげ。)</p>
<p>個人的には「C# 7.4 があってもよかったんじゃ… 再帰パターンだけのリリース」とかもちょっと思ったり。
C# チーム的には「マイナー リリースで出すほど小さい機能ではない」とのことで、C# 8.0 での追加になります。</p>
<p>ということで、大半の機能はだいぶ前から試せる状態にあったんですが、
割と最近にもいくつか細かい追加・変更がありました。</p>
<ul>
<li><code>switch (x, y)</code> の「<code>()</code> を1段省略」は割と最近の採用</li>
<li>
プロパティ パターンの構文は <code>{ X is pattern }</code> か <code>{ X = pattern }</code> か <code>{ X: pattern }</code> のどれがいいか
<ul>
<li><code>:</code> になったのは割と最近</li>
</ul>
</li>
<li>
<code>var (x)</code> みたいな、「1引数 <code>Deconstruct</code>」
<ul>
<li>キャストや、「<code>(1)</code>は単なる<code>1</code>と同じ意味」という既存の構文との弁別の問題があるものの、<code>var</code>の後ろなら弁別できるので認めようということに最近なった</li>
</ul>
</li>
<li>同じく、「0引数<code>Desonctruct</code>」に対する<code>var ()</code>パターンも</li>
</ul>
 ]]></description>
				<pubDate>Mon, 10 Dec 2018 10:00:09 +0900</pubDate>
			</item>
			<item>
				<title>C# 8.0 switch 式</title>
				<link>http://ufcpp.net/blog/2018/12/cs8switchexpr/</link>
				<description><![CDATA[ <p>今日は <code>switch</code> 式の話。
ステートメントではなく、式。
<code>var y = x switch { ... }</code> みたいに書ける構文です。</p>
<p>C# 8.0 候補の中でも割と早い段階に実装されていて、
「the patterns and ranges preview」とかいって<a href="https://github.com/dotnet/csharplang/wiki/vNext-Preview">Preview 公開</a>もされていました。
(後述するように、<code>switch</code>式は「patterns」のおまけです。)</p>
<p>なのでてっきり、Visual Studio 2019 Preview でもまず真っ先に入ると思っていたんですが。
なぜか Preview 1 には入らなかったという…</p>
<p>(たぶん、パターン マッチングにまだもうちょっと調整したいことができたから？)</p>
<h1>新しい switch</h1>
<p>C# の <code>switch</code> ステートメント(C# 1.0 の頃からあるやつ)は、
C 言語系の影響を受けすぎている感じがあり、
使いにくいものでした。
C# 1.0 当時の情勢から言うと C 言語の <code>switch</code> を意識するのはしょうがなかったと思いますが、
それから15年以上経った今となってはちょっとしんどい文法です。</p>
<p>例えばこれまでだと、以下のような書き方を時々見ると思います。</p>
<pre class="source" title="">
<code><span class="reserved">public</span> <span class="reserved">void</span> M(<span class="type">年号</span> e)
{
    <span class="reserved">int</span> y;
    <span class="reserved">switch</span> (e)
    {
        <span class="reserved">case</span> 明治:
            y = 45;
            <span class="reserved">break</span>;
        <span class="reserved">case</span> 大正:
            y = 15;
            <span class="reserved">break</span>;
        <span class="reserved">case</span> 昭和:
            y = 64;
            <span class="reserved">break</span>;
        <span class="reserved">case</span> 平成:
            y = 31;
            <span class="reserved">break</span>;
        <span class="reserved">default</span>: <span class="reserved">throw</span> <span class="reserved">new</span> <span class="type">InvalidOperationException</span>();
    }
    <span class="comment">// y を使って何か</span>
}
</code></pre>
<p>しんどい理由は、</p>
<ul>
<li>それぞれの条件で1つずつ値を返したいだけなのにステートメントを求められる</li>
<li><code>break</code> が必須</li>
<li><code>case</code> ラベルもうざい</li>
</ul>
<p>という辺り。
以下のように別メソッドを1段挟めば多少緩和するようなそうでもないような…</p>
<pre class="source" title="">
<code><span class="reserved">public</span> <span class="reserved">void</span> M(<span class="type">年号</span> e)
{
    <span class="reserved">int</span> lastYear()
    {
        <span class="reserved">switch</span> (e)
        {
            <span class="reserved">case</span> 明治: <span class="reserved">return</span> 45;
            <span class="reserved">case</span> 大正: <span class="reserved">return</span> 15;
            <span class="reserved">case</span> 昭和: <span class="reserved">return</span> 64;
            <span class="reserved">case</span> 平成: <span class="reserved">return</span> 31;
            <span class="reserved">default</span>: <span class="reserved">throw</span> <span class="reserved">new</span> <span class="type">InvalidOperationException</span>();
        }
    }
 
    <span class="reserved">var</span> y = lastYear();
    <span class="comment">// y を使って何か</span>
}
</code></pre>
<p>一方、C# 8.0 で、<code>switch</code> に式として使えるバージョンが追加されます。
この「<code>switch</code> 式」を使えば、以下のように書き直せます。</p>
<pre class="source" title="">
<code><span class="reserved">public</span> <span class="reserved">void</span> M(<span class="type">年号</span> e)
{
    <span class="reserved">var</span> y = e <span class="reserved">switch</span>
    {
        明治 =&gt; 45,
        大正 =&gt; 15,
        昭和 =&gt; 64,
        平成 =&gt; 31,
        _ =&gt; <span class="reserved">throw</span> <span class="reserved">new</span> <span class="type">InvalidOperationException</span>()
    };
}
</code></pre>
<p><code>case</code>や<code>break</code>が消えてちょっとすっきり。</p>
<h2>提案上はパターン マッチングの一部</h2>
<p>今の C# の文法は、<a href="https://github.com/dotnet/csharplang">csharplang リポジトリ</a>上で提案があって、採用することに決まったものは <a href="https://github.com/dotnet/csharplang/milestones">Milestone</a> で管理されていたりします。</p>
<p>が、<code>switch</code> 式はぱっと見 <a href="https://github.com/dotnet/csharplang/milestone/8">C# 8.0 Milestone</a> に並んでいない。
なぜかというと、パターン マッチングの一部として提案されたから。
<a href="https://github.com/dotnet/csharplang/issues/45">パターン マッチングの方の提案 issue</a>を覗いてみれば、その中に「switch expression」の文字もあります。
実装も、<a href="https://github.com/dotnet/roslyn/tree/features/recursive-patterns">features/recursive-patterns</a>ブランチ内で行われていたり。</p>
<p>けど、検索性は最悪なんですよね。
ただでさえ「issue の9割は重複か実現不能な提案」とか陰口言われるレベルの csharplang なのに、検索性が悪いとかちょっと…
実際、もう実装された後になって、「<code>switch</code> 式が欲しい」という重複提案が何度かありました…</p>
<h2>後置き記法</h2>
<p>書き方が <code>e switch {}</code> というちょっと変わった記法。</p>
<p>ステートメントの方の <code>switch</code> との弁別の意味もあるみたいです。<code>switch (e)</code> から初めてしまうとステートメントと混同してしまう。
かといって、新たに別キーワードを導入(例えば <code>match (e) ...</code>)するのもいまいち評判がよくなく。
(ちなみに、当初案はこの<code>match</code>キーワードの導入でした。
なので、長らくこの機能は「<code>match</code> 式」と呼ばれていました。)</p>
<p>あと、基本的に前置きの記法は評判が悪いです。
否定の<code>!</code>とかキャストとか。
csharplangのissueでも、「後置きキャスト文法が欲しい」という提案もよく見ます。
わざわざ <code>As</code> なんとかみたいな名前の拡張メソッドを生やすこともよくあります。
<code>!</code>の方も、<code>Not()</code>とか<code>Negate()</code>みたいな拡張メソッドを書いたことある人、結構いるんじゃないでしょうか。</p>
<p>なんか、前置きって書きにくいんですよねぇ。どうしても、「先に式を書いたうえで、カーソルを前に戻して、改めて<code>!</code>とかを入力する」みたいな書き方をしてしまい、そのカーソルを戻す作業がストレス。</p>
<p>そんな感じのこと、みんな思っているようで、<code>swtich</code>式も後置きの <code>e switch {}</code> になりました。</p>
<h2><code>=&gt;</code></h2>
<p><code>case</code> の方も提案ではいろいろとバリエーションがありました。</p>
<p><code>case</code> の区切り:</p>
<ul>
<li><code>,</code> 区切り</li>
<li><code>;</code> 区切り</li>
</ul>
<p><code>case</code> の書き方</p>
<ul>
<li><code>x: experssion</code></li>
<li><code>x -&gt; experssion</code></li>
<li><code>x ~&gt; experssion</code></li>
<li><code>x =&gt; experssion</code></li>
</ul>
<p>以下のように、<code>when</code>句に条件演算子<code>?:</code>を書いたり、
返す値にラムダ式を書いたりできるので、<code>:</code>とか<code>=&gt;</code>とかも案外弁別に悩む選択肢です。</p>
<pre class="source" title="">
<code><span class="reserved">var</span> i = x <span class="reserved">switch</span>
{
    <span class="reserved">string</span> s <span class="reserved">when</span> (s.Length &gt;= 1 ? s[0] &lt;= 0x7F : <span class="reserved">true</span>) =&gt; () =&gt; <span class="reserved">true</span>,
    _ =&gt; (<span class="type">Func</span>&lt;<span class="reserved">bool</span>&gt;)(() =&gt; <span class="reserved">false</span>)
};
</code></pre>
<p>(ちなみにこのコード、<code>()</code>がないとコンパイルが通りません。
<code>()</code>の入れ子弁別している模様。)</p>
<p>かといって見慣れない(ポインター用な)<code>-&gt;</code>とか、
ほんとに新たに追加する必要がある<code>~&gt;</code>とかもだいぶ気持ち悪いです。</p>
<p>結局、アンケート的なのを取った結果、最終的に <code>x =&gt; expression,</code> に決まりました。</p>
 ]]></description>
				<pubDate>Sun, 09 Dec 2018 12:05:08 +0900</pubDate>
			</item>
			<item>
				<title>C# 8.0 null許容参照型</title>
				<link>http://ufcpp.net/blog/2018/12/cs8nrt/</link>
				<description><![CDATA[ <p>今日も C# 8.0 の新機能の話。
C# 8.0 の中でおそらく一番の目玉機能扱いになると思われる
null許容参照型の話です。</p>
<h2>参照型でもそのままでは null を認めない</h2>
<p>要は、参照型に対しても、単に<code>T</code>と書くとnullを認めない型になり、
null許容にしたければ<code>T?</code>と書くようにするという機能です。</p>
<pre class="source" title="">
<code><span class="reserved">#nullable enable</span>
    <span class="comment">// string には null が来ない</span>
    <span class="comment">// null が来ないなら s.Length で OK</span>
    <span class="reserved">static</span> <span class="reserved">int</span> M1(<span class="reserved">string</span> s) =&gt; s.Length;
 
    <span class="comment">// string? には null が来る</span>
    <span class="comment">// null が来るのに s.Length (null チェックしてない)はダメ</span>
    <span class="reserved">static</span> <span class="reserved">int</span> M2(<span class="reserved">string</span>? s) =&gt; <span class="warning">s.Length</span>;
 
    <span class="comment">// string? には null が来る</span>
    <span class="comment">// null が来ても ?. や ?? を駆使すれば OK</span>
    <span class="reserved">static</span> <span class="reserved">int</span> M3(<span class="reserved">string</span>? s) =&gt; s?.Length ?? 0;
</code></pre>
<h3>null-forgiving</h3>
<p>原理的に null を消せない場合もあります。
一例としては循環参照を作りたいときとかなんですが、
例えば以下のような感じで一時的に有効な値を持てない場合があり得ます。</p>
<pre class="source" title="">
<code><span class="reserved">class</span> <span class="type">Node</span>
{
    <span class="reserved">public</span> <span class="type">Node</span> Next { <span class="reserved">get</span>; <span class="reserved">private</span> <span class="reserved">set</span>; }
    <span class="reserved">public</span> Node(<span class="type">Node</span> next) =&gt; Next = next;
 
    <span class="reserved">public</span> (<span class="type">Node</span> a, <span class="type">Node</span> b) CircularDependency()
    {
        <span class="comment">// 参照に循環があるとき、どうしても片方は最初から有効な参照にできない</span>
        <span class="reserved">var</span> a = <span class="reserved">new</span> <span class="type">Node</span>(<span class="reserved"><span class="warning">null</span></span>); <span class="comment">// やむなくいったん null</span>
        <span class="reserved">var</span> b = <span class="reserved">new</span> <span class="type">Node</span>(a);
        a.Next = b;
 
        <span class="comment">// メソッドを抜けるまでには有効な値を入れておくのでどうかご容赦願いたい…</span>
        <span class="reserved">return</span> (a, b);
    }
}
</code></pre>
<p>こういうとき、警告をもみ消す処理があると問題を回避できます。
そのための演算子が後置きの<code>!</code>。</p>
<pre class="source" title="">
<code><span class="comment">// 非 null なところに null を渡すのを容赦してもらう</span>
<span class="reserved">var</span> a = <span class="reserved">new</span> <span class="type">Node</span>(<span class="reserved">null</span>!);
<span class="reserved">var</span> b = <span class="reserved">new</span> <span class="type">Node</span>(a);
a.Next = b;
</code></pre>
<p>今のところ、この演算子は null-forgiving 演算子と呼ばれています。
(日本語だとどうするといいんだろう。直訳だと「null容赦」。)
(ちなみに、口頭だとたぶん<code>!</code>をそのまま読んで、「びっくり演算子」(英語でも&quot;bang&quot;とか)呼ばれると思います。)</p>
<p>null-forgiving演算子はあくまで「警告になるコードを無視してもらう」という処理です
(そこが許容(able)と容赦(forgive)の差)。
コンパイル結果には何も影響を及ぼさないので、
間違ったコードを書くと普通に<code>NullReferenceException</code>が出るようになります。
(実行時のチェック処理とかは別に何も挿入されません。)</p>
<h2>途中入り</h2>
<p>機能名が「null許容参照型」になっている(非null参照型じゃない)のは、
何もつけない<code>T</code>が非nullで、null許容の方に<code>?</code>を付けるという文法を選んだからです。</p>
<p>ということは、
C# 7.x 以前であれば参照型<code>T</code>はnullを許容していたわけで、
これまでと<code>T</code>の意味が変わります。
そのせいで、最初から<code>T?</code>を考えて言語設計していたなら必要なかったであろう苦労が少しあります。
具体的には、以下のような感じになっています。</p>
<ul>
<li>有効にするにはオプション指定が必要</li>
<li>エラーではなく警告ベース</li>
<li>値型の<code>T?</code>と扱いが違う</li>
<li>ジェネリクスに対して使いづらい</li>
<li>漏れがあり得る</li>
</ul>
<h3>オプション指定</h3>
<p>何も指定しないと、C# 7.x までの動きと同様になります。
参照型 <code>T</code> には null があり得るし、<code>T?</code> とは書けません
(警告が出るだけですが)。</p>
<p>null 許容参照型を有効にするには、以下の2通りのオプション指定の方法があります。</p>
<ul>
<li><code>#nullable</code>ディレクティブ … ファイルの行単位でオン/オフ切り替え</li>
<li><code>NullableReferenceTypes</code> タグ … プロジェクト全体でオン/オフ切り替え</li>
</ul>
<p>前者は、<code>#if</code>や<code>#pragma</code>などと同じ<a href="/study/csharp/sp_preprocess.html">プリプロセス命令</a>です。
以下のように、<code>#nullable</code>を書いた行から先がオン/オフ切り替わります。</p>
<pre class="source" title="">
<code><span class="reserved">#nullable enable</span>
    <span class="reserved">static</span> <span class="reserved">void</span> M1(<span class="reserved">string</span> s)
    {
        <span class="comment">// enable 時に string に null を代入したら警告</span>
        s = <span class="reserved"><span class="warning">null</span></span>;
    }
 
<span class="reserved">#nullable disable</span>
    <span class="reserved">static</span> <span class="reserved">void</span> M2(<span class="reserved">string</span> s)
    {
        <span class="comment">// disable にしたので string に null を代入しても何も言われない</span>
        s = <span class="reserved">null</span>;
    }

</code></pre>
<p>これら<code>enable</code>、<code>disable</code>に加えて、
リリース版までには<code>restore</code>と<code>safeonly</code>というオプションも入るそうです。
(<code>restore</code>は名前通り前の状態に戻すもの。
<code>safeonly</code>の方はちょっと<a href="https://github.com/dotnet/csharplang/blob/master/proposals/nullable-reference-types-specification.md">仕様(書きかけ)</a>を読んだだけだとピンとこなかったので、
実装されたら改めて確認します…)</p>
<p>後者は、csproj に対して設定を書きます。
(最終的にはVisual Studio上の設定画面からもオン/オフができると思いますが、
現状ではcsprojを手書きする必要があります。)</p>
<pre class="xsource" title="">
<code><span class="attvalue">&lt;</span><span class="element">Project</span><span class="attvalue"> </span><span class="attribute">Sdk</span><span class="attvalue">=</span>&quot;<span class="attvalue">Microsoft.NET.Sdk</span>&quot;<span class="attvalue">&gt;</span>
 
<span class="attvalue">  &lt;</span><span class="element">PropertyGroup</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">OutputType</span><span class="attvalue">&gt;</span>Exe<span class="attvalue">&lt;/</span><span class="element">OutputType</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">TargetFramework</span><span class="attvalue">&gt;</span>netcoreapp3.0<span class="attvalue">&lt;/</span><span class="element">TargetFramework</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">LangVersion</span><span class="attvalue">&gt;</span>8.0<span class="attvalue">&lt;/</span><span class="element">LangVersion</span><span class="attvalue">&gt;</span>
<em><span class="attvalue">    &lt;</span><span class="element">NullableReferenceTypes</span><span class="attvalue">&gt;</span>true<span class="attvalue">&lt;/</span><span class="element">NullableReferenceTypes</span><span class="attvalue">&gt;</span></em>
<span class="attvalue">  &lt;/</span><span class="element">PropertyGroup</span><span class="attvalue">&gt;</span>
 
<span class="attvalue">&lt;/</span><span class="element">Project</span><span class="attvalue">&gt;</span>

</code></pre>
<p>完全に1から書くプロジェクトの場合ならオンになっていて特に困ることもないので、
積極的にこのオプションを指定するといいと思います。
<a href="/blog/2018/12/directorybuild/">先日書きましたが</a>、<code>Directory.Build.props</code>に書くのもありかもしれません。</p>
<h3>警告ベース</h3>
<p>null 許容参照型がらみの違反は、全て警告になっていて、エラーにはなりません。
オプションでオン/オフできるとは言え既存のC#とは<code>T</code>の意味が変わるものなので、エラーにするのは怖いというのがあると思います。
また、後述するように漏れがあり得るので、
もしかするとエラーにしてしまうとまずい状況もあり得るかもしれません。</p>
<p>まあ、C# には「警告をエラーとして扱う」というオプションもあるので、
「null は絶対に許さない。慈悲はない」という方はcsprojに<code>TreatWarningsAsErrors</code>を加えるといいと思います。</p>
<pre class="xsource" title="">
<code><span class="attvalue">&lt;</span><span class="element">Project</span><span class="attvalue"> </span><span class="attribute">Sdk</span><span class="attvalue">=</span>&quot;<span class="attvalue">Microsoft.NET.Sdk</span>&quot;<span class="attvalue">&gt;</span>
 
<span class="attvalue">  &lt;</span><span class="element">PropertyGroup</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">OutputType</span><span class="attvalue">&gt;</span>Exe<span class="attvalue">&lt;/</span><span class="element">OutputType</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">TargetFramework</span><span class="attvalue">&gt;</span>netcoreapp3.0<span class="attvalue">&lt;/</span><span class="element">TargetFramework</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">LangVersion</span><span class="attvalue">&gt;</span>8.0<span class="attvalue">&lt;/</span><span class="element">LangVersion</span><span class="attvalue">&gt;</span>
<em><span class="attvalue">    &lt;</span><span class="element">NullableReferenceTypes</span><span class="attvalue">&gt;</span>true<span class="attvalue">&lt;/</span><span class="element">NullableReferenceTypes</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">TreatWarningsAsErrors</span><span class="attvalue">&gt;</span>true<span class="attvalue">&lt;/</span><span class="element">TreatWarningsAsErrors</span><span class="attvalue">&gt;</span></em>
<span class="attvalue">  &lt;/</span><span class="element">PropertyGroup</span><span class="attvalue">&gt;</span>
 
<span class="attvalue">&lt;/</span><span class="element">Project</span><span class="attvalue">&gt;</span>

</code></pre>
<p>ちなみに、「全部警告にするにしてもオプション指定必須、既定動作ではオフ」なのもこいつのせいです。
例え警告であっても、既存コードに対して警告を起こす変更は破壊的変更になります。</p>
<h3>null 許容“値型”との差</h3>
<p><code>T?</code>といえば、C# には、2.0 の頃からnull許容型というものがあります。
本来絶対にnullがない構造体<code>T</code>に対して、<code>T?</code>と書くことでnull許容にできる機能です。
C# 8.0で「null許容参照型」が入ってしまったので、
これまでの「null許容型」は区別のために「null許容“値型”」と呼び変えるようになると思います。</p>
<p>見た目はどちらも「<code>T</code>に対して<code>T?</code>でnull許容」ですが、
結構扱いに差があります。</p>
<p>まず根本的な差として、内部的な実装方法が全然異なります。
値型の場合は<code>T</code>と<code>T?</code>が明確に違う型ですが、
参照型の場合は<code>T?</code>も内部的に<code>T</code>になっていて、単に C# コンパイラーがフロー解析を頑張るだけになっています。</p>
<pre class="source" title="">
<code><span class="comment">// null 許容値型は Nullable&lt;T&gt; 構造体が作られる</span>
<span class="comment">// T と T? は型システムのレベルで別の型</span>
<span class="comment">// なので、typeof の結果もことなる</span>
<span class="type">Console</span>.WriteLine(<span class="reserved">typeof</span>(<span class="reserved">int</span>) == <span class="reserved">typeof</span>(<span class="reserved">int</span>?)); <span class="comment">// false</span>
 
<span class="comment">// null 許容参照型は C# がフロー解析するだけ</span>
<span class="comment">// T? と書いても、内部的には T のまま</span>
<span class="comment">// なので、typeof の結果は同じ</span>
<span class="type">Console</span>.WriteLine(<span class="reserved">typeof</span>(<span class="reserved">string</span>) == <span class="reserved">typeof</span>(<span class="reserved">string</span>?)); <span class="comment">// true</span>
</code></pre>
<p>この余波なんですが、例えば以下のような差が出ます。</p>
<pre class="source" title="">
<code><span class="reserved">static</span> <span class="reserved">void</span> M(<span class="reserved">string</span>? x)
{
    <span class="comment">// 参照型の場合、フロー解析で保証をしている</span>
    <span class="comment">// この if を抜けた時点で、x が null でないことが保証される</span>
    <span class="reserved">if</span> (x == <span class="reserved">null</span>) <span class="reserved">return</span>;
 
    <span class="comment">// なので、? の付かない string に代入できるようになる</span>
    <span class="reserved">string</span> y = x;
}
 
<span class="reserved">static</span> <span class="reserved">void</span> M(<span class="reserved">int</span>? x)
{
    <span class="comment">// 値型の場合、型自体が違う</span>
    <span class="comment">// この if を抜けても x はあくまで Nullable&lt;int&gt; 型</span>
    <span class="reserved">if</span> (x == <span class="reserved">null</span>) <span class="reserved">return</span>;
 
    <span class="comment">// なので、「int? を int に暗黙的に変換できません」となる</span>
    <span class="reserved">int</span> y = <span class="error">x</span>;
}
</code></pre>
<pre class="source" title="">
<code><span class="comment">// int と int? は別の型なので、オーバーロード可能</span>
<span class="reserved">void</span> M(<span class="reserved">int</span> x) { }
<span class="reserved">void</span> M(<span class="reserved">int</span>? x) { }
 
<span class="comment">// string と string? 型システム上は同じ型なので、オーバーロードできない</span>
<span class="reserved">void</span> M(<span class="reserved">string</span> x) { }
<span class="reserved">void</span> <span class="error">M</span>(<span class="reserved">string</span>? x) { }
</code></pre>
<h3>ジェネリクス</h3>
<p>ある程度はジェネリックな型に対しても使えます。
例えば、null 許容参照型を表す <code>class?</code> 制約というものも追加されます。</p>
<pre class="source" title="">
<code><span class="reserved">struct</span> <span class="type">A</span>&lt;<span class="type">T</span>&gt; <span class="reserved">where</span> <span class="type">T</span> : <span class="reserved">class</span>
{
    <span class="reserved">public</span> <span class="type">T</span> Value;
}
 
<span class="reserved">struct</span> <span class="type">B</span>&lt;<span class="type">T</span>&gt; <span class="reserved">where</span> <span class="type">T</span> : <span class="reserved">class</span>?
{
    <span class="reserved">public</span> <span class="type">T</span> Value;
}
 
<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> Main(<span class="reserved">string</span>[] args)
    {
        <span class="reserved">var</span> a1 = <span class="reserved">new</span> <span class="type">A</span>&lt;<span class="reserved">string</span>&gt; { Value = <span class="reserved"><span class="warning">null</span></span> }; <span class="comment">// null ダメ</span>
        <span class="reserved">var</span> a2 = <span class="reserved">new</span> <span class="type">A</span>&lt;<span class="warning"><span class="reserved">string</span>?</span>&gt; { Value = <span class="reserved">null</span> }; <span class="comment">// string? を渡しちゃダメ</span>
        <span class="reserved">var</span> b1 = <span class="reserved">new</span> <span class="type">B</span>&lt;<span class="reserved">string</span>&gt; { Value = <span class="reserved"><span class="warning">null</span></span> }; <span class="comment">// null ダメ</span>
        <span class="reserved">var</span> b2 = <span class="reserved">new</span> <span class="type">B</span>&lt;<span class="reserved">string</span>?&gt; { Value = <span class="reserved">null</span> }; <span class="comment">// これなら警告が出ない</span>
    }
}
</code></pre>
<p>しかし、「null許容参照型でもnull許容値型でもいいので、とにかくnull許容 or 非 null」みたいな指定ができません。</p>
<pre class="source" title="">
<code><span class="reserved">struct</span> <span class="type">A</span>&lt;<span class="type">T</span>&gt; <span class="reserved">where</span> <span class="type">T</span> : <span class="reserved">class</span> <span class="comment">// 非 null 参照型</span>
{
    <span class="reserved">public</span> <span class="type">T</span> NonNull;
    <span class="reserved">public</span> <span class="type">T</span>? Nullable; <span class="comment">// OK</span>
}
 
<span class="reserved">struct</span> <span class="type">B</span>&lt;<span class="type">T</span>&gt; <span class="reserved">where</span> <span class="type">T</span> : <span class="reserved">struct</span> <span class="comment">// 非 null 値型</span>
{
    <span class="reserved">public</span> <span class="type">T</span> NonNull;
    <span class="reserved">public</span> <span class="type">T</span>? Nullable; <span class="comment">// OK</span>
}
 
<span class="reserved">struct</span> <span class="type">C</span>&lt;<span class="type">T</span>&gt; <span class="comment">// 「非 null」だけを指定する手段はない</span>
{
    <span class="reserved">public</span> <span class="type">T</span> NonNull;
    <span class="reserved">public</span> <span class="error"><span class="type">T</span>?</span> Nullable; <span class="comment">// これが無理</span>
}
</code></pre>
<h3>漏れがあり得る</h3>
<p>フロー解析には漏れがあり得るそうです。
元々 null だらけな言語をいきなり完全に null のない言語に変えるのは無理でして。</p>
<p>例えば、現状だと以下のようなものすら漏れます。</p>
<pre class="source" title="">
<code><span class="reserved">using</span> System;
 
<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> Main()
    {
        <span class="comment">// new string[] { null } みたいなのはちゃんと警告になるものの、</span>
        <span class="comment">// new string[1] は通っちゃう。</span>
        <span class="comment">// 「既定値」が使われるので、null が入る。</span>
        M(<span class="reserved">new</span> <span class="reserved">string</span>[1]);
    }
 
    <span class="reserved">static</span> <span class="reserved">void</span> M(<span class="reserved">string</span>[] x)
    {
        <span class="reserved">foreach</span> (<span class="reserved">var</span> item <span class="reserved">in</span> x)
        {
            <span class="comment">// 本来は null は絶対来ないはずなものの…</span>
            <span class="type">Console</span>.WriteLine(item.Length); <span class="comment">// ぬるぽ</span>
        }
    }
}
</code></pre>
<p>この例は、将来的には「治る」可能性が高いです。
(徐々にフロー解析を賢くしたい意志はあるし、
この配列の既定値問題は既知の問題。
もしかしたら、リリース版までにはちゃんと警告が出るかもしれません。)</p>
<p>しかし、根本的に拾えないもの、
例えば unsafe コードや native 相互運用が絡むとどうしても解析しきれなくなります。</p>
<p>ということで、
<code>#nullable</code>を有効にしたうえで警告をすべて取り切っても、
<code>NullReferenceException</code>が出るときは出ます。</p>
<h2>試してみた感じ</h2>
<p>とまあ、完全ではない感じの C# 8.0 の null 解析ですが、
ここからは個人の感想。</p>
<p>実際、職場のコードも含めて、自分の持っているコードに対して <code>#nullable</code> を有効にして試してみました。</p>
<p>まあ、とりあえず感想としては、</p>
<ul>
<li>完全ではないとしても元よりは絶対マシ</li>
<li>
オン/オフ混在させてもそんなに違和感はなさそう
<ul>
<li>ちょっとずつ対応させていけばいい感じはちゃんとある</li>
</ul>
</li>
</ul>
<p>という感じ。</p>
<h3>警告が出た量</h3>
<p>ちなみに、いきなりプロジェクト全体に対して<code>NullableReferenceTypes</code>をtrueにしてやった場合どうなるかですが、
大体50～100行に1個くらい警告が出ます。
23万行ほどあるリポジトリに対してやってみたところ、
警告が3800個出ました。</p>
<p>ほとんどは、元々nullを意図していたコードに対してちまちまと<code>?</code>を付けて回る簡単なお仕事です。
今までさぼっていた人だと、<code>if (x != null)</code> や <code>?.</code> を付けて回るお仕事も待っていると思います。</p>
<h3>普通にやって取れなかった警告</h3>
<p>何十個に1個かくらい、真っ当な方法では警告が取れなくて、<code>!</code>演算子でご容赦を願ったところもあったりはします。
(いくつかはバグだと思うので、リリースまでには治ることを期待。)</p>
<p>前述のジェネリクスの問題は本当にどうしようもなかったです。
例えば以下のような感じのやつ。</p>
<pre class="source" title="">
<code><span class="reserved">class</span> <span class="type">MyDictionary</span>&lt;<span class="type">T</span>&gt;
{
    <span class="comment">// 制約なしの T は T? にできないので…</span>
    <span class="reserved">public</span> <span class="type">T</span> GetValueOrDefault(<span class="reserved">int</span> key)
    {
        <span class="comment">//if (keyで検索) return 見つかったら値を返す;</span>
        <span class="reserved">return</span> <span class="reserved">default</span>!; <span class="comment">// ! を付けないと警告</span>
    }
}
</code></pre>
<p>あとは、「null は素通し」形のメソッド。
以下のような感じのコードがあって、結局は <code>!</code> に頼りました。</p>
<pre class="source" title="">
<code><span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="comment">// 引数が null の場合に限り、戻り値も null</span>
    <span class="comment">// (例として素通ししているものの、実際のコードは多少の変換コードあり。</span>
    <span class="comment">//  ただし、メソッドの先頭で if (s == null) return null;)</span>
    <span class="reserved">static</span> <span class="reserved">string</span>? M(<span class="reserved">string</span>? s) =&gt; s;
 
    <span class="reserved">static</span> <span class="reserved">void</span> Main()
    {
        <span class="comment">// null を与えて null が返ってくるのは想定通り。</span>
        <span class="reserved">string</span>? s1 = M(<span class="reserved">null</span>);
 
        <span class="comment">// 自分は、この場合に M が null を返さないことを知っているものの…</span>
        <span class="comment">// コンパイラーにはわからないので警告が出る。</span>
        <span class="reserved">string</span> s2 = M(<span class="string">&quot;abc&quot;</span>);
    }
}
</code></pre> ]]></description>
				<pubDate>Sat, 08 Dec 2018 19:48:11 +0900</pubDate>
			</item>
			<item>
				<title>C# 8.0 Ranges</title>
				<link>http://ufcpp.net/blog/2018/12/cs8ranges/</link>
				<description><![CDATA[ <p>今日もC# 8.0の新機能の話で、今日のはすでに Visual Studio 2019 Preview 1に入っているやつです。</p>
<p>Ranges and Indicesと呼ばれていて、配列などに対して、
<code>a[^i]</code>で「後ろからi番目」とか、
<code>a[i..j]</code>で「i番目からj番目の範囲」とかを取り出せるようにする機能です。</p>
<p>正確にいうと、<code>^i</code>とか<code>i..j</code>とかの部分がC#の新機能で、
これらはそれぞれ<code>Index</code>型、<code>Range</code>型になります。
<code>Index</code>、<code>Range</code>を受け取るインデクサーやメソッドはライブラリ側の機能です。
(ただし、配列だけは言語レベルで処理している模様。)</p>
<h2>背景1: 統一ルールが欲しい</h2>
<p>一旦先ほどの説明は忘れてまっさらな状態で、
例えば「3..5」と言われると何を思い浮かべるでしょう。
文脈次第だとは思いますが、以下のようなものがあり得ます。</p>
<ul>
<li>3, 4, 5 (5も含む)</li>
<li>3, 4 (5は含まない)</li>
<li>3, 4, 5, 6, 7 (3から初めて5つ)</li>
</ul>
<p>どれがいいかは用途次第で、実際、どれもあり得ます。
例えば、.NET でも、以下のようなメソッドがあります。</p>
<pre class="source" title="">
<code><span class="reserved">var</span> r = <span class="reserved">new</span> <span class="type">Random</span>();
<span class="reserved">var</span> a = <span class="reserved">new</span>[] { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
 
<span class="reserved">var</span> x = r.Next(3, 5); <span class="comment">// 3, 4 (5を含まない)</span>
<span class="reserved">var</span> s = a.AsSpan(3, 5); <span class="comment">// 3, 4, 5, 6, 7 (3から始めて5つ)</span>
</code></pre>
<p>ちょっとでもわかりやすくしたければ、以下のように名前付き引数にすべきかもしれません。</p>
<pre class="source" title="">
<code><span class="reserved">var</span> x = r.Next(minValue: 3, maxValue: 5); <span class="comment">// 「5つ」でないことは明確なものの、5を含むかどうかわからず</span>
<span class="reserved">var</span> s = a.AsSpan(start: 3, length: 5); <span class="comment">// これなら割とわかりやすく「3から始めて5つ」</span>
</code></pre>
<p><code>Random.Next</code>の例のように、名前が「max」だけで、「含むかどうか」がわからないAPIも多いです。
この区別のために、<code>Parallel.For</code>なんかは引数名が<code>fromInclusive</code>、<code>toExclusive</code>とかになっていたりします。
しかし、どんどん名前が長くなって書きづらい上に、
所詮は命名規約なので規約が守られない場合だってあり得ます。</p>
<p>さらにいうと、多次元データになるともっとしんどくなります。</p>
<pre class="source" title="">
<code><span class="reserved">var</span> m = <span class="reserved">new</span>[,]
{
    { 1, 2, 3, 4 },
    { 5, 6, 7, 8 },
    { 9, 10, 11, 12 },
};
 
<span class="comment">// (x, y) が (1, 2) ～ (3, 4) の範囲？</span>
<span class="comment">// x が 1～2、y が 3～4 の範囲？</span>
<span class="comment">// 2, 4 は含む？含まない？</span>
<span class="reserved">var</span> n = m.Slice(1, 2, 3, 4);

</code></pre>
<p>ということで、範囲を表す専用の文法が欲しいという話になります。</p>
<h2>背景2: インデックス用途</h2>
<p>その両端を含むか含まないか問題ですが、どちらがいいかは正直用途によります。</p>
<p>例えば、<code>x in 1..3</code> みたいに「<code>x</code> がその範囲に入るかどうか」(マッチング用途)の場合、
大体は「3も含む」の方にしたいという要望が多いです。
一方で、<code>x[1..3]</code>みたいに「<code>x</code>の1番から3番の要素」(インデックス用途)の場合、
「3を含まない」にした方が都合がよかったりします。
インデックス用途における「含まない」の利点は以下のようなもの。</p>
<ul>
<li>
実装上、パフォーマンス的に有利
<ul>
<li>長さを <code>length = maxExclusive - minInclusive</code> で計算できる(<code>+1</code>が要らない)</li>
<li>ループが <code>for (var i = minInclusive; i &lt; maxExclusive; i++)</code> になる(<code>&lt;=</code> だと <code>int.MaxValue</code>に対する特別扱いが必要)</li>
</ul>
</li>
<li><code>i..i</code>が空(0要素)範囲になる。「含む」の方だと空範囲が<code>i..i-1</code>になってちょっとキモい</li>
</ul>
<p>C# 8.0で導入される範囲構文は、後者のインデックス用途を狙ったもので、「末尾は含まない」の方になります。</p>
<p>ちなみに、「範囲に入るかどうか」の方は別途<a href="/study/csharp/datatype/patterns/">パターン マッチング</a>の一種(range pattern)として提供される可能性はあるんですが、
おそらく別の文法(<code>x in 1 to 3</code>みたいな)になりそうです。</p>
<p>一方、インデックス用途に絞ったことで、
「配列の末尾からi番目」を表したいという別の要望も出てきます。
そこで、<code>^</code>演算子を導入して、<code>^i</code>で「末尾からi番目」を表すことになりました。</p>
<h2>文法</h2>
<p>ということで、C# 8.0で導入されるのは以下のような文法です。</p>
<ul>
<li>
<code>^i</code> 演算子で「末尾からi番目」を表す <code>Index</code>型を作る
<ul>
<li>正確には「<code>Length - i</code>」を表す。<code>^0</code>は<code>Length</code>番目なので、<code>array[^0]</code>は OutOfRange。</li>
</ul>
</li>
<li>
<code>i..j</code> 演算子で、「i番目からj番目」を表す<code>Range</code>型を作る
<ul>
<li>開始の方(<code>i</code>)は含む、末尾の方(<code>j</code>)は含まない</li>
<li>両端は省略可能。<code>i..</code>なら「iから末尾」、<code>..j</code>なら「先頭からj」、<code>..</code>なら「配列全体」</li>
<li><code>Index</code>を受け付ける。<code>^3..</code>なら「末尾から3要素」</li>
</ul>
</li>
</ul>
<p>ちなみに、<code>Range</code>、<code>Index</code>はいずれも<code>System</code>名前空間の構造体です。</p>
<p>例えば以下のように書けます。</p>
<pre class="source" title="">
<code><span class="reserved">var</span> data = <span class="reserved">new</span>[] { 0, 1, 2, 3, 4, 5 };
 
<span class="comment">// 1～2要素目。2 は exclusive。なので、表示されるのは 1 だけ。</span>
Write(data[1..2]);
 
<span class="comment">// 先頭から1～末尾から1。 1, 2, 3, 4</span>
Write(data[1..^1]);
 
<span class="comment">// 先頭～末尾から1。 0, 1, 2, 3, 4</span>
Write(data[..^1]);
 
<span class="comment">// 先頭から1～末尾。 1, 2, 3, 4, 5</span>
Write(data[1..]);
 
<span class="comment">// 全体。0, 1, 2, 3, 4, 5</span>
Write(data[..]);
</code></pre>
<p><img src="/media/1167/ranges.png" alt="範囲構文" /></p>
<h2>内部実装</h2>
<p>実装としては以下のようになります。</p>
<ul>
<li><code>^i</code> は<code>new Index(i, true)</code>になる(第2引数の<code>true</code>が「末尾から」の意味)</li>
<li>整数から <code>Index</code> へは暗黙の型変換がある</li>
<li><code>i..j</code>は<code>Range.Create(i, j)</code>になる</li>
<li><code>i..</code>は<code>Range.FromStart(i)</code>になる</li>
<li><code>..j</code>は<code>Range.ToEnd(j)</code>になる</li>
<li><code>..</code>は<code>Range.All()</code>になる</li>
</ul>
<pre class="source" title="">
<code><span class="reserved">var</span> r1 = <span class="type">Range</span>.Create(1, 2);                  <span class="comment">// 1..2</span>
<span class="reserved">var</span> r2 = <span class="type">Range</span>.Create(1, <span class="reserved">new</span> <span class="type">Index</span>(1, <span class="reserved">true</span>)); <span class="comment">// 1..^1</span>
<span class="reserved">var</span> r3 = <span class="type">Range</span>.ToEnd(<span class="reserved">new</span> <span class="type">Index</span>(1, <span class="reserved">true</span>));     <span class="comment">// ..^1</span>
<span class="reserved">var</span> r4 = <span class="type">Range</span>.FromStart(1);                  <span class="comment">// 1..</span>
<span class="reserved">var</span> r5 = <span class="type">Range</span>.All();                         <span class="comment">// ..</span>
</code></pre>
<p>ちなみに、<code>Range</code>、<code>Index</code>はそれぞれ、</p>
<ul>
<li>
<code>Index</code> … <code>int</code>を1つだけ持つ構造体
<ul>
<li>.NET の配列は負のインデックスを想定していないので、負の数を使って「末尾から」を表現</li>
</ul>
</li>
<li><code>Range</code> … <code>Index</code>を2つ持つ構造体</li>
</ul>
<p>になっています。</p>
<p>また、構文上は、<code>^</code>の方は単なる単項演算子、
<code>..</code>の方は専用の構文(オペランドを省略可能というのが特殊なので、単なる2項演算子扱いにはできない)だそうです。</p>
<h2>Rangeを受け付けるインデクサー</h2>
<p>配列に対して <code>a[i..j]</code> と書いた時の挙動はちょっとまだもめているみたいです。
要は以下のどちらにすべきか。</p>
<ul>
<li>
配列からは配列で「subarray」を返すべきではないか
<ul>
<li>新しい配列のアロケーションとコピーが発生</li>
</ul>
</li>
<li>アロケーションを避けるために <code>Span&lt;T&gt;</code> で返すべきではないか</li>
</ul>
<p>Visual Studio 2019 Preview 1 での実装は前者になっていて、
<code>new T[]</code>と<code>Array.Copy</code>が生成されます。
パフォーマンスを気にするなら<code>a.AsSpan()[i..j]</code>と書く必要があります。</p>
 ]]></description>
				<pubDate>Fri, 07 Dec 2018 11:44:46 +0900</pubDate>
			</item>
			<item>
				<title>C# 8.0 小さな修正</title>
				<link>http://ufcpp.net/blog/2018/12/cs8misc/</link>
				<description><![CDATA[ <p>Visual Studio 2019 Preview 1 が出て、
さすがに C# 8.0 に入る機能・入らない機能がある程度見えてきたので、
今日からしばらくその辺りの紹介をしていこうかと。</p>
<p>とりあえず今日は、「1記事使うほどでもないような小さい奴」をまとめて紹介。</p>
<ol>
<li>文字列補完、<code>$</code> と <code>@</code> の順序緩和</li>
<li><code>??=</code> (null 合体代入)演算子</li>
<li>構造体の宣言時、<code>ref</code>と<code>partial</code>の順序緩和</li>
<li>分解の右辺に <code>default</code> 式</li>
<li>入れ子の<code>{}</code>内での <code>stackalloc</code></li>
<li><code>unmanaged</code> 制約付きの型引数に、ジェネリックな型を渡す</li>
</ol>
<p>ちなみに、VS 2019 Preview 1 で実装されているのは上の2つだけです。</p>
<h2>順序緩和</h2>
<p>C# のキーワードには、並び順を自由に変えられるものがいくつかあります。
代表的なのはクラスやメソッドに対する修飾子ですが、例えば以下の3行は全く同じ意味になります。</p>
<pre class="source" title="キーワードの並び順">
<code><span class="reserved">static</span> <span class="reserved">public</span> <span class="reserved">readonly</span> <span class="reserved">int</span> x;
<span class="reserved">public</span> <span class="reserved">readonly</span> <span class="reserved">static</span> <span class="reserved">int</span> x;
<span class="reserved">readonly</span> <span class="reserved">static</span> <span class="reserved">public</span> <span class="reserved">int</span> x;
</code></pre>
<p>一見するとこれらと同じように順序不問そうに見えるのに、なぜか順序に厳しいものもあります。
やむを得ない理由があってそうなっているものもあるんですが、
例えば、<a href="/study/csharp/oo_class.html#partial_class">部分クラス</a>の<code>partial</code>は、
「C# 2.0 から追加したキーワードなので、1.0 時代のコードを壊さないように、順序を厳しくした」という理由で「<code>class</code>または<code>struct</code>の直前でないといけない」という制限が付いています。C# 7.2 で入った<a href="/study/csharp/resource/refstruct/">ref構造体</a>も同様に、<code>ref</code>キーワードは<code>struct</code>の直前にないといけません。</p>
<p>しかし、いくつかは理不尽、あるいは、過剰で、</p>
<ul>
<li><a href="/study/csharp/sp3_extension.html#ref-extensions">参照引数な拡張メソッド</a>は<code>ref this T</code>でないとダメだった</li>
<li>
構造体に対する <code>ref</code> と <code>partial</code> の両方付けたければ<code>ref partial struct</code>の順でないとダメ
<ul>
<li><code>partial ref struct</code> でもいいはず</li>
</ul>
</li>
<li>
<a href="/study/csharp/st_string.html#string-interpolation">文字列補間</a> の(<code>$</code>)と<a href="/study/csharp/st_embeddedtype.html#verbatim-string">逐語的リテラル</a>の(<code>@</code>)を同時に指定したければ<code>$@</code>の順でないとダメ
<ul>
<li><code>@$</code> でもいいはず</li>
</ul>
</li>
</ul>
<p>とかいうものもあったりします。
こいつらはほんとにどっちが正しいのかわからず、よく間違います。</p>
<p>拡張メソッドの <code>ref this</code>と<code>this ref</code>は、
今は順序緩和されていてどちらでも使えます。
しかもこの修正、パッチ リリースでこっそりと入っていたり。</p>
<p>ということで、この度、C# 8.0 では後者2つも順序緩和されるみたいです。
どちらも最初から認めてくれててもいいレベルなんですけどね…</p>
<h2>null 合体代入</h2>
<p>「null だったら何か適当な既定値で上書き」みたいな処理は結構頻出かと思います。</p>
<pre class="source" title="">
<code><span class="reserved">static</span> <span class="reserved">void</span> M(<span class="reserved">string</span> x = <span class="reserved">null</span>)
{
    <span class="reserved">if</span> (x == <span class="reserved">null</span>) x = <span class="string">&quot;default string&quot;</span>;
    <span class="comment">// x に対して何か処理</span>
}
</code></pre>
<p>あるいは、遅延初期化のために、「初期値にnullを入れておいて、初回アクセス時に有効な値で上書き」みたいなことも結構書きます。</p>
<pre class="source" title="">
<code><span class="reserved">public</span> <span class="reserved">string</span> Name =&gt; _name ?? (_name = GetName());
<span class="reserved">private</span> <span class="reserved">string</span> _name = <span class="reserved">null</span>;
</code></pre>
<p>後者の例では
<a href="/study/csharp/rm_nullusage.html#key-null-coalesce">null 合体演算子</a> <code>??</code> と代入 <code>=</code> を組み合わせていますが、まあ、まさにやりたいことはこれ。
<code>+</code> に対する <code>+=</code> のように、<code>??</code> に対する <code>??=</code> が欲しいという要望は結構あります。</p>
<p>ということで、その<code>??=</code>演算子が C# 8.0で入ります。</p>
<pre class="source" title="">
<code><span class="reserved">static</span> <span class="reserved">void</span> M(<span class="reserved">string</span> x = <span class="reserved">null</span>)
{
    x ??= <span class="string">&quot;default string&quot;</span>;
    <span class="comment">// x に対して何か処理</span>
}
 
<span class="reserved">public</span> <span class="reserved">string</span> Name =&gt; _name ??= GetName();
<span class="reserved">private</span> <span class="reserved">string</span> _name = <span class="reserved">null</span>;

</code></pre>
<p>これ、VS 2019 Preview 1ですでに実装されていますけども、
取り組むことになったの、そこそこ最近なんですよね。
あと、地味な機能なのでそんなに話題にも登らず、アピールもされず。
なんか気が付いたら決まっていて、
気が付いたら実装されてて、
気が付いたらマージされた印象。</p>
<p>大した機能じゃなくて実装が簡単とは言え、ちょっとびっくり…</p>
<h2>分解の右辺に <code>default</code> 式</h2>
<p>C# 7.1 で <a href="/study/csharp/cheatsheet/ap_ver7_1/#default-expr"><code>default</code>式</a>ってのが入ったわけですが。
要は、左辺から推論が効く限りには、<code>default(T)</code>の<code>(T)</code>を省略して<code>default</code>だけで掛けるようになるというやつ。</p>
<p>この<code>default</code>の型推論、C# 7.x までは、以下のような状況では利きませんでした。</p>
<pre class="source" title="">
<code>(<span class="reserved">int</span> x1, <span class="reserved">int</span> y1) = <span class="reserved">default</span>; <span class="comment">// ダメ</span>
(<span class="reserved">int</span> x2, <span class="reserved">int</span> y2) = <span class="reserved">default</span>((<span class="reserved">int</span>, <span class="reserved">int</span>)); <span class="comment">// これならOK</span>
(<span class="reserved">int</span> x3, <span class="reserved">int</span> y3) = (<span class="reserved">default</span>, <span class="reserved">default</span>); <span class="comment">// これでもOK</span>
</code></pre>
<p>この、1行目の「ダメ」ってなっている方を、C# 8.0からはOKにするみたいです。</p>
<p>確かに、なんかきわどい…
<code>(int x, int y)</code> に対して分解代入できる型は別にタプルに限らないわけで、
じゃあ、この<code>default</code>は何に推論されたのか…的な不思議さは一瞬ちょっと感じます。
(まあ、でも、便利さ優先でほしい機能。)</p>
<h2>入れ子の<code>{}</code>内での <code>stackalloc</code></h2>
<p>C# 7.2 で<a href="/study/csharp/resource/span/#safe-stackalloc">安全に使える <code>stackalloc</code></a>が入りました。
ですが、<a href="/study/csharp/resource/refstruct/">ref構造体</a>の制限から、非同期メソッド内ではこの機能が使えませんでした。</p>
<pre class="source" title="">
<code><span class="type">Span</span>&lt;<span class="reserved">int</span>&gt; x = <span class="reserved">stackalloc</span> <span class="reserved">int</span>[32];
 
<span class="comment">// ここで x を使うのは安全なはずだけど、今は問答無用でエラー。</span>
 
<span class="reserved">await</span> <span class="type">Task</span>.Delay(1);
 
<span class="comment">// await をまたいで stackalloc を使おうとするのは明確にまずい。</span>
<span class="comment">// これは制限されていてもしょうがない。</span>
</code></pre>
<p>これに対して、C# 8.0では、以下のように一段<code>{}</code>でくくればOKになります。
要するに、<code>{}</code>でくくることによって、絶対に<code>await</code>をまたがないことが保証されれば(<code>{}</code>内に<code>await</code>がなければ)認めても安全ということです。</p>
<pre class="source" title="">
<code>{
    <span class="comment">// {} でくくったのでこれが書けるようになる。</span>
    <span class="type">Span</span>&lt;<span class="reserved">int</span>&gt; x = <span class="reserved">stackalloc</span> <span class="reserved">int</span>[32];
}
<span class="reserved">await</span> <span class="type">Task</span>.Delay(1);
</code></pre>
<h2><code>unmanaged</code> 制約付きの型引数に、ジェネリックな型を渡す</h2>
<p>C# 7.3 で<a href="/study/csharp/sp_unsafe.html#unmanaged-constraints"><code>unmanaged</code>制約</a>が入りましたが、微妙に使いにくい点がありました。</p>
<pre class="source" title="">
<code><span class="type">Unmanaged</span>&lt;<span class="reserved">int</span>&gt; x; <span class="comment">// int は unmanaged なので OK</span>
 
<span class="comment">// 以下のものは C# 7.3 ではダメ</span>
<span class="type">Unmanaged</span>&lt;(<span class="reserved">int</span>, <span class="reserved">int</span>)&gt; y; <span class="comment">// int しか含まないはずなのに…</span>
<span class="type">Unmanaged</span>&lt;<span class="type">Unmanaged</span>&lt;<span class="reserved">int</span>&gt;&gt; z; <span class="comment">// 再帰的に unmanaged 制約を満たしてそうなのに…</span>
</code></pre>
<p>要は、「ジェネリック型は問答無用ではじく」という状態です。</p>
<p>ちなみに、同様の事情は<a href="/study/csharp/resource/refstruct/">ref構造体</a>にもありまして。
ただ、ref構造体の方は、かなり厳密にチェックしてはじかないとまずい(セキュリティ ホールの原因になりかねない危険性あり)ので、
こちらは絶対にジェネリック型を使えないそうです。</p>
<p>そして、C# の仕様書上、<a href="/study/csharp/sp_unsafe.html#unmanaged-types">ポインターにも同様の制限</a>があります。
C# 2.0の頃からずっと、ジェネリックな型に対してポインターを使えませんでした。</p>
<p>しかしどうも、ポインターに関しては別にこの制限は要らなかったらしいです。
あくまで、「1つでも参照型を含んでいたらダメ」にすべきで、
再帰的に<code>unmanaged</code>制約を満たしているのならジェネリックかどうかは関係ないはずです。</p>
<p>なので、C# 8.0で、<code>unmanaged</code>制約でのジェネリック型の利用制限は撤廃するし、
<a href="https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/unsafe-code">仕様書</a>のアンマネージ型に関する記述も修正すべきという話になっています。</p>
 ]]></description>
				<pubDate>Thu, 06 Dec 2018 21:09:56 +0900</pubDate>
			</item>
			<item>
				<title>Visual Studio 2019 Preview 1</title>
				<link>http://ufcpp.net/blog/2018/12/vs2019p1/</link>
				<description><![CDATA[ <p><a href="https://channel9.msdn.com/Events/Connect/Microsoft-Connect--2018">Connect</a> やってましたね。</p>
<p>とりあえず、関連ブログ:</p>
<ul>
<li>
<a href="https://blogs.msdn.microsoft.com/visualstudio/2018/12/04/making-every-developer-more-productive-with-visual-studio-2019/">Making every developer more productive with Visual Studio 2019</a>
<ul>
<li><a href="https://visualstudio.microsoft.com/ja/vs/preview/">Visual Studio 2019 Preview</a></li>
</ul>
</li>
<li>
<a href="https://blogs.msdn.microsoft.com/dotnet/2018/12/04/announcing-net-core-2-2/">Announcing .NET Core 2.2</a>
<ul>
<li><a href="https://dotnet.microsoft.com/download/dotnet-core/2.2">.NET Core 2.2 downloads</a></li>
</ul>
</li>
<li><a href="https://blogs.msdn.microsoft.com/dotnet/2018/12/04/announcing-net-core-3-preview-1-and-open-sourcing-windows-desktop-frameworks/">Announcing .NET Core 3 Preview 1 and Open Sourcing Windows Desktop Frameworks</a></li>
<li><a href="https://blogs.windows.com/buildingapps/2018/12/04/announcing-open-source-of-wpf-windows-forms-and-winui-at-microsoft-connect-2018/">Announcing Open Source of WPF, Windows Forms, and WinUI at Microsoft Connect(); 2018</a></li>
<li>
<a href="https://www.hanselman.com/blog/AnnouncingWPFWinFormsAndWinUIAreGoingOpenSource.aspx">Announcing WPF, WinForms, and WinUI are going Open Source</a>
<ul>
<li><a href="https://dotnet.microsoft.com/download/dotnet-core/3.0">.NET Core 3.0 Preview</a></li>
<li><a href="https://github.com/dotnet/wpf">github WPF</a></li>
<li><a href="https://github.com/dotnet/winforms">github WinForms</a></li>
<li><a href="https://github.com/Microsoft/microsoft-ui-xaml">github Windows UI Library</a></li>
</ul>
</li>
<li><a href="https://blogs.msdn.microsoft.com/webdev/2018/12/04/asp-net-core-2-2-available-today/">Announcing ASP.NET Core 2.2, available today!</a></li>
<li><a href="https://blogs.msdn.microsoft.com/dotnet/2018/12/04/announcing-entity-framework-core-2-2/">Announcing Entity Framework Core 2.2</a></li>
</ul>
<p>とりあえず、.NET Core 2.2 正式リリース ＆ .NET Core 3.0 プレビュー提供開始。
Visual Studio 2019も preview 1 がダウンロードできるようになりました。</p>
<p>あと、WPF、WinForms 等がオープンソースになったみたいです。
(重ね重ねの注意になりますが、.NET Core 3.0 で動く/オープンソースになったといっても、Windows 限定です。)</p>
<h2>C# 8.0</h2>
<p>大してアナウンスされていませんが、Visual Studio 2019 Preview 1 でひそかにちょこっとだけ C# 8.0 を試せるようになっていたり。</p>
<p>ただ、</p>
<ul>
<li>
LangVersion default は C# 7.0 だし、latest は 7.3 のまま
<ul>
<li>C# 8.0 を試してみたければ LangVersion 8.0 を明示的に指定</li>
<li>LangVersion beta とか experimental みたいなモニカーもなさそう</li>
</ul>
</li>
<li>
実装されている機能は 「<a href="https://github.com/dotnet/roslyn/blob/master/docs/Language%20Feature%20Status.md">Language Feature Status</a>」参照。現時点では以下のものだけっぽい
<ul>
<li>Nullable reference type</li>
<li>Ranges</li>
<li>Null-coalescing Assignment</li>
<li>Alternative interpolated verbatim strings</li>
<li>(※追記) Async streams</li>
</ul>
</li>
<li>どうも、C# 8.0 の正式サポート開始は Visual Studio 2019 の最初のリリースではやらず、その後、 .NET Core 3.0 が出るタイミングからにしたいらしい</li>
</ul>
<h3>今使える機能</h3>
<p><a href="https://github.com/dotnet/roslyn/blob/master/docs/Language%20Feature%20Status.md">Language Feature Status</a> の C# 8.0 のところに並んでいる15個のうち、「Merged to dev16 preview1」になっている4個だけが今試せるっぽいです。</p>
<p>(※追記: もう1個、Async streams も実装されてるっぽい。
ただ、バグっててちゃんとコンパイルできず。)</p>
<p>ちなみに、ちゃんと、C# 8.0 の機能を使おうとすると、「プロジェクトを C# 8.0 にアップグレードしますか？」と聞かれます。</p>
<p><img src="/media/1165/upgradetocs8.png" alt="Upgrade this project to C# language version 8.0 *beta*" /></p>
<p>むっちゃ beta を強調されてますが。</p>
<p>以下、軽くサンプルを。(<a href="https://github.com/ufcpp/UfcppSample/tree/master/Demo/2018/Cs8InVs2019P1">github にも上げてあります</a>)</p>
<h4>Nullable reference type</h4>
<pre class="source" title="">
<code><span class="comment">// 有効にするには #nullable ディレクティブが必要。</span>
#nullable enable

<span class="reserved">using</span> System;

<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> Main()
    {
        Console.WriteLine(LengthSum(<span class="string">"abc"</span>, <span class="string">"xyz"</span>));
        Console.WriteLine(LengthSum(<span class="string">"abc"</span>, <span class="reserved">null</span>));
    }

    <span class="reserved">static</span> <span class="reserved">int</span> LengthSum(<span class="reserved">string</span> a, <span class="reserved">string</span>? b)
    {
        <span class="comment">// こう書いてしまうと b のところで警告。</span>
        <span class="reserved">var</span> len0 = a.Length + <span class="warning">b</span>.Length;

        <span class="comment">// これなら OK。b?. なので、b の null チェック済み。</span>
        <span class="reserved">var</span> len1 = a.Length + b?.Length ?? 0;

        <span class="comment">// こんな感じで if で null チェックしても OK。</span>
        <span class="comment">// チェック済みな個所では b. で大丈夫。</span>
        <span class="reserved">var</span> len = a.Length;
        <span class="reserved">if</span>(b != <span class="reserved">null</span>) len += b.Length;

        <span class="reserved">return</span> len;
    }
}
</code></pre>
<h4>Ranges</h4>
<pre class="source" title="">
<code><span class="reserved">using</span> System;

<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> Main()
    {
        <span class="reserved">var</span> data = <span class="reserved">new</span>[] { 0, 1, 2, 3, 4, 5 };

        <span class="comment">// 1～2要素目。2 は exclusive。なので、表示されるのは 1 だけ。</span>
        Write(Slice(data, 1..2));

        <span class="comment">// 先頭から1～末尾から1。表示されるのは 1, 2, 3, 4</span>
        Write(Slice(data, 1..^1));

        <span class="comment">// 先頭～末尾から1。表示されるのは 0, 1, 2, 3, 4</span>
        Write(Slice(data, ..^1));

        <span class="comment">// 先頭から1～末尾。表示されるのは 1, 2, 3, 4, 5</span>
        Write(Slice(data, 1..));
    }

    <span class="comment">// 最終的に、.NET Core 3.0 には Span&lt;int&gt; に Range 型を受け取るインデクサーが入るはず。</span>
    <span class="comment">// 今はその実装がないので自前で同じ機能を作る。</span>
    <span class="reserved">static</span> Span&lt;<span class="reserved">int</span>&gt; Slice(Span&lt;<span class="reserved">int</span>&gt; data, Range range)
    {
        <span class="reserved">int</span> getIndex(<span class="reserved">int</span> length, Index i) =&gt; i.FromEnd ? length - i.Value : i.Value;
        <span class="reserved">var</span> s = getIndex(data.Length, range.Start);
        <span class="reserved">var</span> e = getIndex(data.Length, range.End);
        <span class="reserved">return</span> data.Slice(s, e - s);
    }

    <span class="comment">// 表示確認用。Span の中身を , 区切り表示。</span>
    <span class="reserved">static</span> <span class="reserved">void</span> Write&lt;<span class="type">T</span>&gt;(Span&lt;T&gt; items)
    {
        <span class="reserved">var</span> first = <span class="reserved">true</span>;
        <span class="reserved">foreach</span> (var x <span class="reserved">in</span> items)
        {
            <span class="reserved">if</span> (first) first = <span class="reserved">false</span>;
            <span class="reserved">else</span> Console.Write(<span class="string">", "</span>);
            Console.Write(x);
        }
        Console.WriteLine();
    }
}
</code></pre>
<h4>Null-coalescing Assignment</h4>
<p><code>x ??= y</code> で、<code>if (x == null) x = y;</code> の意味に。</p>
<pre class="source" title="">
<code><span class="reserved">using</span> System;

<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> Main()
    {
        NullCoalescingAssignment(<span class="string">"abc"</span>); <span class="comment">// "abc" が表示される</span>
        NullCoalescingAssignment(<span class="reserved">null</span>);  <span class="comment">// "default string" が表示される</span>
    }

    <span class="reserved">static</span> <span class="reserved">void</span> NullCoalescingAssignment(<span class="reserved">string</span> s)
    {
        s ??= <span class="string">"default string"</span>;
        Console.WriteLine(s);
    }
}
</code></pre>
<h4>Alternative interpolated verbatim strings</h4>
<p><code>$@</code> の順序しか受け付けなかったやつが、<code>@$</code> も認めるという話。</p>
<pre class="source" title="">
<code><span class="comment">// こっちは C# 6.0 からあるやつ。</span>
<span class="reserved">var</span> s1 = $@"\\\ {x}";

<span class="comment">// これまでは $ と @ の順番逆にできなかった。</span>
<span class="comment">// C# 8.0 から @$ でも OK。</span>
<span class="reserved">var</span> s2 = @$"\\\ {x}";
</code></pre>
<h3>サポートに関して</h3>
<p><a href="https://channel9.msdn.com/Events/Connect/Microsoft-Connect--2018/D140">Mads (C# チームの PM)の動画</a>の説明欄には「included in Visual Studio 2019」とか書いてあるんですが…</p>
<p>C# チームの中の人が gitter で<a href="https://gitter.im/dotnet/csharplang?at=5c0599bd1c439034af12ba30">以下のようなことを言っており</a>:</p>
<blockquote>
<p>The C# 8 language support will not RTM with initial VS2019 release. The features and the language version will be there but as &quot;beta&quot;, meaning some breaking language changes may still occur.
C# 8 will RTM in an update of VS2019, aligned with .NET Core 3.</p>
</blockquote>
<p>VS2019 リリースの時点ではRTMにはならない。ベータ扱いで、まだ破壊的変更の可能性残る。
C# 8のRTMはVS2019のアップデートで、.NET Core 3.0とそろえてやる。</p>
<p>とのこと。</p>
<p>「機能としては乗ってるけどまだベータ」とか、混乱されそうでちょっと怖いですが。
「default」が 8.0 に切り替わらない限りには大丈夫なのかな…</p>
<h2>おまけ: Regexパーサー</h2>
<p><a href="https://ufcpp.net/blog/2018/1/pickuproslyn0103/">今年の初めに紹介した Regex パーサー</a>が Visual Studio 2019 に組み込まれたみたいです。</p>
<p><img src="/media/1166/regexparser.png" alt="Regex パーサー" /></p>
<p>構文ハイライトが付くのと、不正な正規表現の検出、訂正をある程度やってくれるます。</p>
 ]]></description>
				<pubDate>Wed, 05 Dec 2018 09:22:13 +0900</pubDate>
			</item>
			<item>
				<title>RuntimeFeature クラス</title>
				<link>http://ufcpp.net/blog/2018/12/runtimefeature/</link>
				<description><![CDATA[ <p>先日 <a href="/blog/2018/11/cs80_net48/">C# 8.0 予告なブログ</a>で書いた通り、
C# 8.0 で入る<a href="https://github.com/dotnet/csharplang/issues/52">インターフェイスのデフォルト実装</a>は .NET ランタイム側の修正が必要な機能です。</p>
<p>今日は、そういう「ランタイム側機能」についての話を少し。</p>
<h2>ランタイム側機能</h2>
<p>C# の言語機能は、C# コンパイラーがちょこっと頑張ってよい具合にコード生成して、
古い .NET Framework ランタイム上でも動くものが多いです。
「古いランタイム上では動かない新機能」というと、実は .NET Framework 2.0 での<a href="/study/csharp/sp2_generics.html">ジェネリクス</a>の導入まで遡ります。
.NET Framework 2.0 は2005年リリースですし、
C# 8.0 には実に13年ぶりにランタイムの方に修正を求める機能が入ったことになります。</p>
<p>契機となったのはやっぱり .NET Core の存在です。
.NET Core は、オープンソースで開発ペースも速く、
side by side (1台のPCに複数バージョンを同時にインストール可能)なのでランタイムの更新がしやすいという利点があります。
ランタイム更新しやすいからこその、13年ぶりの新機能を追加です。</p>
<p>登場直後の .NET Core は .NET Framework の下位互換のような存在でしたが、
.NET Core 2.0 くらいから互換性が増してきて、
.NET Core 3.0 ではついに Windows 限定な WPF や UWP などの GUI フレームワークも .NET Core 上で動くようになりました。
一応、完全新規の案件であれば .NET Framework の方をわざわざ使う理由がないくらいにはなっています。
ようやく、次のステップに進む段階に入ったといえます。
これも、このタイミングで13年ぶりの新機能追加に至った要因でしょう。</p>
<h2>RuntimeFeature クラス</h2>
<p>しかし、ランタイムの新旧によって使えない機能があるとなると、
それを検知・コンパイル時にエラーにする仕組みが必要になります。
コンパイルできたはいいけど、実際に動かそうとした段階で無理だったというのでは困ります。</p>
<p>その検知機構として用意されたのが、<code>RuntimeFeature</code>クラス(<code>System.Runtime.CompilerServices</code>名前空間)です。
以下のようなクラスになっていて、<code>const string</code>なメンバーが存在するかどうかで、その機能を使えるかどうかを判定します。</p>
<pre class="source" title="RuntimeFeature クラス">
<code><span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">partial</span> <span class="reserved">class</span> <span class="type">RuntimeFeature</span>
{
<span class="inactive">#if</span> FEATURE_DEFAULT_INTERFACES
    <span class="reserved">public</span> <span class="reserved">const</span> <span class="reserved">string</span> DefaultImplementationsOfInterfaces = <span class="string">"DefaultImplementationsOfInterfaces"</span>;
<span class="inactive">#endif</span>
    <span class="reserved">public</span> <span class="reserved">const</span> <span class="reserved">string</span> PortablePdb = <span class="string">"PortablePdb"</span>;
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">bool</span> IsSupported(<span class="reserved">string</span> feature);
}
</code></pre>
<p>今のところ生えているメンバーは、</p>
<ul>
<li><code>DefaultImplementationsOfInterfaces</code> … 今回追加されたインターフェイスのデフォルト実装の可否</li>
<li><code>PortablePdb</code> … 動的コード生成で Portable PDB を解釈できるかどうか</li>
</ul>
<p>の2つです。</p>
<h3>PortablePdb</h3>
<p>ちなみに、<code>PortablePdb</code>の方について補足。
まず、PDB はデバッグ情報が掛かれたファイルで、
Visual C++ の頃から同名の拡張子のファイルは作られていました。
C# でも、ビルド時に dll や exe と一緒に拡張子が pdb のファイルが作られていると思います。</p>
<p>拡張子自体はずっと同じ pdb ですが、内部の形式については最近ガラッと変わりました。
以前の pdb は、仕様がオープンになっておらず、
pdb を読み込めるデバッガーが Windows 依存でした(なので、通称 &quot;Windows PDB&quot;)。
そこで、.NET Core では、せっかくなので仕様自体をオープンにした Portable な pdb 形式を作ることにしたそうです。
それが「Portable PDB」。</p>
<p>PDB は基本的に C# コンパイラーが生成するものなので、<code>RuntimeFeature</code> (ランタイム側)とは無関係そうに見えます。
では <code>PortablePdb</code> は何のためにあるかと言うと、動的コード生成です。
例えば C# スクリプト実行であっても、内部的にはちゃんと PDB を生成して、
デバッグ情報が取れるようにしてあります。
このとき、生成する PDB を Portable PDB にしていいか、クラシックな Windows PDB でないとダメかを判別するための機構がないと困るので、<code>RuntimeFeature.PortablePdb</code>があります。</p>
<h2>その他の RuntimeFeature 機能</h2>
<p>その他に、<code>RuntimeFeature</code>クラスには
(.NET Standard 2.1 から)以下のような bool 型の静的プロパティもあります。</p>
<pre class="source" title="DynamicCode">
<code><span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">partial</span> <span class="reserved">class</span> <span class="type">RuntimeFeature</span>
{
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">bool</span> IsDynamicCodeSupported { <span class="reserved">get</span>; }
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">bool</span> IsDynamicCodeCompiled { <span class="reserved">get</span>; }
}
</code></pre>
<p>先ほどの2つとは違って、こちらは実行時に値を確認して使う用みたいです。
そのランタイムで、</p>
<ul>
<li><code>IsDynamicCodeSupported</code> … そもそも動的コード実行は可能か</li>
<li><code>IsDynamicCodeCompiled</code> … 動的コード実行はコンパイルされているか(= インタープリター実行ではないか = パフォーマンスよく実行できるか)</li>
</ul>
<p>の判別に使います。
例えば、動的コンパイルができない環境で<a href="/study/csharp/sp3_expression.html">式ツリー</a>の <code>Compile</code> メソッドを使ったりすると、
高速化のためにやってることなのにかえって破滅的に遅いコードになってしまいます。
それを避けるために分岐に使うのがこれらのプロパティ。</p>
<h2>今後入るかもしれないランタイム側機能</h2>
<p>とりあえず、<code>DefaultImplementationsOfInterfaces</code> は最初の一歩です。
これからは定期的に、こういう .NET ランタイム側の修正が必要な機能が追加されていくものと思われます。
(おそらく、基本的にはメジャー バージョンアップのタイミングでの追加。
そんなに高頻度で追加はしないと思われます。)</p>
<p>例えば、以下のような issue ページがあります。
.NET ランタイム(CLR)に修正を入れれるなら実現できそうな C# 機能の一覧。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/317">What language proposals would benefit from CLR changes?</a></li>
</ul>
<p>挙がっている内容は、以下のようなものです。</p>
<h3>CLR unification of types across assemblies</h3>
<p>別アセンブリで定義された「同名で同じメンバーを含む型」を同一視したいというもの。</p>
<p>DI 用途でほしかったり。
あと、匿名クラス(内部的に匿名クラスを生成してる)が public なところで使えない理由にもなっているので回避方法が欲しいという要望があります。</p>
<h3>Make void a first-class type</h3>
<p>要するに、<code>Func&lt;void&gt;</code>とか<code>Task&lt;void&gt;</code>と書かせろ、
<code>Action</code>や非ジェネリック<code>Task</code>との分岐がめんどい、というあれ。</p>
<h3>Covariance and contravariance for classes</h3>
<p>現状、<a href="/study/csharp/sp4_variance.html">変性</a>が認められているのはインターフェイスとデリゲートだけなわけですが、どうにかしてクラスでも認めてほしいというやつ。</p>
<p><code>Task&lt;object&gt;</code> に <code>Task&lt;string&gt;</code> を代入したいとか、そういうやつ。</p>
<h3>|, &amp;, and ~ operators on a type parameter with the enum constraint</h3>
<p><code>where T : Enum</code> が付いてるとき、その型の変数に対してビット演算したいというやつ。
今、列挙型とジェネリクスの相性が悪すぎてつらく。</p>
<h3>Union and intersection types</h3>
<p>最近 TypeScript に入ったあれ。
<code>string | int</code> で「<code>string</code> か <code>int</code> のどちらか」みたいな型を作ったり、
<code>IA &amp; IB</code> で「2つのインターフェイス<code>IA</code>と<code>IB</code>の両方を実装した(両方のメソッドを使える)型」を作ったり。</p>
<p>ある程度は C# コンパイラーのレベルでできるんですが、
ランタイムに手を入れて型システムのレベルで対応した方がよいという話。</p>
<h3>Support generic indexers</h3>
<p>インデクサーに型引数を取りたいと。
↓みたいな。(今は、この<code>T</code>がどうやっても使えない。)</p>
<pre class="source" title="インデクサーに型引数">
<code><span class="reserved">public</span> <span class="reserved">interface</span> <span class="type">IOptions</span>
{
    <span class="type">T</span> <span class="reserved">this</span>&lt;<span class="type">T</span>&gt;[<span class="type">OptionKey</span>&lt;<span class="type">T</span>&gt; key]
    {
        <span class="reserved">get</span>;
        <span class="reserved">set</span>;
    }
}
</code></pre>
<h3>Higher-kinded polymorphism</h3>
<p>ジェネリクスの型制約に複雑な条件を付けたいというやつ。
例として挙がってるのは↓みたいなコード。</p>
<pre class="source" title="複雑な型制約">
<code><span class="reserved">public</span> <span class="reserved">static</span> <span class="type">T</span>&lt;<span class="type">A</span>&gt; To&lt;<span class="type">T</span>, <span class="type">A</span>&gt;(<span class="reserved">this</span> <span class="type">IEnumerable</span>&lt;<span class="type">A</span>&gt; xs)
    <span class="reserved">where</span> <span class="type">T</span> : &lt;&gt;, <span class="reserved">new</span>(), <span class="type">ICollection</span>&lt;&gt;
{
    <span class="reserved">var</span> ta = <span class="reserved">new</span> <span class="type">T</span>&lt;<span class="type">A</span>&gt;();
    <span class="reserved">foreach</span> (<span class="reserved">var</span> x <span class="reserved">in</span> xs)
    {
        ta.Add(x);
    }
    <span class="reserved">return</span> ta;
}
</code></pre>
<h3>methods in enums</h3>
<p>列挙型に直接メソッドを持ちたいというやつ。
拡張メソッドでの実装だとちょっとつらいこともあり。</p>
 ]]></description>
				<pubDate>Tue, 04 Dec 2018 10:13:34 +0900</pubDate>
			</item>
			<item>
				<title>Directory.Build.*</title>
				<link>http://ufcpp.net/blog/2018/12/directorybuild/</link>
				<description><![CDATA[ <p>なんか、Gist に書き捨ててそのまま放置なものが結構増えてきたので、
しばらくそれを元にブログに起こしていこうかという気分に。</p>
<p>ここ2年くらい、.NET Core や C# のテーマの1つがパフォーマンス改善だったせいもあって、だいぶ Unsafe でだいぶきわどい最適化の話が多めになるとは思います…</p>
<p>(ちなみに、今日のは全然その系統ではなく、きわどさもない話。)</p>
<h2>Directory.Build.*</h2>
<p>Visual Studio 2017 の頃から、所定のフォルダー以下にあるすべての <code>csproj</code> に対して掛かる共通設定を記述できるようになりました。以下の名前のファイルを置くことで、その内容が自動的に<code>csproj</code>にインポートされます。
(<code>dotnet</code>コマンドでのビルドにも有効です。)</p>
<ul>
<li><code>Directory.Build.props</code> … <code>csproj</code>の先頭にインポートされる</li>
<li><code>Directory.Build.targets</code> … <code>csproj</code> の末尾(NuGetパッケージに含まれている targets ファイルよりも後)にインポートされる</li>
</ul>
<p>そういえばあんまり紹介していなかったで、今日はこれの話でも。</p>
<h2>全フォルダーに影響</h2>
<p>このファイルを置くと、本当にありとあらゆる<code>csproj</code>に影響を及ぼします。
ビルド エラーを起こすようなミスを書いてしまうと、全プロジェクトがきっちり全滅します。
(そういうヤバさもあるので、これまでこの手の一括設定系の機能はあんまり提供されてこなかったんですけども。ここ数年、Visual Studio チームもだいぶ軟化しています。)</p>
<p>そんな、「全てに一律にかかってほしい設定」ってのがどれくらいあるかという話ではあります。</p>
<h3>Deterministic</h3>
<p>公式ドキュメントでは、「Deterministic オプション」を例に挙げています。</p>
<pre class="xsource" title="Deterministic">
<code><span class="attvalue">&lt;</span><span class="element">Project</span><span class="attvalue">&gt;</span>
<span class="attvalue">  &lt;</span><span class="element">PropertyGroup</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">Deterministic</span><span class="attvalue">&gt;</span>true<span class="attvalue">&lt;/</span><span class="element">Deterministic</span><span class="attvalue">&gt;</span>
<span class="attvalue">  &lt;/</span><span class="element">PropertyGroup</span><span class="attvalue">&gt;</span>
<span class="attvalue">&lt;/</span><span class="element">Project</span><span class="attvalue">&gt;</span>
</code></pre>
<p>これも Visual Studio 2017 (C# 7.0) の辺りで入った C# コンパイラーの機能なんですが、ソースコードを変更しない限り生成される DLL/EXE が常に同じバイナリになるというオプションです。</p>
<p>当たり前っぽく聞こえる話ですが、これまで、タイムスタンプが含まれてしまったり、
<a href="/study/csharp/oo_class.html#partial">partial 定義</a>している型を並列処理したとき順序保証が緩かったりで、ビルドのたびに生成物が変化していました。
そのせいで、CI ツールの類で毎度処理が走ってしまい、CI が当たり前な今の時代、だいぶ負担になっていたみたいです。</p>
<p>ただ、いきなり挙動を変えてしまうと既存の CI を壊す可能性があったので、オプションで切り替え可能に作ってあります。
今は、 .NET Core なプロジェクトであれば既定で Deterministic オプションが true になりますが、.NET Framework なプロジェクトの場合は既定が false だそうです。レガシーな .NET Framework は既定動作を変えなかったという話です。</p>
<p>ということで、.NET Framework でも常に true にしたいときに使うのが上記の設定。</p>
<h3>LangVersion latest</h3>
<p>僕が常用しているのはこれ。「LangVersion オプション」を常に latest に。</p>
<pre class="xsource" title="LangVersion">
<code><span class="attvalue">&lt;</span><span class="element">Project</span><span class="attvalue">&gt;</span>
<span class="attvalue"> &lt;</span><span class="element">PropertyGroup</span><span class="attvalue">&gt;</span>
<span class="attvalue">   &lt;</span><span class="element">LangVersion</span><span class="attvalue">&gt;</span>latest<span class="attvalue">&lt;/</span><span class="element">LangVersion</span><span class="attvalue">&gt;</span>
<span class="attvalue"> &lt;/</span><span class="element">PropertyGroup</span><span class="attvalue">&gt;</span>
<span class="attvalue">&lt;/</span><span class="element">Project</span><span class="attvalue">&gt;</span>
</code></pre>
<p>C# 7.0 以降、7.1、7.2、7.3 と、マイナー アップデートをしてきました。
細かく頻繁なリリースなので追いかけれない人というのを懸念してか、</p>
<ul>
<li>default … 最新のメジャー バージョンを使う(今だと、C# 7.0)</li>
<li>latest … 最新のマイナー バージョンを使う(今だと、C# 7.3)</li>
</ul>
<p>というような設定になります。
名前通り、規定値は default。つまり、何もしないと C# 7.0 までしか使えない。</p>
<p>うるせー、俺は常に最新の C# しか使わん。
と言う人にお勧めなのが、<code>Directory.Build.props</code> に<code>&lt;LangVersion&gt;latest&lt;/LangVersion&gt;</code>オプションを入れてしまう方法。
本当におすすめ。是非。</p>
<h3>パッケージ バージョン</h3>
<p>NuGet パッケージの面倒なところに、「バージョンの衝突があったとき、一番古い奴が使われる」という挙動があります。</p>
<p><img src="/media/1164/packageversion.png" alt="NuGet パッケージのバージョン衝突の解決" /></p>
<p>まあ、バージョン違いのものを参照している時点でいろいろ問題は起こしがちなので、
できれば全部のプロジェクトでバージョンをそろえたいです。
が、それはそれですごくめんどくさい。
Visual Studio にはソリューション全体の NuGet パッケージをまとめて管理する機能もありますが、ソリューションが分かれたりすると大変面倒です。
また、まとめてバージョン アップできても、Git の差分が多くて嫌になったりします。</p>
<p>そこで、<code>Directory.Build.targets</code>が使えます。
例として、<code>Google.Apis</code>パッケージでも参照してみましょう。
<code>Directory.Build.targets</code> (<code>props</code>だとダメ。最後に読まれる<code>targets</code>の方)に、以下のように<code>Update</code>属性指定でタグを書きます。</p>
<pre class="xsource" title="PackageReference (targets 中は Update で Version 指定)">
<code><span class="attvalue">&lt;</span><span class="element">Project</span><span class="attvalue">&gt;</span>
<span class="attvalue">  &lt;</span><span class="element">ItemGroup</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">PackageReference</span><span class="attvalue"> </span><span class="attribute">Update</span><span class="attvalue">=</span>"<span class="attvalue">Google.Apis</span>"<span class="attvalue"> </span><span class="attribute">Version</span><span class="attvalue">=</span>"<span class="attvalue">1.36.1</span>"<span class="attvalue"> /&gt;</span>
<span class="attvalue">  &lt;/</span><span class="element">ItemGroup</span><span class="attvalue">&gt;</span>
<span class="attvalue">&lt;/</span><span class="element">Project</span><span class="attvalue">&gt;</span>
</code></pre>
<p>配下にある <code>csproj</code> では、<code>Version</code> を指定せず、<code>Include</code> だけ指定します。</p>
<pre class="xsource" title="PackageReference (csproj 中は Version 未指定)">
<code><span class="attvalue">&lt;</span><span class="element">Project</span><span class="attvalue"> </span><span class="attribute">Sdk</span><span class="attvalue">=</span>"<span class="attvalue">Microsoft.NET.Sdk</span>"<span class="attvalue">&gt;</span>

<span class="attvalue">  &lt;</span><span class="element">PropertyGroup</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">OutputType</span><span class="attvalue">&gt;</span>Exe<span class="attvalue">&lt;/</span><span class="element">OutputType</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">TargetFramework</span><span class="attvalue">&gt;</span>netcoreapp2.1<span class="attvalue">&lt;/</span><span class="element">TargetFramework</span><span class="attvalue">&gt;</span>
<span class="attvalue">  &lt;/</span><span class="element">PropertyGroup</span><span class="attvalue">&gt;</span>

<span class="attvalue">  &lt;</span><span class="element">ItemGroup</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">PackageReference</span><span class="attvalue"> </span><span class="attribute">Include</span><span class="attvalue">=</span>"<span class="attvalue">Google.Apis</span>"<span class="attvalue"> /&gt;</span>
<span class="attvalue">  &lt;/</span><span class="element">ItemGroup</span><span class="attvalue">&gt;</span>

<span class="attvalue">&lt;/</span><span class="element">Project</span><span class="attvalue">&gt;</span>
</code></pre>
<p>これで、<code>Directory.Build.targets</code> 側に書かれた設定で「上書き」されて、
バージョンが 1.36.1 にそろいます。</p>
<p><code>Directory.Build.targets</code> 側に <code>Include</code> を書かないのは、無条件にパッケージ参照されないようにです。<code>Update</code>はすでに同じキーの<code>Include</code>がある場合にだけ働きます。</p>
<h3>C# 8.0 の null 許容参照型</h3>
<p>C# 8.0 で、null 許容参照型(単に <code>T</code> と書くと非 null で、参照型でも <code>T?</code> と書いて初めて null 許容になるフロー解析機能)が入りますが、
<code>T</code> の意味を変えてしまう手前、opt-in (明示的にオプション指定しないとこの機能が有効にならない)になります。</p>
<p>ソースコード中に <code>#nullable</code> ディレクティブを書くことでその行以下の opt-in/opt-out ができますが、それに加えて、プロジェクト全体で opt-in するための csproj プロパティも用意されています。
今のところ、<code>NullableReferenceTypes</code>というタグ名になりそう<sup>※</sup>。</p>
<p><sup>※</sup> 追記: その後、正式リリースまでの間に <code>Nullable</code> タグに変更になりました。</p>
<pre class="xsource" style="text-decoration: line-through" title="2018/12当時の仕様">
<code><span class="attvalue">&lt;</span><span class="element">PropertyGroup</span><span class="attvalue">&gt;</span>
<span class="attvalue">  &lt;</span><span class="element">NullableReferenceTypes</span><span class="attvalue">&gt;</span>True<span class="attvalue">&lt;/</span><span class="element">NullableReferenceTypes</span><span class="attvalue">&gt;</span>
<span class="attvalue">&lt;/</span><span class="element">PropertyGroup</span><span class="attvalue">&gt;</span>
</code></pre>
<pre class="xsource" title="正式版での仕様">
<code><span class="attvalue">&lt;</span><span class="element">PropertyGroup</span><span class="attvalue">&gt;</span>
<span class="attvalue">  &lt;</span><span class="element">Nullable</span><span class="attvalue">&gt;</span>enable<span class="attvalue">&lt;/</span><span class="element">Nullable</span><span class="attvalue">&gt;</span>
<span class="attvalue">&lt;/</span><span class="element">PropertyGroup</span><span class="attvalue">&gt;</span>
</code></pre>
<p>既存のプロジェクトに対していきなりこのオプションを指定するのはちょっと勇気が要ります(相当数の警告が出ます)が、
新規に作り始めるプロジェクトであれば、この設定を入れてしまった方がいいでしょう。</p>
 ]]></description>
				<pubDate>Mon, 03 Dec 2018 17:21:44 +0900</pubDate>
			</item>
			<item>
				<title>タプル要素名の大文字・小文字</title>
				<link>http://ufcpp.net/blog/2018/12/tupleelementcase/</link>
				<description><![CDATA[ <p>タプルの要素名は<code>(int x, int y)</code> みたいに camelCase (先頭小文字) で書くべきか、
<code>(int X, int Y)</code> みたいに PascalCase (先頭大文字) で書くべきか、
割かし最近、この問題が再燃してたりしました。</p>
<h2>背景1: C# のコーディング規約</h2>
<p>大体のプログラミングでは、別に大文字・小文字に意味があるわけではなく、
<code>x</code> と書こうが <code>X</code> と書こうが原理的には自由です。
しかし、実践的には、「その言語の標準ライブラリ辺りに合わせる」というのが一般的かと思います。
現在の C# であれば、「<a href="https://docs.microsoft.com/ja-jp/dotnet/standard/design-guidelines/naming-guidelines">Naming Guidelines</a>」辺りに合わせるのが無難でしょう。</p>
<p>(ちなみに、上記の規約は public な部分にしか言及していません。
割かし「private なところは自由にしたらいいんじゃないか」な文化です。
<a href="https://github.com/dotnet/corefx">corefx</a>なんかは独自に<a href="https://github.com/dotnet/corefx/blob/master/Documentation/coding-guidelines/coding-style.md">C# Coding Style</a>を持っていたりしますが、
これはあくまで corefx に pull request を出すときに気を付けるべき規約であって、
全ての C# 利用者に対して強制するものではありません。
)</p>
<p>今日の主題は casing/capitalization (変数などの先頭を大文字にするか小文字にするか)になります。
今日の話に関係するのは以下の2つ。</p>
<ul>
<li>
メンバー名は大体 PascalCase
<ul>
<li>フィールドであっても、public なものは PascalCase</li>
</ul>
</li>
<li>引数名・ローカル変数名は camelCase</li>
</ul>
<pre class="source">
<code><span class="reserved">public</span> <span class="reserved">class</span> <span class="type">Class</span>
{
    <span class="comment">// フィールドも、public なものは大文字始まり</span>
    <span class="reserved">public</span> <span class="reserved">int</span> PublicField;

    <span class="comment">// private なものについては割かし自由</span>
    <span class="comment">// ほとんどの人は小文字始まり。</span>
    <span class="comment">// 先頭に _ を付けるかどうかは好みが分かれるものの、 _ を付ける人の方がちょっと多い印象。</span>
    <span class="reserved">private</span> <span class="reserved">int</span> _privateField;

    <span class="comment">// 引数は小文字始まり</span>
    <span class="reserved">public</span> <span class="reserved">void</span> M(<span class="reserved">int</span> parameter)
    {
        <span class="comment">// ローカル変数は小文字始まり</span>
        <span class="reserved">int</span> localVariable = parameter;
    }
}
</code></pre>
<h2>背景2: タプル戻り値</h2>
<p>やりたかったことは、要するに LINQ の <code>Zip</code> メソッドにオーバーロードを足したいというもの。
今あるオーバーロードだと、以下のような書き方をよくやると思います。</p>
<pre class="source" title="">
<code><span class="reserved">var</span> x = <span class="reserved">new</span>[] { 1, 2, 3 };
<span class="reserved">var</span> y = <span class="reserved">new</span>[] { <span class="string">"one"</span>, <span class="string">"two"</span>, <span class="string">"three"</span> };
<span class="reserved">var</span> zip = x.Zip(y, (i, s) =&gt; (i, s));
</code></pre>
<p>今の <code>Zip</code> は最後の引数で必ずデリゲートを1個渡す必要がありますが、
大抵の場合はこの例のように「単にタプルで返したい」で十分です。
そこで、以下のようなオーバーロードを足す流れになりました。</p>
<pre class="source" title="">
<code><span class="reserved">static</span> <span class="reserved">class</span> <span class="type">Enumearble</span>
{
    <span class="reserved">public</span> <span class="reserved">static</span> IEnumerable&lt;(TFirst First, TSecond Second)&gt; Zip&lt;<span class="type">TFirst</span>, <span class="type">TSecond</span>&gt;(
        <span class="reserved">this</span> IEnumerable&lt;TFirst&gt; first, IEnumerable&lt;TSecond&gt; second)
        =&gt; first.Zip(second, (x, y) =&gt; (x, y));
        <span class="comment">// 実際には効率化のためにもうちょっと複雑な実装。返す値自体はこれと同じ。</span>
}
</code></pre>
<h2>問題: タプル戻り値の casing</h2>
<p>先ほどの <code>Zip</code> の新オーバーロードですが、戻り値が
<code>IEnumerable&lt;(TFirst First, TSecond Second)&gt;</code>です。
問題となるのは <code>First</code>、<code>Second</code> の部分。</p>
<p>タプルの要素名の casing をどうするべきかは結構意見が割れます。
なぜかというと、</p>
<ul>
<li>
タプルは構造体の一種なんで、各要素は public なフィールドである
<ul>
<li>だとすると、一般的な規約では PascalCase (先頭大文字)</li>
</ul>
</li>
<li>
タプルは「変数をペアリングしたもの」あるいは「引数リストの一般化」である
<ul>
<li>だとすると、camelCase (先頭小文字)</li>
</ul>
</li>
</ul>
<p>前者の立場(構造体のフィールド派)は以下のような感じ。</p>
<pre class="source" title="">
<code><span class="comment">// 立場1: 構造体のフィールド派</span>
<span class="reserved">static</span> <span class="reserved">void</span> A()
{
    <span class="comment">// 以下の2行の差は「匿名か、名前付きか」だけ。</span>
    <span class="reserved">var</span> p = <span class="reserved">new</span> Point(1, 2);
    <span class="reserved">var</span> q = (1, 2);

    <span class="comment">// タプルは「名前がない型」なだけで、各要素はフィールドみたいなもの。</span>

    <span class="comment">// 大体、上記のように要素名を省略した場合、Item1, Item2 と、PacalCase な名前で値を参照することになる。</span>
    System.Console.WriteLine(q.Item1);

    <span class="comment">// 以下のように、PascalCase にしておいた方が「名前付き」の場合とそろってていい。</span>
    <span class="comment">// このタプル(無名の型)から、自動リファクタリングで Point 型みたいなものを生成することもあり得えて、その場合 PascalCase の方が自然</span>
    <span class="reserved">var</span> r = (X: 1, Y: 2);
    <span class="reserved">var</span> x1 = p.X;
    <span class="reserved">var</span> x2 = r.X;
}
</code></pre>
<p>後者の立場(引数の一般化派)は以下の通り。</p>
<pre class="source" title="">
<code><span class="comment">// 立場2: 引数の一般化派</span>
<span class="reserved">static</span> <span class="reserved">void</span> B()
{
    <span class="reserved">var</span> p = <span class="reserved">new</span> Point(1, 2);
    <span class="reserved">var</span> q = (1, 2);

    <span class="comment">// タプルは「引数リストだけがむき出しになっている」という状態。</span>

    <span class="comment">// 「名前付き引数」を使うと以下のような書き方になるわけで、それに合わせる方が自然。</span>
    <span class="reserved">var</span> r = <span class="reserved">new</span> Point(x: 1, y: 2);
    <span class="reserved">var</span> s = (x: 1, y: 2);

    <span class="comment">// s.x という書き方も、「変数 x, y が s によってペアリングされてる」程度の認識。</span>
    <span class="reserved">var</span> sum = s.x + s.y;
}

<span class="comment">// 引数リストとタプル戻り値がほぼ同じ書き方。</span>
<span class="comment">// タプルは引数の対となるもの。</span>
<span class="reserved">static</span> (<span class="reserved">int</span> x, <span class="reserved">int</span> y) Swap(<span class="reserved">int</span> x, <span class="reserved">int</span> y) =&gt; (y, x);
</code></pre>
<h2>どちらが有力か</h2>
<p>C# チームは「引数の一般化派」です。
なので、タプル(C# 7.0)がリリースされてからの2年ほど、
大抵の場所で camelCase が使われてきました。</p>
<p>それに対して、今回、2年越しで corefx 方面に「構造体のフィールド派」が多かったみたいです。
その結果、前述の<code>Zip</code>の戻り値は PascalCase で作られて、
一度それの pull request はマージされました。</p>
<p>ここで、両者の齟齬が発覚。
もめ始めて、</p>
<ul>
<li>いったん <code>Zip</code> のやつは revert</li>
<li>camelCase か PascalCase かちゃんと決めて、規約に書いとこうぜ</li>
<li>
決めかねる。というか、タプルを public なところに使うこと自体よくない
<ul>
<li><code>Zip</code> みたいに「2要素で確定」みたいなものならともかく、通常は、要素(フィールド)を増やすだけで破壊的変更になってしまうようなものは public には使いにくい</li>
</ul>
</li>
<li>規約に書くなら「タプルは public なところに使うものじゃない」がいい</li>
</ul>
<p>みたいな流れに。</p>
<p>結局、前述の <code>Zip</code> 新オーバーロードは、以下のような構造体を返す作りにおそらく変更されることになりそうです。</p>
<pre class="source" title="">
<code><span class="reserved">public</span> <span class="reserved">readonly</span> <span class="reserved">struct</span> <span class="type">ZipResult</span>&lt;<span class="type">TFirst</span>, <span class="type">TSecond</span>&gt;
{
    <span class="reserved">public</span> ZipResult(<span class="type">TFirst</span> first, <span class="type">TSecond</span> second) =&gt; (First, Second) = (first, second);
    <span class="reserved">public</span> <span class="type">TFirst</span> First { <span class="reserved">get</span>; }
    <span class="reserved">public</span> <span class="type">TSecond</span> Second { <span class="reserved">get</span>; }
    <span class="reserved">public</span> <span class="reserved">void</span> Deconstruct(<span class="reserved">out</span> <span class="type">TFirst</span> first, <span class="reserved">out</span> <span class="type">TSecond</span> second) =&gt; (first, second) = (First, Second);
}
</code></pre>
<p>規約に関しては、タプル要素名の casing についてはやっぱり両論あって決まらなさそう。
その代わり、corefx 内では「DO NOT: タプルは public API で使うな」規約を足しそうな雰囲気になっています。
(これももちろん、あくまで corefx 内の話です。corefx は「破壊的変更を起こしそうなもの」を特に強く避ける文化なのでかなり保守的。)</p>
 ]]></description>
				<pubDate>Sun, 02 Dec 2018 15:55:43 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 12/1</title>
				<link>http://ufcpp.net/blog/2018/12/pickuproslyn1201/</link>
				<description><![CDATA[ <p>10月31日～11月28日当たりの Design Notes 追加。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/2032">Added: LDM notes for Oct. 31, Nov. 5, and Nov. 14 #2032</a></li>
<li><a href="https://github.com/dotnet/csharplang/issues/2033">Added: LDM Notes for Nov. 28, 2018 #2033</a></li>
</ul>
<p>ちなみにこの辺りの実装、pull request を探してみたら Milestone が <a href="https://github.com/dotnet/roslyn/milestone/36">16.0.P2</a>になっているものが結構あって、近々出てくれそうな Visual Studio 16 Preview 1 ではまだ入ってなさそうなもの多めです。</p>
<h2>Nullable Reference Types</h2>
<p>今回の Design Notes の半分くらいは null 許容参照型がらみ。</p>
<p>あと、書きかけではありますが、やっと null 許容参照型の提案ドキュメントがアップロードされたみたいです。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/blob/master/proposals/nullable-reference-types-specification.md">Nullable Reference Types Specification</a></li>
</ul>
<p>(これまで、Design Notes に検討事項が散見されていただけで、まとまったページが全くなかったという…)</p>
<p><a href="https://github.com/dotnet/csharplang/blob/master/meetings/2018/LDM-2018-10-31.md">10月31日のやつ</a>は、なんか問題提起だけで結論が入ってなくて、なんかふんわりとした感じ。</p>
<ul>
<li>
明示的な null チェック
<ul>
<li>8.0 というバージョンから急に null 許容参照型を追加する都合で、<code>string x</code> は「古いコード由来だとnull許容なんだけど、8.0以降＋<code>#nullable enable</code>の時には非nullとして扱う」みたいな挙動になる</li>
<li><code>string x</code> に対して<code>if (x == null)</code> があるとき、「明示的に null チェックがあるということは、<code>x</code> 自体は null があり得る」ということなので、<code>string</code> (<code>?</code> が付かない)であっても null 許容扱いする</li>
<li>みたいなの、やるべきかどうか。TypeScript はやってる</li>
</ul>
</li>
<li>
リファクタリング
<ul>
<li>null かどうかのフロー解析は、リファクタリングの影響を受けるという話</li>
<li>例えば、<code>if</code> の中身だけを「メソッド抽出」リファクタリングすると、<code>if</code> の条件式内でやった null チェックの情報を失って(メソッドをまたいだ解析はしないので)、警告が出る</li>
</ul>
</li>
<li>
<code>!</code> 演算子
<ul>
<li>場所によって意味変わりすぎ… (前に置くと否定、後ろに置くて「null forgiving」(null チェックを意図的にやらない)アノテーション)</li>
</ul>
</li>
<li>
ラムダ式中での代入
<ul>
<li>ラムダ式でキャプチャした変数までフロー解析するべきかどうか</li>
</ul>
</li>
</ul>
<p><a href="https://github.com/dotnet/csharplang/blob/master/meetings/2018/LDM-2018-11-05.md">11月5日の</a>:</p>
<ul>
<li>
<code>#nullable</code> の影響する範囲はどこまでか
<ul>
<li>例えば以下のようなコードを書いた場合、disable になるのは第2型引数の<code>string</code>と、<code>Dictionary</code> 自体(<code>Dictionary</code>のシグネチャの一部分である<code>&gt;</code>を範囲に含んでいるので)</li>
</ul>
</li>
</ul>
<pre class="source">
<code><span class="type">Dictionary</span>&lt;<span class="reserved">string</span>,
<span class="inactive">#nullable</span> disable
    <span class="reserved">string</span>&gt;
<span class="inactive">#</span> <span class="inactive">nullable</span> enable
</code></pre>
<ul>
<li>
null 許容参照型
<ul>
<li><code>using</code>ディレクティブ中では認めない？ → そのつもり</li>
<li><code>typeof</code>、<code>nameof</code>は？ → 値型の nullable と同じ挙動にしたい。なので、<code>typeof</code>では認めて、<code>nameof</code>では認めない</li>
</ul>
</li>
</ul>
<p><a href="https://github.com/dotnet/csharplang/blob/master/meetings/2018/LDM-2018-11-14.md">11月14日の</a>:</p>
<ul>
<li>
(同じく C# 8.0 で入る) <code>switch</code>式の網羅性(exhaustiveness)とnull
<ul>
<li>「非 null 参照型だから null は来ないはず」判定のときに、実際には(フロー解析漏れ/C# 7.X 以前のコード由来のせいで) null が来た時どうするか？</li>
<li>→ <code>MatchFailureException</code>例外を投げることにする。<code>MatchFailureException</code>の基底は<code>InvalidOperationException</code> にする</li>
</ul>
</li>
</ul>
<p><a href="https://github.com/dotnet/csharplang/blob/master/meetings/2018/LDM-2018-11-28.md">11月28日の</a>:</p>
<ul>
<li>
多重配列問題
<ul>
<li><code>string[]?[]</code>と<code>string[][]?</code>、「null 許容配列の非 null 配列」と「非 null 配列の null 許容配列」どっちがどっち？</li>
<li>→ 現状、<code>string[]?[]</code> の方が「非 null 配列の null 許容配列」</li>
<li>多重配列の順序は元々ややこしい…</li>
</ul>
</li>
</ul>
<h2>パターン マッチング</h2>
<ul>
<li>
<code>x is (a, b)</code> みたいなパターン
<ul>
<li>x がタプル(<code>ValueTupe&lt;T&gt;</code>構造体等)なら普通にタプル扱いで分解(要素ごとにマッチング)</li>
<li><code>Deconstruct</code>メソッドがあれば(拡張メソッドでの実装を含めて)それを使って分解</li>
<li><code>ITuple</code> インターフェイスを実装していたら、そのインデクサーとかを使って分解</li>
<li>(優先度は上から順。<code>ITuple</code>インターフェイスを実装していて、かつ、<code>Deconstrcut</code> メソッドも持っていたら<code>Deconstruct</code>の方優先)</li>
</ul>
</li>
<li>
0, 1 要素
<ul>
<li><code>x is ()</code> 認めてくれるらしい(0引数の <code>Deconstruct</code> 呼び出し)</li>
<li><code>x is (1)</code> とかも認めてくれるらしい(1引数の<code>Decontruct</code>呼び出し)</li>
<li>これは、パターン マッチング(<code>is</code>と<code>switch</code>-<code>case</code>)の時だけ働く。既存の分解代入・分解変数宣言では、キャストとかとの弁別ができないので残念ながら認められない</li>
</ul>
</li>
</ul>
<h2>インターフェイスのデフォルト実装</h2>
<p>C# では、<code>base.Member</code> みたいな書き方で、基底クラスのメンバーを呼べます。
(override していても、この書き方なら基底クラス側の実装が呼ばれる。)</p>
<p>で、C# 8.0でインターフェイスのデフォルト実装が入ることで、
「メソッドの実装の多重継承」ができるようになってしまい、
<code>base.Member</code>だけだと「どっちの基底だよ」と不明瞭に。</p>
<p>そこで、「どの基底インターフェイスのメンバーか」を指定するための構文が必要になります。
候補はたくさん並んでいますが、採用するのは <code>base(BaseInterface).Member</code> みたいな書き方にしたいそうです。</p>
<h2>非同期ストリームのキャンセル</h2>
<p>非同期ストリーム(<code>IAsyncEnumerable&lt;T&gt;</code>インターフェイス、非同期 <code>foreach</code>、<code>yield</code>と<code>await</code>の混在)に <code>CancellationToken</code> を渡せるようにするという話。
元々「できないとまずいよね」という検討はされてるんですが、やっと「どうするか」まで決めたみたいです。</p>
<p>まず、インターフェイス。<code>GetAsyncEnumerator</code>の引数に<code>CancellationToken</code>を足すみたいです。</p>
<pre class="source" title="">
<code><span class="reserved">interface</span> <span class="type">IAsyncEnumerable</span>&lt;<span class="type">T</span>&gt;
{
    <span class="type">IAsyncEnumerator</span>&lt;<span class="type">T</span>&gt; GetAsyncEnumerator(<span class="type">CancellationToken</span> token = <span class="reserved">default</span>);
</code></pre>
<p>あと、拡張メソッドで <code>IAsyncEnumerable&lt;T&gt; WithCancellationToken&lt;T&gt;(this IAsyncEnumerable&lt;T&gt; e, CancellationToken token)</code> も用意。</p>
<p>非同期 <code>foreach</code> と<code>yield</code>と<code>await</code>の混在については、
細かい単位で<code>CancellationToken</code>を渡せるような構文を用意するかどうかという検討はしたものの、
とりあえず現状はそういう特別なことはしないという結論に。</p>
 ]]></description>
				<pubDate>Sat, 01 Dec 2018 20:35:39 +0900</pubDate>
			</item>
			<item>
				<title>C# 8.0 の予告</title>
				<link>http://ufcpp.net/blog/2018/11/cs80_net48/</link>
				<description><![CDATA[ <p>一昨日、C# 8.0 に関するブログが出たわけですが。</p>
<ul>
<li><a href="https://blogs.msdn.microsoft.com/dotnet/2018/11/12/building-c-8-0/">Building C# 8.0</a></li>
</ul>
<p>個人的には「最近全然ブログ書かない C# チームが働いただと…」的な感想もあるんですが
(C# 7.3 のときとか「半年前にリリースしてたわ」みたいなブログでした)。
近々プレビュー版が公開されるであろう C# 8.0 の予告記事です。</p>
<p>Visual Studio 15.9 正式リリースに続いて近々、Visual Studio 16.0 のプレビュー版も公開されて、
それと一緒に .NET Core 3.0 と C# 8.0 もプレビュー公開になると思われます。</p>
<h2>.NET Framework 4.8 は未サポート？</h2>
<p>で、「.NET Framework 4.8 は .NET Standard 2.1 に追従しないので、C# 8.0 に対応しない」みたいな感じのことが話題になっていますが。
これ、多少不正確でして。
正しくは、</p>
<ul>
<li>
一部、必要なライブラリが .NET Framework 4.8 には提供されない
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/185">Ranges</a> … <a href="https://github.com/dotnet/coreclr/pull/20899"><code>Range</code>構造体と<code>Index</code>構造体</a></li>
<li><a href="https://github.com/dotnet/csharplang/issues/43">Async Streams</a> … <a href="https://github.com/dotnet/coreclr/pull/20628"><code>IAsyncEnumerable&lt;T&gt;</code>インターフェイスと<code>IAsyncDisposable</code>インターフェイス</a></li>
</ul>
</li>
<li>
ランタイム自体に手を入れないと実現できない機能があって、 .NET Framework 4.8 はそれを実装しない
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/52">インターフェイスのデフォルト実装</a></li>
</ul>
</li>
</ul>
<p>という3つの機能に制限が掛かるだけ。他の機能は普通にどの TargetFramework でも動きます。
<a href="https://github.com/dotnet/csharplang/issues/36">null 許容参照型</a>とか<a href="https://github.com/dotnet/csharplang/issues/45">パターン マッチング</a>の完全版とか switch 式とかは .NET Framework 1.0 ですら動くと思われます。</p>
<h3>必要ライブラリ</h3>
<p>まあ、<code>Range</code>/<code>Index</code>構造体なんて結構小さい型なので、
例のごとく<a href="/study/csharp/cheatsheet/listfxlangversion/#how-to">自分で同じ名前・同じ機能の構造体を書いてしまえば</a>普通に古いランタイムでも C# 8.0 の機能を使えます。</p>
<p>といっても、Ranges の機能は、配列とか <code>Span&lt;T&gt;</code> が対応していて初めて役に立つものです。
(以下のような書き方をするためには、配列側が対応している必要あり。)</p>
<pre class="source" title="">
<code><span class="reserved">int</span>[] data = { 1, 2, 3, 4, 5, 6 };
<span class="type">Span</span>&lt;<span class="reserved">int</span>&gt; span = data[1..^1];
<span class="reserved">foreach</span> (var x <span class="reserved">in</span> span)
    Console.WriteLine(x); <span class="comment">// 2, 3, 4, 5</span>
</code></pre>
<p>既存の型に <code>Range</code> 型対応を混ぜ込むのはちょっと無理なので、
その意味では .NET Standard 2.1 でないと大して役に立たない機能になります。</p>
<p>Async Streams の方も似たような感じ。
<code>IAsyncEnumerable&lt;T&gt;</code>インターフェイス自体の移植は簡単ですが、
それに対応したライブラリがないとあんまりおいしくないかもしれません。</p>
<h3>インターフェイスのデフォルト実装</h3>
<p>本当にどうあがいても .NET Framework 4.8 では動かせないのはこちら。
インターフェイスのデフォルト実装だけです。</p>
<p>ちなみに、どんな感じで「動かせない」かというと、</p>
<ul>
<li>
TargetFramework net48 でも、LangVersion 8.0 自体は選べる
<ul>
<li>前述のとおり、大半の機能は普通に使えます</li>
</ul>
</li>
<li>TargetFramework net48 を選んだ場合、デフォルト実装を使ったところだけコンパイル エラーになる</li>
</ul>
<p>みたいな感じ。
デフォルト実装自体そんなに使う機能でもないと思うので、
大抵の状況では特に問題にならないと思います。</p>
<h3>RuntimeFeature クラス</h3>
<p>デフォルト実装の話、
要するに、LangVersion だけじゃなくて、TargetFramework によっても文法に分岐が掛かることになります。</p>
<p>ちなみに、正確にいうと、TargetFramework 自体を見て分岐しているのではなくて、
<a href="https://source.dot.net/#System.Runtime/System.Runtime.cs,6753"><code>RuntimeFeature</code>クラス</a>のプロパティがあるかないかで分岐しています。</p>
<p>以下のようなクラスなんですが、この<code>DefaultImplementationsOfInterfaces</code>プロパティが存在するランタイムでだけデフォルト実装が使えます。</p>
<pre class="source" title="">
<code><span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">partial</span> <span class="reserved">class</span> <span class="type">RuntimeFeature</span>
{
<span class="inactive">#if</span> FEATURE_DEFAULT_INTERFACES
        <span class="reserved">public</span> <span class="reserved">const</span> <span class="reserved">string</span> DefaultImplementationsOfInterfaces = <span class="string">"DefaultImplementationsOfInterfaces"</span>;
<span class="inactive">#endif</span>
    <span class="reserved">public</span> <span class="reserved">const</span> <span class="reserved">string</span> PortablePdb = <span class="string">"PortablePdb"</span>;
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">bool</span> IsSupported(<span class="reserved">string</span> feature) { <span class="reserved">throw</span> <span class="reserved">null</span>; }
}
</code></pre>
<h2>.NET Standard 2.1</h2>
<p>ちなみに、ちょっとわかりにくいですが、</p>
<ul>
<li>登場時期: .NET Core 3.0 = .NET Standard 2.1 = .NET Framework 4.8</li>
<li>持っている機能: .NET Core 3.0 &gt; .NET Standard 2.1 ≒ .NET Core 2.1 &gt; .NET Framework 4.8 = .NET Standard 2.0</li>
</ul>
<p>みたいな感じ。
.NET Standard 2.1 の主だった新機能は<code>ValueTask</code> がらみと <code>Span&lt;T&gt;</code> がらみです。
.NET Core 2.1 ですでにおなじみ(？)のやつ。</p>
<p>(Ranges と Async Streams、最初は .NET Core 3.0 でないと使えないのでは疑惑も多少。
.NET Standard 2.1 に入るのかな…)</p>
<h2>.NET Framework の今後の扱い</h2>
<p>ということで、C# 8.0 への対応という意味では .NET Framework でもそこまで大した問題にはならないと思います。</p>
<p>が、まあ、「.NET Framework 4.8 は最新のものに追従しない」というのは事実。</p>
<p>とりあえず、</p>
<ul>
<li>
同世代の .NET Core 3.0 では Windows 限定機能(WPF, UWP)にもついに対応する
<ul>
<li>もう .NET Framework の方でしか使えない機能が残っていないはず</li>
<li>新規案件で .NET Framework を使うメリットがもう何もない</li>
</ul>
</li>
<li>
保守モードな既存のアプリにまで .NET Core への移行を要請しないだけ良心的
<ul>
<li>そのための「保守アップデート」が .NET Framework 4.8</li>
<li>セキュリティ パッチとかはきっちり当てて出す</li>
</ul>
</li>
</ul>
<p>という感じ。
この辺りに関しては、 C# 8.0 のブログ以前に、
今月初旬に出てる以下のブログの方ですでに告知済みだったり。</p>
<ul>
<li><a href="https://blogs.msdn.microsoft.com/dotnet/2018/11/05/announcing-net-standard-2-1/">Announcing .NET Standard 2.1</a></li>
</ul>
<p>こっちを見る限り、.NET Framework 4.8 が追従しないのは、デフォルト実装だけじゃなくて、
<code>Span&lt;T&gt;</code>がらみの方が主みたいです。</p>
<p>「<a href="/study/csharp/resource/span/"><code>Span&lt;T&gt;</code>構造体</a>」で書いているように、
<code>Span&lt;T&gt;</code>にはslow版(古いランタイムでも動く実装)とfast版(.NET Core 2.1 以降でないと動かない安全かつ高速な実装)の2種類あります。
その<code>Span&lt;T&gt;</code>を使ったライブラリの中には、fast版の安全性保証がないとまずいものもいくつかあって、
そういうものは .NET Standard 2.0 以前向けには提供されていません。</p>
<p>.NET Framework 4.8はこのfast <code>Span&lt;T&gt;</code>対応もできておらず、
なので、.NET Standard 2.0 のまま据え置きということになります。</p>
 ]]></description>
				<pubDate>Wed, 14 Nov 2018 18:40:47 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 10/14: #nonnullディレクティブ、IAsyncEnumerable</title>
				<link>http://ufcpp.net/blog/2018/10/pickuproslyn1014/</link>
				<description><![CDATA[ <p><a href="https://github.com/dotnet/csharplang/issues/1925">Design Notes 2件追加</a>。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/blob/master/meetings/2018/LDM-2018-10-01.md">C# Language Design Notes for Oct 1, 2018</a></li>
<li><a href="https://github.com/dotnet/csharplang/blob/master/meetings/2018/LDM-2018-10-03.md">C# Language Design Notes for Oct 3, 2018</a></li>
</ul>
<p>10/1 のは、nullable 参照型がジェネリクスに絡むときの話。
例えば以下のような、型推論とかについての検討。</p>
<pre class="source" title="">
<code><span class="reserved">using</span> System.Collections.Generic;

<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> Main()
    {
        <span class="type">IEnumerable</span>&lt;<span class="reserved">string</span>&gt; nonNull = <span class="reserved">new</span>[] { <span class="string">""</span> };
        <span class="type">IEnumerable</span>&lt;<span class="reserved">string</span>?&gt; nullable = <span class="reserved">new</span>[] { <span class="reserved">default</span>(<span class="reserved">string</span>) };

        <span class="comment">// 配列の要素の型推論。</span>
        <span class="comment">// これは、IEnumerable&lt;string?&gt;[] になってるみたい。</span>
        <span class="reserved">var</span> array = <span class="reserved">new</span>[] { nonNull, nullable };

        <span class="comment">// ジェネリック メソッドの型引数の型推論。</span>
        <span class="comment">// 配列の要素と似たような推論になるはず。</span>
        <span class="comment">// が、201/9/11 版の実装では IEnumerable&lt;string&gt; で推論されてる。</span>
        <span class="comment">// この挙動が変だよね、と言うのが議題。</span>
        <span class="reserved">var</span> ret = M(nonNull, <span class="warning">nullable</span>);
    }

    <span class="reserved">static</span> <span class="type">T</span> M&lt;<span class="type">T</span>&gt;(<span class="type">T</span> x, <span class="type">T</span> y) =&gt; x;
}
</code></pre>
<p>10/3 の方は、null チェックのコンテキスト切り替えの再検討と、
<code>IAsyncEnumerable</code>インターフェイスの実装方法の決定について。</p>
<h2>null チェックのコンテキスト切り替え</h2>
<p>改めての説明になりますが、元々 null の存在を前提にしている C# にとって、
nullable 参照型(<code>T</code> だと非 null、<code>T?</code> で null 許容)の追加は、何も考えずにやると破壊的変更になってしまいます。
破壊的変更を極力避けている C# にとってそれはまずいので、null チェックの On/Off を切り替える仕組みを用意する予定です。</p>
<p>これまでのプレビュー版では、とりあえず属性ベースでコンテキスト切り替えが実装されていました。
<code>NonNullTypes</code>属性を付けたら On、付けていないかもしくは<code>NonNullTypes(Warning = false)</code>で Off。
が、そのやり方だと苦しそうということで、プリプロセッサ－でやる(<code>#nonnull</code>ディレクティブみたいなものを追加する)ことを改めて検討しているそうです。</p>
<p>(これまでの C# だと、属性の有無によってコンパイラーの挙動がガラッと変わるというような実装をしたことがなく、
そういう「モラル的な意味」でもあまり良くないのは元々良くないんですが、技術的にも苦しそうなことがわかってきたとか。)</p>
<p>ということで、やるとしたら以下の3つのうちのどれかになるだろうということで、これらをそれぞれ検討。</p>
<ul>
<li>
修飾子を作る
<ul>
<li>非同期メソッドの <code>async</code> 修飾子みたいなの</li>
</ul>
</li>
<li>
属性でやるなら、かなり特別扱いした「疑似属性」的なものになる
<ul>
<li><code>const</code> を受け付けない(<code>true</code>, <code>false</code> の直指定しか受け付けない)とか、名前付き引数を認めないとか</li>
</ul>
</li>
<li>
ディレクティブを使う
<ul>
<li><code>#pragma warning</code>と同じノリで、<code>#nonnull disable</code>、<code>#nonnull restore</code>で制御</li>
<li>プロジェクト全体の On/Off 制御のために、コンパイラー オプションも必要</li>
</ul>
</li>
</ul>
<p>で、とりあえず、ディレクティブを使ったアプローチで行ってみようという感じになっているみたいです。
(実際もう、pull request も出てて merge 済み。)</p>
<h2>IAsyncEnumerableインターフェイスの実装方法</h2>
<p>非同期ストリーム(<code>await</code>と<code>yield</code>の混在と、非同期版 <code>foreach</code>)を実装するにあたって、インターフェイスをどうするかというのがずっと課題になっていました。
同期版だと、<code>IEnumerable&lt;T&gt;</code>(と、同じ名前のメソッドを持ってさえいればOK)を使うわけですが、
それの非同期版である<code>IAsyncEnumarable&lt;T&gt;</code>はどういうメソッドを持つべきか。</p>
<p>結局、以下のように、<code>IEnumerable&lt;T&gt;</code>とほぼ同じで単に<code>Async</code>語尾を付け、<code>ValueTask</code>を返す作りにしたいとのこと。</p>
<pre class="source" title="">
<code><span class="reserved">public</span> <span class="reserved">interface</span> <span class="type">IAsyncEnumerable</span>&lt;<span class="reserved">out</span> <span class="type">T</span>&gt;
{
    <span class="type">IAsyncEnumerator</span>&lt;<span class="type">T</span>&gt; GetAsyncEnumerator();
}

<span class="reserved">public</span> <span class="reserved">interface</span> <span class="type">IAsyncEnumerator</span>&lt;<span class="reserved">out</span> <span class="type">T</span>&gt; : <span class="type">IAsyncDisposable</span>
{
    <span class="type">ValueTask</span>&lt;<span class="reserved">bool</span>&gt; MoveNextAsync();
    <span class="type">T</span> Current { <span class="reserved">get</span>; }
}

<span class="reserved">public</span> <span class="reserved">interface</span> <span class="type">IAsyncDisposable</span>
{
    <span class="type">ValueTask</span> DisposeAsync();
}
</code></pre>
<p>他の選択肢としては、以下のようなものが検討されていました。</p>
<pre class="source" title="">
<code><span class="reserved">public</span> <span class="reserved">interface</span> <span class="type">IAsyncEnumerator</span>&lt;<span class="reserved">out</span> <span class="type">T</span>&gt; : <span class="type">IAsyncDisposable</span>
{
    <span class="type">ValueTask</span>&lt;<span class="reserved">bool</span>&gt; WaitForNextAsync();
    <span class="type">T</span> TryGetNext(<span class="reserved">out</span> <span class="reserved">bool</span> success);
}
</code></pre>
<p>というのも、パフォーマンス的には後者の方がだいぶ良いことがわかっています。
ただ、これは今回新たに追加する非同期版だけの話ではなくて、
既存の<code>IEnumerable&lt;T&gt;</code>についても同じ課題を抱えています。</p>
<p><a href="https://gist.github.com/ufcpp/0b9a8a8d4ea6b8eb6505ec0c624b65f8"><code>IEnumerable&lt;T&gt;</code>の方で軽く試してみた感じ</a>、かかるオーバーヘッドがほんとに倍くらい変わり得ます。
というのも、仮想メソッド呼び出しのコストはそこそこあるので、<code>MoveNext</code>/<code>Current</code>の2回の呼び出しに分かれているより、<code>TryGetNext</code>の1回で済む方が明らかに速くなります。</p>
<p>上記の<code>IAsyncEnumerator&lt;T&gt;</code>では、<code>WaitForNextAsync</code>と<code>TryGetNext</code>の2つのメソッドがありますが、<code>WaitForNextAsync</code>の方は呼び出しがかなり少なくなる想定なので、実質的にはこちらでも「<code>TryGetNext</code>の1個だけになるので速い」ということが言えます。</p>
<p>が、以下のようなデメリットもあります。</p>
<ul>
<li>
(<code>foreach</code>とかのコンパイラー生成に頼らず手動で)<code>WaitForNextAsync</code>と<code>TryGetNext</code>を使ったコードを書くのはかなり大変になる
<ul>
<li>.NET の仕様上、<code>bool TryGetNext(out T)</code> だと<a href="https://ufcpp.net/study/csharp/sp4_variance.html#covariance">共変</a>にできなくて、<code>T TryGetNext(out bool)</code>なのがキモい</li>
<li>特に、<a href="https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.zip"><code>Zip</code></a> みたいに複数のenumerableが絡むとかなり大変</li>
</ul>
</li>
<li>
同期版でもどの道同じ問題があるんだから、もしやるなら、同期版の方も含めて <code>foreach</code> の拡張を後から考えるべき
<ul>
<li>同期版が <code>MoveNext</code>/<code>Current</code> なのに非同期版だけ <code>TryGetNext</code> にするのは差が大きすぎる</li>
</ul>
</li>
</ul>
<p>結局、デメリットがきつすぎるということで、同期版と同じ<code>MoveNext</code>/<code>Current</code>型のインターフェイスにこだわりたいということになったようです。</p>
<h3>ValueTask 実装</h3>
<p>この<code>IAsyncEnumerable&lt;T&gt;</code>に関する検討を始めた当初は、<code>Task</code>に掛かるコストが特に懸念されていました。
が、<code>ValueTask</code>を使った最適化が進んだ結果、案外、<code>ValueTask&lt;bool&gt; MoveNextAsync()</code>にすれば低コストになりそうというのもわかってきた結果、上記の決断に至ったというのもありそうです。</p>
<p>そちらの検討も、corefx の方に issue が立っています。</p>
<ul>
<li><a href="https://github.com/dotnet/corefx/issues/32640">Proposal: Public APIs for C# 8 async streams #32640</a></li>
<li><a href="https://github.com/dotnet/corefx/issues/32665">Proposal: Implement IAsyncDisposable on various BCL types #32665</a></li>
<li><a href="https://github.com/dotnet/corefx/issues/32664">Proposal: ManualResetValueTaskSource{Logic} types #32664</a></li>
</ul>
<p><a href="https://ufcpp.net/blog/2018/3/pickuproslyn0323/">前にちょっと書きました</a>が、.NET Core 2.1 世代で、<code>ValueTask</code>が<code>Task</code>だけじゃなくて、<code>IValueTaskSource</code>インターフェイスを受け付けるようになりました。
このインターフェイスを実装した独自のクラスを作ることで、非同期処理に掛かるコストを下げれる場合があります
(作ったインスタンスをキャッシュ・再利用したり)。
非同期ストリーム(<code>await</code>と<code>yield</code>の混在)の実装はまさにその場合に該当していて、
<code>IValueTaskSource</code>を使ったコード生成をしようという流れになっています。</p>
<p>あと、<code>IValueTaskSource</code>自体は.NET Core 2.1世代(<a href="https://www.nuget.org/packages/System.Threading.Tasks.Extensions/4.5.1">NuGetパッケージ</a>を参照すればそれ以外でも利用可能)で追加されましたが、このインターフェイスをちゃんと実装するのはそれなりに面倒です
(いくつか、これを実装したクラスは現在もあるんですが、全部internalだったりします)。
そこで、汎用に使える<code>ManualResetValueTaskSource</code>という実装クラスも、これを機にpublicにしたいという話もついでに出ています。</p>
 ]]></description>
				<pubDate>Sun, 14 Oct 2018 11:57:17 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 9/26</title>
				<link>http://ufcpp.net/blog/2018/9/pickuproslyn0926/</link>
				<description><![CDATA[ <p>Design Notes 2件追加。</p>
<ul>
<li>
<a href="https://github.com/dotnet/csharplang/issues/1878">Added: LDM notes for 2018-09-10 #1878</a>
<ol>
<li>Nullability of constraints in inheritance and interface implementation</li>
<li>Static local functions</li>
</ol>
</li>
<li>
<a href="https://github.com/dotnet/csharplang/issues/1889">Added: LDM Notes for September 19th, 2018 #1889</a>
<ol>
<li>XML doc comment features</li>
<li>New <code>foreach</code> pattern using <code>Length</code> and indexer</li>
<li>Object initializers for <code>readonly</code> members</li>
<li><code>readonly</code> struct methods</li>
<li><code>params Span&lt;T&gt;</code></li>
<li>Nullable reference type features on <code>Nullable&lt;T&gt;</code></li>
</ol>
</li>
</ul>
<h2>オーバーライド時の nullability</h2>
<p>C# 8.0では、参照型に対して単に<code>T</code>と書くと非null、<code>T?</code>と書いた時だけnullを許容するようにしたいわけですが。
十数年の資産がある中、破壊的変更にならないように、属性を使ってnullチェックの有無を切り替えれるようになる予定です。
ちなみに、以下のような選択肢があります。</p>
<ul>
<li>null チェックをしない</li>
<li>
null チェックをする
<ul>
<li>チェックしていないクラスを参照した場合、<code>T</code> をnull許容扱いする</li>
<li>チェックしていないクラスを参照した場合、<code>T</code> を非null扱いする</li>
</ul>
</li>
</ul>
<p>で、基底クラスと派生クラスで選んだ選択肢が違う場合にどう扱うべきかという話題が。</p>
<h2>static local functions</h2>
<p><a href="https://ufcpp.net/study/csharp/cheatsheet/ap_ver7/#local-functions">ローカル関数</a>に対して、意図せずローカル変数をキャプチャしないように、「<code>static</code>修飾子を付けたらキャプチャ不可」という修飾をできるようにしようというのが静的ローカル関数(static local functions)。
これに対して以下のような話題。</p>
<ul>
<li>全部キャプチャするか、全部しないかだけ？キャプチャ リスト(「この変数だけキャプチャする」みたいな指定を明示的に行う機能)とかも用意する？ → しない。全部するかしないかの2択</li>
<li>ローカル関数への属性指定はできるようにする？ → する予定</li>
<li>ローカル関数内で、その外と同名の変数を使える(shadowing、外側のやつを隠す処理)ようにする？ → 考えているけど、staticなものだけに対してやるってのは嫌。既存の、普通のローカル関数でもできるようにしたいし、将来的にはラムダ式でも考えたい</li>
<li>ジェネリック関数内の静的ローカル関数でも、型引数はキャプチャする？ → Yes</li>
<li>「static ラムダ」はやる？ → やらない。ローカル関数と比べると短く使うことが多いし、式に埋め込んで書くものなので。</li>
</ul>
<h2>XML Doc コメント</h2>
<p><a href="https://ufcpp.net/study/csharp/sp_xmldoc.html">XML Doc コメント</a>に対して、いろいろタグを追加したいとかいう話もかなり積もっていたりします。</p>
<p>Doc コメントは、Visual Studio上でのツールチップ表示とか、<a href="https://docs.microsoft.com/ja-jp/dotnet/">Webページ</a>出力したりとか、ツールの対応が必要になります。
チーム外との折衝が必要なので、C# チーム的には常に腰が重いようで、ほんとに要望がたまりにたまっていたり。</p>
<p>で、今回のDesign Noteでようやく検討したみたいなんですが、「やるなら一気にやらないと」、「ツールのバージョンアップのタイミングでやりたいので、C# 的にもメジャー リリースのタイミングで対応したい」とのこと。
(といっても、マイルストーンは「X.0」。少なくとも8.0ではやらない模様。)</p>
<h2>foreach のインデックス アクセス最適化</h2>
<p>C# は昔から、配列に対して <code>foreach (var x in array)</code> と書くと、<code>for (var i = 0; i &lt; array.Length; i++) { var x = array[i] }</code> 相当のコードに最適化されます。
C# 7.2では、<a href="https://ufcpp.net/study/csharp/resource/span/"><code>Span&lt;T&gt;</code></a>に対しても同様の最適化を掛けるようにしました。</p>
<p>で、ここでの議題は、配列と<code>Span&lt;T&gt;</code>だけを特別扱いするのか、それとももっと汎用な仕組みを提供するのか。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/1424">Champion: <code>foreach</code> using <code>Length</code> and indexer #1424</a></li>
</ul>
<p>今回のDesign Meetingの結果、この提案の形ではやらないけども、この手の<code>foreach</code>の最適化自体は引き続き何かしら検討したいとのこと。</p>
<h2>readonly object initializer</h2>
<p><code>readonly</code>なフィールドに対しても<a href="https://ufcpp.net/study/csharp/oo_construct.html#member_initializer">オブジェクト初期子</a>を使えるようにしたいという提案がありまして。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/1684">Champion: readonly object initializers #1684</a></li>
</ul>
<p><a href="https://github.com/dotnet/csharplang/issues/39">Record 型の提案</a>とかなり被ってるところがあるし、今出ている提案の形で進む前に、もっと汎用な仕組みができないか検討したいとのこと。</p>
<h2>readonly functions on structs</h2>
<p><a href="https://ufcpp.net/study/csharp/resource/readonlyness/#avoid-copy">構造体なフィールドに<code>readonly</code>を付けると、かえってコピーが多発してパフォーマンスを落とす場合が</a>あったりします。
これを避けるためのreadonly structなんですが、
メソッド単位でも「このメソッド内ではフィールドの書き換えはしません」という修飾がしたいという提案があります。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/1710">Champion: Readonly members on structs #1710</a></li>
</ul>
<p>興味はあって、引き続き、今の提案の形で進めていくとのこと(今すぐにやるとは言っていない)。</p>
<h2>params Span</h2>
<p>今のC#は、<a href="https://ufcpp.net/study/csharp/sp_params.html">可変長引数</a>で使えるのは配列だけなわけですが。
<code>Span&lt;T&gt;</code>で可変長引数を受けたいという提案あり。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/1757">Champion &quot;params Span<T>&quot; #1757</a></li>
</ul>
<p>ただ、これを制限なく実装したければ、.NETランタイムのレベルでの修正が必要です。
(<a href="https://ufcpp.net/study/csharp/resource/span/#safe-stackalloc"><code>stackalloc</code></a>を使って可変長引数を渡したいものの、現状、ランタイムの制限で、<code>stackalloc</code>が使えるのは<a href="https://ufcpp.net/study/csharp/sp_unsafe.html#unmanaged-constraints"><code>unmanaged</code>な型</a>だけです。)</p>
<p>とりあえずC# 8.0目標で進めたいものの、ちょっとやるべきことが多い状態。</p>
<h2>nullable reference types 関連の機能を nullable value types にも</h2>
<ol>
<li>nullable value types → 要するに C# 2.0 からある<a href="https://ufcpp.net/study/csharp/sp2_nullable.html">null許容型</a>のこと</li>
<li>nullable reference types → C# 8.0 で入る予定の null チェック機構</li>
</ol>
<p>1の方は、<code>Nullable&lt;T&gt;</code>構造体を使った実装で、<code>T</code> と <code>T?</code> が実際に違う型で、<code>T?</code> から <code>T</code> を取り出すときには <code>Value</code>プロパティとか<code>GetValueOrDefault()</code>メソッドを介します。</p>
<p>それに対して2の方は、nullを追跡するためのアノテーションであって、<code>T</code> も <code>T?</code> もどちらも実行時には同じ型になっていて、コンパイラーのnullチェックが掛かるだけです。</p>
<p>まあ、nullable 絡みは途中のバージョンから追加するには結構厳しい機能で、
特に2の方はずっと無理だといわれ続けた結果8.0まで入らなかったくらいなので、
ちょっと無理があるのはしょうがなく、1と2で結構な差が生じています。</p>
<p>とはいえ、差を縮めるように1の方に手を入れることは考えてもよさげ。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/1865">Proposal: Adding nullable reference type features to nullable value types #1865</a></li>
</ul>
<p>要するに、<code>Nullable&lt;T&gt;</code>構造体に対して、例えば以下のようなものも検討したいという話。</p>
<ul>
<li>nullチェックをしないまま<code>Value</code>プロパティにアクセスさせない(したら警告)</li>
<li>nullチェック後であれば、<code>T?</code>のままで(<code>?.</code>でなく<code>.</code>で)<code>T</code>のメンバーにアクセスできるようにする</li>
<li>nullチェック後であれば、<code>T</code>を引数に取るメソッドに対して<code>T?</code>の変数でオーバーロード解決できるようにする</li>
</ul>
<p>いずれは実装したいみたいですけども、C# 8.0時点では「将来これを実装する段階になって破壊的変更にならないかだけ注意する」という扱い。</p>
 ]]></description>
				<pubDate>Wed, 26 Sep 2018 23:15:26 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 9/12: nullable参照型、target-typed new、Index 演算子など</title>
				<link>http://ufcpp.net/blog/2018/9/pickuproslyn0912/</link>
				<description><![CDATA[ <p>夏休みな時期を抜けたからか、7月末辺りからの Design Notes が何件かアップロードされました。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/1836">Added: LDM notes for August 20, 2018 #1836</a></li>
<li><a href="https://github.com/dotnet/csharplang/issues/1848">Added: LDM notes for August 22, 2018 #1848</a></li>
<li><a href="https://github.com/dotnet/csharplang/issues/1849">Added: LDM notes for September 5, 2018 #1849</a></li>
</ul>
<p>どれも、C# 8.0に向けて実装している機能の、割と細かい課題とそれに対してどうするかの決定についての話。</p>
<h2>! 演算子(nullチェックの抑止演算子)</h2>
<p>nullable(もしくは C# 7.X 以前のコード由来)な変数だけど、実際には null が来ないはずという時に使うのが<code>!</code>演算子。単に null チェック警告を出さないようにするもの。</p>
<h3>入れ子の場合</h3>
<p><a href="https://github.com/dotnet/roslyn/issues/29642">入れ子の場合</a> (<code>List&lt;string&gt;</code>から<code>List&lt;string?&gt;</code>に代入するときとか)のチェックをどうするかが議題に。</p>
<p>キャストと <code>!</code> 演算子は似た性質のものだけども、こういう場合、キャストなら警告を出して、<code>!</code>なら出さないべき。</p>
<h3>意味のない !</h3>
<p>元々非nullなものに <code>!</code> を付けたり、2重に<code>!!</code>とか付けた場合をどうするか。</p>
<p>コンパイラーとしては何もしない(警告を出さない)。チェックするとしたらIDEのリファクタリング機能として提供。</p>
<h2>nullable 型の dereference</h2>
<p>ここでいう dereference (脱参照。参照先の値を得る操作)は、<code>x</code> に対して <code>x.Substring(1)</code> とか、メンバー呼び出しすることを指してる。</p>
<p>以下のように、nullable なものに対して何らかのメソッドを呼んだ場合、
<code>x</code> が null だったら例外が出るはずで、だったら、呼び出して以降は null チェック済みと考えていいはず。</p>
<p><code>string? x = y;
var z = x.Substring(1);
...</code></p>
<p>実際そう扱うみたい。
正確には、<code>try</code>-<code>catch</code> があった場合、<code>try</code>句内のdereference以降は非 null として、
<code>catch</code> 句内では nullable として扱う。</p>
<h2>null コントラクト属性</h2>
<p><a href="https://ufcpp.net/blog/2018/5/pickuproslyn0520/">5/22 に書いた、属性でnullチェックの有無を指示する方式</a>のこと。</p>
<p>現在の候補一覧: <a href="https://github.com/dotnet/roslyn/issues/26761">Recognize annotations on methods that affect nullability analysis #26761</a></p>
<p>とりあえず今上がってる候補でプロトタイプ実装を初めて見ようみたいな空気。</p>
<h2>実行的チェック コードの挿入</h2>
<p>nullable 参照型は、現状、コンパイル時にだけ使うアノテーションになってる。
古いコンパイラーを使ったりでチェックをすり抜けたとしても、特に実行時チェックは働いてない。</p>
<p>それに対して、実行時チェックするコードを挿入するような機能もあってもいい？
例えば、<code>void M(string s!) { }</code> みたいに、引数の後ろに <code>!</code> を付けたら、引数の null チェック コードを挿入するとか。</p>
<p>とりあえず正式な提案ドキュメントを書いてみる。</p>
<h2><code>Nullable&lt;T&gt;</code></h2>
<p>nullable 参照型に対するフロー解析、一部は <code>Nullable&lt;T&gt;</code> 構造体の <code>.Value</code> にも使えるはず。</p>
<h2><code>class?</code> 制約</h2>
<p><code>void M&lt;T&gt;(T? t) where T : class?</code> は認める？</p>
<p><code>T?</code> は、<code>T</code> が非 null の時にだけ付けれるようにしたい。<code>T : class?</code> の時点で<code>T</code> が nullable なので、<code>T?</code> は認めない。</p>
<h2><code>List&lt;T&gt;.FirstOrDefault()</code></h2>
<p><code>List&lt;T&gt;</code> の <code>T</code> が制約なしの場合、<code>FirstOrDefault()</code> の戻り値はどうなるべき？</p>
<p><code>MaybeNull</code>扱いに。</p>
<h2>nullable参照型のgeneric制約</h2>
<pre class="source">
<code><span class="reserved">void</span> M&lt;<span class="type">T</span>, <span class="type">U</span>&gt;()
    <span class="reserved">where</span> T : <span class="reserved">class</span>
    <span class="reserved">where</span> U : T
{ }

<span class="reserved">interface</span> <span class="type">I</span> { }
<span class="reserved">void</span> M&lt;<span class="type">T</span>&gt;() <span class="reserved">where</span> T : I { }
</code></pre>
<p>みたいなのの、<code>T</code> は非 null？</p>
<p>非 null 扱いにする予定。</p>
<h2>target-typed new</h2>
<p>左辺からの型推論で、<a href="https://github.com/dotnet/csharplang/blob/master/proposals/target-typed-new.md"><code>new ()</code> だけで<code>new</code>できる</a>やつに関して。</p>
<h3>タプルに関して</h3>
<p>今、タプルに関しては <code>new (int, int)(0, 0)</code> みたいな書き方を認めてないけども。
<code>new (0, 0)</code> の場合は認めるべき？
7要素以上のタプルの場合、実際に作られるのは<code>new ValueTuple&lt;..., ValueTuple&lt;...&gt;&gt;</code> みたいな入れ子の<code>ValueTuple</code>だけども。</p>
<p><code>new (0, 0)</code> は認める予定。この場合はタプル構文(8要素以上も大丈夫。上記の入れ子の<code>ValueTuple</code>を構築)ではなく、単なる<code>ValueTuple</code>構造体のコンストラクター呼び出しという扱い(なので8要素以上の時には使えない/入れ子が必要)になる。</p>
<h3>throw new()</h3>
<p><code>throw new()</code> って書いた時、暗黙的に <code>new Exception()</code> 扱いすべき？</p>
<p>しないことに。</p>
<h3>ユーザー定義の比較、算術演算で new()</h3>
<p><code>x == new ()</code> みたいなの、認める。</p>
<h2>Index 演算子</h2>
<p><code>^1</code> って書き方で、「配列の末尾から1要素目」みたいな扱いにするための <code>^</code> 演算子のこと。</p>
<ul>
<li>構文的に、単項演算子扱い？ → そう</li>
<li>ユーザー定義演算子？ → なしで。今のところ int 以外のオーバーロードの需要をあんまり感じない</li>
<li>優先順位は？ → 単項演算子扱いになったので、他の単項演算子と同列</li>
<li><code>^^1</code> とかは認める？ → 単なる単項演算子扱い + int 以外認めない + <code>^</code> の結果は <code>Index</code> 型なので、<code>^^1</code> は必然的にエラーに</li>
<li><code>..</code> についても同様 → <code>..</code> の方は2項演算子ではなく、専用の構文扱いにする</li>
</ul>
<h2>Compiler intrinsics</h2>
<p><a href="https://ufcpp.net/blog/2018/8/pickuproslyn0822/">8/22に書いた、ldftn + calli のやつ</a>。</p>
<p>この ldftn + calli を出力できる仕組み自体は取り組みたい。ただ、8/22 時点の提案からはちょっと修正が必要そう。例えば:</p>
<ul>
<li>インスタンスに対して <code>&amp;instance.M</code> みたいな書き方は認めない</li>
<li><code>calli</code> は、<code>_calli_stdcall(args, f)</code>みたいな特殊キーワードでやる方がいいかも</li>
<li>呼び出し規約をどうするかは呼び出し側に書きたい</li>
</ul>
 ]]></description>
				<pubDate>Wed, 12 Sep 2018 18:30:11 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 8/22: ldftn + calli</title>
				<link>http://ufcpp.net/blog/2018/8/pickuproslyn0822/</link>
				<description><![CDATA[ <p>結構前から提案は出ていて、1週間くらい前にそこそこ仕様が固まったやつがあるんですが。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/191">Champion &quot;Compiler intrinsics (calli, ldftn, etc)&quot; #191</a></li>
</ul>
<p>C# で、デリゲートではなく、関数ポインターを生で扱うための仕組み。</p>
<p>C# のデリゲートも、そもそもの関数ポインターって概念も、どっちもちゃんと説明しようと思うと結構大変で、どうかこうか迷っていたものの…</p>
<h2>Bing.com runs on .NET Core 2.1</h2>
<p>そんな中、昨日話題になっていたブログ:</p>
<ul>
<li><a href="https://blogs.msdn.microsoft.com/dotnet/2018/08/20/bing-com-runs-on-net-core-2-1/">Bing.com runs on .NET Core 2.1!</a></li>
</ul>
<p><a href="https://www.bing.com/">Bing</a> が .NET Core 2.1 化したよという話なんですが、</p>
<ul>
<li>.NET Standard 1.x 時代は .NET Framework に対して足りてないものが多くて断念したけど、2.0 で行けた</li>
<li><a href="https://github.com/dotnet/coreclr/blob/master/Documentation/building/crossgen.md">crossgen</a> コマンドを使って、CI 時にネイティブ イメージを作ってデプロイしてる</li>
<li>.NET Core 2.1 のパフォーマンス改善の恩恵を受けて30%高速化</li>
</ul>
<p>という感じの内容。で、パフォーマンスに関しては、「.NET Core 2.1 ではこんな改善があった」リストも5個ほど紹介。</p>
<p>そのパフォーマンス改善の1つが「<code>ldftn</code> + <code>calli</code>」がらみ。これらの命令は、関数ポインターの読み込みと、その呼び出し命令です。
通常は<a href="https://ufcpp.net/study/csharp/sp_pinvoke.html">P/Invoke</a>でしか出てこないような命令で、
現状の C# では普通にやってこの命令が出力されるようなコードは書けません。</p>
<p>(なのに、Bing チームは動的コード生成(<a href="https://ufcpp.net/study/il/">IL</a> 出力)で<code>ldftn</code> + <code>calli</code>を使っていて、実際それで高速になっているとのこと。)</p>
<p>という話があったので、いい加減に上記の「<a href="https://github.com/dotnet/csharplang/issues/191">Compiler intrinsics (calli, ldftn, etc)</a>」の話を書こうかなと。</p>
<h2>デリゲートの中身</h2>
<p>とはいえ、まずは C# のデリゲートの中身がどうなっているかの話を。</p>
<p>例えば以下のようなデリゲート型を定義したとします。</p>
<pre class="source" title="">
<code><span class="reserved">delegate</span> <span class="reserved">int</span> <span class="type">A</span>(<span class="reserved">int</span> x, <span class="reserved">int</span> y);
</code></pre>
<p>内部的に、このデリゲートに対して、以下のようなクラスが生成されます。</p>
<pre class="source" title="">
<code><span class="comment">// 実際には MulticastDelegate 型から派生していて、MulticastDelegate 側に処理があったりする。</span>
<span class="comment">// C# では書けない処理が入ってて、InternalCall (.NET ランタイム内の特殊処理)になってる。</span>
<span class="comment">// 細かいところは端折ってるけど、やらないといけないことは概ねこんな感じ。</span>
<span class="reserved">class</span> <span class="type">A</span>
{
    <span class="comment">// obj.Method みたいに書いた時の obj を渡す</span>
    <span class="reserved">object</span> _target;

    <span class="comment">// obj.Method みたいに書いた時の Method に当たる情報を渡す</span>
    <span class="comment">// Method 本体が置かれてるメモリ上のアドレス</span>
    <span class="type">IntPtr</span> _functionPointer;

    <span class="comment">// multicast 用</span>
    <span class="type">A</span>[] _invocationList;

    <span class="reserved">public</span> <span class="reserved">virtual</span> <span class="reserved">int</span> Invoke(<span class="reserved">int</span> x, <span class="reserved">int</span> y)
    {
        <span class="comment">// _target をロード</span>
        <span class="comment">// x をロード</span>
        <span class="comment">// y をロード</span>
        <span class="comment">// _functionPointer をロード</span>
        <span class="comment">// calli 命令 (現状の C# では出力できない命令)</span>
        <span class="comment">// ret 命令</span>
    }

    <span class="comment">// single cast</span>
    <span class="reserved">public</span> A(<span class="reserved">object</span> target, <span class="type">IntPtr</span> functionPointer)
    {
        _target = target;
        _functionPointer = functionPointer;
    }

    <span class="comment">// multicast</span>
    <span class="reserved">public</span> A(<span class="type">A</span>[] invocationList)
    {
        _target = <span class="reserved">this</span>;
        <span class="comment">// _functionPointer に MulticastInvoke のアドレスを代入</span>
        _invocationList = invocationList;
    }

    <span class="reserved">public</span> <span class="reserved">static</span> <span class="type">A</span> Combine(<span class="type">A</span> a, <span class="type">A</span> b)
    {
        <span class="comment">// a, b がそれぞれ _invocationList を持ってたら1つの配列にまとめたりしてるかも</span>
        <span class="reserved">return</span> <span class="reserved">new</span> <span class="type">A</span>(<span class="reserved">new</span>[] { a, b });
    }

    <span class="reserved">private</span> <span class="reserved">int</span> MulticastInvoke(<span class="reserved">int</span> x, <span class="reserved">int</span> y)
    {
        <span class="reserved">var</span> ret = 0;
        <span class="reserved">foreach</span> (<span class="reserved">var</span> item <span class="reserved">in</span> _invocationList)
        {
            ret = item.Invoke(x, y);
        }
        <span class="comment">// 最後の1個しか戻り値が返らない</span>
        <span class="reserved">return</span> ret;
    }
}
</code></pre>
<p>C# では「他の言語でいう関数ポインターのようなもの」としてデリゲートを使うわけですが、
実は、.NET の IL 命令上は生の「関数ポインター」も持っています。
メソッドの中身に当たる IL コードがメモリ上のどこに配置されているか、その先頭アドレスを指すのが関数ポインター(function pointer)です。</p>
<p>で、デリゲートは以下のようなものになっています。</p>
<ul>
<li>インスタンスと関数ポインターのペアを持つ<em>クラス</em>になる</li>
<li>マルチキャスト用に、複数のデリゲートを1つにまとめる機能を持つ</li>
<li>デリゲート型インスタンス <code>d</code> に対して <code>d(x, y)</code> みたいな呼び出しをした場合、実際に呼ばれるのは <code>d.Invoke(x, y)</code> というメソッド(しかも<code>Invoke</code>はvirtual)</li>
</ul>
<p>これはそこそこ重たい仕組みになっていたりします。</p>
<ul>
<li>
常にクラスのインスタンスが <code>new</code> される
<ul>
<li>特に、静的メソッドの時は <code>_target</code> が <code>null</code> で、関数ポインター1個だけしか情報を持たないにも関わらず、無駄にクラスを作ってる</li>
<li>クラスなので、P/Invoke のときに GC されないように<a href="https://ufcpp.net/study/csharp/sp_unsafe.html#fixed">固定</a>が必要で面倒</li>
</ul>
</li>
<li>
マルチキャストのために結構特殊な処理が入ってる
<ul>
<li>マルチキャスト機能は<a href="https://ufcpp.net/study/csharp/sp_event.html">イベント</a>のためにあるものの、それ以外の用途でマルチキャストを必要とすることはない</li>
</ul>
</li>
</ul>
<p>なので、「マルチキャスト不要で静的なメソッドに対しては生の関数ポインターを使わせてほしい」という要望が出てきているようです。</p>
<h2>ldftn と calli</h2>
<p>ちなみに、<code>ldftn</code>. <code>calli</code> は、それぞれ関数ポインターをロードする命令と、その関数を呼び出す命令です。</p>
<p><code>ldftn</code> (load function)は、現状のC#でも、デリゲート型のインスタンスを作るときに使われています。
例えば以下のようなコードを書いた場合、</p>
<pre class="source" title="">
<code><span class="reserved">static</span> <span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> Main()
    {
        <span class="type">A</span> a = Sum;
    }

    <span class="reserved">static</span> <span class="reserved">int</span> Sum(<span class="reserved">int</span> x, <span class="reserved">int</span> y) =&gt; x + y;
    <span class="reserved">public</span> <span class="reserved">delegate</span> <span class="reserved">int</span> <span class="type">A</span>(<span class="reserved">int</span> x, <span class="reserved">int</span> y);
}
</code></pre>
<p>以下のような IL コードが生成されます。</p>
<pre class="source" title="">
<code><span class="reserved">ldnull</span> <span class="comment">// 静的メソッドなので target が null</span>
<span class="reserved">ldftn</span> int32 C::Sum(int32, int32) <span class="comment">// これが関数ポインター読み込み</span>
<span class="reserved">newobj</span> instance void A::.ctor(object, native int) <span class="comment">// デリゲート型のコンストラクターに関数ポインターを渡す</span>
</code></pre>
<p>一方、<code>calli</code> (call indirect)の方は前節のデリゲート型の<code>Invoke</code>メソッドの中や、P/Invokeで使われているくらいで、
大多数の C# コードからは生成されません。</p>
<h2>Compiler intrinsics</h2>
<p>で、<a href="https://github.com/dotnet/roslyn/issues/11475">当初案</a>はどうだったかというと、
「通常の C# コードからは絶対に出力されない<code>calli</code>, <code>ldftn</code>とかの命令を直接出力するための仕組みが欲しい」というものでした。</p>
<p>昔から、「C# コード内に IL コードを埋め込みたい」(いわゆるインライン アセンブラー)という要望もあったりはします。
でも、それは「C# コンパイラー チームが C# 以外の言語も保守しないといけない」、「C# コンパイラーが過度に複雑になる」などの理由で否定されています。</p>
<p>そこで出たのが Compiler intrinsics という提案。
特定のメソッド(例えば <code>CompilerIntrinsic</code> 属性が付いてるもの)の呼び出しがあったら、
それを<code>calli</code>, <code>ldftn</code>とかの命令に置き換えるというもの。
これであれば、C# の文法的にはただのメソッド呼び出しなので、コストは低く所望の動作が得られるだろうという感じです。</p>
<h2>関数ポインター intrinsics</h2>
<p>とはいえ、結局、ディスカッションの過程で例示された実用途は、
「マルチキャスト不要で静的なメソッドに対しては生の関数ポインターを使わせてほしい」だけでした。</p>
<p>(だったら、最初から、「マルチキャスト不要で静的なメソッド」専用の、light weight なデリゲート構文を追加する方がいいのではないかという話もあって、別途、<a href="https://github.com/dotnet/csharplang/blob/master/proposals/static-delegates.md">Static delegate</a>っていう提案も出ていたり。)</p>
<p>ということで、結局、Compiler intrinsics は<code>ldftn</code> + <code>calli</code>専用になりそうです。</p>
<ul>
<li><code>ldftn</code> の方は、単にメソッドの前に <code>&amp;</code> を付けることで関数ポインターを取れるようにする</li>
<li><code>calli</code> だけ、<code>CallIndirect</code>属性を使ったintrinsics (C# コンパイラーが特別扱いするメソッドを用意)にする</li>
</ul>
 ]]></description>
				<pubDate>Wed, 22 Aug 2018 13:34:37 +0900</pubDate>
			</item>
			<item>
				<title>例の事案(✓DO、X DO NOT の誤訳)、追記</title>
				<link>http://ufcpp.net/blog/2018/7/docsmistranslation2/</link>
				<description><![CDATA[ <p><a href="https://ufcpp.net/blog/2018/7/DocsMistranslation/">一昨日のあれ</a>、まだなんかやってんだ…</p>
<p>なんか、個人的にはこういうのはもっと機械的に処理されてほしく、
<a href="https://github.com/dotnet/docs.ja-jp/issues/118#issuecomment-407252836">言うこと言った</a>あとは、
なんか2chみたいな荒れ方し始めたから unsubscribe してたんですけども。</p>
<p>機械的に処理してるのが、冷たくあしらったり避難してるように見えてたら嫌だなぁということで、
ちょっとエモい感じの補足を。</p>
<h2>最初の1行コメントについて</h2>
<ul>
<li><a href="https://github.com/dotnet/docs.ja-jp/issues/118#issue-333923585">最初の1行コメント</a></li>
</ul>
<p>あー、これはひどい誤訳だわー。よくあるけど。</p>
<p>それじゃたぶん通じてないけど、ご報告ありがとうございます。あとはこっちで<a href="https://github.com/dotnet/docs.ja-jp/issues/118#issuecomment-407252836">処理</a>しておきます。</p>
<p>というつもりだったんだけど、「それじゃ通じない」のところだけを取られて、避難してるみたいに見えたみたいで、そこは本当に申し訳ない…</p>
<h2>誤解の原因になったやつについて</h2>
<ul>
<li><a href="https://github.com/dotnet/docs.ja-jp/issues/118#issuecomment-398942172">誤解の原因になったやつ</a></li>
</ul>
<p>これが誤解の原因になってるなぁ…</p>
<p>まあ、わかりみが深いけども。マイクロソフトのドキュメントにはいつも思うけどなんだよあの過剰翻訳。昔、F# を「F番号」とかに訳して炎上してたこともあるけど、そのうち C# も「嬰ハ」とかに訳すんじゃねぇだろうなぁ…</p>
<h2>マイクロソフトからの応答について</h2>
<ul>
<li><a href="https://github.com/dotnet/docs.ja-jp/issues/118#issuecomment-407202477">マイクロソフトからの応答</a></li>
</ul>
<p>テンプレのくせに長ぇ…</p>
<p>というか、どうせ機械的なワークフローでやってるんだから、もっとボットっぽいアカウントから返事を返せばいいのに。どうせ翻訳がらみは外部委託とかでしょ。</p>
<p>見せかけだけ高品質にやって、そのくせ中身はそんな品質高くないから問題を助長してるんじゃないかと。
中身相応の貧相なテンプレでいいのに。
こういうとこの品質はもっと落として、その分、翻訳自体に予算割いてもいいと思うんだけど。</p>
<p>今回のこれだって、ボットみたいなアカウントで「ヨク ワカリマセン デシタ」とか付けて Close してた方がまだ炎上しなかったんじゃないかと。</p>
<h2>👎 400件(当時)について</h2>
<p>👎 400件(当時)とか初めて見たわ… どこから出てきたんだよ、普段そんな人数いないじゃないか…</p>
<p>技術的な話だと全く出てこないのに、翻訳になると急に。
わかった、お前らの仕事は開発じゃなくて文章整形だな。
Excel 方眼紙のマス目をドット単位でそろえるのが主なお仕事の方々だな。
「1mm ずれてるから作り直し！」みたいな乗りで down vote しに来たな。</p>
<p>そういう仕事ばっかりしてるから、「日本の相手はコストかかりすぎるから撤退」とかやられる…</p>
 ]]></description>
				<pubDate>Thu, 26 Jul 2018 11:58:11 +0900</pubDate>
			</item>
			<item>
				<title>✓DO、X DO NOT の誤訳事案</title>
				<link>http://ufcpp.net/blog/2018/7/docsmistranslation/</link>
				<description><![CDATA[ <p>だいぶ炎上してる例のあれ</p>
<ul>
<li><a href="https://github.com/dotnet/docs.ja-jp/issues/118">doの意味が全体的に逆になっています。 #118</a></li>
</ul>
<p>対応ミスってるとはいえさすがにかわいそうなレベルでいいがかり付けられてる感じもするのでちょっと補足を。</p>
<h2>元々の問題</h2>
<p>マイクロソフトの機械翻訳がよくやらかすのはいつものことなんですが。
今回は何をやらかしたかというと、よくある</p>
<ul>
<li>✓DO: 〇〇してください</li>
<li>X DO NOT: 〇〇はしないでください</li>
</ul>
<p>みたいなやつを、DOもDO NOTもどっちも「しないで」と訳してしまっているという問題。
「しないで」も不自然だし、ましてDOの方は真逆の意味になっているという誤訳。</p>
<p>どうしてこうなる… みたいな気持ちはもちろんあるものの、こういう「普通の文章」になっていない部分の単語ってのは、機械翻訳では一番ミスを起こしがちな部分です。
たぶん、原文の時点で何らかのアノテーションでも付けておくとかしないと、今後も同様の誤訳は起こりまくるんじゃないかなぁと思います。</p>
<h2>フィードバック内容</h2>
<p>ということで、「間違ってますよ」とフィードバックが入っているわけですけども。
どう見ても正しく伝わっていない。</p>
<p>おそらく、対応している側も機械翻訳で見ているか、少なくとも日本語ネイティブの人ではなくて、英語ネイティブで日本語を読める人がトリアージュしていそうな感じ。</p>
<p>そこに、</p>
<ul>
<li>
フィードバックが「doが&quot;しないで&quot;と翻訳されています。」という短文
<ul>
<li>かつ、「翻訳されています」自体が問題と取れなくもない</li>
</ul>
</li>
<li><a href="https://github.com/dotnet/docs.ja-jp/issues/118">その下</a>に英語で、オフトピック的に、「DOはDOのままにしてくれ。変に翻訳しても伝わらない」という別フィードバックが混ざっちゃってる</li>
</ul>
<p>というフィードバックが入ったものだから、あちらの対応としては、後者のオフトピックの方だけを拾って、</p>
<ul>
<li>マイクロソフトでのガイドラインとしては、こういう「DO」みたいなやつも何らかの現地語に翻訳することになっている</li>
</ul>
<p>と返した(返せてるつもりになってる)という状態。</p>
<h2>炎上</h2>
<p>これに対して、炎上の仕方はまた違う勘違いが入っているようで。
要するに、「マイクロソフトのガイドラインでは DO は『しないで』と訳すことになっている」と勘違いした日本人が騒がいでいる状況。</p>
<p>で、その状況で結構RTされちゃったわけですけども、
よくある「RTが増えてくるとクソリプがわいてくる」状態(twitterに限った話じゃない)でして、
「どうして Google 翻訳を使わないんだ？」みたいなコメントを付けるやつまで出てきている状態。</p>
<p>さすがにこれは担当者がかわいそうすぎる…</p>
<h2>フィードバックの入れ方</h2>
<p>ja-jp ページのあまりのひどさになれてしまっている日本人からすると「1行説明でも、このひどさは見りゃわかるだろ」と思うかもしれませんけども。
大体通じません。
というか、英語ネイティブ同士の英語でのやり取りでも、「1行説明」の類は結構通じてない。</p>
<p>逆に、経験上は、<a href="https://github.com/dotnet/docs.ja-jp/issues/118#issuecomment-407252836">こんな感じでスクショぽとぺた</a>してやれば、大体すぐに対応してもらえます。</p>
<h2>正しく状況を理解したうえでも、それどうなの？</h2>
<p>まあ、こういう背景を理解したうえでもどうかと思う部分はあると思います。</p>
<h3>そもそも機械翻訳いやだ</h3>
<p>今もう、人力翻訳予算とか付かないので…</p>
<p>予算を割きたくなるくらい日本が景気良かったのはもう遠い昔の話でして。</p>
<h3>機械翻訳の品質が…</h3>
<p>今回みたいなのはちょっと特殊なケースだと思います。
前述のとおり、文章になっていなくて記号的に使われている DO みたいな単語は、機械翻訳的にはかなり難しい用法かと思われます。</p>
<h3>日本語訳はあてにしていないので英語の原文見せて</h3>
<p>見れるで。</p>
<p><img src="/media/1163/docstranslation.png" alt="原文表示機能" /></p>
<p>これも、MSDN時代からずっといろいろあったんですよね…</p>
<p>大まかにいうと、「英語が表示されると怖い。出さないで」派と「英語がないと読めない。出して」派のどっちもうるさくて困るそうで。</p>
<p>やっと、</p>
<ul>
<li>「英語で読む」ボタンが付いた</li>
<li>ポップアップのオンオフちゃんと切り替えれるようになった</li>
</ul>
<p>ってのが実現したんですよ…
活用しましょう。</p>
<h3>DO を訳すなよ</h3>
<p>これは本当にその通りで、ありとあらゆる方面から何度も何度も刺されているはずなんですけども。</p>
<p>1個本当にひどい話をすると、昔、Xbox インディーゲームズの審査を出そうと思うと、ゲーム画面中に「Game Over」とか「Start」とかの文字すら残してはいけない、1文字でもアルファベットが残っていると「翻訳できてないから許可しない」とか言われたことがあります。</p>
<p>その後、たたかれまくった結果Xboxでは「Game Over」が残ってても大丈夫になったそうです。
で、ほとぼり冷めた頃に今度は Windows ストアアプリの審査で全く同じことが起きました。
「News」とかが残ってると「翻訳できてない」と思われて審査に落ちるという。</p>
<p>要するに、日本人が「文字の混在」に慣れてて、簡単な英単語は読めるというか、日本社会には英字がデザインの一部として溶け込んでる、変に訳されたりカタカナになっているとむしろ日本語的に不自然という文化的背景なんて、日本人にしかわからないということです。</p>
<p>何回言っても伝わらないというか、その日本人の機微に対応しようと思うコストがかかりすぎるというか。マイクロソフトは断固として「現地語」にこだわり続けています。</p>
<p>まあ本当にひどいんですけども、それはそれで、別 issue です。
今回は混ざっちゃったことで勘違いによる炎上が起きたわけでして。</p>
 ]]></description>
				<pubDate>Tue, 24 Jul 2018 18:26:23 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 7/14: Roles, extension interfaces, and static interface members</title>
				<link>http://ufcpp.net/blog/2018/7/pickuproslyn0714/</link>
				<description><![CDATA[ <p>ここ数日、C# 8.0 (すぐ次のバージョン)を目標にした内容が多かったものの、今日のはもうちょっと先の話。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/1711">Exploration: Roles, extension interfaces and static interface members #1711</a></li>
</ul>
<p>タイトルに exploration って入っている通り、まだ「吟味・調査」的な段階のものです。
(特に、Roles の呼び名とかは結構不評。あくまで今現在そう呼んでるだけ。)</p>
<p>昔、<a href="https://github.com/dotnet/csharplang/issues/164">Shapes</a>とか<a href="https://github.com/MattWindsor91/roslyn/blob/master/concepts/docs/csconcepts.md">Concept</a>とか言う案もあったんですが、
この辺りと狙いは同じ。</p>
<p>その狙いを、<a href="https://github.com/dotnet/roslyn/issues/11159">extension everything</a>の延長として、以下の3つの要素の組み合わせで実現しようという話になります。</p>
<ul>
<li>Roles: 既存の型に対して、第三者がメンバーを追加するためのラッパー的なものを作る仕組み</li>
<li>Extensions: 拡張メソッドの延長で、プロパティとか演算子とか、何でも「拡張」できるようにするもの。これに、Roles を組み合わせて、拡張でインターフェイスも実装できるようにしたい</li>
<li>Static interface members: インターフェイスに、静的メソッドも含めるようにしたいというもの。単に(実装のある)静的メソッドを持つという話ではなく、静的な「抽象定義」(実装するクラス・構造体ごとに別の定義を持てる)を実現したい</li>
</ul>
<p>Roles と Extensions は似ているものの、Roles は「あるインスタンスをキャストして使う」みたいな感じで、Extensionsは現状の拡張メソッドと同様「一定のスコープ内で、特定の型のインスタンス全部を拡張する」みたいな感じ。</p>
<p>このアイディアは、.NET ランタイム自体の改修が必要になります。
(現状の .NET の型システムの上に、C# コンパイラーによる構文糖衣で作ろうとするとちょっと問題がありそう。)</p>
 ]]></description>
				<pubDate>Sat, 14 Jul 2018 16:44:31 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 7/11: Design Notes</title>
				<link>http://ufcpp.net/blog/2018/7/pickuproslyn0711-2/</link>
				<description><![CDATA[ <p>6月くらいからの C# Design Notes 追加。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/pull/1705">https://github.com/dotnet/csharplang/pull/1705</a></li>
</ul>
<p>いくつかは、提案文書の方が先に出てたので、先にブログを書いてあるものの原案みたいなもの。</p>
<ul>
<li><a href="/blog/2018/6/pickuproslyn0630/">Working with Data</a></li>
<li><a href="/blog/2018/7/pickuproslyn0711/">using patterns and declarations</a></li>
</ul>
<p>その他に関して。</p>
<h2>nullable reference types</h2>
<ul>
<li>
<a href="https://github.com/dotnet/csharplang/blob/master/meetings/2018/LDM-2018-05-30.md">May 30</a>
<ul>
<li>「アノテーションを何もつけていないと非 null 扱い」(unannotated reference types to be non-nullable; &quot;URTANN&quot;)に関して</li>
<li>
URTANN 動作の opt-out ができないと、C# 7.X 以前のコードが警告だらけになる
<ul>
<li>現状の Roslyn にそのまま適用すると2000個くらいの警告が出るらしい</li>
</ul>
</li>
<li>デフォルト挙動は URTANN(true) にしたい</li>
<li>細かい粒度(特定のファイルだけ、特定のクラスだけ、特定のメソッドだけ)で URTANN の opt-in/out 切り替えができるようにしたい</li>
<li>切り替えはたぶん属性でやる。<code>NonNullTypesAttribute(bool)</code></li>
</ul>
</li>
<li>
<a href="https://github.com/dotnet/csharplang/blob/master/meetings/2018/LDM-2018-06-04.md">Jun 4</a>
<ul>
<li>ラムダ式にキャプチャした変数の null フロー解析、ちょっと特殊になりそう</li>
</ul>
</li>
</ul>
<h2>式ツリー</h2>
<ul>
<li><a href="https://github.com/dotnet/csharplang/blob/master/meetings/2018/LDM-2018-06-06.md">Jun 6</a></li>
</ul>
<p>式ツリーで使える文法を増やしたいという話は前々からあるものの、やっと検討が始まったっぽい。</p>
<p>前半は需要のあるシナリオについて。Big data に対するクエリを式ツリーで送りたいとか、機械学習ライブラリ方面で<a href="https://ja.wikipedia.org/wiki/%E8%87%AA%E5%8B%95%E5%BE%AE%E5%88%86">自動微分</a>とか GPU 上でのコード実行したいとか。</p>
<p>後半は実現方法に関して。</p>
<ul>
<li>
既存の、Entity Frameworkとかはノードを追加されても使えない。どのノードが使えるかはライブラリごとに異なる。どう制限するか
<ul>
<li>案1: <a href="https://ufcpp.net/study/csharp/sp5_async.html#task-like">非同期メソッドでやってるみたいに</a>、builder を介して任意の型でツリー構築できるようにする</li>
<li>案2: アナライザーを使って制限する</li>
</ul>
</li>
<li>
reduction (await をその展開結果である AsyncStateMachine の行動に変換したりとか、そういうノード変形)はやるかどうか
<ul>
<li>あまりしない方がよさそう</li>
</ul>
</li>
<li>C# の最新機能全部に、式ツリーが常に100%追従しようとは思っていない</li>
</ul>
<p>とか言う感じ。あと、一応、プロトタイプ実装あり。</p>
<ul>
<li><a href="https://github.com/bartdesmet/ExpressionFutures/">https://github.com/bartdesmet/ExpressionFutures/</a></li>
</ul>
<h2>Target-typed new</h2>
<ul>
<li>
<a href="https://github.com/dotnet/csharplang/blob/master/meetings/2018/LDM-2018-06-25.md">Jun 25</a>
<ul>
<li>オーバーロード解決には寄与させないつもり</li>
<li><code>S? s = new ();</code> みたいに書くとき、<code>new S()</code> の意味にする(<code>new Nullable&lt;S&gt;()</code>、つまり、null の意味にはしない)</li>
<li><code>new ()</code> は型を持たない。<code>var x = new ();</code> みたいなのは型が確定しなくてエラー</li>
<li><code>new ()</code> とか <code>new {}</code> とかは認めるけど、<code>new</code> 単体は認めないつもり</li>
<li><code>dynamic</code>型がターゲットの<code>new ()</code>も認めない</li>
</ul>
</li>
</ul>
<p>オーバーロードに関しては、例えば以下のような話。</p>
<pre class="source" title="">
<code><span class="reserved">struct</span> <span class="type">S1</span> { <span class="reserved">public</span> <span class="reserved">int</span> x; }
<span class="reserved">struct</span> <span class="type">S2</span> { }

<span class="reserved">void</span> M(S1 s1) { }
<span class="reserved">void</span> M(S2 s2) { }

<span class="reserved">void</span> X()
{
    M(<span class="reserved">new</span>() { x = 43 });
    <span class="comment">//↑ x を持ってるのは S1 だけだから、S1 と推論できる</span>
    <span class="comment">// でも、それをやっちゃうと、S2 に後から x を追加することで破壊的変更が起きちゃう</span>
    <span class="comment">// なので、こういうオーバーロード解決はやらない</span>
}
</code></pre>
<h2>null 条件演算</h2>
<ul>
<li><a href="https://github.com/dotnet/csharplang/blob/master/meetings/2018/LDM-2018-07-16.md">Jul 16</a></li>
</ul>
<p><code>?.</code> とか <code>??</code> 系統の機能をいくつか追加。</p>
<ul>
<li><code>x ??= y</code> で、<code>x = x ?? y;</code></li>
<li><code>await? t</code> で、<code>if (t != null) await t;</code></li>
<li>ポインターに対しても<code>p?[a]</code>、<code>p?-&gt;a</code>、<code>p ?? q</code></li>
</ul>
 ]]></description>
				<pubDate>Wed, 11 Jul 2018 23:26:30 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 7/11: using patterns and declarations</title>
				<link>http://ufcpp.net/blog/2018/7/pickuproslyn0711/</link>
				<description><![CDATA[ <p>C# 8.0での追加目標で、<a href="/study/csharp/oo_dispose.html#using"><code>using</code> ステートメント</a>絡みの機能が2つほど。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/pull/1703">Using patterns and declarations #1703</a></li>
</ul>
<p>1つは、パターン ベース(<code>IDiposable</code>インターフェイスの実装不要)で<code>using</code>が使えるようになるというもの。
もう1つは、変数宣言・変数のスコープに紐づいた<code>using</code>。</p>
<h2>パターン ベースで using</h2>
<p>C# の言語機能のいくつかは、単にメソッド呼び出しに変換するだけのシンタックスシュガーが多いです。
<code>foreach</code>、<code>await</code>、クエリ式など、いろんなものが「この名前のメソッドさえ実装していればどんな型でも使える」という類の構文になっています。
ですが、微妙にものによって挙動が違ったり。</p>
<ul>
<li>
拡張メソッドでもいい
<ul>
<li><a href="/study/csharp/sp3_stdquery.html">クエリ式</a></li>
<li><a href="/study/csharp/sp5_awaitable.html#awaiter"><code>await</code></a></li>
<li><a href="/study/csharp/datatype/deconstruction/#arbitrary-types">分解</a></li>
<li><a href="/study/csharp/sp3_lambda.html?key=collectioninit#collectioninit">コレクション初期化子</a> (ただし、<a href="/study/csharp/ap_ver6.html#add-extensions">C# 6.0 以降</a>)</li>
</ul>
</li>
<li>
インスタンス メソッドでないとダメ
<ul>
<li><a href="/study/csharp/sp_foreach.html#ownmaking"><code>foreach</code></a></li>
<li><a href="/study/csharp/sp_unsafe.html#custom-fixed"><code>fixed</code></a></li>
</ul>
</li>
<li>
インターフェイスの実装が必須
<ul>
<li><a href="/study/csharp/oo_dispose.html#using"><code>using</code></a></li>
</ul>
</li>
</ul>
<p>ということで、インターフェイスの実装が必須で使い勝手が悪かった<code>using</code>ステートメントですが、C# 8.0で、これを「<code>Dispose()</code>と言うメソッドさえ持っていれば何でも使える」というものに変えるようです。</p>
<p>というのも、<a href="/study/csharp/resource/refstruct/">ref構造体</a>がインターフェイスを実装できないものの、ref構造体で<code>using</code>を使いたい場面が非常に多い状況になっているので。
パターン ベースな<code>using</code>の需要がかなり上がっているみたいです。</p>
<p>ちなみに、これは<code>using</code>に限った話ではなく、上記のような挙動の差をなくしたいという話でもあります。
C# 8.0では他にも「<a href="https://github.com/dotnet/csharplang/blob/master/proposals/async-streams.md">非同期 <code>foreach</code></a>」みたいな話もあって、これと関連して、上記の「<code>foreach</code>が拡張メソッドの<code>GetEnumerator</code>を受け付けないのは変じゃない？」みたいなことも言われています。こちらもセット。</p>
<h2>using 変数宣言</h2>
<p>これまで、<code>using</code>を使うときには以下のような書き方でした。</p>
<pre class="source" title="">
<code><span class="reserved">using</span> (<span class="reserved">var</span> d = someDisposable)
{
    <span class="comment">// このスコープ内を抜けたら Dispose</span>
}
</code></pre>
<p>で、C# 8.0 では、以下のような書き方を認めようという話です。</p>
<pre class="source" title="">
<code>{
    <span class="comment">// 変数宣言と同時に、その変数を using</span>
    <span class="reserved">using</span> <span class="reserved">var</span> d = someDisposable;

    <span class="comment">// 変数のスコープを抜けたら Dispose</span>
}
</code></pre>
<p>C# の言語機能としては「<code>using</code>修飾付きの変数宣言」みたいになるようです。</p>
<p>この機能を追加する主な動機は、以下のような「<code>using</code>の入れ子」の解消です。</p>
<pre class="source" title="">
<code><span class="comment">// 同寿命のリソースを何個も使うとき、こんな感じになる</span>
<span class="reserved">using</span> (<span class="reserved">var</span> a = someDisposable)
<span class="reserved">using</span> (<span class="reserved">var</span> b = anotherDisposable)
<span class="reserved">using</span> (<span class="reserved">var</span> c = oneMoreDisposable)
{
    <span class="comment">// ここを抜けたら Dispose</span>
}

<span class="comment">// それをこう変えたい</span>
<span class="reserved">using</span> <span class="reserved">var</span> a = someDisposable;
<span class="reserved">using</span> <span class="reserved">var</span> b = anotherDisposable;
<span class="reserved">using</span> <span class="reserved">var</span> c = oneMoreDisposable;

<span class="comment">// メソッドを抜けたら Dispose</span>
</code></pre>
<p>これも、<code>fixed</code>ステートメントにも同じことが言えそう(同寿命で重ねることが結構ある)ということで、
同じような「<code>fixed</code>変数宣言」も考えているそうです(こちらはたぶんC# 8.0よりも将来の話)。</p>
 ]]></description>
				<pubDate>Wed, 11 Jul 2018 17:53:34 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 6/30: Working with Data</title>
				<link>http://ufcpp.net/blog/2018/6/pickuproslyn0630/</link>
				<description><![CDATA[ <p>C# 6.0 くらいの頃から脈々とずっとテーマに挙がっている「データ」関連の機能で、2つほど提案が挙がっています。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/pull/1667">
Proposal: &quot;data&quot; classes for C# #1667</a></li>
<li><a href="https://github.com/dotnet/csharplang/pull/1673">Proposal: Named tuples #1673</a></li>
</ul>
<p>新しいものが出たというよりは、プライマリ コンストラクターとかレコード型とか言われていたものを、コンパクトに分割した感じのものです。</p>
<p>長らく先延ばしになっていた機能ですが、C# 8.0 でいよいよ実装しようといことで、
詳細を詰めた結果2つに分かれたという感じだと思われます。</p>
<h2>data クラス/構造体</h2>
<p>1つ目は、data クラス/構造体 と言われるもので、</p>
<ul>
<li><code>class</code>/<code>struct</code> の前に <code>data</code> 修飾子を付ける</li>
<li>
public なフィールド、自動プロパティから、以下のものを自動生成
<ul>
<li><code>GetHashCode</code></li>
<li><code>Equals</code></li>
<li><code>==</code>, <code>!=</code> 演算子</li>
<li><code>ToString</code></li>
</ul>
</li>
</ul>
<p>というようなもの。</p>
<p>印象としては、<a href="/study/csharp/oo_class.html#anonymous">匿名型</a>の延長で、ちゃんとしたクラス・構造体に昇格させたいとい時に使うものな感じです。</p>
<pre class="source" title="data クラス">
<code><span class="reserved">using</span> System;

<span class="comment">// class に data 修飾子を付ける</span>
<span class="reserved"><em>data</em> class</span> <span class="type">Point</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> X { <span class="reserved">get</span>; }
    <span class="reserved">public</span> <span class="reserved">int</span> Y { <span class="reserved">get</span>; }
}

<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> Main()
    {
        <span class="comment">// 匿名型</span>
        <span class="reserved">var</span> p1 = <span class="reserved">new</span> { X = 1, Y = 2 };

        <span class="comment">// data クラス</span>
        <span class="reserved">var</span> p2 = <span class="reserved">new</span> <span class="type">Point</span> { X = 1, Y = 2 };

        <span class="comment">// 比較とかが自動的に作られる</span>
        <span class="type">Console</span>.WriteLine(p2 == <span class="reserved">new</span> <span class="type">Point</span> { X = 1, Y = 2 });
    }
}
</code></pre>
<h3>対象となるフィールド/プロパティ</h3>
<p>基本的には、比較やハッシュ値計算に使われるのは public なフィールドと自動プロパティだけです。
private なものや、自動実装でないものは除外されます。
(「データから計算で得られる値を、1回だけ計算してキャッシュしておきたい」みたいなとき、そのキャッシュを比較・ハッシュ値計算に使うことはあまりないので。)</p>
<p>ただ、自動実装でないプロパティでも、<code>DataMember</code>属性を付ければ、比較・ハッシュ値計算の対象にできます。</p>
<h3>immutable データに対してオブジェクト初期化子</h3>
<p>また、data クラス/構造体では、immutable なデータ(get-only なプロパティ)に対してもオブジェクト初期化子が使えます。
(これまでの C# だと、匿名型で特別扱いで認められてた。通常のクラスだと、オブジェクト初期化子が使えるのは書き換え可能なフィールド/プロパティだけ。)</p>
<p>例えば上記の例では、<code>X</code>, <code>Y</code> の2つのプロパティは get-only ですが、<code>new Point { X = 1, Y = 2 }</code> という書き方が許されます。
これを認めるために、get-only プロパティを、実際には以下のようにコード生成する予定だそうです。</p>
<pre class="source" title="get-only プロパティでオブジェクト初期化子を使うためのトリック">
<code><span class="reserved">class</span> <span class="type">Point</span>
{
    <span class="comment">// &lt;&gt; から始まる名前は、通常の C# コードでは書けない。</span>
    <span class="comment">// 通常は使えない名前を使うことで、C# コードからは読み書きさせない。</span>
    <span class="comment">// (コンパイラー生成のコードからだけ読み書きする。)</span>
    <span class="reserved">private</span> <span class="reserved">int</span> &lt;&gt;X;
    <span class="reserved">public</span> <span class="reserved">int</span> X =&gt; &lt;&gt;X;

    <span class="reserved">private</span> <span class="reserved">int</span> &lt;&gt;Y;
    <span class="reserved">public</span> <span class="reserved">int</span> Y =&gt; &lt;&gt;Y;

    <span class="comment">// 以下、Equals や GetHashCode なども生成</span>
}

<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> Main()
    {
        <span class="comment">// コンパイラーはオブジェクト初期化子を以下のように展開</span>
        <span class="reserved">var</span> p2 = <span class="reserved">new</span> <span class="type">Point</span>();
        p2.&lt;&gt;X = 1;
        p2.&lt;&gt;Y = 2;
    }
}
</code></pre>
<h2>名前付きタプル</h2>
<p>一方で、<a href="/study/csharp/datatype/tuples/">タプル</a>の延長で、ちゃんとしたクラス・構造体に昇格させるみたいな構文も追加。名前付きタプルと呼ぶそうです。</p>
<p>以下のように、クラス名に続けてタプルみたいなものを書くことで、タプルに名前が付きます。</p>
<pre class="source" title="名前付きタプル">
<code><span class="reserved">using</span> System;

<span class="comment">// 型名の後ろにタプル的なものを書く</span>
<span class="reserved">class</span> <span class="type">Point</span>(<span class="reserved">int</span> X, <span class="reserved">int</span> Y);

<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> Main()
    {
        <span class="comment">// タプル</span>
        <span class="reserved">var</span> p1 = (X: 1, Y: 2);

        <span class="comment">// 名前付きタプル</span>
        <span class="reserved">var</span> p2 = <span class="reserved">new</span> Point(1, 2);
        <span class="type">Console</span>.WriteLine(p2.X);
        <span class="type">Console</span>.WriteLine(p2.Y);
    }
}
</code></pre>
<p>見ての通り、コンストラクターとプロパティが生成されます。
また、タプルと同様、比較、ハッシュ値計算や、<code>Deconstruct</code> メソッドなども生成されるそうです。</p>
<p>この例だと <code>class Point(int X, int Y);</code> だけ書きましたが、クラスの中身も持てるそうです。
(昔あったレコード型の提案に結構近い。)</p>
<p>また、<code>class Point(int, int);</code> と言うように、メンバー名は省略できます。
この場合、タプルと同様、<code>Item1</code>, <code>Item2</code> というような番号付きのメンバーが生成されます。</p>
 ]]></description>
				<pubDate>Sat, 30 Jun 2018 19:38:40 +0900</pubDate>
			</item>
			<item>
				<title>.NET Core 2.1 正式リリース</title>
				<link>http://ufcpp.net/blog/2018/5/netcore21/</link>
				<description><![CDATA[ <p>.NET Core 2.1 が正式リリースされたみたいですね。</p>
<ul>
<li><a href="https://blogs.msdn.microsoft.com/dotnet/2018/05/30/announcing-net-core-2-1/">Announcing .NET Core 2.1</a></li>
</ul>
<p>内部的にかなりパフォーマンス改善してるとか、
<a href="http://ufcpp.net/blog/2018/2/dotnettoolspkgs/">.NET Global Tools</a>が使えるとか、
<a href="https://github.com/dotnet/sourcelink">SourceLink</a>に対応したらしいとかいろいろありますが。
C# 的に直接的に関わってくるのは<a href="/study/csharp/resource/span/"><code>Span&lt;T&gt;</code></a>構造体のリリースでしょうか。</p>
<p><a href="/study/csharp/cheatsheet/ap_ver7_2/">C# 7.2</a>で、<code>Span&lt;T&gt;</code>がらみの言語機能がいろいろ入っているんですが、
肝心の<code>Span&lt;T&gt;</code>自体がプレビュー状態でした。
(<a href="https://github.com/dotnet/corefx">.NET の基本ライブラリ</a>自体がC#で書かれてる部分が多いので、
先に言語機能が入ってくれないと<code>Span&lt;T&gt;</code>周りの最適化がやりにくいので。)
それが今日、正式リリースとなりました。</p>
<p><a href="/study/csharp/resource/span/"><code>Span&lt;T&gt;</code></a>構造体は以下の環境で使えます。</p>
<ul>
<li>.NET Core 2.1 では標準で使える</li>
<li>
<a href="https://www.nuget.org/packages/System.Memory/">System.Memory パッケージ</a> を参照すれば、古い .NET ランタイム上でも使える
<ul>
<li>.NET Standard 1.1、.NET Framework 4.5とかにも対応</li>
</ul>
</li>
<li>.NET Core 2.1 上で実行すると特にパフォーマンスがいい(<a href="http://ufcpp.net/study/csharp/resource/span/#fast-span">fast Span</a>)</li>
</ul>
 ]]></description>
				<pubDate>Thu, 31 May 2018 14:43:45 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 5/24</title>
				<link>http://ufcpp.net/blog/2018/5/pickuproslyn0524/</link>
				<description><![CDATA[ <p>珍しくまめに議事録の投稿が。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/blob/master/meetings/2018/LDM-2018-05-21.md">C# Language Design Notes for May 21. 2018</a></li>
</ul>
<p>今回はこの21日の Design Meeting 議事録1件のみの追加。</p>
<p>さらっと内容紹介:</p>
<h2>target typed new</h2>
<p>要はこんなやつ。</p>
<pre class="source" title="">
<code><span class="comment">// 今まで</span>
M(<span class="reserved">new</span> <span class="type">A</span>(1));

<span class="comment">// 提案: 左辺から推測できる場合、型名を省略可能</span>
M(<span class="reserved">new</span> (1));
</code></pre>
<p>プロトタイプ実装のプルリクが出ていて、いつでも通せる状態ではあるんですが、
ちょっと懸念事項が出てきたとのこと。</p>
<p>今回懸念しているのは以下のような状況。</p>
<pre class="source" title="">
<code><span class="reserved">class</span> <span class="type">A</span>
{
    <span class="reserved">public</span> A(<span class="reserved">int</span> value) { }
}

<span class="reserved">class</span> <span class="type">B</span> { }

<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> M(<span class="type">A</span> x) { }
    <span class="reserved">static</span> <span class="reserved">void</span> M(<span class="type">B</span> x) { }

    <span class="reserved">static</span> <span class="reserved">void</span> Main()
    {
        <span class="comment">// 今は、1引数コンストラクターを持っているのが A だけなので、A で推論すべき？</span>
        <span class="comment">// その場合、後から B に1引数コンストラクターを足してしまった場合どうあるべき？</span>
        M(<span class="reserved">new</span> (1));
    }
}
</code></pre>
<p>厳しくいくなら、「target typed new が使えるのは初期化子でのみ」みたいな制限にしてしまうという案もあり。
なんせ、「フィールドに対して <code>var</code> を使えないのがしんどい。<code>Dictionary&lt;SomeLongNamedType, AnotherLongNamedType&gt;</code> みたいな長い型を2度書きたくない」というのが最大の要件なので、「初期化子のみ」であってもこの最大要件だけは満たせる。</p>
<p>とはいえ、おそらく、一度はそれで実装したとしても結局後から制限を緩めたくなるだろうと思われる。
なので、まじめにこの「後からコンストラクターを足す」問題に向き合わないといけない。</p>
<p>似たものでいうと、「<a href="http://ufcpp.net/study/csharp/sp_ref.html#out-var"><code>out var</code></a>を使った場合、オーバーロード解決しない」(引数の数が同じ複数のオーバーロードがある場合、<code>var</code>ではなく、具体的な型が必須)ってなっているので、今後 target typed new を足す際にも同様の制限を掛けるのがいいかもしれない。</p>
<h2>return/break/continue 式</h2>
<p><code>condition ? value : throw new Exception()</code> みたいに、<code>throw</code>が式にできたんだから、<code>return</code>、<code>break</code>、<code>continue</code>も式の中で使いたいという話。</p>
<p>こちらも、プロトタイプ実装のプルリクが既に(それもコミュニティ貢献で)出ていて、
やろうと思えばいつでも通せる状態。</p>
<p>が、懸念になっているのが <code>return</code> はどこまでさかのぼって <code>return</code> されるべきか。
(<code>throw</code>の場合はどの道「<code>catch</code>があるところまで上に伝搬」なので問題にならないが、
<code>return</code> は1段階だけ戻るものなので。)</p>
<p>例えば、「ブロック式」みたいなのも将来入れる可能性はあって、
以下のような書き方ができるようになったとして、この <code>return</code> はブロックを抜ける(<code>x</code> に 1 もしくは 2 が入る)ために使われることになる。</p>
<pre class="source" title="">
<code><span class="reserved">var</span> x = { <span class="reserved">if</span> (condition) <span class="reserved">return</span> 1; <span class="reserved">else</span> <span class="reserved">return</span> 2; };
</code></pre>
<p>今、「<code>return</code>式」を入れたとして、こういう将来考えうる文法との整合性がちゃんと保てるかという心配が強く、「現時点では保留」としておいた方がよさそう。</p>
<h2>非同期 stream</h2>
<ul>
<li>生成: <code>await</code> と <code>yield</code> を混在させれるようにしたい</li>
<li>消費: <code>foreach await (...)</code> で列挙できるようにしたい</li>
</ul>
<h3>非同期 foreach はパターン ベースであるべきか</h3>
<p>通常の <code>foreach</code> は、所定のパターンさえ満たせば使えます(<code>GetEnumerator</code>, <code>MoveNext</code>, <code>Current</code> などを持っていれば、インターフェイスなどは求めない)。</p>
<p>非同期 <code>foreach</code> も同様にすべき。する予定。</p>
<h3>拡張メソッドで非同期 foreach</h3>
<p>現状、通常の <code>foreach</code> では、<code>GetEnumerator</code> はインスタンス メソッドでないとダメ。
(初期設計がそうだったのと、そこまで拡張メソッドにしたいという要望が強くなかったため。)</p>
<p>非同期 <code>foreach</code> では拡張メソッドも認めたいし、
既存の通常 <code>foreach</code> でも拡張メソッドを認められるよう検討したい。</p>
<h3>ラムダ式中で await と yield の混在</h3>
<p>現状の C# では、ラムダ式中で <code>yield</code> を使えない。
(「メソッド中に1つでも<code>yield</code>があれば<a href="http://ufcpp.net/study/csharp/sp2_iterator.html">イテレーター</a>扱い」っていう仕様と相性が良くない。入れ子のせいで誤判定が怖い。)
ただし、「優先度低」で捨て置かれてるけども、害悪だとまでは思ってない。</p>
<p>非同期版(<code>await</code>と<code>yield</code>の混在)もしばらく考えないでおきたい
(やるなら、同期版(ラムダ式中での<code>yield</code>利用)と同時に考えたい)。</p>
<h3>イテレーター化する条件</h3>
<p>今、</p>
<ul>
<li>非同期メソッドは、メソッドに <code>async</code> 修飾子が必須</li>
<li>イテレーターは、特に修飾子は必要なく、メソッド中に <code>yield</code> があるかどうかで判定</li>
</ul>
<p>と、ちょっと一貫性が欠けた状態にはなっている。
(イテレーターのこの仕様は今となってはあまり良くないかもしれないけども、
破壊的変更や、「同じことを別の文法でもできる」状態にしてまでやることではない。)</p>
<p><code>await</code>と<code>yield</code>を混在させるにあたってはどうするべきか。
現状、今の延長で行く予定。
すなわち、メソッドに<code>async</code>修飾子が付いていて、かつ、メソッド中に<code>yield</code>が1つでもあれば非同期 stream 扱い。</p>
<h3>非同期 stream の戻り値はパターン ベースであるべきか</h3>
<p>非同期メソッドは、当初は戻り値の型が <code>Task</code>/<code>Task&lt;T&gt;</code> 限定だった。
C# 7.0 移行は、所定のパターンを満たしていれば任意の型を使えるようになった。</p>
<p>一方で、イテレーターはいまだに <code>IEnumerator</code>/<code>IEnumerable</code>/<code>IEnumerator&lt;T&gt;</code>/<code>IEnumerable&lt;T&gt;</code>  限定。</p>
<p>非同期 stream では最初から所定のパターンを満たした任意の型を使えるようにしたい。
一緒に、イテレーターの戻り値もパターン ベースにできるように検討したい。</p>
<h3>dynamic に対して foeach await</h3>
<p><code>dynamic x</code> に対して <code>foreach (var i in x)</code> は使えるけども、非同期版の場合にも同様に dynamic を認めるべきか。</p>
<p>やらないつもり。</p>
 ]]></description>
				<pubDate>Thu, 24 May 2018 17:21:59 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 5/20: 5月の Design Notes</title>
				<link>http://ufcpp.net/blog/2018/5/pickuproslyn0520/</link>
				<description><![CDATA[ <p>5月の Language Design Notes が2件ほど追加されました。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/blob/master/meetings/2018/LDM-2018-05-02.md">C# Language Design Notes for May 2, 2018</a></li>
<li><a href="https://github.com/dotnet/csharplang/blob/master/meetings/2018/LDM-2018-05-14.md">C# Language Design Notes for May 14, 2018</a></li>
</ul>
<p>さらっと抜粋。</p>
<h2>switch 式</h2>
<p><a href="http://ufcpp.net/blog/2018/5/cs80preview/">先週書いた</a>通り、現状のプレビュー版では、以下のような文法で「式」としてswitchを書けます。</p>
<pre class="source" title="">
<code><span class="reserved">var</span> s = x <span class="reserved">switch</span>
{
    1 =&gt; <span class="string">"one"</span>,
    2 =&gt; <span class="string">"two"</span>,
    3 =&gt; <span class="string">"three"</span>,
    _ =&gt; <span class="reserved">throw</span> <span class="reserved">new</span> <span class="type">IndexOutOfRangeException</span>()
};
</code></pre>
<p>今のところ、<code>=&gt;</code> で実装されているんですが、これに関して:</p>
<ul>
<li><code>:</code>、<code>-&gt;</code>、<code>~&gt;</code> なんかも考えはした</li>
<li>まだ決めかねてる。今の実装はとりあえず <code>=&gt;</code> になってるけども</li>
<li><code>=&gt;</code> はこれはこれで、ラムダ式と混ざったりデメリットもありそう</li>
</ul>
<p>など。</p>
<h2>ranges</h2>
<p>これも<a href="http://ufcpp.net/blog/2018/5/cs80preview/">先週書いた</a>通り。<code>1..^1</code>みたいな書き方で「<code>1</code> ～ <code>Length - 1</code> の直前まで」(= 最初と最後、1要素ずつ削ったもの)を表す。</p>
<p>アプローチとしては大筋はよさそう。完全に認められたわけでもないけども、「害悪」とまでは思われてない。<code>^</code>って文字を使うのはC#にとってはちょっと馴れないけども、しょせん「馴れてない」程度の話。</p>
<h2>nullable reference types</h2>
<p>参照型に対して <code>T</code> なら null が来ない、<code>T?</code> なら null があり得る、だけだと不十分で、
いくつか、属性を使ったアノテーションを実装し始めたみたい。</p>
<p><code>string.IsNullOrEmpty</code>みたいなメソッドでは、「戻り値が false だったらそれ以降、引数は null ではない」とかいう挙動なわけですが、それ用に<code>NotNullWhenFalse</code>属性を導入。</p>
<pre class="source" title="">
<code><span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">static</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">bool</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(111, 66, 193);">IsNullOrEmpty</span>([<span class="pl-en" style="box-sizing: border-box; color: rgb(111, 66, 193);">NotNullWhenFalse</span>] <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">string</span>? <span class="pl-smi" style="box-sizing: border-box; color: rgb(36, 41, 46);">s</span>) { }
</code></pre>
<p>また、以下のように <code>EnsuresNotNull</code> 属性で、「このメソッドを呼んだら、引数は null ではないことを確認済み」</p>
<pre class="source" title="">
<code><span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">static</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">void</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(111, 66, 193);">AssertNotNull</span>&lt;<span class="pl-en" style="box-sizing: border-box; color: rgb(111, 66, 193);">T</span>&gt;([<span class="pl-en" style="box-sizing: border-box; color: rgb(111, 66, 193);">EnsuresNotNull</span>] <span class="pl-en" style="box-sizing: border-box; color: rgb(111, 66, 193);">T</span>? <span class="pl-smi" style="box-sizing: border-box; color: rgb(36, 41, 46);">t</span>) <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">where</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(111, 66, 193);">T</span> : <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">class</span> { }
</code></pre>
<p><code>AssertNotNull</code> だと「null だったらそこで例外」みたいな挙動だけども、別に例外でなくても、
「メソッド内部で null でない値に上書き」とかもあり得る。</p>
<pre class="source" title="">
<code><span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">static</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">void</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(111, 66, 193);">EnsureNotNull</span>([<span class="pl-en" style="box-sizing: border-box; color: rgb(111, 66, 193);">EnsuresNotNull</span>] <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">ref</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">string</span>? <span class="pl-smi" style="box-sizing: border-box; color: rgb(36, 41, 46);">s</span>) { <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">if</span> (<span class="pl-smi" style="box-sizing: border-box; color: rgb(36, 41, 46);">s</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">is</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(111, 66, 193);">null</span>) <span class="pl-smi" style="box-sizing: border-box; color: rgb(36, 41, 46);">s</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">=</span> <span class="pl-s" style="box-sizing: border-box; color: rgb(3, 47, 98);"><span class="pl-pds" style="box-sizing: border-box; color: rgb(3, 47, 98);">"</span><span class="pl-pds" style="box-sizing: border-box; color: rgb(3, 47, 98);">"</span></span>; }
</code></pre>
<p><code>==</code> 以外での null チェックもできるように、「<code>Equals</code> の類のメソッドです。null 解析に使ってください」を表す <code>NullableEquals</code> 属性も。</p>
<pre class="source" title="">
<code><span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">class</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(111, 66, 193);">Object</span>
{
    [<span class="pl-en" style="box-sizing: border-box; color: rgb(111, 66, 193);">NullableEquals</span>] <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">public</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">static</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">bool</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(111, 66, 193);">ReferenceEquals</span>(<span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">object</span>? <span class="pl-smi" style="box-sizing: border-box; color: rgb(36, 41, 46);">x</span>, <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">object</span>? <span class="pl-smi" style="box-sizing: border-box; color: rgb(36, 41, 46);">y</span>) { }
    [<span class="pl-en" style="box-sizing: border-box; color: rgb(111, 66, 193);">NullableEquals</span>] <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">public</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">static</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">bool</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(111, 66, 193);">Equals</span>(<span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">object</span>? <span class="pl-smi" style="box-sizing: border-box; color: rgb(36, 41, 46);">x</span>, <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">object</span>? <span class="pl-smi" style="box-sizing: border-box; color: rgb(36, 41, 46);">y</span>) { }
    [<span class="pl-en" style="box-sizing: border-box; color: rgb(111, 66, 193);">NullableEquals</span>] <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">public</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">virtual</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">bool</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(111, 66, 193);">Equals</span>(<span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">object</span>? <span class="pl-smi" style="box-sizing: border-box; color: rgb(36, 41, 46);">other</span>) { }
    [<span class="pl-en" style="box-sizing: border-box; color: rgb(111, 66, 193);">NullableEquals</span>] <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">public</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">static</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">bool</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">operator</span><span class="pl-en" style="box-sizing: border-box; color: rgb(111, 66, 193);">==</span>(<span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">object</span>? <span class="pl-smi" style="box-sizing: border-box; color: rgb(36, 41, 46);">x</span>, <span class="pl-k" style="box-sizing: border-box; color: rgb(215, 58, 73);">object</span>? <span class="pl-smi" style="box-sizing: border-box; color: rgb(36, 41, 46);">y</span>) { }
}
</code></pre>
<p>既存のコードでこの属性が付いてない場合に備えて、
「外からアノテーションを足す」みたいな機能も欲しい。
(属性だと、そのメソッドを書いた人にしか付けれない。)</p>
<h2>インターフェイスのデフォルト メソッド</h2>
<p>インターフェイスの中に実装を置くことに対して、やっぱりいくらかの人が反対してる。
多くの人は、インターフェイスを自分で書いて自分で使ってる。
この状況だと、「インターフェイスにメンバーを追加したら破壊的変更」と言うのが問題になりにくい。</p>
<p>でも、public な API を作っている人にとってはデフォルト メソッド(= インターフェイスに後からメソッドを追加しても破壊的変更にならなくできる)は非常に重要。
また、Swift や Java との相互運用(主に Xamarin 用)には必要。</p>
<p>なので重要な機能だと考える。</p>
<h2>discriminated unions</h2>
<h3>switch の網羅性</h3>
<p>以下のような感じで、「Animal の派生クラスは Dog と Cat しか認めない」みたいな状態を作ったとして</p>
<pre class="source" title="">
<code><span class="reserved">abstract</span> <span class="reserved">class</span> <span class="type">Animal</span>
{
    <span class="reserved">private</span> Animal() { }
    <span class="reserved">sealed</span> <span class="reserved">class</span> <span class="type">Dog</span> : <span class="type">Animal</span> { }
    <span class="reserved">sealed</span> <span class="reserved">class</span> <span class="type">Cat</span> : <span class="type">Animal</span> { }
}
</code></pre>
<p>switch の網羅性(考えうるケースを網羅してたら <code>_</code> や <code>default</code> を警告なしで省略できるようにしたい)はどう考えるべきか。
以下のコードだとダメ。</p>
<pre class="source" title="">
<code><span class="reserved">int</span> M(<span class="type">Animal</span> a)
{
    <span class="reserved">return</span> a <span class="reserved">switch</span>
    {
        <span class="type">Cat</span> c =&gt; 1,
        <span class="type">Dog</span> d =&gt; 2
    }
}
<span class="reserved">int</span> M(<span class="type">Box</span>&lt;<span class="type">Animal</span>&gt; b)
{
    <span class="reserved">return</span> b <span class="reserved">switch</span>
    {
        <span class="type">Box</span> (<span class="type">Cat</span> c) =&gt; 1,
        <span class="type">Box</span> (<span class="type">Dog</span> d) =&gt; 2
    }
}
</code></pre>
<p>実際には以下のように書かないと網羅的じゃない。</p>
<pre class="source" title="">
<code><span class="reserved">int</span> M(<span class="type">Animal</span> a)
{
    <span class="reserved">return</span> a <span class="reserved">switch</span>
    {
        <span class="type">Cat</span> c =&gt; 1,
        <span class="type">Dog</span> d =&gt; 2,
        <span class="reserved">null</span> =&gt; 3
    }
}
<span class="reserved">int</span> M(<span class="type">Box</span>&lt;<span class="type">Animal</span>&gt; b)
{
    <span class="reserved">return</span> b <span class="reserved">switch</span>
    {
        <span class="type">Box</span> (<span class="type">Cat</span> c) =&gt; 1,
        <span class="type">Box</span> (<span class="type">Dog</span> d) =&gt; 2,
        <span class="type">Box</span> (<span class="reserved">null</span>) =&gt; 3
        <span class="reserved">null</span> =&gt; 3
    }
}
</code></pre>
<h3>struct unions</h3>
<p>上記のようなクラスを使った discriminated unions の実装(F# の discriminated unions はこんな感じのクラスに展開されてる)の他に、構造体を使った実装もありえる。
<code>int</code> と <code>(short, short)</code> みたいな、小さい型のどちらかだけを使いたいみたいな場合はある(特にパフォーマンスを求める場面で)。
ただ、これを実現するには .NET ランタイムのレベルでの対応が必要。</p>
 ]]></description>
				<pubDate>Sun, 20 May 2018 16:11:02 +0900</pubDate>
			</item>
			<item>
				<title>C# vNext Preview</title>
				<link>http://ufcpp.net/blog/2018/5/cs80preview/</link>
				<description><![CDATA[ <p>以下のページで、C# 8.0のプレビュー公開を始めたみたです。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/wiki/vNext-Preview">vNext Preview</a></li>
</ul>
<h2>インストール</h2>
<p>これまででも、まだ Visual Studio プレビュー版にも組み込まれていないような機能の類も、VSIX (Visual Studio 拡張)や NuGet 参照でコンパイラーだけ差し替えることで使えたりはしました。
<a href="https://dotnet.myget.org/gallery/roslyn">roslyn のデイリー ビルド</a>を「パッケージ ソース」にして、Microsoft.Net.Compilers パッケージを参照すれば行けます。</p>
<p>ただ、このやり方だと、IDEのC#エディターの IntelliSense は最新版になりません。
ビルドを実行するとコンパイルは通るんですが、エディター上ではエラーの赤線だらけになります。</p>
<p>で、今回公開された<a href="https://github.com/dotnet/csharplang/wiki/vNext-Preview">vNext Preview</a>は、インストールとアンインストール用のスクリプトが入っています。基本的には中身は VSIX なんですが、たくさんの VSIX が入っていて、依存順が複雑だとかでそれぞれ個別に入れるのは無理っぽい感じです。
なので、</p>
<ul>
<li>Visual Studio を全て落とす</li>
<li>インストール スクリプト(PowerShell)を実行する</li>
<li>もし、Visual Studio のバージョンアップをする際には、一度 vNext Preview をアンインストールしてから</li>
</ul>
<p>という手順を踏んでほしいとのこと。</p>
<h2>少し先の機能</h2>
<p>最近だと、Visual Studio 自体が、あるバージョンをリリースしてほとんどすぐに、<a href="(https://www.visualstudio.com/ja/vs/preview/)">次のバージョンのプレビュー</a>を公開しています。
インストールも割と簡単で、正式リリース版との共存もできます。</p>
<p>そして、C# もそれでプレビューを体験できたりしました。
Visual Studio のリリース周期は最近3～4か月ごとなので、そのくらい先のものであればそんなに苦労することなく試せます。</p>
<p>一方、今回インストール用スクリプトを用意して提供しているのは、
要するに2バージョン以上先での提供予定のものを早めに試してもらいたいということでしょう。
久々のメジャー バージョンアップですし、ちょっと大き目な機能も入る予定です。</p>
<h2>C# 8.0 プレビューの現状</h2>
<p>とはいえ、こないだ公開された「5月4日ビルド版」では、2個しか C# 8.0 の新機能が入っていなかったりはします。
入っているのは、</p>
<ul>
<li>再帰パターン</li>
<li>ranges</li>
</ul>
<p>の2つ。</p>
<h3>再帰パターン</h3>
<p>C# 7.0 で<a href="http://ufcpp.net/study/csharp/datatype/typeswitch/">パターン マッチング</a>が入ったわけですが、
C# 7.0 時点では、元々計画に挙がってたうちの一部分(型パターン、型スイッチ)だけが実装されています。</p>
<p>C# 8.0 では、7.0 のときに先送りされた再帰パターンが入る予定です。</p>
<p>例えば以下のようなクラスがあったとして、</p>
<pre class="source" title="例">
<code><span class="reserved">class</span> <span class="type">Base</span> { }
<span class="reserved">class</span> <span class="type">A</span> : <span class="type">Base</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> X { <span class="reserved">get</span>; <span class="reserved">set</span>; }
    <span class="reserved">public</span> <span class="reserved">int</span> Y { <span class="reserved">get</span>; <span class="reserved">set</span>; }
    <span class="reserved">public</span> A(<span class="reserved">int</span> x, <span class="reserved">int</span> y) =&gt; (X, Y) = (x, y);
}
<span class="reserved">class</span> <span class="type">B</span> : <span class="type">Base</span>
{
    <span class="reserved">public</span> <span class="reserved">string</span> Name { <span class="reserved">get</span>; <span class="reserved">set</span>; }
    <span class="reserved">public</span> <span class="reserved">int</span> Value { <span class="reserved">get</span>; <span class="reserved">set</span>; }
    <span class="reserved">public</span> B(<span class="reserved">string</span> name, <span class="reserved">int</span> value) =&gt; (Name, Value) = (name, value);
    <span class="reserved">public</span> <span class="reserved">void</span> Deconstruct(<span class="reserved">out</span> <span class="reserved">string</span> name) =&gt; name = Name;
    <span class="reserved">public</span> <span class="reserved">void</span> Deconstruct(<span class="reserved">out</span> <span class="reserved">string</span> name, <span class="reserved">out</span> <span class="reserved">int</span> value) =&gt; (name, value) = (Name, Value);
}
</code></pre>
<p>以下のようなコードなら C# 7.0 でも書けました。</p>
<pre class="source" title="C# 7.0 の型パターン">
<code><span class="reserved">static</span> <span class="reserved">int</span> M(<span class="type">Base</span> obj)
{
    <span class="reserved">switch</span> (obj)
    {
        <span class="reserved">case</span> <span class="type">A</span> a: <span class="reserved">return</span> a.X * a.Y;
        <span class="reserved">case</span> <span class="type">B</span> b <span class="reserved">when</span> b.Name == <span class="string">"one"</span>: <span class="reserved">return</span> b.Value;
        <span class="reserved">case</span> <span class="type">B</span> b <span class="reserved">when</span> b.Name == <span class="string">"two"</span>: <span class="reserved">return</span> 2 * b.Value;
        <span class="reserved">case</span> <span class="type">B</span> b <span class="reserved">when</span> b.Name == <span class="string">"three"</span>: <span class="reserved">return</span> 3 * b.Value;
        <span class="reserved">default</span>: <span class="reserved">throw</span> <span class="reserved">new</span> <span class="type">IndexOutOfRangeException</span>();
    }
}
</code></pre>
<p>C# 8.0 では以下のような、再帰的なパターンが使えるようになります。</p>
<pre class="source" title="C# 8.0 の再帰パターン">
<code><span class="reserved">static</span> <span class="reserved">int</span> M(<span class="type">Base</span> obj)
{
    <span class="reserved">switch</span> (obj)
    {
        <span class="reserved">case</span> <span class="type">A</span> { X: <span class="reserved">var</span> x, Y: <span class="reserved">var</span> y }: <span class="reserved">return</span> x * y;
        <span class="reserved">case</span> <span class="type">B</span> (<span class="string">"one"</span>) { Value: <span class="reserved">var</span> v }: <span class="reserved">return</span> v;
        <span class="reserved">case</span> <span class="type">B</span> (<span class="string">"two"</span>) { Value: <span class="reserved">var</span> v }: <span class="reserved">return</span> 2 * v;
        <span class="reserved">case</span> <span class="type">B</span> (<span class="string">"three"</span>) { Value: <span class="reserved">var</span> v }: <span class="reserved">return</span> 3 * v;
        <span class="reserved">default</span>: <span class="reserved">throw</span> <span class="reserved">new</span> <span class="type">IndexOutOfRangeException</span>();
    }
}
</code></pre>
<p><code>B(&quot;one&quot;)</code> みたいな、<code>()</code> の部分は位置指定パターンと言って、<code>Deconstruct</code> メソッドが呼ばれています(「<a href="http://ufcpp.net/study/csharp/datatype/deconstruction/">分解</a>」と同じ仕組み)。
残りの <code>{}</code> の部分はプロパティ パターンと言って、プロパティに対する <code>X is var x</code> などに展開されます。</p>
<h4>switch 式</h4>
<p>また、<code>switch</code> 式も追加されます。
式です。<code>=&gt;</code> の後ろとかにも書けます。
今のところは以下のような構文になる予定。</p>
<pre class="source" title="switch 式">
<code><span class="reserved">static</span> <span class="reserved">int</span> M(<span class="type">Base</span> obj)
    =&gt; obj <span class="reserved">switch</span>
    {
        <span class="type">A</span> { X: <span class="reserved">var</span> x, Y: <span class="reserved">var</span> y } =&gt; x * y,
        <span class="type">B</span> (<span class="string">"one"</span>) { Value: <span class="reserved">var</span> v } =&gt; v,
        <span class="type">B</span> (<span class="string">"two"</span>) { Value: <span class="reserved">var</span> v } =&gt; 2 * v,
        <span class="type">B</span> (<span class="string">"three"</span>) { Value: <span class="reserved">var</span> v } =&gt; 3 * v,
        _ =&gt; <span class="reserved">throw</span> <span class="reserved">new</span> <span class="type">IndexOutOfRangeException</span>()
    };
</code></pre>
<h4>{} パターンで null チェック</h4>
<p>ちなみに、プロパティ パターン (<code>{}</code> を使ったパターン)には null チェックが伴うそうです。</p>
<pre class="source" title="{} パターンで null チェック">
<code><span class="reserved">string</span> s = <span class="reserved">null</span>;

<span class="comment">// null は型情報を持ってなかったり。たとえ、静的な型が一致していても is は常に false。</span>
<span class="reserved">if</span> (s <span class="reserved">is</span> <span class="reserved">string</span>) <span class="type">Console</span>.WriteLine(<span class="string">"ここは絶対通らない"</span>);

<span class="comment">// is string x みたいな変数宣言を伴ってても同じ。</span>
<span class="reserved">if</span> (s <span class="reserved">is</span> <span class="reserved">string</span> x) <span class="type">Console</span>.WriteLine(<span class="string">"ここも通らない"</span>);

<span class="comment">// が、var パターンは常に true。見た目 is string に似てるけど、結果が違う。</span>
<span class="reserved">if</span> (s <span class="reserved">is</span> <span class="reserved">var</span>  y) <span class="type">Console</span>.WriteLine(<span class="string">"ここは通る"</span>);

<span class="comment">// で、プロパティ パターンを使って、null チェック付きの var に近いことができる。</span>
<span class="reserved">if</span> (s <span class="reserved">is</span> { }) <span class="type">Console</span>.WriteLine(<span class="string">"ここは通らない"</span>);
</code></pre>
<h4>タプル switch</h4>
<p>あと、タプルに対する switch では、<code>()</code> を1重に省略できます。</p>
<pre class="source" title="タプル switch">
<code><span class="reserved">static</span> <span class="reserved">int</span> M(<span class="reserved">int</span> x, <span class="reserved">int</span> y)
{
    <span class="comment">// 本来は、switch ((x, y))</span>
    <span class="reserved">switch</span> (x, y)
    {
        <span class="reserved">case</span> (1, 1): <span class="reserved">return</span> 1;
        <span class="reserved">case</span> (1, 2): <span class="reserved">return</span> 2;
        <span class="reserved">case</span> (2, 1): <span class="reserved">return</span> 3;
        <span class="reserved">case</span> (2, 2): <span class="reserved">return</span> 4;
        <span class="reserved">default</span>: <span class="reserved">return</span> 0;
    }
}
</code></pre>
<h3>ranges</h3>
<p>ranges は、<code>1..3</code> みたいな書き方で「1から3まで(ただし3は含まない)のインデックス」みたいな範囲を表す記法です。
<code>Range</code>構造体と<code>Index</code>構造体に展開される予定で、
<a href="https://raw.githubusercontent.com/dotnet/csharplang/master/proposals/ranges.cs">この<code>range.cs</code></a>みたいな定義が必要です。</p>
<pre class="source" title="ranges">
<code><span class="reserved">using</span> System;

<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> Main()
    {
        <span class="reserved">var</span> data = <span class="reserved">new</span>[] { 1, 2, 3, 4, 5, 6, 7, 8 };

        <span class="comment">// 1～4番目 → { 2, 3, 4 }</span>
        Write(data[1..4]);
        <span class="comment">// ↑は、↓と同じ結果</span>
        Write(data.AsSpan().Slice(1, 4 - 1));

        <span class="comment">// 2～(Length - 2)番目 = 最初と最後の2要素を飛ばす → { 3, 4, 5, 6 }</span>
        Write(data[2..^2]);
        <span class="comment">// ↑は、↓と同じ結果</span>
        Write(data.AsSpan().Slice(2, (data.Length - 2) - 2));

        <span class="comment">// 5～末尾 → { 6, 7, 8 }</span>
        Write(data[5..]);

        <span class="comment">// 先頭～3 → { 1, 2, 3 }</span>
        Write(data[..3]);

        <span class="comment">// 全体</span>
        Write(data[..]);
    }

    <span class="reserved">static</span> <span class="reserved">void</span> Write(<span class="type">Span</span>&lt;<span class="reserved">int</span>&gt; s)
    {
        <span class="reserved">foreach</span> (var x <span class="reserved">in</span> s)
        {
            <span class="type">Console</span>.Write(x);
            <span class="type">Console</span>.Write(<span class="string">" "</span>);
        }
        <span class="type">Console</span>.WriteLine();
    }
}
</code></pre>
<p>正直、<code>Slice(start, length)</code> みたいな記法との差が少なすぎて、便利さで言うとそこまで大きくはないんですが。
以下のような要件があるので、それなりに必要性はあります。</p>
<ul>
<li><code>Slice(x, y)</code> みたいな書き方では、第2引数が「長さ」なのか「終端インデックス」なのかで迷う</li>
<li>「末尾から n 番目」みたいなのは<code>data.Length - n</code> みたいな書き方が必要でしんどい</li>
<li>特に多次元データの時に <code>data[a..b, c..d, e..f]</code> みたいに書きたい</li>
</ul>
<p>現時点では、以下の実装はないみたいです。</p>
<ol>
<li>start, length 型の ranges (「a を始点に長さ b」みたいなやつ)</li>
<li>inclusive ranges (「a～b まで(bも<em>含む</em>)」みたいなやつ)</li>
<li>ユーザー定義の <code>..</code> 演算子</li>
</ol>
<p>このうち、C# 8.0 正式リリースまでに入るかもしれないのは1の start, length 型 ranges くらい。
残りは「その先また改めて検討」のはずです。</p>
<h4>一時的な「拡張インデクサー」</h4>
<p>ちなみに、このプレビューでは、「拡張インデクサー」みたいなものが一時的に入っています
(<code>T[]</code>、<code>Span&lt;T&gt;</code>、<code>string</code>に対する<code>Range</code>型引数のインデクサーを拡張として追加しています)。
これはほんとに一時的な対処で、C# 8.0でこの文法で「拡張インデクサー」が使えるわけではありません。</p>
<p>正式には、「<a href="https://github.com/dotnet/csharplang/issues/110">Type Class</a>」という別提案が出ていて、これ待ちです。
もしかしたらこれも C# 8.0 で入るかも。</p>
 ]]></description>
				<pubDate>Sat, 12 May 2018 20:00:42 +0900</pubDate>
			</item>
			<item>
				<title>Visual Studio 15.7 リリース など</title>
				<link>http://ufcpp.net/blog/2018/5/vs157/</link>
				<description><![CDATA[ <p><a href="https://developer.microsoft.com/en-us/events/build">Micorsoft Build</a>に合わせて、Visual Studioの新バージョンが正式リリースしたみたいですね。その他、.NET/C# 関連をいくつか。</p>
<p>告知ブログ:</p>
<ul>
<li><a href="https://blogs.msdn.microsoft.com/visualstudio/2018/05/07/microsoft-build-2018-new-releases-for-visual-studio-visual-studio-for-mac-net-core-and-xamarin-forms/">Microsoft Build 2018: New releases for Visual Studio, Visual Studio for Mac, .NET Core and Xamarin.Forms</a></li>
</ul>
<p>正式リリース:</p>
<ul>
<li>
<a href="https://blogs.msdn.microsoft.com/visualstudio/2018/05/07/visual-studio-2017-version-15-7-and-version-15-8-preview-1/">Visual Studio 2017 15.7</a>
<ul>
<li><a href="http://ufcpp.net/study/csharp/cheatsheet/ap_ver7_3/">C# 7.3</a>も含まれています</li>
</ul>
</li>
<li><a href="https://blogs.msdn.microsoft.com/visualstudio/2018/05/07/visual-studio-for-mac-version-7-5-and-beyond/">Visual Studio for Mac, version 7.5</a></li>
<li>
<a href="https://github.com/dotnet/machinelearning">ML.NET</a>
<ul>
<li>.NET 実装のオープンソースな機械学習ライブラリ</li>
<li>バージョン 0.1 ですが</li>
</ul>
</li>
</ul>
<p>リリース候補版:</p>
<ul>
<li>
<a href="https://blogs.msdn.microsoft.com/dotnet/2018/05/07/announcing-net-core-2-1-rc-1/">.NET Core 2.1 RC</a>
<ul>
<li>Go Live (自己責任だけど、もう実運用環境で使ってもいいよ)サポートに</li>
<li>Alpine Linux サポート</li>
<li>ARM プロセッサ サポート</li>
<li><a href="https://github.com/dotnet/sourcelink">SourceLink</a></li>
</ul>
</li>
</ul>
<p>プレビュー版:</p>
<ul>
<li>
<a href="https://www.visualstudio.com/services/live-share/">Visual Studio Live Share</a>
<ul>
<li>パブリックに(これまで登録制のプライベート プレビューだった)</li>
</ul>
</li>
<li>
<a href="https://blogs.msdn.microsoft.com/visualstudio/2018/05/07/introducing-visual-studio-intellicode/">Visual Studio IntelliCode</a>
<ul>
<li>AIでインテリセンスを賢くする的なものらしい</li>
</ul>
</li>
</ul>
<p>ロードマップ公開:</p>
<ul>
<li>
<a href="https://blogs.msdn.microsoft.com/dotnet/2018/05/07/net-core-3-and-support-for-windows-desktop-applications/">.NET Core 3</a>
<ul>
<li>今年後半にプレビュー公開、正式版は2019年リリース予定</li>
</ul>
</li>
</ul>
<h2>C# 7.3</h2>
<p>地味な更新なのでほとんど触れられてませんが、C# 7.3も正式リリースっぽいです。</p>
<p>一応なんとかリリースまでに全機能網羅できてんで、
詳しくは「<a href="http://ufcpp.net/study/csharp/cheatsheet/ap_ver7_3/">C# 7.3 の新機能</a>」を参照してください。</p>
<p>「C# 7.2の延長」みたいな機能とか、
相変わらず<a href="http://ufcpp.net/study/csharp/sp_ref.html">refがらみ</a>(一般的なユーザーにはそこまで使われないかも)とか、
<a href="http://ufcpp.net/study/csharp/resource/span/"><code>Span&lt;T&gt;</code>がらみ</a>(言語機能だけは先にあるけど、<code>Span&lt;T&gt;</code>自体はまだリリース候補版の状態)とかが多いですけども。
以下の2つとかは結構面白いかも。</p>
<ul>
<li><a href="http://ufcpp.net/study/csharp/cheatsheet/ap_ver7_3/#overload-resolution">オーバーロード解決の改善</a></li>
<li><a href="http://ufcpp.net/study/csharp/cheatsheet/ap_ver7_3/#constraints">ジェネリック型引数に対する Enum, Delegate 制約</a></li>
</ul>
<h2>.NET Core for Desktop</h2>
<p><a href="https://blogs.msdn.microsoft.com/dotnet/2018/05/07/net-core-3-and-support-for-windows-desktop-applications/">.NET Core 3</a>のロードマップでは、「Windowsデスクトップも .NET Coreの上で動くようにするよ」とのこと。</p>
<p>ちなみに、あくまでWindows限定です。
「WPFとかもクロスプラットフォームにする」的な意味ではなく、
「Windowsでしか動かしようのないものもCore上に載せる」という意味です。</p>
<p>メリットは以下のような感じ。</p>
<ul>
<li>
ユーザー視点: Windows限定機能も、.NET Coreのメリットを享受できる
<ul>
<li>
side by side アップデート可能
<ul>
<li>同一マシン内に複数バージョンの .NET Core ランタイムをインストールして、アプリごとに選べる</li>
<li>最新ランタイムの機能を享受しやすい</li>
<li>「最新版でしか動かない」みたいなものは少ないものの、「最新版にするだけで速くなる」みたいなのは常にある</li>
<li>今後は<a href="https://github.com/dotnet/csharplang/issues/52">「最新版でしか動かない」もあり得る</a></li>
</ul>
</li>
<li>
<a href="https://docs.microsoft.com/ja-jp/dotnet/core/deploying/#self-contained-deployments-scd">App-local デプロイ</a>ができる
<ul>
<li>アプリ自体に依存ライブラリを全部含めてデプロイできる</li>
</ul>
</li>
</ul>
</li>
<li>
.NET チーム視点: ようやく Core に一本化できそう
<ul>
<li>.NET Frameworkにしかない機能がある限り、.NET Frameworkの開発は止めれない</li>
</ul>
</li>
</ul>
 ]]></description>
				<pubDate>Tue, 08 May 2018 11:37:51 +0900</pubDate>
			</item>
			<item>
				<title>C# にも型クラス(Shapes)が欲しい… 距離空間上のアルゴリズム実装</title>
				<link>http://ufcpp.net/blog/2018/5/metricspace/</link>
				<description><![CDATA[ <p>今日は C# で「距離の計算」を汎用的に、かつ、高パフォーマンスでやりたいという話。
というか、やりたいのはやまやまなんだけど、高パフォーマンスを目指すとなかなか大変なことになるという話。
<a href="/blog/2017/2/pickuproslyn0223/">Shapes</a>が来れば楽になるはずだけども、計画上だいぶ先の話なので、待っていると厳しいので大変なのを我慢したという話でもあります。</p>
<p>サンプル コードの全体像: <a href="https://github.com/ufcpp/UfcppSample/tree/master/Demo/2018/MetricSpace">MetricSpace</a></p>
<h2><a id="distance">距離</a></h2>
<p>2つの何らかの情報の距離を求めたいことは結構あります。</p>
<ul>
<li><a href="https://ja.wikipedia.org/wiki/%E3%83%87%E3%83%BC%E3%82%BF%E3%83%BB%E3%82%AF%E3%83%A9%E3%82%B9%E3%82%BF%E3%83%AA%E3%83%B3%E3%82%B0">近いもの同士でグルーピングしたい</a></li>
<li><a href="https://ja.wikipedia.org/wiki/%E6%9C%80%E7%9F%AD%E7%B5%8C%E8%B7%AF%E5%95%8F%E9%A1%8C">最短経路を求めたい</a></li>
<li><a href="https://docs.unity3d.com/jp/current/Manual/OcclusionCulling.html">一定範囲に入っているものだけを取り出したい</a></li>
</ul>
<p>汎用性が要らないなら簡単な話で、以下のようなコードで書けます。</p>
<pre class="source" title="float の配列に対するユークリッド距離">
<code><span class="reserved">class</span> <span class="type">Euclidean</span>
{
    <span class="comment">// a と b の長さが同じとか、いくつか前提を置いちゃってるけども、最低限のコード</span>
    <span class="comment">// a, b を N 次元空間上の点とみなして、その間の距離の2乗、</span>
    <span class="comment">// 要するに「差の2乗和」を求める。</span>
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">float</span> DistanceSquared(<span class="reserved">float</span>[] a, <span class="reserved">float</span>[] b)
    {
        <span class="reserved">var</span> d = 0f;
        <span class="reserved">for</span> (<span class="reserved">int</span> i = 0; i &lt; a.Length; i++)
        {
            <span class="reserved">var</span> dif = b[i] - a[i];
            d += dif * dif;
        }
        <span class="reserved">return</span> d;
    }
}
</code></pre>
<p>ここで、汎用性を気にすると以下のような要望が出てきます。</p>
<ul>
<li>数値の型: <code>float</code>以外にも使いたい</li>
<li>数値の「組」の型: 配列じゃなくしたい</li>
<li>距離計算の方法: 2乗和(いわゆる<a href="https://ja.wikipedia.org/wiki/%E3%83%A6%E3%83%BC%E3%82%AF%E3%83%AA%E3%83%83%E3%83%89%E8%B7%9D%E9%9B%A2">ユークリッド距離</a> )だけが距離じゃない</li>
</ul>
<h2><a id="arithmetic">数値の型</a></h2>
<p>距離計算に使う演算は、和、差、積程度です。
あと、「同じ点かどうか」は知りたいことが多いので、等値比較はしたいでしょう。
距離を計算したあと、「一定範囲に収まっているかどうか」を判定することが多いので、大小比較くらいは必要です。</p>
<p>とはいえ、<code>float</code>に限らず、数値型ならどの型でもこの条件くらいは満たします。
実際例えば、「四角いマス目の上の点」みたいなのを考えると<code>float</code>よりも<code>int</code>が使いたくなります。
精度が必要な場合には<code>double</code>や<code>decimal</code>を使いたくなるでしょうし、省メモリ都合で<code>short</code>を使いたい場合もあるでしょう。</p>
<p>となったときに問題になるのが、C# では、数値の四則演算を素直にジェネリックにできないこと。
以下のコードはコンパイルできません。</p>
<pre class="source" title="ジェネリックな型には演算子が使えない">
<code><span class="comment">// int や double でも使いたいからと言って、以下のようには書けない。</span>
<span class="comment">// ジェネリックな型 T には +, -, * が定義されていない。</span>
<span class="reserved">class</span> <span class="type">Euclidean</span>&lt;<span class="type">T</span>&gt;
{
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="type">T</span> DistanceSquared(<span class="type">T</span>[] a, <span class="type">T</span>[] b)
    {
        <span class="type">T</span> d = <span class="error">0</span>;
        <span class="reserved">for</span> (<span class="reserved">int</span> i = 0; i &lt; a.Length; i++)
        {
            <span class="reserved">var</span> dif = b[i] <span class="error">-</span> a[i];
            d += dif * dif;
        }
        <span class="reserved">return</span> d;
    }
}
</code></pre>
<p>しょうがなく、以下のように書いたりします。</p>
<pre class="source" title="">
<code><span class="reserved">interface</span> <span class="type">IArithmetic</span>&lt;<span class="type">T</span>&gt;
{
    <span class="type">T</span> Zero { <span class="reserved">get</span>; }
    <span class="type">T</span> Add(<span class="type">T</span> a, <span class="type">T</span> b);
    <span class="type">T</span> Subtract(<span class="type">T</span> a, <span class="type">T</span> b);
    <span class="type">T</span> Multiply(<span class="type">T</span> a, <span class="type">T</span> b);
}

<span class="reserved">class</span> <span class="type">Euclidean</span>&lt;<span class="type">T</span>&gt;
{
    <span class="comment">// 四則演算用のインターフェイスを外からもらう</span>
    <span class="type">IArithmetic</span>&lt;<span class="type">T</span>&gt; _arithmetic;
    <span class="reserved">public</span> Euclidean(<span class="type">IArithmetic</span>&lt;<span class="type">T</span>&gt; arithmetic) =&gt; _arithmetic = arithmetic;


    <span class="comment">// static にするのはあきらめる</span>
    <span class="reserved">public</span> <span class="type">T</span> DistanceSquared(<span class="type">T</span>[] a, <span class="type">T</span>[] b)
    {
        <span class="reserved">var</span> arith = _arithmetic;
        <span class="comment">// IArithmetic&lt;T&gt; 越しに 0 をもらったり、四則演算したり</span>
        <span class="reserved">var</span> d = arith.Zero;
        <span class="reserved">for</span> (<span class="reserved">int</span> i = 0; i &lt; a.Length; i++)
        {
            <span class="reserved">var</span> dif = arith.Subtract(b[i], a[i]);
            <span class="reserved">var</span> sq = arith.Multiply(dif, dif);
            d = arith.Add(d, sq);
        }
        <span class="reserved">return</span> d;
    }
}
</code></pre>
<p>が、これだと、</p>
<ul>
<li><code>IArithmetic&lt;T&gt;</code>や<code>Euclidean&lt;T&gt;</code>のインスタンスを持ちまわすのが大変面倒</li>
<li>仮想呼び出しのせいで<a href="/study/csharp/structured/miscinlining/">インライン化</a>が効かなくなってものすごく遅い</li>
</ul>
<p>という問題があります。</p>
<p>で、ちょっとしたトリックなんですが、<a href="/study/csharp/sp2_generics.html?p=3#pseudo-static">値型ジェネリックを使うとインライン化が効く</a>という黒魔術がありまして。
以下のように書けば倍は速くなります。</p>
<pre class="source" title="値型ジェネリックで四則演算">
<code><span class="reserved">class</span> <span class="type">Euclidean</span>&lt;<span class="type">T</span>, <span class="type">TArithmetic</span>&gt;
    <span class="comment">// 構造体にして、型引数で受け取る</span>
    <span class="reserved">where</span> <span class="type">TArithmetic</span> : <span class="reserved">struct</span>, <span class="type">IArithmetic</span>&lt;<span class="type">T</span>&gt;
{
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="type">T</span> DistanceSquared(<span class="type">T</span>[] a, <span class="type">T</span>[] b)
    {
        <span class="comment">// default を使って IArithmetic&lt;T&gt; を作る</span>
        <span class="reserved">var</span> arith = <span class="reserved">default</span>(<span class="type">TArithmetic</span>);
        <span class="comment">// あとは先ほどと同じ</span>
        <span class="reserved">var</span> d = arith.Zero;
        <span class="reserved">for</span> (<span class="reserved">int</span> i = 0; i &lt; a.Length; i++)
        {
            <span class="reserved">var</span> dif = arith.Subtract(b[i], a[i]);
            <span class="reserved">var</span> sq = arith.Multiply(dif, dif);
            d = arith.Add(d, sq);
        }
        <span class="reserved">return</span> d;
    }
}

<span class="reserved">struct</span> <span class="type">FloatArithmetic</span> : <span class="type">IArithmetic</span>&lt;<span class="reserved">float</span>&gt;
{
    <span class="reserved">public</span> <span class="reserved">float</span> Zero =&gt; 0;
    <span class="reserved">public</span> <span class="reserved">float</span> Add(<span class="reserved">float</span> a, <span class="reserved">float</span> b) =&gt; a + b;
    <span class="reserved">public</span> <span class="reserved">float</span> Multiply(<span class="reserved">float</span> a, <span class="reserved">float</span> b) =&gt; a - b;
    <span class="reserved">public</span> <span class="reserved">float</span> Subtract(<span class="reserved">float</span> a, <span class="reserved">float</span> b) =&gt; a * b;
}

<span class="comment">// IntArithmetic, DoubleArithmetic, ...</span>
<span class="comment">// 使いたい型の分だけ同じ IArithmetic&lt;T&gt; を書く</span>

<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> Main()
    {
        <span class="comment">// FloatArithmetic の時点で T は float で確定なんだけど、残念ながら型推論はされない</span>
        <span class="comment">// 常にこの2つの型引数をペアで渡さないといけない</span>
        Euclidean&lt;<span class="reserved">float</span>, <span class="type">FloatArithmetic</span>&gt;.DistanceSquared(<span class="reserved">new</span>[] { 1f, 2f }, <span class="reserved">new</span>[] { 3f, 4f });
    }
}
</code></pre>
<p>一応これで、最初の <code>float</code> 専用で書いたコードに近いパフォーマンスになります。
まあ、面倒も多々あって、特に大変なのが、型引数を常にペアで渡さないと行けなくなる部分です。
この先、さらにどんどん面倒になって行くんですが、もうすでにこの時点で相当面倒です…</p>
<h2><a id="fixed-array">数値の「組」の型</a></h2>
<p>次の課題は、配列を避けたいという点。
前述の例でも、メソッド呼び出しの際に <code>new[] { 1f, 2f }</code> とか書いていますが、
配列は<a href="/study/computer/MemoryManagement.html#heap">ヒープ</a>を使ってしまうので、
今回のような用途ではパフォーマンス上、あまり好ましくありません。</p>
<p>今回の用途だと、</p>
<ul>
<li>要素数が常に固定</li>
<li>しかも、よく使うのはせいぜい2次元か3次元</li>
</ul>
<p>ということで、配列の代わりに以下のような構造体を使いたくなったりします。</p>
<pre class="source" title="">
<code><span class="reserved">struct</span> <span class="type">Array1</span>&lt;<span class="type">T</span>&gt;
{
    <span class="reserved">public</span> <span class="type">T</span> Item1;
}

<span class="reserved">struct</span> <span class="type">Array2</span>&lt;<span class="type">T</span>&gt;
{
    <span class="reserved">public</span> <span class="type">T</span> Item1;
    <span class="reserved">public</span> <span class="type">T</span> Item2;
}

<span class="reserved">struct</span> <span class="type">Array3</span>&lt;<span class="type">T</span>&gt;
{
    <span class="reserved">public</span> <span class="type">T</span> Item1;
    <span class="reserved">public</span> <span class="type">T</span> Item2;
    <span class="reserved">public</span> <span class="type">T</span> Item3;
}

<span class="comment">// 以下、必要なだけ ArrayN を用意</span>
</code></pre>
<p>で、以下の理由から、こいつに対しても先ほどと同様の「値型ジェネリックを使ったトリック」が必要になります。</p>
<ul>
<li>固定長の配列なんだから、長さを静的に取得したい</li>
<li>構造体は、自身のフィールドを <code>ref</code> 戻り値で返せない</li>
</ul>
<pre class="source" title="">
<code><span class="reserved">struct</span> <span class="type">Array2</span>&lt;<span class="type">T</span>&gt;
{
    <span class="reserved">public</span> <span class="type">T</span> Item1;
    <span class="reserved">public</span> <span class="type">T</span> Item2;

    <span class="comment">// これをジェネリックに使いたければトリックが必要</span>
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">int</span> Length =&gt; 2;

    <span class="comment">// ただでさえ、safe にインデックス アクセスを実現する方法はないんだけど…</span>
    <span class="comment">// そもそも、C# の構造体は ref Item1 したものを、ref 戻り値では返せない仕様</span>
    <span class="reserved">public</span> <span class="reserved">ref</span> <span class="type">T</span> <span class="reserved">this</span>[<span class="reserved">int</span> index] =&gt; <span class="reserved">ref</span> <span class="type">Unsafe</span>.Add&lt;T&gt;(<span class="reserved">ref</span> <span class="error">Item1</span>, index);
}
</code></pre>
<p>その結果、行きつく先は以下のようなコードになります。</p>
<pre class="source" title="値型ジェネリックを使った固定長配列">
<code><span class="comment">// 配列自体用。これは大して意味は持ってない。誤用防止程度</span>
<span class="reserved">public</span> <span class="reserved">interface</span> <span class="type">IFixedArray</span>&lt;<span class="type">T</span>&gt; { }

<span class="comment">// 値型ジェネリック トリック用</span>
<span class="reserved">public</span> <span class="reserved">interface</span> <span class="type">IFixedArrayAccessor</span>&lt;<span class="type">T</span>, <span class="type">TArray</span>&gt;
    <span class="reserved">where</span> <span class="type">TArray</span> : <span class="reserved">struct</span>, <span class="type">IFixedArray</span>&lt;T&gt;
{
    <span class="type">TArray</span> New();
    <span class="reserved">ref</span> <span class="type">T</span> At(<span class="reserved">ref</span> <span class="type">TArray</span> array, <span class="reserved">int</span> i);
    <span class="reserved">int</span> Length { <span class="reserved">get</span>; }
}

<span class="reserved">public</span> <span class="reserved">struct</span> <span class="type">Fixed2</span>&lt;<span class="type">T</span>&gt; : <span class="type">IFixedArrayAccessor</span>&lt;<span class="type">T</span>, <span class="type">Fixed2</span>&lt;T&gt;.<span class="type">Array</span>&gt;
{
    <span class="reserved">public</span> <span class="reserved">struct</span> <span class="type">Array</span> : <span class="type">IFixedArray</span>&lt;<span class="type">T</span>&gt;
    {
        <span class="reserved">public</span> <span class="type">T</span> Item1; <span class="reserved">public</span> <span class="type">T</span> Item2;
        <span class="reserved">public</span> Array(<span class="type">T</span> item1, <span class="type">T</span> item2) =&gt; (Item1, Item2) = (item1, item2);
        <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">implicit</span> <span class="reserved">operator</span> Array((<span class="type">T</span>, <span class="type">T</span>) value) =&gt; <span class="reserved">new</span> <span class="type">Array</span>(value.Item1, value.Item2);
    }

    <span class="reserved">public</span> <span class="type">Array</span> New() =&gt; <span class="reserved">default</span>;
    <span class="reserved">public</span> <span class="reserved">int</span> Length =&gt; 2;
    <span class="reserved">public</span> <span class="reserved">unsafe</span> <span class="type">Span</span>&lt;<span class="type">T</span>&gt; AsSpan(<span class="reserved">ref</span> <span class="type">Array</span> array) =&gt; <span class="reserved">new</span> Span&lt;<span class="type">T</span>&gt;(Unsafe.AsPointer(<span class="reserved">ref</span> array.Item1), 2);
    <span class="reserved">public</span> <span class="reserved">ref</span> <span class="type">T</span> At(<span class="reserved">ref</span> <span class="type">Array</span> array, <span class="reserved">int</span> i) =&gt; <span class="reserved">ref</span> AsSpan(<span class="reserved">ref</span> array)[i];
    <span class="comment">// 範囲チェックをさぼる(危険でいい)なら以下の書き方でも OK</span>
    <span class="comment">//public ref T At(ref Array array, int i) =&gt; ref Unsafe.Add(ref array.Item1, i);</span>
}
</code></pre>
<p>この時点で結構悩ましいコードですが、されにこれを距離計算に組み込むと以下のようになります。</p>
<pre class="source" title="固定長配列を距離計算に組み込み">
<code><span class="reserved">class</span> <span class="type">Euclidean</span>&lt;<span class="type">T</span>, <span class="type">TArithmetic</span>, <span class="type">TArray</span>, <span class="type">TArrayAccessor</span>&gt;
    <span class="reserved">where</span> <span class="type">TArithmetic</span> : <span class="reserved">struct</span>, <span class="type">I/OArithmetic</span>&lt;<span class="type">T</span>&gt;
    <span class="reserved">where</span> <span class="type">TArray</span> : <span class="reserved">struct</span>, <span class="type">IFixedArray</span>&lt;<span class="type">T</span>&gt;
    <span class="reserved">where</span> <span class="type">TArrayAccessor</span> : <span class="reserved">struct</span>, <span class="type">IFixedArrayAccessor</span>&lt;<span class="type">T</span>, <span class="type">TArray</span>&gt;
{
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="type">T</span> DistanceSquared(<span class="type">TArray</span> a, <span class="type">TArray</span> b)
    {
        <span class="reserved">var</span> arith = <span class="reserved">default</span>(<span class="type">TArithmetic</span>);
        <span class="reserved">var</span> accessor = <span class="reserved">default</span>(<span class="type">TArrayAccessor</span>);
        <span class="reserved">var</span> d = arith.Zero;
        <span class="reserved">for</span> (<span class="reserved">int</span> i = 0; i &lt; accessor.Length; i++)
        {
            <span class="reserved">var</span> dif = arith.Subtract(accessor.At(<span class="reserved">ref</span> b, i), accessor.At(<span class="reserved">ref</span> a, i));
            <span class="reserved">var</span> sq = arith.Multiply(dif, dif);
            d = arith.Add(d, sq);
        }
        <span class="reserved">return</span> d;
    }
}

<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> Main()
    {
        <span class="comment">// これも、Fixed2&lt;float&gt; を使う時点で残りの型引数確定なんだけど、残念ながら型推論はされない</span>
        <span class="comment">// 常にこの4つの型引数が必要</span>
        <span class="type">Euclidean</span>&lt;<span class="reserved">float</span>, <span class="type">FloatArithmetic</span>, <span class="type">Fixed2</span>&lt;<span class="reserved">float</span>&gt;.<span class="type">Array</span>, <span class="type">Fixed2</span>&lt;<span class="reserved">float</span>&gt;&gt;.DistanceSquared((1, 2), (3, 4));
    }
}
</code></pre>
<p>型引数が4つに増えました。
しかし、実際のところ意味がある情報は、<code>float</code>、「2次元」の2つだけです。
気持ち的には <code>Euclidean&lt;float, 2&gt;</code> とだけ書きたいですが、C# では叶いません。</p>
<h2><a id="metric">距離計算の方法</a></h2>
<p>最後に、距離の計算自体も汎用化してみましょう。</p>
<p>距離にもいろいろあります。
ぶっちゃけ、「非負」「三角不等式が成り立つ」の2点だけ満たしていれば何でも距離です。
<a href="https://ja.wikipedia.org/wiki/%E3%83%A6%E3%83%BC%E3%82%AF%E3%83%AA%E3%83%83%E3%83%89%E8%B7%9D%E9%9B%A2">ユークリッド距離</a>以外でそこそこよく使うものだと以下のようなものがあります。</p>
<ul>
<li>
<a href="https://ja.wikipedia.org/wiki/%E3%83%9E%E3%83%B3%E3%83%8F%E3%83%83%E3%82%BF%E3%83%B3%E8%B7%9D%E9%9B%A2">マンハッタン距離</a>
<ul>
<li>絶対値の和</li>
<li>京都やマンハッタンの街みたいに碁盤の目になっている都市での2点間の距離</li>
<li>「一定距離にある点」をつなぐと、ダイアモンド型になる</li>
</ul>
</li>
<li>
<a href="https://ja.wikipedia.org/wiki/%E3%83%81%E3%82%A7%E3%83%93%E3%82%B7%E3%82%A7%E3%83%95%E8%B7%9D%E9%9B%A2">チェビシェフ距離</a>
<ul>
<li>絶対値の最大値</li>
<li>チェスや将棋みたいに、斜めにも動ける駒にとっての盤面の距離</li>
<li>「一定距離にある点」をつなぐと、四角になる</li>
</ul>
</li>
</ul>
<p>これも、汎用化するだけならインターフェイスを1個用意するだけなんですが、
パフォーマンスを考えると値型ジェネリックを使うことになります。
行きつく先が以下のようなコード。</p>
<pre class="source" title="距離もジェネリック化">
<code><span class="reserved">interface</span> <span class="type">IMetric</span>&lt;<span class="type">T</span>, <span class="type">TArray</span>&gt;
    <span class="reserved">where</span> <span class="type">TArray</span> : <span class="reserved">struct</span>, <span class="type">IFixedArray</span>&lt;T&gt;
{
    <span class="type">T</span> DistanceSquared(<span class="type">TArray</span> a, <span class="type">TArray</span> b);
}

<span class="reserved">struct</span> <span class="type">EuclideanMetric</span>&lt;<span class="type">T</span>, <span class="type">TArithmetic</span>, <span class="type">TArray</span>, <span class="type">TArrayAccessor</span>&gt; : <span class="type">IMetric</span>&lt;<span class="type">T</span>, <span class="type">TArray</span>&gt;
    <span class="reserved">where</span> <span class="type">TArithmetic</span> : <span class="reserved">struct</span>, <span class="type">IArithmetic</span>&lt;<span class="type">T</span>&gt;
    <span class="reserved">where</span> <span class="type">TArray</span> : <span class="reserved">struct</span>, <span class="type">IFixedArray</span>&lt;<span class="type">T</span>&gt;
    <span class="reserved">where</span> <span class="type">TArrayAccessor</span> : <span class="reserved">struct</span>, <span class="type">IFixedArrayAccessor</span>&lt;<span class="type">T</span>, <span class="type">TArray</span>&gt;
{
    <span class="reserved">public</span> <span class="type">T</span> DistanceSquared(<span class="type">TArray</span> a, <span class="type">TArray</span> b)
    {
        <span class="reserved">var</span> arith = <span class="reserved">default</span>(<span class="type">TArithmetic</span>);
        <span class="reserved">var</span> accessor = <span class="reserved">default</span>(<span class="type">TArrayAccessor</span>);
        <span class="reserved">var</span> d = arith.Zero;
        <span class="reserved">for</span> (<span class="reserved">int</span> i = 0; i &lt; accessor.Length; i++)
        {
            <span class="reserved">var</span> dif = arith.Subtract(accessor.At(<span class="reserved">ref</span> b, i), accessor.At(<span class="reserved">ref</span> a, i));
            <span class="reserved">var</span> sq = arith.Multiply(dif, dif);
            d = arith.Add(d, sq);
        }
        <span class="reserved">return</span> d;
    }
}

<span class="comment">// Manhattan とか Chebychev とかも同様に作る</span>

<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="comment">// 近い方の点を求める</span>
    <span class="reserved">static</span> <span class="type">TArray</span> Nearest&lt;<span class="type">T</span>, <span class="type">TArray</span>, <span class="type">TMetric</span>&gt;(<span class="type">TArray</span> origin, <span class="type">TArray</span> a, <span class="type">TArray</span> b)
        <span class="reserved">where</span> <span class="type">T</span> : <span class="type">IComparable</span>&lt;<span class="type">T</span>&gt;
        <span class="reserved">where</span> <span class="type">TArray</span> : <span class="reserved">struct</span>, <span class="type">IFixedArray</span>&lt;<span class="type">T</span>&gt;
        <span class="reserved">where</span> <span class="type">TMetric</span> : <span class="reserved">struct</span>, <span class="type">IMetric</span>&lt;<span class="type">T</span>, <span class="type">TArray</span>&gt;
    {
        <span class="reserved">var</span> metric = <span class="reserved">default</span>(<span class="type">TMetric</span>);

        <span class="reserved">var</span> da = metric.DistanceSquared(origin, a);
        <span class="reserved">var</span> db = metric.DistanceSquared(origin, b);

        <span class="reserved">return</span> da.CompareTo(db) &lt;= 0 ? a : b;
    }

    <span class="reserved">static</span> <span class="reserved">void</span> Main()
    {
        <span class="comment">// 型引数は3つと思いきや、Euclidean がさらに4つ求めるので合計7つ</span>
        <span class="comment">// 常にこの7つの型引数が必要</span>
        <span class="reserved">var</span> n = Nearest&lt;<span class="reserved">float</span>, <span class="type">Fixed2</span>&lt;<span class="reserved">float</span>&gt;.<span class="type">Array</span>, <span class="type">EuclideanMetric</span>&lt;<span class="reserved">float</span>, <span class="type">FloatArithmetic</span>, <span class="type">Fixed2</span>&lt;<span class="reserved">float</span>&gt;.<span class="type">Array</span>, <span class="type">Fixed2</span>&lt;<span class="reserved">float</span>&gt;&gt;&gt;(
            (0, 0), (1, 2), (3, 4));

        <span class="type">Console</span>.WriteLine((n.Item1, n.Item2));
    }
}
</code></pre>
<p>型引数だけで画面の横幅目いっぱい使うようなメソッドができました…
もちろん、意味がある部分は<code>float</code>, <code>2</code>, <code>Euclidean</code>だけで、残りは冗長です。</p>
<h2><a id="instantiation">ごまかし</a></h2>
<p><a href="https://github.com/ufcpp/KdTree/">というようなコードを書くことに最近迫られまして</a>。
(元々公開されていたリポジトリからフォークして、上記のようなトリックを仕込んでパフォーマンス向上する作業をした。)
汎用化を捨てたり、パフォーマンスをあきらめてもよかったんですが。
なんとなくきっちりやっちゃいまして。</p>
<p>最初はしょうがなく7つの冗長な型引数を書いてたんですが、
やっぱりすぐにつらくなって断念。
代わりに、以下のようなごまかしコードを書くことになりました。</p>
<pre class="source" title="派生でごまかす">
<code><span class="comment">// ジェネリックな型を1個用意しておいて、派生で型引数を与えておく</span>
<span class="comment">// 数値の型</span>
<span class="reserved">class</span> <span class="type">FloatPoint</span> : <span class="type">Point</span>&lt;<span class="reserved">float</span>, <span class="type">FloatArithmetic</span>&gt; { }
<span class="reserved">class</span> <span class="type">DoublePoint</span> : <span class="type">Point</span>&lt;<span class="reserved">double</span>, <span class="type">DoubleArithmetic</span>&gt; { }
<span class="reserved">class</span> <span class="type">IntPoint</span> : <span class="type">Point</span>&lt;<span class="reserved">int</span>, <span class="type">IntArithmetic</span>&gt; { }
<span class="reserved">class</span> <span class="type">ShortPoint</span> : <span class="type">Point</span>&lt;<span class="reserved">short</span>, <span class="type">ShortArithmeti</span>c&gt; { }

<span class="reserved">class</span> <span class="type">Point</span>&lt;<span class="type">T</span>, <span class="type">TArithmetic</span>&gt;
    <span class="reserved">where</span> <span class="type">T</span> : <span class="type">IComparable</span>&lt;<span class="type">T</span>&gt;
    <span class="reserved">where</span> <span class="type">TArithmetic</span> : <span class="reserved">struct</span>, <span class="type">IArithmetic</span>&lt;<span class="type">T</span>&gt;
{
    <span class="comment">// 数値の「組」の型</span>
    <span class="reserved">public</span> <span class="reserved">class</span> <span class="type">_1</span> : <span class="type">Dimension</span>&lt;<span class="type">Fixed1</span>&lt;<span class="type">T</span>&gt;.<span class="type">Array</span>, <span class="type">Fixed1</span>&lt;<span class="type">T</span>&gt;&gt; { }
    <span class="reserved">public</span> <span class="reserved">class</span> <span class="type">_2</span> : <span class="type">Dimension</span>&lt;<span class="type">Fixed2</span>&lt;<span class="type">T</span>&gt;.<span class="type">Array</span>, <span class="type">Fixed2</span>&lt;<span class="type">T</span>&gt;&gt; { }
    <span class="reserved">public</span> <span class="reserved">class</span> <span class="type">_3</span> : <span class="type">Dimension</span>&lt;<span class="type">Fixed3</span>&lt;<span class="type">T</span>&gt;.<span class="type">Array</span>, <span class="type">Fixed3</span>&lt;<span class="type">T</span>&gt;&gt; { }
    <span class="reserved">public</span> <span class="reserved">class</span> <span class="type">_4</span> : <span class="type">Dimension</span>&lt;<span class="type">Fixed4</span>&lt;<span class="type">T</span>&gt;.<span class="type">Array</span>, <span class="type">Fixed4</span>&lt;<span class="type">T</span>&gt;&gt; { }

    <span class="reserved">public</span> <span class="reserved">class</span> <span class="type">Dimension</span>&lt;<span class="type">TArray</span>, <span class="type">TArrayAccessor</span>&gt;
        <span class="reserved">where</span> <span class="type">TArray</span> : <span class="reserved">struct</span>, <span class="type">IFixedArray</span>&lt;<span class="type">T</span>&gt;
        <span class="reserved">where</span> <span class="type">TArrayAccessor</span> : <span class="reserved">struct</span>, <span class="type">IFixedArrayAccessor</span>&lt;<span class="type">T</span>, <span class="type">TArray</span>&gt;
    {
        <span class="comment">// 距離計算の方法</span>
        <span class="reserved">public</span> <span class="reserved">class</span> <span class="type">Euclidean</span> : <span class="type">Metric</span>&lt;<span class="type">EuclideanMetric</span>&lt;<span class="type">T</span>, <span class="type">TArithmetic</span>, <span class="type">TArray</span>, <span class="type">TArrayAccessor</span>&gt;&gt; { }
        <span class="reserved">public</span> <span class="reserved">class</span> <span class="type">Manhattan</span> : <span class="type">Metric</span>&lt;<span class="type">ManhattanMetric</span>&lt;<span class="type">T</span>, <span class="type">TArithmetic</span>, <span class="type">TArray</span>, <span class="type">TArrayAccessor</span>&gt;&gt; { }
        <span class="reserved">public</span> <span class="reserved">class</span> <span class="type">Chebyshev</span> : <span class="type">Metric</span>&lt;<span class="type">ChebyshevMetric</span>&lt;<span class="type">T</span>, <span class="type">TArithmetic</span>, <span class="type">TArray</span>, <span class="type">TArrayAccessor</span>&gt;&gt; { }

        <span class="reserved">public</span> <span class="reserved">class</span> <span class="type">Metric</span>&lt;<span class="type">TMetric</span>&gt;
            <span class="reserved">where</span> <span class="type">TMetric</span> : <span class="reserved">struct</span>, <span class="type">IMetric</span>&lt;<span class="type">T</span>, <span class="type">TArray</span>&gt;
        {
            <span class="reserved">public</span> <span class="reserved">static</span> <span class="type">TArray</span> Nearest(<span class="type">TArray</span> origin, <span class="type">TArray</span> a, <span class="type">TArray</span> b)
            {
                <span class="reserved">var</span> metric = <span class="reserved">default</span>(<span class="type">TMetric</span>);

                <span class="reserved">var</span> da = metric.DistanceSquared(origin, a);
                <span class="reserved">var</span> db = metric.DistanceSquared(origin, b);

                <span class="reserved">return</span> da.CompareTo(db) &lt;= 0 ? a : b;
            }

            <span class="comment">// その他、距離空間に対するアルゴリズムをこの中に書く</span>
        }
    }
}

<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> Main()
    {
        <span class="comment">// 使う側に関してはだいぶ短く書けた</span>
        <span class="reserved">var</span> n = <span class="type">FloatPoint</span>.<span class="type">_2</span>.<span class="type">Euclidean</span>.<span class="type">Nearest</span>(
            (0, 0), (1, 2), (3, 4));

        <span class="type">Console</span>.WriteLine((n.Item1, n.Item2));
    }
}
</code></pre>
<p>一応、使う側のコードはだいぶ短くなり、許容範囲になったかなと思います。
ただ、これはこれで、以下のような問題があって、妥協的です。</p>
<ul>
<li>使いたい型、固定長配列の次元、距離計算の方法が増えるたびに、この派生クラスも追加しないといけない</li>
<li>クラスの中に入っているので、他のアセンブリで型を追加できない</li>
</ul>
<p>根本解決できるようなプログラミング言語を求めるなら、
ジェネリック型引数の推論をもっと頑張ってもらうとか、<code>float</code>に対する<code>FloatArithmetic</code>みたいなもののペアリングとかの仕様が必要になります。</p>
<p>型の推論は、かなり頑張っている言語もあって、そういう言語ではもうちょっと手短にコードを書けるんですが、
その代わりにコンパイル時間が指数的に跳ね上がったり、
コンパイル エラーが出たときにエラー メッセージが読めた代物じゃなくなったりという弊害があったりします…</p>
<p><code>float</code>に対する<code>FloatArithmetic</code>、
<code>TArray</code>に対する<code>TArrayAccessor</code>みたいなものは、ShapeとかType Classとか呼ばれたりするんですが、
こいつは<a href="http://ufcpp.net/blog/2017/2/pickuproslyn0223/">将来的に C# に入りそうな雰囲気</a>があります。</p>
<p>これが来てくれればだいぶこの手の作業は楽になるんですが。
現状は明確なマイルストーンが切られておらず、「7.X はおろか、8.X でも無理」という扱いです。
最短で、9.0 とかで入ると仮定しても2年以上は先でしょうか…
なので待ってられないので、しょうがなくこんなコードを書くことに…</p>
 ]]></description>
				<pubDate>Thu, 03 May 2018 16:46:26 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 4/4 C# 8.0辺りの検討事項</title>
				<link>http://ufcpp.net/blog/2018/4/pickuproslyn0404/</link>
				<description><![CDATA[ <p><a href="/blog/2018/3/pickuproslyn0321/">Design Notes の一斉アップロード祭り</a>がらみ、今日でやっと最後。
<a href="https://github.com/dotnet/csharplang/blob/master/meetings/2018/LDM-2018-03-28.md">先月28日に1つ追加の Note もあります</a>。</p>
<p>とりあえずこれまでの分:</p>
<ul>
<li><a href="/blog/2018/3/pickuproslyn0321/">C# 8.0よりさらに先を見越して、いくつかの機能の採用が決定</a></li>
<li><a href="/blog/2018/3/ranges/">一番分量が多かった Ranges (C# 8.0 予定)の話</a></li>
<li><a href="/blog/2018/3/pickuproslyn0331/">C# 7.3 で入りそうな機能の話</a></li>
</ul>
<p>で、今日は最後に、C# 8.0 辺りで入りそうな機能の話になります。</p>
<h2>Caller Expression Attribute</h2>
<p><a href="/study/csharp/ap_ver5.html#CallerInfo">Caller Info 属性</a>に1種類追加。
<code>M(2 * x, y * y, Sin(z));</code> みたいなメソッド呼び出しをした時に、<code>2 * x, y * y, Sin(z)</code> の部分をそのまま受け取るというデバッグ用の機能です。
主な用途は Assert 系の API。</p>
<p>で、既存の Assert API がこの機能を活用しようと思ったら、
<code>Equal(T expected, T actual)</code> みたいなメソッドを
<code>Equal(T expected, T actual, [CallerExpression]string expression = null)</code> みたいなシグネチャに変える必要があります。</p>
<p>こいつの呼び出し側は、元のまま <code>Assert.Equal(x, y);</code> で呼べばいいんですが…</p>
<ul>
<li>既存の <code>Equal(T expected, T actual)</code> を残すと、こっちの方が優先度が高いのでこっちしか呼ばれない</li>
<li>
既存の <code>Equal(T expected, T actual)</code> を消すと、ソースコード互換はあるけどバイナリ互換はない(一応、破壊的変更)
<ul>
<li>ソースコードの再コンパイルなしで、Assert ライブラリの DLL だけ更新すると実行できなくなる</li>
</ul>
</li>
</ul>
<p>という問題が。
XUnit は昔この手の引数追加での破壊的変更を1度やっているらしく、まあ、許容できると言えばできそう。</p>
<h2>null 許容参照型</h2>
<p>このブログでもたびたび紹介していますが、参照型も <code>T</code> (null なし)と<code>T?</code> (null あり)の区別がつくようになるやつ。</p>
<p>待望の機能ですし、すでにプロトタイプ実装も始まっていますが、やっぱ細々と検討事項が出てきます。</p>
<h3>明示的なキャストの扱い</h3>
<p><code>(T)x</code> とか <code>(T?)x</code> とか、キャストをどう扱うかというのも案外自明ではないみたい。
特に、既存コードからの移行の都合と、新たに書き始めるのであれば追求したい「正しさ」との間のバランスで悩むとか。</p>
<ul>
<li>
既存コードには <code>(string)null</code> とかで「型指定ありの null」とかは結構書くけども
<ul>
<li>これは自動的に<code>string?</code>扱いすべきか(既存コード優先)</li>
<li>警告すべきか(正しさ優先)</li>
</ul>
</li>
</ul>
<p><code>M((string)x)</code> と <code>M((string?)x)</code> みたいなキャストは、ジェネリック メソッドの呼び分けでははっきりとキャストが意味を持ってる。
例えば<code>T M&lt;T&gt;(T x)</code> に対して、
<code>var y = M((string)x)</code> とすると <code>y</code> も <code>string</code> (nullなし)になるし、
<code>var y = M((string?)x)</code> とすると <code>y</code> が <code>string?</code> (nullあり)になる。</p>
<p>一方で、<code>M</code>が旧時代のコード(<code>T</code> と <code>T?</code> の区別をしない時代のコードでは、<code>T</code> から null が帰ってくることがあるし、
コンパイラーもそのつもりで null チェックをする)だった場合、
<code>M((string)x)</code> はどう解釈すべきか。
<code>x</code> が新時代(<code>T?</code>あり)コードなら警告でいいけども、
<code>x</code> も旧時代コードならこの<code>string</code>はどう扱うべきか。</p>
<h3>警告の種類</h3>
<p>古いコードをアップグレードするとき、一気にはコードを修正できないので <code>#pragma warning</code> などを使って警告を無視したいことがあり得る。
この「警告オフ」作業を煩雑にしないために、null チェック絡みの警告の種類はまとめられる限りまとめたい。</p>
<p>実際、「null リテラルを <code>T</code> に代入」と、「<code>T?</code> 型変数の値を <code>T</code> に代入」は統合したみたいです。</p>
<h3>型推論</h3>
<p><code>T?</code> 型の変数であっても、null チェックがあったらそれ以降は「null ではない」という扱いになります
(コンパイラーがそういう風に判断して警告の有無が決まる)。</p>
<p>例えば、以下のような判定になったりします。</p>
<pre class="source" title="">
<code><span class="reserved">string</span>? ns = ...
<span class="reserved">if</span> (ns <span class="reserved">is</span> <span class="reserved">null</span>) <span class="reserved">return</span>; <span class="comment">// null だったらここから下にはいかない</span>
<span class="reserved">var</span> s = ns; <span class="comment">// なので、s は「非 null」</span>
</code></pre>
<p>ここで問題なのは、じゃあ、この <code>s</code> は「<code>string?</code>だけどnullチェック済み」という判定なのか、
「<code>string</code>型として推論されてる」という状態なのか。
ジェネリック メソッドに <code>s</code> を渡した時のオーバーロード解決とかにも絡んでくる。</p>
<h3>var?</h3>
<p><code>var s1 =&quot;Hello&quot;;</code> とか書いたとき(<code>string</code>扱い？)、<code>s1</code> に後から <code>null</code> を代入したい場面ではどうするべきか。</p>
<p><code>var s2 = (string?)&quot;Hello&quot;;</code> は、「<code>var</code>と書くと非nullとして推論」として認めないようにするか、<code>string?</code>として推論すべきか。</p>
<p>「<code>var</code>と書くと非null」の対として、<code>var? s3 = &quot;Hello&quot;;</code> みたいな書き方を用意する？</p>
<h2>Records</h2>
<p>C# 6.0の頃から案だけはあるものの、気が付けば C# 7.X でも入らず 8.0 に伸びてる Record 型。
<code>class Record(int X, int Y);</code> とか書くと、プロパティ <code>X</code>、<code>Y</code> とか <code>==</code>、<code>Deconstruct</code> を自動で実装してくれるというやつです。</p>
<p>先月の <a href="https://mvp.microsoft.com/ja-jp/Summit">Microsoft MVP Global Summit</a> でやっぱ <a href="https://www.microsoft.com/ja-jp/communities/mvp/">MVP</a> からさんざん突っ込みが入ったそうで。それに対する回答:</p>
<ul>
<li>重要性はわかっているけども、現実主義的に行きたい(要するに、課題も多くて完成には及ばず)</li>
<li><a href="https://github.com/dotnet/csharplang/issues/113">Discriminated Unions</a>と併せて取り組みたい。別機能ではあるものの、Records と一緒に取り組むとより良くなる</li>
<li>いくつか「用途が狭い」と判定された提案は「<a href="https://github.com/dotnet/csharplang/issues/341">コード生成でやってくれ</a>」と言ってきてるが、Records に関して言うとコード生成の領分ではない。ちゃんと言語機能として取り組むべき</li>
</ul>
<h2>Ranges</h2>
<p><a href="https://github.com/dotnet/csharplang/blob/master/meetings/2018/LDM-2018-03-28.md">28日に追加分</a>でも Ranges に関する記述あり。</p>
<h3>プロトタイプ提供するにあたって</h3>
<p><a href="/blog/2018/3/ranges/">Ranges</a> 構文はあくまで <code>Range</code> 型を作るという機能であって、<code>Span&lt;T&gt; span = array[1..3];</code> みたいな書き方をするためには、配列や<code>List</code>が<code>Range</code>型を受け付けるインデクサーを持っていないといけない。</p>
<p>で、この機能のプロトタイプを提供するにあたって、こういう「<code>Range</code>型を受け付けるインデクサー」も同時にプロトタイプ提供したい。
特に、配列とか<code>string</code>とかの型でこれを使いたいわけだけど、そのために .NET Core ランタイム側で対応作業をしてもらう必要があるとなると、
プロジェクト間の依存が大きすぎる。</p>
<p><code>Span&lt;T&gt; this[Range range]</code> インデクサーを被せるだけのラッパー構造体を作ってそれをプロトタイプ提供すべき？</p>
<p>それか、一時的に「拡張インデクサー」を提供してしまう？
(拡張インデクサーは、<a href="https://github.com/dotnet/csharplang/issues/164">Shapes</a>って機能の一部として提供したけども、
こいつは 8.0 よりもさらに先で検討されてる。Ranges の方が先に実装される。なので、本来 Ranges と同時期には提供しないはずの機能を「一時的に」「仮実装」で提供。)</p>
<p>今のところ「一時的な拡張インデクサー」の提供を考えてる。</p>
<h3>どこまで提供するか</h3>
<p>結局どこまでやるか。</p>
<ul>
<li><code>m..n</code> で「m から n まで」みたいな開始・終了インデックス型だけを提供</li>
<li>「m から len 要素」みたいなやつや、「配列の末尾から n 要素目」みたいなのを考えて、<code>Index</code>型と<code>^</code>演算子みたいなのも提供</li>
</ul>
<p>前者なら実装は楽だけどできることの制限が強い。
まずはこの「実装が楽な部分」だけを実装してみて、ユーザーの反応を見てみるという手もある。
でも、ちょっとこの制限はきついと思っていて、たぶん高機能な後者の方の需要はある。</p>
<h2>switch 式の網羅性</h2>
<p>「<code>switch</code> 式」では網羅性(exhaustiveness)のチェックをしたいという話がある。
例えば <code>bool</code> なら(変なことをしなければ) <code>true</code> と <code>false</code> の2値しか持っていないわけだから、
<code>x switch { case true: a; case false: b; }</code> みたいな式は「すべての値を網羅している」と言えるはず。</p>
<p>これをコンパイラーがチェック(網羅されていれば「default 句なし」を認める)すべき？
チェックするとして、(いくつか、コンパイラーの静的チェックに漏れるケースがあり得るけど、その時のために)実行時チェックもする？</p>
<p>今のところ、網羅性をチェックして、網羅できていなければ警告にする。
静的チェックに漏れた場合の実行時チェックも入れて、例外を投げるようにすると思う。</p>
<h3>nested stackalloc</h3>
<p>現状、<a href="http://ufcpp.net/study/csharp/resource/span/#safe-stackalloc">stackalloc</a>は非同期メソッド内では使えないという制限があります。
まあ、<code>await</code> をまたいで使うことは原理的にできない機能ではあります。</p>
<pre class="source" title="">
<code><span class="reserved">async</span> Task M()
{
    Span&lt;<span class="reserved">int</span>&gt; span = <span class="reserved">stackalloc</span> <span class="reserved">int</span>[10];

    <span class="reserved">await</span> Task.Delay(1);

    span[0] = 1; <span class="comment">// これは本当に不正。原理的に無理</span>
}
</code></pre>
<p>でも、<code>await</code> さえまたがなければ、例えば以下のような書き方であれば安全に使えるはずです。</p>
<pre class="source" title="">
<code><span class="reserved">async</span> Task M()
{
    {
        Span&lt;<span class="reserved">int</span>&gt; span = <span class="reserved">stackalloc</span> <span class="reserved">int</span>[10];
        span[0] = 1;
    }

    <span class="comment">// ブロックでくくったので、span がここに漏れることはない</span>
    <span class="reserved">await</span> Task.Delay(1);
    <span class="comment">// ここから下で使えなければ span は安全</span>
}
</code></pre>
<p>この、「ブロックで囲った(nested) <code>stackalloc</code>」を認めたいという感じになっています。</p>
 ]]></description>
				<pubDate>Wed, 04 Apr 2018 23:19:36 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 3/31: C# 7.3</title>
				<link>http://ufcpp.net/blog/2018/3/pickuproslyn0331/</link>
				<description><![CDATA[ <p><a href="http://ufcpp.net/blog/2018/3/pickuproslyn0321/">C# Language Design Notes アップロード祭り</a>の続き。</p>
<p>Notes のうち3・4割くらいは、C# 7.3の機能の「最後の詰め」みたいな感じの検討でした。</p>
<h2>C# 7.3 の状況</h2>
<p>ちなみに、先日のブログでも書きましたが、C# 7.3に含める機能はもう概ね固まっているみたいです。<a href="https://github.com/dotnet/roslyn/blob/master/docs/Language%20Feature%20Status.md">進捗状況</a>を見ると全項目Merged。</p>
<p>(大半は、<a href="https://dotnet.myget.org/gallery/roslyn">nightly build</a>のパッケージに反映済み。まだなのは「Custom fixed」と「Indexing movable fixed buffers」の2つ。)</p>
<p>うちの<a href="/study/csharp/">C# によるプログラミング入門</a>には、Visual Studio 15.7 Previewで拡張なしで C# 7.3を使えるようになる頃にはページを追加したいなぁとか思いながら、nightly build版でちらほら試しに触ってみています。
とりあえずは、今のnightly buildに含まれていない上記2機能を除いて、書きたい内容のサンプル コードを整備:</p>
<ul>
<li><a href="https://github.com/ufcpp/UfcppSample/tree/master/Demo/2018/Csharp7_3-0309">https://github.com/ufcpp/UfcppSample/tree/master/Demo/2018/Csharp7_3-0309</a></li>
</ul>
<h2>Design Notes で検討されていたこと</h2>
<p>とりあえず具体的な機能説明は<a href="/study/csharp/">C# によるプログラミング入門</a>の方にページ追加するときに頑張ります。</p>
<p>今日は、先日上がった Design Notes で触れられていた内容を軽く紹介。</p>
<h3>式中の変数宣言</h3>
<p>C# 7.0でいわゆる「<a href="http://ufcpp.net/study/csharp/cheatsheet/ap_ver7/#var-expressions"><code>out var</code></a>」が入って、変数宣言を式中でできるようになりました。
C# 7.3では、7.0の頃には使えなかったいくつかの場所でこの機能を使えるよう拡充することになっています。</p>
<p>Notes での検討事項は、主にその変数のスコープをどうするか:</p>
<ul>
<li>コンストラクター初期化子: <code>C(int i) : base(out var x) { x }</code> ← この <code>x</code> は <code>{}</code> 内で有効</li>
<li>
フィールド初期化子: その初期化子内でだけ有効
<ul>
<li><code>int X = M(out var x).N(x);</code> ← <code>N</code>のとこで<code>x</code>は有効</li>
<li>続けて <code>int Y = x;</code> ← <code>X</code> の方で作った <code>x</code> は、<code>Y</code> の方では無効</li>
<li>C# スクリプト実行(変数っぽく宣言したものは、暗黙的に見えないクラスのフィールドになってる)の時の挙動とは一貫性ないんだけど</li>
</ul>
</li>
<li>
クエリ式: 句単位でスコープ切れてる
<ul>
<li><code>from x in e where M(x, out var y) select y;</code> ← <code>select</code>の方の<code>y</code>は無効</li>
<li>ラムダ式の挙動に準じてる。 <code>e.Where(x =&gt; M(x, out var y)).Select(x =&gt; y);</code> ← <code>Select</code>内の<code>y</code>は無効</li>
<li>句をまたぎたければ <code>let</code> 句を使って</li>
</ul>
</li>
</ul>
<h3>ジェネリクスの型制約</h3>
<h4>Enum, Delegate</h4>
<p><code>where T : Enum</code> と <code>where T : Delegate</code> (または <code>where T : MulticastDelegate</code>)が指定できるように。</p>
<p>この<code>Enum</code>、<code>Delegate</code>は、それぞれ<code>System.Enum</code>クラス、<code>System.Delegate</code> クラスのことです。<code>using System;</code>がないと<code>where T : Enum</code>とは書けず。</p>
<p>また、キーワードの<code>enum</code>、<code>delegate</code>を使った<code>where T : enum</code> と <code>where T : delegate</code> は書けません。
将来的にそういうのも検討するかもしれないけども、少なくとも C# 7.3 では実装しません。</p>
<h4>ValueType, Array</h4>
<p>同じような「.NETのランタイムが特別扱いしてる型」に<code>Systam.ValueType</code>と<code>System.Array</code>がありますが、
これらは現状では有意義な用途が見つかっておらず、「もし用途が見つかれば改めて考える」とのこと。</p>
<h4>unmanaged</h4>
<p>もう1個、こっちは文脈キーワードの追加で、<code>where T : unmanaged</code> という制約が追加されます。
これは要するに、「ポインター化可能な型」。
「<a href="/study/csharp/sp_unsafe.html#function">unsafe コード限定機能</a>」のとこで説明していますが、
ポインター化しても安全な型にはちょっとした制約があって、
その制約を満たす型を元々 unmanaged 型と呼びます。</p>
<p>これまで、ジェネリック型引数に対して unmanaged かどうかの判定はできなかったんですが、C# 7.3 でこの制約が入ったことで、ジェネリックなポインターを作れるようになります。</p>
<p>unmanaged の条件の1つが「構造体であること」なので、<code>where T : unmanaged</code> はこの時点で暗黙的に <code>where T : struct</code> の意味も含みます。
なので、<code>where T : struct, unmanaged</code> みたいな併用は認めません。</p>
<p>あと、「ポインター化可能かどうか」の判定には<a href="/blog/2016/12/tipsapisurface/">参照アセンブリ問題</a>っていう問題があったりするんですが、
unmanaged 制約もまったく同じ問題を起こします。
(といっても、これは C# コンパイラーの問題ではないので C# チームとしてはどうしようもない。)</p>
<p>ちなみに、<code>var</code> の時にもそうだったんですが、「後からの文脈キーワードの追加」なので、互換性維持のために「<code>var</code>と言う名前の型、<code>unmanaged</code>という名前の型がすでに存在するときは、キーワードではなくてその型の方が優先される」という挙動になっています。
意図的に<code>class unmanaged { }</code> みたいなクラスを作ると、<code>where T : unmanaged</code> の <code>T</code> は「この <code>unmanaged</code> クラスの派生型」という扱いになります。</p>
<h3>ref reassignment</h3>
<p><code>ref var r</code> に対して、「参照先の振り替え」ができるようになります。
<code>ref var r = ref x;</code> とした後、<code>r = ref y;</code> で振り替え。その後は <code>r = value;</code> とすると、<code>y</code> の中身が書き換わります。</p>
<p>普通の代入と同じく、この <code>r = ref y</code> も式にできます。
例えば、連結リスト操作で <code>while ((l = ref l.Next) != null)</code> みたいなコードを書けます。</p>
<p>あと、C# 7.3 では <code>foreach (ref var x in source)</code> みたいな、<code>foreach</code> の反復変数も参照にできます。
これも、通常の反復変数が書き換え不可なので、参照の場合の「参照先の振り替え」は不可です。</p>
<p><code>ref int r;</code> みたいに未初期化の状態で変数宣言した後、<code>r = ref x;</code> と後から参照先を割り当てることも考えられますが、C# 7.3 の時点ではやらないみたい。
「<a href="http://ufcpp.net/study/csharp/sp_ref.html?p=2#flow-analysis">安全性チェック</a>」(戻り値として返せるかどうか)が大変になるからとのこと。</p>
<h3>stackalloc</h3>
<p>C# 7.2 で「<a href="/study/csharp/resource/span/#safe-stackalloc">安全な stackalloc</a>」が入ります。
そのため、これまでなら「unsafe 限定のレア機能」だった<code>stackalloc</code>が、C# 7.2 以降利用頻度が上がる可能性があります。</p>
<p>ということで、<code>stackalloc</code>の使い勝手を上げてもいいだろうという話に。
具体的には、配列の<code>new</code>に対してできることは<code>stackalloc</code>にもできてもよいという話。
要するに、<code>stackalloc</code>に初期化子を付けれるようになります。
<code>stackalloc[] { 1, 2, 3 }</code>とか。</p>
<h3>パターン ベースの fixed ステートメント</h3>
<p><a href="/study/csharp/resource/span/"><code>Span&lt;T&gt;</code></a>はパフォーマンス向上のために導入された型で、
こいつに対してポインター操作をしたいという需要は結構高いようです。
しかし、<code>Span&lt;T&gt;</code>からポインター取得する際に<code>fixed</code> (GC によってポインターが指してる先が移動しないように、オブジェクトを「固定」する)をどうやって掛けようかと言うので悩んでいました。</p>
<p>今は、<code>fixed (T* p = MemoryMarshal.GetReference(span))</code>とか書いたり、
ちょっと前までは<code>fixed (T* p = span.DangerousGetPinnableReference())</code>とかだったりしました。
これを、<code>fixed (T* p = span)</code> と書いたら何らかのメソッド呼び出しに置き換えたいという話。</p>
<p>展開結果は、まあ、「Dangerous はねぇわ」という感じみたいで、
結局、今現在 marge されているコードを見るに<code>GetPinnableReference</code>と言う名前を使いそう。</p>
<p><code>string</code>とかの標準ライブラリ中の型に関してはこの<code>GetPinnableReference</code>をインスタンス メソッドとして追加予定。
一方で、(<a href="/study/csharp/sp3_extension.html#ref-extensions"><code>ref this</code>、<code>in this</code></a>を含む)拡張メソッドもOKにする予定。</p>
<p>safe な手段ではできないんですが「null 相当する参照」を返すことで、<code>fixed (T* p = s)</code> の結果の<code>p</code>がnullポインターになることも認めるとのこと。
nullチェックは使う側の責任。</p>
<h3>タプルの ==, !=</h3>
<p>C# 7.3 から <code>(x, y) == (1, 2)</code> みたいな、<code>==</code>と<code>!=</code>を使ったタプルの等値判定ができるようになります。</p>
<p>C# のタプルの実体は<code>System.ValueTuple</code>型なわけですが、これの<code>==</code>演算子を呼べばいいという話ではないです。
タプルは「メンバーごとの暗黙の型変換」を認めているので、比較でも型変換を考慮する必要があるとのこと。
例えば、<code>(int x, int y)</code>なタプル変数<code>t</code>に対して、<code>t == (123L, 1E10D)</code> とかができます(それぞれ<code>long</code>、<code>double</code>との比較)。</p>
<p>ということで、タプルの<code>==</code>は、「メンバーごとの<code>==</code>呼び出しを<code>&amp;&amp;</code>で繋いだもの」として解釈。
ユーザー定義の<code>==</code>で、<code>bool</code>ではなくユーザー定義型を返す場合、それの<code>operator.true</code>と<code>operator.false</code>が呼ばれます。</p>
<h3>オーバーロード解決</h3>
<p>C# 6.0くらいの頃からずっと「<a href="http://ufcpp.net/blog/2015/10/pickuproslyn1018/">bestest betterness</a>」とかいうふざけた言い方をしてたやつをついに実装するそうで。
ちなみに、betternessルールの改良はたびたびやっているので、
「better betterness」→「best betterness」→「bestest betterness」とかポケモン進化みたいなふざけた名前になりました。</p>
<p>今まで、「まず引数の型の一致を確認」→「制約等を満たすか調べて、満たしてなければコンパイル エラー」という順の処理をしていました。
制約を調べる方があとなので、解決できないオーバーロードが結構あったという。
それを、引数の一致を調べるより先に、以下のものを調べるように変わります。</p>
<ul>
<li>ジェネリック型制約</li>
<li>静的メンバーかインスタンス メンバーか</li>
<li>(メソッドをデリゲートに渡すときに)メソッドの戻り値の型</li>
</ul>
<p>これは bestest だわー。
(さすがにふざけた名前なので、最近、Proposal のタイトルも「Improve overload candidates」に変更されました。)</p>
 ]]></description>
				<pubDate>Sat, 31 Mar 2018 23:49:38 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 3/24: Ranges</title>
				<link>http://ufcpp.net/blog/2018/3/ranges/</link>
				<description><![CDATA[ <p><a href="http://ufcpp.net/blog/2018/3/pickuproslyn0321/">こないだのDesign Notesアップロード祭り</a>、1月辺りの議題としては割と「Ranges」の話が多かったみたいです。今日はこれの話。</p>
<h2>Ranges</h2>
<p>レンジ、要するに「どこからどこまで」みたいな値の範囲のことです。そこそこいろんなプログラミング言語にありますけども、例えば <code>1..3</code>みたいな書き方で1～3の範囲を表そうという構文。</p>
<p>.NET Core 2.1で、配列などの連続したメモリ領域の一定区間を指し示す<a href="http://ufcpp.net/study/csharp/resource/span/"><code>Span&lt;T&gt;</code>構造体</a>っていう型が入りました。これに伴い、以下のように、配列の一部分を抜き出すような構文が欲しいという話になっています。</p>
<pre class="source" title="Range を使った区間の切り出し">
<code><span class="reserved">int</span>[] array = <span class="reserved">new</span>[] { 1, 2, 3, 4, 5, 6, 7 };
<span class="type">Span</span>&lt;<span class="reserved">int</span>&gt; span = array[1..3];
</code></pre>
<p>ちなみに、現状、この機能は C# 8.0 での実現を目指しています。</p>
<h2>indexing/slicing 用途</h2>
<p>C# チームとしては、前節のような書き方、つまり、<code>[]</code> の中身として使って(= indexing)、配列の一部分を切り出す(= slicing)のを当面の目標に据えたいそうです。</p>
<p>例えば他の用途として、「Range パターン」、要するに、パターン マッチングのパターンの種類として以下のような書き方を認めたいという話もありますが、これはindexingの「次の段階」として考えたい様子。</p>
<pre class="source" title="Range パターン">
<code><span class="reserved">switch</span> (n)
{
    <span class="reserved">case</span> 1..3:
    <span class="reserved">case</span> 5..8:
        <span class="comment">// ...</span>
}
</code></pre>
<p>「次の段階」としては、おそらく「ユーザー定義の Range 演算子」を認めて、任意の型に対して <code>..</code> なりなんなりの Range を作れるようにすることになると思います。
しかし、まずは indexing を中心として構文を検討していきたいとのこと。</p>
<h2>inclusive/exclusive</h2>
<p>先ほど「<code>1..3</code>で1～3の範囲を表す」と言いましたが、1点不明瞭なまま説明を端折った点があります。
両端の数字、この例の場合だと1と3は範囲に含むのか(inclusive)、含まないのか(exclusive)です。</p>
<p>数学だとこれらを明確に区別する記法があったりします。(a, b)みたいに丸括弧を使うとexclusive、[a, b]みたいに四角括弧を使うとinclusive。
組み合わせもあって、(a, b]ならaは含まずbは含む、[a, b)ならaは含んでbは含まない、となります。</p>
<p><img src="/media/1161/mathranges.png" alt="inclusive/exclusive" /></p>
<p>整数だけだと、「1～3 (3は含まない)」と「1～2 (2を含む)」みたいに、±1すれば同じ意味のRangeを作れます。
しかし、将来、ユーザー定義 Range を認めたいわけで、浮動小数点数とかのことも考えないといけません。
浮動小数点数だと「1～3 (3は含まない)」と「1～2 (2を含む)」の意味が全然違うものになります。</p>
<p>他のプログラミング言語だと、<code>..&lt;</code>なら含まない、<code>..=</code>なら含む、見たいに、何らかの弁別のための記号を用意していたりします。
毎度<code>..&lt;</code>とか書くのも面倒なので、「よく使う方」と思うものを単に<code>..</code>と書いて、そうでないものに<code>..=</code>みたいな3文字の記号を割り当てたりもします。</p>
<p>あと、気を付けないといけないのが、言語構文的にinclusive/exclusiveの両方を用意したとして、内部表現はどうすべきか。
例えば、「どちらの構文で書くにしても、内部的には最小値をinclusive、最大値をexclusiveで持つ」と決めたとしましょう。</p>
<pre class="source" title="">
<code><span class="reserved">struct</span> <span class="type">Range</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> MinInclusive;
    <span class="reserved">public</span> <span class="reserved">int</span> MaxExclusive;

    <span class="reserved">public</span> Range(<span class="reserved">int</span> minInclusive, <span class="reserved">int</span> maxExclusive)
    {
        MinInclusive = minInclusive;
        MaxExclusive = maxExclusive;
    }
}
</code></pre>
<pre class="source" title="">
<code><span class="comment">構文は仮。C#がこれを採用するとは限らない</span>
<span class="reserved">var</span> inclusive = 1..=3; <span class="comment">// new Range(1, 3) の意味</span>
<span class="reserved">var</span> exclusive = 1..&lt;3; <span class="comment">// new Range(1, 2) の意味</span>
</code></pre>
<p>このとき、じゃあ、「0～<code>int</code>の最大値(inclusive)」は表せなくなります。</p>
<pre class="source" title="">
<code><span class="reserved">var</span> inclusive = 1..=<span class="reserved">int</span>.MaxValue;
<span class="comment">// new Range(1, int.MaxValue + 1) の意味</span>
<span class="comment">// = オーバーフローして new Range(1, int.MinValue) になる</span>
</code></pre>
<p>Swift ではこの問題の対処として、inclusiveなRangesとexclusiveなRangesを別の型にしたんでしたっけ。それも後からの、破壊的変更で。</p>
<h3>indexing 用途に絞って</h3>
<p>何にしても、とりあえず、用途は広く考えるほどはまりどころは増えます。
C# チームが「まずは indexing 用途に絞って検討したい」としているのもそのためです。
では、その indexing 用途だとどうか。</p>
<p>まあ、この用途だと大半は「最小値がinclusive、最大値がexclusive」です。</p>
<pre class="source" title="">
<code><span class="comment">// 配列の列挙でよく書くのは &lt; Length</span>
<span class="comment">// 要するに最大値は exclusive</span>
<span class="comment">// inclusive だと Length - 1 になってちょっと面倒</span>
<span class="reserved">for</span> (<span class="reserved">int</span> i = 0; i &lt; array.Length; i++)
{
}

<span class="reserved">var</span> r = <span class="reserved">new</span> Random();
r.Next(0, 100); <span class="comment">// こう書いた場合 100 は含まない</span>

<span class="comment">// この 100 も exclusive</span>
Parallel.For(0, 100, i =&gt;
{
});
</code></pre>
<p>なので、おそらく、C# で単に<code>a..b</code>と書くと、「a～b ただしaは含んでbは含まない」になると思われます。
最大値もinclusiveな方は、例えば<code>..:</code>とか<code>.:</code>が使えるかもしれません。</p>
<p>ちなみに、indexing 用途であれば、「負のインデックス」は考えないでいいかもしれません。
そうなると、例えば先ほど言った「inclusiveかexclusiveかを型を変えるなどして弁別できないといけない」とか、
後述する unbounded や starting/length などの表現も、1つの型で、負数の領域をフラグ的に使って弁別するとかできるかもしれません
(別途フラグ用のフィールドを持たないでいいので、構造体がコンパクトになるというメリットあり)。</p>
<h3>: (コロン)の利用</h3>
<p><code>.:</code> みたいなのを使う上で、<code>.</code>も<code>:</code>も別の文法と混ざりやすくて、コンパイラーが区別できる構文が限られたりします。</p>
<ul>
<li><code>.</code> → <code>.1</code> みたいな書き方で <code>0.1</code> を表せる</li>
<li><code>:</code> → 条件演算子 <code>?:</code>、名前付き引数 <code>引数名: 値</code>、<a href="http://ufcpp.net/study/csharp/st_string.html#multi-line">文字列補完</a>の書式 <code>{値:書式}</code></li>
</ul>
<p>例えば <code>flag ? 1:.2:.3</code>とかは、<code>flag ? (1:.2) : (.3)</code> と <code>flag ? (1) : (.2:.3)</code> で不明瞭になったりします。
<code>.:</code> の 方は行けそうなんですが、<code>:.</code> がダメそうという。
同様の理由で、<code>.&lt;</code>は行けても <code>&gt;.</code> はダメそう。</p>
<p>この辺り、Swift の「単項演算子は <code>+x</code> みたいに演算子と変数が密着してないとダメ」「2項演算子は <code>x + y</code> みたいに演算子と変数の間にスペースが必須」みたいな文法は結構良い割り切りだったかもしれないです。</p>
<p>他に、C# は<code>::</code>っていう記号も既存の文法で使っちゃってるんですが、<a href="http://ufcpp.net/study/csharp/sp_namespace.html#extern">外部エイリアス</a>っていうめったに使わない機能です。
これの両辺は今のところ名前空間しか出てこないはずなので、Rangesとはセマンティック的に弁別できそうとのこと。</p>
<h2>starting/length</h2>
<p>配列などの一部分を切り出すとき、両端を指定して切り出す他に、「a番目の要素(starting index)からb要素(length)切り出す」という方法も考えられます。</p>
<pre class="source" title="">
<code><span class="reserved">var</span> sub = <span class="string">"abcdefghijklmn"</span>.Substring(2, 4); <span class="comment">// 2番目から4文字 = cdef</span>

<span class="reserved">byte</span>[] buffer = <span class="reserved">new</span> <span class="reserved">byte</span>[10];
Stream s = File.OpenRead(<span class="string">"a.txt"</span>);
s.Read(buffer, 2, 4); <span class="comment">// buffer の2番目から4バイトに書き込み</span>
</code></pre>
<p>ということで、min/max 版の Range の他に、starting/length 版の Range も欲しいという話になります。
C# チームが例に挙げたのだと以下のような構文がありました。</p>
<pre class="source" title="">
<code><span class="reserved">var</span> r1 = 2..4; <span class="comment">// min/max (exlusive) = 2, 3 の意味</span>
<span class="reserved">var</span> r2 = 2..+4; <span class="comment">// stating/length = 2, 3, 4, 5 の意味</span>
</code></pre>
<p>これだと、ユーザー定義の<code>..</code>演算子を認めたときに、「<code>2</code>と<code>4</code>に対する<code>..</code>」と「<code>2</code>と<code>+4</code>に対する<code>..</code>」で意味が違うってことになるのでかなり気持ち悪い構文になりますが…
まあ、何にしても、何らかの構文は求められています。</p>
<h2>空 Range</h2>
<p>長さ0の Range の扱いはどうあるべきかという話も。</p>
<p>例えば、Range と似たような話で、LINQ の <code>.Skip(a).Take(b)</code> を考えてみます。
「a 番目から長さ b」という意味では前節の starting/length 版の Range と似たようなものになります。
これで、長さ0のシーケンスを2つ比較すると、常に一致扱いになります。</p>
<pre class="source" title="">
<code><span class="reserved">var</span> array = <span class="reserved">new</span>[] { 1, 2, 3, 4, 5 }; <span class="comment">// 値は何でも</span>

<span class="comment">// 開始地点は違うけども、長さ 0 のシーケンスを作る</span>
<span class="comment">// それを比較すると、開始地点によらず常に一致扱い</span>
<span class="reserved">var</span> e = <span class="type">Enumerable</span>.SequenceEqual(
    array.Skip(1).Take(0),
    array.Skip(2).Take(0));
</code></pre>
<p>であれば、<code>1..+0</code>と<code>2..+0</code>は同じと思うべきなのかどうか。
これに対しては、一応以下のように、開始インデックスの範囲チェックは掛かるべきなので、別扱いすべきだろうとのことです。</p>
<pre class="source" title="">
<code><span class="reserved">var</span> array = <span class="reserved">new</span>[] { 1, 2, 3, 4, 5 }; <span class="comment">// 値は何でも</span>

<span class="reserved">var</span> r1 = array[1..0]; <span class="comment">// OK</span>
<span class="reserved">var</span> r2 = array[10..0]; <span class="comment">// OutOfRange</span>
</code></pre>
<h2>bounded/unbounded</h2>
<p>indexing 用途を考えた場合、具体的な数値を伴った<code>a..b</code>以外に、以下のようなものが欲しくなったりします。</p>
<ul>
<li><code>..a</code> → 最初から a 番目まで</li>
<li><code>a..</code> → a 番目から最後まで</li>
<li><code>..</code> → 最初から最後まで</li>
</ul>
<p>端の値が決まっている(bounded: 有界)か、決まっていない(unbounded)か。
例えば、行列とかテンソルとかのデータ構造から「1次元目は全て、2次元目は1～3行目を切り出したい」というとき、
<code>matrix[.., 1..3]</code> というような書き方が考えられます。</p>
<h2>末尾から n 番目</h2>
<p>indexing用途で他によくあるのが、「末尾から n 番目」、「配列長 - n 個」の類です。これに対しても、仮に、以下のような構文を挙げています。</p>
<ul>
<li>案1: <code>-n</code>みたいにマイナスを付けて「末尾から n 番目」を表す</li>
<li>案2: <code>^n</code>みたいに、インデックス専用の新演算子を用意して「末尾から n 番目」を表す</li>
<li><code>+^n</code> みたいに、さらに <code>+</code> を付けると「配列長 - n 個」の意味</li>
</ul>
<p>例えば、「最初と最後の1要素ずつ削る」みたいなことをしたければ<code>array[1..-1]</code>でどうか、と言うことになります。</p>
<h2>Index 型</h2>
<p>前節で<code>^n</code>みたいな「インデックス用演算子」を考えたわけですが、であれば、Range 型(両端を持つ)だけじゃなくて、いっそ Index 型(1要素だけを指すためのインデックス)もあってもいいのではないかという話になります。</p>
<p>例えば、<code>array[^1]</code>で、末尾から1番目、すなわち<code>array[array.Length - 1]</code>を表そうということです。
そして、ここまで話してきた「indexing 用途の Range 型」はあくまで、「Index 型の2つの値に対して <code>..</code> 演算子を適用したもの」ということになります。</p>
<h2>natural type</h2>
<p><code>1..3</code>とか書いた時、これの「自然な型」は考えるべきかどうか。</p>
<p>例えば、C#にはいくつか、「左辺の型によって意味が変わる構文」というものがいくつかあります。</p>
<pre class="source" title="">
<code><span class="comment">// ラムダ式: デリゲートと式ツリー</span>
<span class="type">Func</span>&lt;<span class="reserved">int</span>, <span class="reserved">bool</span>&gt; f = x =&gt; x &gt; 0;
<span class="type">Predicate</span>&lt;<span class="reserved">int</span>&gt; p = x =&gt; x &gt; 0;  <span class="comment">// シグネチャが同じでも Func とは別の型</span>
<span class="type">Expression</span>&lt;<span class="type">Func</span>&lt;<span class="reserved">int</span>, <span class="reserved">bool</span>&gt;&gt; ex = x =&gt; x &gt; 0;

<span class="comment">// 文字列補完: string と FormattableString</span>
<span class="reserved">int</span> a = 1, b = 2;
<span class="reserved">string</span> s = <span class="string">$"a: </span>{a}<span class="string">, b: </span>{b}<span class="string">"</span>;
<span class="type">FormattableString</span> fs = <span class="string">$"a: </span>{a}<span class="string">, b: </span>{b}<span class="string">"</span>;
</code></pre>
<p>前節で言ったように、indexing用途の Range の場合は、Index 型の組み合わせだと考えた方がいいかもしれません。
とはいえ、<code>(Index)1..(Index)3</code>みたいな書き方はしたくないでしょう。
ラムダ式のように、左辺から決定するのもありかもしれません。</p>
<pre class="source" title="">
<code><span class="type">Range</span> indexingRange = 1..3; // indexing用
<span class="type">IntRange</span> intRange = 1..3; // 「末尾から」とかみたいな妙な仕組みを持ってない単なる整数の範囲
</code></pre>
<p>とはいえ、ラムダ式に対してよくある不満として、<code>var</code>やジェネリクスでの型推論が効かないという問題もあります。</p>
<pre class="source" title="">
<code><span class="comment">// エラー。ラムダ式は左辺の型がないと型が決まらない</span>
<span class="reserved">var</span> f = x =&gt; x &gt; 0;

<span class="comment">// こっちはOK。特に指定がない場合、自動的に string 扱い</span>
<span class="reserved">var</span> s = <span class="string">$"a: </span>{a}<span class="string">, b: </span>{b}<span class="string">"</span>;

<span class="comment">// Range はどうあるべき？暗黙的に indexing 用の Range 型？</span>
<span class="reserved">var</span> r = 1..3;
</code></pre>
<p>ということで、Range はどうあるべきでしょう。
ラムダ式の例を見ての通り、自動的に特定の「<code>Range</code> 型」に推論される(<code>1..3</code> にとって自然な型は<code>Range</code>型であるとする)方が使い勝手はいいです。
一方、それをやってしまうと、その特定の <code>Range</code>型に C# が依存してしまうことになります。</p>
<h2>まとめ</h2>
<p>「a～bまでの範囲」みたいなのを表すRange型は、結構いろんな言語にあります。
なのでそんなに迷うものでもないかと思ったら、案外検討事項がたくさん出ています。</p>
<ul>
<li>inclusive/exclusive 問題</li>
<li>unbound な Range</li>
<li>max/min 版と starting/length 版</li>
<li>空 Range の扱い</li>
<li>「末尾から」</li>
<li>Index 型</li>
<li>演算子を何にするか(特に inclusive/exclusive の弁別のために複数の記号が必要)</li>
<li>ある特定の <code>Range</code>型を「自然な型」として採用すべきか</li>
</ul>
<p>今のところは indexing 用途に絞って、<code>a..b</code> と書いて「a要素目(inclusive)からb要素目(exclusive)まで」の意味で使うというような構文になる可能性がたかいです。
将来的には任意の用途・任意の型に対するユーザー定義 Range が提供される予定です。</p>
<p>現状、C# 8.0での実装を目標にしているみたいですが、
検討が始まったの割と最近ですし、この通りの検討項目の多さなので、もしかするともっと時間が掛かるかもしれません。</p>
 ]]></description>
				<pubDate>Sat, 24 Mar 2018 02:25:36 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 3/23: no-allocation非同期メソッド、最近の Utf8String</title>
				<link>http://ufcpp.net/blog/2018/3/pickuproslyn0323/</link>
				<description><![CDATA[ <p><a href="http://ufcpp.net/blog/2018/3/pickuproslyn0321/">昨日のDesign Notes祭り</a>とはまた別件なんですが、こんな提案が。</p>
<h2>メソッド単位でAsyncMethodBuilder属性</h2>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/1407">Proposal: Allow [AsyncMethodBuilder(...)] on methods #1407</a></li>
</ul>
<p><a href="https://github.com/dotnet/corefx/">corefx</a>/<a href="https://github.com/dotnet/coreclr/">coreclr</a>方面でガッチガチのパフォーマンス改善をやりまくってる人からの提案。</p>
<p>タイトルからは内容がちょっとわかりにくいんですが、非同期メソッドの際に必要になるヒープ確保量を0 (no-allocation)にするためにこの機能が必要とのこと。</p>
<p>背景としては、</p>
<ul>
<li>C# 6.0: 非同期メソッドの戻り値は常に<code>Task</code> → <code>Task</code> のヒープ確保が必須でつらい → C# 7.0: <a href="http://ufcpp.net/study/csharp/sp5_async.html#task-like"><code>ValueTask&lt;T&gt;</code>を認めた</a>よ</li>
<li><code>ValueTask&lt;T&gt;</code>、同期で終わるときにはヒープ確保0だけど、実際に非同期だとどうしても<code>Task</code>が発生 → <a href="https://github.com/dotnet/coreclr/pull/16618">最近Mergeされたコミット</a>: <code>IValueTaskSource</code>ってインターフェイスを使うことで、<code>Task</code>を介さず非同期処理できるようにしたよ。うまく使えば<code>Task</code>分のヒープ確保がなくなる</li>
<li><code>IValueTaskSource</code>で、<code>await</code>毎のヒープ確保はなくせるけども、AsyncStateMachine の1インスタンスはどうしても残った → そのインスタンスをキャッシュして持ちたい</li>
</ul>
<p>という感じ。</p>
<p>最終的に、ヒープ確保せざるを得ないインスタンスをキャッシュして、プログラム中で1個だけ(メソッド呼び出しのたびには新規ヒープ確保しない)とかにしたいわけですけども、キャッシュはうまくやらないと効率が悪くて困ることになります。</p>
<p>なので、メソッド単位でどういう非同期メソッド生成するかをカスタマイズできたり、AsyncStateMachine に<code>this</code>を渡せたりしないとこれ以上の最適化が厳しいみたいで、やっと提案のタイトルにつながります。</p>
<p><code>AsyncMethodBuilder</code>属性をメソッド単位で指定して、メソッドごとに非同期メソッドの挙動をカスタマイズできるようにしたいっていう話は昔からあったんですけども、需要が低いということで実装されずにいたんですけども。
こういう方面から改めて需要が出てくるとは…</p>
<h2>UTF8文字列がらみ</h2>
<ul>
<li><a href="https://github.com/dotnet/corefx/issues/24093#issuecomment-375300540">Introducing System.Rune #24093 (Comment)</a></li>
</ul>
<p>去年の9月くらいに<a href="http://ufcpp.net/blog/2017/12/fastutf8string/">Go (Unicode Code Point のことを rune って呼んでる)に倣って Rune 型を作らない？</a>みたいな提案が立っていましたが。
Rune って名前の評判悪すぎて、まあ、別の名前に落ち着きそう。</p>
<p>あと、C# のキーワードも用意したいみたいです。</p>
<table>
<thead>
<tr>
	<th>C# キーワード</th>
	<th>実際の型名</th>
	<th>サイズ(Byte)</th>
	<th>概要</th>
</tr>
</thead>
<tbody>
<tr>
	<td><code>ubyte</code></td>
	<td><code>System.CodeUnit</code></td>
	<td>1</td>
	<td>UTF-8エンコーディングされてる文字列の1バイト1バイト</td>
</tr>
<tr>
	<td><code>uchar</code></td>
	<td><code>System.CodePoint</code></td>
	<td>4</td>
	<td>Unicode のコードポイント</td>
</tr>
<tr>
	<td><code>ustring</code></td>
	<td><code>System.Utf8String</code></td>
	<td></td>
	<td>内部的に UTF-8 でデータを持つ文字列クラス</td>
</tr>
<tr>
	<td><code>uspan</code></td>
	<td><code>System.Utf8Span</code></td>
	<td></td>
	<td><code>ReadOnlySpan&lt;ubyte&gt;</code>で、<code>ustring</code>の一定区間を参照する構造体</td>
</tr>
</tbody>
</table>
<p>まあまだ正式な API の提案になってる段階ではないので、まだ変わると思いますが。</p>
 ]]></description>
				<pubDate>Fri, 23 Mar 2018 00:36:34 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 3/21: Design Notes一斉アップロード祭り</title>
				<link>http://ufcpp.net/blog/2018/3/pickuproslyn0321/</link>
				<description><![CDATA[ <p>昨日なんですけども、2018年に入ってからのC# Language Design Meetingの議事録(design notes)が一斉にアップロードされました。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/tree/master/meetings/2018">C# Language Design Notes for 2018</a></li>
</ul>
<p>読むの大変だった… 春分の日でよかった…</p>
<p>一通りなんとなくは目を通したんですけど、ブログ1回の内容じゃなさすぎるので、少しずつネタにしていこうかと。</p>
<h2>ここ数時の状況</h2>
<p>2週間前に<a href="http://ufcpp.net/blog/2018/3/vs15_6/">Visual Studio 15.6が正式リリース</a>されて、
その後ほどなくして15.7のプレビュー1もリリースされたわけですけども。</p>
<p>このプレビュー1の時点では 15.7 に C# 7.3 は入っていなかったわけですけども、
<a href="https://github.com/dotnet/roslyn/milestone/32">roslynリポジトリの15.7マイルストーン</a>を見るとだいぶC# 7.3がらみの作業がマージされている状況です。
作業進捗を表す<a href="https://github.com/dotnet/roslyn/blob/master/docs/Language%20Feature%20Status.md">Language Feature Status</a>のページもつい5日前に更新されて、C# 7.3のところの大半の機能が Merged になりました。</p>
<p>要するに、15.7向けのC# 7.3の最低限の作業が完了したんでしょうね。
あとは正式リリースに向けてバグ出し・バグ修正するフェーズに。
おそらく近々15.7プレビューにC# 7.3対応が来るのではないかと思われます。</p>
<p>ちなみに、<a href="https://dotnet.myget.org/gallery/roslyn">roslynのナイトリービルド</a>に挙がっているVSIXやNuGetパッケージをインストールすれば、<a href="https://gist.github.com/ufcpp/b4b505077f589235afb169652e10ee8d">結構ちゃんとC# 7.3が使えていました</a>。</p>
<p>そして、作業が落ち着いたタイミングで毎度やってくる「一斉投稿」が昨日来たと…</p>
<h2>最近採用が決まった提案</h2>
<p>とりあえず今日はこの話題のみ。
<a href="https://github.com/dotnet/csharplang/blob/master/meetings/2018/LDM-2018-03-19.md">3/19のDesign Note</a>で今後取り組む作業の選別をしたようで、
いろんな提案issueが新たにChampioned(将来取り組むこと自体は決定)に昇格しています。</p>
<p>取り組み時期はたいてい「8.X」。「8.0ですらなくさらにその後」という意味で、実際のところ「未定」と大差ないやつです。
そんな状態のものなので、具体的な文法はこれからまだだいぶ変わると思います。</p>
<h3>default in deconstruction</h3>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/1394">Champion: allow 'default' in deconstruction #1394</a></li>
</ul>
<p>↓みたいな書き方を認めてほしいというもの。</p>
<pre class="source" title="">
<code><span class="reserved">int</span> x;
<span class="reserved">int</span> y;
(x, y) = <span class="reserved">default</span>; <span class="comment">// x = default; y = default; と同じ意味</span>
</code></pre>
<h3>and, or, and not パターン</h3>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/1350">Champion &quot;and, or, and not patterns&quot; #1350</a></li>
</ul>
<p>↓みたいに、パターン マッチングで条件のところに and, or, not を書けるようにしたいとのこと。</p>
<pre class="source" title="">
<code><span class="reserved">switch</span> (o)
{
    <span class="reserved">case</span> 1 <span class="reserved">or</span> 2:
    <span class="reserved">case</span> <span class="type">Point</span>(0, 0) <span class="reserved">or</span> <span class="reserved">null</span>:
    <span class="reserved">case</span> <span class="type">Point</span>(<span class="reserved">var</span> x, <span class="reserved">var</span> y) <span class="reserved">and var</span> p:
    <span class="reserved">case</span> <span class="reserved">not</span> <span class="reserved">string</span> _:
}
</code></pre>
<h3>型引数の部分的な型推論</h3>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/1349">Champion: &quot;Partial Type Inference&quot; #1349</a></li>
</ul>
<p>いくつか文法案は出ているものの、そのうちの1つで書くと、↓みたいな感じ。</p>
<pre class="source" title="">
<code>M&lt;<span class="reserved">int</span>, &gt;(args); <span class="comment">// 2個目の型引数だけは args から推論できて、1個目は無理な時、こう書けるようにしたい</span>
</code></pre>
<h3>制約なしの型引数に対して is null を認めたい</h3>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/1284">Champion &quot;permit <code>t is null</code> for unconstrained type parameter&quot; #1284</a></li>
</ul>
<p>ちょっと説明しにくいんですけど、以下のような感じ。<code>where T : class</code>なしの<code>T t</code>に対して、<code>t is null</code>を認めたい。</p>
<pre class="source" title="">
<code><span class="reserved">void</span> M(<span class="reserved">string</span> s)
{
    <span class="reserved">if</span> (s <span class="reserved">is</span> <span class="reserved">null</span>) { } <span class="comment">// OK。クラスだし、null チェックしたい</span>
}

<span class="reserved">void</span> M(<span class="reserved">int</span> x)
{
    <span class="reserved">if</span> (x == <span class="reserved">null</span>) { } <span class="comment">// 警告は出るけど別にエラーにはならない。常にfalse</span>
    <span class="comment">// ↑あんまり良い話ではないけど、default とかジェネリクスがなかった頃の名残っぽい</span>
}

<span class="reserved">void</span> M1&lt;<span class="type">T</span>&gt;(<span class="type">T</span> t)
    <span class="reserved">where</span> <span class="type">T</span> : <span class="reserved">class</span>
{
    <span class="reserved">if</span> (t <span class="reserved">is</span> <span class="reserved">null</span>) { } <span class="comment">// OK。クラス制約あるし。</span>
}

<span class="reserved">void</span> M2&lt;<span class="type">T</span>&gt;(<span class="type">T</span> t)
{
    <span class="reserved">if</span> (t <span class="reserved">is</span> <span class="reserved">null</span>) { } <span class="comment">// 今は NG。</span>
    <span class="comment">// とはいえ、構造体の == null が OK なんだから別にこれも認めていいでしょ。常にfalseで</span>
}
</code></pre>
<h3>暗黙的なスコープのusingステートメント</h3>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/1174">Champion &quot;Implicitly scoped using statement&quot; #1174</a></li>
</ul>
<p>以下のような、<code>using</code>したいリソースがたくさんあるときのネスト問題への対処。</p>
<pre class="source" title="">
<code><span class="reserved">using</span> (<span class="reserved">var</span> d = SomeDisposable())
{
    <span class="comment">// ここのネストが1段深くなるのがしんどい時がある</span>
}

<span class="comment">// 特に、多段の時。最後の1個以外は {} を省略できるとはいえ</span>
<span class="reserved">using</span> (<span class="reserved">var</span> d1 = SomeDisposable())
<span class="reserved">using</span> (<span class="reserved">var</span> d2 = SomeDisposable())
<span class="reserved">using</span> (<span class="reserved">var</span> d3 = SomeDisposable())
<span class="reserved">using</span> (<span class="reserved">var</span> d4 = SomeDisposable())
<span class="reserved">using</span> (<span class="reserved">var</span> d5 = SomeDisposable())
{
}
</code></pre>
<p>以下のような書き方を予定。</p>
<pre class="source" title="">
<code>{
    <span class="comment">// 変数宣言の前に using を付けることで、その変数のスコープを using のスコープにする</span>
    <span class="reserved">using</span> <span class="reserved">var</span> d1 = SomeDisposable();
    <span class="reserved">using</span> <span class="reserved">var</span> d2 = SomeDisposable();
    <span class="reserved">using</span> <span class="reserved">var</span> d3 = SomeDisposable();
    <span class="reserved">using</span> <span class="reserved">var</span> d4 = SomeDisposable();
    <span class="reserved">using</span> <span class="reserved">var</span> d5 = SomeDisposable();

    <span class="comment">// Dispose が走るのは、変数がスコープを抜ける時</span>
    <span class="comment">// = このブロックから抜けるとき</span>
}
</code></pre>
<h3>defer ステートメント</h3>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/1398">Champion &quot;defer statement&quot; #1398</a></li>
</ul>
<p>Swift にあるやつ。</p>
<pre class="source" title="">
<code><span class="reserved">static</span> <span class="reserved">void</span> Main()
{
    <span class="reserved">defer</span>
    {
        <span class="type">Console</span>.WriteLine(<span class="string">"関数を抜ける時に呼ばれる"</span>); <span class="comment">// 例外があっても常に</span>
    }

    <span class="type">Console</span>.WriteLine(<span class="string">"こっちの方が先に表示される"</span>);
}
</code></pre>
<p>「一回り外側のブロックに影響する」っていう点が気持ち悪くて据え置きになっていたんですが…
前節の<code>using var</code>を認めてしまった以上、それを理由にリジェクトできなくなった感じ。</p>
<p>前節の<code>using var</code>を使って、以下のように代用できないこともないんですが、
これだとラムダ式のオーバーヘッド(デリゲートのヒープ確保とインライン展開の阻害)が掛かるのが嫌だそうです。</p>
<pre class="source" title="">
<code>    <span class="reserved">using</span> <span class="reserved">var</span> d = <span class="reserved">new</span> <span class="type">ActionDisposable</span>(() =&gt;
    {
        <span class="type">Console</span>.WriteLine(<span class="string">"関数を抜ける時に呼ばれる"</span>);
    });

    <span class="type">Console</span>.WriteLine(<span class="string">"こっちの方が先に表示される"</span>);
</code></pre>
<h3>ユーザー定義の位置指定パターン(positional patterns)</h3>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/1047">Champion &quot;User-defined Positional Patterns&quot; #1047</a></li>
</ul>
<p><a href="https://github.com/dotnet/csharplang/blob/master/proposals/patterns.md">パターン マッチング</a>、C# 7.0時点では「型パターン」とか「定数パターン」とか、一部分だけが実装されました。
残りの大部分は、現状、C# 8.0で提供する予定になっています。</p>
<p>そんな中、さらに C# 8.0からも外れて「8.X」にしようという風に外されたのがこいつ。</p>
<pre class="source" title="">
<code><span class="reserved">struct</span> <span class="type">Cartesian</span>
{
    <span class="reserved">public</span> <span class="reserved">double</span> X;
    <span class="reserved">public</span> <span class="reserved">double</span> Y;
    <span class="reserved">public</span> Cartesian(<span class="reserved">double</span> x, <span class="reserved">double</span> y) =&gt; (X, Y) = (x, y);

    <span class="comment">// こいつを使った positional パターンは C# 8.0 で入る予定</span>
    <span class="reserved">public</span> <span class="reserved">void</span> Deconstruct(<span class="reserved">out</span> <span class="reserved">double</span> x, <span class="reserved">out</span> <span class="reserved">double</span> y) =&gt; (x, y) = (X, Y);
}

<span class="reserved">class</span> <span class="type">Polar</span>
{
    <span class="comment">// こんな感じの定義を書くことで、Cartesian p を p is Polar(var r, var t) みたいなパターンに掛けることができる仕様がある</span>
    <span class="comment">// が、こいつは C# 8.0 では入らない</span>
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">bool</span> <span class="reserved">operator</span> <span class="reserved">is</span>(<span class="type">Cartesian</span> p, <span class="reserved">out</span> <span class="reserved">double</span> radius, <span class="reserved">out</span> <span class="reserved">double</span> theta)
    {
        radius = <span class="type">Math</span>.Sqrt(p.X * p.X + p.Y * p.Y);
        theta = <span class="type">Math</span>.Atan2(p.Y, p.X);
    }
}
</code></pre> ]]></description>
				<pubDate>Thu, 22 Mar 2018 00:13:56 +0900</pubDate>
			</item>
			<item>
				<title>.NET Core 2.1 の JIT 最適化の話</title>
				<link>http://ufcpp.net/blog/2018/3/jitoptimization2_1/</link>
				<description><![CDATA[ <h2>唐突ですが問題</h2>
<p>とある構造体、例えば以下のようなものがあったとします。</p>
<pre class="source">
<code><span class="reserved">struct</span> <span class="type">X</span> : IDisposable
{
    <span class="reserved">public</span> <span class="reserved">bool</span> IsDisposed;
    <span class="reserved">void</span> IDisposable.Dispose() =&gt; IsDisposed = <span class="reserved">true</span>;
}
</code></pre>
<p>この構造体 <code>X</code> の <code>Dispose</code> メソッドを呼び出すにあたって、
以下の3つのうち、一番高速なのはどれでしょう。</p>
<pre class="source">
<code>    <span class="comment">// (1) インターフェイス引数で受け取って呼ぶ</span>
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> Interface(IDisposable x) =&gt; x.Dispose();

    <span class="comment">// (2) X のまま受け取って、メソッド内でインターフェイスにキャストして呼ぶ</span>
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> NonGeneric(X x) =&gt; ((IDisposable)x).Dispose();

    <span class="comment">// (3) ジェネリックなメソッドで受け取って呼ぶ</span>
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> Generic&lt;<span class="type">T</span>&gt;(T x) <span class="reserved">where</span> T : IDisposable =&gt; x.Dispose();
</code></pre>
<h2>解答</h2>
<p>基本的に、というか、これまでは、(3) が最速です。</p>
<p>(1) は、構造体のインスタンスを引数に渡そうとした時点で<a href="/study/csharp/RmBoxing.html#boxing">ボックス化</a>が発生。
ヒープ確保と値のコピーが発生するので、結構な遅さになります。</p>
<p>(2) は、結局<code>((IDisposable)x)</code>と書いた時点でボックス化が発生するので、(1)と大差ない速度になっていました。
過去形なのは、.NET Core 2.1でこいつに関する最適化が入ったみたいで、これが実は今日の本題。</p>
<p>(3) だと、ボックス化は発生しません。
.NET の<a href="http://ufcpp.net/study/csharp/sp2_generics.html">ジェネリクス</a>は構造体に対しては型1つ1つに対してそれぞれメソッドを展開するような最適化を行います。
そんな大変なことをやる設計にしたのは、こういうボックス化を避けるためです。
大変なことした甲斐あって、(1)の数倍高速です。
(手元で取ったベンチマークだと6倍くらい高速。)</p>
<p>ベンチマークはGistに置いてあります:</p>
<ul>
<li><a href="https://gist.github.com/ufcpp/fef52f31e11e0bb11ccbd22638e2dfc0">構造体のインターフェイス明示的実装の devirtualize 問題</a></li>
</ul>
<h2>devirtualize最適化</h2>
<p>すでに少し触れていますが、この(2)が、.NET Core 2.1で実行すると(3)と同程度の速度が出るようになったみたいです。</p>
<p>要するに、ジェネリックなメソッドの時にやっているのと同じような最適化を、単に<code>((IDispose)x)</code>と書いた時にも行うようになったみたいです。</p>
<ul>
<li><a href="https://github.com/dotnet/coreclr/pull/14698">JIT: after devirtualization try undoing box and invoking unboxed entry #14698</a></li>
</ul>
<p>devirtualize (脱・仮想化)ってのは、要は、「<code>Dispose</code>は仮想メソッドだから本来は仮想呼び出しされるべき。それを、直接的な呼び出しに戻す」と言うような感じ。
構造体に対してこれが効くと、単に仮想呼び出しのコストがなくなるだけじゃなくて、
ボックス化自体が消滅する(結果、ヒープ確保がなくなる)ので、相当効果の大きい最適化になります。</p>
<h3>また「ref」を忘れてる…</h3>
<p>Merge 日時を見ての通り、まあ、結構前からだったみたいなんですけども。
気付いたのは、以下のプルリクを見て。</p>
<ul>
<li><a href="https://github.com/dotnet/coreclr/pull/17006">JIT: remove boxing for interface call to shared generic struct #17006</a></li>
</ul>
<p>どうも、値渡しの時にしか上記の最適化が効いていなくて、「参照渡しでも同じこと効くようにしないとダメだろ」っていう不具合報告が入ったみたいでして。</p>
<pre class="source">
<code>    <span class="comment">// これは devirtualize される(去年の10月から)</span>
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> NonGeneric(X x) =&gt; ((IDisposable)x).Dispose();
    <span class="comment">// これは devirtualize し忘れてた(今出てるプルリクで治る)</span>
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> NonGeneric(<span class="reserved">ref</span> X x) =&gt; ((IDisposable)x).Dispose();
</code></pre>
<p><a href="http://ufcpp.net/study/csharp/sp_ref.html#sec-byref">ref</a> がらみ、
「動作確認が漏れてて後から気付いて修正」みたいなのかなり多いんですよねぇ…</p>
<h3>そういうとこだぞ</h3>
<p>ジェネリックな場合に対してこの最適化が掛かっていたのを見ての通り、
この devirtualize っていう手法は大昔から知られている最適化です。
が、まあ、.NET はなんか「JITが頑張らなくてもジェネリクス使えば速いよ？」(実際、ちゃんと書けばほんとに速い)みたいなところがありまして。
JIT は案外さぼってることが結構ありました。</p>
<p>.NET Core 2.1 だと、JIT でも頑張ろうという感じの動きが結構見られます。</p>
<p>もちろんその分、JIT 自体が遅くなったりはするんですが…
そこは、.NET にも <a href="http://mattwarren.org/2017/12/15/How-does-.NET-JIT-a-method-and-Tiered-Compilation/">Tiered JIT</a> (Java でいう<a href="https://ja.wikipedia.org/wiki/HotSpot">HotSpot</a>みたいな、段階最適化)を導入することにしたみたいです。</p>
<p>ちなみに、JIT が頑張れば必ず速くなるってものでもないんですけども。
<a href="http://ufcpp.net/blog/2016/12/tipssmallheapallocation/">Escape Analysis</a>みたいに、「.NET だと構造体を使うのが普通で、JIT が頑張る余地が大して残らない」、「頑張った分のコストでかえって損」的なこともあり得たりします。</p>
 ]]></description>
				<pubDate>Sun, 18 Mar 2018 00:59:53 +0900</pubDate>
			</item>
			<item>
				<title>Visual Studio 15.6 リリース</title>
				<link>http://ufcpp.net/blog/2018/3/vs15_6/</link>
				<description><![CDATA[ <p>なんかVisual Studioの更新に 15.6.0 の正式版が配信されてますね。</p>
<p><a href="https://blogs.msdn.microsoft.com/visualstudio/">ブログ</a>とかのアナウンスはまだなさそう。<a href="https://mvp.microsoft.com/ja-jp/Summit">グロサミ</a>に来たMVPからのフィードバック欲しくてとりあえずリリースだけしちゃったとかですかね。ホテル・会場のWi-Fi負荷が…</p>
<p>それか、<a href="https://blogs.msdn.microsoft.com/visualstudio/2018/02/08/visual-studio-2017-version-15-6-preview-4/">preview 4の時の告知</a>から内容変わってないから書くことないか？</p>
<h2>navigation to decompiled sources</h2>
<p><a href="https://docs.microsoft.com/en-us/visualstudio/releasenotes/vs2017-preview-relnotes#productivity-1">navigation to decompiled source</a>とか便利そうではあります。まだ「experimental」がついていますけども。</p>
<p>今まで、DLL で参照しているものは、F12で「定義へ移動」しても、シグネチャ(どのクラスにどういうメソッドが、どういう引数であるか)しかわかりませんでしたけども。
それが、逆コンパイル処理をした C# コードを見れるようになるというもの。</p>
<p>設定は以下の場所から。</p>
<p><img src="/media/1160/15_6_navtodecompile.png" alt="navigation to decompiled souces の有効化設定" /></p>
<p>まあ、experimental なせいか、根本的に難しいのか、いまいちなコードが出てきたりはしますが。
あと、この機能を ON にしちゃうと、今までの F12 の結果と違って<a href="https://github.com/dotnet/roslyn/issues/25252">アセンブリ名とパスが出なくなる</a>のが不満だったりしますが。</p>
<h2>C# 7.2 fix</h2>
<p>C# 的には、今回のリリースでは C# 7.2 のままです。新文法の追加はなし、ということになっています。</p>
<p>が、<a href="http://ufcpp.net/blog/2018/1/pickuproslyn0103/">以前書いた</a>通り、バグ修正が結構入っています。<code>in</code>引数(<code>ref readonly</code>)がらみの<a href="http://ufcpp.net/blog/2017/12/%E3%83%90%E3%82%B0%E5%A0%B1%E5%91%8A%E7%A5%AD%E3%82%8A/">やべーやつ</a>が一通り治っているのに加えて、
以下の2つも「バグ修正」扱いで追加されていたりします。</p>
<ul>
<li>
参照引数な拡張メソッドが、<code>ref this</code>の語順でも<code>this ref</code>の語順でもよくなった
<ul>
<li>以前は<code>ref this</code>しか受け付けなかった</li>
</ul>
</li>
<li>
<code>M(T x)</code>と<code>M(in T x)</code>というように、<code>in</code>違いのオーバーロードがあるとき、<code>M(x)</code>だけだと前者を呼ぶようになった
<ul>
<li>以前はオーバーロードが解決できない扱いでコンパイル エラー</li>
<li>後者を呼びたければ<code>M(in x)</code>と書く</li>
</ul>
</li>
</ul>
<p>ちなみに、「<code>ref partial struct</code>と<code>partial ref struct</code>の語順も緩めよう」という話もあったんですが、これは今回のリリースには入らなかったみたいです。</p>
 ]]></description>
				<pubDate>Tue, 06 Mar 2018 18:03:56 +0900</pubDate>
			</item>
			<item>
				<title>cszip、nuget.org に上げました</title>
				<link>http://ufcpp.net/blog/2018/3/upload-cszip/</link>
				<description><![CDATA[ <p>こないだ .NET Global Tools を試すのに作ってみた <a href="https://www.nuget.org/packages/cszip/">cszip</a> と <a href="https://www.nuget.org/packages/csunzip/">csunzip</a>、<a href="https://www.nuget.org/">nuget.org</a> に上げてみといた。</p>
<p>以下のコマンドでインストール可能な状態になっています。</p>
<p><code>dotnet instal tool -g cszip
dotnet instal tool -g csunzip</code></p>
<p>以下のように適当にもほどがあるんで nuget.org に上げるかどうか迷っていたものの。</p>
<ul>
<li>readme の類一切ない</li>
<li>
ほんとに内部的に <a href="https://docs.microsoft.com/ja-jp/dotnet/api/system.io.compression.zipfile.createfromdirectory?view=netframework-4.7.1">CreateFromDirectory</a>、<a href="https://docs.microsoft.com/ja-jp/dotnet/api/system.io.compression.zipfile.extracttodirectory?view=netframework-4.7.1">ExtractToDirectory</a> を呼んでるだけ
<ul>
<li>例外処理全然してない (不正な引数を渡したら .NET の例外メッセージがそのまま出る)</li>
<li>オプション指定とかもできない (常に「圧縮率優先」「UTF8」)</li>
</ul>
</li>
<li>専用のリポジトリ持ってなくて、<a href="https://github.com/ufcpp/UfcppSample">UfcppSample</a>のDemoフォルダー以下にある</li>
</ul>
<p>名前的にも、以下のような点で悩んだものの。</p>
<ul>
<li>C# で書いているというだけで、別に「C# 向け」ではないけど cs~</li>
<li>こんな手抜き実装なもので cszip とかいう名前を取っちゃっていいのか</li>
</ul>
<p>あと、当初目的(<a href="http://ufcpp.net/blog/2018/2/dotnettoolspkgs/">前述</a>の通り、クロスプラットフォーム ビルドの面倒をマシにしたい)を考えるとLinuxとかMacでの動作確認しないといけないわけですけどもそれもやっておらず…</p>
<p>まあ、やっちゃってから考えるかと。</p>
 ]]></description>
				<pubDate>Sun, 04 Mar 2018 15:21:09 +0900</pubDate>
			</item>
			<item>
				<title>.NET Global Tools</title>
				<link>http://ufcpp.net/blog/2018/2/dotnettoolspkgs/</link>
				<description><![CDATA[ <p><a href="https://blogs.msdn.microsoft.com/dotnet/2018/02/27/announcing-net-core-2-1-preview-1/">.NET Core 2.1 の Preview 1 が公開されたそうで</a>。</p>
<p>以前から、daily build の不安定な奴で良ければ試せていたんですが、オフィシャルにアナウンスがあったということは、作業が一区切りしたということでしょう。</p>
<p>実際、今回の主題の Global Tools は、以前、daily build で試したときには全然動いていませんでした。
ということで、今日、やっと動いたので試してみたという話。</p>
<h2>Global Tools</h2>
<p>.NET Core 2.1 の、<code>dotnet</code> コマンドの新機能の1つです。</p>
<p><a href="https://docs.npmjs.com/getting-started/installing-npm-packages-globally">NPM global tools</a>にインスパイアされて作ったよ、というもの。</p>
<p>要するに、<code>dotnet</code>コマンドを使って、NuGet 越しにインストール可能なコマンドラインツールを提供するための仕組み。</p>
<p>試しに作ってみたものがこちら:</p>
<ul>
<li><a href="https://github.com/ufcpp/UfcppSample/tree/master/Demo/2018/DotNetGlobalTools">DotNetGlobalTools</a></li>
</ul>
<h2>ツールの作り方</h2>
<p><code>csproj</code> の <code>PropertyGroup</code> に、<a href="https://github.com/ufcpp/UfcppSample/blob/master/Demo/2018/DotNetGlobalTools/cszip/cszip.csproj#L6">以下のような行</a>を足せばいいらしい。</p>
<p><code>&lt;PackAsTool&gt;true&lt;/PackAsTool&gt;</code></p>
<p>ただ、現状、Visual Studio の方はまだ対応していなくて、これを入れたプロジェクトをビルドしてもそのままだとパッケージは作られません。<code>dotnet pack</code>コマンドを手打ちする必要があります。</p>
<p><code>dotnet pack -c release cszip/cszip.csproj</code></p>
<p>詳しくは、<a href="https://github.com/dotnet/core/blob/master/samples/dotnetsay/README.md">公式サンプル: dotnetsay</a>を参照。</p>
<h2>ツールのインストールの仕方</h2>
<p><code>dotnet install tool</code> コマンドでインストールできます。</p>
<p><code>dotnet install tool -g cszip --configfile .\nuget.config</code></p>
<p>NuGet を使ってパッケージを取ってきて、ユーザー フォルダーの下の <code>.dotnet/toolspkgs</code> と <code>.dotnet/tools</code> 以下にもってきて使うようです。
作ったツールは<a href="https://www.nuget.org/">nuget.org</a>にアップロードするもよし、
ローカル フォルダーを <a href="https://github.com/ufcpp/UfcppSample/blob/master/Demo/2018/DotNetGlobalTools/nuget.config#L5">NuGet パッケージ ソースに指定</a>するもよし。</p>
<p>上記の例では、設定ファイルを指定して、ローカルのフォルダーから作ったツールをインストールしています。</p>
<h2>ツールの使い方</h2>
<p><code>.dotnet/tools</code> にはパスが通っているので、作ったコマンド ライン アプリがどこからでも呼べるようになっています。
普通にコマンドをたたけば呼べます。</p>
<p><code>cszip packages sample.zip</code></p>
<h2>試しに作ってみたもの</h2>
<ul>
<li><a href="https://github.com/ufcpp/UfcppSample/tree/master/Demo/2018/DotNetGlobalTools/cszip">cszip</a>: <code>ZipFile.CreateFromDirectory</code> を呼んでるだけ</li>
<li><a href="https://github.com/ufcpp/UfcppSample/tree/master/Demo/2018/DotNetGlobalTools/csunzip">csunzip</a>: <code>ZipFile.ExtractToDirectory</code> を呼んでるだけ</li>
<li><a href="https://github.com/ufcpp/UfcppSample/tree/master/Demo/2018/DotNetGlobalTools/xstatic">xstatic</a>: .NET 標準ライブラリ中の任意の静的メソッドを呼び出せる</li>
</ul>
<p>割と最近、社内で C# で書いたコマンド ライン ツールを、
他社の方に使って貰わないといけない事案がありまして。
その時のやり取り:</p>
<ul>
<li>手元でビルドしたバイナリを毎回手渡しするのしんどいです</li>
<li>先方も、Mac だけど dotnet コマンドは使えるのよね？ .NET Core SDK はインストールしてもらえてて。ソースコードは共有してるんだし、向こうで <code>dotnet build</code> してもらったら？</li>
<li>試してみてもらったんですが、PostBuild イベントで呼んでるコマンドが PowerShell なので Mac で呼べませんでした</li>
</ul>
<p>呼んでるのは Compress-Archive でした。
Cygwin でも入れて zip コマンドに変えれば Mac でも動きそうなものの。
Windows だと bat を書いて、Mac とかだと sh を書いてとかもできはしますが、書くのはいいけど動作確認が大変で。
あと、最近は <a href="https://docs.microsoft.com/ja-jp/powershell/scripting/whats-new/what-s-new-in-powershell-core-60?view=powershell-6">PowerShell も .NET Core 化</a>してるのでこれを入れてもらうという手もなくはないものの。
そこまでやるか…と悩んだ結果、手渡し運用を続行。</p>
<p>ということで、
<code>dotnet</code> コマンドでインストールできて、<code>dotnet</code> コマンドで実行できるものがあるならそれを使くて、
Global Tools の仕組みを使ってみようかということで作ったのが cszip と csunzip。</p>
<p>で、zip/unzip でコマンド分けるべきか、
分けるの面倒ではないか、
というかむしろいっそのこと任意の静的メソッド呼べるようにしてやろうか。
等々、遊んでみてた結果が xstatic の方です。</p>
<p>インスパイア元の NPM Global Tools も似たような動機ですよね、きっと。
node.js でインストールできて、node.js で実行できるツールが欲しいという。</p>
 ]]></description>
				<pubDate>Wed, 28 Feb 2018 20:54:15 +0900</pubDate>
			</item>
			<item>
				<title>Pickup Roslyn 1/21</title>
				<link>http://ufcpp.net/blog/2018/1/pickuproslyn0121/</link>
				<description><![CDATA[ <p>今日は coreclr, corefxlab, designs から1件ずつ、計3つ。</p>
<h2>C# スクリプトの実用</h2>
<ul>
<li><a href="https://github.com/dotnet/coreclr/pull/15858">Update clr-configuration-knobs.md, add new C# csi.exe based script for xplat document generation #15858</a></li>
</ul>
<p>なんかドキュメント生成系のスクリプトを1個、sh から C# スクリプトに置き換えてみるのを試したいらしい。
曰く、</p>
<ul>
<li>典型的なスクリプト作業がどの程度効率化するか知りたい</li>
<li>あんまり重要でないものでとりあえずドッグフーディングを始めたい</li>
<li><a href="https://ss64.com/bash/m4.html">m4</a>への依存を減らしたい</li>
<li>C#ベースのスクリプト利用の強み・弱みの知見を得たい</li>
</ul>
<p>とのこと。</p>
<p>あと、今の (.NET Core 向けのは) Regex が遅すぎてやってらんないからこのプルリクでは Regex クラスの利用を避けてるらしい。</p>
<h2>priority queue</h2>
<ul>
<li><a href="https://github.com/dotnet/corefxlab/pull/1850">Solved priority queue design! #1850</a></li>
</ul>
<p>今更ながら、<a href="http://ufcpp.net/study/algorithm/col_heap.html">priority queue</a> の実装するみたい。
とりあえず、corefxlab でお試し実装を提案中。</p>
<p>割かし「なんで .NET にはないんだろう？」と言われ続けてるデータ構造筆頭。</p>
<p>なんかさらっと見てる感じ、priority queue に mutable なデータを入れたあと、優先度が変わるような変化を書けたときがまずそうな感じ。</p>
<h2>.NET Core Runtime と .NET Core SDKのバージョン</h2>
<ul>
<li><a href="https://github.com/dotnet/designs/pull/29">Add plan for .NET Core SDK version numbers #29</a></li>
</ul>
<p>.NET Coreって、今、Runtime (.NET 製プログラムを動かすための実行環境)とSDK (コンパイラーとかを含む)のバージョン番号がずれてて本当にわかりにくく。</p>
<p>前々からそれに文句を言ってた人が、「上2つの数字(メジャーバージョンとマイナーバージョン)くらいは揃えよう」っていう提案文書を提出。
まあ、全くもってその通りで。</p>
<p>ちなみに、まあ、SDK には「C# コンパイラーのバグ修正のみのリリース」みたいなのがあるので、Runtime と SDK のバージョンを完全に足並みそろえるってのはできないそうです。
なので、上2つのみの統合。</p>
<p>あと、SDK の方の3つ目のは、「基本、100単位でバージョンを上げる。バグ・セキュリティ ホール修正のサービス リリースは1ずつ上げる」みたいなのを提案。</p>
 ]]></description>
				<pubDate>Sun, 21 Jan 2018 19:43:07 +0900</pubDate>
			</item>
			<item>
				<title>GetUnicodeCategory(int codePoint) を提案してみた</title>
				<link>http://ufcpp.net/blog/2018/1/getunicodecategory/</link>
				<description><![CDATA[ <p>今日は、.NET で、U+10000 以上のコードが割り当たってる文字の Unicode カテゴリー判定をする方法について。
提案を出したらそのままプルリクを出すことになった話。</p>
<h2>背景</h2>
<h3>U+10000 以上の文字</h3>
<p>Unicode について詳細は、昔書いた記事があるのでそちらを参照。</p>
<ul>
<li><a href="https://www.buildinsider.net/language/csharpunicode/01">Unicodeとは？ その歴史と進化、開発者向け基礎知識</a></li>
<li><a href="https://www.buildinsider.net/language/csharpunicode/02">Unicodeと、C#での文字列の扱い</a></li>
</ul>
<p>ここではさらっと。</p>
<p>U+10000 以上に割り当たってる文字は、要するに、以下のようなものです。</p>
<ul>
<li>Unicode 設計当初に想定していなくて、後から「追加面」(supplementary planes)として定義した</li>
<li>
UTF-16 だと1文字で表せない
<ul>
<li>なので、サロゲート ペア(surrogate pair: 代理対)っていう2文字1組のコードで表す</li>
</ul>
</li>
<li>UTF-8 だと4バイト文字になる</li>
<li>一部のマイナーな漢字、マイナー言語の文字、絵文字なんかが入ってる</li>
</ul>
<p>C# にとって問題になるのは、C# が作られた時期にはまだこの追加面文字が普及していなかったということです。
C# の文字列は内部的に UTF-16 だし、.NET の標準ライブラリは追加面の文字を扱うためのものがいまいちそろっていなかったりします。</p>
<p>まあ昔は本当に追加面にはマイナーな文字しかなかったのでそれほど問題にはならなかったわけです。
そう、絵文字がASCII圏でも広まり出すまでは…</p>
<h3>Unicode カテゴリー判定</h3>
<p>まあ、絵文字のおかげで、アメリカ産のソフトウェアでも「ASCII 文字しかまともに受け付けない」みたいな不具合は減ってきているそうですが。
その一方で、「追加面文字は全部『サロゲート ペア』扱い」、すなわち、絵文字と一部のマイナーな漢字もいっしょくたに扱われてしまったりする問題はいまだ結構あったりします。</p>
<p>例えば、実のところ、C# コンパイラーがまさにそうでして。
(昔、<a href="https://www.slideshare.net/ufcpp/c-86447482/48">ちょっと勉強会で話したこともある</a>んですが)</p>
<p>C# は仕様上、Letter (書き言葉に使われる文字)なら何でも識別子として使えるはずなんですが、
今、追加面に入っている Letter は使えないという「仕様違反」があります。</p>
<pre class="source" title="現状の C# コンパイラーは追加面文字に未対応">
<code><span class="comment">// U+FFFF 以下 → 識別子に使える</span>
<span class="reserved">var</span> ᚠ = 1; <span class="comment">// ルーン文字(U+16A0, OtherLetter)</span>
<span class="reserved">var</span> ʬ = 2; <span class="comment">// 国際発音記号(U+02AC, LowercaseLetter)</span>
<span class="reserved">var</span> ℏ = 3; <span class="comment">// 文字様記号、プランク定数(U+210F, LowercaseLetter)</span>

<span class="comment">// U+10000 以上 → 識別子に使えない</span>
<span class="reserved">var</span> 𩸽 = 4; <span class="comment">// 一部のマイナーな漢字、ほっけ(U+29E3D, OtherLetter)</span>
<span class="reserved">var</span> 𓀀 = 5; <span class="comment">// ヒエログリフ(U+13000, OtherLetter)</span>
</code></pre>
<p>まさかのルーン文字以下の扱いを受けてる漢字があるとかʬʬ
草生えるʬʬʬʬʬ</p>
<p>これ、既知の問題でして、<a href="https://github.com/dotnet/roslyn/issues/13474">中国の方が報告</a>はしているんですが。
そんなに「私もこれで困ってる」的な反響もなく、低優先度でずっと放置状態です。
(ちなみに、僕は C# コンパイラーの中身をいじってこの問題を修正したこともあるので、その気になれば修正プルリク出せます。需要がなさ過ぎてやる気も起きない…)</p>
<p>どうしてこういう挙動になるかと言うと、追加面文字のカテゴリーを正しく見ていないから。
C# は内部的に UTF-16 で文字列を扱っているので、
追加面文字の文字カテゴリーを見ようとすると、単に<a href="https://docs.microsoft.com/ja-jp/dotnet/api/system.globalization.unicodecategory?view=netcore-2.0#System_Globalization_UnicodeCategory_Surrogate">サロゲート</a>という判定を受けます。</p>
<h3>.NET のカテゴリー判定メソッド</h3>
<p>.NET では、<a href="https://docs.microsoft.com/ja-jp/dotnet/api/system.globalization.charunicodeinfo?view=netcore-2.0"><code>CharUnicodeInfo</code></a>っていうクラスに Unicode 絡みのメソッドが定義されています。
(昔は<code>char</code>型に定義されていて、互換性のために今も <code>char</code> にその手のメソッドはあるんですが。)</p>
<p>Unicode カテゴリー判定は以下の2つメソッドがあります。</p>
<ul>
<li><a href="https://docs.microsoft.com/ja-jp/dotnet/api/system.char.getunicodecategory?view=netcore-2.0#System_Char_GetUnicodeCategory_System_Char_"><code>GetUnicodeCategory(Char)</code></a></li>
<li><a href="https://docs.microsoft.com/ja-jp/dotnet/api/system.char.getunicodecategory?view=netcore-2.0#System_Char_GetUnicodeCategory_System_String_System_Int32_"><code>GetUnicodeCategory(String, Int32)</code></a></li>
</ul>
<p>使い方は以下のような感じ。</p>
<pre class="source" title=".NET の Unicode カテゴリー判定メソッド">
<code><span class="reserved">using</span> <span class="reserved">static</span> System.Console;
<span class="reserved">using</span> <span class="reserved">static</span> System.Globalization.CharUnicodeInfo;

<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> Main()
    {
        <span class="comment">// char 用</span>
        WriteLine(GetUnicodeCategory(<span class="string">'ᚠ'</span>));
        WriteLine(GetUnicodeCategory(<span class="string">'ʬ'</span>));
        WriteLine(GetUnicodeCategory(<span class="string">'ℏ'</span>));

        <span class="comment">// 追加面(= char で表せないもの)用</span>
        WriteLine(GetUnicodeCategory(<span class="string">"𩸽"</span>, 0));
        WriteLine(GetUnicodeCategory(<span class="string">"𓀀"</span>, 0));
    }
}
</code></pre>
<p>お分かりいただけるだろうか…</p>
<p>現状の .NET に追加面文字なんてものはないので、<code>string</code> で判定します。
サロゲート ペアになっている2文字の UTF-16 からカテゴリー判定するメソッドになっています。</p>
<p>内部が UTF-16 な文字列しか持っていないこれまだとそんなに困らなかったかもしれません。
でも、今、.NET にも <a href="http://ufcpp.net/blog/2017/12/fastutf8string/"><code>Utf8String</code></a> なんていうものが実装されようとしているわけでして、このままだと困ります。</p>
<p>というか、<code>Utf8String</code> の完成を待っていられなくて<a href="https://github.com/ufcpp/UfcppSample/tree/master/Demo/2016/Unicode">自作</a>したり<a href="https://github.com/neuecc/Utf8Json">自作</a>したりしてると、今でも困っています。</p>
<pre class="source" title="コードポイントから直接カテゴリーを得る手段がない">
<code><span class="comment">// 𩸽の UTF-8 バイト列</span>
<span class="comment">// ファイルとかネットとか、今時普通は UTF-8 で保存・送受信するでしょ</span>
<span class="reserved">var</span> utf8 = <span class="reserved">new</span> <span class="reserved">byte</span>[] { 240, 169, 184, 189 };

<span class="comment">// UTF-8 をデコード</span>
<span class="comment">// 𩸽のコードポイント U+29E3D が得られてるはず</span>
<span class="reserved">var</span> c = Decode(utf8, 0);

WriteLine(c.ToString(<span class="string">"X"</span>)); <span class="comment">// 29E3D</span>

<span class="comment">// このコードポイントから直接カテゴリーを得る手段がない</span>
<span class="reserved">var</span> category = GetUnicodeCategory(c); <span class="comment">// ここでコンパイル エラー</span>
WriteLine(category);
</code></pre>
<p>(<code>Decode</code> メソッドの実体は <a href="https://gist.github.com/ufcpp/0b1d03675739d624c6d53d8db316d0ea#file-utf8-cs-L23">Gist</a> に。)</p>
<p>これ、もし現状の API でカテゴリー判定をしたければ、以下のような無駄なコードが必要になります。</p>
<pre class="source" title="仕方なく、文字列化">
<code><span class="comment">// 一度 string に変換(= 無駄にヒープ アロケーションが発生)</span>
<span class="reserved">var</span> s = <span class="reserved">char</span>.ConvertFromUtf32(c);
<span class="comment">// string 版の GetUnicodeCategory を呼ぶ</span>
<span class="reserved">var</span> category = GetUnicodeCategory(s, 0);
WriteLine(category);
</code></pre>
<p>要するに、以下のようなメソッドをよこせと言いたい。</p>
<ul>
<li><code>GetUnicodeCategory(int codePoint)</code></li>
</ul>
<p>ちなみに、他のプログラミング言語はというと…</p>
<ul>
<li>Java: 同様のメソッドの引数、ちゃんと int。<a href="https://docs.oracle.com/javase/jp/7/api/java/lang/Character.html#getType(int)"><code>getType(int)</code></a></li>
<li>Go: 最初から<a href="https://golang.org/pkg/builtin/#rune">文字が32ビット</a></li>
<li>Swift: 同上、<a href="https://developer.apple.com/documentation/swift/unicode.scalar">32ビット</a></li>
</ul>
<h3>実は最初から実装ある</h3>
<p>で、ですよ。
上記の、<code>GetUnicodeCategory(String, Int32)</code>の<a href="https://github.com/dotnet/coreclr/blob/38cf93013c1dd1efc7137a6f4930cab7cc653411/src/mscorlib/shared/System/Char.cs#L859">中身を覗く</a>じゃないですか。
だって、サロゲート ペアのままでテーブル引いてるわけないし。
絶対内部で一度コードポイントにデコードしてるだろうと。</p>
<p>そしたらやっぱり簡単に見つかるわけですよ、
<a href="https://github.com/dotnet/coreclr/blob/38cf93013c1dd1efc7137a6f4930cab7cc653411/src/mscorlib/shared/System/Globalization/CharUnicodeInfo.cs#L293"><code>InternalGetUnicodeCategory(int ch)</code></a>とかいう internal なメソッドが。</p>
<p>public にしろと。</p>
<h2>issue 立て、そしてプルリク</h2>
<p>この話、いつから気付いていたかというと、<a href="https://dotnetfringe-japan.connpass.com/event/35659/">昔C# コンパイラーの中身を書き換えたとき</a>なので、もう1年以上前だったりします。</p>
<p>まあ？標準ライブラリに<code>Utf8String</code>が入る頃までには？
ほっといてもそのうちたぶん入るだろうし？
入る…よね？
そもそも<code>Utf8String</code>自体がまだもうちょっと先っぽい？
あれ…？</p>
<p>みたいな。</p>
<h3>issue 立てました</h3>
<p>ということで、観念して突っついてみることに。
issue 立てました。</p>
<ul>
<li>
<a href="https://github.com/dotnet/corefx/issues/26173">API Propsal: char.GetUnicodeCategory(unicode scalar) #26173</a>
<ul>
<li>コードポイントを引数に受け取る <code>GetUnicodeCategory</code> が欲しいんだけど</li>
<li>てか、内部的に最初からあるよね？</li>
</ul>
</li>
</ul>
<p><a href="https://github.com/dotnet/roslyn">roslyn</a> とか <a href="https://github.com/dotnet/csharplang">csharplang</a> とかなら普段から割かし張り付いてるので勝手もわかるんですが。
<a href="https://github.com/dotnet/corefx">corefx</a>は勝手がわからず結構悩んだり。</p>
<p>そもそも、こういうプリミティブ型絡みの機能は corefx (標準ライブラリ)の方じゃなくて、<a href="https://github.com/dotnet/coreclr">coreclr</a> (実行環境)の方に含まれていますし。
それとは別に、最近は「設計に関する提案はこちら」みたいな <a href="https://github.com/dotnet/designs">dotnet/designs</a>とかいうリポジトリもありますし。
どれに、どう書けばいいの…</p>
<p>結局、corefx に出したわけですけども、まあ、一応それでも受け付けてもらえたみたい。</p>
<p>ただ、corefx に対する提案のフォーマットとしてはダメだったみたいで、</p>
<ul>
<li><a href="https://github.com/dotnet/corefx/blob/master/Documentation/project-docs/api-review-process.md">このドキュメント</a>に沿って整形して</li>
<li>あっ、こっちで提案文章を更新しといたわ、これでいいか？</li>
</ul>
<p>みたいなコメントが寝ている間に書かれていてビビったり。
(あちらはアメリカ西海岸なので、日本時間で言うと深夜2時くらいから稼働開始。こっちが寝てる間に話が進む。)</p>
<h3>レビューされました</h3>
<p>提案 issue が corefx チームの目に留まった場合、
当然ですがレビューが掛かります。
今は、レビューの様子も毎回 YouTube に投稿されていたりします。
(<a href="https://www.youtube.com/channel/UCaFP8iQMTuPXinXBMEXsSuw">Immo</a> (.NET 標準ライブラリ周りのプログラム マネージャー)が投稿。)</p>
<p>何気に今週のレビューの様子を見てみたら、割かし最初の方にその提案 issue が取り上げられてるじゃないですか。</p>
<div>
<iframe width="1504" height="759" src="https://www.youtube.com/embed/rSVM5RmAhso" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
</div>
<p>(1分30秒頃から)</p>
<p>英語半分も聞き取れないんで大体ですけども…</p>
<ul>
<li>
やっぱ ASCII 圏の人は追加面文字とか知らない
<ul>
<li><code>string</code> 版のやつは何か特殊なことしてるのか？<code>char</code> ではダメなのか？みたいな</li>
<li>詳しそうな人がチームメイトに向かって「サロゲート ペアとは」みたいな説明を開始</li>
</ul>
</li>
<li>
public にしてリネームするだけだしいいだろう、ただし、引数名はちゃんとしないと
<ul>
<li>提案では Unicode scalar とか code point とか書かれてるけど、どれがいいんだ</li>
<li>scalar とか code point とかの説明も開始</li>
<li>じゃあ、code point の方だな</li>
</ul>
</li>
</ul>
<p>みたいな感じで、10分程度でレビュー完了。
結果がこちらのコメント: <a href="https://github.com/dotnet/corefx/issues/26173#issuecomment-358057543">Looks good but we should rename the parameter</a></p>
<p>ちなみに補足。scalar と code point は以下の差らしい。</p>
<ul>
<li>scalar: サロゲートになっている文字コード(前半 U+D800 〜 U+DBFF、後半 U+DC00 〜 U+DFFF)部分は除く</li>
<li>code point: サロゲートの範囲も含む</li>
</ul>
<p><code>GetUnicodeCategory</code>の場合は、サロゲート文字を食わせると<a href="https://docs.microsoft.com/ja-jp/dotnet/api/system.globalization.unicodecategory?view=netcore-2.0#System_Globalization_UnicodeCategory_Surrogate">Surrogate</a>を返してくるので、この範囲が除外されている scalar ではなく、含んでいる code point が正解とのこと。</p>
<h3>プルリクを出す権利をやろう</h3>
<p>レビューが通ったわけですけども、そしたら<a href="https://github.com/dotnet/corefx/issues/26173#issuecomment-358120197">こんなこと言われた</a>わけですよ。</p>
<blockquote>
<p>この API の実装に関して、ヘルプはほしい？そうする意思があるならガイドをできるけども。</p>
</blockquote>
<p>えっ、あっ、はい。
こちらでプルリク作るんですか。</p>
<p>この作業、
どう考えても「中の人」がやるのが手っ取り早いわけですよ。
public にしてリネームするだけ。
それも、Visual Studio でリファクタリング機能を使えばほんとに一瞬で、
普段から関わっている人が作業すれば1分で済むやつ。</p>
<p>それに対して、英語もカタコト、時差もある相手にプルリクをオファー。
どう考えても、「提案者であることに免じてコミット履歴に名前を残す権利をやろう」的な接待モード。</p>
<p>というか、実際接待。
いただいたガイドも、「この行をリネームしたプルリクを出してくれ」。
作業指示がきわめて具体的な上、テストとか要らないんですか。
テストはそちらでやっていただけるんですか。
はい、プルリク出します。</p>
<ul>
<li><a href="https://github.com/dotnet/coreclr/pull/15911">CharUnicodeInfo.GetUnicodeCategory(int codePoint) #15911</a></li>
</ul>
<h3>条件コンパイルの罠</h3>
<p>もう1度言いますが、「Visual Studio でリファクタリング機能を使えばほんとに一瞬」。</p>
<p>しかし、そこには罠があったのです。</p>
<p>クロスプラットフォームなものに関わらないとあんまりはまることがない罠なんですが。
クロスプラットフォームなものを作ってると、結構、条件コンパイルだらけになります。
Windows 向けビルドでしか通らない場所、Unix でしか通らない場所…</p>
<p>はい、やらかしました。Unix ビルドを壊すやつ。
IDE のリファクタリングって、条件コンパイルの全条件までは追えないんですよねぇ。</p>
<p>世間一般にも、条件コンパイルはビルドを壊す原因ナンバー1。
だって、手元ではビルド通ってるんだもん。
そのままコミットしちゃうじゃない？</p>
<p>しかも今回に関しては、C# の<code>#if</code> プリプロセス分岐ですらなく。
csproj 中に、「<a href="https://github.com/ufcpp/coreclr/blob/44c0d3a6647a2df72b8f2ff1254a77bf74956725/src/mscorlib/System.Private.CoreLib.csproj#L581"><code>ItemGroup Condition</code> で <code>TargetsUnix</code> っていうプロパティが定義されている場合だけこのソースコードを使う</a>」みたいな記述が書かれてるやつでした。
自分が立ち上げてた Visual Studio からはファイルが見えてすらいない…</p>
<p>そしてこれもまた、僕が寝ている間に「直しといたよ」コミットが追加されているという接待っぷり…</p>
<h3>その後</h3>
<p>coreclr に出したプルリクはマージされたみたいですね。</p>
<p>ただ、その後も関連作業が続いているみたいです。
単に coreclr にある mscorlib の実装だけじゃなくて、それを corefx 側に公開したりする作業が必要だそうで。</p>
<p>そっちでも、寝ている間に「テスト通らないなぁ」→「あっ、このテスト失敗は別件だわ、大丈夫」みたいな会話がなされており。</p>
<h2>まとめ</h2>
<ul>
<li>
ASCII 圏の人、ほんとに Unicode 追加面を知らない
<ul>
<li>「こんなのほっといてもすぐに追加されるだろう」とか甘い</li>
<li>たぶん、日本人か中国人が言い出さないと進まない</li>
</ul>
</li>
<li>
プルリクを出す権利をやろう
<ul>
<li>接待モード</li>
<li>時差的に、寝てる間にいろいろ起こってる</li>
<li>条件コンパイルの罠</li>
</ul>
</li>
</ul>
 ]]></description>
				<pubDate>Sun, 21 Jan 2018 00:40:00 +0900</pubDate>
			</item>
			<item>
				<title>await って言う単語</title>
				<link>http://ufcpp.net/blog/2018/1/await/</link>
				<description><![CDATA[ <p>C# 5.0で<a href="http://ufcpp.net/study/csharp/ap_ver5.html#async">非同期メソッド</a>が導入されてから、
正式リリースを基準にしても5年以上、
最初の発表からだと7年以上経っています。</p>
<p>で、5年経っても、「なんて読むの」「asyncのaとawaitのaは違う」などなどが「定番ネタ」として定期的に出てくるわけですが。
特に、<a href="https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/await">ECMAScript 2017</a>がasync/awaitを導入したり、
<a href="https://blogs.unity3d.com/jp/2017/07/11/introducing-unity-2017/">Unity 2017</a>がやっとC#のバージョンを6.0に上げれる感じになってきたり、
5年の断絶を経て去年からasync/awaitに触れる人が増えているようです。</p>
<p>5年も離れたら、世代断絶も起こりますよね…
そりゃ、「定番ネタ」が改めて増えもしますよね…</p>
<p>ということで、5年くらい前に同じようなことをどこかで書いてるはずなんですけど、改めて。</p>
<h2>英単語</h2>
<h3>えいしんく</h3>
<p>まず読み方。</p>
<ul>
<li>async: エイシンク</li>
<li>await : アウェイト</li>
</ul>
<p>ってやつ。async の方が「アシンク」と読まれがち。
ごくまれに await の方を「エイウェイト」って間違う人もいるみたいですけども…</p>
<p>なんていうか、接頭辞の a を「エイ」って読む英単語は珍しいんでよく間違われます。
普通、aをエイと読むのはアクセントのあるところだけなわけですけども、asynchronous のアクセントは syn のところ。
英語のアクセントって「接頭辞を除いて一番前」なことが多く、接頭辞である a にはアクセントが来ない。</p>
<p>これ、たぶん、冠詞の a との弁別のためにこうなっちゃったのかなぁという感じはあります。
a synchronous ~ と、asynchronicity で a の発音同じだと困るだろうと。
日本語で言うと工学と光学、市立と私立みたいなもので。
「ひかりがく」「いちりつ」「わたくしりつ」とか、読み方としてはきもいけど弁別のためにはこう読まざるを得ないことがあるというような類です。</p>
<p>逆にいうと、冠詞を必要としていない日本語にカタカナ語として輸入するなら「アシンク」でも何も問題はなかったりはしますが…
元々がギリシャ語の ασύγχρονη なのでこれの読みだとアシーンクロニーですし。</p>
<p>ちなみに、後述するように async の a と await の a は別由来の別接頭辞なんですけども、
由来が違うから読み方が違うわけじゃないです。
async と同系統の a だと、例えば atom とかがそうですけども、これは英語でもアトムですし。</p>
<h2>a- 接頭辞</h2>
<p>asynchronous も await も、a + synchronous、a + wait という形の単語なわけですが…</p>
<ul>
<li>a + sync: a(否定) sync(同時)</li>
<li>a + wait: a(向かう) wait(待つ)</li>
</ul>
<p>になります。</p>
<p>async はギリシャ語系で、a は否定接頭辞。同じような構成の単語だと、</p>
<ul>
<li>atom: a(否定) tom(切る) → 「切れない」 → 原子</li>
<li>atopy: a(否定) topy(場所、由来) → 「由来がない」 → 特定されていない、奇妙な</li>
</ul>
<p>とかがあります。
ギリシャ語だから変。英語化するときに un とかに振り替えとけよ…という感じ。</p>
<p>await の方は、古フランス語(フランク語)の agaiter が由来でそれの a はラテン語の ad- 接頭辞から来てるっぽく、
現代英語だと to (~へ向かう)的な意味っぽい。
近いのはたぶん、</p>
<ul>
<li>amaze: a(向かう) maze(迷路、当惑) → 驚く</li>
</ul>
<p>とか。
類似の ad- まで広げると、</p>
<ul>
<li>adjust: ad(向かう) just(ちょうど) → 「ちょうどよくする」 → 調整する</li>
<li>adventure: ad(向かう) venture(投機、大胆) → 「大胆に向かう」 → 冒険</li>
</ul>
<p>とか。</p>
<p>同じスペルで全然意味が違うわけですが…
a- 接頭辞は特にひどいみたいでして、まとめると以下のようなものがあるっぽいです。</p>
<ul>
<li>ギリシャ語の a- 由来 → not。否定</li>
<li>ラテン語の ab- 由来 → from, out。「~から離れる」</li>
<li>ラテン語の ad- 由来 → to。「~に向かう」</li>
<li>フランス語の à 由来 → さらにたどるとラテン語の ad- 由来。on とか at 的な意味も</li>
<li>古英語の ar-, or- 由来 → on, up</li>
</ul>
<p>由来違いが混ざったのと、
本来あった差が消失しているせいでひどいみたいです。</p>
<p>日本語で言うと、
不遍・普遍、不通・普通とか、
読む/呼ぶ → 読んだ/呼んだ みたいな感じですかね。
不と普は元の中国語だと区別がつくはずが、日本語は発音が少ないので区別できなくなり。
む・ぶは古代日本語だと区別していたはずが、音便変化で同じになってしまったり。</p>
<h3>wait と await</h3>
<p>wait 自体に動詞用法がある現在、別途 await があるのはちょっと奇妙なものの、
フランク語の時点で gaiter と agaiter 両方あるみたいです。</p>
<p>await の方は古英語っぽく感じるらしく、古臭い・フォーマルな印象になるそうです。
まあこの辺り、「待つ」って大和言葉があるのに「待機」って漢語由来の単語があって、
待機の方がフォーマルな印象になるのと同じ。</p>
<p>a- (向かう)が付くことでニュアンスも変わるらしく、類語辞書を引くと、</p>
<ul>
<li>wait → interval, downtime, halt, hold</li>
<li>await → anticipate, hope, ready for, look for</li>
</ul>
<p>とかが並んでいます。要するに、</p>
<ul>
<li>wait → 待機。止まって待つ(他の事せず待ってる印象あり)</li>
<li>await → 待望。気持ち的には待ってる(他のことをしてる印象あり)</li>
</ul>
<p>という区別になります。</p>
<p>あと、「await は wait 単体じゃなくて、wait for と類語」とか言われたりします。
「A wait B」だと「A が B を待たせる」的な感じで、「A await B」「A wait for B」だと「AがBの到来を待つ」。</p>
<h3>Q. これだから英語は</h3>
<p>A. 「不遍・普遍」「市立・私立」「読んだ・呼んだ」で困ったことのない人だけが石を投げなさい。</p>
<p>「これだから自然言語は」という感じはするので、みんな形式言語で会話すればいいんじゃないでしょうか。</p>
<h3>async + wait?</h3>
<p>で、なんか、「<a href="https://github.com/dotnet/csharplang/issues/1237">await って、もしかして asynchronously wait の略で await なの？</a>」とかいう都市伝説が発生しているらしく…</p>
<p>ちなみに、質問に関する回答は「it's <a href="https://ja.wikipedia.org/wiki/%E3%82%BB%E3%83%AC%E3%83%B3%E3%83%87%E3%82%A3%E3%83%94%E3%83%86%E3%82%A3">serendipity</a>」。</p>
<p>どうも、C# の仕様書に「await: asynchronously wait for the tasks completion」と書かれているからというのが理由みたいなんですけども。
言われてみれば、非ネイティブにはつらい文面。</p>
<p>英語の、前置詞によってニュアンスが変わるのは本当に難しい…
とはいえ、接頭辞のカオスっぷりに比べると幾分かマシなので、
時代とともに「基本的な動詞 + 副詞/前置詞」で表現の幅を増やす用法が増えているという話もあります。</p>
<h2>C# が await キーワードを採用</h2>
<p>C# が非同期メソッドを導入する際には、文法をどうするか、特に await に相当する単語をどうするかはかなり悩んだみたいです。</p>
<p>Eric Lippert (当時の中の人)のブログ:</p>
<ul>
<li><a href="https://blogs.msdn.microsoft.com/ericlippert/2010/10/29/asynchronous-programming-in-c-5-0-part-two-whence-await/">Asynchronous Programming in C# 5.0 part two: Whence await?</a></li>
</ul>
<h3>yield 案</h3>
<p>元々、2010年のPDCでの最初の発表の時点では yield でした。</p>
<pre class="source" title="初出の時の非同期メソッド">
<code><span class="type">Task</span> M()
{
    <span class="reserved">yield</span> <span class="type">Task</span>.Delay(1);
    <span class="reserved">var</span> text = <span class="reserved">yield</span> <span class="type">File</span>.ReadAllTextAsync(<span class="string">"a.txt"</span>);
}
</code></pre>
<p>yield と言えば、C# だと<a href="http://ufcpp.net/study/csharp/sp2_iterator.html">イテレーター構文</a>があります。</p>
<pre class="source" title="イテレーター構文">
<code><span class="type">IEnumerable</span>&lt;<span class="reserved">char</span>&gt; Producer()
{
    <span class="reserved">yield</span> <span class="reserved">return</span> <span class="string">'"'</span>;
    <span class="reserved">for</span> (<span class="reserved">int</span> i = 0; i &lt; 3; i++)
    {
        <span class="reserved">yield</span> <span class="reserved">return</span> (<span class="reserved">char</span>)(i + <span class="string">'0'</span>);
    }
    <span class="reserved">yield</span> <span class="reserved">return</span> <span class="string">'"'</span>;
}

<span class="reserved">void</span> Consumer()
{
    <span class="reserved">foreach</span> (<span class="reserved">var</span> c <span class="reserved">in</span> Producer())
    {
        <span class="type">Console</span>.WriteLine(c);
    }
}
</code></pre>
<p>これで以下のような感じの挙動になります。</p>
<p><img src="/media/1159/yieldreturn.png" alt="yield return" /></p>
<p>Producer 側で値を1つ作るたびに、その値を Consumer 側に渡すような動作。</p>
<p>yield は yield で日本人には何か難しい単語で、以下のような意味があります。</p>
<ul>
<li>(車線などを)譲る・明け渡す・降伏する</li>
<li>産み出す・収穫/利益が出る</li>
</ul>
<p>語源的には「支払う」という意味らしく、後者の意味も「大地から恵みを支払ってもらう」「農作業の結果の支払いを受ける」みたいな感じでしょうか。</p>
<p>それか、win が「勝つ」の意味と「獲得する」の意味があるのと同じような感じですかね。
何かを得るために戦う。なので戦いに勝ったら何かもらえるのは当然、みたいな感じで。
「譲る」と言うからには「産出」を伴うのが当然というか。
略奪文化怖い…</p>
<p>で、「A yield B to C」と書くと、「A は B を(産み出して) C に譲る」になるみたいです。</p>
<p>イテレーターの yield return だと、「制御/スレッド/CPU の利用権を他のメソッドに譲る」みたいな感じで yield という単語が使われます。
でも、「A yield B to C」の用法があるので、
Producer yield return values of &quot;, 0, 1, 2, &quot; to Consumerで
「Producer が戻り値 &quot;, 0, 1, 2, &quot; を産み出して、Consumer に譲り渡す」みたいなニュアンスもたぶんあります。</p>
<p>さて、非同期メソッドの「yield 案」に話を戻しますが、
「制御/スレッド リソース/CPU の利用権を他のメソッドに譲る」という意味では、
非同期メソッドがやっていることはまさにこれです。
実のところ、イテレーターと非同期メソッドは、動作原理/C# コンパイラーのコード生成的な所は全く同じものです。
イテレーターの、非同期処理への応用結果が非同期メソッド。</p>
<p>しかしここで問題になるのが、「何かを産み出しつつ譲る」というニュアンスの方。
<code>await Task.Delay(1)</code>で、Producer は Consumer に <code>Task</code> を支払っているのかというと、そんなことはなく。
イテレーターの場合には譲り渡す相手が明確にいましたが、
非同期メソッドの場合は「スレッド リソースをOSに返還する」みたいな見えない部分での譲渡になるのがわかりにくいです。</p>
<p>それでも、イテレーターよりも先に非同期メソッドがあったのなら、もしかしたら yield 採用の芽もあったかもしれません。
とはいえ、似て非なるものに同じキーワードを使うのも怖いですし。
将来的には「<a href="https://github.com/dotnet/csharplang/issues/43">非同期ストリーム</a>」という、非同期メソッドとイテレーターを混ぜれる機能も入る予定なので、混ざる前提でキーワードを決める必要があります。</p>
<p>上記ブログには「yield return との区別が必要なら、yield with, yield for, yield while, yield until はどうか？」というコメントも結構多いくらいです。
ただ、ECMAScript 2017とかではむしろ、単に <code>yield</code> で generator (C# のイテレーター相当の機能)を表すことになっていますし、
yield return みたいな複合キーワード(2単語で初めてキーワード扱い)は総じて受けが悪いです。</p>
<h3>他の案</h3>
<p>他だと、Eric Lippert の挙げているのが</p>
<ul>
<li>wait for</li>
<li>while away</li>
<li>hearken unto</li>
<li>for sooth Romeo wherefore art thou</li>
</ul>
<p>コメントに挙がってるのが</p>
<ul>
<li>after</li>
<li>continue with, continue after</li>
</ul>
<p>とか。</p>
<p>wait for は、それとほぼ同義を1単語で表す await があるわけで。</p>
<p>while とか continue は<a href="http://ufcpp.net/study/csharp/st_loop.html">ループで使うやつ</a>と被るから駄目でしょうね。</p>
<p>after はどうだったんだろう。そもそも候補に挙げている人も少ないので、あんまりしっくりこないのかも。</p>
<p>hearken とか、wherefore art thou とかは完全にネタです。
await 自体が「古めかしい印象」の単語なので、
もっと古典な hearken unto (listen to) とか wherefore art thou (why are you: ロミオとジュリエットの「どうしてあなたは」)とかをシャレで挙げています。
まあ、「await は気持ち悪い？俺もそう思う。けど難しかったんだ」くらいの主張だと思われます。</p>
<h3>await 案</h3>
<p>ということで、最終的には await になりました。
前述の通り、await には「待望」(待ちつつも他の事やってる感じ)のニュアンスがちょっとあります。</p>
<pre class="source" title="wait と await">
<code><span class="reserved">async</span> Task M()
{
    <span class="comment">// wait = 待機</span>
    <span class="comment">// 止まって待つ</span>
    <span class="comment">// Thread.Sleep してるのと同じで、スレッド リソースを確保したままスレッドが止まる</span>
    Task.Delay(1).Wait();

    <span class="comment">// await = 待望</span>
    <span class="comment">// 気持ち待ってるけど作業は止めない</span>
    <span class="comment">// スレッド リソースを明け渡すので、OS はそのリソースを他に使える</span>
    <span class="reserved">await</span> Task.Delay(1);
}
</code></pre>
<p>とはいえ、await も割かしぎりぎり採用された感じです。
「なんか wait の古めかしい言い方」、「wait forと同じ意味」くらいにも思われる単語ですんで。
wait と await で内部的に起きる現象が違うというのはだいぶ危うい感じ。</p>
<p>とはいえ、メソッド <code>M</code> にとっては <code>Task</code> はやっぱり「完了を待ちたいもの」になります。
「待ちたいんだけど単純に待機しちゃダメ」と言うのが非同期メソッドの難しいところなので…</p>
<p>結局、去年リリースされた <a href="(https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/await)">ECMAScript のやつ</a>も await になりましたし、
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3722.pdf">C++ に出てる提案</a>が await なのは提案者が Microsoft なので当然として、
<a href="https://www.python.org/dev/peps/pep-0492/">Python</a> とか <a href="https://gist.github.com/lattner/31ed37682ef1576b16bca1432ea9f782">Swift</a> で出ている提案も await を使う雰囲気になっていますし、
「わざわざ変えなきゃいけないほどは悪くない」程度には受け入れられている感じはします。</p>
 ]]></description>
				<pubDate>Mon, 08 Jan 2018 18:53:34 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 1/3: Regex パーサー / C# 7.2 fixes</title>
				<link>http://ufcpp.net/blog/2018/1/pickuproslyn0103/</link>
				<description><![CDATA[ <p>なんかこう、GitHub リポジトリのwatchとかしてると、
だいたいアメリカのホリデーシーズンに合わせて自分まで「もう休み」な気分になってしまい。
要するに、12月20日前後にはもう休み気分で。
代わりに1月は2日から仕事に復帰してる感じの人が多く、休みあけた気分に。</p>
<h2>Regex パーサー</h2>
<p>事の発端は、「<a href="https://github.com/dotnet/roslyn/pull/23984">C# に Regex リテラルを入れてくれ</a>」とかいう、まあ、芽がない提案なんですが。
issue 自体はだいぶ前からあるものなんですが、ホリデー前後あたりからなぜか再燃。</p>
<p>「芽がない」ってのは、この手の「C# に別言語を埋め込みたい」系の提案が通った試しがないからでして。
今回も、まあ、C# チームの中の人の1人が、</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/371#issuecomment-290542407">Analyzer 作るのではダメな理由ある？</a></li>
<li><a href="https://github.com/dotnet/csharplang/issues/371#issuecomment-350517894">TypeScript で Regex リテラルのサポートに関わってたけど、あれ、割かし簡単じゃない</a></li>
<li><a href="https://github.com/dotnet/csharplang/issues/371#issuecomment-350517894">言語の変更なしで、IDE 機能として実現できる(それは大きな利益になると思う)</a></li>
</ul>
<p>などなど言語機能としては完全否定。</p>
<p>代わりに、IDE機能としては割かし乗り気だったわけですけども、
「休み中の飛行機の中で暇だったから作った」的なノリで、
Regex パーサーを書いちゃったみたいです。</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/pull/23984">Add in a regex parser so that the IDE can provide services around regex editing. #23984</a></li>
</ul>
<p>持っている機能は以下のようなもの。</p>
<ul>
<li>VirtualCharService: <code>&quot;\\1</code>、<code>@&quot;\1&quot;</code>、<code>&quot;\\\u0031&quot;</code> みたいな同じ文字列の別表現みたいなのの差を吸収する層</li>
<li><code>new Regex(&quot;&quot;)</code> の中身に対して働く正規表現パーサー</li>
<li>正規表現が間違っていたら編集時にエラーを検出する</li>
<li>正規表現の構文を見て色付け</li>
</ul>
<p>まあ、現状、1開発者が休暇中に個人的に作ってみたって感じなので、今後どうなるかはわかりませんが。</p>
<p>あと、「正規表現が間違っていたらエラーに」の方は<a href="https://www.nuget.org/packages/Microsoft.CodeAnalysis.CSharp/">Microsoft.CodeAnalysis</a>だからいいとして、
「構文色付け」の方は<a href="https://www.nuget.org/packages/Microsoft.VisualStudio.LanguageServices/">Microsoft.VisualStudio.LanguageServices</a>なんですよね…
Visual Studio Code とか for Mac で動くのか…</p>
<h3>raw string リテラル</h3>
<p>ということで、結局、特別な言語機能なしで Analyzer を書く感じに収まりそうなんですが。
Regex だけの特別扱いというのは今後も芽はないとして。
とはいえ、汎用な機能として C# に追加したい課題はいくつかあったりはします。</p>
<p>1つは、<a href="https://github.com/dotnet/csharplang/issues/89">&quot;raw&quot; string リテラル</a>。
<code>@</code>付きのやつ(<a href="http://ufcpp.net/study/csharp/st_embeddedtype.html#verbatim-string">逐語的文字列リテラル</a>)よりもさらに、「そのまんま」な文字列リテラルが欲しいという話。
文字列中に <code>\</code> が頻出することは Regex に限らず結構ありますし。
<code>@&quot;&quot;</code> でも、文字列中の<code>&quot;</code> がやっぱり<code>@&quot;&quot;&quot;abc&quot;&quot;&quot;</code>みたいな感じでかなり嫌ですし。</p>
<p>てことで、<a href="https://qiita.com/_meki/items/53db5976a041546eb8c4">C++ 11 の raw string</a>みたいに、開始・終了のパターンを任意に変えれるようにしたいという話に(これも前々からある提案の再燃)。</p>
<h3>コンパイル時処理</h3>
<p>.NET の <code>Regex</code> クラスには、正規表現を解析して、<a href="http://smdn.jp/programming/netfx/regex/1_regex_cached_compiled/">内部的に IL コード生成してキャッシュ</a>しておくような機能もありまして。
動的コンパイル。
初回はやたらと遅いものの、何度も同じパターンを調べる場合は圧倒的に速くなります。</p>
<p>でもその、動的にやっちゃうがゆえに初回やたら遅いとか、
<a href="https://ja.wikipedia.org/wiki/%E4%BA%8B%E5%89%8D%E3%82%B3%E3%83%B3%E3%83%91%E3%82%A4%E3%83%A9">AOT</a> を見越して動的コンパイルが使えない環境で困るとか、
結構悩ましいものがあります。</p>
<p>てことで、C# コンパイルの途中の処理をフックしてIL生成できるプラグイン機構を追加してほしいなんて話も度々出たりはするんですが。
Regex の中身のコード生成とかかなり複雑そうで、そういう機構があっても結構きつそう…</p>
<h2>C# 7.2 fixes</h2>
<p>おまけ。</p>
<p><a href="http://ufcpp.net/blog/2017/12/vs15_5/">Visual Studio 2017 15.5をリリース</a>して割とすぐにホリデーシーズンに入ってしまい、C# 関連も一気に動きが鈍くなったわけですが。
一応、15.6に関する計画的なドキュメントはちょこっと更新されていたり。</p>
<p><a href="https://github.com/dotnet/roslyn/blob/master/docs/Language%20Feature%20Status.md">Language Feature Status</a>に、
「C# 7.2 fixes」ってセクションが増えています。
おそらくこれが 15.6 でのリリースになります。
今出ている 15.6 のプレビュー版には入っていませんが、次のプレビュー辺りからちらほら入り始めるはず。</p>
<p>まあ、名前通り、基本的にはバグ修正です。
<a href="http://ufcpp.net/blog/2017/12/%E3%83%90%E3%82%B0%E5%A0%B1%E5%91%8A%E7%A5%AD%E3%82%8A/">先月書いたやべーやつ</a>も直るはずです。
で、ちょこっと文法にも追加？が入ります。</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/pull/23643">Relax ordering constraints for parameter modifiers #23643</a></li>
<li><a href="https://github.com/dotnet/roslyn/pull/23122">Prefer by-val methods over in methods in overload resolution #23122</a></li>
</ul>
<p>前者は、<a href="/study/csharp/cheatsheet/ap_ver7_2/#ref-extensions">参照渡しの拡張メソッド</a>の<code>ref</code>と<code>this</code>の順序とか、
<a href="/study/csharp/cheatsheet/ap_ver7_2/#span-safety"><code>ref</code>構造体</a>の<code>ref</code>と<code>partial</code>の順序とか、
15.5 の時点では <code>ref this</code>、<code>ref partial</code> の順でないといけなかったのを、どういう語順でもよくするという話。</p>
<p>後者は、通常の引数と<a href="http://ufcpp.net/study/csharp/cheatsheet/ap_ver7_2/#ref-readonly"><code>in</code>引数</a>でオーバーロードを作ってしまった場合(例えば、<code>void M(T x)</code> と <code>void M(in T x)</code>)、<code>M(T x)</code> の方を呼び出す手段がなかったという問題の解消です。<code>M(value)</code> と呼べば <code>M(T x)</code> を、<code>M(in value)</code> と呼べば <code>M(in T x)</code> を呼ぶようになります。</p>
<p>いずれも、まあ既存コードは壊しませんし、今までできなかったことができるようになるだけなので、
「バグ修正みたいな物」として扱うみたいです。
要するに、
「<code>ref this</code> の語順でないとコンパイル エラーになる 15.5 の頃の挙動をあえて選びたい」みたいなことは 15.6 以降ではできなると思われます。</p>
 ]]></description>
				<pubDate>Wed, 03 Jan 2018 18:52:36 +0900</pubDate>
			</item>
			<item>
				<title>コピー禁止(non-copyable)構造体アナライザー</title>
				<link>http://ufcpp.net/blog/2017/12/noncopyable/</link>
				<description><![CDATA[ <p>書き換えられる(mutable)構造体を作ると事故る問題を解決するために<a href="https://github.com/ufcpp/NonCopyableAnalyzer">アナライザー</a>作りました。</p>
<h2>mutable 構造体</h2>
<p>一般論としては、<a href="https://gist.github.com/ufcpp/08cb223b1b53a6cd0b13d953a0055156">構造体を mutable に作ると事故ります</a>。
要するに、「書き換えたつもりが、実は書き換えてたのはコピーであって元の値は書き換わってない」的なやつ。
なので、たいていの場合は「構造体は immutable(書き換え不能)に作れ」という指針になります。</p>
<p>その一方で、まれに、ヒープ確保を避けるために mutable な構造体を作りたい場合があります。
フィールドとしてクラスに埋め込んで使ったり、ローカル変数に確保して<code>ref</code>引数でメソッドに渡す想定で作ります。</p>
<p>例えば、corefxlab が作りかけてる<a href="https://github.com/dotnet/corefxlab/blob/master/src/System.Collections.Sequences/System/Collections/Sequences/ResizableArray.cs"><code>ResizableArray</code></a>とか、neueccさんが作ってるUtf8Json中の<a href="https://github.com/neuecc/Utf8Json/blob/master/src/Utf8Json/JsonWriter.cs"><code>JsonWriter</code></a>とか、
書き込み先の配列(満杯になったら確保しなおす)と現在の書き込み位置だけを持つ小さい型なんですが、
構造体で作られています。
自分が昔作ったのだと、<a href="https://docs.microsoft.com/ja-jp/dotnet/api/system.lazy-1?view=netstandard-1.1"><code>Lazy</code></a>型のためにアロケーションが発生するのがいやすぎて、これの構造体版を作ったこととか。</p>
<p>もちろん、コピーが発生したら事故ります。
「<code>JsonWriter</code>に<code>Write</code>したつもりが何も書き込まれていない(コピーに対して書き込んでた)」とかやらかしがちです。</p>
<h2>コピーの方を禁止する</h2>
<p>mutable 構造体で問題が起きるのはコピーが発生するせいです。
なので、コピーの方を禁止すれば、構造体が mutable でも問題は起こしません。</p>
<p>ということで作ったのがこちら。</p>
<ul>
<li><a href="https://github.com/ufcpp/NonCopyableAnalyzer">NonCopyableAnalyzer</a></li>
</ul>
<p>本当はずっと昔から作ろうとは思ってたんですが。
「Analyzer with Code Fix のプロジェクト テンプレートが SDK-based csproj になったら本気出す」って思ってたらつい最近になってようやく…
<a href="http://ufcpp.net/blog/2017/12/analyzerconvention/">先週のブログ</a>に書いた<a href="https://github.com/ufcpp/AnalyzerConvention">Analyzer 用の自作プロジェクト テンプレート</a>を作った動機もこれ用。</p>
<p>どういうコードが禁止されるかは、<a href="https://github.com/ufcpp/NonCopyableAnalyzer/tree/master/src/NonCopyable/NonCopyable.Test/DataSource/NonCopyable">テスト用のコード</a>を見てみてください。サブフォルダーの Source フォルダー以下にある csx の、❌ コメントを入れている行を禁止。
以下のような感じでコンパイル エラーが出ます。</p>
<p><img src="/media/1158/noncopyable.png" alt="non-copyable error" /></p>
<h3>おまけ: 言語機能化の提案</h3>
<p>コピー禁止って、必要となる場面がそんなに多くないわりに、解析するの結構大変なんですよね…
自分が作った NonCopyableAnalyzer も完璧なものではないです。
例えば、ジェネリクスが絡むと誤判定あり。</p>
<pre class="source" title="non-copyable 誤判定">
<code><span class="reserved">static</span> <span class="reserved">void</span> Main()
{
    <span class="reserved">var</span> x = <span class="reserved">new</span> NonCopyableStruct();
    <span class="reserved">var</span> illegal = x; <span class="comment">// ちゃんと禁止</span>
    <span class="reserved">var</span> misjudged = Copy(x); <span class="comment">// 本来禁止すべき。でも現実装だと通っちゃう</span>
}

<span class="reserved">public</span> <span class="reserved">static</span> T Copy&lt;<span class="type">T</span>&gt;(<span class="reserved">in</span> T x) =&gt; x;
</code></pre>
<p><a href="https://github.com/dotnet/csharplang/issues/859">「Non-cobyable 構造体」を言語機能として入れてほしい</a>っていう要望とかも出てたりはするんですけども。
言語に組み込むには上記のような誤判定がつらいかなぁという感じ…</p>
<p>こういう、「コピー禁止」があると、<a href="http://ufcpp.net/blog/2017/7/pickuproslyn0730/">昔ブログに書いた非ガベコレな高効率メモリ管理</a>とかも実現できたりするんですが、
これは誤判定がちょっとでも残るとやばいやつなので、相当難しそう…</p>
 ]]></description>
				<pubDate>Sun, 17 Dec 2017 16:08:56 +0900</pubDate>
			</item>
			<item>
				<title>ビルドで使う C# コンパイラーを差し替える</title>
				<link>http://ufcpp.net/blog/2017/12/msnetcompilers/</link>
				<description><![CDATA[ <p><a href="http://ufcpp.net/blog/2017/12/vs15_5/">Visual Studio 2017 15.5</a>で、C# コンパイラーのコード生成の仕方がちょっと変わりました。</p>
<p>その余波で起きる問題を回避するために、Visual Studio は 15.5 のまま、C# コンパイラーのバージョンだけを下げる方法について話します。</p>
<h2>背景</h2>
<h3>C# コンパイラーが出力するコードのどこが変わったか</h3>
<p>15.5 の世代では、とにかくいろいろパフォーマンス改善を行っています。
.NET Coreのランタイムや標準ライブラリのパフォーマンスも1～2割上がっています。
Visual Studioも、ソリューションのロードにかかる時間が半減していたりします。
C# コンパイラーも、コンパイラーが出力するコードがより速くなるように微妙に調整が入っています。</p>
<p>コンパイラーの出力結果なんですが、今まで <code>int</code> (符号付き)だったところが <code>uint</code> (符号なし)で生成されていたりします。
なんでかというと、以下のようなコード(よくある配列の範囲チェックみたいなやつ)を考えたとき、</p>
<pre class="source" title="">
<code>0 &lt;= index &amp;&amp; index &lt; length
</code></pre>
<p>以下のように書き換えた方が比較が1回減って速いから。</p>
<pre class="source" title="">
<code>(<span class="reserved">uint</span>)index &lt; length
</code></pre>
<p>こういう範囲チェック、ポインター操作をしていると頻出するので、
ポインターの扱いを符号付き整数から符号なし整数に変えたみたいです。</p>
<p>ということで、以下のようなコードを書いた場合、</p>
<pre class="source" title="">
<code><span class="reserved">public</span> <span class="reserved">unsafe</span> <span class="reserved">void</span> M(<span class="reserved">string</span> s)
{
    <span class="reserved">fixed</span> (<span class="reserved">char</span>* p = s)
    {
    }
}
</code></pre>
<p>これまで、<code>conv.i</code> (<code>s</code>のアドレスを符号付き整数に変換)命令が出ていたところに、
<code>conv.u</code> (同、符号なし整数)命令が出るように変わったりしました。</p>
<h3>Unity でこれが問題に</h3>
<p>この、「ポインター化の <code>conv.u</code>」が、<a href="https://unity3d.com/jp/">Unity</a>(ゲーム エンジンの)を即死させます。
起きていることは <code>InvalidCast</code> 例外(符号の有無が違うから)の類なんですけども、
命令解釈のレベルで起きてることなせいか、Unity エディターが無言で落ちます。</p>
<p>まあ、問題が起きてる場所的に、Unity が落ちる条件も限定的ではあります。
以下のような条件。</p>
<ul>
<li>unsafeコードを使っている</li>
<li>そのコードを Visual Studio 15.5 でビルドした DLL を、Unity で参照する</li>
</ul>
<p>自社のプロジェクトでは、まさにこの条件を踏んでしまっていて困っていました。</p>
<h3>ダウングレードしにくい・side by side インストールしにくい</h3>
<p>ということで、最初は、「Visual Studio のバージョンを上げない」運用をしていたんですけども、
チーム内でうっかりバージョンを上げちゃう事案が発生。
自分もうっかり上げたくなる事案は常に発生中。</p>
<p>で、Visual Studio 2017 (15.0)以来、Visual Studioのインストール手順が簡略化されたんですけども
(Lightweight インストーラーって呼ばれています)、
その代わり、バージョン違いの Visual Studio の同時インストール(side by side インストール)がかえってやりにくくなってたりします。</p>
<p>「Professional と Community で別バージョンを入れる」みたいなことは結構楽なんですけども、
「どっちもProで、15.4.5 と 15.5.0 を同時に入れる」みたいなのは、Lightweight インストーラーではできません。</p>
<p>しかも、ダウングレードが大変。
アップグレードは「更新」ボタン1つでできるんですけども、
ダウングレードは一度アンインストールからのインストールし直しが必要。</p>
<p>ということで、「うっかり上げちゃう事案」が結構深刻な問題になりました。</p>
<h2>コンパイラーのバージョンだけを下げる</h2>
<p>ふと、確か、NuGet パッケージ参照で C# コンパイラーを差し替えれる仕組みがあることを思いだしたので、
それで問題回避をしてみることに。</p>
<h3>Microsoft.Net.Compilers パッケージ</h3>
<p>以下のパッケージを NuGet 参照すると、そのプロジェクトのビルドは、パッケージ中に含まれている csc で行われるようになります。</p>
<ul>
<li><a href="https://www.nuget.org/packages/Microsoft.Net.Compilers/">Microsoft.Net.Compilers</a></li>
</ul>
<p>例えば、Microsoft.Net.Compilers の 2.4.0 を参照すると C# 7.1 時代のコンパイラーになります。</p>
<p>元々は、ASP.NET で使う用です。
ASP.NET だとサーバー上でコンパイルが行われるので、
開発中とサーバー上でコンパイラーのバージョンが違うと困ります。
なので、Visual Studio を使って開発している最中も、指定のバージョンのコンパイラーが使われるようにするのがこのパッケージ。</p>
<p>パッケージ中には、csc 以下ビルドに必要なバイナリ一式と、
そっちの csc を使う設定が書かれた props ファイル(csproj に対してインポートするヘッダー ファイルみたいなもの)が入っています。</p>
<p><a href="https://github.com/ufcpp/UnitySamples/blob/master/2017%2010%2019%20CrashUnityVs15.5/Lib/Lib155-240.csproj#L9">このバージョン 2.4.0 を、unsafe コードを使っているプロジェクトで参照するようにしてみた</a>ところ、
Unity が落ちなくなる(DLL の中身を ildasm したところ、<code>conv.i</code> に戻っている)ことは確認済み。</p>
<h3>問題点</h3>
<p>一応、以下のような問題もあります。</p>
<ul>
<li>
C# のバージョン自体を下げているので、これを参照したプロジェクトでは C# 7.2 が使えない
<ul>
<li>影響が出るのはパッケージを直接参照しているプロジェクトだけです</li>
</ul>
</li>
<li>
さし変わるのはビルドに使うコンパイラーだけなので、Visual Studio 上ではエラーにならないのに、ビルドしたらエラーが出ることがある
<ul>
<li>C# 7.2 の文法を使ってしまった場合だけです</li>
</ul>
</li>
<li>体感できるほどの差はないものの、微妙にコンパイルが遅いはず</li>
<li>
C# の言語バージョンと、Microsoft.Net.Compilers パッケージのバージョンが違いすぎてどれがどれかわからない
<ul>
<li>今回の場合は 2.4.0 で大丈夫です。2.4.0 は C# 7.1 になります</li>
</ul>
</li>
</ul>
<h2>まとめ</h2>
<ul>
<li><code>conv.u</code> (unsigned)</li>
<li>
今のVisual Studio
<ul>
<li>ダウングレードしにくい</li>
<li>side by side インストールしにくい</li>
</ul>
</li>
<li>
ビルド時に使う C# コンパイラーを差し替えたければ<a href="https://www.nuget.org/packages/Microsoft.Net.Compilers/">Microsoft.Net.Compilers</a>パッケージをNuGet参照
<ul>
<li>Visual Studio 上のコード補完の挙動とビルドの挙動が変わるので注意</li>
<li>ASP.NET 以外で使う日が来るとは…</li>
</ul>
</li>
</ul>
 ]]></description>
				<pubDate>Mon, 11 Dec 2017 19:37:14 +0900</pubDate>
			</item>
			<item>
				<title>バグ報告祭り</title>
				<link>http://ufcpp.net/blog/2017/12/バグ報告祭り/</link>
				<description><![CDATA[ <p>やっぱリリースするといろいろバグを見つけるよねと言う話
(<a href="http://ufcpp.net/blog/2017/12/vs15_5/">Visual Studio 15.5がリリース</a>されて以来バグ報告たくさん出してる)。</p>
<p>twitter で見かけたのを代理で報告出したり、
前々から気になってたのを改めて調べてみたらコンパイラーのバグだったり、
リリースまでに直るだろうとか高をくくってたやつがまだ直ってなかったり。</p>
<h2>safe stackalloc のインテリセンスが効かない問題</h2>
<p>報告先: <a href="https://github.com/dotnet/roslyn/issues/23584">#23584</a></p>
<p><a href="http://ufcpp.net/study/csharp/resource/span/#safe-stackalloc"><code>Span&lt;T&gt;</code>構造体で受け取れば、safe な文脈で <code>stackalloc</code>が使える</a>んですが、
これがコード補完に出てこないという問題。</p>
<p><img src="/media/1156/stackalloc.png" alt="stackalloc の補完が出ない" /></p>
<p>インテリセンスのみの問題で、コンパイルは問題なく通ります。</p>
<p>まあ、<code>stackalloc</code>を必要とする人が少ない上に、
この機能を使うには<a href="http://ufcpp.net/study/csharp/resource/span/#fast-span">fast Span</a>が必須。
これが入ってるのは .NET Core 2.1 (まだプレビュー)ということで、
まず試してみてる人がかなり少なそう。</p>
<p>.NET Core 2.1 の正式リリースまでに直ってればいいって感じなのかなぁとか思いつつ一応報告してみたら、
報告した瞬間に修正してたのでやっぱ報告しないと行けなかった奴でした。</p>
<h2>式形式(=&gt;) get/set プロパティが、自動実装と誤認されてる問題</h2>
<p>報告先: <a href="https://github.com/dotnet/roslyn/issues/23668">#23668</a></p>
<p>以下のようなコードで警告が出るという問題。</p>
<pre class="source" title="">
<code><span class="comment">// Warning CS0282</span>
<span class="comment">// この警告は、partial で複数の場所にフィールドを書くと出る。</span>
<span class="comment">// 自動実装プロパティも、自動でフィールドが作られるので partial を分けて書くと警告に。</span>
<span class="reserved">partial</span> <span class="reserved">struct</span> <span class="type">X</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> A { <span class="reserved">get</span>; <span class="reserved">set</span>; }
}

<span class="reserved">partial</span> <span class="reserved">struct</span> <span class="type">X</span>
{
    <span class="comment">// こいつは自動実装じゃないのでフィールド作られないはずなんだけど…</span>
    <span class="comment">// get =&gt;/set =&gt; 型のプロパティは、自動実装プロパティと誤判定するらしい。</span>
    <span class="reserved">int</span> B { <span class="reserved">get</span> =&gt; A; <span class="reserved">set</span> =&gt; A = value; }
}
</code></pre>
<p>職場のコードでずっと前から消えない警告があって気になってたんですけども…</p>
<p>大々的にコード生成で作ってるところなので、実際はもっと複雑な partial の分かれ方になっていて、
何が原因かわからず。
時間が解決する(自分が報告しなくてもそのうち治る)かなぁ？とか思っていたものの、15.5でもまだ残っていたので本腰入れて調べたところ、やっと原因を特定したのがこれです。</p>
<p>結局、どうも、プロパティの<a href="http://ufcpp.net/study/csharp/oo_property.html#expression-bodied"><code>get</code>/<code>set</code>を<code>=&gt;</code>を使って書く</a>と、<a href="http://ufcpp.net/study/csharp/oo_property.html#auto">自動実装プロパティ</a>と誤判定するみたいです。
確か、<code>{}</code>で書いてる時と<code>=&gt;</code>で書いてる時、Roslynの抽象構文木が違うんですよねぇ。
それで誤判定してるんじゃないかと。</p>
<p>これも、報告入れた瞬間に修正入ってました。</p>
<h2>リファクタリング機能が明示的実装を考慮していない</h2>
<p>報告先: <a href="https://github.com/dotnet/roslyn/issues/23672">#23672</a></p>
<p>明示的実装をしていて、インターフェイス越しにしかアクセスできないはずの<code>Add</code>に対して、
「コレクション初期化子を使う」リファクタリングが効いてしまって、
リファクタリング結果がコンパイル エラーになるという問題。</p>
<p><img src="/media/1157/ide0028.png" alt="IDE0028が不正な結果を作る" /></p>
<p>該当のQuick Actionを掛けない限り問題はないやつです。</p>
<p><a href="https://twitter.com/taiga_takahari/status/939053041898070016">これはtwitterで見かけたの</a>の代理報告。</p>
<p>類似の報告(コレクション初期化子じゃなくてオブジェクト初期化子のもの)は元々バグ報告が出てたみたいです。
Quick Action のID (IDE0028)で検索を掛けたので見つからず(コレクション初期化子のとオブジェクト初期化子のでIDが別)。
どうも、もうバグ修正のプルリクは出てたみたいです。</p>
<h2>in 引数がバグりまくり</h2>
<p>報告先: <a href="https://github.com/dotnet/roslyn/issues/23636">#23636</a></p>
<p>本日の一番やばいやつ。</p>
<p><a href="http://ufcpp.net/study/csharp/sp_ref.html#in"><code>in</code>引数</a>がかなりバグりまくり…</p>
<p>これも<a href="https://twitter.com/Temarin_PITA/status/939732108326592512">twitterで見かけたの</a>の代理報告。
<a href="https://qiita.com/Temarin/items/b21b2b8367d41c2bd34e">ご本人のブログあり</a>。</p>
<p>こいつは、実行時エラーを起こすやつなので、踏むと結構デバッグが面倒な奴です…</p>
<p><code>in</code>引数には、<code>ref</code>と違って</p>
<ul>
<li>呼び出し側には <code>in</code> を付けるのが必須じゃない</li>
<li>リテラルを渡せる</li>
<li>既定値を与えられる</li>
</ul>
<p>とかいう特徴があるわけですが、この辺りがちょうどバグりまくり。</p>
<p>具体的には、参照で渡さないといけないのに、呼び出し側の命令が「値を読む命令」になってて、
ただの値をポインターとして使ってしまって<code>NullReference</code>やら<code>AccessViolation</code>やら<code>ExecutionEngine</code>やらの例外が出まくり。</p>
<p>起こる条件も複数あって、以下のようなものなどなど。</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/issues/23636#issuecomment-350258948">値渡しなデリゲートに対して、<code>in</code>引数なメソッドを渡す</a>(本来この時点でエラーになるべきが、渡せてしまう)</li>
<li><a href="http://ufcpp.net/study/csharp/sp4_optional.html#optional">オプション引数</a>をいくつか持ったメソッドに対して、<a href="https://github.com/dotnet/roslyn/issues/23636#issuecomment-350268710">一部分だけ引数を明示的に渡す</a>(後ろの方だけ既定値を使う)</li>
<li><code>in</code>引数に対して<a href="https://github.com/dotnet/roslyn/issues/23636#issuecomment-350268710">参照型の<code>this</code>を渡す</a></li>
</ul>
<p>この2日くらいで別パターンが出るわ出るわ…</p>
<p>まあ、<code>in</code>引数周りの仕様、
つい最近までどこにもドキュメントがなかったんですよねぇ。
<a href="https://github.com/dotnet/csharplang/pull/1165">最新の仕様に合わせてドキュメントを修正</a>し始めたのが9日前。
マージされたのが3日前…</p>
<p><a href="http://ufcpp.net/study/csharp/cheatsheet/ap_ver7_2/">うちのサイト</a>は一通りちゃんと網羅してるものの、
「確かプルリク出てたからもう実装されているはず」みたいな調べ方して書いてるものだったり。
普通はドキュメントにないもの試さないですよねぇ。
試されないものはそりゃバグが残る…</p>
<h2>バグ報告祭りしてみて</h2>
<p>その後の経過など:</p>
<ul>
<li>分かりやすい再現コードを付けて報告を出したら一瞬で修正入る。</li>
<li>報告 issue に書いたコードが<a href="https://github.com/dotnet/roslyn/pull/23680/files/2d739d1d5266234a258103f90160066090d567d2..c59b4da22686f130ce7e18be18d0c5a5f32453a0">そのままテスト コードに入る</a>。</li>
<li>リリース直前2週間程度で見つかったバグは普通にバグったままリリースされてる</li>
<li>たぶん、15.6プレビューの次のやつでいろいろ直ってるはず</li>
</ul>
 ]]></description>
				<pubDate>Sun, 10 Dec 2017 19:45:17 +0900</pubDate>
			</item>
			<item>
				<title>アナライザーのプロジェクト テンプレートとか dotnet new のテンプレートの話</title>
				<link>http://ufcpp.net/blog/2017/12/analyzerconvention/</link>
				<description><![CDATA[ <p>今日は <code>dotnet new</code>向けのテンプレートを書いてみたという話。</p>
<p>Visual Studio 標準の &quot;Analyzer  with Code Fix&quot; テンプレートにちょこっと手を入れたやつです。</p>
<ul>
<li><a href="https://github.com/ufcpp/AnalyzerConvention">AnalyzerConvention</a></li>
</ul>
<h2>背景</h2>
<h3>自作アナライザー</h3>
<p>昔、結構<a href="http://ufcpp.net/study/csharp/package/pkgcodeawarelibrary/">アナライザー</a>を書いてたんですよ。</p>
<ul>
<li><a href="https://github.com/ufcpp/ValueChangedGanerator">ValueChangedGanerator</a></li>
<li><a href="https://github.com/ufcpp/RecordConstructorGenerator">RecordConstructorGenerator</a></li>
<li><a href="https://github.com/ufcpp/LazyMixin">LazyMixin</a></li>
<li><a href="https://github.com/ufcpp/BitFields">BitFields</a></li>
</ul>
<h3>アナライザーに対する規約ベースのテスト</h3>
<p>で、アナライザーって、標準のテンプレートだとテストを書くのが結構面倒なので、
規約ベースで</p>
<ul>
<li>所定のパスに解析対象のソースコードを置く</li>
<li>別のあるパスに Code Fix 結果のソースコードを置く</li>
</ul>
<p>みたいな仕組みを作ったことがあります。
それがこれ。</p>
<ul>
<li><a href="https://github.com/ufcpp/ConventionCodeFixVerifier">ConventionCodeFixVerifier</a></li>
</ul>
<p>NuGet パッケージにしてあって、パッケージ参照すると標準テンプレートのファイルをいくつか上書きします。</p>
<h3>新 NuGet</h3>
<p>ConventionCodeFixVerifier を書いたのはもうだいぶ昔でして、その当時は NuGet も csproj の形式も古かった時代です。</p>
<p>NuGet はまだ packages.confing とか使ってた頃。
NuGet はその後、project.json 形式 → csproj 中に PackageReference タグを書くように変化しまして。
packages.config 時代とは、「プロジェクト中のファイルを上書き」みたいなのをやりたいときの挙動が違います。
ということで、ConventionCodeFixVerifier も更新しないと今はちゃんと動かないんですが…</p>
<p>その一方で、NuGet でプロジェクト中のファイルを上書きするのも嫌な運用だなぁとかずっと思っていました。
むしろ、プロジェクト テンプレートを作るべき事案だろうと。</p>
<h3>SDK-based csproj</h3>
<p>あと、Visual Studio 2017で<a href="http://ufcpp.net/blog/2017/5/newcsproj/">csprojの形式も新しくなったじゃないですか</a>。
SDK-based csproj とか呼ぶみたいなんですけども。
csproj の中身がかなりすっきりしてたり、この形式を使った場合だけオンになるビルド機能がちらほらあったり。</p>
<p>なんですけども、つい最近まで、標準の &quot;Analyzer  with Code Fix&quot;テンプレートは旧型式のままだったんですよね。
しかも未だに packages.config を使ってるという古臭い作り。</p>
<p>それが嫌すぎて、ここ1年くらいアナライザーを書くのを面倒がって、作りたいものはあったものの放置になったり、
上記の自作アナライザーの更新も止まっていたり。</p>
<p>それが、どうも 15.5 で SDK-based な形式に移行したみたい。
なので僕のやる気も復活した次第です。</p>
<h3>そうだ、プロジェクト テンプレート作ろう</h3>
<p>とはいえ、前述の通り、NuGet でプロジェクト中のファイルを上書きするやり方はやめたいわけです。
でも、Visual Studio のプロジェクト テンプレートって何か作るのめんどくさくて。</p>
<p>と、迷っていたところで、「<code>dotnet</code> コマンドのやつならマシになってるのでは？」と思って検索した結果、</p>
<ul>
<li><a href="https://docs.microsoft.com/ja-jp/dotnet/core/tools/custom-templates">dotnet new のカスタム テンプレート</a></li>
</ul>
<p>これを読んでみて、「これなら案外行けそうかも」という気分になったので、こっちで作りました。</p>
<h2>作ったもの</h2>
<p>という背景の元作ったのが冒頭の「<a href="https://github.com/ufcpp/AnalyzerConvention">AnalyzerConvention</a>」。</p>
<h3>導入方法</h3>
<p>以下のコマンドでテンプレートをインストールできます。</p>
<pre><code>dotnet new -i AnalyzerProject.Convention
</code></pre>

<p><code>dotnet</code>コマンドで使えるテンプレート、NuGet パッケージを作ればいいらしく、<a href="https://www.nuget.org/">nuget.org</a>からのインストールもできます。
<code>-i</code> オプションがその「nuget.org とかからパッケージを取って来てインストールする」というオプション。</p>
<p>ちなみに、パッケージ化してnuget.orgに上げたの物:</p>
<ul>
<li><a href="https://www.nuget.org/packages/AnalyzerProject.Convention/">https://www.nuget.org/packages/AnalyzerProject.Convention/</a></li>
</ul>
<p>これをインストールすれば、その後、以下のコマンドでプロジェクトを生成できます。</p>
<pre><code>dotnet new AnalyzerConvention
</code></pre>

<h3>内容物</h3>
<p>作ったテンプレートは、</p>
<ul>
<li>Visual Studio 15.5 の標準の&quot;Analyzer  with Code Fix&quot;テンプレート通りにプロジェクト新規作成</li>
<li>
それに<a href="https://github.com/ufcpp/ConventionCodeFixVerifier">ConventionCodeFixVerifier</a>を上書き
<ul>
<li>ただし、もう V1 (古い規約)対応は切りました</li>
</ul>
</li>
<li>テスト プロジェクトを <a href="https://www.nuget.org/packages/xunit/">XUnit</a> に移行</li>
</ul>
<p>というもの。</p>
<p>標準テンプレートがベースなので、「クラス名を全部大文字にする」っていうクソ Code Fix のままです。</p>
<h3>おまけ: SourceName</h3>
<p>この<code>dotnet</code>コマンドのテンプレート、<a href="https://github.com/ufcpp/AnalyzerConvention/blob/master/src/content/.template.config/template.json">設定ファイル</a>の&quot;<code>sourceName</code>&quot;のところに書いた文字列を、<code>new</code>したときのフォルダー名(もしくは<code>-n</code>/<code>--name</code>オプションで指定した名前)で置換する仕組みみたいです。</p>
<p>この<code>sourceName</code>を何にしようか迷った結果…</p>
<p>Ạṇạḷỵẓẹṛ</p>
<p>に。</p>
<p>Analyzer に見えますけども、よく見ると全文字、下にドットが付いています。
Unicode の「Latin Extended Additional」辺りに入っている文字。
これなら普通のソースコードと混ざらないだろうと。</p>
<p>「混ざらない」って目的は無事果たしたんですけども、ファイル名とかフォルダー名も Unicode になっちゃってて…
nupkgって実体はただのZIPファイルなわけですけども、文字化けしてないかが多少不安…
日本語Windows以外で動かなくなってたりしたらどうしよう…</p>
 ]]></description>
				<pubDate>Sat, 09 Dec 2017 23:34:00 +0900</pubDate>
			</item>
			<item>
				<title>Rune と fast Utf8String</title>
				<link>http://ufcpp.net/blog/2017/12/fastutf8string/</link>
				<description><![CDATA[ <p>今日はRoslynじゃなくてCoreFx方面の話だし、issueの投稿日時的には9月とかで割かし「今更」な話。</p>
<ol>
<li><a href="https://github.com/dotnet/corefx/issues/24093">Introducing System.Rune #24093</a></li>
<li><a href="https://github.com/dotnet/corefxlab/issues/1751">New UTF8String APIs #1751</a></li>
</ol>
<h2>Rune</h2>
<p>1個目のやつ、要は「Unicode のコードポイントに相当するプリミティブ型が欲しい」的な話です。</p>
<h3>文字とは…</h3>
<p>プログラミングにおける「文字」に関するおさらい:</p>
<p><img src="/media/1155/unicodechar.png" alt="文字と言えば" /></p>
<p><code>char</code>って何なんだろうね… と路頭に迷った結果が、以下のような感じ。</p>
<table>
<thead>
<tr>
	<th>言語</th>
	<th>UTF-8</th>
	<th>UTF-16</th>
	<th>符号点</th>
	<th>書記素</th>
</tr>
</thead>
<tbody>
<tr>
	<td>C#</td>
	<td>(<code>byte</code>)</td>
	<td><code>char</code></td>
	<td>(<code>uint</code>)</td>
	<td>(<code>string</code>)</td>
</tr>
<tr>
	<td>Swift</td>
	<td>(<code>UInt8</code>)</td>
	<td>(<code>UInt16</code>)</td>
	<td><code>UnicodeScalar</code></td>
	<td><code>Character</code></td>
</tr>
<tr>
	<td>Go</td>
	<td>(<code>uint8</code>)</td>
	<td>(<code>uint16</code>)</td>
	<td><code>rune</code></td>
	<td>(<code>string</code>)</td>
</tr>
<tr>
	<td>Rust</td>
	<td>(<code>u8</code>)</td>
	<td>(<code>u16</code>)</td>
	<td><code>char</code></td>
	<td>(<code>String</code>)</td>
</tr>
</tbody>
</table>
<p>※ <code>()</code> 付きの物は文字としての型がないので「代わりに使うとしたら」</p>
<p>Java とか C# とか、<code>char</code> がUTF-16を指す言語は「前世代」感を隠せないとしても…
Unicode コンソーシアムもこういう用語をちゃんと定めないんもんだから場所によって符号点って呼ばれたりスカラーって呼ばれたり…
Rust は Unicode 符号点を指して <code>char</code> とか呼んでるけども、結合文字とか不可視文字とかあるからやっぱ「それが<code>char</code>か？」と言われると微妙だし…</p>
<p>そ　し　て　Go…</p>
<p>上記の issue を最近始めてちゃんと読んだんですけども、よく見たらこんなことが書いてあるわけですよ。</p>
<blockquote>
<p>&quot;Code point&quot; is a bit of a mouthful, so Go introduces a shorter term for the concept: rune. The term appears in the libraries and source code, and means exactly the same as &quot;code point&quot;, with one interesting addition.</p>
<p>「コード ポイント」とかちょっと長くて言いにくい。なので、Go ではこの概念に対して短い用語、「ルーン」を導入する。この用語がライブラリ・ソース コード中に現れた場合、完全に「コード ポイント」と同じものを意味する。</p>
</blockquote>
<p>(※ 最後の with one interesting additionは、次の段落に書いてある「<code>rune</code>型は<code>int32</code>のエイリアスで、『ルーン定数』も書けるよ」って話の事を指してると思う。)</p>
<p>確かに何というか、今のUnicodeの符号点って、呪術的、儀式的な感じしちゃってるんでルーン呼ばわりもわからなくもないものの…</p>
<p>ルーン文字って、それを文字として使ってた頃は神秘性・呪術性なかったらしいじゃないですか。
(「使わなくなった古代文字とかかっこよくね？」的な中二病で、後世になって神秘性帯びたもの。)
ただの文字ですぜ…</p>
<h3>Proposal: System.Rune</h3>
<p>で、これに倣って、C# にも<code>System.Rune</code>型を足したら？と言い出したのが冒頭の1つ目のissue。</p>
<ul>
<li><a href="https://github.com/dotnet/corefx/issues/24093">Introducing System.Rune #24093</a></li>
</ul>
<p>言いたいことはわかるし、専用の型は確かに欲しいけども、Runeって名前はちょっと…</p>
<p>ちなみに、このissueは<a href="https://github.com/migueldeicaza">Miguel</a>(Xamarin の偉い人)によるものなわけですけども、
この人は製品名に<a href="https://github.com/NuGet/Home/wiki/NuGetizer-3000">NuGetizer 3000</a>とか<a href="https://github.com/mono/Embeddinator-4000">Embeddinator-4000</a>とか付けようとする人なので…
ごめんなさい、Rune もこの人のネーミングセンスだと思って一瞬疑いました…
Go が犯人とは(ちなみに、Go より前から Rune という呼び名使う人はいたっぽい)、疑ってごめんなさい。</p>
<p>Rune。<a href="https://ja.wikipedia.org/wiki/%E3%83%AB%E3%83%BC%E3%83%B3%E6%96%87%E5%AD%97">ルーン文字</a>のrune。
Unicode 内にも U+16A0(ᚠ) ～ U+16F0(ᛰ) の範囲で存在しているルーン文字の、rune。</p>
<p>これ、最悪、</p>
<pre class="source" title="rune is rune">
<span class="comment">// ルーン(符号点のこと)がルーン(ルーン文字のこと)かどうか調べる</span>
<code><span class="type">Rune</span>.IsRune(<span class="string">'ᚠ'</span>);
</code></pre>
<p>が生まれちゃうやつじゃないですか。</p>
<h3>符号点を表す型</h3>
<p>ちなみに、.NET でこの辺りの文字列処理の新ライブラリは、今ちょうど、<a href="https://github.com/dotnet/corefxlab">corefxlab</a>で参考実装を作っているところです。
(corefx に移ってなくて corefxlab 内で日々変更が入ってるような状態なので、リリースまではまだもうちょっと掛かりそう。)</p>
<p>で、corefxlab 産の <code>Utf8String</code>、1年くらい前までは<code>CodePoint</code>構造体を持ってたんですよねぇ。
それが、今は<a href="https://github.com/dotnet/corefxlab/blob/010238eb489ccfb04a47774cc606653afb82464a/src/System.Text.Utf8String/System/Text/Primitives/Utf8CodePointEnumerator.cs#L22"><code>uint</code>生利用</a>に変わっています。
わざわざ、専用の型を削除。</p>
<p>たぶんなんですけども、パフォーマンスのためですかねぇ。
プリミティブ型を構造体でくるんじゃうと、JIT 結果的に、レジスターを使った最適化が掛かりにくくなるみたいな話も見たことがあり。
(ちゃんと最適化が掛かるようにしたい的な issue だったはずなので、今なら最適化掛かるかも？)</p>
<h2>Fast Utf8String</h2>
<p>そんなRuneの提案ですが、そのさらにきっかけになった別提案が、2つ目のissue。</p>
<ul>
<li><a href="https://github.com/dotnet/corefxlab/issues/1751">New UTF8String APIs #1751</a></li>
</ul>
<p>個人的にはむしろ、こっちの方にこそ面白そうな話が。</p>
<p>元々、<code>Utf8String</code>は以下のような型として提案されてました。</p>
<pre class="source" title="">
<code><span class="reserved">ref</span> <span class="reserved">struct</span> <span class="type">Utf8String</span>
{
    <span class="type">ReadOnlySpan</span>&lt;<span class="reserved">byte</span>&gt; _buffer;
}
</code></pre>
<p>で、これだと「ヒープ上に持っていけないのが不便」と言われ、以下のように変化。</p>
<pre class="source" title="">
<code><span class="comment">// stack-only</span>
<span class="reserved">ref</span> <span class="reserved">struct</span> <span class="type">Utf8Span</span>
{
    <span class="type">ReadOnlySpan</span>&lt;<span class="reserved">byte</span>&gt; _buffer;
}

<span class="comment">// <em>ヒープに置ける</em></span>
<span class="reserved">struct</span> <span class="type">Utf8String</span>
{
    <span class="reserved">byte</span>[] _buffer;
}
</code></pre>
<p>さらに、「構造体嫌だ…」と言われます。
なんせ、<a href="https://source.dot.net/#System.Collections.Immutable/System/Collections/Immutable/ImmutableArray.cs"><code>ImmutableArray</code></a>とかでさんざん苦労しているそうで。
この手の「参照型を1個ラップするのに、アロケーションを減らしたくて構造体にした」みたいな型はいろいろと事故ります。
<code>object</code> とかインターフェイスに渡すときにボックス化でパフォーマンス落としたり、
<code>Interlocked.Exchange</code>がしづらかったり、
「参照型もどき」な癖にさらにそのnullableが作れてしまったり。</p>
<p>ということで、以下のように変化。</p>
<pre class="source" title="">
<code><span class="comment">// stack-only</span>
<span class="reserved">ref</span> <span class="reserved">struct</span> <span class="type">Utf8Span</span>
{
    <span class="type">ReadOnlySpan</span>&lt;<span class="reserved">byte</span>&gt; _buffer;
}

<span class="comment">// ヒープに置けるというか、最初から<em>参照型</em></span>
<span class="reserved"><em>class</em></span> <span class="type">Utf8String</span>
{
    <span class="reserved">byte</span>[] _buffer;
}
</code></pre>
<p>もちろん、これだと、クラスの中に配列があって、ヒープ確保・間接参照が2段階になります。
パフォーマンス的にはちょっと微妙。
(それでも、前述の構造体であることによる問題よりはマシな感じあり。)</p>
<p>なので、上記提案の中には、</p>
<ul>
<li>いつかはやっぱり <code>string</code> 並みのランタイムによる特殊実装入れたい</li>
<li><code>Utf8String</code> は可変長クラスにしたい</li>
</ul>
<p>みたいな話も出ました。</p>
<p>現状、「可変長」が許されている型は<code>string</code>と配列だけで、この2つだけかなり特殊扱いされています。
ユーザー定義で可変長な型が許されていれば、<code>ImmutableArray</code>とか今回の<code>Utf8String</code>でこんなに悩む必要もなく、単にクラスで実装すれば済むわけです。
ユーザー定義は認めないまでも、<code>Utf8String</code>くらいは可変長クラスであることを認めろよ、という風な流れに。
(この場合、対応しているランタイムであればそういう「特殊実装で可変長」(fast <code>Utf8String</code>)、
していないランタイムであれば前述の「中身は単に配列」(slow <code>Utf8String</code>)な2つの実装を用意することになります。)</p>
<p>fast <code>Utf8String</code>、かなり欲しい…
(「後で最適化するのも考えるから、とりあえず今はクラスにするの認めろよ」的な方便でもあるんで、
実際この最適化版<code>Utf8String</code>がいつ実装されるかは未知ですが…)</p>
 ]]></description>
				<pubDate>Wed, 06 Dec 2017 23:21:56 +0900</pubDate>
			</item>
			<item>
				<title>Visual Studio 15.5 Release</title>
				<link>http://ufcpp.net/blog/2017/12/vs15_5/</link>
				<description><![CDATA[ <p>正式リリース来ちゃった。</p>
<ul>
<li><a href="https://www.visualstudio.com/en-us/news/releasenotes/vs2017-relnotes">リリース ノート</a></li>
<li><a href="https://blogs.msdn.microsoft.com/visualstudio/2017/12/04/visual-studio-2017-version-15-5-visual-studio-for-mac-released/">Visual Studio チームのブログ</a></li>
</ul>
<p>ソリューションのロード時間が半分くらいになってるんで一刻も早く使いたいんですけども…</p>
<p>先日、↓の勉強会の最後の方(31ページ目～)でちょっと話した通り、Unity でちょっと問題が出ていて、職場のPCではアップデートしばらくできないかも…</p>
<div>
<iframe src="//www.slideshare.net/slideshow/embed_code/key/E2LF7YT1rWRdKw" width="595" height="485" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe> <div style="margin-bottom:5px"> <strong> <a href="//www.slideshare.net/ufcpp/unity-c-60-net-46" title="Unityで使える C# 6.0～と .NET 4.6" target="_blank">Unityで使える C# 6.0～と .NET 4.6</a> </strong> from <strong><a href="https://www.slideshare.net/ufcpp" target="_blank">信之 岩永</a></strong> </div>
</div>
<h2>C# 7.2 リリース</h2>
<p>ということで、C# 7.2 もリリース。
C# 7.1 が8月だったので、4か月ほどでのバージョン アップ。</p>
<p>C# 7.1 の時と同様、7.2 を有効にするには <code>LangVersion</code> 指定が必要です。</p>
<p><img src="/media/1154/langversionlatest.png" alt="LangVersion latest" /></p>
<pre class="xsource" title="">
<code><span class="attvalue">&lt;</span><span class="element">Project</span><span class="attvalue"> </span><span class="attribute">Sdk</span><span class="attvalue">=</span>"<span class="attvalue">Microsoft.NET.Sdk</span>"<span class="attvalue">&gt;</span>

<span class="attvalue">  &lt;</span><span class="element">PropertyGroup</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">TargetFramework</span><span class="attvalue">&gt;</span>netcoreapp2.0<span class="attvalue">&lt;/</span><span class="element">TargetFramework</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">LangVersion</span><span class="attvalue">&gt;</span><em>latest</em><span class="attvalue">&lt;/</span><span class="element">LangVersion</span><span class="attvalue">&gt;</span>
<span class="attvalue">  &lt;/</span><span class="element">PropertyGroup</span><span class="attvalue">&gt;</span>

<span class="attvalue">&lt;/</span><span class="element">Project</span><span class="attvalue">&gt;</span>
</code></pre>
<p>うちのサイト、今回はもうちゃんと全機能網羅できているはず。</p>
<ul>
<li><a href="/study/csharp/cheatsheet/ap_ver7_2/">C# 7.2 の新機能</a></li>
</ul>
<p>あと、<code>ref</code> がらみの総まとめ的なページを足したいとかは思ってるんですけども、
まあ、機能それぞれ個別には全部書いているはずです。</p>
<p>C# 7.2 は、<code>ref</code>がらみの機能が多く、パフォーマンスに関するアップデートになります。
とりあえず C# コンパイラーとしての作業は今回のアップデートで完了という感じなんですが、
.NET 全体としては、</p>
<ul>
<li><code>Span&lt;T&gt;</code> を安全に使うための C# 機能が入る(今ここ)</li>
<li><code>Span&lt;T&gt;</code> の正式リリース</li>
<li><code>I/O</code> がらみのライブラリが <code>Span&lt;T&gt;</code> に対応</li>
<li>アプリが <code>Span&lt;T&gt;</code> 版のライブラリを使いだす</li>
</ul>
<p>となって初めてパフォーマンス的な恩恵になるので、まだ1歩目を踏み出したところということで、今後に期待となります。</p>
<h2>C# のこの先の話</h2>
<p>次は、7.X 系でもう1回小さいリリースをした後、8.0 でメジャー アップデートになりそうな感じでしょうか。
7.1 から 7.2 では4か月の短いリリース サイクルだったわけですけども、
その分やっぱり新機能は細かく分割された感じがあります。
<a href="https://github.com/dotnet/csharplang/milestone/11">C# 7.3 候補</a>は、7.0 の頃から候補になっているものの優先度が低く設定されていたものや、7.2 の積み残しみたいなものが並んでいます。</p>
<p>一方で、大きい機能は<a href="https://github.com/dotnet/csharplang/milestone/8">C# 8.0 候補</a>に並んでいます。
元々 8.0 に並んでいた<a href="https://github.com/dotnet/csharplang/issues/36">nullable reference types</a>や<a href="https://github.com/dotnet/csharplang/issues/52">default interface method</a>に加えて、
<a href="https://github.com/dotnet/csharplang/issues/45">パターン マッチングの完全版(再起パターン)</a>も、今は8.0ということになっています。</p>
 ]]></description>
				<pubDate>Tue, 05 Dec 2017 14:35:31 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 11/16: Microsoft Connect(); 2017</title>
				<link>http://ufcpp.net/blog/2017/11/pickuproslyn1116/</link>
				<description><![CDATA[ <p><a href="https://www.microsoft.com/ja-jp/events/connect2017.aspx">Connect</a> の1日目がありましたが。</p>
<h2>Live Share</h2>
<p>今回一番気になったのは、<a href="https://code.visualstudio.com/blogs/2017/11/15/live-share">Visual Studio Live Share</a>ですかね。
Visual Studio 2017とVisual Studio Codeで、コーディングやデバッグをリアルタイムに画面共有するコラボツール。</p>
<p>複数のオフィスに分かれるような大企業か、大々的にリモート勤務を推してるような会社でないといきなりは使い道ないでしょうけども。
自分も今務めてるのは1フロアに収まる規模のチームですし、基本的には「開発者はフロアをまたぐと開発に支障が出る」というポリシーなんですけども。
とはいえ、「育休で1年だけリモート」みたいなのは十分あり得るので。</p>
<h2>C#</h2>
<p>まあ、このサイトとしてはこっちが主役。C# 7.2と、その先の話題。</p>
<h3>What's new in C# 7.2</h3>
<p><a href="http://ufcpp.net/blog/2017/10/visualstudio15_5/">Visual Studio 15.5 Preview</a>が出た時点からC# 7.2は試せるわけで、
「普段から追っていれば」新しい話題も特にないんですけども。</p>
<p>ただ、最近ドキュメントがらみが後手に回りがちな C# チームが、今回はちゃんとConnectに合わせて仕事しましたよ！</p>
<ul>
<li>docs 上に<a href="https://docs.microsoft.com/ja-jp/dotnet/csharp/whats-new/csharp-7-2">What's new in C# 7.2</a></li>
<li><a href="https://blogs.msdn.microsoft.com/dotnet/2017/11/15/welcome-to-c-7-2-and-span/">Welcome to C# 7.2 and Span</a></li>
</ul>
<h3>null許容参照型</h3>
<p>あと、null許容参照型 (参照型でも修飾なしのは「非null」扱いにして、<code>?</code> を付けて初めて nullableにするってやつ)のプレビューがアナウンスされました。</p>
<ul>
<li><a href="https://blogs.msdn.microsoft.com/dotnet/2017/11/15/nullable-reference-types-in-csharp/">Introducing Nullable Reference Types in C#</a></li>
<li><a href="https://github.com/dotnet/csharplang/wiki/Nullable-Reference-Types-Preview">Nullable Reference Types Preview</a></li>
</ul>
<p>短縮URLまで取って: <a href="https://aka.ms/nullable-preview">aka.ms/nullable-preview</a></p>
<p>(これも、このドキュメント自体は数週前から着々と準備が進んでたんですけど、正式に。)</p>
<p>こちらはだいぶ先を見た話です。
null許容参照型という機能自体、予定としては C# 8.0 でのリリースを目指している機能で、7.2すらプレビューな現状からするとだいぶ先のものの、かなり早い段階のプレビュー版です。
15.5 Preview を入れれば割かし低リスクで試せる C# 7.2 と違って、
別途インストーラーを実行して Visual Studio (の参照しているコンパイラー)を上書きするタイプなので注意が必要です。</p>
 ]]></description>
				<pubDate>Thu, 16 Nov 2017 13:49:35 +0900</pubDate>
			</item>
			<item>
				<title>GraphemeSplitter の副産物(絵文字調査ツールとRangeスイッチ)</title>
				<link>http://ufcpp.net/blog/2017/11/graphemesplitterbyproduct/</link>
				<description><![CDATA[ <p><a href="/blog/2017/10/graphemesplitter/">先週</a>書いた <a href="https://github.com/ufcpp/GraphemeSplitter">GraphemeSplitter</a> の話からの派生で2点。</p>
<h2>常設の Web サイト化</h2>
<p><a href="https://github.com/ufcpp/GraphemeSplitter/tree/master/RazorPageSample">GraphemeSplitter のサンプル</a>のつもりで ASP.NET Razor Page なページを1個作ったんですけども。</p>
<p>その後。</p>
<ul>
<li>なんか気になる絵文字を見かけた</li>
<li>絵文字なのでそれの正確な意味わからないくて気になる</li>
<li>しょうがないからその絵文字でググったり</li>
<li>文字コードを調べて U+1F680 でググったり(面倒)</li>
<li>そうだ、こないだ作ったサンプル用のページでコード調べられる</li>
<li>Visual Studio でわざわざデバッグ実行起動するのばかばかしくなってきた</li>
<li>そうだ、<a href="http://ufcppfree.azurewebsites.net/Grapheme">Azure の Free プランでホストしとこう</a></li>
<li>ついでだから便利機能(自分用)足しとこう(今ここ)</li>
</ul>
<p><img src="/media/1147/%E3%82%AD%E3%83%A3%E3%83%97%E3%83%81%E3%83%A3.png" alt="ということで、書記素分割サンプルの今" /></p>
<p>追加した機能は以下のようなもの。</p>
<ul>
<li>入力用のフォームを設置</li>
<li>1コードポイントごとにばらした文字も表示</li>
<li>文字コードに対して、「<a href="https://www.google.co.jp/search?q=U%2B1F680">U+1F680</a>」みたいなGoogle検索のURLのリンクを生成</li>
</ul>
<p>書記素分割というか、単なる絵文字調査ツールになりました。
仕組み上、絵文字だけじゃなくて、ASCII顔文字の類も調べられます。</p>
<p>ソースコードは「自分用」と言わんばかりに <a href="https://github.com/ufcpp/UfcppSample/tree/master/Tools/UnicodeService">UfcppSample リポジトリの Tools フォルダー以下</a>に置いてたり。</p>
<h2>Rangeベースのswitch-case</h2>
<p>書記素分割のために、unicode.org 内の <a href="http://www.unicode.org/Public/10.0.0/ucd/auxiliary/GraphemeBreakProperty.txt">GraphemeBreakProperty</a> ってデータを参照して、そこからコード生成で<code>switch</code>ステートメントを作ったわけですが。<a href="https://github.com/ufcpp/GraphemeSplitter/blob/master/GraphemeBreakPropertyCodeGeneratorTest/Benchmark.switch.cs">2万行弱のクソコード</a>っぷりがひどく…</p>
<p>で、以下のような最適化を掛けてほしいというの、<a href="https://github.com/dotnet/roslyn/issues/22997">とりあえず issue 立てとくことに</a>。</p>
<pre class="source" title="">
<code><span class="comment">// 1コード1 case に展開 (最適化が掛かって結構速いけど、クソコード。コンパイル時間もやたらと遅い)</span>
<span class="reserved">switch</span> (codePoint)
{
    <span class="reserved">case</span> 1536:
    <span class="reserved">case</span> 1537:
    <span class="reserved">case</span> 1538:
    <span class="reserved">case</span> 1539:
    <span class="reserved">case</span> 1540:
    <span class="reserved">case</span> 1541:
        <span class="comment">// ...</span>
}

<span class="comment">// when 句を使って範囲を表現 (コードは綺麗になったけど、条件判定が線形探索になっちゃって O(n)。遅い)</span>
<span class="comment">// 二分探索するような最適化をしてほしい</span>
<span class="reserved">switch</span> (codePoint)
{
    <span class="reserved">case</span> <span class="reserved">uint</span> i0 <span class="reserved">when</span> 1536 &lt;= i0 &amp;&amp; i0 &lt;= 1541:
        <span class="comment">// ...</span>
}

<span class="comment">// こういう文法ほしい(C# 8とか9とかくらいでは入るかなぁ、きっと)</span>
<span class="comment">// これなら、コードが綺麗、かつ、最適化しやすいのではないか</span>
<span class="reserved">switch</span> (codePoint)
{
    <span class="reserved">case</span> 1536..1541:
        <span class="comment">// ...</span>
}
</code></pre>
<p>まあさすがに、実用途の説明と、ベンチマークを添えとくと反応よさげ。<code>case 1536..1541</code> みたいな書き方であれば範囲の重複チェック(同じ値の
 <code>case</code> が複数あったらエラーにする)のとか、二分探索化する最適化もしやすそうということで、興味を持ってもらえたっぽい。</p>
 ]]></description>
				<pubDate>Sun, 05 Nov 2017 14:09:28 +0900</pubDate>
			</item>
			<item>
				<title>絵文字の連結と、書記素クラスター判定</title>
				<link>http://ufcpp.net/blog/2017/10/graphemesplitter/</link>
				<description><![CDATA[ <p><a href="https://twitter.com/ufcpp/status/923379224223793152">みんな絵文字好きすぎだろ…</a></p>
<p>というRT状況なわけですが。</p>
<h2>emoji zwj sequences</h2>
<p>元々、👪 (U+1F46A)という、1文字で家族を表す絵文字があったわけですが。</p>
<p>「白人の絵しかないのはおかしい」とか「LGBT に配慮しろ。なぜ男女ペアしかないんだ」とかいろいろと地雷になってしまった結果、
<a href="http://www.atmarkit.co.jp/ait/articles/1604/27/news051.html">合字で解決しよう</a>とかいう仕様が Unicode に入ってしまって今に至っているわけですが。</p>
<p>ちなみに、単に合字になるというだけじゃなくて、
「合字は1文字として扱え」という仕様も決まっています。
仕様は以下のページにあり。</p>
<ul>
<li><a href="http://unicode.org/reports/tr29/">Unicode® Standard Annex #29 UNICODE TEXT SEGMENTATION</a></li>
</ul>
<p>まあ、仕様があるといってもそれにアプリが対応しているかどうかというとまちまち。
以下の動画でのChromeの動作みたいに、「ページ中ではちゃんと1文字として扱う」、「アドレスバーでは家族1人1人がバラバラに」という挙動になったり。</p>
<div>
<iframe width="560" height="315" src="https://www.youtube.com/embed/9SCONCSjMnU" frameborder="0" gesture="media" allowfullscreen></iframe>
</div>
<p>で、この<a href="http://unicode.org/reports/tr29/">Annex #29</a>の仕様では、
家族どころか、絵文字を ZWJ (zero width joiner: ゼロ幅接合子)で繋げば何人でもつながります。
これが、emoji zwj sequences というやつ。</p>
<p>そして、ZWJ でいくらでもつながるんですけど、それをグリフ的にどう描画すべきかというとまたこれが難しくて、その結果が<a href="https://twitter.com/ufcpp/status/923379224223793152">冒頭のツイート</a>の内容。</p>
<p><img src="https://pbs.twimg.com/media/DNCAUS3VQAAY3yV.jpg:large" alt="emoji zwj sequences" /></p>
<h2>「合字は1文字として扱え」仕様 … 書記素判定</h2>
<p>ちなみに、「グリフ的に1つにくっつくから、ユーザーから見ると1文字に見える」、
「なので、カーソル移動や削除の際には1文字として扱え」というものを書記素(grapheme)といいます。</p>
<p><a href="http://unicode.org/reports/tr29/">Annex #29</a>は「書記素の区切りはどこか」(と、単語の区切り、センテンスの区切り)を判定するためのルールを決めたものです。
先ほどの動画を見ての通り環境次第ではあるんですが、最近のOSは結構ちゃんとこの「書記素の区切り判定」を実装しています。</p>
<h2>C# で書記素判定するライブラリ</h2>
<p>でも、この辺りは割かし新しい仕様な上に、Unicode のバージョン依存が激しく、あんまり実装したい類の処理ではなく。
その結果、プログラミングに使えるライブラリとしてはあんまり提供されてなかったり。</p>
<p>標準ライブラリで書記素判定が提供されているものは少ないですし、
あっても「Unicode 8.0の仕様」、「家族絵文字や肌色には対応できない」とかだったりもします。</p>
<p>ということで、ないものは自分で作ったのがこちら。</p>
<ul>
<li><a href="https://github.com/ufcpp/GraphemeSplitter">GraphemeSplitter</a></li>
</ul>
<p>書記素判定の C# 実装です。
一応、Unicode 10.0 相当。</p>
<p>Web とかゲームとかでこの手の文字数判定をやりたくなることもあるでしょうし。
.NET Framework 3.5 にも対応してあるので、もしなんなら <a href="https://unity3d.com/">Unity</a> でもお使いいただけると思います。</p>
<h3>おまけ</h3>
<p>結構いやいやではあるんですけど。
どのくらい嫌かは、この2万行近い switch ステートメントを見てもらえれば伝わるかと思います…</p>
<ul>
<li><a href="https://github.com/ufcpp/GraphemeSplitter/blob/master/GraphemeSplitter/Character.GetGraphemeBreakPropertyV10.cs">Character.GetGraphemeBreakPropertyV10.cs</a></li>
</ul>
<p>要するに、どの文字がどういうカテゴリーなのか、1文字1文字テーブルを引く必要があって、
このテーブルがとにかく巨大です。
しかも Unicode のバージョン依存。</p>
<p>ちなみに、この2万行近い switch ステートメントは、<a href="http://www.unicode.org/Public/10.0.0/ucd/auxiliary/GraphemeBreakProperty.txt">unicode.org が提供しているテーブル データ</a>からコード生成で作っています。
C# コンパイラーが結構いい感じに最適化してくれるんで割かし高速なコードが生成されるんですけども、
その代わり、この1ファイルがあるだけでコンパイル時間がものすごい伸びます…</p>
 ]]></description>
				<pubDate>Sun, 29 Oct 2017 16:40:16 +0900</pubDate>
			</item>
			<item>
				<title>Visual Studio 15.5 Preview</title>
				<link>http://ufcpp.net/blog/2017/10/visualstudio15_5/</link>
				<description><![CDATA[ <p>こないだ <a href="https://blogs.msdn.microsoft.com/visualstudio/2017/10/10/visual-studio-2017-version-15-4-released/">Visual Studio 2017 Version 15.4</a>の正式リリースが出たところですが。
(主にUWP/Windows 10 Fall Creators Update絡みだったので個人的にはバグフィックス以外そこまで恩恵なし。)</p>
<p>翌日にもう[Visual Studio 2017 Version 15.5のプレビュー版]が。</p>
<p>「Stepping Back」デバッグ(1つ前のブレークポイントに状態を戻せる機能)とか割かし素敵そうな。</p>
<p>それはそれとして、15.5の告知ブログにはどこにも書かれていませんが、C# 7.2が含まれています。
大々的に書かない辺り、やっぱり<a href="http://ufcpp.net/blog/2017/10/pickuproslyn1008/">自信ない</a>のかな…
まあ、こっそり出したところで、<a href="https://github.com/dotnet/roslyn">Roslynリポジトリ</a>を見ていれば15.5で出すことだいぶ前からわかっていますが。</p>
<h2>C# 7.2</h2>
<p>ということで、C# 7.2。</p>
<p><a href="https://github.com/dotnet/csharplang/milestone/6">C# 7.2で追加予定</a>となっている機能を一通り手元で試してみましたが、
「<a href="https://github.com/dotnet/csharplang/issues/933">ref local reassignment</a>」以外は実装されていそう。
(※追記: ref local reassignment はそもそも 7.3 に延期されてそう。なので、予定されている機能は全部実装済み。)
あと、<a href="http://ufcpp.net/blog/2017/10/pickuproslyn1008/">先日報告を出したバグ</a>の修正は、さすがに今回のバージョンには含まれていませんけども、
15.5の正式リリースまでには入ると思います。</p>
<p>試しに一通り書いてみたコードはうちのサンプル リポジトリに置いてあります。</p>
<ul>
<li><a href="https://github.com/ufcpp/UfcppSample/tree/master/Demo/2017/Csharp7_2-1012">Csharp7_2-1012</a></li>
</ul>
<p>C# 7.1の時と同様に最初は Gist 辺りに書き捨てとこうかと思ったんですが、思ったよりも分量が多く。
結構なコード量だったのでちゃんとソリューションを作って複数のファイルに分けて書くことになったので GitHub リポジトリにコミット。</p>
<h3><code>ref</code></h3>
<p>C# 7.2の当初予定だと「パフォーマンス関連の機能詰め込み」みたいな感じだったんですけど、やっぱ一部はもっと後に伸びました。
で、残ってるのが何かというと、もうほとんどが<code>ref</code>がらみ。</p>
<ul>
<li>
<a href="https://github.com/dotnet/csharplang/issues/666">Span<T>, aka interior pointer, aka stackonly struct</a>
<ul>
<li><a href="https://github.com/ufcpp/UfcppSample/blob/master/Demo/2017/Csharp7_2-1012/ConsoleApp1/SpanSafety.cs">SpanSafety.cs</a></li>
<li><a href="https://github.com/ufcpp/UfcppSample/blob/master/Demo/2017/Csharp7_2-1012/ConsoleApp1/RefStruct.cs">RefStruct.cs</a></li>
<li><a href="https://github.com/ufcpp/UfcppSample/blob/master/Demo/2017/Csharp7_2-1012/ConsoleApp1/SafeStackalloc.cs">SafeStackalloc.cs</a></li>
<li><a href="https://github.com/ufcpp/UfcppSample/blob/master/Demo/2017/Csharp7_2-1012/ConsoleApp1/SpanSample.cs">SpanSample.cs</a></li>
</ul>
</li>
<li>
<a href="https://github.com/dotnet/csharplang/issues/223">conditional ref operator</a>
<ul>
<li><a href="https://github.com/ufcpp/UfcppSample/blob/master/Demo/2017/Csharp7_2-1012/ConsoleApp1/ConditionalRefOperator.cs">ConditionalRefOperator.cs</a></li>
</ul>
</li>
<li><a href="https://github.com/dotnet/csharplang/issues/186">ref extension methods on structs</a></li>
<li>
<a href="https://github.com/dotnet/csharplang/issues/38">Readonly ref</a>
<ul>
<li><a href="https://github.com/ufcpp/UfcppSample/blob/master/Demo/2017/Csharp7_2-1012/ConsoleApp1/ReadOnlyStruct.cs">ReadOnlyStruct.cs</a></li>
<li><a href="https://github.com/ufcpp/UfcppSample/blob/master/Demo/2017/Csharp7_2-1012/ConsoleApp1/RefExtensionRefOperator.cs">RefExtensionRefOperator.cs</a></li>
</ul>
</li>
</ul>
<p>C# 7.0の<a href="http://ufcpp.net/blog/2016/6/cs7refreturns/">参照戻り値・参照ローカル変数</a>の延長にあたる機能です。</p>
<p>(※ readonly structs とかは <code>ref</code>と関係なさそうにも見えますが、これがないと <code>ref</code> の安全性の保証ができないそうで。)</p>
<p>C# 7.0の参照戻り値の時点で、「9割方の人はおそらく使わない機能」、「残り1割(未満かも)の人が、ライブラリやフレームワークのパフォーマンス改善に使う」、「結果的に、全てのC#ユーザーがパフォーマンス改善の恩恵を受ける」的な機能なわけですが。
C# 7.2はもう、このバージョン全体がそんな感じ。</p>
<h3>他</h3>
<p>一応他にも新機能があるんですが、ものすっごい小粒です。</p>
<ul>
<li>
<a href="https://github.com/dotnet/csharplang/issues/65">allow digit separator after 0b or 0x</a>
<ul>
<li><a href="https://github.com/ufcpp/UfcppSample/blob/master/Demo/2017/Csharp7_2-1012/ConsoleApp1/DigitSeparator.cs">DigitSeparator.cs</a></li>
</ul>
</li>
<li>
<a href="https://github.com/dotnet/csharplang/issues/570">Non-trailing named arguments</a>
<ul>
<li><a href="https://github.com/ufcpp/UfcppSample/blob/master/Demo/2017/Csharp7_2-1012/ConsoleApp1/NonTrailingNamedArguments.cs">NonTrailingNamedArguments.cs</a></li>
</ul>
</li>
<li>
<a href="https://github.com/dotnet/csharplang/milestone/6">Private protected</a>
<ul>
<li><a href="https://github.com/ufcpp/UfcppSample/blob/master/Demo/2017/Csharp7_2-1012/ClassLibrary1/PrivateProtected.cs">ClassLibrary1/PrivateProtected.cs</a></li>
<li><a href="https://github.com/ufcpp/UfcppSample/blob/master/Demo/2017/Csharp7_2-1012/ConsoleApp1/PrivateProtected.cs">ConsoleApp1/PrivateProtected.cs</a></li>
</ul>
</li>
</ul>
 ]]></description>
				<pubDate>Thu, 12 Oct 2017 23:09:59 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 10/9</title>
				<link>http://ufcpp.net/blog/2017/10/pickuproslyn1009/</link>
				<description><![CDATA[ <p>今日は、新たにChampion (取り組むこと確定) が2件と、面白そうな提案1件。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/933">Champion: ref local reassignment #933</a> … ref ローカル変数の再代入</li>
<li><a href="https://github.com/dotnet/csharplang/issues/973">Champion &quot;Declaration Expressions&quot; #973</a> … 宣言式</li>
<li><a href="https://github.com/dotnet/csharplang/issues/982">ValueEnumerator (fast to code and run) #982</a> … 値型 enumerator</li>
</ul>
<h2>ref ローカル変数の再代入</h2>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/933">Champion: ref local reassignment #933</a></li>
</ul>
<p><a href="http://ufcpp.net/study/csharp/cheatsheet/ap_ver7/#ref-returns">C# 7.0</a> で、参照ローカル変数が使えるようになっていましたが、
参照ローカル変数の再代入はできませんでした。</p>
<pre class="source" title="参照ローカル変数の再代入">
<code><span class="reserved">static</span> <span class="reserved">ref</span> <span class="reserved">int</span> Max(<span class="reserved">int</span>[] array)
{
    <span class="reserved">if</span> (array.Length == 0) <span class="reserved">throw</span> <span class="reserved">new</span> <span class="type">ArgumentException</span>();

    <span class="reserved">ref</span> <span class="reserved">var</span> max = <span class="reserved">ref</span> array[0];

    <span class="reserved">for</span> (<span class="reserved">var</span> i = 0; i &lt; array.Length; ++i)
    {
        <span class="reserved">if</span> (max &lt; array[i])
        {
            <span class="comment">// max = x; だと、array[0] の内容を上書きしちゃうのでダメ</span>
            <span class="comment">// こう書きたい(C# 7.0 では無理)</span>
            <span class="reserved">ref</span> max = <span class="reserved">ref</span> array[i];
        }
    }

    <span class="reserved">return</span> <span class="reserved">ref</span> max;
}
</code></pre>
<p>一方、C# 7.2でつかされる機能として前々から決まっていたものとして、<a href="https://github.com/dotnet/csharplang/blob/master/proposals/csharp-7.2/span-safety.md">ref-like 型</a>というものがあります。
これまでの .NET では認められていなかった「フィールドとして参照を持てる構造体」を認めるための仕様です。
その手の構造体を安全に使うには<code>ref</code> (参照引数、参照ローカル変数、参照戻り値)と同じようなフロー解析が必要で、
その仕様が C# 7.2 で追加されます。</p>
<p>で、C# 7.2のref-like型では、変数への「参照の再代入」を認めている(認められるようにフロー解析を賢く実装した)ので、
だったら、C# 7.0までの参照ローカル変数でも再代入を認められるはず。
ということで、これもC# 7.2で実装しようという流れになっています。</p>
<h2>宣言式</h2>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/973">Champion &quot;Declaration Expressions&quot; #973</a></li>
</ul>
<p>こちらは C# 6.0 の頃から提案に上がっていたもの。
以下のように、式の途中で変数宣言ができるという機能。</p>
<pre class="source" title="宣言式">
<code><span class="reserved">var</span> square = (var x = <span class="reserved">int</span>.Parse(<span class="type">Console</span>.ReadLine()) * x;
</code></pre>
<p>「パターンマッチと併せて練り直したい」、「パターンマッチ同様、変数<code>x</code>のスコープをどうするかちょっと迷う」、「大変な割には需要は低め(やらないとは言わないけど優先度低)」みたいな状態だったものに、ついに「Chanpion」タグが付きました。</p>
<p>まあ、ただし、マイルストーンが決まっていないので相変わらず優先度低めです。</p>
<h2>値型 enumerator</h2>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/982">ValueEnumerator (fast to code and run) #982</a></li>
</ul>
<p>今の仕様だと、<a href="http://ufcpp.net/study/csharp/sp2_iterator.html">イテレーター</a>を以下のように書きます。</p>
<pre class="source" title="現在のイテレーター構文">
<code><span class="reserved">static</span> <span class="type">IEnumerable</span>&lt;<span class="reserved">int</span>&gt; X()
{
    <span class="reserved">yield</span> <span class="reserved">return</span> 1;
    <span class="reserved">yield</span> <span class="reserved">return</span> 2;
    <span class="reserved">yield</span> <span class="reserved">return</span> 3;
}
</code></pre>
<p>これで何が問題かというと、必ずインターフェイスを介して列挙子を返すことになるので、
<a href="http://ufcpp.net/study/csharp/misc_heap.html">ヒープ</a>確保が避けれないという点です。</p>
<p>で、この問題を避けるために、結局、イテレーター構文は使わず、構造体な列挙子を1つ1つ作ったりするというつらい最適化作業が待っていたりします。
まあ昔からですが、<a href="http://source.dot.net/#System.Private.CoreLib/src/System/Collections/Generic/List.cs,675"><code>List&lt;T&gt;</code>の<code>GetEnumerator</code></a>なんかがそういう実装になっています。</p>
<p>書きやすさとパフォーマンスのトレードオフは常にあるものなのでしょうがないと言えばしょうがないんですが、
やっぱり最初から「構造体を生成してくれるイテレーターが欲しい」という提案が出てきたという状態。</p>
 ]]></description>
				<pubDate>Mon, 09 Oct 2017 17:50:55 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 10/8: C# 7.1 の default 式のバグ</title>
				<link>http://ufcpp.net/blog/2017/10/pickuproslyn1008/</link>
				<description><![CDATA[ <p>昨日の <a href="https://csugjp.connpass.com/event/66004/">.NET Conf 2017 Tokyo</a>でちょこっと話したりしたんですが、C# 7.1のバグを踏み抜いたという話。
(正確には同僚が踏んじゃったバグを僕がバグ報告入れた)</p>
<p>割と手短に示せるバグで、以下のような例がわかりやすいんですが、nullable型な引数のデフォルト値として、<a href="http://ufcpp.net/study/csharp/cheatsheet/ap_ver7_1/#default-expr"><code>default</code>式</a>を使ったとき、値が <code>null</code> にならないとおかしいはずなのに 0 になるという問題。</p>
<pre class="source" title="デフォルト値にデフォルト式">
<code><span class="reserved">static</span> <span class="reserved">void</span> Main()
{
    <span class="reserved">int</span>? x = <span class="reserved">default</span>; <span class="comment">// null</span>
    <span class="reserved">int</span> y = <span class="reserved">default</span>; <span class="comment">// 0</span>

    <span class="type">Console</span>.WriteLine(x); <span class="comment">// null</span>
    <span class="type">Console</span>.WriteLine(y); <span class="comment">// 0</span>
    A(); <span class="comment">// 0 !!</span>
    A(<span class="reserved">default</span>); <span class="comment">// null !!</span>
}

<span class="reserved">static</span> <span class="reserved">void</span> A(<span class="reserved">int</span>? x = <span class="reserved">default</span>) <span class="comment">// 0 !!</span>
{
    <span class="type">Console</span>.WriteLine(x);
}
</code></pre>
<h2>バグ報告</h2>
<p>結構わかりやすいバグだから既出かなぁとか思いつつも<a href="https://github.com/dotnet/csharplang/issues/970">バグ報告</a>をいれてみたんですが。
案外初出だったらしく、かつ、さすがにまずそうなバグなので「破壊的変更になるけども直す」という感じですぐに修正作業が始まったみたいです。</p>
<p>一応、C# 7.1 (Visual Studio 15.3 (2017 Update 3))は、プレビュー版が出てからだと数か月経っていますし、正式リリース(8/14)からも2か月弱経ってるわけですが。気付かないもんですね、こういうバグ… まあ、デフォルト値が <code>null</code> の時には普通 <code>null</code> って書きますもんね、<code>default</code>を使わず。</p>
<p>ちなみに、類似のバグとして、<code>default</code>式はCode Fix の挙動も怪しかったりします。</p>
<p><img src="/media/1140/defaultcodefix.png" alt="IDE0034 Code Fix (変な挙動してる)" /></p>
<p><code>object x = default(int)</code> (0になるはず)を、<code>object x = default</code> (null になっちゃうので、意味が変わる)にリファクタリングしようとしてしまう問題。</p>
<p>こちらは、既出のバグで先月くらいにはバグ報告されています。かつ、IDE のリファクタリングの問題なので、コンパイル結果自体が怪しい先ほどのバグと比べると幾分かマシ。</p>
<h2>初のマイナーリリースで自信なさげ？</h2>
<p>C# 7.1は、実質的には初のマイナーリリースですし、半年という短いサイクルで新バージョンをリリースしたというのも、C# チーム的には初の試みです。</p>
<p>そのせいか、ちょっと自信なさげな感じもあるんですよね…</p>
<p>例えば、C# チームから「C# 7.1 がリリースされました」的なブログが出ていなかったりしますし。</p>
<p>例えば、Visuals Studio 15.3では規定動作では C# 7.1 を使えませんし(<a href="http://ufcpp.net/blog/2017/8/visualstudio15_3/">LangVersion latest オプションの指定が必要</a>)。</p>
<p>まあ、何事も初の試みは大変ってことですかね…</p>
<h2><code>default</code> の型推論はそんなの大変なのか</h2>
<p>ちなみに、パッと見の感覚で言うと、このバグは不思議に思えるというか、なんでそんなバグを起こしちゃうのか謎というか。
「<code>int? x = default</code> って書かれてたら、ローカル変数だろうと引数のデフォルト値だろうと<code>default(int?)</code>だろ」という感じなんですが。</p>
<p>まあたぶんなんですけど、nullable型とか、値型のデフォルト値とかは結構いろんな特殊対応が入っていて、
思ったほどコンパイラーのコードは単純じゃないのではないかと思われます。</p>
<p>例えば、値型のデフォルト値なんですが、以下のような感じになっています。</p>
<pre class="source" title="値型のデフォルト値">
<code><span class="comment">// 以下の3つの X は全部同じ意味</span>
<span class="reserved">static</span> <span class="reserved">void</span> X(<span class="type">DateTime</span> d = <span class="reserved">default</span>(<span class="type">DateTime</span>)) { }
<span class="reserved">static</span> <span class="reserved">void</span> X(<span class="type">DateTime</span> d = <span class="reserved">new</span> <span class="type">DateTime</span>()) { }

<span class="comment">// これは現在の C# ではコンパイルできない</span>
<span class="comment">// C# 3.0 までデフォルト引数を認めていなかったので、VB との相互運用のために使っていた書き方</span>
<span class="comment">// 属性には定数しか含められず、かつ、構造体の規定値は .NET 的には「定数」ではない</span>
<span class="comment">// 代わりに null を入れてある</span>
[<span class="type">DefaultParameterValue</span>(<span class="reserved">null</span>)]
<span class="reserved">static</span> <span class="reserved">void</span> X(<span class="type">DateTime</span> d) { }
</code></pre>
<p>IL へのコンパイル結果としても以下のような感じ。</p>
<pre class="source" title="上記コードのコンパイル結果のIL">
<code><span class="reserved">.method private hidebysig static</span>
    <span class="reserved">void</span> X(
        [opt] valuetype[mscorlib] System.<span class="type">DateTime</span> d
    ) cil managed
{
    .param [1] = nullref <span class="comment">// DateTime 構造体なのに null 扱い</span>
    .maxstack 8
    IL_0000: ret
}
</code></pre>
<p>本来 <code>null</code> を代入できないはずの <code>DateTime</code> 構造体に対して、<code>null</code> でデフォルト値を代用している状態です。</p>
<p>nullable 型に対しても、以下のような感じで、null の扱いがちょっと特殊になっています。</p>
<pre class="source" title="int? への null 代入">
<code><span class="comment">// 以下の2行は同じ意味</span>
<span class="reserved">int</span>? x = <span class="reserved">null</span>;
<span class="reserved">int</span>? x = <span class="reserved">new</span> <span class="reserved">int</span>?(); <span class="comment">// null というより、(false, 0) みたいな値</span>
</code></pre>
<p>なんかこの辺りが合わさった結果、<code>default</code>式の型推論に失敗したんじゃないかなぁと思います。</p>
<h2>修正による破壊的変更</h2>
<p>このバグを修正すると破壊的変更になります。
もしも、「0 になるものだ」という前提で <code>int? x = default</code> を書いている人がすでにいた場合、
そのコードの挙動が狂います。</p>
<p>C# は基本的には破壊的変更に対して非常に保守的な言語で、
「直したいけども破壊的変更になるから直せない」みたいな言語仕様も結構あります。
ただ、「明らかにバグ」というものに対してはさすがに破壊的変更が許容されることが結構多いです。</p>
<p>一応、マイクロソフト内に「compat council」(互換性協議会)みたいなグループがあって、そこでの審議をしているそうです。
そのcouncilで破壊的変更を許容するかどうかは、バグの深刻度と実際の影響範囲のバランス等を見て決めていると思われます。</p>
<p>今回の場合で言うと、</p>
<ul>
<li>
<code>int? x = default</code> が 0 になるものだという前提でコードを書いているやつがどのくらいいるか？ → あんまりいなさそう
<ul>
<li>そもそも数か月の間誰にも気づかれなかったわけで</li>
<li>普通は <code>int? x = null</code> か <code>int? x = 0</code> と書く(わざわざ <code>int? x = default(int?)</code> とか <code>int? x = default(int)</code> とか書かない)</li>
<li>LangVersion latest オプションが必要なため、そもそも C# 7.1 の利用率自体がまだそこまで上がっていないと思われる </li>
</ul>
</li>
<li>
いくらなんでも挙動がひどい
<ul>
<li>ローカル変数の <code>int? x = default;</code> だと <code>null</code> なのに、引数のデフォルト値の<code>(int? x = default)</code> だと 0</li>
<li><code>X()</code> だと 0 なのに、<code>X(default)</code> だと <code>null</code></li>
</ul>
</li>
</ul>
<p>という感じなので、
さすがにほぼノータイムでcompat councilを通過したみたい。</p>
 ]]></description>
				<pubDate>Sun, 08 Oct 2017 15:09:42 +0900</pubDate>
			</item>
			<item>
				<title>.NET Conf 2017 Tokyo, Japan</title>
				<link>http://ufcpp.net/blog/2017/9/dotnetconf2017tokyo/</link>
				<description><![CDATA[ <p><a href="https://csugjp.connpass.com/event/66004/">.NET Conf 2017 Tokyo, Japan</a>やります。</p>
<ul>
<li>日時: 2017/10/07(土) (12:30開場、13:00開始)</li>
<li>会場: 日本マイクロソフト株式会社 品川オフィスセミナールーム A, B, C+D</li>
</ul>
<h2>公募</h2>
<p>今回の .NET Conf 2017 Tokyo では、８セッションを公募しています。.NET について話してみたいという方はこのチャンスにぜひ！</p>
<p>いつも決まったスピーカーの方ばかりで、喋りたくても自分にはなかなかチャンスがないと諦めているそこの貴方！ この機会にぜひ応募ください。応募はコメント欄に「登壇興味あり」と記入するだけ（ 追って運営側よりご連絡させていただきます）。
あるいは、後からでも、Connpassのメッセージその他手段は問わず運営にご連絡ください。</p>
<p>【セッション関連トピック】</p>
<ul>
<li>.NET Core 2</li>
<li>EF Core 2</li>
<li>.NET Standard</li>
<li>ASP.NET Core (Razor Pages)</li>
<li>Xamarin / VS for Mac</li>
<li>Container / Microservices</li>
<li>Serverless + .NET</li>
<li>Language C# (F#, VB)</li>
<li>Unity/Game Development </li>
<li>IoT devices with .NET Core</li>
<li>Angular / SPA application with Azure</li>
<li>Modernizing applications (WinForms to UWP with Azure, WinForms / WPF to iPad App, etc...)</li>
<li>Cognitive, AI and Azure</li>
</ul>
<h2>Unconference + Unplugged部屋</h2>
<p>公募の8セッションに加え、当日はさらに Unconference + Unplugged 専用部屋を準備します。</p>
<p>Unconferenceはテーマに沿って参加者が自由に喋るスタイルです。今回のテーマは.NETConfということで幅広く.NETに関連すればなんでもアリ。
だいたい一人10分程度目安で思いのたけをぶちまけましょう。奇麗なスライドを用意したり、かしこまって喋る必要はまったくありませんのでお気軽に参加ください。</p>
<p>UnpluggedはMicrosoftのScott Guthrieでもおなじみ、参加者からその場で質問を受けて回答していくスタイルで質問や疑問をぶつけて消化していくセッションです。</p>
<p>どちらも参加者と一緒にセッションを完成させるスタイルですので、質問などを考えながらお気軽に是非ご参加ください。</p>
<p>※ Unconference では、公募8セッションのセッション関連トピックを気にする必要はありません。テーマは自由です。こちらは当日喋りたい人が随時名乗りを上げて喋るスタイルですので、申し込み時に登壇興味あり等コメント記入する必要はありませんが、「Unconferenceで喋るかも」といったコメントがあると運営が喜びます</p>
<p>※ ちなみに、Unpluggedの1コマは僕、岩永がやろうかなと考えています。前々からちらほら「スライド等用意せず、C#がらみの話を何か来場者との対話ベースでやりたいなぁ」と言っていたやつを実際にやってみようかと。
(といっても、「じゃあ何か質問ある？」から始めてもあんまり手が挙がらないとは思うので、<a href="https://github.com/dotnet/csharplang">csharplang</a>や僕の過去のセッション、記事、<a href="https://github.com/ufcpp/UfcppSample/tree/master/Demo/2017">サンプルコード</a>等をベースに何か定時しつつになるかなと思います。)</p>
 ]]></description>
				<pubDate>Wed, 06 Sep 2017 13:16:04 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 9/3</title>
				<link>http://ufcpp.net/blog/2017/9/pickuproslyn0903/</link>
				<description><![CDATA[ <p>今日は以下の3本立て:</p>
<ul>
<li>次のリリース(C# 7.2)の作業どのくらい進んでるのか久々に眺めてみた</li>
<li>1個、Champion(取り組むこと自体は確定)判定を受けた提案が出てた(return, break, continue 式)</li>
<li>C# 8.0に向けて、「null許容参照型」の作業が最近活発化してる</li>
</ul>
<h2>C# 7.2(次のマイナーリリース)を試してみる</h2>
<p>最近ちょっと本腰を入れてC#コードでの速度最適化の作業をしてたりするんですけども、
そこでたどり着いた1つの境地が「<a href="https://github.com/ufcpp/UfcppSample/blob/master/Demo/2017/TypeRepositoryBenchmarks/StackallocDistinctBenchmark/DistinctBenchmark.cs#L7"><code>stackalloc</code> 強すぎ</a>」だったりします。</p>
<p>要するに、まあ .NET のヒープ確保は速いとは言われつつも、そもそもなくせるならなくす方が当然速い。
そのための手段として有効なのが構造体の活用と、この<code>stackalloc</code>。
ただ、まあ、unsafeコードだらけになります。</p>
<p>そのunsafeまみれを解消するのが <a href="https://github.com/dotnet/csharplang/milestone/6">C# 7.2</a> (次のマイナーリリース)のテーマだったりするわけです。
で、そういえば、「<a href="https://github.com/dotnet/csharplang/issues/535#issuecomment-299288113"><code>Span&lt;T&gt;</code>を使えばsafeな文脈で <code>stackalloc</code> を使える</a>」みたいな話を見かけたなぁとか思って、現状の実装状況を確認してみたりしました。</p>
<p>今、Visual Studio 2017 Previewでも提供されていないような新しい言語機能を試そうと思った場合、以下のようにすれば行けます。</p>
<ul>
<li>
Roslyn の nightly build から所望のバージョンの<a href="https://dotnet.myget.org/feed/roslyn/package/nuget/Microsoft.Net.Compilers">Microsoft.Net.Compilersパッケージ</a>を取ってくる
<ul>
<li>今回の場合は、<a href="https://github.com/ufcpp/UfcppSample/blob/master/Demo/2017/Csharp7_2-0902/ConsoleAppRefReadonly/ConsoleAppRefReadonly.csproj#L10">2.6.0-rdonly-ref-62101-05</a>ってバージョンを参照</li>
<li>この NuGet パッケージを参照していると、ビルド時に使われる C# コンパイラーが NuGet パッケージ中のものに刺し変わる</li>
<li>ちなみに、刺し変わるのはビルドに使われるもののみで、Visual StudioのC# エディター上でリアルタイムに動いているコンパイラーは刺し変わらないみたいです(ビルドは通るけどVisual Studio上ではエラーが出まくるみたいな状態になります)</li>
</ul>
</li>
<li><a href="https://github.com/ufcpp/UfcppSample/blob/master/Demo/2017/Csharp7_2-0902/ConsoleAppRefReadonly/ConsoleAppRefReadonly.csproj#L6">csproj に<code>&lt;LangVersion&gt;7.2&lt;/LangVersion&gt;</code> タグを追加</a></li>
</ul>
<p>で試してみた結果が以下のような感じ。</p>
<ul>
<li><a href="https://github.com/ufcpp/UfcppSample/blob/master/Demo/2017/Csharp7_2-0902/ConsoleAppRefReadonly/Program.cs">ConsoleAppRefReadonly/Program.cs</a></li>
</ul>
<p>このバージョンのC#コンパイラーは Roslynリポジトリの<a href="https://github.com/dotnet/roslyn/tree/features/readonly-ref">readonly-ref</a>ブランチが元になっている物っぽいんですが、
名前通りではなくて radonly-ref 以外の機能も含まれています。
含まれているのは以下のようなもの:</p>
<ul>
<li>
<a href="https://github.com/dotnet/csharplang/issues/38">ref readonly</a> … <a href="http://ufcpp.net/study/csharp/sp_ref.html#sec-byref">参照引数</a>を書き換え不能にできる機能
<ul>
<li>(昔は「readonly ref」の語順だったものの、今は「ref readonly」の順になっています)</li>
<li>in … reaf readonlyの省略形。out引数の対比として、「入力専用の参照引数」という意味で in というキーワードが利用できる</li>
</ul>
</li>
<li><a href="https://github.com/dotnet/csharplang/issues/186">ref拡張メソッド</a> … 「<code>ref this</code>」あるいは「<code>in this</code>」という書き方で、<a href="http://ufcpp.net/study/csharp/sp3_extension.html">拡張メソッド</a>の第1引数を参照渡しにできる</li>
<li>
<a href="https://github.com/dotnet/csharplang/issues/666">stackonly struct</a> … <code>Span&lt;T&gt;</code>構造体は<a href="http://ufcpp.net/study/csharp/sp_ref.html?p=2#ref-returns">参照戻り値・参照ローカル変数</a>と同じ扱いをしないといろいろ不具合が起こるので、それをコンパイル時にチェックする
<ul>
<li><code>Span&lt;T&gt;</code>がらみの機能の一環として、「<code>Span&lt;T&gt;</code>の変数で受けるなら<code>stackalloc</code>は安全」というものもある</li>
</ul>
</li>
</ul>
<p>この辺りはもう割と実装済みみたいでした。コンパイルも実行も可能。</p>
<h2>return, break, continue 式</h2>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/867">Champion &quot;return, break and continue expressions&quot; #867</a></li>
</ul>
<p><a href="http://ufcpp.net/study/csharp/oo_exception.html#throwexpr">throw 式</a>と同じ文脈で、<code>return</code>, <code>break</code>, <code>continue</code>も認めてもいいのではないかという話。(補足: throw 式が使える文脈ってのは、以下のように、<code>=&gt;</code>とか<code>??</code>とか<code>?:</code>の後ろです。)</p>
<pre class="source" title="">
<code><span class="reserved">using</span> System;

<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> Main()
    {
        <span class="type">Action</span> a = () =&gt; <span class="reserved">throw</span> <span class="reserved">new</span> <span class="type">Exception</span>(); <span class="comment">// =&gt; の後ろ</span>
    }

    <span class="reserved">static</span> <span class="reserved">int</span> F(<span class="reserved">int</span>? n) =&gt; n ?? <span class="reserved">throw</span> <span class="reserved">new</span> <span class="type">Exception</span>(); <span class="comment">// ?? の後ろ</span>
    <span class="reserved">static</span> <span class="reserved">int</span> F(<span class="reserved">bool</span> b) =&gt; b ? 1 : <span class="reserved">throw</span> <span class="reserved">new</span> <span class="type">Exception</span>(); <span class="comment">// ?: の2、3項目</span>

    <span class="reserved">static</span> <span class="reserved">int</span> F() =&gt; <span class="reserved">throw</span> <span class="reserved">new</span> <span class="type">Exception</span>(); <span class="comment">// =&gt; の後ろ</span>
}
</code></pre>
<p>throw式の実装の時点でreturn式とかは要望がでていましたし、
6月くらいには<a href="https://github.com/dotnet/csharplang/blob/master/meetings/2017/LDM-2017-06-27.md">Design Meeting</a>の議題に挙がってたみたいですが、
この度、「Champion」(やること自体は確定)に昇格。
実装時期は未定(まだ分類されてない。タグ付けなし)。</p>
<h2>null許容参照型</h2>
<p>最近ついに、待望の「null許容参照型」がらみの作業が実働に入ったっぽい雰囲気。そのうちの1つが以下のissue投稿。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/863">Nullable reference types: Mads's current thoughts #863</a></li>
</ul>
<p>Mads (C# のプロダクトマネージャー)の null 許容参照型に関する現在の考えだそうです。
これまでと方針変更があったとかではなく、単に改めてまとめとして考えを表明しただけですが。</p>
<p>「nullがあるもの」だった参照型に対してわざわざ「null許容参照型」なんて呼んでいるのからわかる通り、
参照型も「何も修飾を付けなければnullはないもの」「<code>?</code>を付けたときだけnullを想定」扱いしたいという方針になっています。</p>
<p>もちろん単純にそれをやると破壊的変更なので、on/offは切り替えれるようにする。
切り替えはアセンブリ単位で、「このアセンブリnull許容参照型を前提としたコンパイル時検査を掛けています」みたいなアセンブリ属性も付けるみたい。</p>
<p>あと、null検査に関して、言語仕様と静的解析機能は分けたいみたい。</p>
<ul>
<li>
言語機能としては、あくまで「nullを許すかどうかの注釈を付ける文法を用意」というだけ
<ul>
<li>参照型<code>T</code>に対して単に<code>T</code>と書くと非null、<code>T?</code>と書くとnull許容</li>
<li>
後置き<code>!</code>演算子を付けることでnull検査の対象から外す
<ul>
<li>パフォーマンスの都合で一時的にnullになるのをわかっていてやっている場合とか</li>
<li>注釈が付いていない(C# 8.0以前に書かれていたり、解析オプションをoffにしていたり)アセンブリを参照する場合とか</li>
</ul>
</li>
</ul>
</li>
<li>それに対してどういう検査をするかは、概念上はC#コンパイラーの外、<a href="http://ufcpp.net/study/csharp/package/pkgcodeawarelibrary/#sec-generated-title-2">アナライザー</a>として実装する</li>
</ul>
<p>ちなみに「概念上は」と言っているのは、C#コンパイラー内で実装しないと効率が悪い「解析」もあって実装上はC#コンパイラーに組み込むことになるから。とはいえ、「C#言語の仕様です」として厳密にいろいろと決めるには難しすぎる機能なので、「どこまで厳密に解析するかはアナライザーの実装に依存」としたいみたいです。解析の対象を段階的に広げていきたいみたいな思惑もあると思われます(「言語仕様」としてしまうと、後からの警告の追加も破壊的変更になるので)。</p>
<p>あと、「null検査」と言いつつ、C#としては、実際には「default検査」と表現するべきかも。
以下のようなものが静的解析の対象になります。</p>
<ol>
<li>参照型に対する null の代入</li>
<li>参照型でインスタンス化される可能性がある<a href="http://ufcpp.net/study/csharp/sp2_generics.html#typeparam">型引数</a>に対するdefaultの代入</li>
<li>参照型をフィールドに持つ構造体に対するdefaultの代入</li>
</ol>
<p>これは「段階的に広げていきたい」の典型で、1は「必須」(at least)、2は「任意にできる」(could be optional)、3は「任意であるべきだろう」(should be optional)的に書かれていたり。</p>
 ]]></description>
				<pubDate>Sun, 03 Sep 2017 20:10:44 +0900</pubDate>
			</item>
			<item>
				<title>Visual Studio 2017 Update 3正式リリース</title>
				<link>http://ufcpp.net/blog/2017/8/visualstudio15_3/</link>
				<description><![CDATA[ <p><a href="https://blogs.msdn.microsoft.com/visualstudio/2017/08/14/visual-studio-2017-version-15-3-released/">Visual Studio 2017 Update 3の正式リリース</a>が来てるみたいですね。
普通にVisual Studio 2017上の「通知」や「拡張機能と更新」辺りからや、Visual Studio Installerから更新できます。</p>
<p>先週くらいから、中の人のブログとかtwitter周りで「リリース近い」的な言葉がちらほら出てきてた中、
一昨日、<a href="https://twitter.com/ufcpp/status/896725639494901762">Preview 7.1</a>とか出されたときにはちょっとひやひやしましたが
(細かいリリース挟まないといけないような緊急のバグでも見つけてしまったの？と)。</p>
<p>なんかしかし、最近アップデートのたびに言ってますけども、2017 Update 3 Preview 7.1とか、某<a href="https://www.amazon.co.jp/dp/B000BYUIPC">ZERO3↑↑</a>とか<a href="https://www.amazon.co.jp/dp/B0000E5SEP/">ハイパーIIアニバーサリースペシャル</a>とかが可愛く見えるバージョン名はどうにかならないですかね…</p>
<h2>いろいろ正式リリース</h2>
<p>Visual Studio に伴って、</p>
<ul>
<li>C# 7.1</li>
<li><a href="https://blogs.msdn.microsoft.com/dotnet/2017/08/14/announcing-net-core-2-0/">.NET Core 2.0</a></li>
<li><a href="https://blogs.msdn.microsoft.com/dotnet/2017/08/14/announcing-net-standard-2-0/">.NET Standard 2.0</a></li>
<li><a href="https://blogs.msdn.microsoft.com/webdev/2017/08/14/announcing-asp-net-core-2-0/">ASP.NET Core 2.0</a></li>
<li><a href="https://blogs.msdn.microsoft.com/dotnet/2017/08/14/announcing-entity-framework-core-2-0/">Entity Framework Core 2.0</a></li>
</ul>
<p>とかも正式リリースみたいです。</p>
<p>あと、Visual Studio for Mac version 7.1も同時に利用可能とのこと。</p>
<p>C# 7.1の機能自体は、<a href="http://ufcpp.net/blog/2017/6/vs2017u3p2/">6月のPreview 2の時点</a>でfixしてたみたいで、その後全く変わっていません。
うちの「<a href="http://ufcpp.net/study/csharp/">C# によるプログラミング入門</a>」的にはだいぶ前から<a href="http://ufcpp.net/study/csharp/cheatsheet/ap_ver7_1/">対応済み</a>。
これくらい機能のふらつきが少ないと、記事書き的にはものっっすごい楽です。</p>
<h3>C# 7.1を使う設定(プロパティ→ビルド→ビルドの詳細設定)</h3>
<p>ただ、デフォルトで使われるC#のバージョンはC# 7.0で、7.1を使うには設定が必要みたいです。
この辺り、<a href="http://ufcpp.net/blog/2017/5/vs15_3preview/">Previewの頃</a>のまま。</p>
<p>プロジェクトのプロパティを開いて、ビルド→ビルドの詳細設定で変更可能。</p>
<ul>
<li>既定(default) オプションだと「最新のメジャー バージョン」= C# 7.0</li>
<li>最新(latest)オプションだと「最新のマイナー バージョン」 = C# 7.1</li>
</ul>
<p>になるみたいです。csproj に以下の行を無差別に追加してしまいたい。</p>
<pre class="xsource" title="">
<code><span class="attvalue">  &lt;</span><span class="element">PropertyGroup</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">LangVersion</span><span class="attvalue">&gt;</span>latest<span class="attvalue">&lt;/</span><span class="element">LangVersion</span><span class="attvalue">&gt;</span>
<span class="attvalue">  &lt;/</span><span class="element">PropertyGroup</span><span class="attvalue">&gt;</span>
</code></pre>
<h2>.NET IDE の機能強化</h2>
<p>今回、C# エディター上でのクイック アクションの類が結構いい感じに強化されてるんですが。
リリースノート上は</p>
<ul>
<li>Resolve merge conflicts</li>
<li>Add null checks</li>
<li>Add parameter</li>
</ul>
<p>くらいしか書かれてないんですよね…
他は「many more」扱い。</p>
<p>追記: <a href="https://docs.microsoft.com/ja-jp/visualstudio/ide/quick-actions">https://docs.microsoft.com/ja-jp/visualstudio/ide/quick-actions</a>この辺りにある程度は一覧があるっぽい。ただ、全部ではなさそうだし、Update 3での差分はわからなさそう。</p>
<p>個人的には他のクイック アクションの方がよく使ってるんで、ちょっとちゃんと調べて改めてまとめた方がいいかも。
(最近、C# の新機能以外は大体スルーしてたけど、久々に、IDE周りも真面目に。)</p>
<h2>リリース ノート</h2>
<p>そういえば、リリース ノートがちゃんと日本語でも即日来てますね。</p>
<ul>
<li><a href="https://www.visualstudio.com/ja-jp/news/releasenotes/vs2017-relnotes">https://www.visualstudio.com/ja-jp/news/releasenotes/vs2017-relnotes</a></li>
</ul>
<p>最近、ドキュメントのページはあんまり翻訳を期待してなかったんですが、さすがに正式リリースくらいはちゃんとしますか…</p>
<p>それも割かし、機械翻訳っぽくないちゃんとした文面。</p>
<p>「Resolve merge conflicts」が「結合の競合の解決」になってたりとか、人手による翻訳でもやらかしそうなやつはきっちりやらかしてますが。
(ちなみに、Visual Studio上ではちゃんと「マージ競合」って翻訳されてました。↓みたいな機能。)</p>
<p><img src="/media/1138/mergeconflict.png" alt="enter image description here" /></p>
 ]]></description>
				<pubDate>Tue, 15 Aug 2017 02:57:18 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 7/30: C# 7.1の先の計画＆ .NET でのメモリ手動管理</title>
				<link>http://ufcpp.net/blog/2017/7/pickuproslyn0730/</link>
				<description><![CDATA[ <h2>C# 7.1の先の計画</h2>
<p>C# 7.1 がらみの作業も落ち着いたところで、
その先の優先度付け的な Design Notes がアップロードされていました。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/blob/master/meetings/2017/LDM-2017-07-05.md">C# Language Design Notes for Jul 5, 2017</a></li>
</ul>
<p>概ね以下のような感じ。</p>
<ul>
<li>構造体の活用(特に ref がらみ)は C# 7.2 でまとめて実装</li>
<li><a href="http://www.buildinsider.net/column/iwanaga-nobuyuki/007">Utf8String</a> は C# 8.0 に回りそう</li>
<li>
<a href="https://github.com/dotnet/csharplang/blob/master/proposals/static-delegates.md">static delegate</a> とかいう話が出てる(C# 8.0向け)
<ul>
<li>static なメソッドは関数ポインターで直接管理したいという話</li>
<li>static なメソッドしか参照しないデリゲートのために <code>Delegate</code> 型インスタンス(ヒープを使う)を作りたくない</li>
</ul>
</li>
<li>
その他、バグっぽい挙動に関して
<ul>
<li>自動実装プロパティで、バッキングフィールドに対して属性を適用できなかった問題(いつでも修正する用意あり)</li>
<li>long tuple (<code>System.ValueTuple</code>型の arity を超える8要素以上のタプル)に対するオーバーロード解決が怪しい問題(今のままにしたい)</li>
</ul>
</li>
</ul>
<h2>.NET でのメモリ手動管理</h2>
<p>これは .NET チームとか C# チームでの動きじゃなくて、マイクロソフト リサーチによる論文なんですが、
以下のようなものが出ています。</p>
<ul>
<li><a href="https://www.microsoft.com/en-us/research/wp-content/uploads/2017/07/snowflake-extended.pdf">Project Snowflake: Non-blocking Safe Manual Memory
Management in .NET</a></li>
</ul>
<p>用途を絞らない汎用のメモリ利用に関してはガベージ コレクション(GC)の生産性を下げてまで手動管理を頑張ってもそれほど効果はないんですが、
一方で、手動管理が割かししやすくて、かつ、手動管理できれば数倍程度の高速化が見込めるような状況もあります。
そこで上記論文は  .NET における手動メモリ管理に関する研究なんですが、以下のような内容。</p>
<ul>
<li>
GC と共存
<ul>
<li>手動管理下にあるオブジェクトが、GC 管理下のオブジェクトの参照を持てる</li>
<li>GC に追加の負担を掛けない</li>
</ul>
</li>
<li>
マルチスレッド環境でも高速
<ul>
<li>lock なしでスレッド安全な手動メモリ管理を行う手法の導入</li>
<li>メモリの「owner」(メモリ解放の責任を負っていているただ1つのオブジェクト)と「shield」(一時的にメモリ参照権限を借り受けるオブジェクト)を用意して管理</li>
</ul>
</li>
<li>
(C# とかの)プログラミング言語との連携
<ul>
<li>言語レベルで変数の「コピー不能性」を保証してもらえれば、低負担なメモリ管理アルゴリズムが使える</li>
</ul>
</li>
</ul>
<p>メモリ管理のアルゴリズムについては参考文献をいろいろ引用していて、
Rust とかでもやっている手法っぽい感じ。
GC との共存ができるという点と、実際に <a href="https://github.com/dotnet/coreclr">CoreCLR</a>をベースに実装してみて、
計測してみたというあたりがこの論文のポイントになりそう。</p>
<p>owner (所有者。解放責任者)がはっきりしないとこの手法は使えないんで、用途は限られるんですが、
例えば以下のような用途に使えます。</p>
<ul>
<li><code>List&lt;T&gt;</code> とかの内部で要素の保存に使っている配列</li>
<li>キャッシュ管理</li>
<li>LINQ の <code>GroupBy</code> とかの中で使う一時的なハッシュテーブル</li>
</ul>
<p>はまる用途に関しては2倍とか3倍とかの性能改善が期待できるという計測結果も出ています。</p>
<p>まあ、あくまでリサーチの段階なので、
実際に .NET に取り込まれるとしても結構先になる感じはあります。</p>
 ]]></description>
				<pubDate>Sun, 30 Jul 2017 14:48:12 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップ Roslyn 6/30</title>
				<link>http://ufcpp.net/blog/2017/6/pickuproslyn0630/</link>
				<description><![CDATA[ <p><a href="https://github.com/dotnet/csharplang">csharplang</a>に出てる提案の整理をしたみたいで、
いくつかの提案に「Proposal Champion」ラベルが付き始めたようです。</p>
<p>「Proposal Champion」は、Proposal(提案が出てるだけ)とChanpion(C#チームの誰かがオーナーになって進めることが決まった段階)の間くらいのつもりっぽく。
「いつかは取り組むけども、今すぐとはいかない」くらいみたいです。</p>
<p>以下、いくつか紹介。</p>
<h2>末尾以外で名前付き引数</h2>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/570">Champion &quot;Non-trailing named arguments&quot; #570</a></li>
</ul>
<p>末尾以外の場所にある引数でも名前付き引数を使いたいという話。</p>
<p>どうもこれはプロトタイプ実装がすでに始まってるっぽい。</p>
<pre class="source" title="">
<code><reserved></span><span class="reserved">static</span> <span class="reserved">void</span> Main()
{
    <span class="comment">// よく言われる話で、bool なフラグがたくさん並ぶとどれがどれかわからない</span>
    M(<span class="reserved">true</span>, <span class="reserved">true</span>, <span class="reserved">true</span>);

    <span class="comment">// 名前付き引数には「オプションな引数を省略可能にする」という意味もあるけども</span>
    M(isC: <span class="reserved">true</span>);

    <span class="comment">// どのフラグが何だったかを明記する意味でも使う</span>
    M(isA: <span class="reserved">true</span>, isB: <span class="reserved">true</span>, isC: <span class="reserved">true</span>);

    <span class="comment">// (これまで) 末尾の引数だけを名前付きにすることならできた</span>
    M(<span class="reserved">true</span>, <span class="reserved">true</span>, isC: <span class="reserved">true</span>);

    <span class="comment">// (提案) それ以外の位置でも、一部分だけ名前付きにできるようにしたい</span>
    M(isA: <span class="reserved">true</span>, <span class="reserved">true</span>, <span class="reserved">true</span>);
}

<span class="reserved">private</span> <span class="reserved">static</span> <span class="reserved">void</span> M(<span class="reserved">bool</span> isA = <span class="reserved">false</span>, <span class="reserved">bool</span> isB = <span class="reserved">false</span>, <span class="reserved">bool</span> isC = <span class="reserved">false</span>)
{
}
</code></pre>
<h2>どこででも拡張メソッドを定義</h2>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/301">Champion &quot;Support extension methods everywhere&quot; #301</a></li>
</ul>
<p>これまでだと拡張メソッドは、トップレベル(名前空間直下)の静的クラスの中でしか定義できませんでした。</p>
<p>でも、「あるクラスの中でだけ使う拡張メソッドのために、外に1クラス作るのは嫌」というような話はたびたび出てくるわけで、
「静的でないクラスでも拡張メソッドを定義したい」とか、
「入れ子のクラス内で拡張メソッドを定義したい」とかいう要望はよく見ます。</p>
<p>ということで、制限を緩めようという話がついに検討に上がったみたいです。</p>
<h2>0b, 0x の直後に _ 区切り</h2>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/65">Champion &quot;allow digit separator after 0b or 0x&quot; #65</a></li>
</ul>
<p>C# 7で、数値リテラルの数字と数字の間を <code>_</code> で区切れるようになりました
(<a href="http://ufcpp.net/study/csharp/start/stnumber/#digit-separator">数字区切り文字</a>)。</p>
<p>で、数字区切り(digit separator)の名前通り、ほんとに数字と数字の間にしか <code>_</code> を書けません。</p>
<pre class="source" title="">
<code><reserved></span><span class="reserved">var</span> a = 1_2_3; <span class="comment">// OK</span>
<span class="reserved">var</span> b = 0b1111_1111; <span class="comment">// OK</span>
<span class="reserved">var</span> c = 0b_1111_1111; <span class="comment">// エラー。0b の直後に _ を書くのはダメ</span>
<span class="reserved">var</span> d = 0xab_cd; <span class="comment">// OK</span>
<span class="reserved">var</span> e = 0x_ab_cd; <span class="comment">// エラー。0x の直後に _ を書くのはダメ</span>
</code></pre>
<p>元々、<code>0b</code> や <code>0x</code> の直後にも <code>_</code> を書きたいという要望は多々あったんですが、
「名前通りにしたい」、「数字区切りなのに数字でないところで区切れるようにはあんまりしたくない」みたいな雰囲気で、
C# 7ではこういう仕様になっています。</p>
<p>まあでも、やっぱり要望が大きく、<code>0b</code> や <code>0x</code> の直後の <code>_</code> (上記サンプルの<code>c</code>、<code>e</code>みたいな書き方)も認めようという流れになりつつあるみたいです。</p>
<h2>分解にタプルは要らないのではないか</h2>
<ul>
<li><a href="https://github.com/dotnet/roslyn/issues/18629">Surprising System.ValueTuple requirement for deconstruction #18629</a></li>
</ul>
<p>「提案」ってわけではないんですが。</p>
<p>C# 7で<a href="http://ufcpp.net/study/csharp/datatype/deconstruction/">分解</a>構文(deconstruction)が入りましたが、例えば以下のような場合を考えてみます。</p>
<pre class="source" title="">
<code><reserved></span><span class="reserved">class</span> <span class="type">Point</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> X { <span class="reserved">get</span>; }
    <span class="reserved">public</span> <span class="reserved">int</span> Y { <span class="reserved">get</span>; }
    <span class="reserved">public</span> Point(<span class="reserved">int</span> x, <span class="reserved">int</span> y) =&gt; (X, Y) = (x, y);
    <span class="reserved">public</span> <span class="reserved">void</span> Deconstruct(<span class="reserved">out</span> <span class="reserved">int</span> x, <span class="reserved">out</span> <span class="reserved">int</span> y) =&gt; (x, y) = (X, Y);
}

<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> Main()
    {
        <span class="reserved">var</span> (x, y) = (1, 2);

        <span class="comment">// ↑現状は一度 ValueTuple を作ってから、それぞれ x, yに代入するようなコードに展開される</span>
        <span class="comment">//var t = new ValueTuple&lt;int, int&gt;(1, 2);</span>
        <span class="comment">//var x = t.Item1;</span>
        <span class="comment">//var y = t.Item2;</span>

        <span class="comment">// でも、仕様上は以下のような状態に展開する最適化を認めてるし、実際将来的にそういうコード生成する可能性がある</span>
        <span class="comment">//var x = 1;</span>
        <span class="comment">//var y = 2;</span>

        <span class="comment">// だったら、var (x, y) = (1, 2); に ValueTuple は不要なはず</span>

        <span class="reserved">var</span> (a, b) = <span class="reserved">new</span> <span class="type">Point</span>(1, 2);

        <span class="comment">// ↑この場合は完全にタプルは要らないはず</span>
        <span class="comment">// 以下のようなコードに展開される(どこにも ValueTuple は出てこない)</span>
        <span class="comment">//var p = new Point(1, 2);</span>
        <span class="comment">//int a, b;</span>
        <span class="comment">//p.Deconstruct(out a, out b);</span>

        <span class="comment">// にもかかわらず、現状、分解を使っただけで ValueTuple (.NET 4.7以上、もしくは、System.ValueTuple パッケージの参照)が求められる</span>
    }
}
</code></pre>
<p>現状だと、不要なはずの <code>ValueTuple</code> が求められます。</p>
<p>これは、将来的に以下のような構文を認めるために、分解とタプル構築の内部表現を統一したのの余波です。</p>
<pre class="source" title="">
<code><reserved></span><span class="reserved">var</span> t = (<span class="reserved">var</span> x, <span class="reserved">var</span> y) = (1, 2);

<span class="comment">// ↑これは、↓これと同じ意味</span>
<span class="comment">// (var x, var y) = (1, 2);</span>
<span class="comment">// var t = (x, y);</span>
</code></pre>
<p>ですが、まあ、利用者としては不要なはずのパッケージ参照が必要になるというのは気分がいいものではありません。
実際「バグ報告」扱いで報告が入ってしまっている状況。</p>
<p>で、まあ、修正するようです。
本当に <code>ValueTuple</code> が必要になるまでは、パッケージ参照を求めないよう修正済み。
C# 7.2辺りに入れる予定みたいです。</p>
 ]]></description>
				<pubDate>Fri, 30 Jun 2017 14:13:39 +0900</pubDate>
			</item>
			<item>
				<title>Visual Studio 2017 Update 3 Preview 2</title>
				<link>http://ufcpp.net/blog/2017/6/vs2017u3p2/</link>
				<description><![CDATA[ <p>なんかVisual Studio上の通知に来てたので気づいたんですが、Visual Studio 2017 Update 3 の更新が来てました。
Visual Studio 2017 Update 3 Preview 2。
(なんかこう、もうVisual Studioもセマンティックバージョンにすればいいのに。15.3.2 とか。)</p>
<h2>C# 7.1</h2>
<p>で、ちょっと試した感じ、C# 7.1 予定の機能は全部入ってるっぽいです。
といっても、<a href="http://ufcpp.net/blog/2017/5/pickuproslyn0530/">先日書いた通り</a>、
入る機能はだいぶ絞ったっぽく、4つだけ。
以下のようなコードがちゃんとコンパイルできました。</p>
<div>
<script src="https://gist.github.com/ufcpp/6cd44a847db870559a3fccb4c64d4cb2.js"></script>
</div> ]]></description>
				<pubDate>Fri, 09 Jun 2017 19:30:33 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 5/30: C# 7.1など(de:code 2017)</title>
				<link>http://ufcpp.net/blog/2017/5/pickuproslyn0530/</link>
				<description><![CDATA[ <p>先週、<a href="https://www.microsoft.com/ja-jp/events/decode/2017/">de:code 2017</a>で登壇してきたわけですが。
資料、公開しました。</p>
<div style="width: 608px; max-width: 100%; margin-bottom:5px;"><a href="https://docs.com/iwanaga-nobuyuk/3751" title="C#の現状と今後" target="_blank" style="font-family: 'Segoe UI'; font-size: 13px; text-decoration: none; margin-left:18px ">C#の現状と今後</a><span style="font-family: 'Segoe UI'; font-size: 13px ">—</span><a href="https://docs.com/iwanaga-nobuyuk" target="_blank" style="font-family: 'Segoe UI'; font-size: 13px; text-decoration: none ">Iwanaga Nobuyuki</a></div><iframe src="https://docs.com/d/embed/D25190616-0290-4835-4550-001218788925%7eMd2f0fde0-d68b-9095-2ec5-841305bd4fb1" frameborder="0" scrolling="no" width="608px" height="377px" style="max-width:100%" allowfullscreen="True"></iframe>
<p>トラック オーナーの方に「日本の第一人者」とかいう煽りタイトルを付けられてしまったわけですが。
なんかネタなタイトル(このすば)を冗談で言ってみたら採用されてしまい、「MVPはどいつもこいつも…」とか思われてそうで怖いわけですが。
ネタはタイトルだけです。</p>
<h2>C# 7.1</h2>
<p>で、本題。
de:code参加者の中には気づいた方もいらっしゃったみたいですけども、
この資料、de:code参加者向けの事前配布版と、当日発表でちょっと内容が変わっています。</p>
<p>変わったというか、C# 7.1のところのボリュームが単純に減ってるんですが。</p>
<p>つい最近、<a href="https://github.com/dotnet/csharplang/milestone/5">C# 7.1候補マイルストーン</a>に並んでいる項目がごそっと減りました。
それを反映して、de:code登壇資料も削ったという感じです。
候補として残っているのは以下の4つ。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/102">default 式</a></li>
<li><a href="https://github.com/dotnet/csharplang/issues/415">tuple projection</a></li>
<li><a href="https://github.com/dotnet/csharplang/issues/154">ジェネリクスに対してのパターン マッチング</a></li>
<li><a href="https://github.com/dotnet/csharplang/issues/97">Main メソッドを非同期(<code>async Task</code>)にできるように</a></li>
</ul>
<p>要は、リリースまでの時間が短いなら、リリースする機能は減ってしかるべき。
項目が減ったということは、早めのタイミングでのリリースが決まった。
ということかなぁと思われます。</p>
<p><a href="http://ufcpp.net/blog/2017/5/vs15_3preview/">先日プレビュー版が出た Visual Studio 2017 Update 3</a>に、
C# 7.1も一部実装が載ったわけですが。
上記リリース タイミングの話もあり、
おそらくはVisual Studio 2017 Update 3と同時にC# 7.1もリリースなんじゃないかという状況です。</p>
<p><a href="http://www.dotnetconf.net/">.NET Conf</a>が今年は7月19～21日にやるみたいなので、この辺りでの動きを期待したいところ。</p>
 ]]></description>
				<pubDate>Tue, 30 May 2017 19:57:07 +0900</pubDate>
			</item>
			<item>
				<title>TryRoslyn 改め SharpLab で、JIT Asm表示</title>
				<link>http://ufcpp.net/blog/2017/5/roslynjitasm/</link>
				<description><![CDATA[ <p><a href="https://twitter.com/matarillo/status/864469038008631296">いつの間にか</a>と話題に。
<a href="http://ufcpp.net/blog/2016/12/tipstryroslyn/">去年の年末にちょこっと紹介したTryRoslyn</a>がJIT ASM (JITの結果がどういうネイティブコードになっているかを見れる)機能に対応してたみたいです。</p>
<p>TryRoslyn、今は<a href="https://github.com/ashmind/SharpLab">SharpLab</a>っていう名前に変わって、ドメインも取った見たいです:</p>
<ul>
<li><a href="https://sharplab.io/">https://sharplab.io/</a></li>
</ul>
<h2>ネイティブ コードの確認</h2>
<p>例えばこんな感じのコードを書いて、</p>
<pre class="source" title="">
<code><span class="reserved">using</span> <span class="reserved">static</span> System.<span class="type">Math</span>;

<span class="reserved">public</span> <span class="reserved">class</span> <span class="type">C</span>
{
    <span class="reserved">public</span> <span class="reserved">double</span> M(<span class="reserved">double</span> x, <span class="reserved">double</span> y) =&gt; Exp(x) * Sin(y);
}
</code></pre>
<p><a href="https://sharplab.io/#f:&gt;asmr/K4Zwlgdg5gBCAuBDeYDGMDKBPBBTAtgHQCyyAFgNwCwAULQA7ABGANmjKi4iCDAMK0A3rRiiYjVuwAmAe2YtcMYgApZ8xQA8ANDDWtFWAJQwAvAD4YAUQ31lG4wCpMkZUeo0AvrSA===">SharpLabに貼り付けて</a>、
ページ内の「Decompiled」のコンボボックスで「JIT Asm」を選ぶと、以下のような結果が出ます
(現時点での結果)。</p>
<pre class="source" title="">
<code><span class="comment">; This is an experimental implementation.
; Please report any bugs to https://github.com/ashmind/TryRoslyn/issues.

; Desktop CLR v4.6.1590.00 (clr.dll) on x86.</span>

C..ctor()
    L0000: <span class="reserved">ret</span>

C.M(Double, Double)
    L0000: <span class="reserved">fld</span> qword [esp+0xc]
    L0004: <span class="reserved">sub</span> esp, 0x8
    L0007: <span class="reserved">fstp</span> qword [esp]
    L000a: <span class="reserved">call</span> System.Math.Exp(Double)
    L000f: <span class="reserved">fld</span> qword [esp+0x4]
    L0013: <span class="reserved">fsin</span>
    L0015: <span class="reserved">fmulp</span> st1, st0
    L0017: <span class="reserved">ret</span> 0x10
</code></pre>
<p>C#は、C# → IL にコンパイルする時点ではそこまで大きな最適化はしていなくて、
インライン展開とかの処理はIL → ネイティブコードに JIT コンパイルするタイミングで行っていたりします。
なので、本気で最適化に取り組みたかったらネイティブコードまで追わないと細かいところがわからなかったりします。</p>
<p>昔、<a href="http://ufcpp.net/blog/2016/12/tipsildasm/">Visual Studio上でネイティブコードまで追う方法</a>とかも書きましたけど、
そこそこ面倒な手順だったりしますし。
さらっとオンラインで確認して見れるのは結構ありがたいかも。</p>
<h2>中身</h2>
<p>なんか流れを見るに、</p>
<ul>
<li>.NETチームが、主に自分たちの動作確認用に使う目的でJIT結果を見れるライブラリ(<a href="https://github.com/dotnet/jitutils">jitutils</a>)を去年くらいから作ってる</li>
<li>.NETチームの中の人が<a href="https://github.com/ashmind/SharpLab/issues/39">SharpLabの方に「これ使うとすげぇいいんじゃないか」みたいなissueを立てる</a></li>
<li>最近ついにCharpLabに組み込まれた</li>
</ul>
<p>という感じみたい。</p>
<p>ということで、最終的には.NETチームが作っているツールに行きつくみたいです。</p>
 ]]></description>
				<pubDate>Thu, 18 May 2017 11:42:28 +0900</pubDate>
			</item>
			<item>
				<title>Visual Studio 2017 Update 3 (15.3) Preview</title>
				<link>http://ufcpp.net/blog/2017/5/vs15_3preview/</link>
				<description><![CDATA[ <p><a href="https://channel9.msdn.com/Events/Build/2017/">Build 2017</a>で、Visual Studio 2017 Update 3の Preview 版が公開されました。
(ちなみに、Preview のつかない安定板 Visual Studio とは side by side の別フォルダーへのインストールになります。)</p>
<p>当初、.NET Core 2.0/.NET Standard 2.0 Preview がらみの更新かと思ったら、案外C#がらみも更新かかっていたことに今更気づいたり。
「<a href="https://channel9.msdn.com/Events/Build/2017/B8104">The future of C#</a>」とか「<a href="https://channel9.msdn.com/Events/Build/2017/B8083">The future of Visual Studio</a>」とかを見ていると、「C# 7.1」の文字が。</p>
<p>確かに、今見てみたら「C# 7.1」を使えるオプションがありました。</p>
<p><img src="/media/1133/vs15_3cs7_1.png" alt="C# 7.1" /></p>
<h2>現時点で実装されている C# 7.1 機能</h2>
<p>資料を見てると、以下の2つがリストに並んではいるんですが。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/102">default expressions</a></li>
<li><a href="https://github.com/dotnet/csharplang/issues/97">async main</a></li>
</ul>
<p>試してみてる感じ、default expressions の方しか動いてなさげ。</p>
<h3>default 式 (default expressions)</h3>
<p><code>default(T)</code>と書かなくても、左辺から型推論できる限りには<code>default</code>だけで既定値を与えられるという機能。
ちゃんと型推論なので、以下のように、マウス オーバーで型が出たりします。</p>
<p><img src="/media/1134/defaultexpressions.png" alt="default 式" /></p>
<p>名前が長い型のデフォルト引数とか作る場合にありがたそう。</p>
<pre class="source" title="">
<code>
<span class="reserved">void</span> X(
    (<span class="reserved">int</span> x, <span class="reserved">int</span> y) t = <span class="reserved">default</span>,
    <span class="type">KeyValuePair</span>&lt;<span class="reserved">string</span>, <span class="reserved">int</span>?&gt; p = <span class="reserved">default</span>,
    <span class="type">CancellationToken</span> ct = <span class="reserved">default</span>)
{
    ...
}
</code></pre>
<h3>async Mainメソッド</h3>
<p><code>Main</code>メソッドの戻り値が、<code>Task</code>、<code>Task&lt;int&gt;</code>でもよくなったという話。
もちろん、<code>await</code> を使うための仕様。</p>
<p>なんですが、なんか現状の Update 3 Preview (15.3 26510.0-Preview)ではダメでした。
普通に「<code>Main</code>のシグネチャが不正」って言ってコンパイル エラーになりました。</p>
<p>何か他に条件いるのか、次の更新で来るのか…</p>
<h2>その他、新しい IDE 機能</h2>
<p>なんか、いくつか便利そうなQuick Actionが追加されてました。</p>
<h3>引数生成</h3>
<p>メソッドの引数を書くとき、型名まで打てば、それと同名の引数を作ってくれるCode-Fixが入ったみたいです。</p>
<p>確かに、型名と引数名が一致すること多いですもんね。</p>
<p><img src="/media/1135/autoparametername.png" alt="型名通りの引数名を自動的に挿入できる機能" /></p>
<p>今、仕事で書いてるライブラリ、大体<code>CancellationToken</code>な引数の名前が<code>ct</code>だわ…
こういう略語はあんまりよくないと思いつつ、cancellationTokenって文字列が長すぎて心折れてて。
この機能を紹介するデモでまさに<code>CancellationToken</code>を使っていて、みんな考えることは同じなのかとか思いました。</p>
<h3>git 衝突解決</h3>
<p>git の衝突解決するためのQuick Actionが入ってました。</p>
<p>確かに、<code>git gui</code>とかで衝突の解決しようとすると、「どっちがremoteだっけ… この操作であってるかな…」とか常に間違い、
結局 Visual Studio 上で手作業解決してたりしますし。</p>
<p>例えば、こんな衝突したとして。</p>
<pre class="source" title="">
<code><span class="comment">&lt;&lt;&lt;&lt;&lt;&lt;&lt; HEAD</span>
<span class="reserved">class</span> <span class="type">A</span> { }
<span class="comment">=======</span>
<span class="reserved">class</span> B { }
<span class="comment">&gt;&gt;&gt;&gt;&gt;&gt;&gt; branch</span>
</code></pre>
<p>なるほど、こういうQuick Action出れば間違えないわ。</p>
<p><img src="/media/1136/gitconflict.png" alt="git 衝突解決" /></p>
<h3>コンストラクター引数からのプロパティ生成</h3>
<p>コンストラクターだけ書けば、対応するプロパティと、プロパティへの代入を生成してくれます。</p>
<p><img src="/media/1137/genproperty.png" alt="コンストラクター引数からのプロパティ生成" /></p>
<p><a href="https://www.nuget.org/packages/RecordConstructorGenerator/">RecordConstructorGenerator</a>もやっと退役かなぁ。</p>
 ]]></description>
				<pubDate>Sat, 13 May 2017 18:49:52 +0900</pubDate>
			</item>
			<item>
				<title>新しい csproj 形式</title>
				<link>http://ufcpp.net/blog/2017/5/newcsproj/</link>
				<description><![CDATA[ <p>Visual Studio 2017で、csproj 形式が新しくなりました。</p>
<p>背景としては、</p>
<ul>
<li>一時期、脱msbuildをしようとしてた
-脱msbuildのついでに、csprojを辞めて、project.json 形式にプロジェクト設定全部入れようとしてた時期があった</li>
<li>結局、msbuildに戻ったけども、既存のcsprojをもっとシンプルにしたいという要件だけが残った</li>
</ul>
<p>というものです。過渡期に関しては昔書いたブログ参照:</p>
<ul>
<li><a href="http://ufcpp.net/blog/2015/12/csprojprojectjson/">.csproj + project.json</a></li>
<li><a href="http://ufcpp.net/blog/2016/6/project-json/">「project.json辞めます」の意味</a></li>
</ul>
<p>最近、やっと新形式のcsprojの扱いに慣れてきたのでブログに書き残しておきます。</p>
<p>サンプル: <a href="https://github.com/ufcpp/UfcppSample/tree/master/Demo/2017/NewCsproj">https://github.com/ufcpp/UfcppSample/tree/master/Demo/2017/NewCsproj</a></p>
<h2>新形式</h2>
<p>これまで、Visual StudioでC#プロジェクトを新規作成すると、以下のような感じのcsprojファイルが作られていました。
(この例は、ConsoleAppNet35という名前で、 .NET Framework 3.5 向けのコンソールアプリを作ったものです。)</p>
<ul>
<li><a href="https://github.com/ufcpp/UfcppSample/blob/master/Demo/2017/NewCsproj/OldCsproj/ConsoleAppNet35/ConsoleAppNet35.csproj">ConsoleAppNet35.csproj</a></li>
</ul>
<p>一方で、Visual Studio 2017で、「.NET Standard向けライブラリ」もしくは「.NET Core向けアプリ」を作ると以下のようなcsprojが作られます。</p>
<p><a href="https://github.com/ufcpp/UfcppSample/tree/master/Demo/2017/NewCsproj/NewCsproj/ClassLibraryStd14">.NET Standard 1.4向けライブラリの例</a>:</p>
<pre class="xsource" title="">
<code><attvalue></span><span class="attvalue">&lt;</span><span class="element">Project</span><span class="attvalue"> </span><span class="attribute">Sdk</span><span class="attvalue">=</span>"<span class="attvalue">Microsoft.NET.Sdk</span>"<span class="attvalue">&gt;</span>

<span class="attvalue">  &lt;</span><span class="element">PropertyGroup</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">TargetFramework</span><span class="attvalue">&gt;</span>netstandard1.4<span class="attvalue">&lt;/</span><span class="element">TargetFramework</span><span class="attvalue">&gt;</span>
<span class="attvalue">  &lt;/</span><span class="element">PropertyGroup</span><span class="attvalue">&gt;</span>

<span class="attvalue">&lt;/</span><span class="element">Project</span><span class="attvalue">&gt;
</code></pre>
<p><a href="https://github.com/ufcpp/UfcppSample/tree/master/Demo/2017/NewCsproj/NewCsproj/ConsoleAppCore11">.NET Core 1.1向けコンソール アプリの例</a>:</p>
<pre class="xsource" title="">
<code><attvalue></span><span class="attvalue">&lt;</span><span class="element">Project</span><span class="attvalue"> </span><span class="attribute">Sdk</span><span class="attvalue">=</span>"<span class="attvalue">Microsoft.NET.Sdk</span>"<span class="attvalue">&gt;</span>

<span class="attvalue">  &lt;</span><span class="element">PropertyGroup</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">OutputType</span><span class="attvalue">&gt;</span>Exe<span class="attvalue">&lt;/</span><span class="element">OutputType</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">TargetFramework</span><span class="attvalue">&gt;</span>netcoreapp1.1<span class="attvalue">&lt;/</span><span class="element">TargetFramework</span><span class="attvalue">&gt;</span>
<span class="attvalue">  &lt;/</span><span class="element">PropertyGroup</span><span class="attvalue">&gt;</span>

<span class="attvalue">&lt;/</span><span class="element">Project</span><span class="attvalue">&gt;
</code></pre>
<p>要するに、「どうせ初期設定のまま大して変更しない設定が多いんだから、全部消す。設定した値だけを入れる」という変更。</p>
<p><code>Project</code>タグに<code>Sdk=&quot;Microsoft.NET.Sdk&quot;</code>という属性を入れることで、新形式とみなされ、この「要るものだけ残して全部消す」動作が有効になります。</p>
<h2>.NET Standard/Core 以外にも使える</h2>
<p>Visual Studio 2017でも、「.NET Framework向けライブラリ」もしくは「.NET Framework向けアプリ」のプロジェクト テンプレートは古いままです。
旧型式のcsprojファイルを生成します。</p>
<p>でも、.NET Framework向けライブラリ/アプリでも、手作業で良ければ新csproj形式を使えます。
必要な作業は、</p>
<ul>
<li>.NET Standard向けライブラリか、.NET Core向けライブラリを選んでプロジェクトを新規作成する</li>
<li>作られたcsprojファイルを開いて、<code>TargetFramework</code>タグの中身を書き換える</li>
</ul>
<p>これだけです。
.NET Framework 2.0とか3.5とか、古いフレームワークもちゃんとターゲットにできます。
また、旧型式のcsprojから、新形式のcsprojも「プロジェクト参照」できます。</p>
<p>この仕組みで作ったサンプル プロジェクトが以下の通り。</p>
<ul>
<li><a href="https://github.com/ufcpp/UfcppSample/tree/master/Demo/2017/NewCsproj/NewCsproj/ClassLibraryNet35">.NET 3.5向けライブラリ</a></li>
<li><a href="https://github.com/ufcpp/UfcppSample/tree/master/Demo/2017/NewCsproj/NewCsproj/ConsoleAppNet35">.NET 3.5向けコンソール アプリ</a></li>
</ul>
<h2>複数ターゲット</h2>
<p>新形式のcsprojでは、ターゲット フレームワークを複数指定できます。</p>
<ul>
<li><code>TargetFramework</code>タグを消して、<code>TargetFrameworks</code>(複数形)に置き換えます。</li>
<li>ターゲットを <code>;</code> で区切って複数並べます。</li>
</ul>
<p>例えば、<a href="https://github.com/ufcpp/UfcppSample/tree/master/Demo/2017/NewCsproj/NewCsproj/ClassLibraryMultiTarget">以下のような感じ</a>。</p>
<pre class="xsource" title="">
<code><attvalue></span><span class="attvalue">&lt;</span><span class="element">Project</span><span class="attvalue"> </span><span class="attribute">Sdk</span><span class="attvalue">=</span>"<span class="attvalue">Microsoft.NET.Sdk</span>"<span class="attvalue">&gt;</span>

<span class="attvalue">  &lt;</span><span class="element">PropertyGroup</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">TargetFrameworks</span><span class="attvalue">&gt;</span>net35;netstandard1.0<span class="attvalue">&lt;/</span><span class="element">TargetFrameworks</span><span class="attvalue">&gt;</span>
<span class="attvalue">  &lt;/</span><span class="element">PropertyGroup</span><span class="attvalue">&gt;</span>

<span class="attvalue">&lt;/</span><span class="element">Project</span><span class="attvalue">&gt;
</code></pre>
<p>この状態で、自動的に<code>NET35</code>、<code>NETSTANDARD1_0</code>みたいなシンボルが<code>#define</code>された状態になるので、
C#コードも以下のような条件コンパイルができます。</p>
<pre class="source" title="">
<code>    <span class="reserved">public</span> <span class="reserved">class</span> <span class="type">Class1</span>
    {
<span class="inactive">#if</span> NET35
<span class="inactive">        public static string Name =&gt; ".NET Framework 3.5";
#elif</span> NETSTANDARD1_0
        <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">string</span> Name =&gt; <span class="string">".NET Standard 1.0"</span>;
<span class="inactive">#endif</span>
    }
</code></pre>
<h2>新形式でだけ有効になる Visual Studio 2017 新機能</h2>
<p>msbuild/Visual Studioは、ビルドがらみのいくつかの新機能のオン/オフ切り替えを、ファイル形式を見て分岐しています。</p>
<p>機能としては実装されているものの、下手に既存のプロジェクトに新機能を適用すると互換性を壊しかねないので、新しいプロジェクトにだけ適用したいという意図です。</p>
<p>確かに既存プロジェクトの挙動が変わると迷惑なので仕方がないんですが、
待望の新機能を使うためにはプロジェクトの移行作業が必要になるので面倒ではあります…</p>
<p>csprojでも、新形式でだけ働きだす機能がいくつかあります。</p>
<h3>ワイルドカード</h3>
<p>ソースコードのバージョン管理をしていて、
C#ファイルを追加するたびにcsprojが衝突してうっとおしいという経験をした方は多いと思います。
ソースコード1つ1つに対して、以下のようなタグが書き出されるせいです。</p>
<pre class="source" title="">
<code><reserved></span><span class="reserved">  &lt;</span><span class="string">ItemGroup</span><span class="reserved">&gt;</span>
<span class="reserved">    &lt;</span><span class="string">Compile</span><span class="reserved"> </span>Include<span class="reserved">=</span>"<span class="reserved">Class1.cs</span>"<span class="reserved"> /&gt;</span>
<span class="reserved">    &lt;</span><span class="string">Compile</span><span class="reserved"> </span>Include<span class="reserved">=</span>"<span class="reserved">Properties\AssemblyInfo.cs</span>"<span class="reserved"> /&gt;</span>
<span class="reserved">  &lt;/</span><span class="string">ItemGroup</span><span class="reserved">&gt;</span>
</code></pre>
<p>これに対して、Visual Studio 2017では、ワイルドカード指定ができるようになっています。
以下のように、<code>**/*.cs</code>でソースコード指定すれば、フォルダー下のすべてのC#ファイルがコンパイルの対象になります。</p>
<pre class="source" title="">
<code><reserved></span><span class="reserved">  &lt;</span><span class="string">ItemGroup</span><span class="reserved">&gt;</span>
<span class="reserved">    &lt;</span><span class="string">Compile</span><span class="reserved"> </span>Include<span class="reserved">=</span>"<span class="reserved">**/*.cs</span>"<span class="reserved"> /&gt;</span>
<span class="reserved">  &lt;/</span><span class="string">ItemGroup</span><span class="reserved">&gt;</span>
</code></pre>
<p>これは、実のところ、Visual Studio 2017を使えば旧形式csprojでも使えはするんですが…</p>
<ul>
<li>もちろん手書きで csproj ファイルを書き換えないと、Visual Studioはワイルドカードを書き込んでくれない</li>
<li>それどころか、その後、Visual Studio上でC#ファイルの追加をしてしまうと、ファイル名指定の<code>Compile</code>タグが追加される</li>
<li><code>**/*.cs</code>指定のタグがある状況下で、上記操作でファイル名指定のタグが出来てしまうと「ファイルが2重に読み込まれています」警告が出まくる</li>
</ul>
<p>という状態になります。</p>
<p>一方で、新形式csprojでは、何も書かなくてもデフォルトで<code>&lt;Compile Include=&quot;**/*.cs&quot; /&gt;</code>が入っているという扱いを受けます。</p>
<h3>推移的パッケージ参照</h3>
<p>NuGetパッケージの「依存先の依存先」を遷移的に(transitive)解決してくれます。</p>
<p>これは、Visual Studio 2017での初出の機能ではなく、2015の頃からのものですが、
csproj形式の新旧によってNuGetパッケージ参照の仕方が変わります。</p>
<p>昔、「<a href="http://ufcpp.net/blog/2015/12/csprojprojectjson/">.csproj + project.json</a>」で書きましたが、「NuGet 3」移行の機能です。</p>
<p>NuGetパッケージの依存管理を packages.config でやっていると古い挙動になります。
一方で、Visual Studio 2015, 2017では、以下の方法で依存管理出来て、この場合は新しい挙動になります</p>
<ul>
<li>(Visual Studio 2015の頃) project.json を使う</li>
<li>(Visual Studio 2017) PackageReference を使う</li>
</ul>
<p>PackageReference は、新形式csprojを使うのであれば無条件にこの形式が使われます。
旧csprojの場合でも、以下のオプションを設定することでこちらを使うことができます。</p>
<p><img src="/media/1132/packagereferenceoption.png" alt="enter image description here" /></p>
<p>挙動の違いは以下のようなものです。</p>
<ul>
<li>古い挙動: 依存先が芋づる式に全部 packages.config に書き出される</li>
<li>新しい挙動: 直接参照したパッケージだけが書き出される</li>
</ul>
<h3>推移的プロジェクト参照</h3>
<p>Visual Studio 2017では、プロジェクト参照でも「依存先の依存先」を遷移的に(transitive)解決してくれます。</p>
<p>これは、新形式csprojを使っている場合にだけ有効です。
注意点として、依存階層全部が新形式csprojでないと、この仕組みが正しく動作しません。
新形式csprojからであっても、依存先が旧型式だった場合、「依存先の依存先」を全部律儀にプロジェクト参照していく必要があります。</p>
<h3>決定論的ビルド/Portable PDB</h3>
<p>新形式csprojを使うと、どうも、アセンブリ(exeやdll)やPDB(デバッグ情報ファイル)の形式がちょっと変化するみたいです。</p>
<p>C#コンパイラーが割かし最近実装した2つの機能があります。</p>
<ul>
<li>
決定論的ビルド
<ul>
<li>ドキュメント: <a href="https://github.com/dotnet/roslyn/blob/master/docs/compilers/Deterministic%20Inputs.md">Deterministic Inputs</a></li>
<li>コンパイラーに <code>/deterministic</code> オプションを付けると有効になる</li>
<li>入力が同じなら、バイナリレベルで完全に同じ出力が常に得られるという機能</li>
<li>ビルド結果のキャッシュが効きやすくなって、テスト実行とかが大幅に速くなる</li>
</ul>
</li>
<li>
Portable PDB
<ul>
<li>ドキュメント: <a href="https://github.com/dotnet/corefx/blob/master/src/System.Reflection.Metadata/specs/PortablePdb-Metadata.md">Portable PDB v1.0: Format Specification</a></li>
<li><code>/debug:portable</code>オプションを付けるとこの形式でPDBを出力する</li>
<li>仕様がオープンになっていなくて実質的にWindows専用だったPDB形式を、クロスプラットフォーム向けに一新した</li>
</ul>
</li>
</ul>
<p>で、新形式csprojを使うと、デフォルトでこれらのオプションが使われるようになります。</p>
<p>出力されるexe, dll, pdbのファイル形式が変わるので、当然、古いアプリを使っている場合に問題を起こす場合があります。
例えば、<a href="http://ilspy.net/">ILSpy</a>で逆コンパイルできなくなったりします
(まあ、<a href="https://github.com/0xd4d/dnSpy">dnSpy</a>なら読めるんで、移行してしまえばいいんですが)。</p>
<p>これで困った場合は、以下のように<code>DebugType</code>タグ設定を入れて、旧PDBを出力するようにすれば解決します。</p>
<pre class="xsource" title="">
<code><attvalue></span><span class="attvalue">&lt;</span><span class="element">Project</span><span class="attvalue"> </span><span class="attribute">Sdk</span><span class="attvalue">=</span>"<span class="attvalue">Microsoft.NET.Sdk</span>"<span class="attvalue">&gt;</span>

<span class="attvalue">  &lt;</span><span class="element">PropertyGroup</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">TargetFramework</span><span class="attvalue">&gt;</span>net35<span class="attvalue">&lt;/</span><span class="element">TargetFramework</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">DebugType</span><span class="attvalue"> </span><span class="attribute">Condition</span><span class="attvalue">=</span>"<span class="attvalue">'$(Configuration)'=='DEBUG'</span>"<span class="attvalue">&gt;</span>full<span class="attvalue">&lt;/</span><span class="element">DebugType</span><span class="attvalue">&gt;</span>
<span class="attvalue">  &lt;/</span><span class="element">PropertyGroup</span><span class="attvalue">&gt;</span>

<span class="attvalue">&lt;/</span><span class="element">Project</span><span class="attvalue">&gt;
</code></pre>
<h2>共有プロジェクト的なこと</h2>
<p>共有プロジェクト(shproj)は、要するに、1つのファイルを複数のプロジェクトから参照して使う仕組みです。</p>
<p>shprojを新形式に変換(前節で説明したような新機能への対応)するのは結局できませんでした。</p>
<p>が、まあ、かつて共有プロジェクトでやっていたようなことは、新形式csprojなら別にSharedプロジェクトなしでできます。
要するに、共有したいC#ファイルが入っているフォルダーをワイルドカードで指定してやるだけ。</p>
<p>以下のような<code>Compile</code>タグを書けば、「1段上のフォルダーの、別プロジェクトのフォルダー以下のすべてのC#ファイルをコンパイルの対象にする」ということができます。</p>
<pre class="xsource" title="">
<code><attvalue></span><span class="attvalue">&lt;</span><span class="element">Project</span><span class="attvalue"> </span><span class="attribute">Sdk</span><span class="attvalue">=</span>"<span class="attvalue">Microsoft.NET.Sdk</span>"<span class="attvalue">&gt;</span>

<span class="attvalue">  &lt;</span><span class="element">PropertyGroup</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">TargetFramework</span><span class="attvalue">&gt;</span>netstandard1.4<span class="attvalue">&lt;/</span><span class="element">TargetFramework</span><span class="attvalue">&gt;</span>
<span class="attvalue">  &lt;/</span><span class="element">PropertyGroup</span><span class="attvalue">&gt;</span>

<span class="attvalue">  &lt;</span><span class="element">ItemGroup</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">Compile</span><span class="attvalue"> </span><span class="attribute">Include</span><span class="attvalue">=</span>"<span class="attvalue">..\ClassLibraryNet35\**\*.cs</span>"<span class="attvalue"> </span><span class="attribute">Exclude</span><span class="attvalue">=</span>"<span class="attvalue">..\ClassLibraryNet35\obj\**\*.cs</span>"<span class="attvalue"> /&gt;</span>
<span class="attvalue">  &lt;/</span><span class="element">ItemGroup</span><span class="attvalue">&gt;</span>

<span class="attvalue">&lt;/</span><span class="element">Project</span><span class="attvalue">&gt;
</code></pre>
<h2>WPF/UWP</h2>
<p>まあ、「.NET Standard向け」もしくは「.NET Core向け」だけテンプレートだけが新形式csprojになっていることからお察しの通り、
<code>OutputType</code>が<code>Library</code>か<code>Exe</code>でないとちょっと苦労します。</p>
<p>WPFやWindows Formsのアプリは<code>WinExe</code>、UWPは<code>AppContainerExe</code>なんですが、この辺りのプロジェクトはデバッグ実行できなくなります。</p>
<p>ちなみに、WPFでビルドするところまではできることを確認済み。
以下のような設定が、WPFアプリをビルドするのに必要な最低限のものです。
(ビルドはできるんですが、デバッグ実行しようとすると「Unable to run your project」というエラーが出ます。)</p>
<pre class="xsource" title="">
<code><attvalue></span><span class="attvalue">&lt;</span><span class="element">Project</span><span class="attvalue"> </span><span class="attribute">Sdk</span><span class="attvalue">=</span>"<span class="attvalue">Microsoft.NET.Sdk</span>"<span class="attvalue">&gt;</span>

<span class="attvalue">  &lt;</span><span class="element">PropertyGroup</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">OutputType</span><span class="attvalue">&gt;</span>WinExe<span class="attvalue">&lt;/</span><span class="element">OutputType</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">TargetFramework</span><span class="attvalue">&gt;</span>net47<span class="attvalue">&lt;/</span><span class="element">TargetFramework</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">LanguageTargets</span><span class="attvalue">&gt;</span>$(MSBuildExtensionsPath)\$(VisualStudioVersion)\Bin\Microsoft.CSharp.targets<span class="attvalue">&lt;/</span><span class="element">LanguageTargets</span><span class="attvalue">&gt;</span>
<span class="attvalue">  &lt;/</span><span class="element">PropertyGroup</span><span class="attvalue">&gt;</span>

<span class="attvalue">  &lt;</span><span class="element">ItemGroup</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">ApplicationDefinition</span><span class="attvalue"> </span><span class="attribute">Include</span><span class="attvalue">=</span>"<span class="attvalue">App.xaml</span>"<span class="attvalue"> </span><span class="attribute">SubType</span><span class="attvalue">=</span>"<span class="attvalue">Designer</span>"<span class="attvalue"> </span><span class="attribute">Generator</span><span class="attvalue">=</span>"<span class="attvalue">MSBuild:Compile</span>"<span class="attvalue"> /&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">Page</span><span class="attvalue"> </span><span class="attribute">Include</span><span class="attvalue">=</span>"<span class="attvalue">**\*.xaml</span>"<span class="attvalue"> </span><span class="attribute">Exclude</span><span class="attvalue">=</span>"<span class="attvalue">App.xaml</span>"<span class="attvalue"> </span><span class="attribute">SubType</span><span class="attvalue">=</span>"<span class="attvalue">Designer</span>"<span class="attvalue"> </span><span class="attribute">Generator</span><span class="attvalue">=</span>"<span class="attvalue">MSBuild:Compile</span>"<span class="attvalue"> /&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">Compile</span><span class="attvalue"> </span><span class="attribute">Update</span><span class="attvalue">=</span>"<span class="attvalue">**\*.xaml.cs</span>"<span class="attvalue"> </span><span class="attribute">SubType</span><span class="attvalue">=</span>"<span class="attvalue">Designer</span>"<span class="attvalue"> </span><span class="attribute">DependentUpon</span><span class="attvalue">=</span>"<span class="attvalue">%(Filename)</span>"<span class="attvalue"> /&gt;</span>
<span class="attvalue">  &lt;/</span><span class="element">ItemGroup</span><span class="attvalue">&gt;</span>

<span class="attvalue">  &lt;</span><span class="element">ItemGroup</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">Reference</span><span class="attvalue"> </span><span class="attribute">Include</span><span class="attvalue">=</span>"<span class="attvalue">System.Xaml</span>"<span class="attvalue"> /&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">Reference</span><span class="attvalue"> </span><span class="attribute">Include</span><span class="attvalue">=</span>"<span class="attvalue">PresentationCore</span>"<span class="attvalue"> /&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">Reference</span><span class="attvalue"> </span><span class="attribute">Include</span><span class="attvalue">=</span>"<span class="attvalue">PresentationFramework</span>"<span class="attvalue"> /&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">Reference</span><span class="attvalue"> </span><span class="attribute">Include</span><span class="attvalue">=</span>"<span class="attvalue">WindowsBase</span>"<span class="attvalue"> /&gt;</span>
<span class="attvalue">  &lt;/</span><span class="element">ItemGroup</span><span class="attvalue">&gt;</span>

<span class="attvalue">&lt;/</span><span class="element">Project</span><span class="attvalue">&gt;
</code></pre>
<p>実行できないのでアプリのプロジェクトに使うには苦しいんですが、例えば、「WPF向けコントロールやリソース ディクショナリ(XAML)を含むライブラリ」を作りたい場合であれば、新形式csprojを十分実用できます。</p>
 ]]></description>
				<pubDate>Fri, 12 May 2017 21:05:17 +0900</pubDate>
			</item>
			<item>
				<title>int 型のジェネリック型引数</title>
				<link>http://ufcpp.net/blog/2017/4/intgenericparamter/</link>
				<description><![CDATA[ <p><a href="http://ufcpp.net/blog/2017/4/bitfields/">昨日のビットフィールド用コード生成</a>の副産物の話。</p>
<h2>M～Nビット目</h2>
<p>「int型変数のM～Nビットの範囲を取り出す処理をしたい」みたいなときに、「M～Nビット目を表す型」を作りたいときがあったりします。
(まあ、ビットフィールドの利用頻度自体がそんなに高くないので、この型の需要もそこまで大きくはないですが。)</p>
<p>ってことで、書きたいのはこんなコード:</p>
<pre class="source" title="[M, N)ビット目を読み書きする構造体">
<code><span class="comment">// C# では書けない書き方。C++だとこんな感じのことができたりする。</span>
<span class="comment">// [M, N) (N は含まない)の範囲のビットを読み書きする構造体。</span>
<span class="reserved">struct</span> <span class="type">Bit</span>&lt;<span class="type">T</span>, <span class="type">M</span>, <span class="type">N</span>&gt;
{
    <span class="comment">// C# で書けないことその1: 参照フィールド</span>
    <span class="reserved">ref</span> <span class="type">T</span> _r;
    <span class="reserved">public</span> Bit(<span class="reserved">ref</span> <span class="type">T</span> r) =&gt; _r = <span class="reserved">ref</span> r;

    <span class="comment">// C# で書けないことその2: ジェネリック引数が型じゃなくて int</span>
    <span class="reserved">private</span> <span class="reserved">const</span> <span class="reserved">int</span> Shift = <span class="type">M</span>;
    <span class="reserved">private</span> <span class="reserved">const</span> <span class="type">T</span> Mask = (1 &lt;&lt; <span class="type">N</span>) - (1 &lt;&lt; <span class="type">M</span>);

    <span class="comment">// C# で書けないことその3: ジェネリックな型に対して静的な処理(&amp; とかの演算子)</span>
    <span class="reserved">public</span> <span class="type">T</span> Value
    {
        <span class="reserved">get</span> =&gt; (r &gt;&gt; Shift) &amp; Mask;
        <span class="reserved">set</span> =&gt; r = (r &amp; (~Mask)) | ((<span class="reserved">value</span> &lt;&lt; Shift) &amp; Mask);
    }
}
</code></pre>
<p>素直にできないことが3つほどあります。</p>
<ol>
<li>参照フィールド</li>
<li><code>int</code> 型なジェネリック引数</li>
<li>ジェネリックな型に対して静的な処理(特に、<code>&amp;</code> などの演算子)</li>
</ol>
<p>1つ目の参照フィールドに関しては、unsafeでよければポインターを使って近いことはできます。
(ポインターなので、使う際に<a href="http://ufcpp.net/study/csharp/sp_unsafe.html#fixed"><code>fixed</code></a>必須だったり、参照先が残っている保証がなかったり、いろいろ問題あり。)
今、<a href="https://github.com/dotnet/coreclr/blob/master/src/mscorlib/src/System/ByReference.cs"><code>ByReference&lt;T&gt;</code>型</a>とかいう、ランタイムで特殊処理して「参照フィールドっぽいもの」を実現しようとしている動きもあります。</p>
<p>まあ、今日の話は残りの2つ、特に、2つ目の<code>int</code>型ジェネリック引数です。</p>
<h2>ジェネリクスに静的な処理を</h2>
<p>素直な手段では、C#で静的な処理に対してジェネリクスを使う手段がなかったりします。
だいたいインターフェイス越しにメソッドを呼ぶことになっちゃって、仮想呼び出しになる。
仮想呼び出しなので、インライン展開とかも効かず、あんまり実行性能はよろしくない。</p>
<p>ですが、まあ、ちょっと煩雑なコードを書いていいなら、ジェネリック、かつ、高性能なコードを書く手段は一応あります。</p>
<p>参考:</p>
<ul>
<li><a href="http://ufcpp.net/study/csharp/sp2_generics.html?p=3#pseudo-static">静的メソッド代わり</a></li>
<li>
<a href="https://github.com/ufcpp/UfcppSample/tree/master/Demo/2017/InlineExpansion">値型ジェネリックを使った最適化</a>
<ul>
<li>(この辺りもそのうちちゃんとした説明書きたい)</li>
</ul>
</li>
</ul>
<p>こういうトリックを使って、「M～Nビット目を表す型」を作ってみたのが以下のコード:</p>
<ul>
<li><a href="https://github.com/ufcpp/BitFields/blob/master/experimental/TypeClassBits/Bits_M_N.cs">型定義: <code>Bits&lt;T, TOp, LowBit, HighBit&gt;</code>型</a></li>
<li><a href="https://github.com/ufcpp/BitFields/blob/master/experimental/ConsoleApp1/TypeClassBits/DoubleView.cs">利用例</a></li>
</ul>
<h2><code>int</code> 型なジェネリック引数の需要</h2>
<p>まあ、上記の<a href="https://github.com/ufcpp/BitFields/blob/master/experimental/TypeClassBits/Bits_M_N.cs"><code>Bits&lt;T, TOp, LowBit, HighBit&gt;</code>型</a>だと、やってることが多すぎてちょっと細かく見て行くのしんどいかなぁとか思って、「<code>int</code> 型なジェネリック引数」もどきを実現する部分だけを抜き出したのがこちら:</p>
<ul>
<li><a href="https://github.com/ufcpp/UfcppSample/tree/master/Demo/2017/IntTemplateParameter/IntTemplateParameter">C++ の template<int N> もどきを C# で</a></li>
</ul>
<p>この手の要件に対してよく例として使われる<a href="https://ja.wikipedia.org/wiki/%E6%9C%89%E9%99%90%E4%BD%93">ガロアの有限体</a>を実装しています。</p>
<p>またちょっと、数学わからない人には申し訳ない感じの例ですが…
要するに、Nが素数のとき、N個の値から成る「四則演算全部まっとうにできる型」が作れるって話です。
(整数の部分集合なのに、整数÷整数で、同じ範囲の整数値に収まる。任意の値 a に対して、a × b = 1 となる b がただ1つ定まります。)</p>
<p>2値からなるF<sub>2</sub>と、3値からなるF<sub>3</sub>は当然「別の型」なわけで、
プログラムを書く場合にも、型引数にして2と3で「別の具象型」を作れる仕組みが欲しくなります。</p>
<h2><code>GaloisField&lt;N&gt;</code></h2>
<p>ということで、それをC#で、<a href="https://github.com/ufcpp/UfcppSample/tree/master/Demo/2017/IntTemplateParameter/IntTemplateParameter"><code>GaloisField&lt;N&gt;</code>って書き方で書けるようにしたのが</a>今日のポイント。</p>
<p>必要な個所だけ抜き出すと、以下のような感じ。</p>
<pre class="source" title="C# でintジェネリック引数">
<code><span class="reserved">public</span> <span class="reserved">interface</span> <span class="type">IConstant</span>&lt;<span class="type">T</span>&gt;
{
    <span class="type">T</span> Value { <span class="reserved">get</span>; }
}

<span class="reserved">public</span> <span class="reserved">struct</span> <span class="type">GaloisField</span>&lt;<span class="type">N</span>&gt;
    <span class="reserved">where</span> <span class="type">N</span> : <span class="reserved">struct</span>, <span class="type">IConstant</span>&lt;<span class="reserved">int</span>&gt;
{
    <span class="comment">// ガロアの有限体を作るにあたって必要なのは、拡張ユークリッド互除法っていうアルゴリズム</span>
    <span class="comment">// https://github.com/ufcpp/UfcppSample/blob/master/Demo/2017/IntTemplateParameter/IntTemplateParameter/GaloisField_N.cs#L43</span>

    <span class="comment">// で、その中で、「i を N で割った余り」を使う</span>
    <span class="comment">// (C# の % だと、i が負の時に結果が負になるので、その場合には N を足して正にする。)</span>
    <span class="reserved">static</span> <span class="reserved">int</span> Mod(<span class="reserved">int</span> i)
    {
        <span class="comment">// 定数「N」の代わりに、default(N).Value って書く</span>
        i %= <span class="reserved">default</span>(<span class="type">N</span>).Value;
        <span class="reserved">if</span> (i &lt; 0) i += <span class="reserved">default</span>(<span class="type">N</span>).Value;
        <span class="reserved">return</span> i;
    }
}
</code></pre>
<p>ただし、定数代わりに、以下のような構造体を作っておく必要あり。</p>
<pre class="source" title="定数もどきの構造体">
<code><span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">class</span> <span class="type">ConstantInt</span>
{
    <span class="reserved">public</span> <span class="reserved">struct</span> <span class="type">_0</span> : <span class="type">IConstant</span>&lt;<span class="reserved">int</span>&gt; { <span class="reserved">public</span> <span class="reserved">int</span> Value =&gt; 0; }
    <span class="reserved">public</span> <span class="reserved">struct</span> <span class="type">_1</span> : <span class="type">IConstant</span>&lt;<span class="reserved">int</span>&gt; { <span class="reserved">public</span> <span class="reserved">int</span> Value =&gt; 1; }
    <span class="reserved">public</span> <span class="reserved">struct</span> <span class="type">_2</span> : <span class="type">IConstant</span>&lt;<span class="reserved">int</span>&gt; { <span class="reserved">public</span> <span class="reserved">int</span> Value =&gt; 2; }
    <span class="comment">//...</span>
}
</code></pre>
<p>いちいち必要な分だけ構造体を定義しておかないといけないので、定数の置き換えとしては不完全ですけども、
実行性能的には結構いい結果になるはずです。
(ちゃんと静的に展開されて、インライン化もされる状態になります。)</p>
 ]]></description>
				<pubDate>Sat, 29 Apr 2017 23:12:33 +0900</pubDate>
			</item>
			<item>
				<title>C# でビットフィールド</title>
				<link>http://ufcpp.net/blog/2017/4/bitfields/</link>
				<description><![CDATA[ <p><a href="https://github.com/dotnet/csharplang/">csharplang</a>に、</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/465">C++のビットフィールドみたいなの、C# にもほしい</a></li>
<li><a href="https://github.com/dotnet/csharplang/issues/457">(任意のビット数を表す)bit 型が欲しい</a></li>
</ul>
<p>みたいなのが投稿されていまして。</p>
<p>「それ、ライブラリとアナライザー、ちょっとしたソースコード生成でできるよ。」という話。</p>
<h2>BitFields ライブラリ</h2>
<p>ということで実装してみたのがこちら。</p>
<ul>
<li><a href="https://github.com/ufcpp/BitFields">BitFields ライブラリのソースコード</a></li>
<li><a href="https://github.com/ufcpp/UfcppSample/blob/master/Demo/2017/BitFieldsSample/Program.cs">利用例(double/floatの内部ビット操作とか、RGB555形式とか)</a></li>
<li><a href="https://gist.github.com/ufcpp/f1fd6a5acd7717565e4fddfa9431e9fa">他に、昔実際に仕事で書いたビットフィールドの例</a></li>
</ul>
<p>昔、ビットフィールド的なものを手作業実装してた時に、「これはコード生成でやりたい…」とか思ってて、
できる宛まではついてたんですが。
なんだかんだ言って<a href="http://www.buildinsider.net/enterprise/roslynextension/03">アナライザーを書くの</a>は結構めんどくさいんで、放置してすでに数年。</p>
<p>まあ、いい機会だから久々に重い腰を上げてアナライザー書いてみるかと思って作ったのが上記の<a href="https://github.com/ufcpp/BitFields">BitFields</a>です。</p>
<h2>できること</h2>
<h3>Nビット整数</h3>
<p>Nビットまでの整数を受け付ける<code>BitN</code>(<code>N</code>は1～64)型と、それに対するアナライザーがあります。</p>
<p><img src="/media/1130/bitn.png" alt="BitN型とアナライザー" /></p>
<p>ちゃんと、ビット数を超える値(例えば<code>Bit1</code>に2)を代入しようとするとコンパイル エラーになります。</p>
<h3>ビットフィールドコード生成</h3>
<p>例えば、<a href="http://www.webtech.co.jp/blog/optpix_labs/format/942/">RGB555</a>とか、半端なビット数で色情報を扱う形式があります。
32bitカラーが当たり前な今時だと珍しいですけど、昔はこういう形式も割と使われていました。</p>
<p>で、それを、こう書く。</p>
<pre class="source" title="Rgb555構造体定義">
<code><reserved></span><span class="reserved">struct</span> <span class="type">Rgb555</span>
{
    <span class="reserved">enum</span> <span class="type">BitFields</span>
    {
        B = 5,
        G = 5,
        R = 5,
    }
}
</code></pre>
<p>コード生成都合で、「構造体の中に<code>BitFields</code>という名前のenumを定義、値としてビット数を与える」みたいな規約ベースの型情報を書きます。
このenumはあくまでメタデータ(型情報)であって、実行時には一切使いません。</p>
<p>で、以下のように、クイック アクション(電球アイコン)が出るので、生成メニュー(Generate bit-fields)を選択。</p>
<p><img src="/media/1131/bitfieldgenerator.png" alt="ビットフィールド生成" /></p>
<p>以下のようなコードが生成されます。</p>
<pre class="source" title="Rgb555の生成結果">
<code><reserved></span><span class="reserved">using</span> BitFields;

<span class="reserved">partial</span> <span class="reserved">struct</span> <span class="type">Rgb555</span>
{
    <span class="reserved">public</span> <span class="reserved">ushort</span> Value;

    <span class="reserved">private</span> <span class="reserved">const</span> <span class="reserved">int</span> BShift = 0;
    <span class="reserved">private</span> <span class="reserved">const</span> <span class="reserved">ushort</span> BMask = <span class="reserved">unchecked</span>((<span class="reserved">ushort</span>)((1U &lt;&lt; 5) - (1U &lt;&lt; 0)));
    <span class="reserved">public</span> <span class="type">Bit5</span> B
    {
        <span class="reserved">get</span> =&gt; (<span class="type">Bit5</span>)((Value &amp; BMask) &gt;&gt; BShift);
        <span class="reserved">set</span> =&gt; Value = <span class="reserved">unchecked</span>((<span class="reserved">ushort</span>)((Value &amp; ~BMask) | ((((<span class="reserved">ushort</span>)<span class="reserved">value</span>) &lt;&lt; BShift) &amp; BMask)));
    }
    <span class="reserved">private</span> <span class="reserved">const</span> <span class="reserved">int</span> GShift = 5;
    <span class="reserved">private</span> <span class="reserved">const</span> <span class="reserved">ushort</span> GMask = <span class="reserved">unchecked</span>((<span class="reserved">ushort</span>)((1U &lt;&lt; 10) - (1U &lt;&lt; 5)));
    <span class="reserved">public</span> <span class="type">Bit5</span> G
    {
        <span class="reserved">get</span> =&gt; (<span class="type">Bit5</span>)((Value &amp; GMask) &gt;&gt; GShift);
        <span class="reserved">set</span> =&gt; Value = <span class="reserved">unchecked</span>((<span class="reserved">ushort</span>)((Value &amp; ~GMask) | ((((<span class="reserved">ushort</span>)<span class="reserved">value</span>) &lt;&lt; GShift) &amp; GMask)));
    }
    <span class="reserved">private</span> <span class="reserved">const</span> <span class="reserved">int</span> RShift = 10;
    <span class="reserved">private</span> <span class="reserved">const</span> <span class="reserved">ushort</span> RMask = <span class="reserved">unchecked</span>((<span class="reserved">ushort</span>)((1U &lt;&lt; 15) - (1U &lt;&lt; 10)));
    <span class="reserved">public</span> <span class="type">Bit5</span> R
    {
        <span class="reserved">get</span> =&gt; (<span class="type">Bit5</span>)((Value &amp; RMask) &gt;&gt; RShift);
        <span class="reserved">set</span> =&gt; Value = <span class="reserved">unchecked</span>((<span class="reserved">ushort</span>)((Value &amp; ~RMask) | ((((<span class="reserved">ushort</span>)<span class="reserved">value</span>) &lt;&lt; RShift) &amp; RMask)));
    }
}
</code></pre>
<p>現状だと1度は手作業で「クイック アクションの選択」が必要なので、使い勝手はいまいちなんですが。
そのうち、<a href="https://github.com/dotnet/csharplang/issues/107">正式にコード生成機能がC#に入るはず</a>で、その暁ににはもう少し利便性がよくなります。</p>
<h2>ライブラリだけでできることはライブラリで</h2>
<p>まあ、一般論として、ライブラリだけでできるならライブラリ提供でいいわけで。
ライブラリを作ってみた結果として、本当にライブラリだけだと不便ということになれば、そこで初めて言語文法の提案をすればいい。</p>
<p>実際、ライブラリありきで出ている提案もあったりします。</p>
<ul>
<li><a href="https://ja.wikipedia.org/wiki/Midori_(%E3%82%AA%E3%83%9A%E3%83%AC%E3%83%BC%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0)">Midori</a>の成果の1つとして、<a href="https://github.com/joeduffy/slice.net">Slice.NET</a>ってのが作られる</li>
<li>Slice.NETを標準ライブラリに取り入れるべく、<a href="https://github.com/dotnet/corefxlab/blob/master/docs/specs/span.md">corefxlab</a>で検討される</li>
<li>
現在、実際に<a href="https://github.com/dotnet/corefx/tree/master/src/System.Memory">System.Memory</a>というパッケージ名で標準ライブラリ化してる
<ul>
<li><a href="https://dotnet.myget.org/feed/dotnet-core/package/nuget/System.Memory">dailyビルドなプレビュー版で良ければ、NuGetパッケージあり</a></li>
<li>プレビューが外れるのはたぶん、「<a href="https://github.com/dotnet/csharplang/milestone/6">C# 7.2</a>」のタイミング</li>
</ul>
</li>
<li>これが標準ライブラリに入るのであれば、C#としても検討していい文法がある: <a href="https://github.com/dotnet/csharplang/issues/185">slicing</a></li>
</ul>
<p>特に、今回やったビットフィールド生成みたいなものは、ちょっと「コンパイラーの仕事」にするにはいまいちかなぁと思います。</p>
<ul>
<li>シフトやマスク演算のコードが見えている方が理解がしやすい</li>
<li>
エンディアンの問題とかあって、汎用化するには怖い
<ul>
<li>個人でライブラリを作る限りには「ビッグ エンディアン？知らない子ですね。現存するエンディアンじゃないですよ？」とか敵を作りそうな発言もできるものの、標準に取り込む際にそれを言えるかというと無理</li>
</ul>
</li>
<li>
人によって求めるものが違う
<ul>
<li>immutable版が欲しい</li>
<li><code>Value</code>フィールドがpublicなのは嫌</li>
<li>コンストラクター、デコンストラクターもほしい</li>
<li><code>BitN</code>、コンパイル時チェックだけじゃなくて実行時チェックもほしい(あるいは逆に、そんな実行時コストは絶対避けたい)</li>
</ul>
</li>
</ul>
<p>しかも今のC#だと、アナライザーを書けば「<code>Bit1</code>なら0と1だけ代入で来てほしい。2以上はビット数オーバーでコンパイル時エラー」みたいなこともできます。
ライブラリだけでできちゃうことも増えているので、コンパイラーのバージョンアップとか待ってないでライブラリ作っちゃえば良かったりします。</p>
 ]]></description>
				<pubDate>Fri, 28 Apr 2017 20:24:16 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 4/16</title>
				<link>http://ufcpp.net/blog/2017/4/pickuproslyn0416/</link>
				<description><![CDATA[ <p>結構久々のSprint進捗報告。</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/issues/18719">Sprint 116 Summary #18719</a></li>
</ul>
<p>Visual Studio 2017リリース前後の作業が「バグ修正してた」しかなかったので、割かしほんとに久々。
C# 7.1/7.2作業が始まっています。
いくつか紹介。
(ここに並んでいるのが7.1/7.2に入る全てでもないし、優先度の変更もあり得るものです。あくまで、最近作業したもので、現状の予定としてこのバージョンで出したいというもの。)</p>
<h2>C# 7.1</h2>
<h3>default 式</h3>
<p>左辺から型推論が効くなら、<code>default(T)</code>の<code>(T)</code>の部分を省略可能にするという話。</p>
<p><a href="http://ufcpp.net/blog/2016/9/pickuproslyn0906/">割と前から</a>実装を初めていて、masterにmerge済み。</p>
<h3>async main</h3>
<p>やっと、<code>Main</code> メソッドを非同期にできるようになるみたい。実装的には、</p>
<ul>
<li><code>Main</code>の戻り値に<code>Task</code>と<code>Task&lt;int&gt;</code>を許す</li>
<li>その場合、<code>async</code>修飾子を付けるの必須</li>
<li>コード生成で、<code>Main().GetAwaiter().GetResult()</code>を呼ぶだけの繋ぎ用メソッドを生成する</li>
</ul>
<p>という感じみたい。</p>
<h3>Tuple names</h3>
<p>タプルでも、匿名型みたいに要素名を自動で付けたいっていう話。
↓みたいに、変数<code>x</code>, <code>y</code>があるとき、<code>(x, y)</code>と書けば、タプル要素名を自動的に<code>x</code>にしてほしいという。</p>
<p><img src="/media/1129/tuplename.png" alt="tuple names" /></p>
<h2>C# 7.2</h2>
<p>一部ビルドできるようにして、<a href="https://github.com/dotnet/corefxlab/">CoreFX Labs</a>で使ってもらい始めたみたい。</p>
<p>確かに、時々、Visual Studio 2017付属の普通のC# 7.0コンパイラーではビルドできないコードがあるんですよねぇ、corefxlab。</p>
<h3>Span Safety</h3>
<p><a href="https://dotnet.myget.org/feed/dotnet-core/package/nuget/System.Memory"><code>System.Memory</code></a>パッケージ中に入ってる<code>Span&lt;T&gt;</code>構造体がらみで、ちょっとコンパイラーによる制限を掛けたいっていう話。</p>
<p><code>Span&lt;T&gt;</code>型は、内部的にスタック上の参照を握っちゃったりするんで、<code>ref</code>と同種のコード フロー解析をしないとまずいということみたい。今は妥協的な実装をしているものの、将来的には<a href="https://github.com/dotnet/coreclr/blob/d4fd78eb013de26639b3327f45072807858d0dde/src/mscorlib/src/System/ByReference.cs"><code>ByReference&lt;T&gt;</code>型</a>とかいう、ほんとに「フィールドとして参照を持てる型」を作って使いたいみたいで、そうなると、<code>Span&lt;T&gt;</code>に対するフロー解析をちゃんとやらないといよいよまずい。</p>
<p>要するに、</p>
<ul>
<li><code>ref T</code>と同種の扱いをしないといけない型を<code>ref-like</code>タイプと呼ぶ</li>
<li>
条件としては、
<ul>
<li>参照(<code>ref T</code>)や、一定範囲のメモリ(<code>(ref T data, int length)</code>)を握っている構造体</li>
<li>あるいは、それを入れ子で握っている構造体</li>
</ul>
</li>
<li>
掛かる制限としては、<code>ref T</code>と同じく、
<ul>
<li>
普通の型のフィールドにできない
<ul>
<li><code>ref-like</code>型のフィールドにはできる</li>
</ul>
</li>
<li><a href="http://ufcpp.net/study/csharp/sp_ref.html?p=2#ref-returns">引数として受け取ったものとか、一部のものしか戻り値として返せない</a></li>
</ul>
</li>
</ul>
<p>という型。</p>
<h4>補足: TypedReference</h4>
<p>これ、実のところ、現在のC#でも<code>TypedReference</code>っていう「<code>ref T</code>と同じ扱いしないとまずい型」があったりします。
まあ、<a href="http://ufcpp.net/study/csharp/sp_makeref.html">隠し(ドキュメント化されていない)機能</a>を使わないと扱えない型なので問題にはなっていませんが。</p>
<p>現状の<code>TypedReference</code>は特殊な制約が掛かっていて、やっぱり普通の型のフィールドにできなくなっています。
C# 7.0で参照戻り値が書けるようになったのに対して、<code>TypedReference</code>はいまだに戻り値にも使えません。
これも、参照戻り値と同ラインまでは制限を緩めて大丈夫なはずで、<code>ref-like</code>型の一例です。</p>
<h3>ref readonly</h3>
<p><a href="http://ufcpp.net/blog/2017/2/pickuproslyn0213/">2月に紹介した</a>やつ。C++でいう<code>const&amp;</code>。
構造体のコピーを避けるための参照渡しであって、書き換えは認めたくないっていうやつ。
一部、プロトタイプ実装を始めたみたいです。</p>
<h2>その先</h2>
<p>ちょうど最近<a href="http://www.buildinsider.net/column/iwanaga-nobuyuki/013">Build Insiderの記事書きました</a>けども、インターフェイスのデフォルト メソッドの実装作業、もう始まっていたりします。
まあ、それなりに時間が掛かる作業なので、今実装が始まっているって言っても、実際のリリースはだいぶ先。</p>
<p>同様に、非null参照がらみもちらほら作業を進めてるみたいです。
(書かれてる作業内容的には、前々から作業してたやつがしばらく塩漬けで、それを久々にmasterブランチと同期したっぽい？)</p>
 ]]></description>
				<pubDate>Sun, 16 Apr 2017 21:39:16 +0900</pubDate>
			</item>
			<item>
				<title>.NET Framework 4.7</title>
				<link>http://ufcpp.net/blog/2017/4/net47update/</link>
				<description><![CDATA[ <p>.NET Framework 4.7がリリースされたみたいですね。</p>
<ul>
<li><a href="https://blogs.msdn.microsoft.com/dotnet/2017/04/05/announcing-the-net-framework-4-7/">Announcing the .NET Framework 4.7</a></li>
</ul>
<h2>更新内容</h2>
<p>.NET Framework 自体よりも、ドキュメントとかのシステム更新の方が目立つかも。</p>
<ul>
<li><a href="https://docs.microsoft.com/en-us/dotnet/api/">API ドキュメントが docs に移行</a></li>
<li><a href="https://github.com/Microsoft/dotnet/blob/master/releases/net47/dotnet47-api-changes.md">API の更新履歴が GitHub 上に</a></li>
</ul>
<p>自分が直接関係しそうなのは、<code>ValueTuple</code>構造体の追加くらいかなぁ。</p>
<h2>ValueTuple</h2>
<p><a href="http://ufcpp.net/study/csharp/datatype/tuples/">C# 7.0のタプル</a>を使うには、<code>ValueTuple</code>構造体が必要なわけですが。</p>
<p>.NET Framework 4.7は、標準で<code>ValueTuple</code>構造体を含む初のバージョンになりました。
(.NET Framework 4.7以外では<a href="https://www.nuget.org/packages/System.ValueTuple/"><code>System.ValueTuple</code>パッケージ</a>の参照が必要。)
後述の通り、今日のリリースだとWindows 10にしか.NET Framework 4.7が来ていないので、あまりまだ選べる選択肢ではなさそうな気もします。
まあそれに、PCLとかNetStandardなライブラリ、.NET Coreでもまだ<a href="https://www.nuget.org/packages/System.ValueTuple/"><code>System.ValueTuple</code>パッケージ</a>が必要です。</p>
<h2>Windows 10 Creators Update</h2>
<p>というか、単体インストーラーはなくて、Windows 10の<a href="http://internet.watch.impress.co.jp/docs/news/1051787.html">Creators Update</a>とともにアナウンス。</p>
<p>Visual Studio 2017も同時に更新されましたけども、.NET Framework 4.7をターゲットにするためには、現状だと、</p>
<ul>
<li>Windows 自体にCreators Updateを掛ける</li>
<li>Visual Studio 2017を更新する</li>
<li>更新の際に、[変更] → [コンポーネント] → .NET Framework 4.7 SDK、.NET Framework 4.7 Targeting Pack にチェックを入れる</li>
</ul>
<p>ってやらないとダメみたい。</p>
<p><img src="/media/1128/vs2017net47.png" alt="Visual Studio 2017に.NET Framework 4.7 SDKを追加" /></p>
<h2>リリース順</h2>
<p>リリース順、これまでだと、</p>
<ol>
<li>.NET Framework の更新/単体インストーラー配布</li>
<li>Visual Studio/C# のリリース = Windows のリリース</li>
</ol>
<p>みたいな順が多かったんですけどね。今回、</p>
<ol>
<li>Visual Studio/C# のリリース</li>
<li>Windows のリリース/.NET Framework の更新</li>
<li>.NET Framework 単体インストーラー配布(まだない)</li>
</ol>
<p>っぽい。
「C# 7.0がリリースされたのに、<code>ValueTuple</code>を標準で含んだバージョンの.NET Frameworkはまだ出ないんだ」とか、
これまでのリリース順からすると不思議な感じでしたけども、Windowsのリリース スケジュールのせいでしたか。
(てっきり、.NET Core辺りのリリース遅れが犯人かと思ってました。)</p>
<h2>.NETランタイム更新</h2>
<p>.NETランタイムの配布方法を、以下のようにしていきたいのかなぁとか思ったり。</p>
<ul>
<li>スマホ: AOT(Ahead of Time: 事前コンパイル)でアプリ単一バイナリにコンパイル</li>
<li>サーバー: .NET CoreでNuGetベースの更新</li>
<li>デスクトップ: Windowsの自動アップデートに同梱</li>
</ul>
<p>C# にもそろそろ、ランタイムへの機能追加が必要な構文を追加したいみたいな動き出てきてますしね。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/251">Places where runtime bugs interfere with compiler or language evolution #251</a></li>
<li><a href="https://github.com/dotnet/csharplang/issues/288">A Tour of Default Interface Methods for C# (&quot;traits&quot;) #288</a></li>
</ul>
<p>古いランタイムが残りにくい仕組みにしたがっていそう。</p>
 ]]></description>
				<pubDate>Thu, 06 Apr 2017 16:42:04 +0900</pubDate>
			</item>
			<item>
				<title>C# 7.0リリース(もう2週間くらい経過したけども)</title>
				<link>http://ufcpp.net/blog/2017/3/csharp7rtm/</link>
				<description><![CDATA[ <p>気が付けば、Visual Studio 2017がリリースされてから2週間くらい経ってしまっているわけですが…</p>
<p>マイクロソフト公式の<a href="https://connpass.com/event/50910/">Release Celebration</a>でLT登壇したり、
自分主催の<a href="https://csugjp.connpass.com/event/50930/">リリース記念勉強会</a>やったりとかで、
すっかり力尽きていました。</p>
<p>そんな感じでしたが、2点ほどそれの事後的な話。</p>
<ul>
<li><a href="https://csugjp.connpass.com/event/50930/">リリース記念勉強会</a>の動画上げました</li>
<li><a href="http://ufcpp.net/study/csharp/">C# によるプログラミング入門</a>、リリース版対応しました</li>
</ul>
<h2>動画</h2>
<p><a href="https://csugjp.connpass.com/event/50930/">Visual Studio 2017 リリース記念勉強会</a>、
当日にストリーミング配信とかはやらなかったんですが、
一応動画に撮っていたりはしまして。</p>
<p>許可が取れたものは、YouTube にアップロードしていってたりします。
C#ユーザー会でチャネルを作ったので、こちらで公開中です。</p>
<ul>
<li><a href="https://www.youtube.com/channel/UCWNxu4tBmihABhzJjPiHMVw">Japan C# User Group</a></li>
</ul>
<h2>リリース版対応</h2>
<p><a href="http://ufcpp.net/study/csharp/">C# によるプログラミング入門</a>内から、C# 7.0がらみは「正式版ではこうなります」、「予定」、「仮」的な文面全部なくしたはず。
ついに正式リリースですよ。</p>
<p>ちなみに、RCからRTMの間で、C# 7.0の実装にも微妙に変更もありました。</p>
<p>1つ目。タプルに対する拡張メソッドの呼び出しで、オーバーロード解決時にメンバーごとの型変換を考慮してくれるようになりました。
<a href="http://ufcpp.net/blog/2017/1/pickuproslyn0125/">1月25日のブログ</a>の最後の方にちょっと書いたやつです。
「『今やる』か『今後もうできないか』の2択なので、もう時間も限られているけど頑張って今やってみる」っていう状態になっていた機能が、無事に入りました。</p>
<div>
<script src="https://gist.github.com/ufcpp/168dc0519f4f58ffa6c5b146246d9f77.js"></script>
</div>
<p>2つ目。<code>while</code> の条件式中で宣言した変数のスコープ変更(while内のみになった)。
<a href="http://ufcpp.net/blog/2016/12/pickuproslyn1214/">去年の12月</a>にちょっと書いてたやつ。
これ、直前のRC版でもまだ<code>while</code>の外にスコープ漏れてて、リリース後に確認してみたらちゃんと<code>while</code>内のみに変更掛かっていることを確認。
うちの記事にも反映させておきました。</p>
<div>
<script src="https://gist.github.com/ufcpp/5984fee9bbbc0600c0314baa9a438ba3.js"></script>
</div>
<p>そういや、最近、すっかりC#のバージョン番号の書式が「C# 7.0」(.0が付く)なんですよね。
一時期は、<a href="http://ufcpp.net/blog/2016/6/versionnumber/">C# 6, C# 7</a>だったんですけども。
しれっと、いろいろとやっぱり .0 が付くように変わっていたり。
うちのサイト内の表記、どうしようかな…</p>
 ]]></description>
				<pubDate>Tue, 21 Mar 2017 20:53:51 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 3/18: インターフェイスのデフォルト実装</title>
				<link>http://ufcpp.net/blog/2017/3/pickuproslyn0318/</link>
				<description><![CDATA[ <p>C#でもインターフェイスのデフォルト実装(まんま、Javaのデフォルト メソッドと同じ機能)の実装始めたって。</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/pull/17927">Enable a default implementation of an interface method to be provided as part of its declaration. #17927</a></li>
</ul>
<p>結構びっくり…</p>
<p>驚いてるって言っても、この機能が革新的だとかそういう驚きではなくてですね。
この機能、.NET ランタイムに手を入れないと実現できない機能なので、「今から実装始めれるんだ？！」という驚きになります。</p>
<h2>デフォルト実装</h2>
<p>機能的にはそんなに驚くこともなく。
というか、本当にJavaのデフォルト メソッドそのままなので。
まあ、今からC#にデフォルト実装の機能を入れても、そこまで大きなインパクトはないと思います。</p>
<p>メリットは、</p>
<ul>
<li>インターフェイスに後からメンバーを追加しても、利用側コードを壊さずに済むようになる</li>
<li><code>IEnumerable.GetEnumerator</code>みたいな、1.0時代の互換性のためだけに現存しているものの実装が楽になる</li>
</ul>
<p>というくらい。後者の方は要するに、以下のような話。</p>
<pre class="source" title="デフォルト実装でGetEnumeratorの実装を楽に">
<code><span class="reserved">namespace</span> System.Collections.Generic
{
    <span class="reserved">public</span> <span class="reserved">interface</span> <span class="type">IEnumerable</span>&lt;<span class="reserved">out</span> <span class="type">T</span>&gt; : <span class="type">IEnumerable</span>
    {
        <span class="type">IEnumerator</span>&lt;<span class="type">T</span>&gt; GetEnumeartor();

        <span class="comment">// こんな風に、デフォルト実装を与えておいてもらう</span>
        <span class="type">IEnumerator</span> <span class="type">IEnumerable</span>.GetEnumeartor() =&gt; GetEnumerator();
    }
}

<span class="reserved">namespace</span> ConsoleApp1
{
    <span class="reserved">using</span> System.Collections.Generic;

    <span class="reserved">class</span> <span class="type">MyEnumerable</span> : <span class="type">IEnumerable</span>&lt;<span class="reserved">int</span>&gt;
    {
        <span class="type">IEnumerator</span>&lt;<span class="reserved">int</span>&gt; GetEnumerator()
        {
            <span class="reserved">yield</span> <span class="reserved">return</span> 1;
            <span class="reserved">yield</span> <span class="reserved">return</span> 2;
            <span class="reserved">yield</span> <span class="reserved">return</span> 3;
        }

        <span class="comment">// IEnumerator IEnumerable.GetEnumeartor の方は書かなくてもいい</span>
    }
}
</code></pre>
<p>あったらあったで便利なんですが、ランタイム側の修正が必要となるとなかなか。</p>
<h2>.NET ランタイムに手を入れる</h2>
<p>C# の機能って、C# 3～7までの間は、コンパイラーが頑張って実現しているような機能がほとんどで、
.NET ランタイム的にいうと .NET Framework 2.0上でも動くものばかりでした。</p>
<p>(参考: <a href="http://ufcpp.net/study/csharp/cheatsheet/listfxlangversion/">C#の言語バージョンと.NET Frameworkバージョン</a>
<a href="http://ufcpp.net/study/csharp/sp5_async.html">async/await</a>が<a href="https://msdn.microsoft.com/ja-jp/library/system.threading.tasks.task(v=vs.110).aspx"><code>Task</code>クラス</a>に依存していたり、ライブラリを必要とする機能はちらほらありましたが、
ランタイムに関しては.NET Framework 2.0以降何も変化していません。
)</p>
<p>とはいえ、さすがに、ランタイムに手を入れないとなぁという感じはしてきています。
いくつか、「ランタイムによってコンパイラーの進化が妨げられている」みたいなリストもできていたりします。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/251">Places where runtime bugs interfere with compiler or language evolution #251</a></li>
</ul>
<p>見るからに「バグだから直して」って感じのもありますが、
他にも例えば、以下のようなものが挙がっています。</p>
<ul>
<li>構造体に対して引数なしのコンストラクターを認めたい(<code>Activator.CreateInstance</code>のバグで今はそれができない)</li>
<li>属性にジェネリックなものを認めたい</li>
<li>インターフェイスにデフォルト実装を認めたい</li>
</ul>
<p>需要があるんだからランタイムの修正してくれよって話ではあるんですが、
ここ数年の.NETって、クロスプラットフォーム化とかで忙しくて、新機能を追加する余裕なんて全然なかったんですよね。
そりゃまあ、デフォルト実装を認めるよりも先にXamarin (iOS/Android)とか.NET Core (Linux/Mac)とかの安定化の方が先だろと。</p>
<p>ってことで、個人的な予想としては、この手のランタイム修正が必要な機能の実装は.NET Core 2.0とかよりさらに後だろうとか思ってたんですが。
デフォルト実装も、当初予定では<a href="https://github.com/dotnet/csharplang/milestone/8">C# 8.0 milestone</a>に並べられてたはずですし。
なので、冒頭の「今？！」という驚きにつながるわけです。</p>
<p>今作業が始まったってことは、.NET Core 2.0(一瞬、「今年の春には」とか言う話も出ていましたけど。今年中には出るのかなぁ…出るはずよなぁ…きっと？)とかでひょっとしてランタイムの修正もするのかな？とか期待に胸を膨らませたり。</p>
 ]]></description>
				<pubDate>Sat, 18 Mar 2017 21:00:51 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 2/28: Milestones 7.X</title>
				<link>http://ufcpp.net/blog/2017/2/pickuproslyn0228/</link>
				<description><![CDATA[ <p>なんか、<a href="https://github.com/dotnet/csharplang/milestones">csharplang にマイルストーンが切られてた</a>。</p>
<p>ちなみに、リリース時期を邪推されないように、期日は2070年とかのむちゃくちゃな日付になっています。
7.0が2070年、7.1が2071年、…みたいな。</p>
<h2>7.0</h2>
<ul>
<li><a href="https://github.com/dotnet/csharplang/milestone/4">7.0</a></li>
</ul>
<p>3/7のリリースを考えるととっくに実装終わってるはずのもの。</p>
<p><a href="https://github.com/dotnet/roslyn">Roslynリポジトリ</a>側からの移植と、あと、ドキュメントがまだないのでそれが残タスクっぽいです。(最近、ほんとにドキュメントが後…)</p>
<h2>7.1</h2>
<ul>
<li><a href="https://github.com/dotnet/csharplang/milestone/5">7.1</a></li>
</ul>
<p>C#的には初の「小数点リリース」計画なわけですが、これは、Visual Studio とか .NET ランタイムのリリース スケジュールとは合わせないって意味で使いたさそうな雰囲気。
ライブラリ、ランタイムやIDE支援が要らない機能を主に入れていく感じ。</p>
<p>7.1は、みるからに7.0の積み残し。時間的な都合で入れなかっただけで、いつでも実装可能なやつ。</p>
<p><a href="https://github.com/dotnet/csharplang/issues/37">private protected</a>なんて、7.0どころか6.0の積み残しだった李。これの話とか見事なもんで、「<a href="http://www.buildinsider.net/column/iwanaga-nobuyuki/001">機能的には大したことがなくていつでも実装可能。あとはキーワードを決めるだけ。キーワードが決まらなくて延期</a>」って状態だったのに、この期に及んで「それでも私は別キーワードがいい」ってコメントを付けてる人がいたり。
「もう多数決では決まらないからC#チームがprivate protectedに決めた。このキーワードでやるか、さもなくばまったくやらないからの二択」と説明されてなお、あれやこれやコメントを付けてる人がいたり…</p>
<h2>7.2</h2>
<ul>
<li><a href="https://github.com/dotnet/csharplang/milestone/6">7.2</a></li>
</ul>
<p>なんか、パフォーマンス改善系の世代っぽい。
もしかしたら、この辺りで<a href="http://ufcpp.net/blog/2016/12/tipscorefxlab/">System.Memory</a>とか、<a href="http://www.buildinsider.net/language/csharpunicode/02">Utf8String</a>とかのライブラリを実用段階に持っていきたいのかも。
それと関連しそうなものがちらほら並んでいます。</p>
<h2>7.X</h2>
<ul>
<li><a href="https://github.com/dotnet/csharplang/milestone/7">7.X</a></li>
</ul>
<p>その他、7.0の延長、ライブラリやIDEの機能追加が要らない感じのもの。</p>
<p><a href="https://github.com/dotnet/csharplang/issues/45">フル機能版のパターン マッチング</a>はここに入ったっぽいんですよねぇ。
確かにまあ、<a href="http://ufcpp.net/study/csharp/datatype/typeswitch/">型パターン</a>が入るだけでそこそこ満足度高いですし。
再帰パターンの類は実装大変な割には用途が狭く。</p>
<h2>8.0</h2>
<ul>
<li><a href="https://github.com/dotnet/csharplang/milestone/8">8.0</a></li>
</ul>
<p>メジャーリリースなので、でかい機能。時間も掛かりそうかなぁ…</p>
<p><a href="http://ufcpp.net/study/csharp/misc/misclanguageevolution/#record-type">レコード型</a>とか、
<a href="http://www.buildinsider.net/column/iwanaga-nobuyuki/012">null許容参照型</a>とか、
<a href="http://www.buildinsider.net/column/iwanaga-nobuyuki/010">非同期シーケンス</a>とかはここに。</p>
<h2>X</h2>
<ul>
<li><a href="https://github.com/dotnet/csharplang/milestone/9">X.X</a></li>
<li><a href="https://github.com/dotnet/csharplang/milestone/10">X.0</a></li>
</ul>
<p>ほんとに未定。
「何かいいアイディアがあれば」とか、
「.NET ランタイム自体に機能追加が必要で、そっち次第」とか、そんな感じのもの。
逆にいうと、ふといいアイディアが降りてきて急に実装されたり、
.NETチームとかVisual Studio IDEチームとかのスケジュール次第では早くも遅くもなりそうな。</p>
<p><a href="https://github.com/dotnet/csharplang/issues/107">コード生成拡張</a>(replace/original)とかはほんと、IDE側の対応次第って感じのものなんですよね…
これ、ほんと一刻も早くほしかったりするんですけど。</p>
 ]]></description>
				<pubDate>Tue, 28 Feb 2017 01:35:47 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 2/23: Shapes and Extensions</title>
				<link>http://ufcpp.net/blog/2017/2/pickuproslyn0223/</link>
				<description><![CDATA[ <p>久しぶりに面白そうな話が。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/issues/164">Exploration: Shapes and Extensions #164</a></li>
</ul>
<p>2つほど原案があって、組み合わせて結構よさげな機能案ができたので詳細を詰めていきたいという感じの話。
元になっているのは以下の2つ。</p>
<ul>
<li>
<a href="https://github.com/dotnet/roslyn/issues/11159">Extension everything</a>
<ul>
<li>メソッドだけじゃなくて、プロパティとかインデクサーとかあらゆるものを「拡張」定義したい</li>
<li>静的メソッドも(インスタンスじゃなくて型に対して)「拡張」したい</li>
<li>インターフェイスの後刺しとかもしたい</li>
</ul>
</li>
<li>
<a href="https://github.com/dotnet/csharplang/issues/164">Type Classes</a>
<ul>
<li>Haskellの型クラス的なもの、 .NET ランタイムに手を入れなくてもちょっとした「値型ジェネリック」を使ったトリックで実現できそうという話</li>
<li><a href="https://github.com/MattWindsor91/roslyn/blob/master/concepts/docs/csconcepts.md">MS Researchの人と、インターンで来た人の成果っぽい</a></li>
<li>
型クラスってのはどういうのかというと:
<ul>
<li>静的メソッドやコンストラクターを含めて、その型が持つべきメンバーを規定するもの</li>
<li>「型、インスタンスどちらにも有効なインターフェイス」みたいな感じ</li>
</ul>
</li>
</ul>
</li>
</ul>
<h2>Shapes (型クラス)</h2>
<p>今のところ型クラスの定義を Shapes って呼びたいみたい。
要するに、どういうメンバーを持っているべきかという、型の「形状」(shape)を規定するもの。</p>
<p>例として挙げてるのが、零元と加算演算子を持つ型。
数学で「<a href="http://ufcpp.net/study/math/group/group/">群</a>」(group)って呼んでるやつです。
(正確にはこれだと<a href="http://ufcpp.net/study/math/group/group/#monoid">モノイド</a>なんですけど)</p>
<pre class="source" title="群を表すShape">
<code><span class="reserved">public</span> <span class="reserved">shape</span> <span class="type">SGroup</span>&lt;<span class="type">T</span>&gt;
{
    <span class="reserved">static</span> <span class="type">T</span> Zero { <span class="reserved">get</span>; }
    <span class="reserved">static</span> <span class="type">T</span> <span class="reserved">operator</span> +(<span class="type">T</span> t1, <span class="type">T</span> t2);
}
</code></pre>
<p>概ねインターフェイスと似たような書き方なわけですが、以下の点が異なります。</p>
<ul>
<li><code>interface</code>キーワードの代わりに<code>shape</code>キーワードを書く</li>
<li>静的メンバーを持てる</li>
</ul>
<p>静的メンバーが持てるので、ジェネリックの残念な点の1つとしてよく上がる「演算子を使えない」問題が解消します。</p>
<p>わざわざShapes(インターフェイス的なもの)をかますのは、いろんな型、いろんな演算子がこの条件を満たすからです。
例えば:</p>
<ol>
<li>整数の加法群: 整数に対して、零元 = 0、演算子 = +</li>
<li>整数の乗法群: 整数に対して、零元 = 1、演算子 = ×</li>
<li>文字列に対して、零元 = 空文字、演算子 = 文字列結合</li>
</ol>
<p>これらに対して、共通ロジックで「総和」を取ったりできるわけです。</p>
<pre class="source" title="Shapeに対する共通ロジック">
<code><span class="reserved">public</span> <span class="reserved">static</span> <span class="type">T</span> AddAll&lt;<span class="type">T</span>&gt;(<span class="type">T</span>[] ts) <span class="reserved">where</span> <span class="type">T</span> : <span class="type">SGroup</span>&lt;<span class="type">T</span>&gt; <span class="comment">// shape 制約</span>
{
    <span class="reserved">var</span> result = <span class="type">T</span>.Zero;                   <span class="comment">// 静的プロパティから零元を取得</span>
    <span class="reserved">foreach</span> (<span class="reserved">var</span> t <span class="reserved">in</span> ts) { result += t; } <span class="comment">// + 演算子の呼び出し</span>
    <span class="reserved">return</span> result;
}
</code></pre>
<p>例えば、</p>
<ul>
<li>1, 2, 3, 4 に対して上記1の意味で総和(普通に足し算) → 10</li>
<li>1, 2, 3, 4 に対して上記2の意味で総和(全部を掛け算) → 24</li>
<li>&quot;ab&quot;, &quot;c&quot;, &quot;de&quot; に対して上記3の意味で総和(Concat) → &quot;abcde&quot;</li>
</ul>
<p>とかになります。</p>
<h2>Extensions</h2>
<p>で、拡張(extensions)。
拡張メソッドだけじゃなくて、プロパティだろうがインデクサーだろうが、静的メソッドだろうがコンストラクターだろうが、なんでも拡張できるようにしたいという話が元々ありまして。
この「拡張」で、Shapesを実装できるようにするみたいです。</p>
<p>例えば上記1の意味のShape (整数の加法群)であれば、以下のように書けます(構文は「仮」なもの。特に <code>of</code> の辺りが今後どうなるか怪しい)。</p>
<pre class="source" title="「群」Shapeに対する「整数の加法群」実装">
<code><span class="reserved">public</span> <span class="reserved">extension</span> <span class="type">IntGroup</span> <span class="reserved">of</span> <span class="reserved">int</span> : <span class="type">SGroup</span>&lt;<span class="reserved">int</span>&gt;
{
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">int</span> Zero =&gt; 0;
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">int</span> <span class="reserved">operator</span> +(<span class="reserved">int</span> t1, <span class="reserved">int</span> t2) =&gt; t1 + t2;
}
</code></pre>
<p>2のやつ(乗法群)であれば以下の通り。</p>
<pre class="source" title="「群」Shapeに対する「整数の乗法群」実装">
<code><span class="reserved">public</span> <span class="reserved">extension</span> <span class="type">IntMulGroup</span> <span class="reserved">of</span> <span class="reserved">int</span> : <span class="type">SGroup</span>&lt;<span class="reserved">int</span>&gt;
{
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">int</span> Zero =&gt; 1;
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">int</span> <span class="reserved">operator</span> +(<span class="reserved">int</span> t1, <span class="reserved">int</span> t2) =&gt; t1 * t2;
}
</code></pre>
<p>呼び出し側は以下のように書けます。</p>
<pre class="source" title="共通ロジック呼び出し">
<code><span class="comment">// 全部を足し算。sum == 10</span>
<span class="reserved">var</span> sum = AddAll&lt;<span class="type">IntGroup</span>&gt;(<span class="reserved">new</span>[] { 1, 2, 3, 4 });

<span class="comment">// 全部を掛け算。prod == 24</span>
<span class="reserved">var</span> prod = AddAll&lt;<span class="type">IntMulGroup</span>&gt;(<span class="reserved">new</span>[] { 1, 2, 3, 4 });
</code></pre>
<h2>展開</h2>
<p>構文的には割かしよさそうです。
で、気になるのはどう実現するか。
メタデータ的に(リフレクションや旧バージョンのコンパイラーから見たの時の挙動が)どうなるのかとか、
動的リンクできるのか(コンパイル時にベタ展開しちゃうと、変更時に利用側の再コンパイルが必要)とか、
パフォーマンス的に大丈夫かとか。</p>
<p>とりあえず、予定されている展開結果をお見せしましょう。
これまで挙げてきたコードは、以下のように展開されます。
(比較のために元のコードを並べつつ)</p>
<h3>Shapes</h3>
<p>元:</p>
<pre class="source" title="群を表すShape">
<code><span class="reserved">public</span> <span class="reserved">shape</span> <span class="type">SGroup</span>&lt;<span class="type">T</span>&gt;
{
    <span class="reserved">static</span> <span class="type">T</span> Zero { <span class="reserved">get</span>; }
    <span class="reserved">static</span> <span class="type">T</span> <span class="reserved">operator</span> +(<span class="type">T</span> t1, <span class="type">T</span> t2);
}
</code></pre>
<p>展開結果:</p>
<pre class="source" title="SGroup shape の展開結果">
<code><span class="comment">// shape はべたにインターフェイス化</span>
<span class="comment">// 静的なものもインスタンス メンバーに変更</span>
<span class="reserved">public</span> <span class="reserved">interface</span> <span class="type">SGroup</span>&lt;<span class="type">T</span>&gt;
{
    <span class="type">T</span> Zero { <span class="reserved">get</span>; }
    <span class="type">T</span> op_Addition(<span class="type">T</span> t1, <span class="type">T</span> t2); <span class="comment">// 演算子は所定の命名ルールでメソッド化</span>
}
</code></pre>
<h3>Extensions</h3>
<p>元:</p>
<pre class="source" title="「群」Shapeに対する「整数の加法群」・「整数の乗法群」実装">
<code><span class="reserved">public</span> <span class="reserved">extension</span> <span class="type">IntGroup</span> <span class="reserved">of</span> <span class="reserved">int</span> : <span class="type">SGroup</span>&lt;<span class="reserved">int</span>&gt;
{
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">int</span> Zero =&gt; 0;
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">int</span> <span class="reserved">operator</span> +(<span class="reserved">int</span> t1, <span class="reserved">int</span> t2) =&gt; t1 + t2;
}

<span class="reserved">public</span> <span class="reserved">extension</span> <span class="type">IntMulGroup</span> <span class="reserved">of</span> <span class="reserved">int</span> : <span class="type">SGroup</span>&lt;<span class="reserved">int</span>&gt;
{
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">int</span> Zero =&gt; 1;
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">int</span> <span class="reserved">operator</span> +(<span class="reserved">int</span> t1, <span class="reserved">int</span> t2) =&gt; t1 * t2;
}
</code></pre>
<p>展開結果:</p>
<pre class="source" title="IntGroup/IntMulGroup extensionsの展開結果">
<code><span class="comment">// extension による shape 実装は、構造体でのインターフェイス実装に</span>
<span class="reserved">public</span> <span class="reserved">struct</span> <span class="type">IntGroup</span> : <span class="type">SGroup</span>&lt;<span class="reserved">int</span>&gt;
{
    <span class="reserved">public</span> <span class="reserved">int</span> Zero =&gt; 0;
    <span class="reserved">public</span> <span class="reserved">int</span> op_Addition(<span class="reserved">int</span> t1, <span class="reserved">int</span> t2) =&gt; t1 + t2;
}

<span class="reserved">public</span> <span class="reserved">struct</span> <span class="type">IntMulGroup</span> : <span class="type">SGroup</span>&lt;<span class="reserved">int</span>&gt;
{
    <span class="reserved">public</span> <span class="reserved">int</span> Zero =&gt; 1;
    <span class="reserved">public</span> <span class="reserved">int</span> op_Addition(<span class="reserved">int</span> t1, <span class="reserved">int</span> t2) =&gt; t1 * t2;
}
</code></pre>
<h3>Shapes に対する共通ロジック</h3>
<p>元:</p>
<pre class="source" title="Shapeに対する共通ロジック">
<code><span class="reserved">public</span> <span class="reserved">static</span> <span class="type">T</span> AddAll&lt;<span class="type">T</span>&gt;(<span class="type">T</span>[] ts) <span class="reserved">where</span> <span class="type">T</span> : <span class="type">SGroup</span>&lt;<span class="type">T</span>&gt; <span class="comment">// shape 制約</span>
{
    <span class="reserved">var</span> result = <span class="type">T</span>.Zero;                   <span class="comment">// 静的プロパティから零元を取得</span>
    <span class="reserved">foreach</span> (<span class="reserved">var</span> t <span class="reserved">in</span> ts) { result += t; } <span class="comment">// + 演算子の呼び出し</span>
    <span class="reserved">return</span> result;
}
</code></pre>
<p>展開結果:</p>
<pre class="source" title="AddAll メソッドの展開結果">
<code><span class="comment">// 型引数を1個追加。そこに Shape を渡す想定</span>
<span class="reserved">public</span> <span class="reserved">static</span> <span class="type">T</span> AddAll&lt;<span class="type">T</span>, <span class="type">TShape</span>&gt;(<span class="type">T</span>[] ts)
    <span class="reserved">where</span> <span class="type">TShape</span> : <span class="type">SGroup</span>&lt;<span class="type">T</span>&gt; <span class="comment">// shape </span>
{
    <span class="reserved">var</span> tShape = <span class="reserved">default</span>(<span class="type">TShape</span>); <span class="comment">// 静的メソッド呼び出しだったものは、構造体の既定値に対するメソッド呼び出しに展開</span>
    <span class="reserved">var</span> result = tShape.Zero;
    <span class="reserved">foreach</span> (<span class="reserved">var</span> t <span class="reserved">in</span> ts) { result = tShape.op_Addition(result, t); }
    <span class="reserved">return</span> result;
}
</code></pre>
<h3>メソッド呼び出し</h3>
<p>元:</p>
<pre class="source" title="Shape呼び出し">
<code><span class="comment">// 全部を足し算。sum == 10</span>
<span class="reserved">var</span> sum = AddAll&lt;<span class="type">IntGroup</span>&gt;(<span class="reserved">new</span>[] { 1, 2, 3, 4 });

<span class="comment">// 全部を掛け算。prod == 24</span>
<span class="reserved">var</span> prod = AddAll&lt;<span class="type">IntMulGroup</span>&gt;(<span class="reserved">new</span>[] { 1, 2, 3, 4 });
</code></pre>
<p>展開結果:</p>
<pre class="source" title="AddAll メソッド呼び出しの展開結果">
<code><span class="comment">// 型引数を1個追加</span>
<span class="reserved">var</span> sum = AddAll&lt;<span class="reserved">int</span>, <span class="type">IntGroup</span>&gt;(<span class="reserved">new</span>[] { 1, 2, 3, 4 });
<span class="reserved">var</span> prod = AddAll&lt;<span class="reserved">int</span>, <span class="type">IntMulGroup</span>&gt;(<span class="reserved">new</span>[] { 1, 2, 3, 4 });
</code></pre>
<h2>展開結果から言えること</h2>
<h3>メタデータ</h3>
<p>展開してみればそこまで変なコードではないので、リフレクションや、古いコンパイラーから使う場合でもそんなにおかしなコードにはならないと思います。</p>
<h3>動的リンク</h3>
<p>結局はただのインターフェイスなので、ちゃんと動的リンクできます。
要するに、</p>
<ul>
<li>ライブラリの実装側を修正する</li>
<li>利用側は再コンパイル不要</li>
<li>JIT 実行するとちゃんと修正結果が反映される</li>
</ul>
<p>という状態になります。</p>
<h3>パフォーマンス</h3>
<p>構造体＋ジェネリックに展開されるのがポイントでして。
ちょうど、ついこないだ以下のような文章を書いたんですが、これと同じ状態になっています。</p>
<ul>
<li><a href="http://ufcpp.net/study/csharp/sp2_generics.html?p=3#pseudo-static">静的メソッド代わり</a></li>
</ul>
<p>値型に対するジェネリックは、JIT コンパイル時に静的に展開されます。
元々インターフェイスの仮想メソッド呼び出しだったものも、通常のメソッド呼び出しに展開されます。
仮想呼び出しが消えることで、インライン展開すらされます。</p>
<p>もしインライン展開までされれば、きわめて高パフォーマンスに実行できます。
ここまで例示してきたような<code>SGroup</code>程度、
すなわち、0/1を返したり<code>+</code>/<code>*</code>を計算するだけのものなら、
リリース(最適化オプション付き)ビルドすれば確実にインライン展開されます。</p>
<p>結果的に、以下のようなコードとほとんど変わらない状態に最適化されます。</p>
<pre class="source" title="値型ジェネリックの展開 ＋ インライン展開の結果">
<code><span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">int</span> AddAll_IntGroup(<span class="reserved">int</span>[] ts)
{
    <span class="reserved">var</span> result = 0;
    <span class="reserved">foreach</span> (<span class="reserved">var</span> t <span class="reserved">in</span> ts) { result += t; }
    <span class="reserved">return</span> result;
}

<span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">int</span> AddAll_IntMulGroup(<span class="reserved">int</span>[] ts)
{
    <span class="reserved">var</span> result = 1;
    <span class="reserved">foreach</span> (<span class="reserved">var</span> t <span class="reserved">in</span> ts) { result *= t; }
    <span class="reserved">return</span> result;
}
</code></pre>
<h2>まとめ</h2>
<p>なんか急にきれいにまとまった感じ。</p>
<p>これまで「なんでも拡張」(Extension everything)をどう実現しようか迷っていたところに、
低コストで型クラス(Type Classes)を実現できそうという案が降ってきたことで、
合わせるといい感じに。</p>
<p>実装的には値型ジェネリックを使ったちょっとしたトリックになっています。
値型ジェネリックに対して .NET の JIT が結構いい最適化を掛けてくれることによって、</p>
<ul>
<li>リフレクションや古いコンパイラーから見てもそこまで苦しくなく</li>
<li>動的リンク可能で</li>
<li>きわめて低コスト(静的メソッドとほとんど変わらない高パフォーマンス)</li>
</ul>
<p>が実現できそうです。</p>
<p>このブログでは触れませんでしたが、<a href="https://github.com/dotnet/csharplang/issues/164">元 issue</a>では、インターフェイスの後刺しとかについても書かれています。</p>
 ]]></description>
				<pubDate>Thu, 23 Feb 2017 01:24:33 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 2/13</title>
				<link>http://ufcpp.net/blog/2017/2/pickuproslyn0213/</link>
				<description><![CDATA[ <p><a href="http://ufcpp.net/blog/2017/2/pickuproslyn0110/">2/10のブログ</a>の補足。</p>
<p><a href="https://github.com/dotnet/csharplang">csharplangリポジトリ</a>内にいくつか提案ドキュメントが上がり始めたというものの中で、2点ほど取り上げて紹介。この2個だけ、ちょっと以前からの進展があったものです。</p>
<h2>読み取り専用参照</h2>
<ul>
<li><a href="https://github.com/dotnet/csharplang/blob/master/proposals/readonly-ref.md">Readonly references</a></li>
</ul>
<p>最近、C#でも構造体を使ったパフォーマンス改善をいろいろやろうとしているわけですが。
<a href="http://ufcpp.net/study/csharp/sp_ref.html?p=2#ref-returns">参照戻り値</a>とかはそのための機能ですし、
<a href="http://ufcpp.net/study/csharp/datatype/tuples/">タプル</a>は内部的にmutable(書き換え可能)な構造体になっています(パフォーマンス的にはそれが一番いい)。</p>
<p>ただ、大き目の構造体の受け渡しは、値渡し(コピーが発生)の負担が大きいです。
なので、例えば以下のように、参照引数を使ったりします。</p>
<pre class="source" title="大き目の構造体を参照渡し">
<code><span class="reserved">static</span> <span class="reserved">void</span> AddTo(<span class="reserved">ref</span> <span class="type">Matrix4x4</span> x, <span class="reserved">ref</span> <span class="type">Matrix4x4</span> y)
{
    x.M11 += x.M12;
    <span class="comment">// 後略</span>
    <span class="comment">// 4×4行列なので15行ほど同じようなの</span>
}
</code></pre>
<p>ここで問題は、このコード、<code>x</code>と<code>y</code>のどちらが書き換わるのかわからないところ。
<code>x</code>の方は書き換える前提で参照渡しをしていますが、
<code>y</code>の方は書き換えるつもりがない。
でも、値渡しするとコピー負荷が高いんで、やむなく参照渡しにしている。
という状態。</p>
<p>こういうのは、意図を明示できるべきだし、もし意図に反して<code>y</code>を書き換えようとしたらコンパイル エラーになるべきです。
そこで、「読み取り専用参照」が提案されていました。
C++ならよくやるやつです。<code>const T&amp;</code>。
C#に対するこれまでの提案では<code>readonly ref</code>なんかが上がっていたんですが、
今回<code>in</code>キーワードを使うのはどうだろうという話になりました。</p>
<pre class="source" title="in参照渡し">
<code><span class="reserved">static</span> <span class="reserved">void</span> AddTo(<span class="reserved">ref</span> <span class="type">Matrix4x4</span> x, <span class="reserved"><em>in</em></span> <span class="type">Matrix4x4</span> y)
{
    x.M11 += x.M12;
    <span class="comment">// 後略</span>
}
</code></pre>
<p>前々から<code>readonly ref</code>だと長すぎて嫌だしという話はでていまして。
要するに、</p>
<ul>
<li>参照渡しの特殊形として<a href="http://ufcpp.net/study/csharp/sp_ref.html#out"><code>out</code></a>引数があるんなら、その逆の<code>in</code>引数があってもいいじゃない</li>
<li><code>in</code>なら、<code>foreach</code>やジェネリックの<a href="http://ufcpp.net/study/csharp/sp4_variance.html#in_out">反変性</a>で使ってて今もキーワードだし(破壊的変更になりにくい)</li>
</ul>
<p>ということで、<code>in</code>参照引数にしてはどうかということになっているみたいです。</p>
<h2><code>IntPtr</code>に対する演算子</h2>
<ul>
<li><a href="https://github.com/dotnet/csharplang/blob/master/proposals/intptr-operators.md">Operators should be exposed for System.IntPtr and System.UIntPtr</a></li>
</ul>
<p>去年の年末に「<a href="http://ufcpp.net/blog/2016/12/tipsprimitives/">小ネタ</a>」で書きましたが、<code>System.IntPtr</code>と<code>System.UIntPtr</code>はプリミティブ型です。
要するに、専用の<a href="http://ufcpp.net/study/il/summary/il_about/">IL</a>を持っていて、高速な計算ができる型です。
というか、<code>IntPtr</code>、<code>UIntPtr</code>は、ILの内部的にはnative int, native unsigned intという名前の型になっています。
CPUのバスサイズ(32ビットCPUであれば32ビット、64ビットCPUであれば64ビット)の、実行環境依存の整数型。</p>
<p>最近だと、C#もいろんな場所で動かすようになってきました。
Xamarinや.NET Coreのおかげでクロスプラットフォームになっています。
その結果、このnative intをC#上でも使う機会が増えています。
(まあ、クロスプラットフォームを意識したnative相互運用をしたりといった限られた用途ですけども。
以前よりは必要性が高まっているのは確かです。)</p>
<p>ところが、C#上では、<code>IntPtr</code>、<code>UIntPtr</code>に対する演算子が一切使えない。
IL的には持っている専用命令を一切活用できない。
<code>#if</code>でプラットフォームごとに<code>int</code>もしくは<code>long</code>にしてから計算とかが必要でした。
ということで、<code>IntPtr</code>、<code>UIntPtr</code>に対して、一通りの演算子を使えるようにしたという話が出ているようです。</p>
 ]]></description>
				<pubDate>Mon, 13 Feb 2017 20:34:18 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップ Roslyn 2/10</title>
				<link>http://ufcpp.net/blog/2017/2/pickuproslyn0110/</link>
				<description><![CDATA[ <p>Visual Studio 2017 のリリース日、決まったみたいですね。</p>
<ul>
<li><a href="http://forest.watch.impress.co.jp/docs/news/1043543.html">「Visual Studio 2017」のリリースは3月7日</a></li>
</ul>
<p>リリース記念勉強会を開く(リリースされてなかったら「リリース直前勉強会」にする)つもりで3/11(土)に会場を押さえてあるんですが、割かしいいタイミングだったみたいで。
そろそろ1か月前ですし、告知・募集ページを近々作る予定です。</p>
<p>で、Visual Studioがリリースできる段階に来てるということは、C#チーム的にはもう C# 7 向け作業を終えて、その先の作業に入っているような状態。</p>
<h2>proposals</h2>
<p>先日の、<a href="http://ufcpp.net/blog/2017/2/pickuproslyn0203/">ディスカッションの場がメーリングリストになりそうで炎上</a>って話は、
とりあえず「事前にコミュニティに相談しなかったのは悪かったと思っているので改めて投票の場を作った」って感じで進んでいます。
確か、投票の締め切りが今日。</p>
<p>それはそれとして、<a href="https://github.com/dotnet/csharplang">csharplangリポジトリ</a>内に、すでに取り組むことが決まっている範囲で、
提案ドキュメントがアップロードされ始めました。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang/blob/master/proposals/readonly-ref.md">Readonly references</a></li>
<li><a href="https://github.com/dotnet/csharplang/blob/master/proposals/intptr-operators.md">Operators should be exposed for System.IntPtr and System.UIntPtr</a></li>
<li><a href="https://github.com/dotnet/csharplang/blob/master/proposals/nullable-reference-types.md">Nullable reference types in C#</a></li>
<li><a href="https://github.com/dotnet/csharplang/blob/master/proposals/records.md">records</a></li>
<li><a href="https://github.com/dotnet/csharplang/blob/master/proposals/private-protected.md">private protected</a></li>
<li><a href="https://github.com/dotnet/csharplang/blob/master/proposals/null-coalecing-assignment.md">null coalescing assignment</a></li>
<li><a href="https://github.com/dotnet/csharplang/blob/master/proposals/null-conditional-await.md">null-conditional await</a></li>
<li><a href="https://github.com/dotnet/csharplang/blob/master/proposals/improved-common-type.md">improved common type</a></li>
<li><a href="https://github.com/dotnet/csharplang/blob/master/proposals/expression-variables-in-initializers.md">expression variables in initializers</a></li>
<li><a href="https://github.com/dotnet/csharplang/blob/master/proposals/patterns.md">pattern matching</a></li>
<li><a href="https://github.com/dotnet/csharplang/blob/master/proposals/auto-prop-field-attrs.md">Auto-Implemented Property Field-Targeted Attributes</a></li>
<li><a href="https://github.com/dotnet/csharplang/blob/master/proposals/covariant-returns.md">covariant return types</a></li>
<li><a href="https://github.com/dotnet/csharplang/blob/master/proposals/default-interface-methods.md">default interface methods</a></li>
</ul>
<p>とりあえず<a href="https://github.com/dotnet/roslyn">Roslyn</a>側から持ってきただけという感じで新しい話は特にないんですが。
早々にここに並んだってことで、今ここに並んでいるものは割と実現性の高いものなんじゃないかと思います。</p>
<h2>deterministic ビルドオプション</h2>
<p>そういえば、こんな話が。</p>
<blockquote>
<p><a href="https://twitter.com/jaredpar/status/829838775308005376">My personal favorite feature of the new dotnet SDK / MSBuild format: deterministic builds on by default.</a></p>
</blockquote>
<p>(C# チームの中の人の発言)</p>
<p>これの詳細:</p>
<ul>
<li><a href="http://blog.paranoidcoding.com/2016/04/05/deterministic-builds-in-roslyn.html">Deterministic builds in Roslyn</a></li>
</ul>
<p>去年の春くらいから、C# コンパイラーには <code>/deterministic</code> っていうビルドオプションが実装されています。
これは要するに、同じ入力を与えたら必ず同じ出力になるというもの。決定論的ビルド。
(これまでだと、そこら中にタイムスタンプが入ったり、partial class内のメンバーの順序決定に仕様がなかったりで、
同じ内容のコードをビルドしても毎度exeやdllのバイナリに変化が出ていました。)
決定論的になったことで、ビルド結果のキャッシュが聞きやすくなって、テスト実行とかが大幅に高速になったとか。</p>
<p>で、最近の dotnet SDK を使ってビルドすると、デフォルト動作が <code>/deterministic</code> モードになるみたいです。
ちょっと触ってみている感じだと、たぶん、Visual Studio 2017だと、 .NET Standard 向けライブラリ、もしくは、 .NET Core 向けアプリでだけこのモードになるんじゃないかと思われます。</p>
<p>どおりで…
Visual Studio 2017 RCに先月のアップデートをかけて以来、<a href="http://ilspy.net/">ILSpy</a>で.NET Core/.NET Standardなアセンブリの中身が見れなくなってると思ったら…</p>
<p><img src="/media/1126/ilspy-deterministic.png" alt="ILSpy上で、.NET Core/.NET Standardなアセンブリを開いたとき" /></p>
<p>ILSpyが<code>/deterministic</code>でビルドされたpdbファイルに対応していないみたいです。
ちなみに、読めないのはpdbファイルだけ。
pbdファイルを消してからexe/dllを開きなおせば読めました。</p>
 ]]></description>
				<pubDate>Fri, 10 Feb 2017 21:40:49 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 2/3: csharplang リポジトリ</title>
				<link>http://ufcpp.net/blog/2017/2/pickuproslyn0203/</link>
				<description><![CDATA[ <p>ようやく、言語設計に関するリポジトリを、<a href="https://github.com/dotnet/roslyn">Roslyn</a>から分離する流れに。</p>
<ul>
<li><a href="https://github.com/dotnet/csharplang">C# Language Design</a></li>
<li><a href="https://github.com/dotnet/vblang">Visual Basic .NET Language Design</a></li>
</ul>
<p>ここまではOK。</p>
<p>Roslynリポジトリはコンパイラー実装に関するリポジトリなわけで、issueはバグ報告とかで埋まります。
今現在、3000件以上のissueがあって、そのうちかなりの割合がバグ報告なので、まあ、そりゃそんな場所で言語設計に関する話はできないですよね、というのは仕方がない話。
ユーザーからもリポジトリを分けてくれっていう要望は出ていますし、何よりC#チームがかなりGitHub issueの物量に参っているようです。
ということで、新たにcsharplangリポジトリが出来てみんな幸せに…？！</p>
<h2>メーリングリスト…</h2>
<p>問題はここから。</p>
<p>曰く、</p>
<blockquote>
<p>Design Process</p>
<p>C# is designed by the C# Language Design Team (LDT).</p>
<ol>
<li>To submit, support, and discuss ideas please subscribe to the language design <em>mailing list</em>.</li>
</ol>
</blockquote>
<p>えっ、メーリングリスト！？</p>
<p>ということで、もちろん炎上中。</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/issues/16905">Language Design Process Moving (again) #16905</a></li>
</ul>
<p>反応はおおむね、</p>
<ul>
<li>リポジトリを分けるのには賛成</li>
<li>メーリングリストはやめてくれ</li>
<li>GitHub issueがつらい気持ちもわからなくはないけど、メーリングリスト、てめぇはダメだ</li>
</ul>
<p>な感じです。</p>
<p>あまりの炎上っぷりにさすがにC#チームの中の人も再三の説明は繰り返していて、</p>
<ul>
<li>まず最初に、分離先にメーリングリストを使うという判断に関して、チーム内だけで決めたことは謝りたい</li>
<li>
C#チームの運用上GitHub issueはつらいものがある
<ul>
<li>「何百もコメントが付くし、後から編集できるから後から事実を追うのもつらいし」などなど</li>
</ul>
</li>
<li>もちろんその代案がメーリングリストというのは、チーム内でも揉めた</li>
<li>けど、どの案にも善し悪しあって、とりあえず当面、メーリングリストでの運用を容赦してはもらえないだろうか</li>
</ul>
<p>という感じのようです。</p>
<h2>私的な意見として</h2>
<p>まあ、僕個人の意見としては、やっぱり「いろいろと気持ちはわかる。でも、メーリングリスト、てめぇはダメだ」ですねぇ…</p>
<p>もう、メールって言うメディアがダメ。
Windows付属のメールアプリとか、もうとてもじゃないけど使うのつらいじゃないですか。
メール ベースで何かやられたら、もうそんな場所に参加するだけで苦痛。</p>
<p>これはもう、「別のもっと良いアプリに移行すべき」とかそういうレベルの話ではなくて。
もう付属アプリが良くなる当てがない(そこに投資してもMicrosoftもユーザーも大して幸せにならない)という現実があるわけで。
Eメール自体に将来性がない。</p>
<p>そして、そういう将来性のないメディアでディスカッションしているプログラミング言語を使いたいかという問題になるんですが、
僕としては嫌。
使いたくない。</p>
<p><a href="http://ufcpp.net/blog/2016/8/rickuproslyn0827/">去年の夏ごろにこのブログでも取り上げました</a>けど、その頃、
Mads (C#言語設計のPM)が<a href="https://blogs.msdn.microsoft.com/dotnet/2016/08/24/whats-new-in-csharp-7-0/">「What’s New in C# 7.0」っていうブログ記事</a>のコメント欄で、</p>
<blockquote>
<p>C# needs to be among the greatest programming languages today, or it won’t be among them tomorrow.</p>
<p>C#は今この時「最高のプログラミング言語」の1つでなければならない。 さもなくば、明日にはそうではなくなってしまう。</p>
</blockquote>
<p>って言ってるわけですよ。
それが、もう、メールなんてメディア使ってる時点でだいぶ「今この時最高」からはずれる気分。</p>
<h2>そして、それを伝えたいけど…</h2>
<p>今のGitHub issue運用がきついって言うのはかなりわかるし、かといってその代案としても決め手に欠けているってのもわかるので、あんまり非難はしたくないんですけども。
なので、今の苦労をねぎらいつつも、「メールだけは勘弁してくれ、C#っていう言語のブランディングに関わる」って話をしたいんですが…</p>
<p>これを、まあ、つたない英語力で英訳すると、</p>
<blockquote>
<p>Mailing lists are f***'in</p>
</blockquote>
<p>の1行に縮まりかねないわけでして…
バグ報告とかの類と比べて難易度高い…</p>
<h3>おまけ</h3>
<p>そんな感じのことをぼやいてたら、英ペの勇さんがRTしてたので、きっと翻訳してくれるんだと思います。</p>
<p><a href="https://twitter.com/ufcpp/status/827337737812340736"><img src="/media/1125/eipe.png" alt="英ペの勇さん" /></a></p>
 ]]></description>
				<pubDate>Fri, 03 Feb 2017 20:58:30 +0900</pubDate>
			</item>
			<item>
				<title>コンパイラーの資源枯渇系エラーとの付き合い方</title>
				<link>http://ufcpp.net/blog/2017/2/compileroutofmemory/</link>
				<description><![CDATA[ <p><a href="https://twitter.com/tanaka_733/status/826405563638575105">ちょっとしたきっかけ</a>があって、C# 7のタプル、何要素まで書けるのかというのにチャレンジすることになりまして。
結果だけ書くと、<a href="https://gist.github.com/ufcpp/066e7e558cb2ca184bba1bc7d0b5dd63">数万要素のタプル</a>を書くとVisual Studioがクラッシュしました。</p>
<p>これは、別にタプルに限った話ではなくて、巨大なソースコードを食わせてコンパイラーを限界まで酷使したら落ちるのは当然なことでして。
起こしているエラーはスタック枯渇に類するもの(Insufficient Stack)のようです。
コンピューターの資源は有限なので、OutOfMemoryやStaskOverflowなどの資源枯渇系のエラーはどうやっても起こりえます。
数万引数のメソッドを書いたり、数万項の足し算をしたり、数万<code>case</code>の<code>switch</code>を書いたりしても、同様に落とせると思います。</p>
<p>なので、本当に気にするべきなのは以下のような点かなぁと思われます。</p>
<ul>
<li>仕様上の上限: 要素数などに仕様上の上限を設けるべきかどうか</li>
<li>資源枯渇への対処: 資源枯渇を事前に察して適切にエラー メッセージを出すすべきか、コンパイラー自体をクラッシュさせるべきか</li>
<li>クラッシュ時の対処: コンパイラー自体がクラッシュした際に、IDE側は同エラー処理すべきか</li>
</ul>
<p>まあ、割かし一般的な「異常系に対する対処」に関する話です。</p>
<h2>仕様上の上限</h2>
<h3>仕様で決まっている例</h3>
<p>この手の数の上限、仕様として定めているものもあります。例を挙げると以下のようなものがあります。</p>
<ul>
<li>
C++ では、constexprという機能で、再帰呼び出しに上限があります
<ul>
<li>標準仕様上は「512回以上であることを推奨」という感じで推奨設定が決まっています</li>
<li>実際の上限はコンパイラー依存、かつ、コンパイル オプションで変更できます</li>
</ul>
</li>
<li>
Java では、メソッドの引数の上限が256個までと決まっています
<ul>
<li>バイトコード上の制約なので、どうやってもこの数を超えることはできません</li>
</ul>
</li>
</ul>
<h3>仕様を決めることの善し悪し</h3>
<p>仕様的に上限を決めることには善し悪しあります。</p>
<p>仕様化するためには、結構余裕をもって上限を設定せざるを得ません。コンピューターの性能が上がって、ちょっと頑張れるようになったとしても、仕様で決まっている数を超えれなくて不便だったりします。</p>
<p>その一方で、コンパイラーの限界ぎりぎりまで頑張る場合、あるマシンではコンパイルできたのに、他のマシンではできないということがあり得ます。
今回のタプルに関しても、実際、手元のマシンだと1万要素くらいはコンパイルできましたが、<a href="https://tryroslyn.azurewebsites.net/">TryRoslyn</a>などのオンライン サービスを使うと1000ちょっとでもうコンパイル エラーを起こす用です(要するに、使っているVMインスタンスがしょぼい)。</p>
<p>個人的に、1000っていうラインは結構微妙なところです。
手書きで1000個のタプル要素や引数を書くことはまずないでしょう。
でも、「コード生成とかしててうっかり」だと、数百～1000は「ありえる」範疇。</p>
<p>で、開発機ではコンパイルできる。なのに、CIとかを掛けていて、毎朝ナイトリー ビルドには失敗している、みたいなことがあり得るわけです。</p>
<p>マシン環境に左右されない意味では、明確に上限が決まっている(少なくともC++のconstexprみたいに「推奨」が決まっている)方がありがたいのはありがたいです。</p>
<h3>仕様を決められるか</h3>
<p>とはいえ、引数の数や、再帰の段数みたいに具体的な数値を指定しやすいものばかりではありません。</p>
<p>タプルの場合、「要素数」で区切ればいいじゃないかと思うかもしれませんが、実際にエラーの原因になっているのはスタックの深さであって、要素数は直接の原因ではありません。
例えばの話、数千項の足し算の中に、数千要素のタプルと、数千引数のメソッド呼び出しが混在していたりすると、項数/要素数/引数の数の合計によって限界が決まるだろうことは大まかに想像がつくかと思います。
なので、単純にタプル要素数だけに制限を書けるのも変な話でしょう。</p>
<p>もっと難しい例でいうと、型推論をかなり頑張ってる言語では、「型推論に時間が掛かりすぎているのであきらめてエラーにします」みたいなエラーを出すものもあったりします。
時間で言われても、どういう場合なら推論できて、どういう場合ならできないのかがまるで分らず…</p>
<h2>資源枯渇時の対処</h2>
<p>まあ、割かし仕様としては決めかねるものなので、コンパイラーの限界まで頑張ることにしましょう。
そうなると、資源枯渇した瞬間がコンパイルの限界になります。</p>
<p>ところが、OutOfMemoryにしろStackOverflowにしろ、資源枯渇からの復帰はかなり難しいです。
そりゃまあ、復帰にもメモリを使ったりするわけで、OutOfMemory下でできることとか限られています。</p>
<p>なので、コンパイラーをクラッシュさせないためには、かなり防衛的に、余裕を持った上限設定が必要だったりします。
「再帰呼び出しが1000段を超えたのでエラーにしよう」的な。
結果的に、仕様的に上限を決める場合同様、過剰な制限が掛かって利便性に難ありです。</p>
<p>そこまでしても、どうせ返せるコンパイル エラーは「資源不足なのでこれ以上のコンパイル作業はできません」程度の、何の解決にもならないメッセージのみ。
だったら、OutOfMemoryやStackOverflowをそのまま未処理例外にして、コンパイラー自体がクラッシュした方が費用対効果は高いのではないかということになります。</p>
<p>ただ、その場合、コンパイラーを呼び出している側でクラッシュに対するちゃんとした対処が必要になります。</p>
<h2>クラッシュ時の対処</h2>
<p>で、まあ、今回Visual Studioがクラッシュしているのがちょうどそんな感じの状況なわけです。
無理なソースコードを食わせたからコンパイラーがクラッシュした。
Visual Studio側がコンパイラーのクラッシュに正しく対応していないみたいで、Visual Studioごとクラッシュする。</p>
<p>これ、Visual Studio Codeだと大丈夫みたいです。
Codeの場合は、急にインテリセンスが働かなくなるだけ。
エディターとしてはフリーズすることなく稼働し続ける。
Codeでは、<a href="http://qiita.com/atsushieno/items/ce31df9bd88e98eec5c4">Language Server Protocol</a>ってものを介して、エディターの外のプロセスと通信してインテリセンスを動かしているので、言語サーバー側がクラッシュしても、エディターは無事です。</p>
<p>利用者からすると、エディターごと落ちるとかほんとつらいんで、今のVisual Studioの挙動は結構いやなんですけども。
Visual Studioの、C#コンパイラーの未処理例外に対する耐性の低さは結構きついものがあります。
今でこそ、Visual Studio 2017もRC3 (リリース直前)まで来たのでクラッシュも減っていますけど、
もっと開発初期なら簡単にコンパイラーがクラッシュしますし。
いまだに、例えば「<code>null is</code>」って打つだけでコンパイラーをクラッシュさせれるバグが残っていたりするんですけども、
それでも、Visual Studioごとクラッシュします。</p>
<h2>まとめ</h2>
<p>数万要素のタプルを書くとVisual Studioが落ちます。</p>
<p>そんなソースコードを食わせたらコンパイラーが落ちるのは割と想定の範囲内なことかと思われます。
この手の問題に対して仕様的に上限を定めるのは、過剰な制限になって利便性を損なったり、
適切な上限の掛け方が見つからなかったり、結構な難しさがあります。</p>
<p>めったに起きない状況に対して過剰なコストをかけてもしょうがないでしょう。
限界に挑戦するようなソースコードを与えられたとき、クラッシュするのが現実解であることは多々あります。</p>
<p>問題は、むしろ、Visual Studio側が、C#コンパイラーのクラッシュに対して脆弱すぎる点かなぁと思います。
同じようなひどいソースコードを与えても、Visual Studio Codeだったらクラッシュしなかったりもします(インテリセンスだけが効かなくなる)。
Visual Studioにも、C#コンパイラーのクラッシュにエディターごと巻き込まれないような対処が必要でしょう。</p>
 ]]></description>
				<pubDate>Thu, 02 Feb 2017 00:07:54 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 1/25: Design Notes 数か月分</title>
				<link>http://ufcpp.net/blog/2017/1/pickuproslyn0125/</link>
				<description><![CDATA[ <p>Mads (C# コンパイラーのPM)が、去年8月辺りからの C# Language Design Notes がまとめて投稿されました。
たぶん、C# 7の作業が一段落したのかな(最近のC#チームは、実装作業が落ち着くまでドキュメントの類が放置されがち)。</p>
<p>ちなみに内容的には、個別のトピック用のissueページが別にあって、そっちで一通り公開済み。
当然、特に目新しい情報はなくて、まとめと履歴的な状態になっています。</p>
<p>かなりの分量一気に来たのであんまりしっかり読む気にもなれないけども、軽く紹介：</p>
<h2>2016/8/24</h2>
<p>-<a href="https://github.com/dotnet/roslyn/issues/16476">C# Language Design Meeting, Aug 24, 2016</a></p>
<ul>
<li>Task-likeに対して、どうやってmethod builderを取るか決めた</li>
<li>
フィールド初期化子やコンストラクター初期化子内でのout varを認めたらこんな問題が出るみたいな検討したみたい
<ul>
<li>※結局、初期化子でのout varの利用自体、今のところは禁止してる</li>
</ul>
</li>
</ul>
<h2>2016/9/6</h2>
<ul>
<li><a href="https://github.com/dotnet/roslyn/issues/16477">C# Design Notes for Sep 6, 2016 #16477</a></li>
</ul>
<p>引数の数が同じ<code>Deconstruct</code>メソッドがあるときに<a href="http://ufcpp.net/study/csharp/datatype/deconstruction/">分解</a>できないの不便だなぁとは思ってたけども。
タプル間の変換を想定してのことらしい。</p>
<h2>2016/10/18</h2>
<ul>
<li><a href="https://github.com/dotnet/roslyn/issues/16482">C# Design Notes for Oct 18, 2016 #16482</a></li>
</ul>
<p>C# 7に入れる機能の最終確認をしていたのはこの次期みたい。</p>
<ul>
<li>
discardsがC# 7に入るかどうかまだ怪しい時期だったものの、分解とかout varとか、今後追加する文法では<code>_</code>を予約しておこうとはしていたみたい
<ul>
<li>※ 結局discardsの実装、C# 7に間に合ってる</li>
</ul>
</li>
<li><code>case (int, int) x:</code>みたいなタプルへの型スイッチは認めていない。将来「再帰パターン」って構文が入る予定で、その構文に近くなっちゃうんでその時まで保留</li>
<li>
ローカル関数では、理想としてはその外でできることは全部ローカル関数内でもできるようにしたかったけど、2点ほど無理なものがあった:
<ul>
<li>コンストラクター内のローカル関数内での readonly field への書き込み</li>
<li>
非同期メソッドとイテレーターになっているローカル変数内で、その外の変数の「確実な初期化」保証ができない
<ul>
<li>https://gist.github.com/ufcpp/ad84a38cd8b5e324245bda1472de4679 ←たぶんこういう話</li>
</ul>
</li>
</ul>
</li>
<li>
<code>_</code>を使った<a href="http://ufcpp.net/study/csharp/start/stnumber/#digit-separator">数字区切り</a>、数字の間でだけ認める
<ul>
<li><code>0x1a_2b</code>はOKだけど、<code>0x_1a2b</code>はダメ。先頭と末尾を認めない</li>
<li>「区切り」なんだから、数字の間だけであるべき</li>
</ul>
</li>
<li>throw式は、<code>??</code>と<code>?:</code>でだけ使えるように制限した。<code>&amp;&amp;</code>とか<code>||</code>の後ろとか<code>()</code>の中はダメ。</li>
<li>
タプルの名前の順序間違い、例えば<code>var (first, last) = (last, first);</code>みたいなの、事故りそうな予感があって警告は出したい
<ul>
<li>※結局は「工数の問題でC# 7の時点ではできない」「後からWarning Wave追加する」ってなってる(11/15のNotes参照)</li>
</ul>
</li>
<li>
タプルに対して<code>new (int x, int y)()</code>は認めないことにしたけども、配列とかnullableはどうか<code>new (int x, int y)[10]</code>と<code>new (int x, int y)?()</code>は認めたい
<ul>
<li>※結局認めたみたい</li>
</ul>
</li>
</ul>
<h2>2016/10/25</h2>
<ul>
<li>
<p><a href="https://github.com/dotnet/roslyn/issues/16640">C# Language Design Notes for Oct 25 and 26, 2016</a></p>
</li>
<li>
<p>C# 6の時に一度は検討して、最終的には入れれなかった「変数宣言式」について</p>
<ul>
<li>宣言式自体は問題あって、提案当時のままというわけにはいかない</li>
<li>宣言式から派生した、分解とout varはC# 7に入った</li>
<li>
分解とout varは、再び統一的に扱った方がよさそう(C# 7では間に合わないけど、将来の予定として)
<ul>
<li>分解代入と分解宣言を混ぜたり: <code>(x, int y) = e</code></li>
<li>out引数のところに分解を書いたり: <code>M(out (x, y))</code></li>
</ul>
</li>
</ul>
</li>
<li>
パターン マッチングでは、いくらか、絶対に成功するパターン(irrefutable(反論の余地がない)パターンって呼んでる)がある
<ul>
<li>今は、絶対に成功していることを前提としたフロー解析(確実な初期化とか、null解析とか)をまだあまりやっていないけど、将来的には役立ちそう</li>
</ul>
</li>
<li>
分解のために使う<code>Deconstruct</code>メソッド、out引数を使ったもの(<code>Deconstruct(out int x, out int y)</code>)じゃなくてタプルを返す(&quot;(int x, int y)Deconstruct()&quot;)のはどうかというのを検討
<ul>
<li>計測してみたけども、どっちが効率的かみたいな差は出なかった</li>
<li>あんまりやる価値はなさそう</li>
</ul>
</li>
<li>
<code>if (int.TryParse(s1, out var i)) { ... i ... }</code> みたいな書き方で、Tryの成功時も失敗時も必ず<code>i</code>が初期化されちゃうがために、<code>if</code>の外でも<code>i</code>が使えてしまうのは問題じゃないか
<ul>
<li><code>if</code>の外に変数が漏れる設計にした以上これを防ぐ手立てはないんだけど</li>
<li>「Tryパターンなメソッドのout varの場合は<code>if</code>の外で使うと警告」みたいなことができるAnalyzerは用意した方がいいかも</li>
</ul>
</li>
<li>
discards に<code>_</code>を使うことにしたけども…
<ul>
<li>分解とかout varとか、これから足す構文については常にdiscards扱いしたい</li>
<li>既存構文の場合、<code>_</code>を2個以上宣言していたらdiscards扱い、1つも読み出ししてないならdiscards扱い、みたいなルールでやる予定</li>
</ul>
</li>
</ul>
<h2>2016/11/15</h2>
<ul>
<li>
<p><a href="https://github.com/dotnet/roslyn/issues/16674">C# Design Notes for Nov 15, 2016 #16674</a></p>
</li>
<li>
<p>要素の名前違いのタプルに関して警告を出すべき状況がある</p>
<ul>
<li>今は実装していないけど、将来的にはWarning Wavesで警告を追加したい</li>
</ul>
</li>
<li>
Wildcardsって呼び名をDiscardsに改めたのはこの辺り
<ul>
<li>MVP Summitで、MVPからこの案が出てた</li>
<li>
<code>*</code>よりも<code>_</code>がいいだろうという感触もここで得た
<ul>
<li>現状、<code>_</code>が有効な識別子だと言っても、それを「値の無視」以外の目的で使っている人は少なそう</li>
</ul>
</li>
</ul>
</li>
</ul>
<h2>2016/11/30</h2>
<ul>
<li>
<p><a href="https://github.com/dotnet/roslyn/issues/16694">C# Language Design Notes for Nov 30, 2016</a></p>
</li>
<li>
<p><code>while</code>の条件式内のout varで宣言された変数は、<code>while</code>の外に漏れないようにした</p>
</li>
<li><code>for</code>の更新式の中で定義した変数は、<code>for</code>の内側にも漏れないようにした</li>
<li>10/25のNotesで検討していた「分解から宣言式への統一化」、自信をもってできそう</li>
<li>
式中で宣言した変数をどこでも使わなかった場合は「未使用変数警告」を出すべきか？
<ul>
<li>そういう変数はたいてい無視するためのダミー変数で、discards機能が入ったら要らなくなるはず</li>
<li>でも、警告にまではせずとも、サジェストとして「discardsへの変更」機能を提供することもできる</li>
<li>結局、後者(警告にはしない)を選択</li>
</ul>
</li>
<li>
C#では、embedded ステートメント(<code>if</code>とかの後ろ)の中で宣言ステートメントを書くとエラーになるけど、同様の文脈で、今後、分解とかout varとかを使って変数宣言できるようになる。これはエラーにすべきか？
<ul>
<li>しない。むしろ既存の制限の方を緩める可能性すらある(と言ってもC# 7ではやらない)</li>
</ul>
</li>
<li>
nullでないことを調べるだけのパターンが欲しいって案が出てた
<ul>
<li>やりたい。C# 7までには時間がないけど、アイディアとしてはいい</li>
</ul>
</li>
</ul>
<h2>2016/12/7と12/14</h2>
<ul>
<li>
<p><a href="https://github.com/dotnet/roslyn/issues/16709">C# Design Notes for Dec 7 and Dec 14, 2016 #16709</a></p>
</li>
<li>
<p>クエリ式中で(out varとかで)宣言された変数は、式中ずっと使えるべきかも</p>
<ul>
<li><code>where int.TryParse(s, out int i)</code> とかで宣言された<code>i</code>は、その後ろのselect句とかでも使えるようにする</li>
<li>そうなると、単純に<code>Where(x =&gt; int.TryParse(x.s, out int i))</code>みたいな展開はできない。透過識別子が追加される</li>
<li><code>let</code>句での分解(<code>let (dx, dy) = (x - x0, y - y0)</code>みたいなの)でも同様に透過識別子が増える</li>
<li>とりあえずC# 7までに実装できる時間はないんで、C# 7時点ではコンパイル エラーにしてある。将来的にはできる余地だけ残してある</li>
</ul>
</li>
<li>
10/25で出てた「絶対に成功するパターン(irrefutableパターン)」は、到達可能かどうか(<code>return</code>や<code>throw</code>、永久ループの後ろに何か書くと警告を出して呉れるやつ)の判定にも使うべきか
<ul>
<li>やってもそこまで価値はなさそうで、既存のセマンティクスを変えるほどのコストは見合わなさそう</li>
</ul>
</li>
<li>11/30で、<code>while</code>の条件式と、<code>for</code>の更新式中で宣言した変数のスコープを縮めるって話は書いたけど、言い忘れてただけで、<code>do-while</code>も同様</li>
</ul>
<h2>2017/1/17</h2>
<ul>
<li>
<p><a href="https://github.com/dotnet/roslyn/issues/16710">C# Design Notes for Jan 17, 2017 #16710</a></p>
</li>
<li>
<p>定数パターン(<code>e is 42</code>みたいなの)の展開結果をちょっと変更</p>
<ul>
<li>これまで<code>object.Equals(e, 42)</code></li>
<li>これから<code>object.Equals(42, e)</code></li>
<li><code>object.Equals</code>の中で、第1引数のインスタンス メソッドの<code>Equals</code>に処理を丸投げしているらしくて、第1引数が定数な(かつ、nullじゃない)保証がある方がちょっとだけパフォーマンスがいいらしい</li>
</ul>
</li>
<li>
タプルに対する拡張メソッドで、型変換が効くように
<ul>
<li>配列に対して<code>IEnumerable&lt;T&gt;</code>の拡張メソッドが呼べるんだから、<code>(T[], U[])</code>に対して<code>(IEnumerable&lt;T&gt;, IEnumerable&lt;U&gt;)</code>の拡張メソッドを呼べるべきだろうという提案があった</li>
<li>通常、明示的な型変換が必要な場合に拡張メソッドは呼ばれない。で、<code>ValueTuple</code>間には暗黙的型変換が働かないので、上記拡張メソッドを呼べない</li>
<li>でも、全要素がそれぞれ暗黙的に変換できる場合にコンパイラーがタプル間の変換をするんだから、拡張メソッド呼び出しの時にもこの変換を認めるべき</li>
<li>これ、「今やる」か「今後もうできないか」の2択なので、もう時間も限られているけど頑張って今やってみる</li>
</ul>
</li>
</ul>
 ]]></description>
				<pubDate>Tue, 24 Jan 2017 21:12:30 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 1/24: null参照</title>
				<link>http://ufcpp.net/blog/2017/1/nullref/</link>
				<description><![CDATA[ <p>今日はピックアップRoslynなのかC#小ネタ集なのか微妙なライン。</p>
<p>なんか、C# 7で導入される<a href="http://ufcpp.net/blog/2016/6/cs7refreturns/">参照戻り値</a>に関して、参照なのにnullを返せるというネタを思いついてしまったり。
ただのネタのつもりだったんですが、案外考えなきゃ行けない事案かもなぁという話。</p>
<h2>経緯</h2>
<p>参照戻り値で、「null参照」を返したいっていう要望が出ていたりします。</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/issues/16670">Please add new syntax keyword &quot;ref?&quot; to represent that &quot;ref return&quot; result might be null #16670</a></li>
</ul>
<p><code>ref? T</code> みたいな専用の記法が欲しいという要望です。
他の人の反応としては、「参照はnullを返すものじゃない。あきらめろ」的な雰囲気。
僕個人の感想としても、「メリットの割に複雑。実装するのは割に合わない」と思います。</p>
<p>なのでそのままスルーしようとしていたところで、ふと、邪悪なアイディアを思いついてしまいます。
「<a href="https://www.nuget.org/packages/System.Runtime.CompilerServices.Unsafe/"><code>Unsafe</code>クラス</a>使ってnull返せるよ」とかいう。
以下のようなコードでできます。</p>
<pre class="source" title="null参照戻り値">
<code>    <span class="reserved">unsafe</span> <span class="reserved">static</span> <span class="reserved">ref</span> <span class="type">T</span> NullRef&lt;<span class="type">T</span>&gt;() <span class="reserved">where</span> <span class="type">T</span> : <span class="reserved">struct</span> =&gt; <span class="reserved">ref</span> <span class="type">Unsafe</span>.AsRef&lt;<span class="type">T</span>&gt;((<span class="reserved">void</span>*)0);
    <span class="reserved">unsafe</span> <span class="reserved">static</span> <span class="reserved">bool</span> IsNull&lt;<span class="type">T</span>&gt;(<span class="reserved">ref</span> <span class="type">T</span> r) <span class="reserved">where</span> <span class="type">T</span> : <span class="reserved">struct</span> =&gt; <span class="type">Unsafe</span>.AsPointer(<span class="reserved">ref</span> r) == (<span class="reserved">void</span>*)0;
</code></pre>
<p>どういうことかというと、<a href="http://ufcpp.net/blog/2016/12/tipsgeneratedil/">先月18日の小ネタ</a>の最後でちょっと話しましたけど、 .NET ランタイムの内部的には参照とポインターの扱いは全く同じです。で、<code>Unsafe</code>クラスは、それを利用して(半分、悪用レベル)ポインターと参照の相互変換する機能を提供しています。名前通り結構安全性を損なう機能で、色々悪用もできます。その1つが、今回の「null参照」。0をポインターに渡して、それを参照に変換してやれば、nullな参照の完成という。</p>
<h2>参照にnullは期待しない</h2>
<p>参照とポインターの違いの1つに、無効な参照先(要するにnull)を認めるかどうかがあります。ポインターにはnullポインターがありますが、普通、参照先がない参照なんて想定しません。無効な場所を指さないように、コンパイラーが色々制限を掛けているのが参照です。 
C#でも「そのつもり」です。
参照引数も、参照戻り値も、通常は必ず有効な参照先を持ちます。</p>
<p>それを台無しにできる程度に悪用可能なのがunsafeコンテキストなわけです。まあ、そういうことが可能だから、コンパイルオプションで「unsafeコードを認める」(/unsafeオプション)をオンにしないと使えなくしているわけですが… 参照戻り値を使うと、/unsafeオプションなしで危ない事ができる可能性が出てきます。 </p>
<p><code>Unsafe</code>クラスの利用自体では、危ない事をするにはポインターを介する必要があって、使う側にも/unsafeオプションが必要です。危ないことしている自覚が出るという意味では、<code>Unsafe</code>クラスはまだ安全な部類と言えます。 </p>
<p>ところが、先ほどのコード、再掲になりますが以下のようなものが入ったライブラリを作るとします。 </p>
<pre class="source" title="null参照戻り値">
<code>    <span class="reserved">unsafe</span> <span class="reserved">static</span> <span class="reserved">ref</span> <span class="type">T</span> NullRef&lt;<span class="type">T</span>&gt;() <span class="reserved">where</span> <span class="type">T</span> : <span class="reserved">struct</span> =&gt; <span class="reserved">ref</span> <span class="type">Unsafe</span>.AsRef&lt;<span class="type">T</span>&gt;((<span class="reserved">void</span>*)0);
    <span class="reserved">unsafe</span> <span class="reserved">static</span> <span class="reserved">bool</span> IsNull&lt;<span class="type">T</span>&gt;(<span class="reserved">ref</span> <span class="type">T</span> r) <span class="reserved">where</span> <span class="type">T</span> : <span class="reserved">struct</span> =&gt; <span class="type">Unsafe</span>.AsPointer(<span class="reserved">ref</span> r) == (<span class="reserved">void</span>*)0;
</code></pre>
<p>このコードを実装する際にはポインターが含まれているので/unsafeオプションが必要です。一方、引数や戻り値にはポインターが出てこず、これを使う側には/unsafeオプション不要です。通常の、safeなコンテキストで、危ないものが使えている状態になりました。 </p>
<h3>null参照を認めるべきか</h3>
<p>できてしまうものは仕方がない。であれば、改めて、null参照を認めるべきなのかという問題が出てきます。 </p>
<p>まあ、前述の通り、普通、「無効な参照」なんて期待しません。他の言語でも見たことがない。「nullがほしければポインターを使え」という感じ。あまり期待されないていないものが存在するのはそれだけでデメリットです。完全に消せるならそれに越したことはない。 </p>
<p>ところが、先ほどの邪悪なアイディアにより、現状でも存在しうることがはっきりしました。まあ、敢えてあんなコードを書かない限りは起きない事なので、別に問題なしとして放置するのもありな範囲でしょう。(参照戻り値自体、利用頻度はそれほど多くならないだろうものです。低頻度なものにコストを掛けても割に合いません。) </p>
<p>逆に、積極的にnull参照を認めるならどうすべきでしょう。今現在、<a href="http://www.buildinsider.net/column/iwanaga-nobuyuki/012">null許容参照型</a>っていう言語機能も提案されているくらいですし、少なくとも、null参照があり得るかあり得ないかの区別は、メソッドシグネチャだけ見て区別が付くべきでしょう。そうなると、冒頭の<code>ref? T</code>という書き方が現実味を帯びてきます。 </p>
<h2>まとめ</h2>
<p><a href="https://www.nuget.org/packages/System.Runtime.CompilerServices.Unsafe/"><code>Unsafe</code>クラス</a>がなかなかやりたい放題で、通常あり得なさそうな「null参照」を得られることに気づきました。</p>
<p>まあ、<code>Unsafe</code>とかいう名前からして危なそうなものを使って初めてできることですし、参照戻り値自体利用頻度はそう高くない機能になると思われるので、放っておいても問題なさそうなものです。</p>
<p>とはいえ、もしかすると、「null許容参照」みたいな概念も必要になるかもしれません。</p>
 ]]></description>
				<pubDate>Tue, 24 Jan 2017 00:06:35 +0900</pubDate>
			</item>
			<item>
				<title>今年の振り返り</title>
				<link>http://ufcpp.net/blog/2016/12/lookbackattheyear/</link>
				<description><![CDATA[ <p>普段あんまりこういう「1年の〆」みたいなブログは書かないんですけど、今年は12月に1日1ブログを書いてるついでに、最後に1日を振り返りで埋めてしまおうかなぁとか、数日前に思いついたので。</p>
<p>今年というか、去年くらいからなんですけども、このサイトや僕が関わっているものの傾向を手短にまとめると、</p>
<ul>
<li>勉強会開催・登壇が減った</li>
<li>ブログが増えた</li>
</ul>
<p>ですかねぇ。</p>
<p>まあ、主に「ピックアップRoslyn」をやってるせい。
で、そうなった理由まで考えると、C# のオープンソース化の影響かなぁ。</p>
<h2>出る前が楽しい</h2>
<p>C# 7、結局、2016年中には出ませんでしたが。</p>
<p>とはいえ、RC版まで行くと後は基本的にバグ修正しかしなくなるので、むしろPreviewの頃の方が楽しいですね。
これも、オープンソース化の影響。
リリースよりも、作業が進んでるところが見えている方が楽しいって言う。</p>
<p><a href="http://www.buildinsider.net/column/iwanaga-nobuyuki">build insider</a>で書いてる記事なんかも、「最新動向」ってテーマでお願いされていて、なので、リリースよりも、現在の進捗追いつつ将来の機能を書く感じになっていますし。</p>
<h2>直接的な開発コミュニティ化</h2>
<p>なんか、コミュニティの作られ方がより直接的になったのかなとか感じます。</p>
<p>どこの方面でも共通の話ですが、「勉強会の高齢化」みたいな話題結構あって、C#もまあ、コミュニティによっては結構おっさんばっかり。MS技術は<a href="https://www.microsoft.com/ja-jp/education/imagine-cup.aspx">Imagine Cup</a>とか<a href="https://msdn.microsoft.com/ja-jp/microsoftstudentpartners.aspx">MSP</a>とかのおかげで定期的に若い子入ってきたりはしますし、
<a href="http://japan.unity3d.com/">Unity</a>の流行のおかげでUnityにも触れるようなところでは若返った感はありますが。</p>
<p>まあでも、全体的に高齢化していくのは世の常で。「上が詰まってて活躍できないから他のところに行く」みたいな、技術の良し悪しとは関係ないレイヤーで高齢化したりしますし…</p>
<p>でも、じゃあ、若い子がいないかというと、GitHub上でissue報告とかpull-request送ってくれたりするのは圧倒的に若い子っぽいんですよね。
なんていうか、紹介記事書いたり登壇したりじゃなくて、直接開発に関われる。
今時のコミュニティって、ソースコード リポジトリ上に中心があるのかも、とか思います。</p>
<p>もちろん、オープンソース自体はここ数年の動きじゃなくて、だいぶ昔からあるものですけども。
pull-request出しやすいとか、GitHubの功績が大きいのかなぁ。
C# 的にも、(<a href="https://roslyn.codeplex.com/">Codeplex</a>で)オープンソース化した瞬間よりも、<a href="https://github.com/dotnet/roslyn">GitHub移行</a>したときの方がインパクトが大きかった気がします。</p>
<h2>勉強会</h2>
<p>まあ、だからって、オフラインでの集まりがなくていいとも思ってはいないんですけども。
単純に、ちょっと記事書きに時間取られすぎてさぼっちゃったかなぁ…</p>
<p>幸いなのは、「<a href="https://csugjp.connpass.com/">C#ユーザー会</a>」の名前で、僕以外にも活動してくれる人が現れたこと。
<a href="https://twitter.com/kobake_/">こばやん</a>さん。</p>
<p>あんまり個人に依存していると、その個人の事情に左右されて、頻度や質にどうしても波ができちゃうんで、
協力してくれる人がいるって言うのは大変助かります。</p>
<p>あっ、ちなみに、VS 2017リリース記念勉強会はやります。
会場都合でたぶん2017年の3月11日(会場都合があるので、リリースがまだだったら「リリース間近」とかにタイトル変えてやります)。</p>
<h2>英語で出す</h2>
<p>で、ソースコード リポジトリが中心になると、割かし必然的にコミュニケーションは英語になっちゃうんですよね…</p>
<p>まあ、PPAPの流行に対しても「最大の教訓は、グローバルなメディアに英語で出すべきということ」なんて言う人いますしね。</p>
<p>というか、使ってくれる人、コメントくれる人はほんと英語が多い。
自分専用と思って適当に作ってまったく宣伝していないものでも、英語で出しとくと気が付いたら誰かが使ってて、
気が付いたら「いいね」的なコメントが付いてたりします。</p>
<p>ということで、まあ、宣伝して人に使ってもらう気が全くなくても、
ちょっとでも実用の芽があるあるかもって思ったものはとりあえず、ソースコード リポジトリを全部英語にしてます。</p>
<p>最近だと、こないだ作って公開した<a href="https://github.com/ufcpp/ContextFreeTask">ContextFreeTask</a>ってやつに興味を持って、
<a href="https://github.com/ufcpp/ContextFreeTask/pulls?q=is%3Apr+is%3Aclosed">pull-request</a>を送ってくれた人がいます。
元々はコンセプトの紹介用に適当に、実用性考えずに作ったものですけども、
どうも自分が思っていた以上に実用に使いたい/使えそうと思ってくれる人がいまして、
実用に耐えうるように修正するpull-requestという感じです。</p>
<p>日本人同士のやり取りでも全部とりあえず英語にしてもらいました。
まあ、面倒だったらtwitter上とかで日本語で話つつ修正するんですけども、
少なくとも、記録に残るところは英語にしておこうかなと。</p>
<h2>英語が返ってくる</h2>
<p>さらに言うと、タイトルとか説明文が日本語でも、例えば言語を問わないような動画(操作デモとか、演奏の類とか)だと、
真っ先にコメントが付くのは英語だったりしますし。</p>
<p>なんか、「特に意識しなくても返ってくるのは英語」って感じですかね。
もちろん能動的に自分で英語を書く方が得られる機会は多いんですけど、
受動的ですら英語。</p>
<p>個人の嗜好としては、やっぱりわざわざ英語の勉強を頑張るってのは嫌で、
「自然と触れるからなんとなく覚える」くらいの状態でありたいので、
最近のこういう傾向はありがたかったりします。</p>
<h2>C#小ネタ集の振り返り</h2>
<p>ついでなので、短期的な振り返りも。今月延々と書いてたC#小ネタ集。</p>
<p>当初予定では25日までの書き溜めがあったのが、追加や、別ネタの割り込みがあって気が付いたら30日分になっていて。
昨日でちょうど、在庫ピッタリ一掃。
今日、これを投稿したらほんとに1日1投稿です。</p>
<p>小ネタ集、アクセスが多かったのは上から順に以下の通りです。</p>
<ol>
<li>
<a href="http://ufcpp.net/blog/2016/12/tipstadpoleoperator/">小ネタ 隠し演算子(？)</a>
<ul>
<li>かなり丁寧に、本気でだますつもりで書きましたけど、それが良かったのかな</li>
</ul>
</li>
<li>
<a href="http://ufcpp.net/blog/2016/12/tipstryroslyn/">C#小ネタ集: C#をWeb上で試す</a>
<ul>
<li>まあ、初日ですし(だいたい、アドベントカレンダー的なものは初日だけ伸びる)</li>
<li>あと、やっぱり「ブラウザー上とかでさらっと試したい」需要はありますよね</li>
</ul>
</li>
<li>
<a href="http://ufcpp.net/blog/2016/12/tipsapisurface/">小ネタ privateメンバーはAPIの一部か</a>
<ul>
<li>これは<a href="https://twitter.com/Grabacr07">ぐらばくさん</a>効果かなぁ</li>
<li>あと、踏むと結構つらそうな不具合の話だからかな</li>
</ul>
</li>
</ol>
<p>オタマジャクシ演算子の話(他のやつの1.5倍～2倍)と比べると残りは微々たる差ですけども。</p>
<p>ちなみに、年間で言うと、以下の3つが上位。</p>
<ol>
<li><a href="http://ufcpp.net/blog/2016/2/porting-to-net-core/">.NET Coreへの移植</a></li>
<li><a href="http://ufcpp.net/blog/2016/9/awaitinunity55/">Unity 5.5でasync/await使えた話</a></li>
<li><a href="http://ufcpp.net/blog/2016/9/unicode/">プログラミング言語における文字コードの話</a></li>
</ol>
<p>案外 .NET Core が気になっている人多い。やっぱりUnityは強い。</p>
<p>意外だったのは、文字コードのやつですね。
他の方から、「システム開発やってて絶対はまるから文字コードの説明はしたいけど、文字コード単体だとものすごく受けが悪いから、プログラミング言語の講座とかに混ぜてやる」とかいう話も聞くんですけども。
なんか、3番目のアクセス数でした。</p>
<p>という結果を受けて書いたのが、以下のBuild Insiderでの記事なんですけども。</p>
<ul>
<li><a href="http://www.buildinsider.net/language/csharpunicode/01">Unicodeとは？ その歴史と進化、開発者向け基礎知識</a></li>
</ul>
<p>慣れない記事書いたもんだから、これ、ほんと苦労した…</p>
 ]]></description>
				<pubDate>Sat, 31 Dec 2016 14:37:10 +0900</pubDate>
			</item>
			<item>
				<title>小ネタ 正規分布の丸み</title>
				<link>http://ufcpp.net/blog/2016/12/tipsnormaldistribution/</link>
				<description><![CDATA[ <p>今日もたいがい、数学の話です。
一瞬、「<a href="http://togetter.com/li/1044668">動きにコクが出る</a>」って表現で話題になったあれの話。</p>
<p>そっかー、アニメーション付ける人に一言で説明するには「コク」って言葉になるのかー…
という衝撃は結構ありますが、まあ、乱数をいくつか足すと丸みが出るというの自体は事実。</p>
<h2>正規分布</h2>
<p>ちゃんとした数学的な説明をすると、</p>
<ul>
<li><a href="https://ja.wikipedia.org/wiki/%E4%B8%AD%E5%BF%83%E6%A5%B5%E9%99%90%E5%AE%9A%E7%90%86">中心極限定理</a>によって、独立な乱数を数多く足せば足すほど正規分布に近づく</li>
<li>自然界は多数の独立な乱雑さが重なってできてるので結構な頻度で正規分布が出てくる</li>
<li>正規分布で作った図形は丸みがかってる(というか、完全に真円・真球を作れる)</li>
</ul>
<p>みたいな話です。</p>
<p>C#関係ない… こころなし程度にC#に関係している点というと、「<a href="http://www.mathdotnet.com/">Math.NET</a> っていう数学ライブラリがあるよ」という話。</p>
<h2>例: 2次元上の点の分布を作る</h2>
<p>「丸み」の例として、2次元上の点(x, y)を乱数を使って作ることを考えます。</p>
<p>以降のサンプル コードでは、<a href="https://www.nuget.org/packages/MathNet.Numerics/">Math.NET Numerics</a>を使って、
以下の<code>using</code>ディレクティブがあるものとして説明します。</p>
<pre class="source" title="MathNet.Numerics.Distributions">
<code><span class="reserved">using</span> MathNet.Numerics.Distributions;
<span class="reserved">using</span> <span class="reserved">static</span> System.<span class="type">Math</span>;
</code></pre>
<p>例えば、x, yそれぞれに対して、一様乱数(一定の範囲内で、全ての値が均等な確率で出現する乱数)を使って点を作ると、完全に真四角になります。</p>
<pre class="source" title="一様乱数を2個使って2次元座標を作る">
<code><span class="reserved">var</span> rand = <span class="reserved">new</span> <span class="type">ContinuousUniform</span>(-1, 1);
<span class="reserved">var</span> p = (rand.Sample(), rand.Sample());
</code></pre>
<p>このコードで1万点ほどプロットすると、以下のようになります。</p>
<p><img src="/media/1124/uniformxy.png" alt="一様乱数でx, yを生成した結果" /></p>
<p>で、四角いのはあまりに不自然なので、これを丸くしたいです。
割と軽い計算量で実現する方法があって、
それが冒頭で言った、「乱数をいくつか足す」というやつです。</p>
<p>乱数を足すために、以下のようなメソッドを用意してみます。
<code>n</code>個足して平均を取るだけの関数です。</p>
<pre class="source" title="一様乱数を n 回重ねて平均を取る">
<code><span class="reserved">static</span> <span class="reserved">double</span> Mean(<span class="type">IContinuousDistribution</span> d, <span class="reserved">int</span> n)
    =&gt; <span class="type">Enumerable</span>.Range(0, n).Select(_ =&gt; d.Sample()).Sum() / n;
</code></pre>
<p>これを使って、<code>n</code> = 2～5に対して、以下のコードで点を生成してみます。</p>
<pre class="source" title="一様乱数を重ねたもので2次元座標を作る">
<code><span class="reserved">var</span> rand = <span class="reserved">new</span> <span class="type">ContinuousUniform</span>(-1, 1);
<span class="reserved">var</span> p = (Mean(rand, n), Mean(rand, n));
</code></pre>
<p>先ほどと同様、1万点ずつプロットした結果を以下に示します。
上から順に、<code>n</code> = 2～5です。</p>
<p><img src="/media/1120/uniform2xy.png" alt="一様乱数を2個足してx, yを生成した結果" />
<img src="/media/1121/uniform3xy.png" alt="一様乱数を3個足してx, yを生成した結果" />
<img src="/media/1122/uniform4xy.png" alt="一様乱数を4個足してx, yを生成した結果" />
<img src="/media/1123/uniform5xy.png" alt="一様乱数を5個足してx, yを生成した結果" /></p>
<p><code>n</code> = 5 くらいまでくると、だいぶ丸くなります。</p>
<p>ちなみに、正規分布乱数を使うと、真円になります。</p>
<pre class="source" title="正規分布乱数で2次元座標を作る">
<code><span class="reserved">var</span> rand = <span class="reserved">new</span> <span class="type">Normal</span>(-1, 1);
<span class="reserved">var</span> p = (rand.Sample(), rand.Sample());
</code></pre>
<p><img src="/media/1119/normalxy.png" alt="正規分布乱数でx, yを生成した結果" /></p>
<p>要するに、以下のような感じ。</p>
<ul>
<li>一様乱数を足していくと、数が多いほど正規分布乱数に近づく</li>
<li>5個も足すと結構いい感じに丸くなる</li>
<li>正規分布乱数は真円(理論上、本当に完全に円)</li>
</ul>
<h2>乱数の和</h2>
<p>まあ、一様乱数を複数足すと正規分布乱数になるってのは、
結構難しい話になります。</p>
<p>確率って、連続な分布を持つものをまっとうに考えようと思うと、
<a href="https://ja.wikipedia.org/wiki/%E6%B8%AC%E5%BA%A6%E8%AB%96">測度</a>とか、
<a href="https://ja.wikipedia.org/wiki/%E3%83%AB%E3%83%99%E3%83%BC%E3%82%B0%E7%A9%8D%E5%88%86">ルベーグ積分</a>とか、
<a href="https://ja.wikipedia.org/wiki/%E3%83%95%E3%83%BC%E3%83%AA%E3%82%A8%E5%A4%89%E6%8F%9B">フーリエ変換</a>とか、
数学の中でもそこそこ高等な部類に入る理論が出まくる結構ガチな分野です。</p>
<p>とりあえず、大学学部くらいで習う言葉で要約すると、</p>
<ul>
<li>乱数の和を取ると、確率密度関数が畳み込み積(convolution)になる</li>
<li>
一様分布を何度も畳み込みしていくと、徐々に正規分布に収束する
<ul>
<li>参考: <a href="http://ogyahogya.hatenablog.com/entry/2014/09/22/%E7%A2%BA%E7%8E%87%E5%A4%89%E6%95%B0%E3%81%AE%E5%92%8C_-%E5%90%88%E6%88%90%E7%A9%8D%E3%81%A8%E3%81%AE%E9%96%A2%E4%BF%82-">確率変数の和 -合成積との関係-</a></li>
<li>参考: <a href="http://www.biwako.shiga-u.ac.jp/sensei/mnaka/ut/irwinhalldist.html">連続型一様分布の和の分布</a></li>
</ul>
</li>
<li>
正規分布同士を畳み込みすると、結果もまた正規分布になる
<ul>
<li>参考: <a href="http://fussy.web.fc2.com/algo/stat5_gaussian.htm">確率・統計 正規分布</a></li>
</ul>
</li>
</ul>
<p>という感じ。</p>
<p>微分しても元通りになる指数関数が微分・積分の分野で最も自然な関数になるのと同様に、
確率分布では正規分布が最も自然な分布になる、という感じです。</p>
<h2>正規分布は丸い</h2>
<p>まあ、「正規分布乱数を使うと自然に見える」というのは正しいんですが。
ちょっとまだ不思議なことがあります。</p>
<p>これまで例を示してきた話はまとめると以下のようになります。</p>
<ul>
<li>一様乱数は四角い、そして、不自然に見える</li>
<li>正規分布乱数は丸い、そして、自然に見える</li>
</ul>
<p>ここで疑問に思うべきは、丸いのは自然なのか。
自然は丸くなるのか。</p>
<p>まあ実際、丸いんですよね。自然物にはあんまり角がない。
いろいろ根拠はあるんですが。
いろんな物理法則が、計算してみると円や球を解に持ちます。
例えば、わかりやすい例だと以下のようなやつ。</p>
<ul>
<li>距離に反比例するような物理法則が多くて、等ポテンシャル面をプロットすると球</li>
<li>体積に対して表面積が最小になる図形が球なので、真球状態が一番安定して存在できる</li>
</ul>
<p>そして、正規分布乱数の話でも、やっぱり真円や真球が出てきたりします。
先ほど、「正規分布同士を畳み込みすると、結果もまた正規分布になる」と書きましたが、
これから言えることは、「正規分布乱数同士の和や差は、やっぱり正規分布乱数になる」ということです。</p>
<p>回転を表す座標変換は、以下の通り、和と差になるので、
<math xmlns="http://www.w3.org/1998/Math/MathML"><msub><mrow><mi>x</mi></mrow><mrow><mn>1</mn></mrow></msub></math>, <math xmlns="http://www.w3.org/1998/Math/MathML"><msub><mrow><mi>y</mi></mrow><mrow><mn>1</mn></mrow></msub></math>が正規分布乱数で作られているとき、
回転した結果の <math xmlns="http://www.w3.org/1998/Math/MathML"><msub><mrow><mi>x</mi></mrow><mrow><mn>2</mn></mrow></msub></math>, <math xmlns="http://www.w3.org/1998/Math/MathML"><msub><mrow><mi>y</mi></mrow><mrow><mn>2</mn></mrow></msub></math> も正規分布乱数になります。</p>
<p><math xmlns="http://www.w3.org/1998/Math/MathML"><msub><mrow><mi>x</mi></mrow><mrow><mn>2</mn></mrow></msub><mo>=</mo><mrow><mrow><mi mathvariant="normal">cos</mi></mrow><mo>⁡</mo><mrow><mi>θ</mi></mrow></mrow><mi> </mi><msub><mrow><mi>x</mi></mrow><mrow><mn>1</mn></mrow></msub><mo>-</mo><mrow><mrow><mi mathvariant="normal">sin</mi></mrow><mo>⁡</mo><mrow><mi>θ</mi></mrow></mrow><mi> </mi><msub><mrow><mi>y</mi></mrow><mrow><mn>1</mn></mrow></msub></math></p>
<p><math xmlns="http://www.w3.org/1998/Math/MathML"><msub><mrow><mi>y</mi></mrow><mrow><mn>2</mn></mrow></msub><mo>=</mo><mrow><mrow><mi mathvariant="normal">sin</mi></mrow><mo>⁡</mo><mrow><mi>θ</mi></mrow></mrow><mi> </mi><msub><mrow><mi>x</mi></mrow><mrow><mn>1</mn></mrow></msub><mo>+</mo><mrow><mrow><mi mathvariant="normal">cos</mi></mrow><mo>⁡</mo><mrow><mi>θ</mi></mrow></mrow><mi> </mi><msub><mrow><mi>y</mi></mrow><mrow><mn>1</mn></mrow></msub></math></p>
<p>正規分布乱数は、回転対象な分布を作ります。
どの方向も均一です。</p>
<p>例えばの話、以下のような乱数で2次元の点を作ってみましょう。
角度を一様分布にしたものです。</p>
<pre class="source" title="確度を一様分布にして作った2次元座標">
<code><span class="reserved">var</span> chi = <span class="reserved">new</span> <span class="type">ChiSquared</span>(2);
<span class="reserved">var</span> uni = <span class="reserved">new</span> <span class="type">ContinuousUniform</span>(0, 2 * PI));
<span class="reserved">var</span> r = Sqrt(chi.Sample());
<span class="reserved">var</span> θ = uni.Sample();
<span class="reserved">var</span> p = (r * Cos(θ), r * Sin(θ));
</code></pre>
<p><code>ChiSquared</code>は<a href="https://ja.wikipedia.org/wiki/%E3%82%AB%E3%82%A4%E4%BA%8C%E4%B9%97%E5%88%86%E5%B8%83">カイ二乗分布</a>っていうやつで、
正規分布なx, yに対して、<math xmlns="http://www.w3.org/1998/Math/MathML"><msup><mrow><mi>x</mi></mrow><mrow><mn>2</mn></mrow></msup><mo>+</mo><msup><mrow><mi>y</mi></mrow><mrow><mn>2</mn></mrow></msup></math>
の分布がカイ二乗分布になります。</p>
<p>これも1万点プロットすると、以下のようになります。</p>
<p><img src="/media/1118/chisquaredr.png" alt="カイ二乗分布で半径を、一様分布で角度を生成した結果" /></p>
<p>比較のために、正規分布乱数でx, yを作ったものを再度並べてみましょう。</p>
<p><img src="/media/1119/normalxy.png" alt="正規分布乱数でx, yを生成した結果" /></p>
<p>ほとんど同じ分布になっていると思います。
理論上は完全一致するはずで、点の数を増やせば増やすほど一致するはずです。</p>
<p>適当にx軸、y軸を決めて、それぞれ独立に乱雑に座標を振っても、
x, yともに正規分布乱数(= 自然な乱数)になっている限り、
軸のとり方に依らない(回転する座標変換を掛けても、元の法則と同じ式が現れる)ということです。</p>
<p>自然物は向きを持たなくて、自然法則は軸のとり方に依らない。
ということが、自然法則を表すいろいろな数式上に現れます。
その結果が、真円や真球に結びついたりします。</p>
 ]]></description>
				<pubDate>Fri, 30 Dec 2016 00:35:19 +0900</pubDate>
			</item>
			<item>
				<title>小ネタ atan2</title>
				<link>http://ufcpp.net/blog/2016/12/tipsatan2/</link>
				<description><![CDATA[ <p>今日は、<code>Math</code>クラスの<code>Atan2</code>メソッドの話。あんまり数学がわかってない人だと、「tanの逆関数」なのにどうして2引数あるのかとか、<code>Atan</code>と<code>Atan2</code>で戻り値の範囲が違う(前者が-90度～90度、後者が-180度から180度)のが不思議だったりするみたいですね。</p>
<p>大元をたどるとatan2はFORTRANとかC言語とかの頃からあって、ちょっと調べれる範囲でもFORTRAN 77の時点であったらしいので、少なくとも1977年より前まで遡ります。なのでC#の小ネタというよりはプログラミング全般の小ネタだったり、むしろ、単に数学の話だったり。</p>
<h2>x軸とのなす角</h2>
<p>単純化のために、まずは半径1の円周上の点(x, y)の1点だけを考えて、原点からこの点までの線分と、x軸がなす角を考えます。以下の絵のような感じ。</p>
<p><img src="/media/1117/sincos.png" alt="x軸と線分のなす角" /></p>
<p>この絵を見ての通り、以下の条件を満たすθを計算することになります。</p>
<p><math xmlns="http://www.w3.org/1998/Math/MathML" ><mi>x</mi><mo>=</mo><mrow><mrow><mi mathvariant="normal">cos</mi></mrow><mo>⁡</mo><mrow><mi>θ</mi></mrow></mrow></math></p>
<p><math xmlns="http://www.w3.org/1998/Math/MathML" ><mi>y</mi><mo>=</mo><mrow><mrow><mi mathvariant="normal">sin</mi></mrow><mo>⁡</mo><mrow><mi>θ</mi></mrow></mrow></math></p>
<p>「逆三角関数を使えば簡単」と思うかもしれませんが、それだと半分だけ正解。<math xmlns="http://www.w3.org/1998/Math/MathML" ><mi>θ</mi><mo>=</mo><mrow><mrow><msup><mrow><mi mathvariant="normal">cos</mi></mrow><mrow><mo>-</mo><mn>1</mn></mrow></msup></mrow><mo>⁡</mo><mrow><mi>x</mi></mrow></mrow></math>だと、x軸を中心に左右どちら周りなのかがわからなくなります。</p>
<p><img src="/media/1115/acos.png" alt="acosで求める角度" /></p>
<p>同様に、<math xmlns="http://www.w3.org/1998/Math/MathML" ><mi>θ</mi><mo>=</mo><mrow><mrow><msup><mrow><mi mathvariant="normal">sin</mi></mrow><mrow><mo>-</mo><mn>1</mn></mrow></msup></mrow><mo>⁡</mo><mrow><mi>y</mi></mrow></mrow></math>だとy軸中心の折り返しがわからないです。さらにいうと、以下の式もダメ。y/xしている時点でわかると思いますが、符号が消えます。x, yともに正の場合と、共に負の場合が同じ値になってしまうので、やっぱり半円分しか計算できません。</p>
<p><math xmlns="http://www.w3.org/1998/Math/MathML" ><mfrac><mrow><mi>y</mi></mrow><mrow><mi>x</mi></mrow></mfrac><mo>=</mo><mrow><mrow><mi mathvariant="normal">tan</mi></mrow><mo>⁡</mo><mrow><mi>θ</mi></mrow></mrow></math></p>
<p><math xmlns="http://www.w3.org/1998/Math/MathML" ><mi>θ</mi><mo>=</mo><mrow><mrow><msup><mrow><mi mathvariant="normal">tan</mi></mrow><mrow><mo>-</mo><mn>1</mn></mrow></msup></mrow><mo>⁡</mo><mrow><mfrac><mrow><mi>y</mi></mrow><mrow><mi>x</mi></mrow></mfrac></mrow></mrow></math></p>
<p>ということで、角度θを360度ちゃんと求めるためには、x, y、すなわち、cos, sinの両方の値が必要です。実際、<code>Atan2</code>は大体以下のような感じの分岐をしています。</p>
<pre class="source" title="Atan2 の中身(抜粋)">
<code><span class="reserved">static</span> <span class="reserved">double</span> Atan2(<span class="reserved">double</span> y, <span class="reserved">double</span> x)
{
    <span class="reserved">var</span> z = <span class="type">Math</span>.Atan(<span class="type">Math</span>.Abs(y / x));
    <span class="reserved">if</span> (x &gt; 0)
    {
        <span class="reserved">if</span> (y &gt; 0) <span class="reserved">return</span> z;
        <span class="reserved">else</span> <span class="reserved">return</span> -z;
    }
    <span class="reserved">else</span>
    {
        <span class="reserved">if</span> (y &gt; 0) <span class="reserved">return</span> <span class="type">Math</span>.PI - z;
        <span class="reserved">else</span> <span class="reserved">return</span> z - <span class="type">Math</span>.PI;
    }
    <span class="comment">// ほんとは0, infinity, NaN の場合分けあり</span>
}
</code></pre>
<h2>2点のなす角</h2>
<p>ここからは完全におまけ。ちょっとした数学の話。2点だとどうでしょう。(x<sub>1</sub>, y<sub>1</sub>)と原点と(x<sub>2</sub>, y<sub>2</sub>)のなす角。</p>
<p><img src="/media/1116/angle.png" alt="2点のなす角" /></p>
<p>これも、正弦定理・余弦定理からの変形で、以下のような式が成り立ちます。</p>
<p><math xmlns="http://www.w3.org/1998/Math/MathML" ><mrow><mrow><mi mathvariant="normal">cos</mi></mrow><mo>⁡</mo><mrow><mi>θ</mi></mrow></mrow><mo>=</mo><msub><mrow><mi>x</mi></mrow><mrow><mn>1</mn></mrow></msub><msub><mrow><mi>x</mi></mrow><mrow><mn>2</mn></mrow></msub><mo>+</mo><msub><mrow><mi>y</mi></mrow><mrow><mn>1</mn></mrow></msub><msub><mrow><mi>y</mi></mrow><mrow><mn>2</mn></mrow></msub></math></p>
<p><math xmlns="http://www.w3.org/1998/Math/MathML" ><mrow><mrow><mi mathvariant="normal">sin</mi></mrow><mo>⁡</mo><mrow><mi>θ</mi></mrow></mrow><mo>=</mo><msub><mrow><mi>x</mi></mrow><mrow><mn>1</mn></mrow></msub><msub><mrow><mi>y</mi></mrow><mrow><mn>2</mn></mrow></msub><mo>-</mo><msub><mrow><mi>x</mi></mrow><mrow><mn>2</mn></mrow></msub><msub><mrow><mi>y</mi></mrow><mrow><mn>1</mn></mrow></msub></math></p>
<p>内積がcosで、面積(交代積)がsin。これらを<code>Atan2(sin, cos)</code>の順で与えれば角度θが求まります。</p>
<h2>オイラーの公式</h2>
<p>もう1つおまけ。
「オイラーは数多の公式を残しすぎてどの公式だよ」という話もあるんですが、ここで話すのは複素解析におけるオイラーの公式です。有名なあれ。
<math xmlns="http://www.w3.org/1998/Math/MathML"><msup><mrow><mi>e</mi></mrow><mrow><mi>i</mi><mi>θ</mi></mrow></msup><mo>=</mo><mrow><mrow><mi mathvariant="normal">cos</mi></mrow><mo>⁡</mo><mrow><mi>θ</mi></mrow></mrow><mo>+</mo><mi>i</mi><mrow><mrow><mi mathvariant="normal">sin</mi></mrow><mo>⁡</mo><mrow><mi>θ</mi></mrow></mrow></math></p>
<p>これを逆に、<math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mrow><mi mathvariant="normal">cos</mi></mrow><mo>⁡</mo><mrow><mi>θ</mi></mrow></mrow><mo>+</mo><mi>i</mi><mrow><mrow><mi mathvariant="normal">sin</mi></mrow><mo>⁡</mo><mrow><mi>θ</mi></mrow></mrow><mo>=</mo><mi>x</mi><mo>+</mo><mi>i</mi><mi>y</mi></math>だと考えた場合、両辺の対数を取ることで、</p>
<p><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>i</mi><mi>θ</mi><mo>=</mo><mrow><mrow><mi mathvariant="normal">log</mi></mrow><mo>⁡</mo><mrow><mfenced separators="|"><mrow><mi>x</mi><mo>+</mo><mi>i</mi><mi>y</mi></mrow></mfenced></mrow></mrow></math></p>
<p><math xmlns="http://www.w3.org/1998/Math/MathML"><mi>θ</mi><mo>=</mo><mo>-</mo><mi>i</mi><mrow><mrow><mi mathvariant="normal">log</mi></mrow><mo>⁡</mo><mrow><mfenced separators="|"><mrow><mi>x</mi><mo>+</mo><mi>i</mi><mi>y</mi></mrow></mfenced></mrow></mrow></math></p>
<p>となります。
ここで、<code>Atan2</code>の使い道を思い出してみます。<code>θ=Atan2(y, x)</code>なわけで、</p>
<p><math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mrow><mi mathvariant="normal">Atan</mi><mn>2</mn></mrow><mo>⁡</mo><mrow><mfenced separators="|"><mrow><mi>y</mi><mo>,</mo><mi> </mi><mi>x</mi></mrow></mfenced></mrow></mrow><mo>=</mo><mo>-</mo><mi>i</mi><mrow><mrow><mi mathvariant="normal">log</mi></mrow><mo>⁡</mo><mrow><mfenced separators="|"><mrow><mi>x</mi><mo>+</mo><mi>i</mi><mi>y</mi></mrow></mfenced></mrow></mrow></math></p>
<p>です。<code>Atan2</code>は、絶対値が1の複素数に対する対数関数と関連していたりします(指数関数が三角関数と関連しているんだから、対数関数(指数関数の逆関数)が逆三角関数と関連しているのも当然の話です)。</p>
<p>てことで、実のところ、<code>Atan2</code>って、「複素対数関数」だと言っても過言ではなかったり。
実装都合の変な関数ではなくて、割かし「数学的にあり得る関数」です。</p>
 ]]></description>
				<pubDate>Thu, 29 Dec 2016 00:39:40 +0900</pubDate>
			</item>
			<item>
				<title>小ネタ do-while</title>
				<link>http://ufcpp.net/blog/2016/12/tipsdowhile/</link>
				<description><![CDATA[ <p><a href="http://ufcpp.net/study/csharp/st_loop.html#dowhile">do-whileステートメント</a>とか使っていますか？</p>
<p>あんまり実際に使われているコードを実務で見たことはなく。
<a href="http://blog.modd.com/entry/2016/09/21/120442">使われていないキーワードランキング</a>的にも<code>do</code>は使われてない方から数えて27位。
もしかしたら使われないどころか存在を忘れてる人すらいるんじゃないかというこの文法。</p>
<p>「使ってる？」とか人に聞いてみたところ、
「初心者の頃にちょっと」「もしかしたら初心者ほど使ってるかも」とかいう回答も得られたり。
確かに、入門書とか(<a href="http://ufcpp.net/study/csharp/">うちのサイト</a>含めて)には書かれてますもんね。書かれてば使うか。</p>
<p>たぶん、徐々に、以下のように <code>while (true)</code> になっていくのかなぁとか。
まあ、そもそも、ループの大半が <code>foreach</code> ですけど。<code>do-while</code> どころか <code>while</code> もそこそこレア。</p>
<pre class="source" title="while (true)">
<code><reserved></span><span class="reserved">while</span> (<span class="reserved">true</span>)
{
    <span class="comment">// 前にも書きたいことあるし、</span>
    <span class="reserved">if</span> (条件) <span class="reserved">break</span>;
    <span class="comment">// 後ろにも書きたいことある</span>
}
<span class="reserved">while</span> (<span class="reserved">true</span>)
{
    <span class="comment">// というか、メソッド抽出して return する方が多いかも</span>
    <span class="reserved">if</span> (条件) <span class="reserved">return</span> ...;
}
</code></pre>
<p>さて、そんな<code>do-while</code>がなぜあるか、ですが。
確かに<code>do-while</code>の「最低1回は実行したい」という要件はそもそも出番が少ない上に、やろうと思えば<code>while</code>だけで書けます。
要するに、レアケースのために専用構文がある意味はあったのかという問題が。</p>
<p>ご存知の通り、この構文はC言語からあります。
「その当時ならば使ったのか」と言われると、やっぱりそんなに使いはしなかったと思うんですけど…</p>
<p>実は、生成されるコードが<code>while</code>よりも<code>do-while</code>の方が短いんですよね。
ということで、おそらく、<code>do-while</code>があるのは、そういうパフォーマンス上の理由かなぁと思います。</p>
<p>どういうことかというと、例えば、<code>do-while</code>は以下のように展開されます。</p>
<pre class="source" title="do-whileの展開">
<code><reserved></span><span class="reserved">static</span> <span class="reserved">void</span> DoWhile(<span class="reserved">int</span> x)
{
    <span class="reserved">do</span>
    {
        --x;
    } <span class="reserved">while</span> (x &gt; 0);
}
<span class="comment">// ↓</span>
<span class="reserved">static</span> <span class="reserved">void</span> DoWhileCompiled(<span class="reserved">int</span> x)
{
    BEGIN_DO_WHILE:;
    --x;
    <span class="reserved">if</span> (x &gt; 0) <span class="reserved">goto</span> BEGIN_DO_WHILE;
}
</code></pre>
<p>これに対して、<code>while</code>だと以下のように、<code>goto</code> (IL 的には <code>br</code> 命令。x64 系 CPU のネイティブコード的には jmp 命令)が1個多く展開されたりします。</p>
<pre class="source" title="whileの展開">
<code><reserved></span><span class="reserved">static</span> <span class="reserved">void</span> While(<span class="reserved">int</span> x)
{
    <span class="reserved">while</span> (x &gt; 0)
    {
        --x;
    }
}
<span class="comment">// ↓</span>
<span class="reserved">static</span> <span class="reserved">void</span> WhileCompiled(<span class="reserved">int</span> x)
{
    <span class="reserved">goto</span> END_WHILE;<span class="comment">// この goto がいまいち好きになれない</span>
    BEGIN_WHILE:;
    --x;
    END_WHILE:;
    <span class="reserved">if</span> (x &gt; 0) <span class="reserved">goto</span> BEGIN_WHILE;
}
</code></pre>
<p>この、<code>while</code>、<code>do-while</code>を使ったものと、展開結果の<code>goto</code>を使ったものが本当に一緒になるかも確認してみましょう。
上記コードをコンパイルして、ildasmを掛けた結果は以下の通りです。
上が<code>while</code>、下が<code>do-while</code>。
左が展開前、右が展開後。</p>
<p><img src="/media/1114/dasm.png" alt="コンパイル結果" /></p>
<p>ついでに、<code>do-while</code>の方が数バイト小さくなることもわかります。
ここではILしか出していませんけども、たいていのCPUで、ネイティブ コードでもやっぱり<code>do-while</code>の方が短くなると思います。</p>
<p>とはいえ、この微々たる要件のためにいまだにこの構文が必要かと言われると微妙なラインですかね。</p>
 ]]></description>
				<pubDate>Wed, 28 Dec 2016 00:00:53 +0900</pubDate>
			</item>
			<item>
				<title>小ネタ 並列化</title>
				<link>http://ufcpp.net/blog/2016/12/tipsparallelism/</link>
				<description><![CDATA[ <p>よく目にする話題だと思いますが、ここ10数年くらい、CPUの性能は高クロック動作化ではなく、並列化によって向上しています。
CPU律速になるような計算処理は、ガチガチに最適化するなら並列処理を考える必要が出てきます。</p>
<p>並列化によって高速化しやすい計算の例として、浮動小数点数のデータ列の積和演算を考えてみます。
例えば、以下のようなコードになります。</p>
<pre class="source" title="シングルスレッド実行">
<code><span class="reserved">private</span> <span class="reserved">static</span> <span class="reserved">float</span> SingleThreadScalar(<span class="reserved">float</span>[] x, <span class="reserved">float</span>[] y)
{
    <span class="reserved">var</span> prod = 0f;

    <span class="reserved">for</span> (<span class="reserved">int</span> i = 0; i &lt; N; i++)
        prod += x[i] * y[i];

    <span class="reserved">return</span> prod;
}
</code></pre>
<h2>並列化のレイヤー</h2>
<p>まあ、一口に並列化と言っても、いくつかの手段があります。</p>
<ul>
<li>分散コンピューティング</li>
<li>CPU間並列</li>
<li>CPU内並列</li>
</ul>
<h3>分散コンピューティング</h3>
<p>1つ目は、複数台のマシンに処理を分散する方法。</p>
<p><img src="/media/1112/distribution.png" alt="分散コンピューティング" /></p>
<p>要はビッグデータ(big data)とかHPC (high perfomance computing)とか言われている分野です。
どういうコンピューターを、どういうネットワークでつなげて、どう大規模に運用していくか、みたいな個人ではどうにもならないノウハウが必要なので、
並列処理コードを書くというよりは、大手クラウド業者から提供されているサービスを使って計算するという感じになります。</p>
<p>今回さらっと試して見せれるような面白いデータを持っているわけでもないので、今日はこのレイヤーには触れません。</p>
<h3>CPU間並列</h3>
<p>2つ目は、複数のCPUで一斉に計算する方法。
1台のマザーボードに複数のCPUを刺して使ったりするやつです(マルチCPU)。
あるいは最近のCPUであれば、同じ機能を有した「コア」が、1つのチップ内に複数並んで配置されていて、OSから見ると複数のCPUが刺さっているように見えます(マルチコア)。</p>
<p>また、ハイバースレッディング(hyper-threading)なんていう手法もあります。
これは、あるCPUコア内で、内部の演算器で暇になっているやつがある場合に、仮想的にもう1個CPUがあるように見せかけて暇な演算器を活用できるようにする仕組みです。</p>
<p>いずれにしても、それぞれ独立したCPUが、1つのマザーボードやメインメモリを共有して動いています。</p>
<p><img src="/media/1113/multicore.png" alt="マルチコア/マルチCPU" /></p>
<p>それぞれが独立して動いているので、CPUコア間での同期はそれなりの負担になります。
分散コンピューティングと比べると微々たるものですが、CPU内部で完結した処理と比べるとかなり遅いです。</p>
<p>複数のCPUを使って並列に処理するためには、C#だとスレッドを使います。
と言っても、<code>Thread</code>クラス(<code>System.Threading</code>名前空間)を直接使うことはあまりなくて、
<code>Task</code>クラスや<code>Parallel</code>クラス(<code>System.Threading.Tasks</code>名前空間)を使います。</p>
<p>積和演算くらいの小さな処理を<code>Parallel</code>クラスを使って高速化するのは難しいようです。
そこで、ここでは<code>Task</code>クラスを使った例を挙げます。
以下のような書き方になります。</p>
<pre class="source" title="マルチスレッド実行">
<code><span class="reserved">private</span> <span class="reserved">static</span> <span class="reserved">float</span> MultiThreadScalar(<span class="reserved">float</span>[] x, <span class="reserved">float</span>[] y)
{
    <span class="reserved">var</span> windowSize = N / NumWorkerThread;

    <span class="reserved">var</span> prod = 0f;

    <span class="reserved">var</span> partialProds = <span class="type">Task</span>.WhenAll(
        <span class="type">Enumerable</span>.Range(0, NumWorkerThread)
        .Select(n =&gt; <span class="type">Task</span>.Run(() =&gt;
        {
            <span class="reserved">var</span> local = 0f;
            <span class="reserved">for</span> (<span class="reserved">int</span> i = n * windowSize; i &lt; (n + 1) * windowSize; i++)
                local += x[i] * y[i];
            <span class="reserved">return</span> local;
        }))
        ).GetAwaiter().GetResult();
    prod = 0f;
    <span class="reserved">for</span> (<span class="reserved">int</span> i = 0; i &lt; partialProds.Length; i++)
        prod += partialProds[i];
    <span class="reserved">return</span> prod;
}
</code></pre>
<p><code>NumWorkerThread</code>は、CPUのコア数にそろえておくのが一番効率がいいと言われています。
例えば、<code>NumWorkerThread = Environment.ProcessorCount</code>で取得できます。</p>
<p>この例では、コア数分にループを分割して、それぞれのコアで個別に積和を求めて、
最後にそれぞれの結果を足しています。
こういう、それぞれ個別に計算して最後に集計できるものでないと、マルチコアを活用した高速化はなかなかできません。</p>
<h3>CPU内並列</h3>
<p>1つのCPUコアの内部でも並列処理があります。
SIMD(Single Instruction Multiple Data)命令と呼ばれていて、
複数のデータをまとめて格納できるレジスターや、
まとめて計算できる命令を持っています。</p>
<p><img src="/media/1111/simd.png" alt="SIMD演算" /></p>
<p>SIMD命令を活用できるかどうかは、コンパイラーがどのくらい頑張っているか次第ではあります。
一応、プログラマーが意図的に、特定の場所でSIMD命令が使われるように指示できるライブラリも用意されている場合があります。</p>
<p>C#では、.NET Framework 4.6でSIMD命令対応がありました。
<a href="https://www.nuget.org/packages/System.Numerics.Vectors/"><code>System.Numerics.Vectors</code></a>というパッケージを参照して、
その中にある<code>Vector</code>構造体を使うと.NET Framework 4.6以降のJIT (<a href="https://blogs.msdn.microsoft.com/jpvsblog/2016/01/11/net-framework-4-6-64-bit-jit/">RyuJIT</a>)は、SIMD命令に置き換えて最適化してくれます。</p>
<p>例えば、以下のようなコードを書いたとします。
2つの浮動小数点数データ列の積和を行っています。
<code>Vector4.Dot</code>は、4つの浮動小数点数をまとめたもの(<code>Vector4</code>)の内積(積和演算)です。</p>
<pre class="source" title="SIMD命令化">
<code><span class="reserved">private</span> <span class="reserved">static</span> <span class="reserved">float</span> SingleThreadVector(<span class="type">Vector4</span>[] vx, <span class="type">Vector4</span>[] vy)
{
    <span class="reserved">var</span> prod = 0f;
    prod = 0f;
    <span class="reserved">for</span> (<span class="reserved">int</span> i = 0; i &lt; N / 4; i++)
        prod += <span class="type">Vector4</span>.Dot(vx[i], vy[i]);
    <span class="reserved">return</span> prod;
}
</code></pre>
<p>これを、x64向けにビルドして実行すると、JIT結果は以下のようなネイティブ コードになります(上記コードのループの中身に相当する部分を抜粋)。</p>
<p><code>vmovupd     xmm1,xmmword ptr [rdi+r8+10h]  
vdpps       xmm0,xmm0,xmm1,0F1h  
vaddss      xmm0,xmm0,xmm6  
vmovaps     xmm6,xmm0</code></p>
<p><code>xmm0</code>や<code>xmm1</code>が、複数のデータをまとめて格納できるレジスターの名前です。
<code>vdpps</code>が4つの<code>float</code>(32ビット浮動小数点数)の積和演算、
<code>vaddss</code>が加算、<code>vmovupd</code>と<code>vmovaps</code>がレジスター間のデータ移動です。</p>
<p>ちなみに、それ以前の.NET Frameworkなど、対応していないプラットフォームで実行すると、SIMDではない普通の命令に展開されます(早くはならないけども、<code>Vector</code>を使わない場合と比べてそんなに遅くなるわけでもない)。</p>
<p>同じコードを、Any CPU向けにビルドして実行すると、以下のような命令に変わります。</p>
<p><code>fmul        dword ptr [edi+eax*4+8]  
faddp       st(1),st</code></p>
<p>こちらは単なる浮動小数点数向けの命令で、1度に1データずつ掛けて、足してを行っています。</p>
<h2>並列化の結果</h2>
<p>最後に、これらの並列化でどのくらいの高速化を図れるかを示しておきます。</p>
<p><code>Task</code>も<code>Vector</code>も使って、CPU間並列もCPU内並列も使った例も挙げておきます。</p>
<pre class="source" title="マルチスレッド化 ＋ SIMD命令化">
<code><span class="reserved">private</span> <span class="reserved">static</span> <span class="reserved">float</span> MultiThreadVector(<span class="type">Vector4</span>[] vx, <span class="type">Vector4</span>[] vy)
{
    <span class="reserved">var</span> windowSize = N / NumWorkerThread;

    <span class="reserved">var</span> prod = 0f;
    <span class="reserved">var</span> partialProds = <span class="type">Task</span>.WhenAll(
        <span class="type">Enumerable</span>.Range(0, NumWorkerThread)
        .Select(n =&gt; <span class="type">Task</span>.Factory.StartNew(() =&gt;
        {
            <span class="reserved">var</span> local = 0f;
            <span class="reserved">for</span> (<span class="reserved">int</span> i = n * windowSize / 4; i &lt; (n + 1) * windowSize / 4; i++)
                local += <span class="type">Vector4</span>.Dot(vx[i], vy[i]);
            <span class="reserved">return</span> local;
        }))
        ).GetAwaiter().GetResult();
    prod = 0f;
    <span class="reserved">for</span> (<span class="reserved">int</span> i = 0; i &lt; partialProds.Length; i++)
        prod += partialProds[i];
    <span class="reserved">return</span> prod;
}
</code></pre>
<p>計測コードの全体はGistに置いてあります。</p>
<ul>
<li><a href="https://gist.github.com/ufcpp/0f6d1ae24eeaccf522e8130b1915018f">https://gist.github.com/ufcpp/0f6d1ae24eeaccf522e8130b1915018f</a></li>
</ul>
<p>僕の環境(Core i7-4790(4コア8スレッドなCPU)のデスクトップPC)で、それぞれを500回ずつループするのにかかった時間は以下の通りになります(単位は秒)。</p>
<table>
<thead>
<tr>
	<th></th>
	<th>シングルスレッド</th>
	<th>マルチスレッド</th>
</tr>
</thead>
<tbody>
<tr>
	<td>SIMD なし</td>
	<td>2.0295843</td>
	<td>0.9619755</td>
</tr>
<tr>
	<td>SIMD あり</td>
	<td>1.1649900</td>
	<td>0.8847980</td>
</tr>
</tbody>
</table>
<p>ループやスレッド起動のオーバーヘッドなどもあるのできっちりコア数やSIMD並列度分の倍率にはなりませんが、2倍以上には高速化できます。
ループの中身の処理がもう少し大きければ、もうちょっと良い倍率で高速化されるはずです。</p>
 ]]></description>
				<pubDate>Tue, 27 Dec 2016 15:30:32 +0900</pubDate>
			</item>
			<item>
				<title>小ネタ 小さなオブジェクトのスタック割り当て</title>
				<link>http://ufcpp.net/blog/2016/12/tipssmallheapallocation/</link>
				<description><![CDATA[ <p>今回は、C#や.NETの現在ある機能でも、近い将来入りそうな機能でもないんですが、ちょっとした最適化の話。小ネタというか、いつものピックアップRoslynの亜種というか。「Javaでやってるんだし.NETでも」的な要望にし対して、.NETでは事情が変わるよ、というネタ紹介。</p>
<p>小さくて、かつ、短い期間使われないオブジェクトは、たとえ参照型(通常はヒープ上にメモリ確保)であってもスタック上にメモリ確保してはどうかという案があったりします。</p>
<ul>
<li><a href="https://github.com/dotnet/coreclr/issues/1784">CLR/JIT should optimize &quot;alloc temporary small object&quot; to &quot;alloc on stack&quot; automatically #1784</a></li>
</ul>
<p>例えば、以下のようなコードを考えます。非常に小さい型<code>Distance</code>があって、ループの中でそのインスタンスが<code>new</code>されています。</p>
<pre class="source" title="小さいオブジェクトの new">
<code><span class="reserved">using</span> System;
<span class="reserved">using</span> System.Linq;

<span class="comment">// ただの double なんだけど、次元をはっきりさせたいために専用の型を作る的なやつ</span>
<span class="reserved">class</span> <span class="type">Distance</span>
{
    <span class="reserved">public</span> <span class="reserved">double</span> Value { <span class="reserved">get</span>; }
    <span class="reserved">public</span> Distance(<span class="reserved">double</span> value) { Value = value; }
}

<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> Main()
    {
        <span class="reserved">var</span> r = <span class="reserved">new</span> <span class="type">Random</span>();
        <span class="reserved">var</span> segments = <span class="type">Enumerable</span>.Range(0, 1000).Select(_ =&gt; <span class="reserved">new</span> <span class="type">Distance</span>(r.NextDouble())).ToArray();

        <span class="reserved">var</span> sum = <span class="reserved">new</span> <span class="type">Distance</span>(0);
        <span class="reserved">foreach</span> (<span class="reserved">var</span> s <span class="reserved">in</span> segments)
        {
            <span class="comment">// ループの中で new されるのがまずい。</span>
            <span class="comment">// ヒープ確保が頻繁すぎる。</span>
            sum = <span class="reserved">new</span> <span class="type">Distance</span>(sum.Value + s.Value);
        }

        <span class="type">Console</span>.WriteLine(<span class="string">$"</span>{sum.Value}<span class="string">"</span>);
    }
}
</code></pre>
<p>Javaでは起こりうる問題で、この、ループの中の<code>new</code>で、オブジェクトをヒープではなくスタック上に確保できれば結構なパフォーマンス改善が見込めます。で、そのためコード解析手法(Escape Analysisと言います)は論文になっているし、実際、Java 6で採用されているみたいです。</p>
<ul>
<li>Java HotSpot™ Virtual Machine Performance Enhancements: <a href="https://docs.oracle.com/javase/8/docs/technotes/guides/vm/performance-enhancements-7.html#escapeAnalysis">Escape Analysis</a></li>
</ul>
<p>ということで、この最適化は.NETでも有効かどうか。</p>
<p>とりあえず、coreclrチームの中の人曰く「気づいているし、議論もしている。real-worldな事例を挙げてもらえると優先度が上がるかも。人工的なサンプルであれば持っている。」だそうです。</p>
<p>まあ、.NETだとそんな頑張らなくても簡単な回避策があるんで。上記の例で言うと、<code>Distance</code>クラスを構造体に変えるだけ。小さくて、かつ、短い期間しか使われないものは構造体にしますからね、最初から。なので、よっぽど大きなインパクトがあるreal-world事例がないと動いてもらえないかも、という感じです。</p>
<p>一応、上記提案ページで挙がった「事例」だと、以下のようなものがあります。</p>
<ol>
<li>enumerator (主にLINQ)</li>
<li>文字列処理</li>
<li>immutableデータの構築</li>
<li><code>new FileInfo(path).Exists</code>みたいなの</li>
</ol>
<p>どうかなぁ…これ…</p>
<p>1のLINQに関しては、そもそもEscape Analysisの対象にできないみたいです。メソッドをまたぐとダメ。インライン展開が掛からない限りは解析できないそうですが、LINQはインライン展開される類の処理ではないので無理。</p>
<p>2の文字列処理に関しては、<a href="https://github.com/dotnet/corefxlab/tree/master/src/System.Text.Primitives/System/Text/Encoding/Utf8"><code>Utf8String</code></a>のような、低アロケーションな文字列型が開発中で、これが入れば負担が激減するかもしれません。
現状の<code>string</code>型に対しては効き目があっても、将来的には要らなかったということになる可能性が高いです。</p>
<p>3は、多くが「構造体にすれば解決」になる気もします。</p>
<p>ってことで、この事例の中だと4くらいですかね、効き目がありそうなのは。
Escape Analysisをするにもオーバーヘッドは結構あるわけで、ちょっとメリットを得にくそう。</p>
 ]]></description>
				<pubDate>Mon, 26 Dec 2016 00:21:00 +0900</pubDate>
			</item>
			<item>
				<title>discards</title>
				<link>http://ufcpp.net/blog/2016/12/discards/</link>
				<description><![CDATA[ <p>書いた。</p>
<ul>
<li><a href="http://ufcpp.net/study/csharp/datatype/declarationexpressions/">変数宣言式</a></li>
</ul>
<p>ということで、今日も「小ネタ」休みで「C#7思い出話」の方を書くことにします。</p>
<h2>このページのタイトル</h2>
<p>このページのタイトルはかなり悩んだ…
実質的にはdiscards(<code>_</code>を使った値の破棄)の話なんですけども。
discards単体だと入れる場所に悩み。</p>
<p>discardsを書ける場所はどこかと考えたら、「変数宣言する場所」なんですよね。
で、「将来的には変数宣言式になるはずだし…」とか、
「というかむしろ、先にアイディアがあったのは変数宣言式で、それを細切れで実装することになったのがC# 7の今の姿だし…」とか、
「とはいえ、C# 7ではまだ入らない機能をタイトルにつける？…」とか、
悩みましたが最終的にはこの構成になりました。</p>
<h2>RCから変更ないといったな</h2>
<p><a href="http://ufcpp.net/blog/2016/12/vs2017rc2/">14日のブログで書いていますが</a>。</p>
<p>11月のリリース候補版の時点でC# 7の全機能そろったといったな。あれは嘘だ。</p>
<p>今のC#って結構、「パターン マッチングという大きな目標を少しずつ実装していってる」って感じなんですが、
そこで迷うのが「どこまでをC# 7としてリリースするのか」という区切り。
当初は、C# 7に入ると言っていた機能、もっと少なかったんですよね。
気が付いたらだいぶ「あっ、それもC# 7に入れてくれるんだ！」みたいな感じに。</p>
<p>なんか、Visual Studio 2017自体、リリース スケジュールが伸びてる感じがするなぁ(あくまで個人の感想です)。
遅れる原因になりそうなものというと、主に.NET Coreがらみのツール類がネックになっていそうな予感がちらほら。</p>
<p>そして、最後の最後まで「まだ未定」になってたのがこのdiscards。
まあ、「既存コードの破壊的変更になりかねない機能」ではあったんで、最後の最後まで悩んだんじゃないかと思います。</p>
<h2>wildcards から discards に</h2>
<p>なんか、最近名前が変わったんですよね、こいつ。</p>
<p>元々の呼び名は、「どんなパターンにでもマッチするもの」という意味でwildcards(万能札)でした。
関数型言語なんかでは、この何にでもマッチするものを「ワイルドカード パターン」とか呼んでいるので、そこから来ています。
でも、万能と言いつつ、C# 7のやつは<code>(int x, int _) = tuple;</code>みたいな書き方ができます。
<code>int</code>型しか受け付けない、ただ単に値を無視したいだけの<code>_</code>なわけです。
全然ワイルドじゃない。</p>
<p>ってことで、なんかこじゃれたアイディアが降りてきたのがdiscards(破棄)。
discardsって、破棄の他にカード ゲーム用語で「捨て札」の意味があります。
というか、cardってついてることからわかる通り、むしろそっちが原義。
wildcardsからdiscardsへの、カード ゲーム用語由来の単語同士だし、
語感も似ててなんかよさそう！
みたいな感じで気が付いたら呼び名が変わっていました。</p>
<h2>* から _ に</h2>
<p>discards用にどの記号を使うかも結構最近まで悩んでたんですよね。
最終決定したのは、以下のブログを書いた頃。</p>
<ul>
<li><a href="http://ufcpp.net/blog/2016/10/pickuproslyn1030/">ピックアップRoslyn 10/30</a></li>
</ul>
<p>このブログでも書いている通り、<code>*</code>か<code>?</code>か、それとも<code>_</code>にするかで悩んでいました。</p>
<p>そのリンク先の<a href="https://github.com/dotnet/roslyn/issues/14794">デザイン ミーティング議事録</a>によれば、
決定したのは10月25日。
Visual Studio 2017のリリース候補版が出たのが11月16日なので、その高々2・3週間前にそういう決定しますか…
という感じで。</p>
<p>まあ、間違いなくC# 7で一番の難産機能。
なので、個人的にはもしかしたらC# 7に入らないかなぁとか思ってたんですけどね。
なんとか間に合うようです。</p>
 ]]></description>
				<pubDate>Sun, 25 Dec 2016 16:46:56 +0900</pubDate>
			</item>
			<item>
				<title>小ネタ Concurrent コレクション</title>
				<link>http://ufcpp.net/blog/2016/12/tipsconcurrentcollections/</link>
				<description><![CDATA[ <p>.NET 4以来、<a href="https://msdn.microsoft.com/ja-jp/library/system.collections.concurrent.aspx"><code>System.Collections.Concurrent</code></a>以下に、
Concurrentなコレクションがいくつか追加されました。</p>
<p>Concurrent、英単語の意味としては「同時に起こる」という意味の形容詞。
プログラミングにおいては、「複数のプログラムやスレッドから同時にアクセスされる」という意味で使われ、
「並行」とか「同時実行」とか訳されます。
たいてい、「Concurrentなんとか」みたいな名前のものは「同時実行があっても問題が起きない」という意味になります。</p>
<p>ただし、「問題を起こさない」って言ってもいろいろな意味があって、それぞれのコレクションの性質をちゃんとわかっておかないと困ったりします。
(.NET の<code>System.Collections.Concurrent</code>に限らず、たいていのプログラミング言語のたいていのライブラリで、Concurrentと名の付くものは同様の注意が必要です。)</p>
<p>ということで、今日は<a href="https://msdn.microsoft.com/ja-jp/library/dd287191.aspx"><code>ConcurrentDictionary</code></a>の<code>GetOrAdd</code>メソッドを例にとって挙動をちょっと説明。</p>
<h2>GetOrAdd</h2>
<p>こいつ: <a href="https://msdn.microsoft.com/ja-jp/library/ee378677.aspx"><code>GetOrAdd(TKey key, Func&lt;TKey, TValue&gt; valueFactory)</code></a></p>
<p>名前通り、キーに応じた値がすでにあればその値を返し、なければ <code>valueFactory</code> を呼んで、新しい値を作って辞書に登録しつつ、その作った値を返します。</p>
<p>話を簡単にするために、まずちょっと、同時実行が必要ない状況で例を出しますが、以下のような挙動になります。</p>
<pre class="source" title="GetOrAdd: 同時実行がない場合">
<code><span class="reserved">using</span> System;
<span class="reserved">using</span> System.Collections.Concurrent;

<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> Main(<span class="reserved">string</span>[] args)
    {
        <span class="reserved">const</span> <span class="reserved">int</span> theKey = 1;
        <span class="reserved">var</span> d = <span class="reserved">new</span> <span class="type">ConcurrentDictionary</span>&lt;<span class="reserved">int</span>, <span class="reserved">string</span>&gt;();

        <span class="comment">// まず、GetOrAdd の同時実行が起こらない場合を見てみる</span>
        <span class="comment">// 普通の逐次実行なので、同時実行にはならない</span>
        <span class="reserved">for</span> (<span class="reserved">int</span> i = 0; i &lt; 4; i++)
        {
            <span class="reserved">var</span> item = d.GetOrAdd(theKey, key =&gt;
            {
                <span class="comment">// インスタンス新規作成</span>
                <span class="comment">// 単一のキーでアクセスしているので1回限り</span>
                <span class="type">Console</span>.WriteLine(<span class="string">$"Add: </span>{i}<span class="string">"</span>);
                <span class="reserved">return</span> i.ToString();
            });

            <span class="comment">// 同じインスタンスが返ってきているか確認</span>
            <span class="type">Console</span>.WriteLine(<span class="string">$"Get: </span>{item}<span class="string">"</span>);
        }
    }
}
</code></pre>
<pre class="source" title="実行結果">
<code>Add: 0
Get: 0
Get: 0
Get: 0
Get: 0
</code></pre>
<p>この例では、同じキーで何度も <code>GetOrAdd</code> を呼んでいます。
値の生成(<code>$&quot;Add: {i}&quot;</code>と表示される部分)は最初の1回でしか通りません。</p>
<h2>並列動作</h2>
<p>この<code>for</code>ループを並列化することを考えます。</p>
<h3>ConcurrentDictionary の必要性</h3>
<p>単に同時実行で問題を起こさないようにするなら、わざわざ<code>ConcurrentDictionary</code>なんていう新しいクラスを作らなくても、
<code>lock</code>ステートメントを掛ければ済む話です。</p>
<p>Concurrentを名乗らない普通の<code>Dictionary</code>を使って、
自前で<code>lock</code>を掛けるのであれば、例えば以下のように書けばいいでしょう。</p>
<pre class="source" title="Dictionaryに対して自前でlockを掛ける GetOrAdd 実装">
<code><span class="reserved">static</span> <span class="reserved">class</span> <span class="type">DictionaryExtensions</span>
{
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="type">TValue</span> GetOrAdd&lt;<span class="type">TKey</span>, <span class="type">TValue</span>&gt;(<span class="reserved">this</span> <span class="type">IDictionary</span>&lt;<span class="type">TKey</span>, <span class="type">TValue</span>&gt; d, <span class="type">TKey</span> key, <span class="type">Func</span>&lt;<span class="type">TKey</span>, <span class="type">TValue</span>&gt; valueFactory)
    {
        <span class="reserved">lock</span> (d)
        {
            <span class="type">TValue</span> value;
            <span class="reserved">if</span> (!d.TryGetValue(key, <span class="reserved">out</span> value))
            {
                value = valueFactory(key);
                d[key] = value;
            }
            <span class="reserved">return</span> value;
        }
    }
}
</code></pre>
<p>このコードの何が嫌かというと、<code>lock</code>範囲が広すぎること。</p>
<ul>
<li>Getにも<code>lock</code>が掛かる。新規追加(Add)の頻度が低い時に完全に無駄</li>
<li>Add のときに、<code>valueFactory</code>呼び出し中にもずっと<code>lock</code>が掛かっていて、<code>valueFactory</code>の中身次第では<code>lock</code>時間が長くなりすぎる</li>
</ul>
<p><code>lock</code>は、意外と重たい処理です。可能な限り避けて、可能な限り短くする必要があります。</p>
<p><code>ConcurrentDictionary</code>は、<code>lock</code>範囲を極力小さくすることで、パフォーマンス向上を図っているクラスです。</p>
<h3>ConcurrentDictionaryの癖</h3>
<p>ただし、<code>ConcurrentDictionary</code>の<code>GetOrAdd</code>には少々癖があります。</p>
<p><a href="https://msdn.microsoft.com/ja-jp/library/ee378677.aspx">ドキュメント</a>をちゃんと読むと書いてあるんですが、</p>
<ul>
<li><code>valueFactory</code>は複数回呼ばれる可能性があります</li>
<li>返す値・辞書内に格納する値は必ず1つであることが保証されています</li>
</ul>
<p>という挙動。</p>
<p>その結果、最初にあげた例で、<code>for</code>ループを<code>Parallel.For</code>に変えて並列化すると、以下のような挙動をします。</p>
<pre class="source" title="GetOrAdd: 同時実行する場合">
<code><span class="reserved">using</span> System;
<span class="reserved">using</span> System.Collections.Concurrent;
<span class="reserved">using</span> System.Threading.Tasks;

<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> Main(<span class="reserved">string</span>[] args)
    {
        <span class="reserved">const</span> <span class="reserved">int</span> theKey = 1;
        <span class="reserved">var</span> d = <span class="reserved">new</span> <span class="type">ConcurrentDictionary</span>&lt;<span class="reserved">int</span>, <span class="reserved">string</span>&gt;();

        <span class="comment">// 並列動作</span>
        <span class="comment">// 並列なので、ループの中身が複数のスレッドで同時に動くことがある</span>
        <span class="type">Parallel</span>.For(0, 4, i =&gt;
        {
            <span class="reserved">var</span> item = d.GetOrAdd(theKey, key =&gt;
            {
                <span class="comment">// 同時に来られると、ここは複数回動く可能性がある</span>
                <span class="type">Console</span>.WriteLine(<span class="string">$"Add: </span>{i}<span class="string">"</span>);
                <span class="reserved">return</span> i.ToString();
            });

            <span class="comment">// Add が複数回動いても、Get で帰ってくる値は必ず単一の保証あり</span>
            <span class="type">Console</span>.WriteLine(<span class="string">$"Get: </span>{item}<span class="string">"</span>);
        });
    }
}
</code></pre>
<p>実行する環境によって/実行するたびに結果は異なりますが、一例としては以下のような実行結果になります。</p>
<pre class="source" title="実行結果">
<code>Add: 0
Add: 3
Get: 0
Add: 1
Get: 0
Add: 2
Get: 0
Get: 0
</code></pre>
<p>(この環境では)Addは4回動いています。
しかし、戻り値として返っているのはそのうち1つだけで、Getのところに表示されている値は全部同じです。</p>
<h3>癖の回避: Lazyとの組み合わせ</h3>
<p><code>lock</code>を減らすためとはいえ、ちょっと癖のある挙動です。この癖を回避したければ一工夫要ります。
その工夫として、別途、<a href="https://msdn.microsoft.com/ja-jp/library/dd642331.aspx"><code>Lazy</code>クラス</a>(<code>System</code>名前空間)と組み合わせる方法があります。</p>
<p>以下のような書き方をします。</p>
<pre class="source" title="ConcurrentDictionary と Lazy の併用">
<code><span class="reserved">using</span> System;
<span class="reserved">using</span> System.Collections.Concurrent;
<span class="reserved">using</span> System.Threading.Tasks;

<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> Main(<span class="reserved">string</span>[] args)
    {
        <span class="reserved">const</span> <span class="reserved">int</span> theKey = 1;
        <span class="reserved">var</span> d = <span class="reserved">new</span> <span class="type">ConcurrentDictionary</span>&lt;<span class="reserved">int</span>, <span class="type">Lazy</span>&lt;<span class="reserved">string</span>&gt;&gt;(); <span class="comment">// 値を Lazy&lt;string&gt; に変える</span>

        <span class="comment">// 並列動作</span>
        <span class="comment">// 並列なので、ループの中身が複数のスレッドで同時に動くことがある</span>
        <span class="type">Parallel</span>.For(0, 4, i =&gt;
        {
            <span class="reserved">var</span> lazy = d.GetOrAdd(theKey, key =&gt; <span class="reserved">new</span> <span class="type">Lazy</span>&lt;<span class="reserved">string</span>&gt;(() =&gt;
            {
                <span class="comment">// 複数個の Lazy インスタンスが作られることはあるけども、</span>
                <span class="comment">// Lazy が作られただけでは valueFactory は呼ばれない</span>
                <span class="type">Console</span>.WriteLine(<span class="string">$"Add: </span>{i}<span class="string">"</span>);
                <span class="reserved">return</span> i.ToString();
            }));

            <span class="comment">// lazy 自体は単一のインスタンスが返る保証あり</span>

            <span class="comment">// この時点で初めて Add: の行が呼ばれる</span>
            <span class="comment">// Lazy のデフォルトの挙動では、valueFactory が呼ばれるのは1回限りの保証あり</span>
            <span class="reserved">var</span> item = lazy.Value;

            <span class="type">Console</span>.WriteLine(<span class="string">$"Get: </span>{item}<span class="string">"</span>);
        });
    }
}
</code></pre>
<p>結果は以下のようになります。</p>
<pre class="source" title="実行結果">
<code>Add: 0
Get: 0
Get: 0
Get: 0
Get: 0
</code></pre>
<p>値は0である保証はなくて、<code>Add: 1</code>とか<code>Add: 2</code>が表示されることもありますが、少なくとも</p>
<ul>
<li><code>Add:</code>の行が表示されるのは1回限り</li>
<li><code>Add:</code>の行と<code>Get:</code>の行で表示されている値は同じ</li>
</ul>
<p>という保証はされています。</p>
<p>これで、<code>GetOrAdd</code>全体を<code>lock</code>するよりはだいぶパフォーマンスのよいコードになります。
特に、Addがほとんどなく、Get頻度が高い場合にはかなり顕著な差になるでしょう。</p>
 ]]></description>
				<pubDate>Sat, 24 Dec 2016 00:23:54 +0900</pubDate>
			</item>
			<item>
				<title>小ネタ C# と他の言語との差というと</title>
				<link>http://ufcpp.net/blog/2016/12/tipsotherlangs/</link>
				<description><![CDATA[ <p>C#で、「他の言語との差というと」とか「他の言語から来たばかりの人が書きがちなコード」みたいなことを聞かれた場合、まず何が思い浮かぶでしょう。</p>
<p>C#に馴れちゃってる人だと、LINQとかasync/awaitとかの機能が最初に浮かんだりします。でも、この辺りは「大きな機能」過ぎて、知ってるか知らないかの二択、1度知れば検索してすぐに解説が出てくる類で、かえって問題にならないという印象。
案外、困るのはもうちょっと細かい部分じゃないかと思います。</p>
<p>みたいなのが今日の話題。</p>
<h2>辞書(ハッシュテーブル)の列挙</h2>
<p><code>Dictionary&lt;TKey, TValue&gt;</code>の列挙を、キーも値も両方使うのに、<code>Keys</code>を使ってやろうとする人が結構いるらしいという話を聞きます。要するに以下のような書き方。</p>
<pre class="source" title="C#っぽくない書き方">
<code><span class="reserved">using</span> System;
<span class="reserved">using</span> System.Collections.Generic;

<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> Main()
    {
        <span class="reserved">var</span> dic = <span class="reserved">new</span> <span class="type">Dictionary</span>&lt;<span class="reserved">string</span>, <span class="reserved">int</span>&gt;
        {
            { <span class="string">"one"</span>, 1 },
            { <span class="string">"two"</span>, 2 },
            { <span class="string">"three"</span>, 3 },
        };

        <span class="reserved">foreach</span> (<span class="reserved">var</span> key <span class="reserved">in</span> <em>dic.Keys</em>)
        {
            <em><span class="reserved">var</span> value = dic[key];</em>
            <span class="type">Console</span>.WriteLine(<span class="string">$"</span>{key}<span class="string"> =&gt; </span>{value}<span class="string">"</span>);
        }
    }
}
</code></pre>
<p>C#の<code>Dictionary</code>はキーと値をまとめて列挙できる(<code>IDictionary&lt;TKey, TValue&gt;</code>インターフェイスが<code>IEnumerable&lt;KeyValuePair&lt;TKey, TValue&gt;&gt;</code>インターフェイスから派生している)ので、以下のように書けます。</p>
<pre class="source" title="C#の書き方">
<code>        <span class="reserved">foreach</span> (<span class="reserved">var</span> x <span class="reserved">in</span> dic)
        {
            <span class="type">Console</span>.WriteLine(<span class="string">$"</span>{x.Key}<span class="string"> =&gt; </span>{x.Value}<span class="string">"</span>);
        }
</code></pre>
<p>得られる結果が一緒だからどちらでもいいと思うかもしれないですけど、パフォーマンスが結構違います。この手のコレクション(他の言語で言うところの<code>map</code>とか<code>Hashtable</code>)のインデクサー アクセスはそこそこなコストです。
この例みたいなのだと、<code>Dictionary</code>内の要素の数にもよりますが、前者の<code>Keys</code>越しの方が2～3倍くらい遅いです。</p>
<h2>文字列中の文字の列挙</h2>
<p><code>string</code>が<code>IEnumerable&lt;char&gt;</code>なのも案外気付いていない人がいるとか。</p>
<pre class="source" title="C#っぽくない書き方">
<code><span class="reserved">var</span> s = <span class="string">"aáαあ亜😀"</span>;

<span class="reserved">for</span> (<span class="reserved">int</span> i = 0; i &lt; s.Length; i++)
{
    <span class="reserved">var</span> c = s[i];
    <span class="type">Console</span>.WriteLine(c);
}
</code></pre>
<p>C#だと大体は<code>foreach</code>で列挙します。</p>
<pre class="source" title="C#の書き方">
<code><span class="reserved">foreach</span> (<span class="reserved">var</span> c <span class="reserved">in</span> s)
{
    <span class="type">Console</span>.WriteLine(c);
}
</code></pre>
<p>というか、<a href="http://www.buildinsider.net/language/csharpunicode/01">文字列からインデックス使って「N文字目」を取れると思うなよ</a>。</p>
<p>上記の例でも、<code>foreach</code>の書き方含め、絵文字が2文字に割れちゃって正しく文字コードを取れません。
C#で正しくサロゲートペアを正しく扱うのはいまだにちょっと面倒なんですが…
いずれ、以下のように書けるようになるはずです。</p>
<pre class="source" title="Utf8String">
<code><span class="reserved">using</span> System;
<span class="reserved">using</span> System.Text.Utf8;

<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> Main()
    {
        <span class="reserved">var</span> si = <span class="reserved">new</span> <span class="type">Utf8String</span>(<span class="string">"aáαあ亜😀"</span>);

        <span class="reserved">foreach</span> (<span class="reserved">var</span> c <span class="reserved">in</span> si.CodePoints)
        {
            <span class="type">Console</span>.WriteLine(c);
        }
    }
}
</code></pre>
<p>逆に、この<code>Utf8String</code>からは、インデックスを使って「N文字目」を取る手段はなくなっています。</p>
<h2><code>Format(&quot;{0} {0}&quot;, x)</code></h2>
<p>C# 6で<a href="http://ufcpp.net/study/csharp/st_string.html?sec=string-interpolation#string-interpolation">interpolation</a>が入った今、あんまり使うものではなくなりましたが、<code>string.Format</code>の呼び方に関して。</p>
<p>interpolation でも書けない書き方なんですけども、以下のように、同じインデックスを複数回使う書き方ができたりします。</p>
<pre class="source" title="C#の書き方">
<code><span class="type">Console</span>.WriteLine(<span class="string">"({0} + {1}) × ({0} - {1}) = {0}^2 - {1}^2"</span>, <span class="string">"x"</span>, <span class="string">"y"</span>);
<span class="comment">// (x + y) × (x - y) = x^2 - y^2</span>
</code></pre>
<p>わざわざ、以下のような書き方をしてしまう人をちらほら見かけるとか</p>
<pre class="source" title="C#っぽくない書き方">
<code><span class="type">Console</span>.WriteLine(<span class="string">"({0} + {1}) × ({2} - {3}) = {4}^2 - {5}^2"</span>, <span class="string">"x"</span>, <span class="string">"y"</span>, <span class="string">"x"</span>, <span class="string">"y"</span>, <span class="string">"x"</span>, <span class="string">"y"</span>);
</code></pre>
<p><code>printf</code>だとこんな感じで書いてましたもんね…</p>
<h2>文字列の <code>+</code> 演算</h2>
<p>以下のようなコードをC#で書くと、結果はどうなるでしょう。</p>
<pre class="source" title="問題">
<code><span class="reserved">string</span> s1 = <span class="string">"abc"</span>;
<span class="reserved">object</span> s2 = <span class="reserved">null</span>;
<span class="type">Console</span>.WriteLine(s1 + s2);
</code></pre>
<p>選択肢:</p>
<ol>
<li>ぬるぽ(<code>NullReferenceException</code>発生)</li>
<li><code>abc</code>が表示される</li>
<li><code>abcnull</code>が表示される</li>
</ol>
<p>答えは2番です。C#で、nullを文字列連結すると、空文字扱いになります。</p>
<p>Javaは3番になるんでしたっけ？nullが<code>&quot;null&quot;</code>に化けるっていう。</p>
<p>言われてみると、言語ごとに挙動が微妙に違ってちょっとめんどくさいですね、これ。</p>
<p>どっちもどっちというか、文字列連結に<code>+</code>演算子を使うって発想がまず、本当によかったのかどうかという疑問があります…</p>
<p>C#文化では、ガイドラインとして「演算子は、組み込み型のものと全然違う用途でオーバーロードするな」というものがあります。
となると、「組み込み型の<code>+</code>は足し算だろ、足し算として使えよ」と言われても仕方がなく。
「文字列連結は足し算といえるか」という命題ではあるんですが。
連結の結果、文字列長が足し算になるので足し算的な何かと言えなくもないですけど、きわどい。</p>
<p>ストリームの読み書きにシフト演算子(<code>&lt;&lt;</code>)を使われるよりは幾分かマシですけど、
文字列に対する<code>+</code>もやめといた方がよかったんじゃないかなぁ…
「顧客が本当に欲しかったものは<a href="http://ufcpp.net/study/csharp/st_string.html?sec=string-interpolation#string-interpolation">interpolation</a>だった」説もありますし。</p>
<h2><code>if (x)</code></h2>
<p>これはC言語方面から来た人がたまーにやらかして、ほんとみんな迷惑するやつなんですが…
<code>operator true</code>とかに変な実装を入れてしまうことがあります。</p>
<p>やらかす人は「<a href="http://ufcpp.net/blog/2016/12/tipsnulloperation/">null関係の演算子</a>」の回で話した 「nullじゃないのに<code>x == null</code>がtrueになる」っていうコードとセットでやらかすんですが…</p>
<p>以下のようなコード。</p>
<pre class="source" title="C#っぽくない書き方">
<code><span class="reserved">class</span> <span class="type">MyObject</span> : <span class="type">IDisposable</span>
{
    <span class="reserved">bool</span> _isDisposed;

    <span class="reserved">public</span> <span class="reserved">void</span> Dispose()
    {
        <span class="comment">// Dispose 後、もうこのオブジェクトは無効</span>
        _isDisposed = <span class="reserved">true</span>;
    }

    <span class="comment">// 無効だったら if (x) { } で {} の中を通らなくする</span>
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">bool</span> <span class="reserved">operator</span> <span class="reserved">true</span>(<span class="type">MyObject</span> obj) =&gt; !obj._isDisposed;
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">bool</span> <span class="reserved">operator</span> <span class="reserved">false</span>(<span class="type">MyObject</span> obj) =&gt; obj._isDisposed;
}
</code></pre>
<p>使う側は以下のような感じ。</p>
<pre class="source" title="C#っぽくない書き方">
<code><span class="reserved">static</span> <span class="reserved">void</span> M(<span class="type">MyObject</span> obj)
{
    <span class="type">Console</span>.WriteLine(<span class="string">"----"</span>);
    <span class="reserved">if</span> (obj) <span class="type">Console</span>.WriteLine(<span class="string">"有効"</span>);
}
</code></pre>
<p>C言語だと<code>if (x)</code>って結構書いてたましたもんね…
<code>bool</code>って概念を持っていなくて、0以外の値は全てtrue扱い(nullは0)で。
間違えて意図しない条件を<code>if</code>の中に書いてしまうので良くないと言われています。</p>
<p>良くないから、C#ではわざわざ書けなくしたものでして…
それをぶり返すような<code>operator</code>を書かれると結構困惑します。</p>
 ]]></description>
				<pubDate>Fri, 23 Dec 2016 15:19:37 +0900</pubDate>
			</item>
			<item>
				<title>小ネタ 引数の個数の上限</title>
				<link>http://ufcpp.net/blog/2016/12/tipsnumargs/</link>
				<description><![CDATA[ <p>引数の個数に制限があること、ご存じでしょうか。 むやみに多くても実装上の無駄が大きかったりしますし、上限が決まっていたりします。</p>
<p>C#は意外と大きくて、最大で65536個まで行けます。要するに2バイト分。
ということで、以下のC#コードはコンパイル可能です。
1バイトで収まらない、0～256までの257個の引数。</p>
<pre class="source" title="257個の引数">
<code><span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> M(
<span class="reserved">int</span> x0, <span class="reserved">int</span> x1, <span class="reserved">int</span> x2, <span class="reserved">int</span> x3, <span class="reserved">int</span> x4, <span class="reserved">int</span> x5, <span class="reserved">int</span> x6, <span class="reserved">int</span> x7, <span class="reserved">int</span> x8, <span class="reserved">int</span> x9, <span class="reserved">int</span> x10, <span class="reserved">int</span> x11, <span class="reserved">int</span> x12, <span class="reserved">int</span> x13, <span class="reserved">int</span> x14, <span class="reserved">int</span> x15,
<span class="reserved">int</span> x16, <span class="reserved">int</span> x17, <span class="reserved">int</span> x18, <span class="reserved">int</span> x19, <span class="reserved">int</span> x20, <span class="reserved">int</span> x21, <span class="reserved">int</span> x22, <span class="reserved">int</span> x23, <span class="reserved">int</span> x24, <span class="reserved">int</span> x25, <span class="reserved">int</span> x26, <span class="reserved">int</span> x27, <span class="reserved">int</span> x28, <span class="reserved">int</span> x29, <span class="reserved">int</span> x30, <span class="reserved">int</span> x31,
<span class="reserved">int</span> x32, <span class="reserved">int</span> x33, <span class="reserved">int</span> x34, <span class="reserved">int</span> x35, <span class="reserved">int</span> x36, <span class="reserved">int</span> x37, <span class="reserved">int</span> x38, <span class="reserved">int</span> x39, <span class="reserved">int</span> x40, <span class="reserved">int</span> x41, <span class="reserved">int</span> x42, <span class="reserved">int</span> x43, <span class="reserved">int</span> x44, <span class="reserved">int</span> x45, <span class="reserved">int</span> x46, <span class="reserved">int</span> x47,
<span class="reserved">int</span> x48, <span class="reserved">int</span> x49, <span class="reserved">int</span> x50, <span class="reserved">int</span> x51, <span class="reserved">int</span> x52, <span class="reserved">int</span> x53, <span class="reserved">int</span> x54, <span class="reserved">int</span> x55, <span class="reserved">int</span> x56, <span class="reserved">int</span> x57, <span class="reserved">int</span> x58, <span class="reserved">int</span> x59, <span class="reserved">int</span> x60, <span class="reserved">int</span> x61, <span class="reserved">int</span> x62, <span class="reserved">int</span> x63,
<span class="reserved">int</span> x64, <span class="reserved">int</span> x65, <span class="reserved">int</span> x66, <span class="reserved">int</span> x67, <span class="reserved">int</span> x68, <span class="reserved">int</span> x69, <span class="reserved">int</span> x70, <span class="reserved">int</span> x71, <span class="reserved">int</span> x72, <span class="reserved">int</span> x73, <span class="reserved">int</span> x74, <span class="reserved">int</span> x75, <span class="reserved">int</span> x76, <span class="reserved">int</span> x77, <span class="reserved">int</span> x78, <span class="reserved">int</span> x79,
<span class="reserved">int</span> x80, <span class="reserved">int</span> x81, <span class="reserved">int</span> x82, <span class="reserved">int</span> x83, <span class="reserved">int</span> x84, <span class="reserved">int</span> x85, <span class="reserved">int</span> x86, <span class="reserved">int</span> x87, <span class="reserved">int</span> x88, <span class="reserved">int</span> x89, <span class="reserved">int</span> x90, <span class="reserved">int</span> x91, <span class="reserved">int</span> x92, <span class="reserved">int</span> x93, <span class="reserved">int</span> x94, <span class="reserved">int</span> x95,
<span class="reserved">int</span> x96, <span class="reserved">int</span> x97, <span class="reserved">int</span> x98, <span class="reserved">int</span> x99, <span class="reserved">int</span> x100, <span class="reserved">int</span> x101, <span class="reserved">int</span> x102, <span class="reserved">int</span> x103, <span class="reserved">int</span> x104, <span class="reserved">int</span> x105, <span class="reserved">int</span> x106, <span class="reserved">int</span> x107, <span class="reserved">int</span> x108, <span class="reserved">int</span> x109, <span class="reserved">int</span> x110, <span class="reserved">int</span> x111,
<span class="reserved">int</span> x112, <span class="reserved">int</span> x113, <span class="reserved">int</span> x114, <span class="reserved">int</span> x115, <span class="reserved">int</span> x116, <span class="reserved">int</span> x117, <span class="reserved">int</span> x118, <span class="reserved">int</span> x119, <span class="reserved">int</span> x120, <span class="reserved">int</span> x121, <span class="reserved">int</span> x122, <span class="reserved">int</span> x123, <span class="reserved">int</span> x124, <span class="reserved">int</span> x125, <span class="reserved">int</span> x126, <span class="reserved">int</span> x127,
<span class="reserved">int</span> x128, <span class="reserved">int</span> x129, <span class="reserved">int</span> x130, <span class="reserved">int</span> x131, <span class="reserved">int</span> x132, <span class="reserved">int</span> x133, <span class="reserved">int</span> x134, <span class="reserved">int</span> x135, <span class="reserved">int</span> x136, <span class="reserved">int</span> x137, <span class="reserved">int</span> x138, <span class="reserved">int</span> x139, <span class="reserved">int</span> x140, <span class="reserved">int</span> x141, <span class="reserved">int</span> x142, <span class="reserved">int</span> x143,
<span class="reserved">int</span> x144, <span class="reserved">int</span> x145, <span class="reserved">int</span> x146, <span class="reserved">int</span> x147, <span class="reserved">int</span> x148, <span class="reserved">int</span> x149, <span class="reserved">int</span> x150, <span class="reserved">int</span> x151, <span class="reserved">int</span> x152, <span class="reserved">int</span> x153, <span class="reserved">int</span> x154, <span class="reserved">int</span> x155, <span class="reserved">int</span> x156, <span class="reserved">int</span> x157, <span class="reserved">int</span> x158, <span class="reserved">int</span> x159,
<span class="reserved">int</span> x160, <span class="reserved">int</span> x161, <span class="reserved">int</span> x162, <span class="reserved">int</span> x163, <span class="reserved">int</span> x164, <span class="reserved">int</span> x165, <span class="reserved">int</span> x166, <span class="reserved">int</span> x167, <span class="reserved">int</span> x168, <span class="reserved">int</span> x169, <span class="reserved">int</span> x170, <span class="reserved">int</span> x171, <span class="reserved">int</span> x172, <span class="reserved">int</span> x173, <span class="reserved">int</span> x174, <span class="reserved">int</span> x175,
<span class="reserved">int</span> x176, <span class="reserved">int</span> x177, <span class="reserved">int</span> x178, <span class="reserved">int</span> x179, <span class="reserved">int</span> x180, <span class="reserved">int</span> x181, <span class="reserved">int</span> x182, <span class="reserved">int</span> x183, <span class="reserved">int</span> x184, <span class="reserved">int</span> x185, <span class="reserved">int</span> x186, <span class="reserved">int</span> x187, <span class="reserved">int</span> x188, <span class="reserved">int</span> x189, <span class="reserved">int</span> x190, <span class="reserved">int</span> x191,
<span class="reserved">int</span> x192, <span class="reserved">int</span> x193, <span class="reserved">int</span> x194, <span class="reserved">int</span> x195, <span class="reserved">int</span> x196, <span class="reserved">int</span> x197, <span class="reserved">int</span> x198, <span class="reserved">int</span> x199, <span class="reserved">int</span> x200, <span class="reserved">int</span> x201, <span class="reserved">int</span> x202, <span class="reserved">int</span> x203, <span class="reserved">int</span> x204, <span class="reserved">int</span> x205, <span class="reserved">int</span> x206, <span class="reserved">int</span> x207,
<span class="reserved">int</span> x208, <span class="reserved">int</span> x209, <span class="reserved">int</span> x210, <span class="reserved">int</span> x211, <span class="reserved">int</span> x212, <span class="reserved">int</span> x213, <span class="reserved">int</span> x214, <span class="reserved">int</span> x215, <span class="reserved">int</span> x216, <span class="reserved">int</span> x217, <span class="reserved">int</span> x218, <span class="reserved">int</span> x219, <span class="reserved">int</span> x220, <span class="reserved">int</span> x221, <span class="reserved">int</span> x222, <span class="reserved">int</span> x223,
<span class="reserved">int</span> x224, <span class="reserved">int</span> x225, <span class="reserved">int</span> x226, <span class="reserved">int</span> x227, <span class="reserved">int</span> x228, <span class="reserved">int</span> x229, <span class="reserved">int</span> x230, <span class="reserved">int</span> x231, <span class="reserved">int</span> x232, <span class="reserved">int</span> x233, <span class="reserved">int</span> x234, <span class="reserved">int</span> x235, <span class="reserved">int</span> x236, <span class="reserved">int</span> x237, <span class="reserved">int</span> x238, <span class="reserved">int</span> x239,
<span class="reserved">int</span> x240, <span class="reserved">int</span> x241, <span class="reserved">int</span> x242, <span class="reserved">int</span> x243, <span class="reserved">int</span> x244, <span class="reserved">int</span> x245, <span class="reserved">int</span> x246, <span class="reserved">int</span> x247, <span class="reserved">int</span> x248, <span class="reserved">int</span> x249, <span class="reserved">int</span> x250, <span class="reserved">int</span> x251, <span class="reserved">int</span> x252, <span class="reserved">int</span> x253, <span class="reserved">int</span> x254, <span class="reserved">int</span> x255,
<span class="reserved">int</span> x256
        )
    { }
}
</code></pre>
<p>確かJavaだと、256個までだったはずです。1バイト分。</p>
<p>こういう制限、Javaや.NETの場合、何によって制約されるかというと、中間コードの命令セットに依ります。例えば、.NETの場合だと、引数参照のために以下のような命令を持っています。</p>
<table>
<thead>
<tr>
	<th>命令</th>
	<th>op code</th>
	<th>概要</th>
	<th>命令サイズ</th>
</tr>
</thead>
<tbody>
<tr>
	<td><code>ldarg.0</code></td>
	<td><code>02</code></td>
	<td>最初の引数をスタックにロードする</td>
	<td>1バイト</td>
</tr>
<tr>
	<td><code>ldarg.1</code></td>
	<td><code>03</code></td>
	<td>2つ目の引数をスタックにロードする</td>
	<td>1バイト</td>
</tr>
<tr>
	<td><code>ldarg.2</code></td>
	<td><code>04</code></td>
	<td>3つ目の引数をスタックにロードする</td>
	<td>1バイト</td>
</tr>
<tr>
	<td><code>ldarg.3</code></td>
	<td><code>05</code></td>
	<td>4つ目の引数をスタックにロードする</td>
	<td>1バイト</td>
</tr>
<tr>
	<td><code>ldarg.s</code></td>
	<td><code>0E &lt;index&gt;</code></td>
	<td>1バイトのオペランドで指定したインデックスの引数をスタックにロードする</td>
	<td>命令1バイト+オペランド1バイト</td>
</tr>
<tr>
	<td><code>ldarg</code></td>
	<td><code>FE 09 &lt;index&gt;</code></td>
	<td>2バイトのオペランドで指定したインデックスの引数をスタックにロードする</td>
	<td>命令2バイト+オペランド2バイト</td>
</tr>
</tbody>
</table>
<p>4つ目の引数まで(0～3番目)なら1バイトで参照できます。
4～255番目までなら2バイト、そして、それ以上になると4バイト必要になります。
というように、オペランドによってプログラム サイズがでかくならないように、よく使うものほど短く、そうでないものほど長くなるように、複数の命令が用意されています。</p>
<p>この場面で効いてくるJavaと.NETの最大の差は、中間コード(Javaの場合はbyte code、.NETの場合はILと呼ばれてるやつ)の命令長の差です。
.NETは可変長になっていて、多くの命令が1バイトですが、いくつか2バイト命令を持っています。
上記の<code>ldarg</code> (2バイト オペランドの方)もその1つで、めったに使わないであろう命令に2バイトのコードを割り当てています。</p>
<p>一方、Javaのbyte codeは1バイト固定長の命令セットになっています。
使える命令は最大で256個ですし、無駄な命令はあまり入れたくありません。</p>
<p>まあ、引数の数が257個以上になるというのはほとんどないでしょう…
と締めたいところですが、ごくまれに、「機械生成で作ったコードで257個超えてJavaでコンパイル エラーになった」なんていう恐ろしいことを言いだす人も見かけるので侮れません。
そういう人が実際にいたから、.NETは<code>ldarg</code>命令を用意したんでしょうかね…</p>
 ]]></description>
				<pubDate>Thu, 22 Dec 2016 15:06:44 +0900</pubDate>
			</item>
			<item>
				<title>小ネタ string型のマーシャリング</title>
				<link>http://ufcpp.net/blog/2016/12/tipsstringmarshal/</link>
				<description><![CDATA[ <p>数値や文字列の内部形式は、プログラミング言語ごとに違っています。プログラミング言語をまたいで値を受け渡しするには、その間に変換処理が必要になります。その変換処理のことをマーシャリング(marshalling: 整列する(特に、指揮官の指示で整列、集結、先導されるような意味あい))と言います。</p>
<h2>無変換転送</h2>
<p>といっても、変換処理はそれなりに重たい処理なので、異なるプログラミング言語間でも揃えられる限りには同じ形式を使って、そのまま値を渡せるようにしたくなるものです。C#では、Windows APIが使っている内部形式と揃えた形式にすることで、マーシャリング時の変換処理を極力減らしていたりします。</p>
<p>数値型は比較的簡単です。何せ、C#が動く環境は大体Little EndianのCPUですし、C#コンパイラーはアラインメントにも気を使った仕様になっていています。この辺りが一致しているなら、たいていの数値型は他のプログラミング言語にそのまま渡すことができます。こういう、そのまま渡せる型のことを<a href="https://msdn.microsoft.com/ja-jp/library/75dwhxf7(v=vs.110).aspx">blittable</a>型というようです(blitはboundary block transferの略語から派生した「生データ転送する」という意味の単語)。</p>
<h2>文字列のマーシャリング</h2>
<p>問題は文字列です。文字列は、数値と同じくらい汎用的に使われるものですが、その内部形式は数値程単純ではありません。文字コードはどうなっているのかや、文字列の長さの管理などが、プログラミング言語ごとに異なります。</p>
<p>で、C#の文字列がどうなっているかというと、<a href="http://www.buildinsider.net/language/csharpunicode/01">Build Insiderの記事</a>で書きましたが、COMの<code>BSTR</code>型互換です。そして、<code>BSTR</code>型も、C言語やC++でよく使われるUTF-16のnull終端文字列互換です。Windows APIはCやC++で書かれていて、たいていがnull終端文字列なので、ネイティブ側がUTF-16 (<code>wchar_t*</code>)を使っている限り、実は、C#側から変換なしで文字列を渡すことができます。</p>
<p>変換なしでというか、ポインターがそのまま渡ります。例えば、以下のようなネイティブ コードがあったとします。受け取った文字列をすべて「a」の文字で上書きしてしまう関数です。</p>
<pre class="source" title="C#から呼び出したいC++コード">
<code><span class="reserved">extern</span> <span class="string">"C"</span>
{
    <span class="comment">// UTF-16 null終端文字列</span>
    <span class="reserved">__declspec</span>(<span class="reserved">dllexport</span>) <span class="reserved">void</span> <span class="reserved">__stdcall</span> FillA16(<span class="reserved">wchar_t</span>* <span class="inactive">str</span>)
    {
        <span class="reserved">for</span> (<span class="reserved">auto</span> p = <span class="inactive">str</span>; *p; p++)
        {
            *p = <span class="string">L'a'</span>;
        }
    }

    <span class="comment">// ANSI null終端文字列</span>
    <span class="reserved">__declspec</span>(<span class="reserved">dllexport</span>) <span class="reserved">void</span> <span class="reserved">__stdcall</span> FillA8(<span class="reserved">char</span>* <span class="inactive">str</span>)
    {
        <span class="reserved">for</span> (<span class="reserved">auto</span> p = <span class="inactive">str</span>; *p; p++)
        {
            *p = <span class="string">'a'</span>;
        }
    }
}
</code></pre>
<p>これを呼び出すC#コードは以下のようになります。</p>
<pre class="source" title="C++コードを呼び出すC#">
<code><span class="reserved">using</span> System;
<span class="reserved">using</span> System.Runtime.InteropServices;

<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="comment">// 対 UTF-16。無変換で(ポインター渡しで)呼び出せる。</span>
    <span class="comment">// CharSetで指定している「Unicode」はUTF-16のこと。</span>
    [<span class="type">DllImport</span>(<span class="string">"Win32Dll.dll"</span>, CharSet = <span class="type">CharSet</span>.Unicode)]
    <span class="reserved">extern</span> <span class="reserved">static</span> <span class="reserved">void</span> FillA16(<span class="reserved">string</span> s);

    <span class="comment">// 対 ASCII。変換が必要。</span>
    [<span class="type">DllImport</span>(<span class="string">"Win32Dll.dll"</span>, CharSet = <span class="type">CharSet</span>.Ansi)]
    <span class="reserved">extern</span> <span class="reserved">static</span> <span class="reserved">void</span> FillA8(<span class="reserved">string</span> s);

    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> Main()
    {
        <span class="type">Console</span>.WriteLine(GetValue());

        <span class="comment">// 変換が必要な方。</span>
        <span class="comment">// コピーが書き換わるだけなので、s1 には影響なし。</span>
        <span class="reserved">var</span> s1 = <span class="string">"awsedrftgyhu"</span>;
        FillA8(s1);
        <span class="type">Console</span>.WriteLine(s1); <span class="comment">// awsedrftgyhu</span>

        <span class="comment">// ポインターで渡る方。</span>
        <span class="comment">// s2 はネイティブ コード側での書き換えの影響を受ける。</span>
        <span class="reserved">var</span> s2 = <span class="string">"awsedrftgyhu"</span>;
        FillA16(s2);
        <span class="type">Console</span>.WriteLine(s2); <span class="comment">// aaaaaaaaaaaa</span>
    }
}
</code></pre>
<p>UTF-16なnull終端文字列に対してC#側から文字列を渡す場合、ポインター渡しになって、ネイティブ コード側での書き換えの影響を受けます。
一方で、相手がANSI文字列(<code>char*</code>)の場合には、変換処理が走って、別途メモリが確保されてコピーするので、C++側で書き換えた結果は元の文字列に影響しません。</p>
<h2>補足: ANSIとUnicode</h2>
<p>ちなみに、Windows的には、ANSI、Unicodeというのは以下の意味です。</p>
<p>ANSI:</p>
<ul>
<li>内部的に<code>char*</code> (C++の1バイト文字列)</li>
<li>ANSIと言いつつ、ASCII互換でロケール依存の文字コードのこと</li>
<li>要するに、日本語Windowsの場合はShift-JIS</li>
</ul>
<p>Unicode:</p>
<ul>
<li>内部的に<code>wchar_t*</code> (C++の2バイト文字列)</li>
<li>UTF-16のこと</li>
<li>昔(サロゲート ペアが生まれるまで)は、Unicode = UTF-16でした</li>
</ul>
 ]]></description>
				<pubDate>Wed, 21 Dec 2016 00:00:16 +0900</pubDate>
			</item>
			<item>
				<title>小ネタ privateメンバーはAPIの一部か</title>
				<link>http://ufcpp.net/blog/2016/12/tipsapisurface/</link>
				<description><![CDATA[ <h2>ことの発端</h2>
<p>なんかぐらばくさんとこので、<a href="https://twitter.com/Grabacr07/status/808972608309866496">エラーになるはずのコードがPCLなプロジェクトでだけビルド通ってしまって問題になってた</a>らしい。</p>
<p>要点を抜き出すと以下のような感じ。</p>
<pre class="source" title="なぜかフィールドの初期化が不要になってしまう例">
<code><span class="reserved">using</span> System;

<span class="reserved">struct</span> <span class="type">DateTimeWrapper</span>
{
    <span class="type">DateTimeOffset</span> t;

    <span class="reserved">public</span> DateTimeWrapper(<span class="reserved">int</span> i)
    {
        <span class="comment">// t を初期化しないとコンパイル エラーになるはず</span>
        <span class="comment">// でも、なぜか PCL プロジェクトではエラーにならない</span>
    }
}
</code></pre>
<p>本来ダメなはずのコードが、PCL プロジェクトでだけコンパイルできてしまうという問題。
「ちゃんと初期化しないと怒られるはず」というのが常識のC#でこれをやられると、ほんと見つけられないバグになったりします。</p>
<p>プロジェクトの種類によって挙動が変わる謎の不具合…</p>
<p>csprojの中身を見てみても、どうも最終的に同じコンパイラーを使っていそう。
軽く<a href="http://forest.watch.impress.co.jp/library/software/prcsxplorer/">Process Explorer</a>を眺めてみても、
ちゃんと同じコンパイラーが動作していそう。
コンパイラーが同じなのに、なぜ同じコードのコンパイル結果が変わってしまうのか、
謎は深まるばかり…</p>
<h2>原因は参照アセンブリ</h2>
<p>で、調べてみたら、どうも、参照しているアセンブリが違うせいみたい。</p>
<ul>
<li><a href="https://github.com/dotnet/corefx/issues/6185">Reference assemblies need to include private struct fields #6185</a></li>
</ul>
<p>ちなみに、再現用のサンプル コード: <a href="https://github.com/ufcpp/UfcppSample/tree/master/Demo/2016/PrivateField">PrivateField</a></p>
<h3>参照アセンブリ</h3>
<p>問題の話をする前にまず簡単に、アセンブリの種類について補足。
今、<a href="https://www.nuget.org/">NuGet</a>とかでライブラリを参照すると、開発時と実行時で別のDLLが参照されたりします。</p>
<ul>
<li>実装アセンブリ: 実際に動くコードが入っているDLL。実行時に参照されるのはこれ。</li>
<li>参照アセンブリ: APIサーフェスだけが入っているDLL。開発時にはこっちが参照される。</li>
</ul>
<p>これは、開発環境と実行環境が違っても問題なく開発できるようにするための処置です。</p>
<p>元々は .NET Framework 3.5の頃に、
クライアント プロファイルっていう、クライアント上では使わない機能を削ったバージョンの .NET Frameworkインストーラーを用意したことが発端で、
「開発環境ではつかえたクラスが、実行に TypeLoadException を起こした」みたいな自体を回避するために作られた仕組みです。
その後、<a href="https://msdn.microsoft.com/ja-jp/library/gg597391(v=vs.100).aspx">PCL</a>でも同様の手法が使われるようになりました。</p>
<p>要するに、</p>
<ul>
<li>実行環境の数だけ、開発環境にも別バージョンの .NET のインストールが必要になる</li>
<li>それをすべてインストーラーに同梱していたらインストーラー サイズが大きくなりすぎる</li>
<li>コンパイルに必要な情報(APIサーフェス)だけ残して、メソッドの中身とかはごっそり削ったバージョンのDLLを用意して、開発環境ではそのDLLを参照する</li>
</ul>
<p>みたいな仕組み。
ここで言うAPIサーフェスっていうのは「APIとして外に公開されている表層の情報」という意味あいです。
見えない部分は削ってしまえと。</p>
<h3>どこまでが API サーフェスか</h3>
<p>ここでちゃんと考えないといけないのが、どこまでを API サーフェスとみなすべきか。
すなわち、「開発時に参照するだけならどこまでの情報を残す必要があって、どこまでを削って大丈夫か」という話です。</p>
<p>publicやprotectedなメンバーはわかりやすくていいでしょう。外から見えるので、当然APIサーフェスに含まれるべきです。</p>
<p>ちょっと微妙なラインがinternalで、本来は外から見えないはずですが、
<a href="https://msdn.microsoft.com/ja-jp/library/bb385840(v=vs.90).aspx"><code>InternalsVisibleTo</code>属性</a>なんてものもあるので、
外から見える可能性が残ります。
なので、APIサーフェスになりえます(<code>InternalsVisibleTo</code>属性があるときだけでいいんですが、参照ライブラリに残す必要があります)。</p>
<p>そして、private。
privateメンバーは、外から参照する手段がありません。
(リフレクションを使うと取れたりはしますけども、コンパイル時には関係ない話です。)
なので、APIサーフェスとはみなされない…
はず…？</p>
<p>と思いきや、privateメンバーがコンパイルに影響する場面が1つだけあります。
それが、構造体のprivateフィールド。</p>
<h3>構造体のprivateフィールド</h3>
<p>いくつか、構造体のprivateフィールドがコンパイル結果に影響を及ぼす例を挙げてみましょう。</p>
<ul>
<li><a href="http://ufcpp.net/study/csharp/resource/rm_struct/#definite-assignment">確実な初期化</a>ルール</li>
<li>ポインター型</li>
<li>再帰レイアウト</li>
</ul>
<h4>確実な初期化</h4>
<p>C#では、構造体のフィールドは、コンストラクター内で必ず初期化しないといけない、初期化するまでは他のメンバーを呼べないという制約があります。
初期化忘れによるバグを防ぐ意図があります。</p>
<p>でも、空っぽの構造体は初期化しなくてもいいらしい。</p>
<pre class="source" title="空っぽの構造体の初期化は不要">
<code><reserved></span><span class="reserved">struct</span> <span class="type">EmptyStruct</span> { }
<span class="reserved">struct</span> <span class="type">Integer</span> { <span class="reserved">private</span> <span class="reserved">int</span> _x; }

<span class="reserved">struct</span> <span class="type">DefiniteAssignement</span>
{
    <span class="type">EmptyStruct</span> _e;
    <span class="type">Integer</span> _i;

    DefiniteAssignement(<span class="reserved">int</span> i)
    {
        <span class="comment">// 中身があるものは初期化必須</span>
        _i = <span class="reserved">new</span> <span class="type">Integer</span>();
        <span class="comment">// 一方で、EmptyStruct みたいに空っぽのものは初期化不要</span>
    }
}
</code></pre>
<p>中身の有無によって挙動が変わります。</p>
<h4>ポインター型</h4>
<p>基本的に、<a href="http://ufcpp.net/study/csharp/rm_gc.html#garbage-collection">GC</a>管理下のオブジェクトのポインターを作るのは危険です。</p>
<p>そこで、C#では以下の条件を満たす型(非管理型(unmanaged type)と呼びます)でだけポインターを作ることを認めています</p>
<ul>
<li>参照型ではない</li>
<li>ジェネリックではない</li>
<li>上記2条件を再帰的に満たす(フィールドに1つ含まない)</li>
</ul>
<p>例えば、もし仮にこの条件を満たさない(GC管理下にある)型のポインターを作れたとします。
そうすると、以下のような問題のあるコードが書けてしまいます。
(そうならないように、赤線の部分をコンパイル エラーにしている。)</p>
<pre class="source" title="managedな型のポインターが作れた場合の問題">
<code><reserved></span><span class="reserved">using</span> System.Runtime.InteropServices;

<span class="comment">// 参照型を含む構造体</span>
<span class="reserved">struct</span> <span class="type">Wrapper</span> { <span class="reserved">object</span> _obj; }

<span class="reserved">class</span> <span class="type">ManagedPointer</span>
{
    <span class="reserved">public</span> <span class="reserved">unsafe</span> <span class="reserved">void</span> X()
    {
        <span class="comment">// Wrapper みたいに内部的に参照型のフィールドを持っている型は、本来はポインター化できない</span>
        <span class="comment">// sizeof 取得も本来はできない</span>

        <span class="comment">// unmanaged なメモリを確保</span>
        <span class="comment">// AllocHGlobal で取得したメモリ領域は初期化されている保証がない</span>
        <span class="comment">// 実行するたびに違う値が入ってる</span>
        <span class="reserved">var</span> p = <span class="type">Marshal</span>.AllocHGlobal(<span class="error"><span class="reserved">sizeof</span>(<span class="type">Wrapper</span>)</span>);
        <span class="type">Wrapper</span> a = *(<span class="error"><span class="type">Wrapper</span>*</span>)p;

        <span class="comment">// ここで GC が発生したとすると、</span>
        <span class="comment">// GC が TaskAwaiter 中の Task のフィールド(未初期化)を参照する</span>
        <span class="comment">// 未初期化(= 意味のないランダムな値)な参照先を見に行こうとして死ぬ</span>

        <span class="type">Marshal</span>.FreeHGlobal(p);
    }
}
</code></pre>
<p>こちらも、メンバーに参照型を含んでいるかどうかを追うのに、構造体の中身を追う必要があります。</p>
<h4>再帰レイアウト</h4>
<p>構造体の中にそれ自身の型のフィールドを持とうとすると、当然ですが無限再帰を起こします。
無限に再帰する構造体のレイアウトなんて決定できない(オーバーフローする)ので、当然禁止事項です。</p>
<pre class="source" title="無限に再帰する構造体レイアウト">
<code><reserved></span><span class="reserved">struct</span> <span class="type">Container</span>&lt;<span class="type">T</span>&gt;
{
    <span class="reserved">public</span> <span class="type">T</span> Item;
}

<span class="reserved">struct</span> <span class="type">RecursiveLayout</span>
{
    <span class="comment">// 無限再帰するので、この構造体はレイアウトが確定できない</span>
    <span class="type">Container</span>&lt;<span class="type">RecursiveLayout</span>&gt; <span class="error">_x</span>;
}
</code></pre>
<p>再帰していないかどうかを調べるために、構造体の中身の情報が必要です。</p>
<h3>privateフィールドを残していない問題</h3>
<p>この、「構造体は、中身のprivateフィールドの情報も残さないとまずい」というのに気づいたのは、
参照アセンブリの仕組みを導入したのよりもちょっと後です。
リリースまでには気づいてなくて、リリース後に不具合報告を受けて気づいたようで。</p>
<p>PCLプロジェクトから参照しているいくつかの参照アセンブリが、構造体のprivateフィールドまで削除してしまっていて、問題を起こします。</p>
<p>ということで、本題に戻りますが、PCLプロジェクトでだけ起こせる問題の数々。
以下のコード、本来はコンパイル エラーになるべきですが、PCLではコンパイルできてしまします。</p>
<p>1つ目。確実な初期化に漏れるケース。</p>
<pre class="source" title="本来は未初期化エラーになるはず">
<code><reserved></span><span class="reserved">using</span> System;

<span class="reserved">struct</span> <span class="type">DefiniteAssignment</span>
{
    <span class="comment">// DateTimeOffset には中身があるはずなのに…</span>
    <span class="type">DateTimeOffset</span> _x;

    <span class="reserved">public</span> <span class="error">DefiniteAssignment</span>(<span class="reserved">int</span> n) { } <span class="comment">// PCL ではエラーにならない</span>
}
</code></pre>
<p>2つ目。ポインター化できるかどうかの判定をミスるケース。</p>
<pre class="source" title="本来はポインター化できない型をポインター化">
<code><span class="reserved">using</span> System.Runtime.CompilerServices;
<span class="reserved">using</span> System.Runtime.InteropServices;

<span class="reserved">class</span> <span class="type">ManagedPointer</span>
{
    <span class="reserved">public</span> <span class="reserved">unsafe</span> <span class="reserved">void</span> X()
    {
        <span class="comment">// TaskAwaiter は内部的に Task クラスのフィールドを1個だけ持っている</span>
        <span class="comment">// 本来はポインター化できない</span>
        <span class="reserved">var</span> p = <span class="type">Marshal</span>.AllocHGlobal(<span class="error"><span class="reserved">sizeof</span>(<span class="type">TaskAwaiter</span>)</span>);

        <span class="comment">// PCL ではエラーにならない</span>
        <span class="type">TaskAwaiter</span> a = *(<span class="error"><span class="type">TaskAwaiter</span>*</span>)p;

        <span class="comment">// ここで GC が発生したとするとまずい</span>

        <span class="type">Marshal</span>.FreeHGlobal(p);
    }
}
</code></pre>
<p>3つ目。無限再帰なレイアウトを作れてしまうケース。</p>
<pre class="source" title="無限再帰レイアウト">
<code><span class="reserved">using</span> System.Collections.Generic;

<span class="reserved">struct</span> <span class="type">RecursiveLayout</span>
{
    <span class="comment">// 無限再帰するので、この構造体はレイアウトが確定できない</span>
    <span class="type">KeyValuePair</span>&lt;<span class="type">RecursiveLayout</span>, <span class="type">RecursiveLayout</span>&gt; <span class="error">_x</span>; <span class="comment">// PCL ではエラーにならない</span>
}
</code></pre>
<p>どれも結構まずいんですが、今のところ、これがPCLではコンパイルできてしまっています。
<code>DateTimeOffset</code>、<code>KeyValuePair</code>、<code>TaskAwaiter</code>などの構造体で、PCLが参照している参照アセンブリでは中身がごっそり削られているのが原因。</p>
<h3>この問題を踏む可能性</h3>
<p>この問題ですが、根本的には「参照アセンブリを作るときに消しちゃいけないところまで消しすぎた」というのが原因なわけで、
参照しているもの次第で起こるかどうかが決まります。</p>
<p>問題が起きるケース:</p>
<ul>
<li>PCL を使っていて、上記の<code>DateTimeOffset</code> などを参照する</li>
<li>同様に、<a href="https://docs.microsoft.com/ja-jp/dotnet/articles/standard/library">.NET Standard 向けのライブラリ</a> プロジェクトでも、該当する型を参照すると問題が起きる</li>
</ul>
<p>起きないケース:</p>
<ul>
<li>アプリなど、実行アセンブリを直接参照しているもの</li>
<li>
実装アセンブリを直接提供しているライブラリなら問題が起きない
<ul>
<li><a href="https://www.nuget.org/packages/System.Threading.Tasks.Extensions/"><code>ValueTask</code></a>や<a href="https://www.nuget.org/packages/System.ValueTuple/"><code>ValueTuple</code></a>は実装アセンブリしか提供していないので、こいつらでは問題は起きない</li>
</ul>
</li>
</ul>
<h3>問題への対処(検討中)</h3>
<p>とりあえず、どこの問題かというと参照アセンブリを作るツールになります。</p>
<p>今は構造体のすべてのprivateフィールドを削ってしまっている挙動を、以下のように変更する必要があります。
(フィールドをすべて残すのではなく、以下のルールにするのは参照アセンブリのサイズ削減のため。
C#コンパイラーが誤動作しないようにするにはこのルールで十分。)</p>
<ul>
<li>1つでも値型のフィールドを持っていれば、<code>int</code>型など適当な型のフィールドを1個だけ作って含める</li>
<li>1つでも参照型のフィールドを持っていれば、<code>object</code>型のフィールドを1個だけ作って含める</li>
<li>ジェネリックな構造体の場合は、ジェネリック型引数で与えられた型のフィールドは消さずに残す</li>
</ul>
<p>今は、C# コンパイラー自身が実装アセンブリリと同時に参照アセンブリを作る機能を持っているみたいなので、
基本的にはC# チームの仕事かも。
(昔からそうだったわけではなくて、割かし最近、そういう機能を持った。
それ以前は、オープンになっていないツールで、標準ライブラリの参照アセンブリ作りをしてた。)</p>
<p>とはいえ、現在問題を起こしている参照アセンブリとかを、ちゃんと治ったバージョンのツールで生成しなおして、
パッケージをNuGetサーバーに上げなおす作業は、たぶんC# チームの範疇外。</p>
<p>問題を起こす状況も限られているし、複数のチームが絡んでいるしで、ちょっと修正には時間が掛かりそうな雰囲気…</p>
 ]]></description>
				<pubDate>Tue, 20 Dec 2016 15:07:11 +0900</pubDate>
			</item>
			<item>
				<title>小ネタ プリミティブ型</title>
				<link>http://ufcpp.net/blog/2016/12/tipsprimitives/</link>
				<description><![CDATA[ <p>.NETには「プリミティブ型」とかいうものがあるんですが、
何をもってプリミティブと言えるのか、
どういう型がプリミティブ型なのかというと、
なんかよくわからない存在です。</p>
<p><code>Type</code>型に<code>IsPrimitive</code>というプロパティがあって、こいつが<code>true</code>を返すものがプリミティブ型なんですが。
以下のコードを見ての通り、どういう基準なのかがパッと見でわからず。</p>
<pre class="source" title="IsPrimitiveの結果">
<code><span class="reserved">using</span> <span class="reserved">static</span> System.<span class="type">Console</span>;

<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> Main()
    {
        WriteLine(<span class="reserved">typeof</span>(<span class="reserved">int</span>).IsPrimitive);     <span class="comment">// true</span>
        WriteLine(<span class="reserved">typeof</span>(<span class="reserved">bool</span>).IsPrimitive);    <span class="comment">// true</span>
        WriteLine(<span class="reserved">typeof</span>(<span class="reserved">double</span>).IsPrimitive);  <span class="comment">// true</span>
        WriteLine(<span class="reserved">typeof</span>(<span class="reserved">object</span>).IsPrimitive);  <span class="comment">// false!</span>
        WriteLine(<span class="reserved">typeof</span>(<span class="reserved">string</span>).IsPrimitive);  <span class="comment">// false!</span>
        WriteLine(<span class="reserved">typeof</span>(<span class="reserved">decimal</span>).IsPrimitive); <span class="comment">// false!</span>
        WriteLine(<span class="reserved">typeof</span>(System.<span class="type">IntPtr</span>).IsPrimitive); <span class="comment">// true!</span>
    }
}
</code></pre>
<h2>primitive</h2>
<p>primitiveという単語の意味は、原始的とか基本的とかそんな意味なわけですが。
C#とかのプログラミング言語において「原始的」っていうのは、内部的に専用命令などを持っていて、
ユーザー定義のクラスや構造体ではできない何らかの特別扱いを受けているという意味になります。</p>
<p>特にC#の場合には、C#のレベルではなく、.NETランタイム的に、専用のIL (中間言語、Intermediate Language)命令を持っているかどうかが1つの基準なんですが…
それにしても分類は結構あいまいで、よくわからなかったりします。</p>
<h2>元々はJavaから</h2>
<p>元々はJavaから来ているんですかね。Javaの場合は割かしプリミティブ型がはっきりしています。
以下の3つが一致していて、これこそがプリミティブ型です。</p>
<ul>
<li><code>int</code>とか<code>boolean</code>みたいに、専用のキーワードがある</li>
<li>言語的に許される唯一の値型</li>
<li>中間言語(bytecode)的に専用命令を持ってる</li>
</ul>
<p>C#というか.NETでよくわからなくなる理由は、</p>
<ul>
<li><code>object</code>、<code>string</code>、<code>decimal</code>にも専用のキーワードがある</li>
<li>構造体や列挙型があるのでいくらでも値型を作れる</li>
<li>専用命令を持っているって意味では<code>string</code>もちょっとだけ命令を持っている</li>
</ul>
<p>というあたり。</p>
<h2>.NETのプリミティブ事情</h2>
<p>.NET だと、</p>
<ul>
<li>
<code>IsPrimitive</code>が<code>true</code>な型は以下の通り
<ul>
<li><code>Boolean</code>, <code>Byte</code>, <code>SByte</code>, <code>Int16</code>, <code>UInt16</code>, <code>Int32</code>, <code>UInt32</code>, <code>Int64</code>, <code>UInt64</code>, <code>IntPtr</code>, <code>UIntPtr</code>, <code>Char</code>, <code>Double</code>, <code>Single</code></li>
<li>
C#のキーワードになってる型から、
<ul>
<li><code>decimal</code>, <code>object</code>, <code>string</code>は除く</li>
<li><code>IntPtr</code>, <code>UIntPtr</code>を加える</li>
</ul>
</li>
</ul>
</li>
<li><code>object</code>、<code>string</code>はキーワードになってるけど参照型</li>
<li>構造体や列挙型があるので、いくらでも値型を作れる</li>
<li>
<code>string</code>はプリミティブ型とかと比べると大して専用命令ない
<ul>
<li>けども、ないわけじゃない</li>
<li>
命令ではなくメモリの確保の仕方で言うと、<code>string</code>は他のクラスと比べて相当特殊
<ul>
<li>この意味で言うと配列もかなり特殊</li>
</ul>
</li>
</ul>
</li>
<li>
<code>decimal</code>に至っては全く専用命令ない
<ul>
<li><code>decimal</code>が特別なのはC#的にリテラルがあることくらい</li>
<li>IL 的にはリテラルすらない、完全に普通の構造体</li>
</ul>
</li>
</ul>
<p>ということで、何が何やら。まあ大まかに言うと、プリミティブ型 = 「中間言語(IL)的に専用を持っていて、かつ、値型」ですかね。</p>
<h2>IL的な扱い</h2>
<p>せっかくなので、IL 的な扱いも見てみますか。
以下のようなコードをコンパイルしてみます。</p>
<pre class="source" title="2つの引数の + 演算子呼び出しするだけの例">
<code><span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> Main()
    {
        M(1, 2);
        M(<span class="string">"a"</span>, <span class="string">"b"</span>);
        M(1.23m, 2.71m);
    }

    <span class="reserved">static</span> <span class="reserved">int</span> M(<span class="reserved">int</span> x, <span class="reserved">int</span> y) =&gt; x + y;
    <span class="reserved">static</span> <span class="reserved">decimal</span> M(<span class="reserved">decimal</span> x, <span class="reserved">decimal</span> y) =&gt; x + y;
    <span class="reserved">static</span> <span class="reserved">string</span> M(<span class="reserved">string</span> x, <span class="reserved">string</span> y) =&gt; x + y;
}
</code></pre>
<h3>int</h3>
<p>まずは<code>int</code>の場合。
メソッド<code>M(int, int)</code>の中身が</p>
<pre class="source" title="int の +">
<code>  IL_0000:  ldarg.0
  IL_0001:  ldarg.1
  IL_0002:  add
</code></pre>
<p><code>M(int, int)</code>を呼び出す側が</p>
<pre class="source" title="M(int, int) の呼び出し">
<code>  IL_0000:  ldc.i4.1
  IL_0001:  ldc.i4.2
  IL_0002:  call       <span class="reserved">int32</span> Program::M(<span class="reserved">int32</span>,
                                        <span class="reserved">int32</span>)
</code></pre>
<p>という感じです。
足し算用に<code>add</code>という専用命令があったり、
定数読み込みのために<code>ldc.i4.1</code> (load constant 4バイト整数の1という意味)という命令があったりします。</p>
<h3>string</h3>
<p>続いて<code>string</code>
メソッド<code>M(string, string)</code>の中身が</p>
<pre class="source" title="string の +">
<code>  IL_0000:  ldarg.0
  IL_0001:  ldarg.1
  IL_0002:  call       <span class="reserved">string</span> [mscorlib]System.String::Concat(<span class="reserved">string</span>,
                                                              <span class="reserved">string</span>)
</code></pre>
<p><code>M(string, string)</code>を呼び出す側が</p>
<pre class="source" title="M(string, string) の呼び出し">
<code>  IL_0008:  ldstr      <span class="string">"a"</span>
  IL_000d:  ldstr      <span class="string">"b"</span>
  IL_0012:  call       <span class="reserved">string</span> Program::M(<span class="reserved">string</span>,
                                         <span class="reserved">string</span>)
</code></pre>
<p>です。
連結のためには特に命令を持っているわけではなく、<code>+</code>演算子は<code>Concat</code>メソッド呼び出しに置き換わります。
一方で、値の読み込みのために<code>ldstr</code> (load stringの意味)命令は持っています。</p>
<p>微妙なライン…
C#的には組み込み型(<code>string</code>っていうキーワードがあり、リテラルとかが用意されてる特別な型)だし、
IL的にはプリミティブ型ではない、という割には<code>ldstr</code>命令とか持ってる…</p>
<h3>decimal</h3>
<p>最後に<code>decimal</code>。
メソッド<code>M(decimal, decimal)</code>の中身が</p>
<pre class="source" title="decimal の +">
<code>  IL_0000:  ldarg.0
  IL_0001:  ldarg.1
  IL_0002:  call       <span class="reserved">valuetype</span> [mscorlib]System.Decimal [mscorlib]System.Decimal::op_Addition(<span class="reserved">valuetype</span> [mscorlib]System.Decimal,
                                                                                                <span class="reserved">valuetype</span> [mscorlib]System.Decimal)
</code></pre>
<p><code>M(decimal, decimal)</code>を呼び出す側が</p>
<pre class="source" title="M(decimal, decimal)の呼び出し">
<code>  IL_0018:  ldc.i4.s   123
  IL_001a:  ldc.i4.0
  IL_001b:  ldc.i4.0
  IL_001c:  ldc.i4.0
  IL_001d:  ldc.i4.2
  IL_001e:  newobj     <span class="reserved">instance</span> <span class="reserved">void</span> [mscorlib]System.Decimal::<span class="reserved">.ctor</span>(<span class="reserved">int32</span>,
                                                                     <span class="reserved">int32</span>,
                                                                     <span class="reserved">int32</span>,
                                                                     <span class="reserved">bool</span>,
                                                                     uint8)
  IL_0023:  ldc.i4     0x10f
  IL_0028:  ldc.i4.0
  IL_0029:  ldc.i4.0
  IL_002a:  ldc.i4.0
  IL_002b:  ldc.i4.2
  IL_002c:  newobj     <span class="reserved">instance</span> <span class="reserved">void</span> [mscorlib]System.Decimal::<span class="reserved">.ctor</span>(<span class="reserved">int32</span>,
                                                                     <span class="reserved">int32</span>,
                                                                     <span class="reserved">int32</span>,
                                                                     <span class="reserved">bool</span>,
                                                                     uint8)
  IL_0031:  call       <span class="reserved">valuetype</span> [mscorlib]System.Decimal Program::M(<span class="reserved">valuetype</span> [mscorlib]System.Decimal,
                                                                     <span class="reserved">valuetype</span> [mscorlib]System.Decimal)
</code></pre>
<p>です。
どこにも専用命令がないどころか、リテラルの<code>1.23m</code>や<code>2.71m</code>すらも、
<code>new decimal(123, 0, 0, false, 2)</code>の意味のコンストラクター呼び出しに置き換わっています。
加算も、<code>op_Addition</code>メソッド呼び出しです。</p>
<p>正直なところ、<code>decimal</code>がC#的に特別扱いを受ける理由はリテラルだけだったりします。
あくまでC#上の特別扱いであって、IL上は他の構造体の扱いとまったく同じです。
なので、<code>decimal</code>はプリミティブではない。</p>
<p>もしかすると、C++みたいに<a href="http://cpprefjp.github.io/lang/cpp11/user_defined_literals.html">ユーザー定義リテラル</a>が書ければ、
<code>decimal</code>なんていう組み込み型は要らなかったかもしれません。</p>
 ]]></description>
				<pubDate>Mon, 19 Dec 2016 21:05:28 +0900</pubDate>
			</item>
			<item>
				<title>小ネタ 構文糖衣と、そうではない構文と</title>
				<link>http://ufcpp.net/blog/2016/12/tipsgeneratedil/</link>
				<description><![CDATA[ <h2>構文糖衣が多い言語</h2>
<p>C#は構文糖衣が結構多い言語です。
構文糖衣(syntax sugar)っていうのは、要するに、「定型的な長くて面倒なコードにはなるけども、原理的にはその構文がなくても全く同じ意味のコードが書ける」というような類の機能です。</p>
<p>例えば<a href="http://ufcpp.net/study/csharp/sp3_linq.html#query">クエリ式</a>がわかりやすいですが、以下の3つの式は全く同じ意味になります。</p>
<pre class="source" title="クエリ式">
<code><span class="reserved">from</span> x <span class="reserved">in</span> data <span class="reserved">where</span> x &gt; 2 <span class="reserved">select</span> x * x
</code></pre>
<pre class="source" title="クエリ式 → メソッド呼び出しに展開">
<code>data.Where(x =&gt; x &gt; 2).Select(x =&gt; x * x)
</code></pre>
<pre class="source" title="拡張メソッド → 静的メソッドに展開">
<code><span class="type">Enumerable</span>.Select(<span class="type">Enumerable</span>.Where(data, x =&gt; x &gt; 2), x =&gt; x * x)
</code></pre>
<p>ということで、C#の機能を説明するとき、結構、「こういうコードと同じ意味になります」というような文章を書くことは多いです。</p>
<p>特に、ここで例に挙げたクエリ式は、式 → メソッド呼び出し → 必要があれば拡張メソッドの静的メソッドへの展開 と、2段階の変換を行う機能です。
いうなれば、「2段階」構文糖衣。</p>
<h2>構文糖衣でない文法</h2>
<p>逆に、C#に対して後から追加された構文の全部が全部単なる構文糖衣ではなく、コンパイル結果まで覗いてみる必要のものもちらほらあります。</p>
<p>もちろん、<a href="http://ufcpp.net/study/csharp/ap_ver2.html#generics">C# 2.0の時のジェネリックの追加</a>のように、.NET Frameworkのランタイム自体に手を入れることで実現した機能もあります。</p>
<p>一方で、「ランタイムのレベル(型システムや中間言語(IL: Intermediate Language)の仕様レベル)では元々機能としてあるけども、
C# からは使えなかったものを使えるようにした」 というような機能もいくつかあります。
代表的なのは以下の2つでしょう。</p>
<ul>
<li>C# 4.0から: <a href="http://ufcpp.net/study/csharp/sp4_variance.html">ジェネリックの変性</a>(variance)</li>
<li>C# 7から: <a href="http://ufcpp.net/study/csharp/sp_ref.html?p=2#ref-returns">参照戻り値</a></li>
</ul>
<h2>ジェネリックの変性</h2>
<p><a href="http://ufcpp.net/study/csharp/sp4_variance.html">ジェネリックの変性</a>(variance)は割かしわかりやすい例でしょうか。
C#上の構文糖衣でどうこうできるわけではなくて、.NETのメタデータのレベルで処理されています。</p>
<p>例えばC# 4.0以降で以下のようなコードを書いたとしましょう。型引数<code>T</code>に、共変であることを示す<code>out</code>修飾子を付けています。</p>
<pre class="source" title="共変なジェネリック型引数T">
<code><span class="reserved">interface</span> <span class="type">IWrapper</span>&lt;<span class="reserved">out</span> <span class="type">T</span>&gt;
{
    <span class="type">T</span> Value { <span class="reserved">get</span>; }
}
</code></pre>
<p>逆アセンブルしてみると以下のようになっています。
ILのレベルでも、<code>T</code>の前に<code>+</code>という記号が入っていますが、これが共変を表すフラグです。</p>
<pre class="source" title="">
<code>.class <span class="reserved">interface</span> <span class="reserved">private</span> <span class="reserved">abstract</span> <span class="reserved">auto</span> <span class="reserved">ansi</span> IWrapper`1&lt;+ T&gt;
{
} <span class="comment">// end of class IWrapper`1
</code></pre>
<p>このフラグは、IL的には .NET 2.0の頃からありましたが、
C#からこのフラグをいじれるようになったのはC# 4.0(.NET 4と同世代)からです。</p>
<p>まあ、何にしても「以前のC#であればこう展開されます」的な説明はできない機能です。</p>
<h2>参照戻り値</h2>
<p>最近だと<a href="http://ufcpp.net/study/csharp/sp_ref.html?p=2#ref-returns">参照戻り値</a>なんかもそうです。</p>
<p>ILって実は安全性を損なうきわどい書き方をやりたい放題で、
C#のレベルで制限を掛けて安全性を担保していることが結構あります。
参照戻り値は、</p>
<ul>
<li>これまで安全性を担保するための解析がしんどかったから使えなかった、</li>
<li>C# 7では、C#コンパイラーが賢くなったからその解析ができるようになって、認められるようになった</li>
</ul>
<p>というものなわけです。
ILはそんな安全性とか気にしないので、昔から参照戻り値を使えました。</p>
<p>例えば、C# 7で以下のようなコードを書いたとします。</p>
<pre class="source" title="参照戻り値を使ったC#コード">
<code><span class="reserved">static</span> <span class="reserved">ref</span> <span class="reserved">int</span> RefMax(<span class="reserved">ref</span> <span class="reserved">int</span> x, <span class="reserved">ref</span> <span class="reserved">int</span> y)
{
    <span class="reserved">if</span> (x &gt;= y) <span class="reserved">return</span> <span class="reserved">ref</span> x;
    <span class="reserved">else</span> <span class="reserved">return</span> <span class="reserved">ref</span> y;
}
</code></pre>
<p>コンパイル結果は以下の通り。<code>&amp;</code>が参照を表す記号です。</p>
<pre class="source" title="IL的には参照は &amp;">
<code>.method <span class="reserved">private</span> <span class="reserved">hidebysig</span> <span class="reserved">static</span> <span class="reserved">int32</span>&amp;  RefMax(<span class="reserved">int32</span>&amp; x,
                                                <span class="reserved">int32</span>&amp; y) <span class="reserved">cil</span> <span class="reserved">managed</span>
{
  <span class="comment">// コード サイズ       10 (0xa)
</span>  .maxstack  8
  IL_0000:  ldarg.0
  IL_0001:  ldind.i4
  IL_0002:  ldarg.1
  IL_0003:  ldind.i4
  IL_0004:  blt.s      IL_0008
  IL_0006:  ldarg.0
  IL_0007:  ret
  IL_0008:  ldarg.1
  IL_0009:  ret
} <span class="comment">// end of method Program::RefMax
</span>
</code></pre>
<p>このコードは、.NET 1.0の頃から書けました。
もっとも、<code>int32&amp;</code> (C# 7でいう<code>ref int</code>)の戻り値を受け取る手段がなかったので、実際のところ書いてもC#からは使えないコードになります(例えばこのコードをVisual Studio 2017でコンパイルして、その結果のDLLをVisual Studio 2015から参照した場合、このメソッドはクラスのメンバー一覧情報のところに表示されません)。</p>
<p>ちなみに、参照に対する操作は、実のところポインターに対する操作とまったく同じになります。
例えば、以下のようなunsafeなコードを書いてみます。
ポインターになっただけで、やっていることは先ほどの参照を使ったコードとまったく同じです。</p>
<pre class="source" title="ポインターを使ったC#コード">
<code><span class="reserved">unsafe</span> <span class="reserved">static</span> <span class="reserved">int</span>* RefMax(<span class="reserved">int</span>* x, <span class="reserved">int</span>* y)
{
    <span class="reserved">if</span> (*x &gt;= *y) <span class="reserved">return</span> x;
    <span class="reserved">else</span> <span class="reserved">return</span> y;
}
</code></pre>
<p>こちらのコンパイル結果は以下のようになります。<code>&amp;</code>が<code>*</code>に変わった以外の部分は一字一句たがわず、先ほどのコードと完全に一致しています。</p>
<pre class="source" title="IL的にはポインターは*">
<code>.method <span class="reserved">private</span> <span class="reserved">hidebysig</span> <span class="reserved">static</span> <span class="reserved">int32</span>*  RefMax(<span class="reserved">int32</span>* x,
                                                <span class="reserved">int32</span>* y) <span class="reserved">cil</span> <span class="reserved">managed</span>
{
  <span class="comment">// コード サイズ       10 (0xa)
</span>  .maxstack  8
  IL_0000:  ldarg.0
  IL_0001:  ldind.i4
  IL_0002:  ldarg.1
  IL_0003:  ldind.i4
  IL_0004:  blt.s      IL_0008
  IL_0006:  ldarg.0
  IL_0007:  ret
  IL_0008:  ldarg.1
  IL_0009:  ret
} <span class="comment">// end of method Program::RefMax
</span>
</code></pre>
<p><code>ldind</code>はload indirect (間接ロード)の略で、
ポインターや参照ごしに値を取ってくる命令です。
ポインターと参照でまったく同じ命令を使います。</p>
<h2>おまけ: <code>Unsafe</code></h2>
<p>余談となりますが、ILを使えば、自己責任で安全でないコード書き放題だという例にも触れておきます。</p>
<p>今、<a href="https://www.nuget.org/packages/System.Runtime.CompilerServices.Unsafe/">System.Runtime.CompilerServices.Unsafe</a>とかいう名前からしてunsafeなライブラリがあったりします。</p>
<p>このパッケージ中にある<code>Unafe</code>クラスは、<a href="http://ufcpp.net/blog/2016/12/tipscorefxlab/">3日目</a>に紹介した<code>System.Memory</code>の中で使われています。
というか、元々は<code>System.Memory</code>パッケージ内にあったコードを、これ単体で使えるだろうと切り出した結果が<code>System.Runtime.CompilerServices.Unsafe</code>パッケージです。</p>
<p>ソースコードも以下のGitHubリポジトリで公開されているので中身を覗いてみると…</p>
<ul>
<li><a href="https://github.com/dotnet/corefx/blob/master/src/System.Runtime.CompilerServices.Unsafe">dotnet/corefx: System.Runtime.CompilerServices.Unsafe</a></li>
</ul>
<p><a href="https://github.com/dotnet/corefx/blob/master/src/System.Runtime.CompilerServices.Unsafe/src/System.Runtime.CompilerServices.Unsafe.il">完全にILで書かれています</a>。</p>
<p>ポインターと参照を相互に変換するメソッドなんかもあったりするんですが、
以下のような感じで、実はほぼ素通しです。
ロード(<code>ldarg</code>)して、即リターン(<code>ret</code>)。</p>
<pre class="source" title="参照とポインターは実はほぼ素通しで変換可能">
<code>.method <span class="reserved">public</span> <span class="reserved">hidebysig</span> <span class="reserved">static</span> <span class="reserved">void</span>* AsPointer&lt;T&gt;(!!T&amp; 'value') <span class="reserved">cil</span> <span class="reserved">managed</span> aggressiveinlining
  {
        .custom <span class="reserved">instance</span> <span class="reserved">void</span> System.Runtime.Versioning.NonVersionableAttribute::<span class="reserved">.ctor</span>() = ( 01 00 00 00 )
        .maxstack 1
        ldarg.0
        conv.u
        ret
  } <span class="comment">// end of method Unsafe::AsPointer
</span>
    .method <span class="reserved">public</span> <span class="reserved">hidebysig</span> <span class="reserved">static</span> !!T&amp; AsRef&lt;T&gt;(<span class="reserved">void</span>* source) <span class="reserved">cil</span> <span class="reserved">managed</span> aggressiveinlining
  {
        .custom <span class="reserved">instance</span> <span class="reserved">void</span> System.Runtime.Versioning.NonVersionableAttribute::<span class="reserved">.ctor</span>() = ( 01 00 00 00 )
        .maxstack 1
        ldarg.0
        ret
  } <span class="comment">// end of method Unsafe::AsRef
</span>
</code></pre>
<p>ちなみに、<code>conv.u</code>命令は、ネイティブ(CPUの種類に応じて32bitか64bitか切り替わる)符号なし整数への変換命令です。
ポインター = ネイティブ符号なし整数。</p>
 ]]></description>
				<pubDate>Sun, 18 Dec 2016 09:55:07 +0900</pubDate>
			</item>
			<item>
				<title>小ネタ 「deconstruct」という単語</title>
				<link>http://ufcpp.net/blog/2016/12/tipsdeconstruct/</link>
				<description><![CDATA[ <p>今日も、小ネタなような、C#7思い出話なような。</p>
<p>C# 7で、<a href="http://ufcpp.net/study/csharp/datatype/deconstruction/">分解</a>という機能が入ったわけですが、英語だと deconstruction という単語になります。</p>
<p>分解という機能のおさらいですが、以下のような書き方でタプルなどの型のメンバーを抽出できる機能です。</p>
<pre class="source" title="分解構文">
<code><span class="reserved">var</span> (x, y) = tuple;
</code></pre>
<p>これ、他のプログラミング言語だと、destructuring とか呼ばれたりしています。
といっても、文法上正式に destructuring と呼ばれているわけではないんですが(大体の言語は文法上は単に「pattern」とか呼ばれる機能)…
まあ、解説ページなんかでは destructuring と呼ばれます。</p>
<p>で、今日、何が言いたいかというと、</p>
<ul>
<li>deconstruct  : デコンストラクト</li>
<li>destructuring: デストラクト</li>
</ul>
<p>並べるとわかりますかね。
「con」の有無。
<span style="color:#a00000">de</span><span style="color:#00a000">con</span><span style="color:#0000a0">struct </span>
と
<span style="color:#a00000">de</span><span style="color:#0000a0">struct</span>uring。</p>
<p>用語として多少もめてたりするみたいです。</p>
<ul>
<li>他の言語に合わせてdestucturingであるべきじゃないか。</li>
<li>construct (con(共) + struct(築))の逆はdestruct (de(脱) + struct(築))じゃないのか</li>
<li>でも、destuctureだと<a href="http://ufcpp.net/study/csharp/oo_construct.html#dtor">デストラクター</a>と紛らわしくないか。</li>
<li>C#のデストラクターって、あれ、実際にはfinalizerだし。誰だよ、destructorって名前にしたやつ</li>
</ul>
<p>みたいな雰囲気。</p>
<p>日本語だとたぶん、僕みたいに「分解」とかに訳しちゃうんでそんなに変でもないんですが、
英語だとdestructorとdeconstructionが並ぶことになるんで気持ち悪いみたいですね。</p>
<p>まあ、デストラクターも分解も、どちらもコンストラクターの逆ではあります。</p>
<p><img src="/media/1109/construction.png" alt="コンストラクターの仕事" /></p>
<p>ちなみに、コンストラクター、初期化子、デストラクター、分解の例をまとめて挙げると以下のような感じ。</p>
<p><img src="/media/1110/example.png" alt="constructor, initialiser, destructor, deconstructionの例" /></p>
<p>そもそも英語でdestroyの名詞形がdestructionなのが良くないかも。
「destruct」で切った場合、それはdestroy(破壊)のことなのかdestructure(脱構造化)のことなのかそもそもわからず。</p>
<p>それに、C#で破棄用の構文をデストラクターと呼ぶのはC++から持ってきた言葉なわけですけど、
これ、やっぱりJavaみたいにfinalizerって呼んでおくべきだったのかも。
デストラクターに関しては、分解が絡まなくても元々名前には悩んでいるみたいです。</p>
<ul>
<li>.NET的には finalizer って呼び名になってる。destructor って呼び名はC#だけ</li>
<li>ECMAに出しているC#仕様書上は finalizer って呼び名になっているらしい</li>
<li>
MSDN上に出してるC#仕様書は destructor になってる
<ul>
<li>今、ECMA版とMSDN版の統合を考えてるんで、なおのこと問題に</li>
</ul>
</li>
<li>
<a href="https://github.com/dotnet/roslyn">Roslyn</a> の API 中でも destructor という単語を使ってる
<ul>
<li>これがあるんで、単純に文章上だけの変更ってわけではなくて、ソースコードにも影響あり</li>
</ul>
</li>
</ul>
<p>とりあえず、現状のC#チームの希望的には以下のような雰囲気です。</p>
<ul>
<li>分解は deconstruction のまま(de + con 付き)</li>
<li>デストラクターって呼び名は微妙なので変えることも視野に入ってるみたい</li>
</ul>
 ]]></description>
				<pubDate>Sat, 17 Dec 2016 02:30:36 +0900</pubDate>
			</item>
			<item>
				<title>パターン マッチング</title>
				<link>http://ufcpp.net/blog/2016/12/patternmatching/</link>
				<description><![CDATA[ <p>小ネタ休んだついでに、C# 7思い出話。</p>
<p>そういや、<a href="http://ufcpp.net/blog/2016/8/tuples/">タプル</a>の辺りまでは、<a href="http://ufcpp.net/search?bc=C%23+7%E6%80%9D%E3%81%84%E5%87%BA%E8%A9%B1">C# 7思い出話</a>とか称して、仕様が固まるまでにあった流れなんかもブログに残そうとしてたのを思い出したり。</p>
<p><a href="http://ufcpp.net/study/csharp/cheatsheet/ap_ver7/">C# 7の紹介</a>、後半は一気に埋めちゃったのもあって、思い出話をどう書こうか考えてるうちに流れてしまったというか。
<a href="http://www.buildinsider.net/language/csharpunicode/01">ちょっと書くのに苦労した原稿</a>とか、グロサミ参加とか、色々忙しくて忘れていたというか。</p>
<p>とりあえず、今日はパターン マッチングの話。</p>
<h2>パターン マッチングを小分けに</h2>
<p>元々予定されていたパターン マッチングの全機能はC# 7の時点では入れれない、段階的に実装していくという話は結構早い段階で決まっていました。</p>
<p>ちなみに、その、予定されている全機能で言うと、以下のような書き方とかもできます。</p>
<pre class="source" title="全機能版パターン マッチング">
<code><reserved></span><span class="reserved">static</span> <span class="reserved">int</span> Calculate(<span class="type">Node</span> n, <span class="reserved">int</span> x)
{
    <span class="reserved">switch</span> (n)
    {
        <span class="comment">// この2行はC# 7の時点で書ける</span>
        <span class="reserved">case</span> <span class="type">Variable</span> v: <span class="reserved">return</span> x;
        <span class="reserved">case</span> <span class="type">Constant</span> c: <span class="reserved">return</span> c.Value;
        <span class="comment">// この2行は先送り</span>
        <span class="reserved">case</span> <span class="type">Add</span> { <span class="type">Le</span> <span class="reserved">is</span> <span class="reserved">var</span> l, Right <span class="reserved">is</span> <span class="reserved">var</span> r }: <span class="reserved">return</span> Calculate(l, x) + Calculate(r, x);
        <span class="reserved">case</span> <span class="type">Mul</span>(<span class="reserved">var</span> l, <span class="reserved">var</span> r): <span class="reserved">return</span> Calculate(l, x) * Calculate(r, x);
    }
}
</code></pre>
<p>一方で、どこまでをC# 7に入れるかは、徐々に、スケジュールと相談しつつ決めていたみたいで最近まで全然確定していません。</p>
<p>初期は、本当に<a href="http://ufcpp.net/study/csharp/datatype/typeswitch/">型スイッチ</a>くらいでした。</p>
<p>続いて、まあタプルが入るんなら<a href="http://ufcpp.net/study/csharp/datatype/deconstruction/">分解</a>くらいは要るだろうとなったのか、こいつが実装されます。</p>
<p><a href="http://ufcpp.net/study/csharp/oo_exception.html#throwexpr">throw式</a>もパターン マッチングからの派生です。パターン マッチングのお供として「switch 式」みたいなやつを入れることを考えると、「どのパターンにもマッチしなかったら例外を投げる」という処理が必要で、そのための throw 式です。</p>
<p><a href="http://ufcpp.net/study/csharp/datatype/deconstruction/">分解</a>や<a href="http://ufcpp.net/study/csharp/sp_ref.html#out-var">out var</a>が入るならdiscards (wildcards)もほしいわけですが、これは、<code>_</code> を使うか <code>*</code> を使うか、既存の文脈でも discards を使えるようにするかどうかとかで悩んでいたみたいで、
本当につい最近実装されています。
<a href="http://ufcpp.net/blog/2016/12/vs2017rc2/">先日書いた</a>通り、Visual Studio 2017 RCの初期リリースでは実装されていなくて、Update での実装。</p>
<p>気が付いてみれば、「再帰的な分解」と「switch 式」以外は一通り実装されたのかなぁという感じです。
(再帰的っていうのは、最初に挙げた例でいう<code>Add { Left is var l, Right is var r }</code>とか<code>Mul(var l, var r)</code>とかみたいなパターンです。)</p>
<p>まあ、それぞれを見ると、細かく「先送り」になっているものもあるんですが。例えば以下のコードは、計画上はできることになっているんですが、現状ではコンパイルエラーになります。</p>
<pre class="source" title="VS 2017 RCの12月更新ではまだ使えない機能">
<code><comment></span><span class="comment">// 計画上は、クエリ式の let での分解も予定あり</span>
<span class="reserved">var</span> q = <span class="reserved">from</span> x <span class="reserved">in</span> <span class="reserved">new</span> [] { 1, 2, 3, 4, 5 }.Select((x, i) =&gt; (x, i))
        <span class="reserved">let</span> (y, z) = x
        <span class="reserved">select</span> y * z;

<span class="comment">// 計画上は、ラムダ式とかの既存の文法にも discards 導入の予定あり</span>
<span class="type">Func</span>&lt;<span class="reserved">int</span>, <span class="reserved">int</span>, <span class="reserved">int</span>&gt; f = (_, _) =&gt; 1;

<span class="comment">// 計画上は、ラムダ式でも throw 式を書ける予定あり</span>
<span class="type">Action</span> a = () =&gt; <span class="reserved">throw</span> <span class="reserved">new</span> <span class="type">Exception</span>();
</code></pre>
<p>もしかしたら、まだリリースまでにこれらの構文も対応するかもしれませんが、断定はできなさそう。</p>
 ]]></description>
				<pubDate>Fri, 16 Dec 2016 00:06:23 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 12/14</title>
				<link>http://ufcpp.net/blog/2016/12/pickuproslyn1214/</link>
				<description><![CDATA[ <p>小ネタ休んだついでにピックアップRoslynも。</p>
<p>Visual Studio 2017の正式リリースまではバグ修正くらいしか作業しない段階に来てるんで大したネタはない…
と思っていた時期がありました。</p>
<p>まあ、小ネタ程度の話はあった…</p>
<h2>whileとforのスコープ変更</h2>
<p>まあ、既存動作を壊す変更ではないんですが、<code>while</code>と<code>for</code>の仕様書上の記述を変更しなきゃという話が出ています。</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/issues/15630">Change scoping of expression variables for while, for #15630</a></li>
</ul>
<p><a href="http://ufcpp.net/study/csharp/datatype/typeswitch/">型スイッチ</a>と<a href="http://ufcpp.net/study/csharp/sp_ref.html#out-var">out var</a>のせいで、whileやforの条件式や更新式の中で変数を作れるようになりました。
その変数のスコープはどうなるべきかというのを考えたときに、<code>while</code>や<code>for</code>の展開結果に関する記述をちょっと変更する必要があるっていう話です。</p>
<h3>while</h3>
<p>まず<code>while</code>。</p>
<pre class="source" title="while">
<code><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">while</span> (&lt;cond&gt;) &lt;body&gt;
</code></pre>
<p>こういう<code>while</code>ステートメントがあったとき、これまでだと、以下のように展開するという仕様になっていました。</p>
<pre class="source" title="while 旧仕様">
<code>continueLabel:;
<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">if</span> (!&lt;cond&gt;) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">goto</span> breakLabel;
{
    &lt;body&gt;
}
<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">goto</span> continueLabel;
breakLabel:;
</code></pre>
<p>これが、以下のように変わります。<code>{ }</code> が1段増える。</p>
<pre class="source" title="while 新仕様">
<code>continueLabel:;
{
    <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">if</span> (!&lt;cond&gt;) <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">goto</span> breakLabel;
    {
        &lt;body&gt;
    }
    <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">goto</span> continueLabel;
}
breakLabel:;
</code></pre>
<p>要するに、条件式の中で宣言された変数は、<code>while</code>の外には漏らさないよというルールの追加です。</p>
<p>(現状のRC版はルール変更前の実装になってる。RTMまでにたぶん変わる。)</p>
<h3>for</h3>
<p>同様に、<code>for</code>。</p>
<pre class="source" title="for">
<code><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">for</span> (&lt;decl&gt;; &lt;cond&gt;; &lt;incr&gt;) &lt;body&gt;
</code></pre>
<p>この<code>for</code>ステートメントは、以下のような仕様になっていました。</p>
<pre class="source" title="for 旧仕様">
<code>{
    &lt;decl&gt;
    <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">while</span>(&lt;cond&gt;)
    {
        &lt;body&gt;
    continueLabel:;
        &lt;incr&gt;
    }
}
</code></pre>
<p>これが以下のように変更。更新式(<code>&lt;incr&gt;</code>のところ)に <code>{ }</code>が増えます。</p>
<pre class="source" title="for 新仕様">
<code>{
    &lt;decl&gt;
    <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">while</span>(&lt;cond&gt;)
    {
        &lt;body&gt;
    continueLabel:;
        { &lt;incr&gt; }
    }
}
</code></pre>
<p>更新式のところで宣言した変数はその中でだけ使えて、<code>for</code>ステートメントのbody内でも参照できなくするということのようです。</p>
<h2>Design by Contract のコミュニティ実装</h2>
<p>C# チーム的には「メリットの割には構文が煩雑になりすぎる」と、今まだちょっと及び腰になっている Design by Contract がらみの構文ですが、
しびれを切らした人が自前実装を始めた模様。</p>
<ul>
<li><a href="https://github.com/JamesFaix/Traction">Lightweight design-by-contact for C#6</a></li>
</ul>
<p>実装的には、<a href="https://github.com/StackExchange/StackExchange.Precompilation">StackExchange.Precompilation</a>を使ったビルド時コード書き換えみたいです。なので、実行時コストは高くないはず。</p>
<p>まあ、ビルド時コード書き換えはそこそこはまりどころもあるので、どうしてもDbCが欲しいという人にしかあんまりお勧めはできませんけども…
C#に公式に機能追加されるまでのつなぎとしてはいいかも。</p>
 ]]></description>
				<pubDate>Thu, 15 Dec 2016 00:22:37 +0900</pubDate>
			</item>
			<item>
				<title>Updating Visual Studio 2017 Release Candidate</title>
				<link>http://ufcpp.net/blog/2016/12/vs2017rc2/</link>
				<description><![CDATA[ <p>先月出たVisual Studio 2017 RC、ちょこっとアップデートが掛かりました。</p>
<ul>
<li><a href="https://blogs.msdn.microsoft.com/visualstudio/2016/12/12/updating-visual-studio-2017-release-candidate/">Updating Visual Studio 2017 Release Candidate</a></li>
</ul>
<p>小ネタ集？そんなの休み休み。</p>
<p>ちなみに、MSDNブログには「前のRCを入れてる人はアップデートの通知が出るはずだからそこからアップデートできる」って書いてあるんですが、うちではなんかトラブって、結局アンインストールからのインストールしなおしでした。
(ASP.NET がらみのVSIXパッケージが1個インストール失敗してた。)</p>
<h2>新旧 csproj</h2>
<p>概ねバグ修正っぽいんですが、個人的にうれしいのは、ようやくだいぶ .NET Core Tooling周りがマシになってきたこと。
昔ながらのcsproj (普通に .NET Framework向けライブラリ作ったり、旧Portable Class Libraryを作ったりしたときのやつ)と新csproj (元々xproj + project.jsonだったもの。 .NET Standardライブラリ作ったり、.NET Coreアプリ書いたりするときのやつ)の混在がやっとまっとうに。
.NET Standardライブラリのプロジェクトを、.NET Frameworkなコンソール アプリとかからプロジェクト参照できるように。</p>
<h2>言語パック</h2>
<p>あと、表示言語を切り替えれるように。最近もうすっかり、普段は英語UIで使っていて、記事を書くときのスクリーンショットとかのためだけに日本語に切り替えたりしてるんですけども、それが前のRCまではできなかったという。しょうがないからCommunity(日本語)とEnterprise(英語)をside by sideに入れてたんですが、それはそれで、スタートメニューにはそのうち片方(後からインストールした方)しか出てこないとか言う別の不具合が。それもやっと解消。</p>
<h2>C# 7</h2>
<p>で、C# 7。先月のRCリリースの時点でC# 7の全機能そろったといったな。あれは嘘だ。</p>
<p>えーっと、「C# 7に間に合わせて入れるかどうかまだ迷ってるけども…」と言われていた機能が1個、入ることに決まったようです。
Wildcards(ワイルドカード、万能札)と言われてたものが、Discards(破棄、捨て札)という呼び名に変わりましたが、機能的には同じものです。</p>
<p>要するに、<a href="http://ufcpp.net/study/csharp/datatype/deconstruction/">分解</a>や<a href="http://ufcpp.net/study/csharp/sp_ref.html#out-var">out var</a>で、要らない値のところに <code>_</code> を書けば無視できるという機能。
以下のようなコードが書けます。</p>
<pre class="source" title="discards">
<code><span class="reserved">using</span> System;
<span class="reserved">using</span> System.Collections.Generic;

<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> Main(<span class="reserved">string</span>[] args)
    {
        <span class="comment">// 分解と out var では _ が discard 使いになったっぽい</span>
        <span class="reserved">var</span> (_, sum) = Tally(<span class="reserved">new</span>[] { 1, 2, 3, 4, 5 });
        (_, <span class="reserved">var</span> sum2) = Tally(<span class="reserved">new</span>[] { 2, 3, 5, 7, 11 });
        <span class="reserved">var</span> (count, _) = Tally(<span class="reserved">new</span>[] { 1, 3, 5 });

        <span class="type">Console</span>.WriteLine((count, sum, sum2));

        <span class="reserved">if</span> (<span class="reserved">int</span>.TryParse(<span class="string">"123"</span>, <span class="reserved">out</span> _) &amp;&amp; <span class="reserved">int</span>.TryParse(<span class="string">"456"</span>, <span class="reserved">out</span> _))
            <span class="type">Console</span>.WriteLine(<span class="string">"successfully parsed"</span>);

        <span class="comment">// 既存文法に対しては未対応。</span>
        <span class="comment">// 計画上は出てたはずだけど、いつ対応するかは不明。</span>
        <span class="type">Func</span>&lt;<span class="reserved">int</span>, <span class="reserved">int</span>, <span class="reserved">int</span>&gt; f = (_, _) =&gt; 1;
    }

    <span class="reserved">static</span> (<span class="reserved">int</span> count, <span class="reserved">int</span> sum) Tally(<span class="type">IEnumerable</span>&lt;<span class="reserved">int</span>&gt; items)
    {
        <span class="reserved">var</span> count = 0;
        <span class="reserved">var</span> sum = 0;
        <span class="reserved">foreach</span> (<span class="reserved">var</span> x <span class="reserved">in</span> items)
        {
            count++;
            sum += x;
        }
        <span class="reserved">return</span> (count, sum);
    }
}
</code></pre>
<p>これ、今までのC#だと、<code>_</code>も有効な識別子なので、1度どこかで使ってしまうと、他の場所では二重定義扱いになってコンパイル エラーになります。
それが、とりあえず分解とout varというC# 7からの新構文な場所では、識別子ではなくてdiscards扱いされるようになりました。</p>
<p>ラムダ式の引数など、既存の文脈でどうするかってのはちょっと悩んでたみたいですけども、
とりあえず、「一度でも値の読み出しがあるなら変数扱い、なければdiscards扱い」みたいにしたいそうです。
ちょっと最終的な判断どうなっているのかまでは把握してないんですが、C# 7リリースまでには入るかも。</p>
 ]]></description>
				<pubDate>Wed, 14 Dec 2016 00:02:38 +0900</pubDate>
			</item>
			<item>
				<title>小ネタ null関係の演算子</title>
				<link>http://ufcpp.net/blog/2016/12/tipsnulloperation/</link>
				<description><![CDATA[ <p>今日は、<code>?.</code>とか<code>??</code>での、nullの判定方法について。</p>
<p>C# 6で導入されたnull条件演算子(<code>?.</code>)ですが、以下の2つの式が<strong>ほぼ</strong>同じ意味になります。</p>
<pre class="source" title="">
<code>x != <span class="reserved">null</span> ? x.M() : <span class="reserved">null
</code></pre>
<pre class="source" title="">
<code>x ?.M()
</code></pre>
<p>「ほぼ」であって「完全に同じ」と言えないのは、<code>==</code>演算子を呼ぶか呼ばないかが変わってしまうせいです。
前者(自分で<code>==</code>を呼んでいるやつ)はオーバーロードされた<code>==</code>を呼び出しますが、
後者(<code>?.</code>を利用)は呼びません(直接nullかどうか調べます)。</p>
<p>例えば、以下のように、本当はnullじゃないのにnullを自称する(<code>x == null</code>がtrueになる)クラスを作ると、ちょっと変な挙動になります。</p>
<pre class="source" title="null でないのに == nullなクラスを作る">
<code><span class="reserved">using</span> <span class="reserved">static</span> System.<span class="type">Console</span>;

<span class="reserved">class</span> <span class="type">NonDefault</span>&lt;<span class="type">T</span>&gt;
{
    <span class="reserved">public</span> <span class="type">T</span> Value { <span class="reserved">get</span>; }
    <span class="reserved">public</span> NonDefault(<span class="type">T</span> value) { Value = value; }

    <span class="reserved">public</span> <span class="reserved">override</span> <span class="reserved">string</span> ToString() =&gt; Value.ToString();

    <span class="comment">// Value が既定値のときに null と同値扱いする</span>
    <span class="comment">// null でないものとの x == null が true になることがある</span>
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">bool</span> <span class="reserved">operator</span> ==(<span class="type">NonDefault</span>&lt;<span class="type">T</span>&gt; x, <span class="type">NonDefault</span>&lt;<span class="type">T</span>&gt; y) =&gt;
        ReferenceEquals(x, <span class="reserved">null</span>) ? ReferenceEquals(y, <span class="reserved">null</span>) || Equals(y.Value, <span class="reserved">default</span>(<span class="type">T</span>)) :
        ReferenceEquals(y, <span class="reserved">null</span>) ? ReferenceEquals(x, <span class="reserved">null</span>) || Equals(x.Value, <span class="reserved">default</span>(<span class="type">T</span>)) :
        Equals(x.Value, y.Value);

    <span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">bool</span> <span class="reserved">operator</span> !=(<span class="type">NonDefault</span>&lt;<span class="type">T</span>&gt; x, <span class="type">NonDefault</span>&lt;<span class="type">T</span>&gt; y) =&gt; !(x == y);
}

<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="comment">// null の時には "null" と表示する ToString</span>
    <span class="reserved">static</span> <span class="reserved">string</span> A(<span class="type">NonDefault</span>&lt;<span class="reserved">int</span>&gt; x) =&gt; (x != <span class="reserved">null</span> ? x.ToString() : <span class="reserved">null</span>) ?? <span class="string">"null"</span>;
    <span class="comment">// A とほぼ同じ意味に見えて…</span>
    <span class="reserved">static</span> <span class="reserved">string</span> B(<span class="type">NonDefault</span>&lt;<span class="reserved">int</span>&gt; x) =&gt; x?.ToString() ?? <span class="string">"null"</span>;

    <span class="reserved">static</span> <span class="reserved">void</span> Main()
    {
        WriteLine(A(<span class="reserved">new</span> <span class="type">NonDefault</span>&lt;<span class="reserved">int</span>&gt;(1))); <span class="comment">// 1</span>
        WriteLine(B(<span class="reserved">new</span> <span class="type">NonDefault</span>&lt;<span class="reserved">int</span>&gt;(1))); <span class="comment">// 1</span>

        WriteLine(A(<span class="reserved">null</span>));                   <span class="comment">// null</span>
        WriteLine(B(<span class="reserved">null</span>));                   <span class="comment">// null</span>

        <span class="comment">// == を呼ぶ呼ばないことによる差がここで出る</span>
        WriteLine(A(<span class="reserved">new</span> <span class="type">NonDefault</span>&lt;<span class="reserved">int</span>&gt;(0))); <span class="comment">// null</span>
        WriteLine(B(<span class="reserved">new</span> <span class="type">NonDefault</span>&lt;<span class="reserved">int</span>&gt;(0))); <span class="comment">// 0</span>
    }
}
</code></pre>
<p>まあ、普通、こんな<code>==</code>演算子オーバーロードの仕方はしないんですが。
というか、参照型に対する<code>==</code>オーバーロード自体めったにしないんですが。
(通常、<code>==</code>演算子を使うのは、<code>Dictionary</code>のキーにしたい不変なクラスくらいです。)</p>
<p>ちなみに、このメソッド<code>A</code>、<code>B</code>のコンパイル結果はそれぞれ以下のようになります。
比較のために表にして命令ごとに並べてみましょう。</p>
<table>
<thead>
<tr>
	<th>A</th>
	<th>B</th>
</tr>
</thead>
<tbody>
<tr>
	<td><code>ldarg.0</code></td>
	<td><code>ldarg.0</code></td>
</tr>
<tr>
	<td><code>ldnull</code></td>
	<td><code>brtrue.s IL_0006</code></td>
</tr>
<tr>
	<td><code>call     NonDefault::op_Inequality</code></td>
	<td>&nbsp;</td>
</tr>
<tr>
	<td><code>brtrue.s IL_000c</code></td>
	<td>&nbsp;</td>
</tr>
<tr>
	<td><code>ldnull</code></td>
	<td><code>ldnull</code></td>
</tr>
<tr>
	<td><code>br.s     IL_0012</code></td>
	<td><code>br.s     IL_000c</code></td>
</tr>
<tr>
	<td><code>ldarg.0</code></td>
	<td><code>ldarg.0</code></td>
</tr>
<tr>
	<td><code>callvirt Object::ToString</code></td>
	<td><code>callvirt Object::ToString</code></td>
</tr>
<tr>
	<td><code>dup</code></td>
	<td><code>dup</code></td>
</tr>
<tr>
	<td><code>brtrue.s IL_001b</code></td>
	<td><code>brtrue.s IL_0015</code></td>
</tr>
<tr>
	<td><code>pop</code></td>
	<td><code>pop</code></td>
</tr>
<tr>
	<td><code>ldstr    &quot;null&quot;</code></td>
	<td><code>ldstr    &quot;null&quot;</code></td>
</tr>
<tr>
	<td><code>ret</code></td>
	<td><code>ret</code></td>
</tr>
</tbody>
</table>
<p>nullの判定方法(2行目～4行目)だけが違って、残りは全く同じです。
<code>==</code>演算子を呼ばずに直接nullを調べるなら<code>brtrue</code>命令1個でできます。</p>
<p>ちなみに、<code>brtrue</code>は&quot;branch if true&quot;の略で、
「直前の結果がtrueだったらジャンプする」という命令になります。
整数の0とか、参照型のnullとかはfalse扱い。</p>
<p>この挙動は<a href="http://ufcpp.net/study/csharp/sp2_nullable.html#coalescing">null合体演算子</a>(<code>??</code>)でも同様です。</p>
<h2>おまけ: <code>throw null</code></h2>
<p>話題は変わりますが、<code>?.</code>の中身をILレベルで覗いたついでと言ってはなんですが、ちょっとしたおまけ。</p>
<p>時々、「<code>throw null</code>と書くと、<code>throw new NullReferenceException()</code>と同じ意味になる」的な誤解(？)を見かけたりします。
コンパイル結果的には当然、全然違うんですよね。</p>
<p>以下のように書いた場合、</p>
<pre class="source" title="throw null">
<code><span class="reserved">static</span> <span class="reserved">void</span> X() { <span class="reserved">throw</span> <span class="reserved">null</span>; }
<span class="reserved">static</span> <span class="reserved">void</span> Y() { <span class="reserved">throw</span> <span class="reserved">new</span> <span class="type">NullReferenceException</span>(); }
</code></pre>
<p>コンパイル結果は以下の通り。</p>
<pre class="source" title="throw null">
<code>.method <span class="reserved">private</span> <span class="reserved">hidebysig</span> <span class="reserved">static</span> <span class="reserved">void</span>  X() <span class="reserved">cil</span> <span class="reserved">managed</span>
{
  <span class="comment">// コード サイズ       2 (0x2)
</span>  .maxstack  8
  IL_0000:  ldnull
  IL_0001:  throw
} <span class="comment">// end of method Program::X
</span>
.method <span class="reserved">private</span> <span class="reserved">hidebysig</span> <span class="reserved">static</span> <span class="reserved">void</span>  Y() <span class="reserved">cil</span> <span class="reserved">managed</span>
{
  <span class="comment">// コード サイズ       6 (0x6)
</span>  .maxstack  8
  IL_0000:  newobj     <span class="reserved">instance</span> <span class="reserved">void</span> [mscorlib]System.NullReferenceException::<span class="reserved">.ctor</span>()
  IL_0005:  throw
} <span class="comment">// end of method Program::Y
</span>
</code></pre>
<p>割かしそのまんまなILコードです。
nullをロード(<code>ldnull</code>)して、<code>throw</code>命令を実行。
要するに、前者は(<code>throw</code>命令の実行に失敗して)実行エンジンが<code>NullReferenceException</code>を作って投げていて、
後者は自分自身で作った<code>NullReferenceException</code>を投げている。
まあ、結果的には同じような挙動をするんですが。</p>
 ]]></description>
				<pubDate>Tue, 13 Dec 2016 00:37:03 +0900</pubDate>
			</item>
			<item>
				<title>小ネタ 隠し演算子(？)</title>
				<link>http://ufcpp.net/blog/2016/12/tipstadpoleoperator/</link>
				<description><![CDATA[ <p>C#には隠しキーワードとして<a href="http://ufcpp.net/study/csharp/sp_makeref.html"><code>__makeref</code>などの見慣れないキーワードがある</a>という話はたまに話題に出てきますが、実は隠し演算子もあります。</p>
<table>
<thead>
<tr>
	<th>演算子</th>
	<th>同じ結果の式</th>
	<th>意味合い</th>
</tr>
</thead>
<tbody>
<tr>
	<td><code>-~x</code></td>
	<td><code>x + 1</code></td>
	<td><code>x</code>に向かって値が入っているイメージ</td>
</tr>
<tr>
	<td><code>~-x</code></td>
	<td><code>x - 1</code></td>
	<td><code>x</code>から値が出ていくイメージ</td>
</tr>
</tbody>
</table>
<p>副作用を起こさない(非変)インクリメント、デクリメント(non-modified increment/decrement)です。
実際、以下のようなコードを実行することができます。</p>
<pre class="source" title="非変インクリメント・デクリメント">
<code><span class="reserved">var</span> a = 10;
<span class="type">Console</span>.WriteLine(-~a); <span class="comment">// 11</span>
<span class="type">Console</span>.WriteLine(~-a); <span class="comment">// 9</span>
</code></pre>
<p><a href="http://ideone.com/SSnP7U">ideone</a>とかでも実行できます。
ideoneは確かMonoで動いているはずで、MonoのC#コンパイラーもひそかに対応しているということですね。</p>
<p>こいつは、演算子の形状からtadpole (オタマジャクシ)とか言われたりもします。
(<code>?.</code> なんかもエルビス プレスリーの髪型っぽく見えるという話からelvis演算子とか呼ばれたりもします。それと同種の愛称です。)</p>
<p><code>x + 1</code>でいいじゃないかと思うかもしれませんが、
単項演算子なので優先度が高いという利点があります。
<code>(x + 1) * (y - 1)</code>というような式が、`-~x*~-y'となります。</p>
<p>一方で、単項演算子の±1であれば、<code>++</code> (インクリメント)と<code>--</code> (デクリメント)もあります。
しかし、これらは副作用を伴っていて、<code>x</code>の値を書き換えてしまいます。</p>
<table>
<thead>
<tr>
	<th>演算子</th>
	<th>同じ結果の式</th>
</tr>
</thead>
<tbody>
<tr>
	<td><code>++x</code></td>
	<td><code>x += 1</code></td>
</tr>
<tr>
	<td><code>--x</code></td>
	<td><code>x -= 1</code></td>
</tr>
</tbody>
</table>
<p>副作用を伴う式というはあまり行儀がいいものではないので、その副作用なし版がこっそり用意されているというのが<code>-~</code>と<code>~-</code>です。</p>
<p>まあ、利点と言っても微々たるものですし、どっちがプラスでどっちがマイナスかわかりにくいですから、正式採用とはならず、仕様書等には載っていません。</p>
<p><br/>
<br/>
<br/>
<br/></p>
<h2>種明かし</h2>
<p>さて、まあ、嘘なわけですが。
実行できる嘘。</p>
<p>昔同じネタをちょっと取り上げたことはあるんで覚えてらっしゃる方もいらっしゃいますかね。</p>
<ul>
<li><a href="http://ufcpp.net/blog/2015/5/pickuproslyn27/">ピックアップRoslyn 5/27: Support the tadpole operators</a></li>
</ul>
<p>要するに、</p>
<ul>
<li><a href="https://blogs.msdn.microsoft.com/oldnewthing/20150525-00/?p=45044/">The Old New Thingの冗談</a>を真に受ける人が結構いた</li>
<li><a href="https://github.com/dotnet/roslyn/issues/3072">真に受けて「C# にも入れない？」とか言い出す人までいた</a></li>
<li>エイプリルフールにでもやれよ…</li>
</ul>
<p>という話だったんですが…</p>
<p>真に受ける人が多いということは、ちゃんとした解説書かなきゃダメなのかなというのが、今回の本当の主題。</p>
<p>実際、つい最近も、2の補数表現の話とかを知らない人にこの話を説明したりしたんですよね。ピックアップRoslynのついででさらっと流すのはもったいなかったかなぁと。</p>
<h3>本当は <code>-</code> と <code>~</code> の組み合わせ</h3>
<p>これ、要するに、以下の意味です。</p>
<table>
<thead>
<tr>
	<th>元</th>
	<th>括弧で整理</th>
</tr>
</thead>
<tbody>
<tr>
	<td><code>-~x</code></td>
	<td><code>-(~x)</code></td>
</tr>
<tr>
	<td><code>~-x</code></td>
	<td><code>~(-x)</code></td>
</tr>
</tbody>
</table>
<p>単項演算子が2個並んでいるだけ。</p>
<p>たぶん、3つのはまりどころがあります。</p>
<ul>
<li><code>~</code>演算子とかめったに使わない</li>
<li>ビット反転とマイナスの関係を知らない人がそこそこいる</li>
<li>単項演算子をくっつけて書くのはどうなのよ</li>
</ul>
<h3>ビット反転</h3>
<p>真に受ける人が多かった理由の1つは、<code>~</code>演算子とかめったに使わないからでしょうね。
そもそも<code>~</code>がC++とかC#で有効な演算子なことを知らない/忘れている人がそれなりにいるんでしょう。
というか、ビット操作とか2進数での数値表現がまず苦手って人も見ますもんねぇ、ちらほら。</p>
<p><code>~</code>はビット反転の意味です。以下の例のように、すべてのビットの0と1を逆にします。</p>
<p><img src="/media/1107/bitflip.png" alt="ビット反転" /></p>
<h3>ビット反転とマイナスの関係</h3>
<p>次に必要な説明は、ビット反転とマイナスの組み合わせでどうして±1になるのかです。
ビット反転<code>~</code>とマイナス<code>-</code>は、常に以下の式を満たします。</p>
<p><code>~x + 1 == -x</code></p>
<p>例えば、以下のようなコードを書くと、<code>throw</code>の行は通らずプログラムが正常終了します。</p>
<pre class="source" title="~x + 1 == -x の確認">
<code><span class="reserved">using</span> System;

<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> Main()
    {
        <span class="reserved">for</span> (<span class="reserved">int</span> x = 0; x &lt; 256; x++)
        {
            <span class="reserved">if</span> (~x + 1 == -x) <span class="reserved">continue</span>;

            <span class="reserved">throw</span> <span class="reserved">new</span> <span class="type">InvalidOperationException</span>();
        }
    }
}
</code></pre>
<p>これは、以下の図のように考えれば説明が付きます。</p>
<p><img src="/media/1108/complement.png" alt="ビット反転 + 1" /></p>
<ol>
<li>元の数字と、ビット反転した数字を足すと、全ての桁で 1 + 0 が起きるわけで、
結果は全桁1になります</li>
<li>これに1を足すと、桁上がりによって0が並びます</li>
<li>オーバーフロー(桁上がりしてしまった最上位桁)を無視すると、完全に0になります</li>
<li>すなわち、<code>x</code>と<code>~x + 1</code>を足すと0になります</li>
<li><code>-x</code>というのは「<code>x</code>と足して0になる数」のことを指すわけで、<code>~x + 1</code>は<code>-x</code>と等しいはずです。</li>
</ol>
<p>実際、符号付き(この例で言うと8 bitなので<code>sbyte</code>)の-123と、
符号なし(<code>byte</code>)の133 = 256 - 123は、ビット表現としては全く同じ<code>1000 0101</code>になります(123のビット反転は132です。132 + 1 = 133 = -123)。</p>
<p>この考え方は、コンピューターのハードウェアを作る上で非常に便利です。</p>
<ol>
<li>負の数を「ビット反転 + 1」で表すものとする</li>
<li>この場合、<code>a - b</code>は<code>a + ~b + 1</code>となる</li>
<li>つまり、加算回路をそのまま流用して減算回路を作れる</li>
</ol>
<p>ということで、だいたいのハードウェアでこの「ビット反転 + 1」で負の数を表現する方式が採用されています。
この表現形式を「2の補数(two's complement)表現」と言います。
わざわざ「2の」とかいう名前が付いているのは、他の方式もあったからなんですが、まあ、現存していません。</p>
<h3>単項演算子をくっつけて書く</h3>
<p>あとは、演算子をくっつける書き方自体がどうなのか、という話はあります。</p>
<p>だって、識別子(変数名とか)の場合、<code>ab</code>と<code>a b</code>は違う意味になるじゃないですか。
前者は「ab」という名前の1つの識別子、後者「a」と「b」が並んでる。
なのに、<code>~-</code>と<code>~ -</code>は同じ意味で、<code>~</code>と<code>-</code>に分解される。</p>
<p><code>~-</code>みたいな、複数文字で1つの演算子にできれば、演算子オーバーロードに幅ができて便利かもしれません。
実際、F#なんかはそれを認めています。</p>
<ul>
<li><a href="https://docs.microsoft.com/ja-jp/dotnet/articles/fsharp/language-reference/operator-overloading">F# Operator Overloading</a></li>
</ul>
<p>C#でも、<code>~-</code>みたいに書かれると、一瞬それを期待しちゃうのかもしれません。
でも、実際には、<code>~-</code>は2つに分解されて、複数文字1演算子はできません。</p>
<h4>おまけ: くっつけて書けるとそれはそれでひどい</h4>
<p>常に一貫して「演算子は1文字1文字全部区切る」ってルールならまだしも、いくつか例外が存在しているのがまた面倒です。
<code>++</code> (インクリメント)とか<code>&gt;=</code> (大なりイコール)とか<code>=&gt;</code> (ラムダ式の矢印)とかは2文字で1演算子。だったら、「<code>~-</code>で1演算子」も期待しかねない。</p>
<p>インクリメントなんて、<code>+</code>と<code>++</code>がそれぞれ別の意味になるもんだから本当にひどくて。
<code>a+++b</code>って式はC#などでは有効な式なんですが、どういう意味になるかぱっと見ではわからない。なんせ、以下の3つの式、どれも有効で、それぞれ違う結果になります。</p>
<ul>
<li><code>a++ +b</code></li>
<li><code>a+ ++b</code></li>
<li><code>a+ + +b</code></li>
</ul>
<pre class="source" title="a+++b">
<code><span class="reserved">using</span> <span class="reserved">static</span> System.<span class="type">Console</span>;

<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> Main()
    {
        <span class="reserved">int</span> a, b;

        a = 1; b = 1;
        WriteLine(<span class="string">$"</span>{a++ +b}<span class="string">, </span>{a}<span class="string">, </span>{b}<span class="string">"</span>); <span class="comment">// 2, 2, 1: (a++) + b</span>
        a = 1; b = 1;
        WriteLine(<span class="string">$"</span>{a+ ++b}<span class="string">, </span>{a}<span class="string">, </span>{b}<span class="string">"</span>); <span class="comment">// 3, 1, 2: a + (++b)</span>
        a = 1; b = 1;
        WriteLine(<span class="string">$"</span>{a+ + +b}<span class="string">, </span>{a}<span class="string">, </span>{b}<span class="string">"</span>); <span class="comment">// 2, 1, 1: a + (+(+b))</span>
        a = 1; b = 1;
        WriteLine(<span class="string">$"</span>{a+++b}<span class="string">, </span>{a}<span class="string">, </span>{b}<span class="string">"</span>); <span class="comment">// 2, 2, 1: つまり、a+++b は a++ +b 扱い</span>
    }
}
</code></pre>
<p>Swiftなんかだと、単項演算子を隣接させるのを禁止してるみたいですね。
<code>-~x</code>はエラーになります。</p>
<p>かつ、単項演算子とオペランドの間は逆にスペースを挟むのを禁止しているようで。
<code>- ~x</code>という書き方もエラー。
括弧を使って<code>-(~x)</code>と書くのを義務付けているようです。</p>
<p>まあ、確かに括弧が付いている方が見やすくて人的ミスは起こしにくいでしょう。
一方で、関数適用は<code>f  (x)</code>とか書けるのに、単項演算子は<code>~ (x)</code>とは書けないっていうちょっと気持ち悪い状態ではあります。</p>
 ]]></description>
				<pubDate>Mon, 12 Dec 2016 00:02:56 +0900</pubDate>
			</item>
			<item>
				<title>小ネタ 隠しメンバー</title>
				<link>http://ufcpp.net/blog/2016/12/tipsimplicitmembers/</link>
				<description><![CDATA[ <p>今日は、C# 上からは見えない隠しメンバーが作られるという話。
「覚えがないのになぜか『すでに定義があります』っていう名前被りのコンパイル エラーが出た」なんてこともあり得ます。</p>
<p>C# は .NET 向け言語の代表的な位置づけの言語ではありますが、だからと言って、C# の機能と .NET IL (中間言語)の機能は同じではありません。
C# コンパイラーによって、ILのレベルでは結構身に覚えのないメンバーが追加されます。</p>
<p>例えば以下のようなコードを書くだけで、自動的に追加されたメンバーがたくさん出てきます。</p>
<pre class="source" title="全メンバーの列挙">
<code><span class="reserved">using</span> System;
<span class="reserved">using</span> <span class="reserved">static</span> System.<span class="type">Console</span>;
<span class="reserved">using</span> <span class="reserved">static</span> System.Reflection.<span class="type">BindingFlags</span>;

<span class="reserved">class</span> <span class="type">C</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> X { <span class="reserved">get</span>; <span class="reserved">set</span>; }
    <span class="reserved">public</span> <span class="reserved">int</span> <span class="reserved">this</span>[<span class="reserved">int</span> index] { <span class="reserved">get</span> { <span class="reserved">return</span> index; } <span class="reserved">set</span> { } }
    <span class="reserved">public</span> <span class="reserved">event</span> <span class="type">Action</span> E;
}

<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> Main()
    {
        <span class="reserved">foreach</span> (<span class="reserved">var</span> x <span class="reserved">in</span> <span class="reserved">typeof</span>(<span class="type">C</span>).GetMembers(Public | NonPublic | Instance | DeclaredOnly))
        {
            WriteLine(x.Name);
        }
    }
}
</code></pre>
<p>実行結果は以下の通り。</p>
<pre class="console" title="全メンバーの列挙">
<code>get_X
set_X
add_E
remove_E
get_Item
set_Item
.ctor
X
Item
E
&lt;X&gt;k__BackingField
E
</code></pre>
<p>今日はこれらについて説明して行きます。</p>
<h2>コンストラクター</h2>
<p>これはまあ、わかりやすいですね。C# のクラスは、明示的にコンストラクターを書かなくても<code>new Class()</code>と書けるわけで、暗黙的にコンストラクターが1つ作られています(クラスで、コンストラクターを1つも書かなかった場合だけ)。</p>
<p>リフレクション的には、コンストラクターは<code>.ctor</code>という名前で見えます。
ちなみに、生成されるILを覗いてみると以下のような感じ。</p>
<pre class="source" title="コンストラクターの中身">
<code>.class <span class="reserved">private</span> <span class="reserved">auto</span> <span class="reserved">ansi</span> <span class="reserved">beforefieldinit</span> C
       <span class="reserved">extends</span> [mscorlib]System.Object
{
  .method <span class="reserved">public</span> <span class="reserved">hidebysig</span> <span class="reserved">specialname</span> <span class="reserved">rtspecialname</span> 
          <span class="reserved">instance</span> <span class="reserved">void</span>  <span class="reserved">.ctor</span>() <span class="reserved">cil</span> <span class="reserved">managed</span>
  {
    .maxstack  8
    IL_0000:  ldarg.0
    IL_0001:  call       <span class="reserved">instance</span> <span class="reserved">void</span> [mscorlib]System.Object::<span class="reserved">.ctor</span>()
    IL_0006:  nop
    IL_0007:  ret
  }
}
</code></pre>
<p><code>rtspecialname</code>とかいう特別そうなフラグが付いているのと、
名前が変という以外はただのメソッドです。
中身も親クラスのコンストラクターを呼んでいるだけ。</p>
<h2>プロパティ</h2>
<p>プロパティは、<code>get</code>、<code>set</code>に応じたメソッドと、
自動実装プロパティであればフィールドが1つ作られます。
今回の例では、<code>X</code>は自動実装プロパティで、<code>get</code>、<code>set</code>共に持っているので以下のようなILが生成されます。</p>
<pre class="source" title="プロパティの中身">
<code>  .field <span class="reserved">private</span> <span class="reserved">int32</span> '&lt;X&gt;k__BackingField'
  .custom <span class="reserved">instance</span> <span class="reserved">void</span> [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::<span class="reserved">.ctor</span>() = ( 01 00 00 00 ) 

  .property <span class="reserved">instance</span> <span class="reserved">int32</span> X()
  {
    .get <span class="reserved">instance</span> <span class="reserved">int32</span> C::get_X()
    .set <span class="reserved">instance</span> <span class="reserved">void</span> C::set_X(<span class="reserved">int32</span>)
  }

  .method <span class="reserved">public</span> <span class="reserved">hidebysig</span> <span class="reserved">specialname</span> <span class="reserved">instance</span> <span class="reserved">int32</span> 
          get_X() <span class="reserved">cil</span> <span class="reserved">managed</span>
  {
    .custom <span class="reserved">instance</span> <span class="reserved">void</span> [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::<span class="reserved">.ctor</span>() = ( 01 00 00 00 ) 
    .maxstack  8
    IL_0000:  ldarg.0
    IL_0001:  ldfld      <span class="reserved">int32</span> C::'&lt;X&gt;k__BackingField'
    IL_0006:  ret
  }

  .method <span class="reserved">public</span> <span class="reserved">hidebysig</span> <span class="reserved">specialname</span> <span class="reserved">instance</span> <span class="reserved">void</span> 
          set_X(<span class="reserved">int32</span> 'value') <span class="reserved">cil</span> <span class="reserved">managed</span>
  {
    .custom <span class="reserved">instance</span> <span class="reserved">void</span> [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::<span class="reserved">.ctor</span>() = ( 01 00 00 00 ) 
    .maxstack  8
    IL_0000:  ldarg.0
    IL_0001:  ldarg.1
    IL_0002:  stfld      <span class="reserved">int32</span> C::'&lt;X&gt;k__BackingField'
    IL_0007:  ret
  }
</code></pre>
<p>意味的には以下のような感じ。</p>
<ul>
<li><code>&lt;&gt;</code>が含まれる読めた代物じゃないフィールドができる</li>
<li><code>get_</code>、<code>set_</code>から始まるメソッドができる</li>
<li>フィールドとメソッドには<code>CompilerGenerated</code>属性が付いてる</li>
<li>プロパティの定義自体は、メソッドを参照しているだけ</li>
</ul>
<p>フィールドは、通常のC#では書けないような記号入りの名前なので特に問題を起こさないんですが、
メソッドの方は被りがあり得ます。つまり、以下のコードはコンパイル エラーを起こします。</p>
<pre class="source" title="エラーを起こすコード">
<code><span class="reserved">class</span> <span class="type">C</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> X { <span class="error"><span class="reserved">get</span></span>; }
    <span class="reserved">int</span> get_X() =&gt; 0;
}
</code></pre>
<p>しかもエラーを起こすのは <code>get</code> のところ。</p>
<h2>インデクサー</h2>
<p>インデクサーなどというものは存在しない。いいね？</p>
<p>C#のインデクサーは、ILのレベルでは<code>Item</code>という名前のプロパティになっています。</p>
<pre class="source" title="インデクサーの中身">
<code>  .custom <span class="reserved">instance</span> <span class="reserved">void</span> [mscorlib]System.Reflection.DefaultMemberAttribute::<span class="reserved">.ctor</span>(<span class="reserved">string</span>) = ( 01 00 04 49 74 65 6D 00 00 ) <span class="comment">// ...Item..
</span>
    .property <span class="reserved">instance</span> <span class="reserved">int32</span> Item(<span class="reserved">int32</span>)
  {
    .get <span class="reserved">instance</span> <span class="reserved">int32</span> C::get_Item(<span class="reserved">int32</span>)
    .set <span class="reserved">instance</span> <span class="reserved">void</span> C::set_Item(<span class="reserved">int32</span>,
                                   <span class="reserved">int32</span>)
  }

  .method <span class="reserved">public</span> <span class="reserved">hidebysig</span> <span class="reserved">specialname</span> <span class="reserved">instance</span> <span class="reserved">int32</span> 
          get_Item(<span class="reserved">int32</span> index) <span class="reserved">cil</span> <span class="reserved">managed</span>
  {
    .maxstack  1
    .locals init ([0] <span class="reserved">int32</span> V_0)
    IL_0000:  nop
    IL_0001:  ldarg.1
    IL_0002:  stloc.0
    IL_0003:  br.s       IL_0005

    IL_0005:  ldloc.0
    IL_0006:  ret
  }

  .method <span class="reserved">public</span> <span class="reserved">hidebysig</span> <span class="reserved">specialname</span> <span class="reserved">instance</span> <span class="reserved">void</span> 
          set_Item(<span class="reserved">int32</span> index,
                   <span class="reserved">int32</span> 'value') <span class="reserved">cil</span> <span class="reserved">managed</span>
  {
    .maxstack  8
    IL_0000:  nop
    IL_0001:  ret
  }
</code></pre>
<p>意味的には以下のような感じ。</p>
<ul>
<li><code>Item</code>という名前のプロパティが作られる</li>
<li>
プロパティは実は引数を取れる
<ul>
<li>(C#では無理だけど、VBなら引数付きプロパティも書ける)</li>
</ul>
</li>
<li><code>DefaultMember</code>属性で<code>Item</code>プロパティを指定している</li>
</ul>
<p>つまるところ、インデクサー = 「名前を省略していい引数付きプロパティ」です。</p>
<p><code>Item</code>に展開されるので、もちろん、以下のコードは<code>this</code>のところでコンパイル エラー。</p>
<pre class="source" title="エラーを起こすコード">
<code><span class="reserved">class</span> <span class="type">C</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> <span class="error"><span class="reserved">this</span></span>[<span class="reserved">int</span> index] { <span class="reserved">get</span> { <span class="reserved">return</span> index; } }
    <span class="reserved">int</span> Item { <span class="reserved">get</span>; }
}
</code></pre>
<p><code>get_Item</code>メソッドもダメです。<code>get</code>のところでエラー。</p>
<pre class="source" title="エラーを起こすコード">
<code><span class="reserved">class</span> <span class="type">C</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> <span class="reserved">this</span>[<span class="reserved">int</span> index] { <span class="error"><span class="reserved">get</span></span> { <span class="reserved">return</span> index; } }
    <span class="reserved">int</span> get_Item(<span class="reserved">int</span> index) =&gt; 0;
}
</code></pre>
<p><code>Item</code>プロパティは普通に使いそうな名前なので、罠を踏むとしたらこれが一番頻出しそうなやつです。</p>
<p>ちなみに、回避方法も、まあ、あって、インデクサーから生成されるプロパティの名前は変更できます。</p>
<pre class="source" title="インデクサーから生成されるプロパティの名前を明示的に指定">
<code><span class="reserved">class</span> <span class="type">C</span>
{
    [System.Runtime.CompilerServices.<span class="type">IndexerName</span>(<span class="string">"Indexer"</span>)]
    <span class="reserved">public</span> <span class="reserved">int</span> <span class="reserved">this</span>[<span class="reserved">int</span> index] { <span class="reserved">get</span> { <span class="reserved">return</span> index; } }

    <span class="comment">// ↑これで Item は生成されなくなるので、自前のもの↓と被らなくなる</span>

    <span class="reserved">int</span> Item { <span class="reserved">get</span>; }
    <span class="reserved">int</span> get_Item(<span class="reserved">int</span> index) =&gt; 0;
}
</code></pre>
<p>ちなみに、C#コード上はインデクサーに<code>IndexerName</code>属性が付いていますが、
コンパイル結果的にはクラスに対する<code>DefaultMember</code>属性に変換されます。</p>
<h2>イベント</h2>
<p>最後は、他の言語から来た人が困惑する機能ナンバー1、イベントです。
もっと難しい機能もたくさんありますけど、利用頻度の割に複雑という意味では断トツではないかと。
(使う頻度は多少あるけど、作る頻度はかなり低いんじゃないでしょうか。)</p>
<p>プロパティに近いんですが、<code>get</code>、<code>set</code>の代わりに<code>add</code>、<code>remove</code>です。
自動実装でフィールドが作れる部分は同じです。</p>
<pre class="source" title="イベントの中身">
<code>  .event [mscorlib]System.Action E
  {
    .addon <span class="reserved">instance</span> <span class="reserved">void</span> C::add_E(<span class="reserved">class</span> [mscorlib]System.Action)
    .removeon <span class="reserved">instance</span> <span class="reserved">void</span> C::remove_E(<span class="reserved">class</span> [mscorlib]System.Action)
  } <span class="comment">// end of event C::E
</span>
  .field <span class="reserved">private</span> <span class="reserved">class</span> [mscorlib]System.Action E
  .custom <span class="reserved">instance</span> <span class="reserved">void</span> [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::<span class="reserved">.ctor</span>() = ( 01 00 00 00 ) 

    .method <span class="reserved">public</span> <span class="reserved">hidebysig</span> <span class="reserved">specialname</span> <span class="reserved">instance</span> <span class="reserved">void</span> 
          add_E(<span class="reserved">class</span> [mscorlib]System.Action 'value') <span class="reserved">cil</span> <span class="reserved">managed</span>
  {
    .custom <span class="reserved">instance</span> <span class="reserved">void</span> [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::<span class="reserved">.ctor</span>() = ( 01 00 00 00 ) 
    <span class="comment">// 結構長いのでさすがに省略
</span>  }

  .method <span class="reserved">public</span> <span class="reserved">hidebysig</span> <span class="reserved">specialname</span> <span class="reserved">instance</span> <span class="reserved">void</span> 
          remove_E(<span class="reserved">class</span> [mscorlib]System.Action 'value') <span class="reserved">cil</span> <span class="reserved">managed</span>
  {
    .custom <span class="reserved">instance</span> <span class="reserved">void</span> [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::<span class="reserved">.ctor</span>() = ( 01 00 00 00 ) 
    <span class="comment">// 結構長いのでさすがに省略
</span>  }
</code></pre>
<p>プロパティと似た感じで、</p>
<ul>
<li>フィールドができる</li>
<li><code>add_</code>、<code>remove_</code>から始まるメソッドができる</li>
<li>フィールドとメソッドには<code>CompilerGenerated</code>属性が付いてる</li>
<li>イベントの定義自体は、メソッドを参照しているだけ</li>
</ul>
<p>という状態なんですが、ちょっと違うのは、以下の部分。</p>
<ul>
<li>フィールドの名前がイベントの名前とまったく同じ(この例の場合<code>E</code>)</li>
<li>自動生成されるメソッドの中身はほんと長い(参考: <a href="http://ufcpp.net/study/csharp/sp_event.html#auto-event">補足: 自動イベント</a>)</li>
</ul>
<p>C#では許されていませんが、ILレベルだと、メンバーの種類が違えば同じ名前を使えます。</p>
<p>そして、実は、イベントを触っているように見えて、実は裏で作られたフィールドを触っているという事態に。</p>
<pre class="source" title="Eの参照の仕方">
<code><span class="reserved">class</span> <span class="type">C</span>
{
    <span class="reserved">public</span> <span class="reserved">event</span> <span class="type">Action</span> E;

    <span class="comment">// 登録の側は add_E が呼ばれてるんだけど</span>
    <span class="reserved">public</span> <span class="reserved">void</span> Register() =&gt; E += Handler;
    <span class="reserved">void</span> Handler() { }

    <span class="comment">// 呼び出し側では、実はイベントの E じゃなくて、フィールドの E</span>
    <span class="reserved">public</span> <span class="reserved">void</span> Invoke() =&gt; E();
}
</code></pre>
<p>この<code>Invoke</code>メソッドの中を見てみると以下のような感じ。<code>ldfld</code>命令はフィールド読み込みのための命令です。</p>
<pre class="source" title="Invokeメソッドの中身">
<code>.method <span class="reserved">public</span> <span class="reserved">hidebysig</span> <span class="reserved">instance</span> <span class="reserved">void</span>  Call() <span class="reserved">cil</span> <span class="reserved">managed</span>
{
  .maxstack  8
  IL_0000:  ldarg.0
  IL_0001:  ldfld      <span class="reserved">class</span> [mscorlib]System.Action C::E
  IL_0006:  callvirt   <span class="reserved">instance</span> <span class="reserved">void</span> [mscorlib]System.Action::Invoke()
  IL_000b:  nop
  IL_000c:  ret
}
</code></pre>
<p>つまり、イベントを明示的に実装すると、<code>E()</code>みたいな呼び出しはできなくなります。</p>
<pre class="source" title="イベントを明示的実装に変えると、フィールドのEが消える">
<code><span class="reserved">class</span> <span class="type">C</span>
{
    <span class="reserved">private</span> <span class="type">Action</span> _e;
    <span class="reserved">public</span> <span class="reserved">event</span> <span class="type">Action</span> E
    {
        <span class="reserved">add</span> { _e += <span class="reserved">value</span>; }
        <span class="reserved">remove</span> { _e -= <span class="reserved">value</span>; }
    }

    <span class="comment">// 明示的に add/remove を実装すると、自動実装なフィールドの E が消える</span>
    <span class="comment">// ↓このコードが書けなくなる</span>
    <span class="reserved">public</span> <span class="reserved">void</span> Invoke() =&gt; E();
}
</code></pre>
<p>イベントの明示的な実装とかめったにするものじゃないのでそんなに踏まないと思いますが、一応注意が必要です。</p>
 ]]></description>
				<pubDate>Sun, 11 Dec 2016 00:03:15 +0900</pubDate>
			</item>
			<item>
				<title>小ネタ フォーマット文字識別子</title>
				<link>http://ufcpp.net/blog/2016/12/tipsformattingcharacter/</link>
				<description><![CDATA[ <p>いい加減、小ネタらしい小ネタを書かないとタイトル詐欺臭いのでほんとに小ネタを。</p>
<p>C#では、以下のようなコードが書けたりします。変数<code>ab</code>を用意して、<code>a\u200db</code>って変数に書き込むと、<code>ab</code>の値が変わるという。
要するに、この2つは識別子としては同一扱いされます。</p>
<pre class="source" title="Zero Width Joiner 識別子">
<code><span class="reserved">using</span> System;

<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> Main()
    {
        <span class="reserved">var</span> ab = 0;
        a\u200db = 1; <span class="comment">// ab と同じ扱い。\u200d は Zero Width Joiner</span>
        <span class="type">Console</span>.WriteLine(ab); <span class="comment">// 1</span>
    }
}
</code></pre>
<p>この挙動を説明するには、以下の2つの仕様が出てきます。</p>
<ul>
<li>
Unicode エスケープ シーケンス
<ul>
<li>参考: <a href="https://msdn.microsoft.com/ja-jp/library/aa664669.aspx">2.4.1 Unicode 文字エスケープ シーケンス</a></li>
</ul>
</li>
<li>
識別子におけるフォーマット文字の挙動
<ul>
<li>参考: <a href="https://msdn.microsoft.com/ja-jp/library/aa664670.aspx">2.4.2 識別子</a></li>
</ul>
</li>
</ul>
<p>1つのUnicodeエスケープ シーケンスは、<code>\u</code>に続けて4桁の16進数を打つか、<code>\U</code>に続けて8桁の16進数を打つと、その番号に対応したUnicode文字に変換されるというものです。このエスケープ シーケンスは、文字列リテラルの外、どこででも有効です。例えば、以下のようなことも可能。aの文字は、UnicodeではU+61です。</p>
<pre class="source" title="a と \u0061 は同じ">
<code><span class="reserved">using</span> System;

<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> Main()
    {
        <span class="reserved">var</span> a = 0;
        \u0061 = 1;
        <span class="type">Console</span>.WriteLine(a);
    }
}
</code></pre>
<p>もう1つは、フォーマット文字は識別子に含められるけど、除外して考えるという仕様。
フォーマット文字ってのは、文字を描画方法とかを指定するための不可視文字で、例えば以下のようなものがあります。</p>
<ul>
<li>Zero Width Joiner (U+200D): その左右の文字が不可分なことを表す。ゼロ幅接合子。略称 ZWJ。</li>
<li>Left-to-Right Mark (U+200E): 文字を左から右に向かって描画すべきということを表す</li>
<li>Right-to-Left Mark (U+200F): 同上、右から左</li>
</ul>
<p>一部の自然言語でこの手の制御が必要だけども、見えない文字だからこの文字のあるなしで別識別子にはしたくないっていうことでしょう。</p>
<p>これら2つを組み合わせた結果が冒頭のコードです。<code>a\u200db</code>は、<code>a</code>と<code>b</code>の間にZWJを挟んだ状態で、結果的に、識別子としてはZWJが無視されて、<code>ab</code>として扱われます。</p>
<p>まあ、見えない文字とか無視すべきですよね。
普通、見えない文字はそもそも識別子として使えなくしてるものなんですが、Right-to-Left Markとかは、アラビア語プログラミングとかすると使うかもしれないですもんねぇ。「使う」というか、もしかしたらエディターによって勝手に挿入されるかもしれず。
その場合、無視すべき、ということなんでしょう。</p>
<p><a href="http://swiftlang.ng.bluemix.net/#/repl/584acaa094b17a360a54c2bc">無視しないプログラミング言語もありますが</a>…</p>
<h2>Unicode Consortium で規定</h2>
<p>この挙動、どうも、<a href="http://www.unicode.org/">Unicode Consortium</a>のレポートに基づいてるみたいです。</p>
<p><a href="http://www.unicode.org/reports/tr15/tr15-18.html">Unicode Technical Report #15</a>の、<a href="http://www.unicode.org/reports/tr15/tr15-18.html#Programming%20Language%20Identifiers">Annex7: Annex 7: Programming Language Identifiers</a>のところ。
プログラミング言語の識別子に使える文字はどうあるべきか、みたいな話が結構詳細に書かれています。
これに沿っている言語は他にもありそうなので、試してみるといいかも。</p>
 ]]></description>
				<pubDate>Sat, 10 Dec 2016 00:23:13 +0900</pubDate>
			</item>
			<item>
				<title>小ネタ 同期コンテキストを拾わないTask型</title>
				<link>http://ufcpp.net/blog/2016/12/tipscontextfreetask/</link>
				<description><![CDATA[ <p>今日も小ネタというかC# 7ネタというか、C# 7に合わせて1個ライブラリ書いたというか。</p>
<p>勢いで、こんなライブラリ1個作ってしまいました。
C# 7向けです(半分くらいはC# 5.0でも使えるものですが)。</p>
<ul>
<li><a href="https://github.com/ufcpp/ContextFreeTask">ContextFreeTask</a></li>
</ul>
<p>ということで、C# 7の機能の1つについて説明。
C# 7で以下のような機能が入ります。</p>
<ul>
<li><a href="http://ufcpp.net/study/csharp/cheatsheet/ap_ver7/#tasklike">非同期メソッドの戻り値に任意の型を使えるように</a></li>
</ul>
<p>ほぼ、<code>ValueTask</code>のために入った機能なんですが、まあ、せっかくなので他でも使ってみようというのが今日の話。</p>
<h2>同期コンテキスト</h2>
<p>C#に限らずいろんなプログラミング言語で、非同期処理の後にメイン スレッドに戻ってこないといけないという制約があったりします。
特に、GUIプログラムの開発環境だとたいてい、UIがらみのクラスはメイン スレッド(UI末ラッド)からしか触れないとかそういう制約があります。</p>
<p>こういう、「メイン スレッドに戻らないといけない」とか、その場その場にある文脈を同期コンテキストと言います。
C#で<code>await</code>を使って非同期処理をする場合、
<code>await</code>した時点で同期コンテキストを持っていたら、
それを拾って元のコンテキストに戻ってくるようになっています。</p>
<p>同期コンテキストに関する説明、参考URLを探そうとしたものの…
意外とこの時期、真面目に自分のサイトを更新してなくて「書きかけ」ばっかり…
一番真面目に書いてあるのが@ITで書いたSilverlightの記事という…
(XamarinとかASP.NET Coreあたりで書き直したい気もしつつ。)</p>
<ul>
<li><a href="http://www.atmarkit.co.jp/fdotnet/chushin/introsl_04/introsl_04_02.html">避けて通れない「非同期処理」を克服しよう</a></li>
<li><a href="http://ufcpp.net/study/csharp/misc_uithread.html">[雑記] GUI と非同期処理</a></li>
</ul>
<p>とにかく、C#には同期コンテキストってものがあって、通常、<code>await</code>するとそのコンテキスト拾って、スレッド プールからメイン スレッドとかに自動的に戻ってきてくれる仕組みが入っています。</p>
<h3>コンテキスト拾いすぎ</h3>
<p>とはいえ、これはアプリのレイヤーのためにある機能であって、
逆に、ライブラリの中でコンテキストを拾っちゃうとまずかったりします。
意図しないタイミングでメイン スレッドを止めてしまって、デッドロックを起こしたりします。</p>
<p>ということで、ライブラリ作者は、同期コンテキストを拾わないようにするために、以下のようなコードを書くことを強要されます。</p>
<pre class="source" title="ConfigureAwait">
<code><span class="comment">// ConfigureAwait で同期コンテキストを拾うかどうか設定できる</span>
<span class="comment">// 引数を false にすると拾わない</span>
<span class="reserved">await</span> FAsync().ConfigureAwait(<span class="reserved">false</span>);
</code></pre>
<p>ライブラリを書く側の人は毎度毎度、これで苦労します。
正直に言って結構うざい…</p>
<h2>コンテキストを拾わない Task</h2>
<p>ってことで作ったのが <code>ContextFreeTask</code>。
コンテキストを拾わない<code>Task</code>です。</p>
<p>冒頭の通り、C# 7では非同期メソッドの戻り値の型を任意に変えれるようになったので、自作してみました。</p>
<pre class="source" title="ContextFreeTask">
<code><span class="comment">// Task の代わりに ContextFreeTask を非同期メソッドの戻り値にできる</span>
<span class="comment">// この中にある await は同期コンテキストを一切拾わない</span>
<span class="reserved">private</span> <span class="reserved">async</span> <span class="type">ContextFreeTask</span> FAsync()
{
    <span class="comment">// この時点でどんなコンテキストで動いていようと…</span>
    <span class="reserved">await</span> <span class="type">Task</span>.Delay(100);
    <span class="comment">// コンテキストは拾われないので、元のコンテキストには戻らない</span>
    <span class="reserved">await</span> <span class="type">Task</span>.Delay(100);
    <span class="comment">// 同上、戻らない</span>
}

<span class="reserved">private</span> <span class="reserved">async</span> <span class="type">Task</span> GAsync()
{
    <span class="comment">// ContextFreeTask に対する await もできる</span>
    <span class="comment">// この await も同期コンテキストを拾わない</span>

    <span class="reserved">await</span> FAsync();
    <span class="comment">// コンテキストは拾われない</span>
}
</code></pre>
<p>概ね、以下のコードと同じ挙動になります。</p>
<pre class="source" title="ContextFreeTask に対する await = ConfigureAwait(false)">
<code><span class="reserved">private</span> <span class="reserved">async</span> <span class="type">ContextFreeTask</span> FAsync()
{
    <span class="reserved">await</span> <span class="type">Task</span>.Delay(100).ConfigureAwait(<span class="reserved">false</span>);
    <span class="reserved">await</span> <span class="type">Task</span>.Delay(100).ConfigureAwait(<span class="reserved">false</span>);
}

<span class="reserved">private</span> <span class="reserved">async</span> <span class="type">Task</span> GAsync()
{
    <span class="reserved">await</span> FAsync().ConfigureAwait(<span class="reserved">false</span>);
}
</code></pre>
<p>戻り値があるとき用、すなわち、<code>Task&lt;TResult&gt;</code> の代わりの <code>ContextFreeTask&lt;T&gt;</code> もあります。</p>
<pre class="source" title="ContextFreeTask&lt;T&gt;">
<code><span class="reserved">private</span> <span class="reserved">async</span> <span class="type">ContextFreeTask</span>&lt;<span class="reserved">string</span>&gt; HAsync(<span class="reserved">int</span> n)
{
    <span class="reserved">await</span> <span class="type">Task</span>.Delay(100);
    <span class="reserved">return</span> n.ToString();
}
</code></pre>
<h3>中身</h3>
<p><code>Task</code> 1個だけ持つ薄いラッパー構造体で、
ほとんどの処理は<code>Task</code>や、そのawaiter、async method builderへの丸投げです。
その手前に<code>ConfigureAwait(false)</code>や<code>SetSynchronizationContext(null);</code>を挟んでいるだけ。</p>
<pre class="source" title="ContextFreeTask の中身">
<code><span class="reserved">public</span> <span class="reserved">struct</span> <span class="type">ContextFreeTask</span>&lt;<span class="type">T</span>&gt;
{
    <span class="reserved">public</span> <span class="type">Task</span>&lt;<span class="type">T</span>&gt; Task { <span class="reserved">get</span>; }
}

<span class="reserved">public</span> <span class="reserved">struct</span> <span class="type">ContextFreeTaskAwaiter</span> : <span class="type">ICriticalNotifyCompletion</span>
{
    <span class="reserved">private</span> <span class="reserved">readonly</span> <span class="type">Task</span> _value;
    <span class="reserved">public</span> <span class="reserved">void</span> OnCompleted(<span class="type">Action</span> continuation) =&gt; _value.ConfigureAwait(<span class="reserved">false</span>).GetAwaiter().OnCompleted(continuation);
}

<span class="reserved">public</span> <span class="reserved">struct</span> <span class="type">AsyncContextFreeTaskMethodBuilder</span>
{
    <span class="reserved">private</span> <span class="type">AsyncTaskMethodBuilder</span> _methodBuilder;

    <span class="reserved">public</span> <span class="reserved">void</span> AwaitOnCompleted&lt;<span class="type">TAwaiter</span>, <span class="type">TStateMachine</span>&gt;(<span class="reserved">ref</span> <span class="type">TAwaiter</span> awaiter, <span class="reserved">ref</span> <span class="type">TStateMachine</span> stateMachine)
        <span class="reserved">where</span> <span class="type">TAwaiter</span> : <span class="type">INotifyCompletion</span>
        <span class="reserved">where</span> <span class="type">TStateMachine</span> : <span class="type">IAsyncStateMachine</span>
    {
        <span class="type">SynchronizationContext</span>.SetSynchronizationContext(<span class="reserved">null</span>);
        _methodBuilder.AwaitOnCompleted(<span class="reserved">ref</span> awaiter, <span class="reserved">ref</span> stateMachine);
    }
}
</code></pre>
<h2>やってみて</h2>
<p>とりあえず小ネタというか、単にライブラリ紹介だったわけですが…</p>
<p>まあ、この、任意の型を非同期メソッドの戻り値に使える機能、
「<a href="http://ufcpp.net/study/csharp/cheatsheet/ap_ver7/">C# 7の新機能紹介</a>」でもどう取り扱うかは結構悩みまして。
何せ、実用例がほんとに少ない。
なので、どうしても「ほぼ <a href="http://ufcpp.net/study/csharp/sp5_async.html#valuetask"><code>ValueTask</code></a> 専用です」的な書き口に。
(<code>ValueTask</code> だけで十分価値は高いんですが。)</p>
<p>一応小ネタっぽい話もすると、この機能、C#チームからも</p>
<blockquote>
<p>We estimate that in the eventual C# ecosystem maybe 5 people will write tasklike types that get mainstream adoption.</p>
<p>我々の見積もりでは、最終的に C# エコシステム内において、たぶんせいぜい5人くらいが、メインストリームに採用される tasklike 型を書くことになるだろう。</p>
</blockquote>
<p>とか言われています(参考: <a href="https://github.com/dotnet/roslyn/issues/10902#issuecomment-242428870">C# LDM notes from 2016.08.24</a>)。
せいぜい5人。</p>
<p>たぶん確実に使われそうなのとしては、</p>
<ul>
<li>主目的たる<code>ValueTask</code></li>
<li><a href="https://msdn.microsoft.com/ja-jp/library/windows/apps/br206598.aspx">WinRTの<code>IAsyncOperation</code></a>との相互運用</li>
<li><a href="https://www.nuget.org/packages/System.Reactive/">Rx</a></li>
</ul>
<p>の3つは確定。
残りせいぜい2個ですか。</p>
<p>まあ、<code>ContextFreeTask</code>も、作ったはいいけど、大々的に使うかどうかはちょっと悩ましかったり。
誤用(逆に使うとまずいアプリのレイヤーで使われたり。ライブラリでも、publicなところで使ってしまうと、アプリ側でコンテキストを拾い損ねる事態になりそう)がちょっと怖そうですし。</p>
 ]]></description>
				<pubDate>Fri, 09 Dec 2016 00:16:14 +0900</pubDate>
			</item>
			<item>
				<title>小ネタ チェック例外とUnion型</title>
				<link>http://ufcpp.net/blog/2016/12/tipsuniontypes/</link>
				<description><![CDATA[ <p>今日の話は、C# 7で入る<a href="http://ufcpp.net/study/csharp/datatype/typeswitch/">型スイッチ</a>や、さらにその先で予定されている、<a href="https://github.com/dotnet/roslyn/blob/master/docs/features/patterns.md">パターン マッチング</a>や、<a href="https://github.com/dotnet/roslyn/blob/features/records/docs/features/records.md">代数的データ型</a>(特に<a href="https://github.com/dotnet/roslyn/issues/728">Union型</a>)というもので、例外処理の仕方が変わるかも、という話です。</p>
<h2>例外</h2>
<p>例外にはいくつかの性質があります。
まず、挙動としては、以下の2点が特徴的でしょう。</p>
<ul>
<li>ロング ジャンプ: 複数のメソッドをまたいで、遠く離れた場所に移動する</li>
<li>型スイッチ: 例外の型を見て分岐処理を行う</li>
</ul>
<p><img src="/media/1106/usage.png" alt="例外の使い方・挙動" /></p>
<p>例外に含められる情報としては、以下の2つが特に有用でしょう。</p>
<ul>
<li>メッセージ(<code>Message</code>プロパティ): 発生理由を、自由な文章で伝えられる</li>
<li>スタック トレース(<code>StackTrace</code>プロパティ): 発生個所を、呼び出し階層すべて含めて伝えられる</li>
</ul>
<p><img src="/media/1105/info.png" alt="例外に含められる情報" /></p>
<p>これらは便利ではあるんですが、少々過剰気味ではあります。
特に、ロング ジャンプとスタック トレース取得はそこそこ負担が大きな処理で、
例外を<code>throw</code>してしまうと、正常動作と比べて2～3桁くらい動作が遅くなったりします。</p>
<p>この大きな負担が嫌で、例外を嫌う人も多いわけです。
少なくとも、準正常系に対して例外を使うのは過剰スペックじゃないかという話になります。</p>
<p>じゃあ、代わりに何が使えるかというと、最近注目されているのがUnion型とパターン マッチング。</p>
<h2>例外の使い方</h2>
<p>先に過剰スペックじゃないかという話の方を。</p>
<p>例外って言っても、以下の2つに分けられたりするわけです。</p>
<ul>
<li>異常系: 完全に想定外の事態</li>
<li>純正常系: あんまり起きてほしくはないけども、想定の範囲内で、対処方法がわかってて処理を続けられる</li>
</ul>
<h3>異常系</h3>
<p>異常系の「完全に想定外」っていうのは、まあ、「バグが残ってる」という類なので、理想を言えばテストの段階でなくしたいものです。</p>
<p>といっても、バグを100%取れれば苦労はしないわけで、実際には残ります。
バグが残っていた場合の対策も必要なわけで、たいてい、fail-fastでログだけ残して処理を止めます。</p>
<p>処理の止め方としては、まあ状況によっては<a href="https://msdn.microsoft.com/ja-jp/library/system.environment.failfast.aspx"><code>FailFast</code></a>メソッドとかで完全にプロセス停止させてもいいんですが、だいたいは今いるページのリロードとか、ログオフしてログイン画面に戻すとか、そういう対処になるんじゃないでしょうか。</p>
<p>こういう用途には、ロング ジャンプやスタック トレース情報は非常にありがたいです。</p>
<ul>
<li>根っこの方で1か所<code>catch</code>を書くだけでいい</li>
<li>どこで発生したかがわかって、その後、バグ修正がはかどる</li>
</ul>
<p>ということで、こういう用途なら、例外は便利なものです。</p>
<h3>準正常系</h3>
<p>一方で、準正常系、要するに「嫌だけど、まあ避けれない」、「起きることは知ってる」、「対処もできる」みたいなものもあって、こちらにロング ジャンプやスタック トレースが要るかと言われると、かなり微妙。たいていは、呼び出し元のメソッドですぐにエラーを調べて対処するものなので、長距離移動はしないし、どこで発生したかもスタック トレースを見るまでもなくわかっています。</p>
<p>ということで、C#だと、あんまりこの用途で例外を使うことはないんじゃないかと思います。</p>
<p>一方で、<a href="http://msugai.fc2web.com/java/throwstry.html">チェック例外</a>を持っているJavaだと、</p>
<ul>
<li>異常系には実行時例外を使う</li>
<li>準正常系にはチェック例外を使う</li>
</ul>
<p>みたいな例外の使い方をしたりもします。
チェック例外にはチェック例外のいいところがあって、それが準正常系の処理と相性が良かったという面があります。</p>
<h2>チェック例外</h2>
<p>準正常系の例として、平方根を求める関数を考えてみましょう。
いろんな言語で、標準の平方根を求める<code>sqrt</code>関数は以下のような実装になっています。</p>
<ul>
<li>浮動小数点数(C# だと<code>double</code>)を受け取って、浮動小数点数を返す</li>
<li>負の数が来るなど、計算できない値だった場合、戻り値はNaN (Not a Number)を返す</li>
</ul>
<p>これを、諸事情あって、以下のような挙動に変える必要があったとします。</p>
<ul>
<li>引数がそもそもNaNだったら<code>InvalidArgument</code>エラーとする</li>
<li>それ以外で、戻り値がNaNになる(引数が負の数)場合、<code>InvalidResult</code>エラーとする</li>
<li>それ以外は普通に標準ライブラリを使って平方根を計算して返す</li>
</ul>
<p>チェック例外を持つJavaだと、以下のように書いたりします。</p>
<p>まず、エラーを表現するために、例外型を定義。</p>
<pre class="source" title="(Java)例外型を定義">
<code><span class="reserved">class</span> InvalidArgumentException <span class="reserved">extends</span> Exception { }
<span class="reserved">class</span> InvalidResultException <span class="reserved">extends</span> Exception { }
</code></pre>
<p>平方根を求める関数は、以下のような静的メソッドになります。</p>
<pre class="source" title="(Java)正常値か、InvalidArgument, InvalidResultを返すメソッド">
<code><span class="reserved">private</span> <span class="reserved">static</span> <span class="reserved">double</span> sqrt(<span class="reserved">double</span> value) <span class="reserved">throws</span> InvalidResultException, InvalidArgumentException
{
    <span class="reserved">if</span> (Double.isNaN(value)) <span class="reserved">throw</span> <span class="reserved">new</span> InvalidArgumentException();
    <span class="reserved">if</span> (value &lt; 0) <span class="reserved">throw</span> <span class="reserved">new</span> InvalidResultException();
    <span class="reserved">return</span> Math.sqrt(value);
}
</code></pre>
<p>このメソッドを呼び出す側は例えば以下のようになるでしょう。</p>
<pre class="source" title="(Java)メソッドを呼び出す側">
<code><span class="reserved">try</span>
{
    <span class="reserved">double</span> y = sqrt(x);
    System.out.println(y);
}
<span class="reserved">catch</span>(InvalidArgumentException b)
{
    System.out.println(<span class="string">"引数の時点でおかしな値"</span>);
}
<span class="reserved">catch</span>(InvalidResultException a)
{
    System.out.println(<span class="string">"計算結果がおかしな値"</span>);
}
</code></pre>
<p>チェック例外のメリットは2つあります。</p>
<ul>
<li>型の明示(denotation): メソッド定義側で、どういう例外が出るかを明示できる</li>
<li>完備検査(completeness check): 呼び出し側で、出る可能性のある例外を<code>catch</code>しなかったらコンパイル エラーにできる</li>
</ul>
<p>この2つは非常に重要な観点なので確かに欲しい機能なんですが、
その一方で、以下の2点が不満という話になります。</p>
<ul>
<li>戻り値と<code>throws</code>句の2カ所に分かれた書き方は本当にいいのか</li>
<li>おまけでロング ジャンプやスタック トレース情報が付いてくるのは過剰ではないか</li>
</ul>
<h2>Union型とパターン マッチ</h2>
<p>ロング ジャンプやスタック トレース取得は要らない、
型の明示と完備検査はほしい…
となったときに、関数型言語の類だとちょうどそういう仕組みを持っていたりします。
Union型(直和型)とパターン マッチです。</p>
<p>例えばF#で先ほどと同様のsqrt関数を書こうと思うと、
まず、正常な値か、<code>InvalidArgument</code>エラー、<code>InvalidResult</code>エラーを表すUnionを作ります(F#の場合は<a href="https://msdn.microsoft.com/ja-jp/library/dd233226(v=vs.110).aspx">判別共用体</a>(discriminated union types)と言います)。</p>
<pre class="source" title="(F#)値、InvalidArgument、InvalidResultのいずれかの値を取る型">
<code>type SqrtResult =
    | Value of Double
    | InvalidArgument
    | InvalidResult
</code></pre>
<p>これを使って、平方根を求める関数は以下のように書けます。</p>
<pre class="source" title="(F#)値、InvalidArgument, InvalidResultを返すメソッド">
<code>let sqrt x =
    if Double.IsNaN(x) then InvalidArgument
    elif x &lt; 0.0 then InvalidResult
    else Value(Math.Sqrt(x))
</code></pre>
<p>呼び出す側は以下のとおり。</p>
<pre class="source" title="(F#)メソッドを呼び出す側">
match sqrt(x) with
| Value y        -&gt; Console.WriteLine(y)
| InvalidArgument -&gt; Console.WriteLine("引数の時点でおかしな値")
| InvalidResult   -&gt; Console.WriteLine("計算結果がおかしな値")
</code></pre>
<p>ちゃんと要件は満たしています。</p>
<ul>
<li>型の明示: 判別共用体を使って、<code>InvalidArgument</code>、<code>InvalidResult</code>が返る可能性を明示できている</li>
<li>完備検査: 判別共用体に対する<code>match</code> (C#でいう<code>switch</code>)では、条件が足りていなかったら「Incomplete pattern matches」(パターンが不完全です)という警告が出る</li>
<li>ロング ジャンプやスタック トレース取得は要らない</li>
</ul>
<h2>完備検査の課題</h2>
<p>チェック例外にしても、Union型にしても、完備検査をするためにはちょっとした課題があったりします。
何かというと、後からのパターン追加がかなり厳しい。</p>
<p>エラーのパターンを増やしたとしましょう。例えば、この例で言うと、NaNだけじゃなくて∞もエラーにしたくなって、<code>InvalidArgument</code>とは別に<code>Infinite</code>エラーというのを返したくなったとします。</p>
<pre class="source" title="(Java) throws句に例外を1つ追加">
<code><span class="reserved">private</span> <span class="reserved">static</span> <span class="reserved">double</span> sqrt(<span class="reserved">double</span> value) <span class="reserved">throws</span> InvalidResultException, InvalidArgumentException, InfiniteException
{
    <span class="reserved">if</span> (Double.isInfinite(value)) <span class="reserved">throw</span> <span class="reserved">new</span> InfiniteException();
    <span class="reserved">if</span> (Double.isNaN(value)) <span class="reserved">throw</span> <span class="reserved">new</span> InvalidArgumentException();
    <span class="reserved">if</span> (value &lt; 0) <span class="reserved">throw</span> <span class="reserved">new</span> InvalidResultException();
    <span class="reserved">return</span> Math.sqrt(value);
}
</code></pre>
<pre class="source" title="(F#)判別共用体に1つcase追加">
<code>let sqrt x =
    if Double.IsInfinity(x) then Infinite
    elif Double.IsNaN(x) then InvalidArgument
    elif x &lt; 0.0 then InvalidResult
    else Value(Math.Sqrt(x))
</code></pre>
<p>呼び出し側も修正しないと、Javaの場合はコンパイル エラー、F# の場合は警告になります。(ビルド設定で「警告もエラー扱いする」という項目もある以上、警告の追加も破壊的変更です。)</p>
<p>おかしな挙動をするくらいならコンパイル時にエラーや警告が出た方が傷は浅くて済むんですが、コードが大規模化してくると結構厄介な問題になります。</p>
<ul>
<li>
関数を作る人と使う人が全然違う。場合によっては組織をまたぐ
<ul>
<li>使う人にとっては意図しない(例えば別件にかかりきりで修正できないような)タイミングでも、修正を強要される</li>
</ul>
</li>
<li>
パッケージも分かれる
<ul>
<li>使う側の再コンパイルなしでパッケージのバージョンを上げたいのに、再コンパイルしてみないと結局、完備検査が働かない</li>
</ul>
</li>
</ul>
<h2>C# で準正常系の処理</h2>
<p>さて、やっとC#に関してなんですが、C#で準正常系の処理を書くとしたら、</p>
<ul>
<li>
現状: エラー コードを返すような昔ながらの処理に先祖返り
<ul>
<li>型の明示はできてる</li>
<li>完備検証はできてない</li>
</ul>
</li>
<li>
現在検討されていること:
<ul>
<li>C#にもUnion型の追加</li>
<li><code>switch</code>ステートメントでの完備検証の追加</li>
</ul>
</li>
</ul>
<p>という感じになっています。</p>
<p>現状だと、どうしても以下のような感じに落ち着いたりします。</p>
<p>まず、エラーを示すための列挙型を作ります。</p>
<pre class="source" title="現状のC#で同様のsqrt">
<code><span class="reserved">using</span> System;

<span class="reserved">enum</span> <span class="type">ErrorType</span>
{
    None,
    InvalidArgument,
    InvalidResult,
}

<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="type">ErrorType</span> TrySqrt(<span class="reserved">double</span> x, <span class="reserved">out</span> <span class="reserved">double</span> y)
    {
        y = 0;
        <span class="reserved">if</span> (<span class="reserved">double</span>.IsNaN(x)) <span class="reserved">return</span> <span class="type">ErrorType</span>.InvalidArgument;
        <span class="reserved">if</span> (x &lt; 0) <span class="reserved">return</span> <span class="type">ErrorType</span>.InvalidResult;
        y = <span class="type">Math</span>.Sqrt(x);
        <span class="reserved">return</span> <span class="type">ErrorType</span>.None;
    }

    <span class="reserved">static</span> <span class="reserved">void</span> Main()
    {
        <span class="reserved">var</span> data = <span class="reserved">new</span>[] { <span class="reserved">double</span>.NaN, -1.0, 2.0 };

        <span class="reserved">foreach</span> (<span class="reserved">var</span> x <span class="reserved">in</span> data)
        {
            <span class="type">Console</span>.Write(x + <span class="string">" → "</span>);
            <span class="reserved">double</span> y;
            <span class="reserved">switch</span> (TrySqrt(x, <span class="reserved">out</span> y))
            {
                <span class="reserved">case</span> <span class="type">ErrorType</span>.None:
                    <span class="type">Console</span>.WriteLine(y);
                    <span class="reserved">break</span>;
                <span class="reserved">case</span> <span class="type">ErrorType</span>.InvalidArgument:
                    <span class="type">Console</span>.WriteLine(<span class="string">"引数の時点でおかしな値"</span>);
                    <span class="reserved">break</span>;
                <span class="reserved">case</span> <span class="type">ErrorType</span>.InvalidResult:
                    <span class="type">Console</span>.WriteLine(<span class="string">"計算結果的におかしな値"</span>);
                    <span class="reserved">break</span>;
            }
        }
    }
}
</code></pre>
<p>正直なところ、この先祖返り感は結構な残念さではあるんですが。
先祖返りが起こるってのは、現状(例外機構)に対して結構な不満があるという証でもあります。</p>
<p>将来的に、これがどうなってほしいかというと、以下のような感じでしょうか。</p>
<pre class="source" title="(まだ見ぬ未来のC#)同様のsqrt">
<code><span class="reserved">using</span> System;

<span class="reserved">enum</span> <span class="type">ErrorType</span>
{
    InvalidArgument,
    InvalidResult,
}

<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">double</span> | <span class="type">ErrorType</span> M(<span class="reserved">double</span> x)
    {
        <span class="reserved">if</span> (<span class="reserved">double</span>.IsNaN(x)) <span class="reserved">return</span> <span class="type">ErrorType</span>.InvalidArgument;
        <span class="reserved">if</span> (x &lt; 0) <span class="reserved">return</span> <span class="type">ErrorType</span>.InvalidResult;
        <span class="reserved">return</span> <span class="type">Math</span>.Sqrt(x);
    }

    <span class="reserved">static</span> <span class="reserved">void</span> Main()
    {
        <span class="reserved">var</span> data = <span class="reserved">new</span>[] { <span class="reserved">double</span>.NaN, -1.0, 2.0 };

        <span class="reserved">foreach</span> (<span class="reserved">var</span> x <span class="reserved">in</span> data)
        {
            <span class="type">Console</span>.Write(<span class="string">$"</span>{x}<span class="string"> → "</span>);
            <span class="type">Console</span>.WriteLine(M(x) <span class="reserved">match</span>
            {
                <span class="reserved">double</span> y: y.ToString(),
                <span class="type">ErrorType</span>.InvalidArgument: <span class="string">"引数の時点でおかしな値"</span>,
                <span class="type">ErrorType</span>.InvalidResult: <span class="string">"計算結果的におかしな値"</span>,
            });
        }
    }
}
</code></pre>
<p>パーツごとに説明すると、以下のようなものから成り立ちます。</p>
<ul>
<li>
Union型(確度 低)
<ul>
<li><code>double | ErrorType</code>みたいな書き方でUnion型を定義</li>
<li>この書き方は TypeScript を習ったもの</li>
<li>C#でこの書き方ができるようになるかというと微妙。後述する「<code>abstract sealed</code>」なクラスならできるようになるかも</li>
</ul>
</li>
<li>
型による分岐(<a href="http://ufcpp.net/study/csharp/cheatsheet/ap_ver7/#type-switch">C# 7で入る</a>)
<ul>
<li><code>switch</code>ステートメントの<code>case</code>や、<code>is</code>演算子で、型を見た分岐ができるようになる</li>
</ul>
</li>
<li>
<code>match</code> 式(確度 高)
<ul>
<li><code>switch</code>を式にしたもの</li>
</ul>
</li>
<li>Union型とEnum型の<a href="https://github.com/dotnet/roslyn/issues/188">完備検査</a>(確度 高)</li>
</ul>
<p>Union型は、要するに、<code>A | B</code> と書いた場合、<code>A</code>か<code>B</code>かのどちらかの値を持つ型です。
一応、これをC#で似たようなことしようと思うと、以下のように書くことになります。要するに、ただ単にクラスの継承階層を作るだけ。</p>
<pre class="source" title="AかBかを表す型">
<code><span class="reserved">abstract class</span> <span class="type">AorB</span> { }
<span class="reserved">class</span> <span class="type">A</span> : <span class="type">AorB</span> { }
<span class="reserved">class</span> <span class="type">B</span> : <span class="type">AorB</span> { }
</code></pre>
<p>ここで問題は、<code>AorB</code>を赤の他人が継承して使えることです。
「完備検査の課題」で説明した通り、完備検査をする場合、パターン追加が破壊的変更を起こします。
<code>AorB</code>を作った人が意図して破壊的変更を起こすならまだしも、
作った人でも使う人でもない第3者のせいでコンパイル エラーが起きるのはさすがに許容できないでしょう。</p>
<p>一応、第3者による継承を防止する手段はあって、以下のように書きます。</p>
<pre class="source" title="AかBかを表し、かつ、それ以外はあり得ない型">
<code><span class="comment">// AorB 自体のインスタンスを作れないように abstract</span>
<span class="reserved">abstract</span> <span class="reserved">class</span> <span class="type">AorB</span>
{
    <span class="comment">// クラスの外からの派生を禁止するためにコンストラクターを private に</span>
    <span class="reserved">private</span> AorB() { }

    <span class="reserved">public</span> <span class="reserved">class</span> <span class="type">A</span> : <span class="type">AorB</span> { }
    <span class="reserved">public</span> <span class="reserved">class</span> <span class="type">B</span> : <span class="type">AorB</span> { }
}
</code></pre>
<p>ですが、この書き方はネストするのがうざい。
ということで、以下のような書き方で、上記のネスト状態のコードに展開したいという案が出ています。</p>
<pre class="source" title="(まだ見ぬ未来のC#)AかBかを表し、かつ、それ以外はあり得ない型">
<code><span class="comment">// 継承前提(abstract)なんだけど、意図しない継承はさせたくない(sealed)という意図で</span>
<span class="comment">// abstract sealed と付ける</span>
<span class="reserved">abstract</span> <span class="reserved">sealed</span> <span class="reserved">class</span> <span class="type">AorB</span> { }
<span class="reserved">class</span> <span class="type">A</span> : <span class="type">AorB</span> { }
<span class="reserved">class</span> <span class="type">B</span> : <span class="type">AorB</span> { }
</code></pre>
<p><code>abstract sealed</code>という、現在のC#的にいうと矛盾する2つの修飾子を組み合わせて、
継承して使う前提だけど、意図しない第3者には継承させないという型を作ることができます。
こういう構文で、Union型に類するものを提供しようという感じです。</p>
<p>ちなみに、F#の判別共用体は、内部実装的にはこれと同じようなコード(privateなコンストラクター ＋ ネストしたクラス)を生成しています。</p>
 ]]></description>
				<pubDate>Thu, 08 Dec 2016 00:43:44 +0900</pubDate>
			</item>
			<item>
				<title>小ネタ インデックス付き foreach</title>
				<link>http://ufcpp.net/blog/2016/12/tipsindexedforeach/</link>
				<description><![CDATA[ <p><code>foreach</code> ステートメントで、インデックス付きで列挙したいことが時々あります。
今回は、そういうときの対処方法について。
というか、C# 7が待ち遠しくなる話。</p>
<p>配列や<code>List&lt;T&gt;</code>であれば以下のようにも書けます。</p>
<pre class="source" title="やむなく for ステートメント">
<code><span class="reserved">for</span> (<span class="reserved">int</span> i = 0; i &lt; length; i++)
{
    <span class="reserved">var</span> item = array[i];
    <span class="type">Console</span>.WriteLine(<span class="string">$"index: </span>{i}<span class="string">, value: </span>{item}<span class="string">"</span>);
}
</code></pre>
<p><code>IEnumerable&lt;T&gt;</code>の場合にはこうは書けず、
現状だと、以下のようにループの外側に1個変数を作る必要があったりします。</p>
<pre class="source" title="やむなく foreach ループの外に変数を置く">
<code><span class="reserved">var</span> i = 0;
<span class="reserved">foreach</span> (<span class="reserved">var</span> item <span class="reserved">in</span> items)
{
    <span class="type">Console</span>.WriteLine(<span class="string">$"index: </span>{i}<span class="string">, value: </span>{item}<span class="string">"</span>);
    i++;
}
</code></pre>
<p>ループの外側に変数<code>i</code>が漏れるのが嫌なのと、
あと、<code>continue</code>が絡むと<code>i++</code>するのが大変になったりします。</p>
<p><code>Select</code>のオーバーロードの1つを使って、以下のような書き方も一応できます。</p>
<pre class="source" title="Select のオーバーロードの1つに、インデックスを拾えるものがある">
<code><span class="reserved">foreach</span> (<span class="reserved">var</span> x <span class="reserved">in</span> items.Select((item, index) =&gt; <span class="reserved">new</span> { item, index }))
{
    <span class="type">Console</span>.WriteLine(<span class="string">$"index: </span>{x.index}<span class="string">, value: </span>{x.item}<span class="string">"</span>);
}
</code></pre>
<p>ただ、これだと無駄にオブジェクトが<code>new</code>されます(匿名型は参照型なのでヒープ確保が発生します)。ループの中でのヒープ確保はできれば避けたい負担です。
それに、<code>x.item</code>みたいな書き方がちょっと嫌な感じです。</p>
<p><a href="http://ufcpp.net/study/csharp/cheatsheet/ap_ver7/">C# 7</a>であれば、<a href="http://ufcpp.net/study/csharp/datatype/tuples/">タプル</a>を使うのがいいかもしれません。ついでに、<a href="http://ufcpp.net/study/csharp/datatype/deconstruction/">分解構文</a>も使えば多少すっきりします。</p>
<pre class="source" title="[C# 7] タプルがあれば">
<code><span class="reserved">foreach</span> (<span class="reserved">var</span> (item, index) <span class="reserved">in</span> items.Select((item, index) =&gt; (item, index)))
{
    <span class="type">Console</span>.WriteLine(<span class="string">$"index: </span>{index}<span class="string">, value: </span>{item}<span class="string">"</span>);
}
</code></pre>
<p>タプルは値型なので、いくらかヒープ確保が減ります。
また、<a href="http://ufcpp.net/study/csharp/datatype/deconstruction/">分解</a>があるおかげで<code>x.</code>とか書く必要がなくなりました。</p>
<p>でもまだちょっとうっとおしいですね。
<code>(item, index) =&gt; (item, index)</code>とか毎度書きたくないです。
拡張メソッドを用意しておきたいところ。</p>
<pre class="source" title="Indexed 拡張メソッド">
<code><span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">partial</span> <span class="reserved">class</span> <span class="type">TupleEnumerable</span>
{
    <span class="reserved">public</span> <span class="reserved">static</span> <span class="type">IEnumerable</span>&lt;(<span class="type">T</span> item, <span class="reserved">int</span> index)&gt; Indexed&lt;<span class="type">T</span>&gt;(<span class="reserved">this</span> <span class="type">IEnumerable</span>&lt;<span class="type">T</span>&gt; source)
    {
        <span class="reserved">if</span> (source == <span class="reserved">null</span>) <span class="reserved">throw</span> <span class="reserved">new</span> <span class="type">ArgumentNullException</span>(<span class="reserved">nameof</span>(source));

        <span class="type">IEnumerable</span>&lt;(<span class="type">T</span> item, <span class="reserved">int</span> index)&gt; impl()
        {
            <span class="reserved">var</span> i = 0;
            <span class="reserved">foreach</span> (<span class="reserved">var</span> item <span class="reserved">in</span> source)
            {
                <span class="reserved">yield</span> <span class="reserved">return</span> (item, i);
                ++i;
            }
        }

        <span class="reserved">return</span> impl();
    }
}
</code></pre>
<p>これで、以下のように書けます。</p>
<pre class="source" title="Indexed拡張メソッドの使い方">
<code><span class="reserved">foreach</span> (<span class="reserved">var</span> (item, index) <span class="reserved">in</span> items.Indexed())
{
    <span class="type">Console</span>.WriteLine(<span class="string">$"index: </span>{index}<span class="string">, value: </span>{item}<span class="string">"</span>);
}
</code></pre>
<p>これなら、まあ、悪くはなさそうです。
こういうメソッド、そこそこ使うことがありそう。</p>
<p>ちなみに、今回は<a href="http://ufcpp.net/study/csharp/sp2_iterator.html">イテレーター</a>を使って<code>Indexed</code>メソッドを実装しましたが、ガチガチに最適化するなら、以下のように、構造体で実装してヒープ確保をなくすべきかもしれません。</p>
<ul>
<li><a href="https://gist.github.com/ufcpp/2b3e1a5821169f6b21ded175ad05c752">Gist: index付きforeach</a></li>
</ul>
 ]]></description>
				<pubDate>Wed, 07 Dec 2016 00:23:23 +0900</pubDate>
			</item>
			<item>
				<title>小ネタ コレクション初期化子</title>
				<link>http://ufcpp.net/blog/2016/12/tipscollectioninitializer/</link>
				<description><![CDATA[ <p>昨日のオブジェクト初期化子に続き、今日はコレクション初期化子の話。</p>
<p>コレクション初期化子ってのは、例えば以下のようなやつのことです。</p>
<pre class="source" title="コレクション初期化子">
<code><span class="comment">// この、{} の部分がコレクション初期化子。</span>
<span class="reserved">var</span> x = <span class="reserved">new</span> <span class="type">List</span>&lt;<span class="reserved">int</span>&gt; { 1, 2, 3, 4, 5 };
</code></pre>
<p>このコレクション初期化を使える条件は、<code>Add</code> メソッドを持っていて、かつ、 <code>IEnumerable</code> を実装していることです。</p>
<p>最低限の実装をしてみると、以下のような感じ。</p>
<pre class="source" title="コレクション初期化子の最低限の条件を満たす例">
<code><span class="reserved">class</span> <span class="type">MyList</span> : <span class="type">IEnumerable</span>
{
    <span class="type">List</span>&lt;<span class="reserved">int</span>&gt; _list = <span class="reserved">new</span> <span class="type">List</span>&lt;<span class="reserved">int</span>&gt;();
    <span class="reserved">public</span> <span class="reserved">void</span> Add(<span class="reserved">int</span> value) =&gt; _list.Add(value);
    <span class="reserved">public</span> <span class="type">IEnumerator</span> GetEnumerator() =&gt; _list.GetEnumerator();
}

<span class="reserved">static</span> <span class="reserved">void</span> ListSample()
{
    <span class="reserved">var</span> x = <span class="reserved">new</span> <span class="type">MyList</span> { 1, 2, 3, 4, 5 };

    <span class="reserved">foreach</span> (<span class="reserved">var</span> item <span class="reserved">in</span> x)
        <span class="type">Console</span>.WriteLine(item);
}
</code></pre>
<p>この、コレクション初期化子は以下のように展開されます。</p>
<pre class="source" title="コレクション初期化子の展開結果">
<code><span class="reserved">var</span> x = <span class="reserved">new</span> <span class="type">MyList</span>();
x.Add(1);
x.Add(2);
x.Add(3);
x.Add(4);
x.Add(5);
</code></pre>
<p>ここで生じる疑問があります: <code>IEnumerable</code> の実装、要るの？</p>
<h2>依存は避けれるなら避けるべきもの</h2>
<p>だって、<code>Add</code>メソッドしか使ってなくない？<code>IEnumerable</code>は何にも使ってないよね？</p>
<p>だいたい、C#の文法が<code>IEnumerable</code>に依存しちゃうの？
例えば、<code>foreach</code>であれば<code>GetEnumeartor</code>メソッドさえ持っていれば、別に<code>IEnumerable</code>インターフェイスを実装していない型であっても使えます。
LINQもそうで、<code>Select</code>や<code>Where</code>など、所定のメソッドさえ持っていれば、クエリ式を使えます。</p>
<p>最近、Build Insiderで<a href="http://www.buildinsider.net/column/iwanaga-nobuyuki/009">Task-likeの話</a>とかも書きましたけど、
言語の文法が何かの型に依存するというのはリスクを持ちます。
可能なら避けるべきものです。</p>
<p>で、コレクション初期化子、<code>IEnumerable</code> 要るの？</p>
<h2>たぶん、誤用の防止</h2>
<p>まあ、問題になるとすると以下のような例ですかね。</p>
<pre class="source" title="コレクション初期化子の誤用の例">
<code><span class="reserved">struct</span> <span class="type">Adder</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> Add(<span class="reserved">int</span> x, <span class="reserved">int</span> y) =&gt; x + y;
}

<span class="reserved">static</span> <span class="reserved">void</span> AdderSample()
{
    <span class="comment">// こういう誤用を防ぎたかったのかなという気はする</span>
    <span class="reserved">var</span> x = <span class="reserved">new</span> <span class="type">Adder</span>
    {
        { 2, 1 },
        { 3, 4 },
        { 5, 9 },
    };
}
</code></pre>
<p><code>Add</code>メソッドだけを条件にしてしまうと、こういうコードが書けてしまう。
で、この<code>Add</code>の呼ばれ方だと、何の役にも立たないわけです。
<code>Adder</code>の内部状態を変えたいわけじゃなてく、単なるオペレーターなわけでして。</p>
<p>もちろん、<code>IEnumerable</code>の実装を義務付けたところで、あえて濫用することはできます。
例えば、以下のような書き方なら現在の仕様でもできます。</p>
<pre class="source" title="GetEnumeratorを空実装して無理やりコレクション初期化子を使う例">
<code><span class="reserved">class</span> <span class="type">Accumulator</span> : <span class="type">IEnumerable</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> Sum { <span class="reserved">get</span>; <span class="reserved">set</span>; }
    <span class="reserved">public</span> <span class="reserved">int</span> Add(<span class="reserved">int</span> value) =&gt; Sum += value;

    <span class="comment">// 空実装してしまえば、コレクション初期化子の乱用可能</span>
    <span class="reserved">public</span> <span class="type">IEnumerator</span> GetEnumerator() =&gt; <span class="reserved">throw</span> <span class="reserved">new</span> <span class="type">NotSupportedException</span>();
}

<span class="reserved">static</span> <span class="reserved">void</span> AccumulatorSample()
{
    <span class="comment">// コレクションでもないんでもないけど、コレクション初期化子を使える</span>
    <span class="reserved">var</span> x = <span class="reserved">new</span> <span class="type">Accumulator</span> { 1, 2, 3, 4, 5 };
    <span class="type">Console</span>.WriteLine(x.Sum); <span class="comment">// 15</span>
}
</code></pre>
<p>とりあえず空実装。</p>
<p>まあ、意図的にやってるので大して問題にはならないんですが。
<code>Adder</code>みたいなのが意図せずコレクション初期化子で使われるのだけは防止したかったんですかね…
そのために<code>GetEnumerator</code>の空実装しろと…</p>
 ]]></description>
				<pubDate>Tue, 06 Dec 2016 00:00:49 +0900</pubDate>
			</item>
			<item>
				<title>小ネタ オブジェクト初期化子</title>
				<link>http://ufcpp.net/blog/2016/12/tipsobjectinitializer/</link>
				<description><![CDATA[ <p>今日の小ネタは、オブジェクト初期化子について、意外と知られてないらしい話。</p>
<h2>問い</h2>
<p>唐突ですが問題です。以下の3つのコードはそれぞれどういう意味でしょう。</p>
<pre class="source" title="オブジェクト初期化子パターン1">
<code><span class="reserved">var</span> x = <span class="reserved">new</span> <span class="type">Line</span>
{
    A = <span class="reserved">new</span> <span class="type">Point</span> { X = 1, Y = 2 },
    B = <span class="reserved">new</span> <span class="type">Point</span> { X = 3, Y = 4 },
};
</code></pre>
<pre class="source" title="オブジェクト初期化子パターン2">
<code><span class="reserved">var</span> x = <span class="reserved">new</span> <span class="type">Line</span>
{
    A = { X = 1, Y = 2 },
    B = { X = 3, Y = 4 },
};
</code></pre>
<pre class="source" title="オブジェクト初期化子パターン3">
<code><span class="reserved">var</span> x = <span class="reserved">new</span> <span class="type">Line</span>
{
    A = <span class="reserved">new</span> { X = 1, Y = 2 },
    B = <span class="reserved">new</span> { X = 3, Y = 4 },
};
</code></pre>
<p>ついでに、将来的に認められるようになるかもしれないパターンをもう1つ。</p>
<pre class="source" title="オブジェクト初期化子パターン4 (将来OKになるかも)">
<code><span class="reserved">var</span> x = <span class="reserved">new</span> <span class="type">Line</span>
{
    A = <span class="reserved">new</span>() { X = 1, Y = 2 },
    B = <span class="reserved">new</span>() { X = 3, Y = 4 },
};
</code></pre>
<h2>答え合わせの前に</h2>
<p>答えを説明する前に、コード中に出ていた2つの型、<code>Point</code>、<code>Line</code>について。</p>
<p>まず、<code>Point</code>の方は、どのパターンであっても以下のような感じである必要があります。</p>
<pre class="source" title="Point の例">
<code><span class="reserved">class</span> <span class="type">Point</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> X { <span class="reserved">get</span>; <span class="reserved">set</span>; }
    <span class="reserved">public</span> <span class="reserved">int</span> Y { <span class="reserved">get</span>; <span class="reserved">set</span>; }
}
</code></pre>
<p>構造体でもいいんですが、その場合、<code>Line</code>側に参照戻り値が必要になります。</p>
<p><code>Line</code>の方は、2パターンあります。
1つは、プロパティが書き換え可能なもの。</p>
<pre class="source" title="書き換え可能な Line の例">
<code><span class="reserved">class</span> <span class="type">Line</span>
{
    <span class="reserved">public</span> <span class="type">Point</span> A { <span class="reserved">get</span>; <span class="reserved">set</span>; }
    <span class="reserved">public</span> <span class="type">Point</span> B { <span class="reserved">get</span>; <span class="reserved">set</span>; }
}
</code></pre>
<p>もう1つは、getのみのプロパティに対して、コンストラクター、もしくは、プロパティ初期化子で初期値を与えているものです。</p>
<pre class="source" title="get のみな Line の例">
<code><span class="reserved">class</span> <span class="type">Line</span>
{
    <span class="reserved">public</span> <span class="type">Point</span> A { <span class="reserved">get</span>; } = <span class="reserved">new</span> <span class="type">Point</span>();
    <span class="reserved">public</span> <span class="type">Point</span> B { <span class="reserved">get</span>; } = <span class="reserved">new</span> <span class="type">Point</span>();
}
</code></pre>
<h2>答え</h2>
<h3>パターン1</h3>
<p>パターン1のやつは、一番シンプルというか、多くの方がこれのつもりでオブジェクト初期化子を使っているのではないかと思います。</p>
<pre class="source" title="パターン1の答え">
<code><span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> Q()
{
    <span class="reserved">var</span> x = <span class="reserved">new</span> <span class="type">Line</span>
    {
        A = <span class="reserved">new</span> <span class="type">Point</span> { X = 1, Y = 2 },
        B = <span class="reserved">new</span> <span class="type">Point</span> { X = 3, Y = 4 },
    };
}

<span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> A()
{
    <span class="reserved">var</span> x = <span class="reserved">new</span> <span class="type">Line</span>();
    x.A = <span class="reserved">new</span> <span class="type">Point</span> { X = 1, Y = 2 };
    x.B = <span class="reserved">new</span> <span class="type">Point</span> { X = 3, Y = 4 };
}
</code></pre>
<p>展開結果を見ての通り、<code>x.A</code>や<code>x.B</code>に対する代入が発生するので、<code>A</code>, <code>B</code> は set アクセサーを持つ必要があります。</p>
<p>その結果、書き換え可能な方の <code>Line</code> 実装に対してならこの構文を使えますが、
getのみの方の <code>Line</code> 実装には使えません。</p>
<h3>パターン2</h3>
<p>意外と知られてないのはこいつですね。</p>
<pre class="source" title="パターン2の答え">
<code><span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> Q()
{
    <span class="reserved">var</span> x = <span class="reserved">new</span> <span class="type">Line</span>
    {
        A = { X = 1, Y = 2 },
        B = { X = 3, Y = 4 },
    };
}

<span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> A()
{
    <span class="reserved">var</span> x = <span class="reserved">new</span> <span class="type">Line</span>();
    x.A.X = 1;
    x.A.Y = 2;
    x.B.X = 3;
    x.B.Y = 4;
}
</code></pre>
<p>オブジェクト初期化子は再帰的に書けます。
その場合、この例の <code>x.A.X</code> というように、全部展開されて、そこに代入が行われます。</p>
<p>ここで注意が必要なのは、<code>x.A</code> の初期化は外からは行われないということです。
もしも、<code>Line</code> のコンストラクター内で <code>A</code> を初期化していなければ、当然のようにぬるぽります。</p>
<p>つまり、getのみの方の <code>Line</code> に対しても使える代わりに、
書き換え可能な方の <code>Line</code> 実装みたいにコンストラクター内での初期化をしていないものに対してこの書き方を使うと実行時エラーを起こします。</p>
<h3>パターン3</h3>
<p>並べられると、似たようなもので全然違う結果になるので気持ち悪くなりますが、
まあ、個別によく見るとそんなに不思議なものではないと思います。</p>
<p>パターン3は、単に匿名型を代入しているだけ。</p>
<pre class="source" title="パターン3の答え">
<code><span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> Q()
{
    <span class="comment">// 実はコンパイル エラー</span>
    <span class="reserved">var</span> x = <span class="reserved">new</span> <span class="type">Line</span>
    {
        A = <span class="reserved">new</span> { X = 1, Y = 2 },
        B = <span class="reserved">new</span> { X = 3, Y = 4 },
    };
}

<span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> A()
{
    <span class="reserved">var</span> x = <span class="reserved">new</span> <span class="type">Line</span>();
    <span class="comment">// この new { } は匿名型。</span>
    <span class="comment">// A, B は Point 型なので、匿名型だと型があってない。</span>
    <span class="comment">// つまり、コンパイル エラー: 匿名型を暗黙的に Point に変換できません</span>
    x.A = <span class="reserved">new</span> { X = 1, Y = 2 };
    x.B = <span class="reserved">new</span> { X = 3, Y = 4 };
}
</code></pre>
<p>C#だと、コンパイル時にエラーなことがわかるんでそんなに問題はないと思うんですが。
もしも実行してみないとこの差がわからないとか言われたらちょっと殺意を覚えますね…</p>
<h3>パターン4</h3>
<p>パターン4は将来の話。今現在はコンパイル エラーになります。
どういう構文が追加されそうかというと、左辺からの型推論です。</p>
<pre class="source" title="パターン4の答え">
<code><span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> Q()
{
    <span class="reserved">var</span> x = <span class="reserved">new</span> <span class="type">Line</span>
    {
        A = <span class="reserved">new</span>() { X = 1, Y = 2 },
        B = <span class="reserved">new</span>() { X = 3, Y = 4 },
    };
}

<span class="reserved">public</span> <span class="reserved">static</span> <span class="reserved">void</span> A()
{
    <span class="reserved">var</span> x = <span class="reserved">new</span> <span class="type">Line</span>();
    <span class="comment">// new() って書き方で、左辺から型推論してくれる構文が入りそう。</span>
    <span class="comment">// この場合、A, B が Point なので、new () は new Point() の意味。</span>
    x.A = <span class="reserved">new</span> <span class="type">Point</span> { X = 1, Y = 2 };
    x.B = <span class="reserved">new</span> <span class="type">Point</span> { X = 3, Y = 4 };
}
</code></pre>
<p>ものすごいほしい型推論機能です。早く実装されないかな…</p>
<p>とはいえ、まあ、こういう、並べると気持ち悪いコードが書けますよ、と。
<code>{ }</code>と<code>new { }</code>と<code>new() { }</code>で全部意味が違うという。</p>
 ]]></description>
				<pubDate>Mon, 05 Dec 2016 01:10:05 +0900</pubDate>
			</item>
			<item>
				<title>小ネタ 式の評価順序</title>
				<link>http://ufcpp.net/blog/2016/12/tipsevalorder/</link>
				<description><![CDATA[ <p>C#小ネタと言いつつ、IL小ネタになりがちだったので、今日はC#小ネタらしく。</p>
<p>最初にちょっとしたクイズ。
まず、中身は何でもいいんですが適当な2引数のメソッドを用意します。
例として、単純な足し算でも用意しておきましょう。</p>
<pre class="source" title="2に引数のメソッドをまず用意">
<code><span class="reserved">static</span> <span class="reserved">int</span> F(<span class="reserved">int</span> x, <span class="reserved">int</span> y) =&gt; x + y;
</code></pre>
<p>以下の2つのコードの挙動は同じでしょうか？違うでしょうか？</p>
<p>1つ目: 一時変数を使用</p>
<pre class="source" title="一時変数を使用して呼び出し">
<code><span class="reserved">var</span> temp = F(2, 3);
<span class="reserved">var</span> result = F(1, temp);
</code></pre>
<p>2つ目: 1つの式で計算</p>
<pre class="source" title="1つの式で呼び出し">
<code><span class="reserved">var</span> result = F(1, F(2, 3));
</code></pre>
<p>まあ、同じですね。<em>副作用を残さない限りは。</em></p>
<h2>オペランドの評価順序</h2>
<p>ということで、今日はオペランドの評価順の話です。
上記の2つのコードを、わざと副作用付きに書き換えてみます。</p>
<p>そのためにとりあえず、副作用を起こすメソッドを追加。
<code>Console</code>にログ出力した後、引数を素通しするだけのメソッドです。
値渡し版と参照渡し版を用意。</p>
<pre class="source" title="副作用を起こすメソッド">
<code><span class="comment">// WriteLine + 素通し</span>
<span class="reserved">static</span> <span class="type">T</span> Log&lt;<span class="type">T</span>&gt;(<span class="type">T</span> x) { <span class="type">Console</span>.WriteLine(x); <span class="reserved">return</span> x; }
<span class="reserved">static</span> <span class="reserved">ref</span> <span class="type">T</span> Log&lt;<span class="type">T</span>&gt;(<span class="reserved">ref</span> <span class="type">T</span> x) { <span class="type">Console</span>.WriteLine(x); <span class="reserved">return</span> <span class="reserved">ref</span> x; }
</code></pre>
<p>1つ目(一時変数を使用)を改めて:</p>
<pre class="source" title="一時変数を使用 + 副作用あり">
<code><span class="reserved">var</span> temp = F(Log(2), Log(3));
<span class="reserved">var</span> result = F(Log(1), temp);
</code></pre>
<pre class="console" title="一時変数を使用 + 副作用あり">
<code>2
3
1
</code></pre>
<p>2つ目(1つの式で計算)を改めて:</p>
<pre class="source" title="1つの式で計算">
<code><span class="reserved">var</span> result = F(Log(1), F(Log(2), Log(3)));
</code></pre>
<pre class="console" title="1つの式で計算">
<code>1
2
3
</code></pre>
<p>C#では、式の評価は、上から下へ、左から右へ逐次実行です。
なので、一時変数を導入すると結果が変わります。</p>
<p>1つの式の中でも、演算子の優先順位や結合方向とは無関係に、評価は一律左から右です。
代入(優先度が低い上に右から左に結合)が混ざっていようと、そのオペランドの評価は左から右です。</p>
<p>例えば以下の通り。</p>
<pre class="source" title="演算子の優先順位や結合方向とは無関係に、オペランドは左から右に評価">
<code><span class="reserved">bool</span> x = <span class="reserved">false</span>, y = <span class="reserved">true</span>;
Log(<span class="reserved">ref</span> x) = Log(<span class="reserved">ref</span> y) = Log(1) + Log(2) * Log(3) &gt; Log(4) &amp; Log(5) &lt;= Log(6) - Log(7) | Log(8) == Log(9);
</code></pre>
<pre class="console" title="演算子の優先順位や結合方向とは無関係に、オペランドは左から右に評価">
<code>False
True
1
2
3
4
5
6
7
8
9
</code></pre>
<h2>名前付き引数のオペランド評価</h2>
<p>前節の結果はそんなに不思議なことないでしょう。コードから挙動を予想しやすいって意味では書かれてる順番通りが一番です。それに、パフォーマンス的にも悪い選択ではありません。例えば、</p>
<pre class="source" title="コンパイル元1">
<code><span class="reserved">var</span> result = F(1, F(2, 3));
</code></pre>
<p>というようなコードであれば、コンパイル結果は以下のような感じになります(必要なところを抜粋)。</p>
<pre class="source" title="コンパイル結果1">
<code>ldc.i4.1
ldc.i4.2
ldc.i4.3
call       F
call       F
</code></pre>
<p>元のC#のオペランドと同じ、1, 2, 3の順で<code>ldc</code> (load constant)しています。
副作用を起こすために<code>Log</code>メソッドを挟む場合、この<code>ldc</code>のところが数命令に置き換わりますが、命令の並ぶ順序はこの場合と同じです。</p>
<p>ということで、素直に実装すればいいだけ…</p>
<p>でもなくて、まあ、ほとんどの式は素直に実装していいんですが、一部めんどくさい奴がいます。例えば、名前付き引数。
以下のようなコードを書いたとします。
<code>x</code>, <code>y</code>を逆に並べています。</p>
<pre class="source" title="コンパイル元2">
<code>F(1, F(y: 2, x: 3));
</code></pre>
<p>すると、コンパイル結果は以下の通り。C#ソースコード上は1, 2, 3だったものが、IL的には1, 3, 2になります。</p>
<pre class="source" title="コンパイル結果2">
<code>ldc.i4.1
ldc.i4.<em>3</em>
ldc.i4.<em>2</em>
call       F
call       F
</code></pre>
<p>この結果は副作用がないからこそ、C#コンパイラーの最適化が掛かってこうなっています。
副作用がないことがわかっている場合、評価順を並べ替えを行います。</p>
<p>一方で、副作用があるとそうはいきません。あくまで、C#では左から右への評価が必要です。</p>
<p>例えば以下のようなコードをでは、ちゃんと、1, 2, 3の順での評価が必要です。</p>
<pre class="source" title="コンパイル元3">
<code>F(Log(1), F(y: Log(2), x: Log(3)));
</code></pre>
<p>コンパイル結果は以下の通りです。これまでは必要のなかった一時変数(<code>stloc</code>: ローカル変数へのストア)が必要になります。</p>
<pre class="source" title="コンパイル結果3">
<code>ldc.i4.1
call       Log
ldc.i4.2
call       Log
stloc.0    <span class="comment">// 一時変数！
</span>ldc.i4.3
call       Log
ldloc.0
call       F
call       F
</code></pre>
<p>ちなみに、これ、C# 4.0の時にはバグってて評価順が狂ってた(逆順になってた)そうです。
C# 5.0でバグ修正した結果、<a href="https://msdn.microsoft.com/en-us/library/hh678682(v=vs.110).aspx">破壊的変更</a>になっていたり(めったにこんなコード書かない上に、バグの修正なので特に問題にはならず)。</p>
<h2>タプルの要素の評価順序</h2>
<p>もう1個変な例を挙げておきましょう。C# 7で導入されるタプルと分解で、以下のように、swapコードを書けるようになりました。</p>
<pre class="source" title="タプルを使ったswap処理">
<code><span class="reserved">var</span> x = 1;
<span class="reserved">var</span> y = 2;
(x, y) = (y, x);
<span class="type">Console</span>.WriteLine(<span class="string">$"</span>{x}<span class="string">, </span>{y}<span class="string">"</span>);
</code></pre>
<p>これ、同じ処理をタプルを使わず書くとすると、まあ、以下のようにしますよね。</p>
<pre class="source" title="タプルを使わないswap処理">
<code><span class="reserved">var</span> temp = x;
x = y;
y = temp;
</code></pre>
<p>こいつらにも副作用を加えてみましょう。</p>
<p>まず、タプルを使うもの。</p>
<pre class="source" title="タプルを使ったswap処理 + 副作用">
<code><span class="reserved">var</span> x = 1;
<span class="reserved">var</span> y = 2;
(Log(<span class="reserved">ref</span> x), Log(<span class="reserved">ref</span> y)) = (Log(y), Log(x));
</code></pre>
<p>ちゃんと、これも左から右に順に評価されます。すなわち、<code>ref x</code>, <code>ref y</code>, <code>y</code>, <code>x</code>の順。なので結果は以下の通り。</p>
<pre class="console" title="タプルを使ったswap処理 + 副作用">
<code>1
2
2
1
</code></pre>
<p>で、これをタプルなしで副作用も込みで全く同じ挙動にするためにはどうするか。</p>
<p>先ほどの類推で以下のように書いてしまうと、副作用の順序が変わります。</p>
<pre class="source" title="タプルを使わないswap処理 + 副作用 1">
<code><span class="reserved">var</span> temp = Log(x);
Log(<span class="reserved">ref</span> x) = Log(y);
Log(<span class="reserved">ref</span> y) = temp;
</code></pre>
<pre class="console" title="タプルを使わないswap処理 + 副作用 1">
<code>1
1
2
2
</code></pre>
<p>正しくは、以下のように書かないと同じにはなりません。</p>
<pre class="source" title="タプルを使わないswap処理 + 副作用 2">
<code><span class="reserved">ref</span> var rx = <span class="reserved">ref</span> Log(<span class="reserved">ref</span> x);
<span class="reserved">ref</span> var ry = <span class="reserved">ref</span> Log(<span class="reserved">ref</span> y);
<span class="reserved">var</span> vy = Log(y);
<span class="reserved">var</span> vx = Log(x);
rx = vy;
ry = vx;
</code></pre>
<h2>まとめ</h2>
<p>副作用があっても常に一定の結果になるように、C#では、オペランドの評価順が常に左から右、書かれている通りの順序で行われます(まあ、割かし最近のプログラミング言語では大体同じで順序保証があります)。</p>
<p>ただ、順序保証がない場合に比べて、保証のためのコストがちょっとだけかかります(なので、古いプログラミング言語では「コンパイラーの実装ごとに変えていい」となっているものも結構あります)。</p>
<p>まあ、これだけ書いておいて身もふたもない結論で締めますが、副作用起こすような式を書くやつが悪い。</p>
 ]]></description>
				<pubDate>Sun, 04 Dec 2016 01:10:43 +0900</pubDate>
			</item>
			<item>
				<title>小ネタ corefxlabとSystem.Memory</title>
				<link>http://ufcpp.net/blog/2016/12/tipscorefxlab/</link>
				<description><![CDATA[ <h2>corefxlab</h2>
<p>.NETチームは以下のリポジトリの1つに、<a href="https://github.com/dotnet/corefxlab">corefxlab</a>というものがあります。
名前通り、<a href="https://github.com/dotnet/corefx">corefx</a> (.NET の標準ライブラリ)入りを目指して試験的なコードを入れておく場所で、
安定したものからcorefxに移転になったりします。</p>
<p>corefxの方にいきなり入らず、一度「lab」を経ているわけで、
それなりに「これまでの.NETではあまり取り組んでなくてこなれていないもの」が含まれています。</p>
<p>その最たるものがパフォーマンス。
.NETは、これまでどちらかというと生産性や安全性が優先だったわけで、
「そんなコード書いてまでパフォーマンス求める？」みたいなものは少なかったんですが、
最近ではそういうコードが増えてきています。</p>
<p>もちろんこれまでもパフォーマンスは必要だったわけですが、
そういう場合はすぐにネイティブ コードに逃げていました。
.NETはネイティブ コードとの相互運用もしっかりしているわけで、それも1つの解決策です。</p>
<p>ですが、.NETもこなれてきて、.NET単体でのパフォーマンスに目を向ける余裕も出てきました。
それになんだかんだ言って、ネイティブ側、.NET側の双方で配慮しないとパフォーマンスが出ないことも多々あります。
それに取り組んでいるのがcorefxlabです。</p>
<p>といっても、そういう「そんなの書いてまで」的なコードは、型の中に閉じ込めています。
corefxlab中のライブラリの中身は結構な頑張り具合になっていますが、
単にビルド済みのライブラリを使うだけならそこまで変なライブラリでもないでしょう。</p>
<h2>System.Memory (旧 System.Slices)</h2>
<p>そんなcorefxlab出身のライブラリの中から例として1つのライブラリを紹介します。</p>
<ul>
<li><a href="https://github.com/dotnet/corefx/tree/master/src/System.Memory"><code>System.Memory</code></a></li>
</ul>
<p>昔は<code>System.Slices</code>という名前でcorefxlabにありました。
というか、まあ、さらに追加で試験的なコードを書く場所として、corefxlab側にも<code>System.Slices</code>が残ってはいます。(本当にやばそうなコードはcorefxlab側に取り残されています。<a href="https://github.com/dotnet/corefxlab/blob/master/src/System.Slices/System/SpanExtensions_binary.cs#L22"><code>Cast</code></a>とか。)</p>
<ul>
<li><a href="https://github.com/dotnet/corefxlab/tree/master/src/System.Slices"><code>System.Slices</code></a></li>
</ul>
<p>Slices (切れ端、断片)という名前は歴史的経緯のようです。
現在<code>Span</code> (区間)と呼ばれている構造体も、昔は<code>Slice</code>という名前だったみたいです。
今となってはどこにも<code>Slice</code>という名前は残っていないし、corefxに移る際には<code>System.Memory</code>というパッケージ名に変わりました。</p>
<p><code>Span&lt;T&gt;</code>構造体の持つ機能を単純化して書くと、以下のようなコードと同類の機能を提供するものです。</p>
<pre class="source" title="単純化したSpan">
<code><reserved></span><span class="reserved">struct</span> <span class="type">Span</span>
{
    <span class="reserved">public</span> <span class="reserved">byte</span>[] _data;
    <span class="reserved">public</span> <span class="reserved">int</span> _offset;
    <span class="comment">// 本来は範囲チェックも必要なので length も必要</span>

    <span class="reserved">public</span> Span(<span class="reserved">byte</span>[] data, <span class="reserved">int</span> offset = 0)
    {
        _data = data;
        _offset = offset;
    }

    <span class="comment">// C# 7登場に合わせて ref uint に変更予定</span>
    <span class="reserved">public</span> <span class="reserved">unsafe</span> <span class="reserved">uint</span> <span class="reserved">this</span>[<span class="reserved">int</span> index]
    {
        <span class="reserved">get</span>
        {
            <span class="reserved">fixed</span> (<span class="reserved">byte</span>* p = _data)
            {
                <span class="reserved">var</span> q = (<span class="reserved">uint</span>*)(p + _offset);
                <span class="reserved">return</span> q[index];
            }
        }
        <span class="reserved">set</span>
        {
            <span class="reserved">fixed</span> (<span class="reserved">byte</span>* p = _data)
            {
                <span class="reserved">var</span> q = (<span class="reserved">uint</span>*)(p + _offset);
                q[index] = <span class="reserved">value</span>;
            }
        }
    }

    <span class="reserved">public</span> <span class="type">Span</span> Slice(<span class="reserved">int</span> startIndex) =&gt; <span class="reserved">new</span> <span class="type">Span</span>(_data, startIndex + _offset);
}
</code></pre>
<p>この単純化して示せている部分で言うと、<code>Span</code>の機能は以下の通りです。</p>
<ul>
<li>配列の一部分だけを参照する</li>
<li>元の型(この例だと<code>byte</code>)とは違う型(同 <code>int</code>)の値を、配列に対して直接読み書きする</li>
</ul>
<p>これに対してさらに、本物の <code>Span&lt;T&gt;</code> は以下のようなものです。</p>
<ul>
<li>
型を自由に変えれる
<ul>
<li>
任意の型の配列を受け取れる
<ul>
<li>ジェネリックを使える</li>
</ul>
</li>
<li>
<code>Cast&lt;T, U&gt;()</code>で、他の型に強制変換できる
<ul>
<li><code>T</code>型の配列に、<code>U</code>の値を直接書き込める</li>
</ul>
</li>
</ul>
</li>
<li>ヒープ(配列)、スタック(<code>stackalloc</code>)、ネイティブ バッファー(ポインター)を統一的に扱える</li>
<li><code>fixed</code> (それなりに負担がある操作)が不要でパフォーマンスがいい</li>
</ul>
<p>たったこれだけのことなんですが、通常のC#では書けなかったりします(後述)。</p>
<p>まあ、とにかく、以下の例のようなことが、そこそこ高パフォーマンスで実行できます。</p>
<pre class="source" title="Spanの利用例">
<code><reserved></span><span class="reserved">using</span> System;

<span class="reserved">struct</span> <span class="type">Data</span>
{
    <span class="reserved">public</span> <span class="reserved">byte</span> A;
    <span class="reserved">public</span> <span class="reserved">byte</span> B;
    <span class="reserved">public</span> <span class="reserved">short</span> C;
    <span class="reserved">public</span> <span class="reserved">int</span> D;
}

<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> Main(<span class="reserved">string</span>[] args)
    {
        <span class="comment">// データ書き込み用のバッファーを byte 配列で用意</span>
        <span class="reserved">var</span> data = <span class="reserved">new</span> <span class="reserved">byte</span>[24];

        <span class="comment">// byte のまま書き込み</span>
        <span class="reserved">var</span> b = <span class="reserved">new</span> <span class="type">Span</span>&lt;<span class="reserved">byte</span>&gt;(data);
        b[0] = 1;
        b[1] = 2;

        <span class="comment">// short を書き込み</span>
        <span class="reserved">var</span> s = b.Slice(2).Cast&lt;<span class="reserved">byte</span>, <span class="reserved">ushort</span>&gt;();
        s[0] = 0x0403;
        s[1] = 0x0605;
        s[2] = 0x0807;

        <span class="comment">// int</span>
        <span class="reserved">var</span> i = s.Slice(3).Cast&lt;<span class="reserved">ushort</span>, <span class="reserved">uint</span>&gt;();
        i[0] = 0x0C0B0A09;
        i[1] = 0x100F0E0D;

        <span class="comment">// 構造体</span>
        <span class="reserved">var</span> l = i.Slice(2).Cast&lt;<span class="reserved">uint</span>, <span class="type">Data</span>&gt;();
        l[0] = <span class="reserved">new</span> <span class="type">Data</span>
        {
            A = 0x11,
            B = 0x12,
            C = 0x1413,
            D = 0x18171615,
        };

        <span class="comment">// 1～24が並ぶはず</span>
        <span class="type">Console</span>.WriteLine(<span class="reserved">string</span>.Join(<span class="string">" "</span>, data));
    }
}
</code></pre>
<h3>構造体の読み書き</h3>
<p>特に、構造体を直接読み書きできるのは、使い方次第では非常に強力です。
構造体内部のレイアウトを気にしなければ、きわめて低コストなシリアライズが実現できる可能性があります。
(データ構造を値型のみの固定長にしないといけなかったり、
文字列を直接持てなかったり、
ARMで使うならバイト境界をまたげないはずだし、制限はきつい。
可能性があると言っても設計はそこそこ難しそう。)</p>
<p>レイアウトに関しては、以下の点に注意が必要です。</p>
<ul>
<li>
エンディアン
<ul>
<li>サーバーもクライアントもIntel系かARM系のCPUを使う状況下ではリトル エンディアン固定で考えても特に問題は出ない</li>
<li>.NETが移植されてる先の大部分がリトル エンディアン(XBox？知らない子ですね…)</li>
<li>
というか、ビッグ エンディアン自体がそこまでもう残ってない
<ul>
<li>「ネットワーク エンディアン」とか言われてTCPとかの世代ではビッグ エンディアンが使われてるけども、最近だとQUICとかはリトル エンディアン</li>
<li>XBoxもXBox Oneで、PSもPS4でリトル エンディアンなCPUに変更</li>
<li>Java がビッグ エンディアンなのが唯一つらいところ…</li>
</ul>
</li>
</ul>
</li>
<li>
バイト境界
<ul>
<li>32ビットCPUか64ビットCPUかで4バイト境界か8バイト境界かが変わるので注意</li>
<li>心配なら<a href="http://ufcpp.net/study/csharp/interop/memorylayout/#layout-kind"><code>StructLayout</code>属性</a>を付ければどの環境でも同じレイアウトにできる</li>
</ul>
</li>
</ul>
<h3>C# で書けないコード</h3>
<p>「通常の C# では書けない」と言いましたが、理由は、ポインターに対する制限が強いせい:</p>
<ul>
<li>ジェネリック型引数に対してポインターを作れない</li>
<li>ポインターと<a href="http://ufcpp.net/study/csharp/sp_ref.html?p=2#ref-returns">参照</a>を相互変換できない</li>
<li>ポインターだけでは<a href="http://ufcpp.net/study/csharp/rm_gc.html#garbage-collection">GC</a>的に安全に参照を持てない</li>
</ul>
<p>じゃあ、どうやって<code>Span&lt;T&gt;</code>構造体を書いているかというと…
ILアセンブラーです。
ILが必要な部分は別の、<a href="https://www.nuget.org/packages/System.Runtime.CompilerServices.Unsafe/"><code>System.Runtime.CompilerServices.Unsafe</code></a>というライブラリに追い出していますが、こちらの中身はほぼ全部ILです。</p>
<ul>
<li>
IL: <a href="https://github.com/dotnet/corefx/blob/master/src/System.Runtime.CompilerServices.Unsafe/src/System.Runtime.CompilerServices.Unsafe.il"><code>Unsafe</code>クラス</a>
<ul>
<li>C#でコンパイル → ildasm で逆アセンブル → 属性中のコードでメソッドの中身を上書きするツール(<a href="https://github.com/dotnet/corefxlab/tree/master/samples/ILsub">ILSub</a>)を通す → ilasm でアセンブル という黒魔術</li>
</ul>
</li>
</ul>
<p>IL を書くのは大変だし、ビルド手順も面倒になるしでなかなか保守がしんどそう。</p>
<p>まあ、こういうコードをC#だけで書けるようにしたいという提案は出ているんですが、
採用されるかどうかは不透明(少なくとも直近の作業には載ってない)。
参考: <a href="http://ufcpp.net/blog/2016/5/pickuproslyn0529/">Compiler intrinsics</a></p>
 ]]></description>
				<pubDate>Sat, 03 Dec 2016 00:01:36 +0900</pubDate>
			</item>
			<item>
				<title>小ネタ コンパイル結果を覗いてみよう</title>
				<link>http://ufcpp.net/blog/2016/12/tipsildasm/</link>
				<description><![CDATA[ <p>めったにはないんですが、パフォーマンス チューニングとかを始めると、C#のコンパイル結果がどうなっているかを覗きたくなることがあります。C#の場合は、C#コード → IL (.NETの中間コード) → ネイティブ コードという2段階の変換が掛かります。</p>
<p>ということで、その極々まれにやりたくなることをやってみましょう。ILとネイティブ コードをそれぞれ覗いてみます。</p>
<p>例として、以下のようなC#コードを考えます。単純にvirtualなメソッドを呼び出すだけのコードです。主に、Mainメソッドの中身を見ていきます。</p>
<pre class="source" title="簡単なC#コード">
<code><span class="reserved">using</span> System;

<span class="reserved">class</span> <span class="type">Base</span> { <span class="reserved">public</span> <span class="reserved">virtual</span> <span class="reserved">void</span> M() =&gt; <span class="type">Console</span>.WriteLine(<span class="string">"Base.M"</span>); }
<span class="reserved">class</span> <span class="type">Derived</span> : <span class="type">Base</span> { <span class="reserved">public</span> <span class="reserved">override</span> <span class="reserved">void</span> M() =&gt; <span class="type">Console</span>.WriteLine(<span class="string">"Derived.M"</span>); }

<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> Main()
    {
        <span class="type">Base</span> b = <span class="reserved">new</span> <span class="type">Derived</span>();
        b.M();
    }
}
</code></pre>
<h2>IL逆アセンブル</h2>
<p>まずはILがどうなっているかを覗いてみましょう。ildasm というツールを使います。ildasmは、以下の場所にあります。</p>
<ul>
<li><code>&quot;C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.1 Tools\x64\ildasm.exe&quot;</code></li>
</ul>
<p>ちなみに、ildasmは IL disassembler (IL逆アセンブラー)の略です。</p>
<p>10.0Aや4.6.1という数字の部分はバージョンによって変わります。あと、x64フォルダーの中と、直上の両方にildasm.exeがあります。ildasmはバージョン違い、x86かx64か違いでいくつか見つかりますが、まあ、大体どれも同じです。</p>
<p>これを使って先ほどのC#コードのコンパイル結果を覗いてみると、<code>Main</code>メソッドは以下のようになっています。</p>
<pre class="source" title="Mainメソッドの逆アセンブル結果">
<code>.method <span class="reserved">private</span> <span class="reserved">hidebysig</span> <span class="reserved">static</span> <span class="reserved">void</span>  Main() <span class="reserved">cil</span> <span class="reserved">managed</span>
{
  .entrypoint
  <span class="comment">// コード サイズ       11 (0xb)
</span>  .maxstack  8
  IL_0000:  newobj     <span class="reserved">instance</span> <span class="reserved">void</span> Derived::<span class="reserved">.ctor</span>()
  IL_0005:  callvirt   <span class="reserved">instance</span> <span class="reserved">void</span> Base::M()
  IL_000a:  ret
} <span class="comment">// end of method Program::Main
</code></pre>
<p>ILは、インスタンス生成や仮想メソッド呼び出し用の命令を持っています。</p>
<ul>
<li>
<code>newobj</code>: インスタンス生成
<ul>
<li>new objectの略</li>
<li>引数には、コンストラクターを参照するためのIDを渡します</li>
<li>命令1バイト + オペランド4バイト</li>
</ul>
</li>
<li>
<code>callvirt</code>: 仮想メソッド呼び出し
<ul>
<li>call virtualの略</li>
<li>引数には、メソッドを参照するためのIDを渡します</li>
<li>命令1バイト + オペランド4バイト</li>
</ul>
</li>
<li>
<code>ret</code>: メソッドを抜ける
<ul>
<li>return</li>
</ul>
</li>
</ul>
<p>ILは、アセンブリ言語ではあるものの、かなり高級言語なことがわかります。仮想メソッド呼び出しのようなオブジェクト指向プログラミングの基本操作が1バイト・1命令で書けるので、ILにコンパイルされた命令列はサイズがかなり小さくなります。</p>
<h2>JIT結果の逆アセンブル</h2>
<p>ILからネイティブ コードへの変換はJIT (Just-in-Time)、すなわち実行時に行われます。そこで、ILから生成されるネイティブ コードを覗くためには、実際に実行してみる必要があります。Visual Studioには、実行時にJIT生成されたネイティブ コードを覗く機能が備わっているので、これを使って覗いてみましょう。</p>
<p>場所は以下の通りです。メニューを <code>[Debug]</code> → <code>[Windows]</code> → <code>[Disassembly]</code> とたどったところにあります。ただし、このウィンドウは、デバッグ実行中しか表示されません。</p>
<p><img src="/media/1102/disasm-quick.png" alt="クイック起動から逆アセンブルを表示" /></p>
<p><img src="/media/1101/disasm-menu.png" alt="メニューから逆アセンブルを表示" /></p>
<p>これで、先ほどのプログラムを実行して、<code>Main</code>メソッドの辺りでブレイクして中身を見てみると、以下のような状態になります。</p>
<p><img src="/media/1103/disasm.png" alt="逆アセンブル結果" /></p>
<h2>ブレイク ポイント</h2>
<p>この画面で、黄色い矢印は、ブレイク ポイントを仕掛けて止めた位置になります。ネイティブ コードの中から、コードを読み進めつつ自分が調べたいコードがどこかを探し出すのは至難のわざなので、こうやって、見たい場所にブレイク ポイントを仕掛けて止めるのがいいでしょう。</p>
<p>ただ、Releaseビルド(というか、最適化オプションを付けてコンパイル)すると、ブレイク ポイントの位置がずれて、自分が狙った位置でプログラムが止まってくれなくなります。最適化された結果のネイティブ コードを確認したいときにはちょっと困ります。</p>
<p>そこで、ちゃんと狙った場所でプログラムを止めるためには、<code>Debugger</code>クラス(<code>System.Diagnostics</code>名前空間)の<code>Break</code>メソッドを使うといいでしょう。このメソッドを書いた位置で必ずプログラムが止まってくれます。</p>
<pre class="source" title="Debugger.Breakメソッドでプログラムを止める">
<code>        System.Diagnostics.<span class="type">Debugger</span>.Break();
        <span class="type">Base</span> b = <span class="reserved">new</span> <span class="type">Derived</span>();
        b.M();
        System.Diagnostics.<span class="type">Debugger</span>.Break();
</code></pre>
<h2>生成されたネイティブ コード</h2>
<p>さて、先ほどの<code>Main</code>メソッドからどういうネイティブ コードが生成されるかを改めてみてみましょう。
x64環境で実行すると以下のようになります。</p>
<pre class="source" title="Mainメソッドから生成されるネイティブ コード">
<code>01960450  mov         ecx,1874E58h  
01960455  call        018630F4  
0196045A  mov         ecx,eax  
0196045C  mov         eax,dword ptr [ecx]  
0196045E  mov         eax,dword ptr [eax+28h]  
01960461  call        dword ptr [eax+10h]  
</code></pre>
<p>それぞれの命令がどういう意味かというと、以下の通りです。</p>
<p><img src="/media/1104/naitive-code.png" alt="Mainメソッドから生成されるネイティブ コード" /></p>
<p>仮想メソッドの仕組みが分かってもらえるでしょうか。2段ほど間接参照が挟まります。</p>
<p>この例でいうと、コンストラクター呼び出しは通常のメソッド呼び出しになるわけですが、こちらは最初からメソッドのアドレスがわかっているので直接呼び出しています(01960455の行)。</p>
<p>一方、メソッドMの呼び出しは、オブジェクトのヘッダー → 型情報テーブル → メソッドのアドレスと参照してからのメソッド呼び出しになります(0196045A～01960461の行)。</p>
<h2>実行が必要</h2>
<p>ここで話したように、JIT結果を覗くためには実際に実行してみる必要があるわけですが…</p>
<p>開発機上での実行だと、Visual Studio = Windowsデスクトップ = Intel CPUなわけで、x86かx64のコードを見ることになります。
一応、UWPプロジェクトを作って、ARMなWindows 10 Mobile実機をPCにつないで実行することで、ARMコードの逆アセンブルも見れることは確認しています(もっと楽な方法ないかな？)。Xamarin.Androidではダメでした。</p>
 ]]></description>
				<pubDate>Fri, 02 Dec 2016 00:03:03 +0900</pubDate>
			</item>
			<item>
				<title>C#小ネタ集: C#をWeb上で試す</title>
				<link>http://ufcpp.net/blog/2016/12/tipstryroslyn/</link>
				<description><![CDATA[ <h2>小ネタ</h2>
<p>ここのところ、twitterで脊髄反射的に飛びついたきり、gistとかに書き散らかして終わりにしちゃってるネタがちらほら溜まってきたので、ここらでブログかしようかなと思います。
C#小ネタ集とか銘打って。</p>
<p>C#小ネタ集と言いつつ、あんまりC#が関係ない物もありますが。
結構溜まってるんで、数日は連続で書くことになるかなと思われます。</p>
<h2>Web上で試したい</h2>
<p>初日のネタは、C#をWeb上で触ってみようという話。</p>
<p>C#の入門記事とか書いてるとよく言われ続けていたのが、「Visual Studioをインストールするのがめんどくさい」って話です。
まあ、めんどくさいですよね。</p>
<p>そこで、今はC#にもWeb上でさらっと試すことができる場所があるので、今日はその紹介をします。</p>
<p>もちろん、じっくり腰を据えてコードを書くときにはもちろんVisual Studioを起動しといた方が楽なんですが。
(日々の仕事がC#とかだったりするとどうせ常時Visual Studioが起動してる状態にあるので別に立ち上げも大した面倒はありません。)
とはいえ、入門向けにいきなり「Visual Studioを入れてください」は、今時ちょっとないよなぁ。</p>
<p>こういうのは、もうVisual Studioなどの統合開発環境に馴れてる人は忘れてる感覚です。
でも、自分が普段使わないプログラミング言語をちょっと試してみたいときのことを想像してみてください。
実務で使うわけでもなし、本腰入れてがっつり勉強するでもなし、ほんのちょっとしたネタを確認したいだけ。
そのためにわざわざ環境構築をしたいですかと言われると、まあ僕だったら嫌です。
実際、<a href="https://golang.org/">Go</a>とか<a href="https://swiftlang.ng.bluemix.net/">Swift</a>とかの挙動を見たいときは、まずWeb上で試します。
コピペ程度のコードしか書けませんが、試してみるだけならそれで十分なことが多いです。</p>
<h2>C#をWeb上で</h2>
<p>ということで、まずは公式サイト。</p>
<p><a href="http://ufcpp.net/blog/2016/5/dotnet/">前にも1度ブログで取り上げていますが</a>、
今は、<a href="http://dot.net/">公式サイト(dot.net！)</a>で、試しにその場でC#を書いて実行結果が見れる機能が付いています。</p>
<p><img src="/media/1098/dotnet.png" alt="dot.net内のStart codingコーナー" /></p>
<p>まあもちろん、<a href="https://paiza.io/">paiza.io</a>とか<a href="http://ideone.com/">ideone</a>みたいなコード共有サイトを使ってもいいんですけども。
やっぱり公式サイトでやってないと、今時不格好ですよね…
ということで、dot.netというドメイン取ったのと、その中でオンラインC#実行ができるようになってたことに気づいたときはうれしかったものです。</p>
<h2>コード共有しつつ、C#をWeb上で</h2>
<p><a href="http://dot.net/">dot.net</a>のオンライン エディターは保存してURLで他の人と共有したりはできません。</p>
<p>最近だと、適当に書き捨てのつもりで書いたコードも、
<a href="https://gist.github.com/">Gist</a>とかに置いておいて、twitterとかで垂れ流したりもします。
そういう用途では、さすがに公式サイトのオンライン エディターは使えません。</p>
<p>そこで、ちょうどこれをやってくれるサイトがあります。
要するに、Gistと連携して、Gistに保存したC#コードを編集、実行してくれるサイト。
そういうサイトも作ってくている方がいらっしゃいます。</p>
<ul>
<li><a href="http://gistlyn.com/">Gistlyn</a></li>
<li><a href="https://github.com/ServiceStack/Gistlyn">Gistlynのソースコード リポジトリ</a></li>
</ul>
<h2>最新のC#をWeb上で</h2>
<p>dot.net上にあるオンライン エディター中のC#は、「リリースされている最新版」です。
当然と言えば当然。
現時点ではC# 6ということになります。</p>
<p><img src="/media/1099/dotnet_cs6.png" alt="dot.net内のStart codingはC# 6" /></p>
<p><a href="https://github.com/dotnet/roslyn">GitHubリポジトリ</a>で開発途中の最新版を試したければ、まあ、通常、ソースコードをcloneしてきて、ビルドして、実行してみたり、その<a href="https://dotnet.myget.org/gallery/roslyn">デイリー ビルド</a>結果を取ってきて、Visual Studio拡張などをインストールしてみる必要があります。</p>
<p>ですがここで、これも前にもブログで触れましたが、オンラインで割と最近のバージョンのC#を試せるサイトを作ってくれている人がいます。</p>
<ul>
<li><a href="http://tryroslyn.azurewebsites.net/">TryRoslyn</a></li>
</ul>
<p><a href="https://github.com/dotnet/roslyn">RoslynのGitHubリポジトリ</a>からいろんなブランチを定期的に取ってきて、それぞれでどういう挙動をしているか確認できるサイトです。
実行結果というか、コンパイル結果のILとか、それを古いバージョンのC#で書くにはどうすればいいかという逆コンパイル結果を表示してくれます。</p>
<p><img src="/media/1100/tryroslyn.png" alt="TryRoslyn" /></p>
<h2>GitHub上のC#コードを解析</h2>
<p>Visual Studioが常時起動しているとしても、
GitHubで見かけたC#コードを、わざわざCloneしてきて手元で見ようとはなかなか思わないですよね。
そのままブラウザーで読みたいです。</p>
<p>その一方で、GitHub上でコードを読んでいると、
クラス名などのシンタックス ハイライトがいまいちだったり、
「定義に移動」したくなるけど、当然GitHub上でそんなことできるはずなくイラッとしたりします。</p>
<p>ブラウザー中で、正しくハイライトされ、「定義に移動」とか「すべての参照を検索」ができるページがほしいです。</p>
<p>マイクロソフトが公式に提供している参照コードがちょうどそんな感じです。</p>
<ul>
<li><a href="https://referencesource.microsoft.com/">.NET 全体の参照ソースコード</a></li>
<li><a href="http://source.roslyn.io/">Roslyn の参照ソースコード</a></li>
</ul>
<p>これらのサイト、Roslynを使ったWebページ生成ツールで作ってるそうです。
ツール自体もオープンソースになっていて、以下のリポジトリで見れます。</p>
<ul>
<li><a href="https://github.com/KirillOsenkov/SourceBrowser">KirillOsenkov/SourceBrowser</a></li>
</ul>
<p>で、要は、このツールを任意のGitHubリポジトリに対してかけてくれるサービスがあるとすごく幸せなわけですが…
これがまた、そういうサービスを作ってくれてる大変親切な方がいらっしゃいます。</p>
<ul>
<li><a href="http://sourcebrowser.io/">Source Browser</a></li>
<li><a href="https://github.com/CodeConnect/SourceBrowser">Source Browserのソースコード リポジトリ</a></li>
</ul>
 ]]></description>
				<pubDate>Thu, 01 Dec 2016 15:16:05 +0900</pubDate>
			</item>
			<item>
				<title>Visual Studio 2017 Release Candidate</title>
				<link>http://ufcpp.net/blog/2016/11/vs2017rc/</link>
				<description><![CDATA[ <p>来てた。</p>
<p>(<a href="https://twitter.com/hashtag/MSFTConnect?src=hash">Connect</a>前のリーク騒動ありましたが… Connectをもって)</p>
<ul>
<li><a href="https://blogs.msdn.microsoft.com/visualstudio/2016/11/16/visual-studio-2017-rc/">Visual Studio 2017 Release Candidate</a></li>
</ul>
<p>もう今、クロスプラットフォームを推す状況なので、Visual Studio for Mac (Xamarin Studioのリブランディング)と、モバイル開発、Azure辺りなんかが前面に出てますが。</p>
<p>とりあえず、「C#な人」的に言えることは、RCになって、C# 7として予定されている機能は全部載ったはず。<a href="http://ufcpp.net/study/csharp/cheatsheet/ap_ver7/">うちのサイトのC# 7の新機能のページ</a>に書かれている内容は全部試せるようになっているはずです。</p>
<p>(<a href="https://github.com/dotnet/roslyn">ソースコード</a>取ってきてビルドして最新の状況を試していたりすると、1か月前くらいからC# 7の全機能使えていたので、自分の中ではそこまでニュース性が大きくなかったりはするんですが。やっぱりインストーラーで入れれる製品で試せるようになると嬉しい。)</p>
<p>ちなみに… <a href="https://github.com/dotnet/roslyn/milestones">リポジトリのマイルストーン</a>を覗いてしまうと、
この後RC 2, RC 3が控えていることが見えてしまっているわけですが。
RC 3かー…
たぶんまだ結構変更入るんだろうなー…
とはいえ、今回のやつでRC (リリース候補)の名前を冠してgo-live (自己責任でプロダクション環境で使ってOK)になりました。
使うか、仕事で…</p>
 ]]></description>
				<pubDate>Wed, 16 Nov 2016 16:42:44 +0900</pubDate>
			</item>
			<item>
				<title>Roslynに提案issueを立てた話: nullの扱いに関して</title>
				<link>http://ufcpp.net/blog/2016/11/nullproblem/</link>
				<description><![CDATA[ <p>MVP Global Summit (グロサミ)に行ってきてたわけですが。</p>
<p>なんか、行きの飛行機内で思いついてしまって、そのまま向こうで頑張って issue 投稿、
せっかくだからグロサミ中に <a href="https://github.com/MadsTorgersen">Mads</a> (C# のPM)を捕まえて「こんな問題見つけちゃって、昨日ちょうどissue立てたんだけどどうしよう？」みたいな話を振ってきたり。</p>
<p>(先に具体例を書いておけば、どれだけ英語がつたなくても結構意図は伝えられる。)</p>
<p>(ちなみに、元々は帰国後にゆっくりページ書くつもりだったんだけど、なんかグロサミ参加の妙なテンションに任せて、
<a href="https://twitter.com/kekyo2">kekyoさん</a>、<a href="https://twitter.com/yfakariya">藤原さん</a>、<a href="https://twitter.com/RyotaMurohoshi">室星さん</a>とかと部屋の飲みの最中にこの方々も巻き込んでissue書きました。)</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/issues/15108">Proposal: user-defined null/default check (non-defaultable value types / nullable-like types) #15108</a></li>
</ul>
<p>勢いで立てたものなので整理できてないんですが… たぶん2パートに分けた方が良さそう。
以下、改めて要約した内容(英語に訳して再投稿予定)。</p>
<h2>2つの提案</h2>
<p>nullの取り扱いと関連して、以下の2つを提案する。</p>
<ul>
<li>非default値型: <code>default(T)</code>の状態を認めない値型が必要ではないか</li>
<li>nullable-like型: 参照型と<code>Nullable&lt;T&gt;</code>以外にも、<code>?.</code>や<code>??</code>が使える型をユーザー定義できるようにすべきではないか</li>
</ul>
<h2>非default値型</h2>
<p><a href="https://github.com/dotnet/roslyn/issues/119">Method Contracts</a>、特に<a href="https://github.com/dotnet/roslyn/issues/5032">参照型の非null保証</a>を入れようと思うと、確実な初期化処理が必須になる。</p>
<p>しかし、構造体の場合、<code>defautl(T)</code>など、既定値によって初期化処理を通らない「0/nullクリア」が発生する。
既定値の「0/nullクリア」のせいで、Contractsや非null保証のフロー解析が狂う可能性がある。</p>
<h3>例1: 非null保証</h3>
<p>パフォーマンスのために、参照型を1つだけ持つようなラッパーを構造体で作ることがある。
(例: <a href="https://github.com/dotnet/corefx/blob/master/src/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableArray_1.cs">ImmutableArray</a>、)
今、パフォーマンスはC#の1つの大きなテーマであり、こういうケースは今後より一層増えるだろう。</p>
<p>例として以下のような構造体を考える。</p>
<pre class="source" title="">
<code><span class="reserved">struct</span> <span class="type">Wrapper</span>&lt;<span class="type">T</span>&gt; <span class="reserved">where</span> <span class="type">T</span> : <span class="reserved">class</span>
{
    <span class="reserved">public</span> <span class="type">T</span> Value { <span class="reserved">get</span>; }
    <span class="reserved">public</span> Wrapper(<span class="type">T</span> value)
    {
        Value = value ?? <span class="reserved">throw</span> <span class="reserved">new</span> <span class="type">ArgumentNullException</span>(<span class="reserved">nameof</span>(value));
    }
}
</code></pre>
<p><a href="https://github.com/dotnet/roslyn/blob/master/docs/features/records.md">レコード型</a>や<a href="https://github.com/dotnet/roslyn/issues/5032">非null保証</a>が入れば、単に以下のように書けるだろう。</p>
<pre class="source" title="">
<code><span class="reserved">struct</span> <span class="type">Wrapper</span>&lt;<span class="type">T</span>&gt;(<span class="type">T</span> Value) <span class="reserved">where</span><span class="type">T</span> : <span class="reserved">class</span>
</code></pre>
<p>単に<code>T</code>と書けば非nullとなり、nullを受け付けたければ<code>T?</code>と書くようになる。
問題は、この構造体を<code>default(Wrapper&lt;T&gt;)</code>で作ると、<code>T Value</code> (本来は非nullであるはず)がnullになってしまうことである。</p>
<h3>例2: 値の制約付きの構造体</h3>
<p>以下のような、値に制約の入った構造体を考える。この例は、正の数しか受け取れない数値型である。</p>
<pre class="source" title="">
<code><span class="reserved">struct</span> <span class="type">PositiveInt</span>
{
    <span class="reserved">public</span> <span class="reserved">int</span> Value { <span class="reserved">get</span>; }
    <span class="reserved">public</span> PositiveInt(<span class="reserved">int</span> value)
    {
        <span class="reserved">if</span> (value &lt;= 0) <span class="reserved">throw</span> <span class="reserved">new</span> <span class="type">ArgumentOutOfRangeException</span>(<span class="reserved">nameof</span>(value));
        Value = value;
    }
}
</code></pre>
<p>C#に<a href="https://github.com/dotnet/roslyn/blob/master/docs/features/records.md">レコード型</a>や<a href="https://github.com/dotnet/roslyn/issues/119">Method Contracts</a>が入ると、この構造体はおそらく以下のように書ける。</p>
<pre class="source" title="">
<code><span class="reserved">struct</span> <span class="type">PositiveInt</span>(<span class="reserved">int</span> Value) <span class="reserved">requires</span> Value &gt; 0;
</code></pre>
<p>これで<code>Value</code>プロパティが常に0より大きいことが保証できているように見えるが、<code>default(PositiveInt)</code>のせいで、<code>Value</code>に0が入ることがあり得る。この値は無効なはずである。</p>
<h3>提案: 非defaultフロー解析</h3>
<p>現在提案されている参照型の<a href="https://github.com/dotnet/roslyn/issues/5032">非null保証</a>は、フロー解析に基づいている。
値型が既定値でないことも、同じフロー解析で行えるはずである。</p>
<p>そこで、non-nullable reference typesに対して、non-defaultable value typesを提案したい。
何らかのアノテーション、例えば<code>[NonDefault]</code>属性を付けた構造体は既定値を取ってはいけないとするのはどうだろうか。</p>
<pre class="source" title="">
<code>[<span class="type">NonDefault</span>]
<span class="reserved">struct</span> <span class="type">Wrapper</span>&lt;<span class="type">T</span>&gt;(<span class="type">T</span> Value) <span class="reserved">where</span><span class="type">T</span> : <span class="reserved">class</span>

[<span class="type">NonDefault</span>]
<span class="reserved">struct</span> <span class="type">PositiveInt</span>(<span class="reserved">int</span> Value) <span class="reserved">requires</span> Value &gt; 0;
</code></pre>
<p>このとき、non-nullable reference typesに倣って、以下のように警告を出す。</p>
<pre class="source" title="">
<code><span class="type">PositiveInt</span> x = <span class="reserved">default</span>(<span class="type">PositiveInt</span>); <span class="comment">// warning</span>
<span class="type">PositiveInt</span>? y = <span class="reserved">default</span>(<span class="type">PositiveInt</span>); <span class="comment">// OK</span>
<span class="type">PositiveInt</span> z = y; <span class="comment">// warning</span>
<span class="type">PositiveInt</span> w = y ?? <span class="reserved">new</span> <span class="type">PositiveInt</span>(1); <span class="comment">// OK</span>
</code></pre>
<p>non-defaultable value typesに対する<code>T?</code>は<code>Nullable&lt;T&gt;</code>を必要としない。
何故なら、<code>default(T)</code>は無効であり、<code>x.HasValue</code>を確かめなくても、<code>x == default(T)</code>で値を持っていないことが確認できるからである。
non-defaultable value typesに対しては<code>null</code>を<code>default(T)</code>と同一視してもいいかもしれない。</p>
<p>また、通常の構造体の中では、non-nullable reference typesのメンバーを持てないようにすべきだろう。
non-nullable reference typesを持てるのは、参照型か、non-defaultable value typesのみである。</p>
<h2>nullable-like型</h2>
<p>現在、参照型と<code>Nullable&lt;T&gt;</code>構造体はC#コンパイラーによって特別な地位を与えられている。
すなわち、null条件演算子(<code>?.</code>)とnull合体演算子(<code>??</code>)の利用である。</p>
<p>しかし、これらの型以外にも、無効なインスタンスを<code>?.</code>や<code>??</code>で伝搬/差し替えしたいことがある。</p>
<p>この挙動はmonad的であり、<a href="http://mikehadlow.blogspot.jp/2011/01/monads-in-c-5-maybe.html">LINQ</a>や<a href="https://github.com/ckimes89/arbitrary-async-return-nullable/">Task-like</a>を使って無理やり解決しようとしている例もある。
しかし、悪用・乱用の類であり、決して読みやすいコードにはならないだろう。
無効なインスタンスの伝搬/差し替えは、やはり、<code>?.</code>や<code>??</code>を使うべきである。</p>
<h3>例1: UnityEngine.Object</h3>
<p><a href="http://japan.unity3d.com/">Unity</a>のゲーム中のオブジェクトの共通基底クラスとなる<code>UnityEngine.Object</code>は<code>operator ==</code>をオーバーロードしていて、オブジェクトが持っているネイティブ リソースがすでに破棄されているとき、オブジェクトをnull扱いする(<code>x == null</code>が真になる)。</p>
<p>しかし、参照型に対する<code>?.</code>や<code>??</code>では、オーバーロードした<code>==</code>は呼ばれない(<code>brtrue</code>命令によるnullチェックに展開される)。
そのため、以下のように、<code>?.</code>を使ったコードが正しく動かない。</p>
<pre class="source" title="">
<code><span class="reserved">int</span>? X(UnityEngine.<span class="type">Object</span> obj)
{
    <span class="comment">// OK</span>
    <span class="reserved">if</span> (obj == <span class="reserved">null</span>) <span class="reserved">return</span> <span class="reserved">null</span>;
    <span class="reserved">return</span> obj.GetInstanceID();
}

<span class="comment">// runtime exception</span>
<span class="reserved">int</span>? Y(UnityEngine.<span class="type">Object</span> obj) =&gt; obj?.GetInstanceID();
</code></pre>
<p>これまではUnityがC# 3.0にしか対応していなかったので問題にならなかったが、
Unity 5.5でC# 6.0に対応しようとしている。
この<code>?.</code>の挙動がはまるポイントになるだろう。</p>
<h3>例2: Expected</h3>
<p>無効な値としてnullを使うことを嫌う人が一定数いるが、その理由の1つが、「なぜ無効な値を返す必要があったのか」という原因に関する情報が消えることである。
そのため、<code>Nullable&lt;T&gt;</code>の代わりに、<code>T</code>と例外のunion型にあたる<code>Expected&lt;T&gt;</code>のような型を作って使おうとする人がいる。
例えば、<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4015.pdf">C++でそういう動きがみられる</a>。</p>
<pre class="source" title="">
<code><span class="reserved">struct</span> <span class="type">Expected</span>&lt;<span class="type">T</span>&gt;
{
    <span class="reserved">public</span> <span class="type">T</span> Value { <span class="reserved">get</span>; }
    <span class="reserved">public</span> <span class="type">Exception</span> Exception { <span class="reserved">get</span>; }
}
</code></pre>
<p>もしC#でもそういう型を作るのであれば、<code>?.</code>を使った例外の伝搬や、<code>??</code>を使った例外からの復帰があってもいいのではないだろうか。</p>
<pre class="source" title="">
<code><span class="type">Expected</span>&lt;<span class="reserved">string</span>&gt; x = <span class="reserved">new</span> <span class="type">Expected</span>&lt;<span class="reserved">string</span>&gt;(<span class="reserved">new</span> <span class="type">Exception</span>());
<span class="type">Expected</span>&lt;<span class="reserved">int</span>&gt; y = x?.Length;
<span class="reserved">string</span> z = x ?? <span class="string">""</span>;
</code></pre>
<h3>提案: ユーザー定義のnullable-like型</h3>
<p>所定のパターンを実装した型であれば<code>?.</code>および<code>??</code>を使えるようにすることを提案する。
<a href="https://github.com/dotnet/roslyn/issues/7169">Task-like</a>に倣ってこれをnullable-likeと呼ぼう。</p>
<p>例えば、以下のようなパターンはどうだろうか。</p>
<pre class="source" title="">
<code><span class="reserved">struct</span> <span class="type">NullableLike</span>&lt;<span class="type">T</span>&gt;
{
    <span class="reserved">public</span> <span class="type">T</span> Value { <span class="reserved">get</span>; }
    <span class="reserved">public</span> <span class="reserved">bool</span> HasValue { <span class="reserved">get</span>; }
    <span class="comment">// propagate a valid value</span>
    <span class="reserved">public</span> <span class="type">NullableLike</span>&lt;<span class="type">U</span>&gt; Propagate&lt;<span class="type">U</span>&gt;(<span class="type">U</span> value);
    <span class="comment">// propagate an invalid value</span>
    <span class="reserved">public</span> <span class="type">NullableLike</span>&lt;<span class="type">T</span>&gt; Propagate();
}
</code></pre>
<p>これで、先ほどの<code>Expected&lt;T&gt;</code>の例であれば、以下のように展開する。</p>
<pre class="source" title="">
<code><span class="type">Expected</span>&lt;<span class="reserved">string</span>&gt; x = <span class="reserved">new</span> <span class="type">Expected</span>&lt;<span class="reserved">string</span>&gt;(<span class="reserved">new</span> <span class="type">Exception</span>());
<span class="type">Expected</span>&lt;<span class="reserved">int</span>&gt; y = x.HasValue ? x.Propagate(x.Value.Length) : x.Propagate&lt;<span class="reserved">int</span>&gt;();
<span class="reserved">string</span> z = x.HasValue ? x.Value : <span class="string">""</span>;
</code></pre>
<p>ちなみに、このパターンに沿った<code>Expected&lt;T&gt;</code>の実装は以下のようになる。</p>
<pre class="source" title="">
<code><span class="reserved">struct</span> <span class="type">Expected</span>&lt;<span class="type">T</span>&gt;
{
    <span class="reserved">public</span> <span class="type">T</span> Value { <span class="reserved">get</span>; }
    <span class="reserved">public</span> <span class="type">Exception</span> Exception { <span class="reserved">get</span>; }

    <span class="reserved">public</span> Expected(<span class="type">T</span> value)
    {
        Value = value;
        Exception = <span class="reserved">null</span>;
    }
    <span class="reserved">public</span> Expected(<span class="type">Exception</span> exception)
    {
        Value = <span class="reserved">default</span>(<span class="type">T</span>);
        Exception = exception;
    }

    <span class="reserved">public</span> <span class="reserved">bool</span> HasValue =&gt; Exception == <span class="reserved">null</span>;
    <span class="reserved">public</span> <span class="type">Expected</span>&lt;<span class="type">U</span>&gt; Propagate&lt;<span class="type">U</span>&gt;() =&gt; <span class="reserved">new</span> <span class="type">Expected</span>&lt;<span class="type">U</span>&gt;(Exception);
    <span class="reserved">public</span> <span class="type">Expected</span>&lt;<span class="type">U</span>&gt; Propagate&lt;<span class="type">U</span>&gt;(<span class="type">U</span> value) =&gt; <span class="reserved">new</span> <span class="type">Expected</span>&lt;<span class="type">U</span>&gt;(value);
}
</code></pre> ]]></description>
				<pubDate>Sat, 12 Nov 2016 10:30:15 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 10/30: 分解、宣言式、ワイルドカードの内部仕様変更</title>
				<link>http://ufcpp.net/blog/2016/10/pickuproslyn1030/</link>
				<description><![CDATA[ <p><a href="https://github.com/dotnet/roslyn">Roslynリポジトリ</a>のブランチやマイルストーンの動きを見るに、次のVisual Studio 15 PreviewはもうRCなようですが。
RC (リリース候補)の段階で大きな変更をするわけもなく、<a href="https://github.com/dotnet/roslyn/issues/14804">最近のC#チームの動き</a>は大体「ただひたすらバグ修正」なわけです。</p>
<p>そんな中、仕様変更の話が。</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/issues/14794">Proposed changes for deconstruction, declaration expressions, and wildcards #14794</a></li>
</ul>
<p>まあ、内部挙動的な話なので、C# 7の見栄え上はほとんど変わらないはず。<a href="http://ufcpp.net/study/csharp/datatype/deconstruction/">分解</a>や<a href="http://ufcpp.net/study/csharp/sp_ref.html#out-var">出力変数宣言</a>で、<code>(A &lt; B, C &gt; D)</code>みたいな解釈の難しい書き方がどう解釈されるか、みたいな細かい挙動が変わるだけです。</p>
<p>ただ、プログラミング言語としてのC# 7的には大した変化じゃないですが、CodeAnalysis API(いわゆる、Compiler as a Service。C#コンパイラーの中身を誰でも見れるようにするって意味でのC# 7 API)的にはもちろん目立つ変更になります。要は、<code>SyntaxNode</code>の種類が変わります。</p>
<h2>ワイルドカード</h2>
<p>ワイルドカード(wildcard)は、仮引数、分解、出力変数などの値を受け取る側で、別にその値を使わない場合に無視する記法がほしいというやつ。
以下の、<code>*</code>みたいなやつ。</p>
<pre class="source" title="Wildcardの例">
<code><span class="reserved">using</span> System;
<span class="reserved">using</span> System.Diagnostics;

<span class="reserved">class</span> <span class="type">Base</span>
{
    <span class="reserved">public</span> <span class="reserved">event</span> <span class="type">EventHandler</span>&lt;<span class="reserved">string</span>&gt; E;
    <span class="reserved">protected</span> <span class="reserved">virtual</span> <span class="reserved">void</span> M(<span class="reserved">int</span> x, <span class="reserved">int</span> y) { }
    <span class="reserved">public</span> <span class="reserved">void</span> Deconstruct(<span class="reserved">out</span> <span class="reserved">int</span> x, <span class="reserved">out</span> <span class="reserved">int</span> y)
    {
        x = 1;
        y = 2;
    }
}

<span class="reserved">class</span> <span class="type">X</span> : <span class="type">Base</span>
{
    <span class="reserved">public</span> X()
    {
        E += (*, *) =&gt; <span class="type">Debug</span>.WriteLine(<span class="string">"log message"</span>);

        Deconstruct(<span class="reserved">out</span> *, <span class="reserved">out</span> <span class="reserved">var</span> y);
    }

    <span class="reserved">protected</span> <span class="reserved">override</span> <span class="reserved">void</span> M(<span class="reserved">int</span> *, <span class="reserved">int</span> *)
    {
    }
}
</code></pre>
<p>案としては <code>_</code>、<code>*</code>、<code>?</code> なんかが出ていました。これまで、<code>*</code> が最有力だったんですが、<code>_</code> の方にするかも、とのこと。</p>
<ul>
<li>
<code>_</code>
<ul>
<li>今現在、<code>_</code> 1文字はC#の識別子として有効なものなので、<code>_</code> をワイルドカードに使うのは破壊的変更になりかねない</li>
<li>一応、<code>_</code>を使っている場所があれば識別子として、使ってなければワイルドカードとして扱うみたいな処理を入れれば破壊的変更にはならない</li>
<li>ただ、それやるとユーザー的には混乱しないかという話はある。まあ、現状すでに、多くのユーザーが<code>_</code>を「使わない引数」として使ってるので大丈夫ではないか</li>
</ul>
</li>
<li>
<code>*</code>、<code>?</code>
<ul>
<li>破壊的変更は起こしにくい</li>
<li>ただ、<code>int *</code>みたいな書き方が、「<code>int</code>型をワイルドカードで無視」なのか、「ポインター型<code>int*</code>」なのかという不明瞭さがある</li>
<li><code>?</code>も、null許容型の<code>int?</code>との不明瞭さがある</li>
<li>この不明瞭さの解決の方が、<code>_</code>の方の問題よりも難しそうという意見に傾いてきた</li>
</ul>
</li>
</ul>
<h2>宣言式</h2>
<p>元々の計画としては、式の途中のどこにでも変数宣言を書ける「宣言式」(declaration expressions)という機能が検討されていました。
現在でも、将来的には宣言式を追加する見込みは非常に高いですが、C# 7では入りません。</p>
<p>一方、C# 7に入る<a href="http://ufcpp.net/study/csharp/sp_ref.html#out-var">出力変数宣言</a>は、この宣言式のサブセットみたいなものです。
なので、内部的には(CodeAnalysis API的には)、出力変数宣言は最初から「declaration expression」という名前になっています。</p>
<h2>分解</h2>
<p>一方、現状では、<a href="http://ufcpp.net/study/csharp/datatype/deconstruction/">分解</a>は、分解専用のステートメントとして実装されています。
これが、将来的に宣言式を入れたときに邪魔になりそうなわけです。
分解も、宣言式を使って表現した方がいいだろうということで、C# 8の際に破壊的変更にならないように、今から変えてしまいたいとのこと。</p>
<p>例えば、現状、C# 7では書けないものの、将来的には認められそうな書き方として、以下のようなものがあります。</p>
<pre class="source" title="C# 7では書けないけども、将来的には認められそうな書き方">
<code><span class="reserved">var</span> tuple = (1, 2);

<span class="comment">// タプル構築 + 分解(しかも、新しい変数 x, y を宣言しながら)</span>
<span class="reserved">var</span> t = (<span class="reserved">int</span> x, <span class="reserved">int</span> y) = tuple;
</code></pre>
<p>この、<code>int x</code>、<code>int y</code>の部分は、まさに、宣言式であるべきだろうという話です。</p>
<p>付随して、タプル、分解、出力変数宣言などでモデルをそろえておかないと、細かい挙動で差が出て気持ち悪いというのもあります。
例えば、以下のようなコードはどう評価されるべきか。</p>
<p><code>(A &lt; B, C &gt; D) = F(A &lt; B, C &gt; D = value);</code></p>
<p>以下の2つの解釈ができます。</p>
<ul>
<li><code>A &lt; B</code>と<code>C &gt; D</code>という2つの式を持つ</li>
<li><code>A&lt;B, C&gt;</code>というジェネリック型の変数<code>D</code>を宣言式で宣言している</li>
</ul>
<p>これが、現状の、宣言式と分解で異なる実装をしてる状態だと、それぞれ逆の解釈になるそうで、まずい。
今のうちに統一挙動にしてしまいたいということに。</p>
<h2>foreach の変更</h2>
<p>C# 7的に、分解が書けるのは以下の3カ所。</p>
<ul>
<li>分解ステートメント: <code>var (x, y) = t;</code></li>
<li><code>for</code>ステートメント: <code>for (var (x, y) = t; cond; iter)</code></li>
<li><code>foreach</code>ステートメント: <code>foreach (var (x, y) in list)</code></li>
</ul>
<p>このうち、<code>for</code>は現在の文法構造で、この「分解も宣言式で定義する」という変更に耐えれるそうです。</p>
<p>一方、<code>foreach</code>には変更が必要そう。</p>
<h2>まとめ</h2>
<p>宣言式とワイルドカードっていう、C# 7では入らない/入らなさそうな機能に関する話ではあるけども、
C# 7の時点からちゃんと考えて作っておかないと後から困りそう。
なので今から、宣言式とワイルドカードを前提とした作りにしておきたい、という話。</p>
 ]]></description>
				<pubDate>Sun, 30 Oct 2016 03:22:22 +0900</pubDate>
			</item>
			<item>
				<title>.NET Fringe Japan 2016で登壇してきました</title>
				<link>http://ufcpp.net/blog/2016/10/dotnetfringejp/</link>
				<description><![CDATA[ <p><a href="http://dotnetfringe-japan.connpass.com/event/35659/">.NET Fringe Japan 2016</a>やりました。</p>
<p><a href="http://dotnetfringe.org/">.NET Fringe</a>っていう本家イベント(アメリカのポートランドで開催)があって、本家の人からそれの日本版をやりませんか？という話が来てそれに応じた形での開催だったりします。</p>
<p>アメリカのイベントって朝からがっつりやるんですよね。本家.NET Fringeは9時開始。日本でもたまにはがっつりやるかって感じで10時開始になりました。
まあ、逆に、アメリカのイベントは17時前に終わるんですが…10時～20時半はさすがにきつかったかなぁ。という感じも。</p>
<h2 id="c">C#言語機能の作り方</h2>
<p>で、僕のセッション。</p>
<div style="width: 608px; max-width: 100%; margin-bottom:5px;"><a href="https://docs.com/iwanaga-nobuyuk/1121" title="C#言語機能の作り方" target="_blank" style="font-family: 'Segoe UI'; font-size: 13px; text-decoration: none; margin-left:18px ">C#言語機能の作り方</a><span style="font-family: 'Segoe UI'; font-size: 13px ">—</span><a href="https://docs.com/iwanaga-nobuyuk" target="_blank" style="font-family: 'Segoe UI'; font-size: 13px; text-decoration: none ">Iwanaga Nobuyuki</a></div><iframe src="https://docs.com/d/embed/D25192700-1492-1911-6360-000919169843%7eMd2f0fde0-d68b-9095-2ec5-841305bd4fb1" frameborder="0" scrolling="no" width="608px" height="378px" style="max-width:100%" allowfullscreen="True"></iframe>
<p>作り方とかいいつつ、むしろ全力で止めにかかってる予防接種セッション。</p>
<p>⚠使用上の注意</p>
<ul>
<li>「独自に言語を作ろう・拡張しよう」みたいな話はハシカみたいなもんです
<ul>
<li>早めに免疫つけといた方がいい</li>
<li>歳食ってから罹ると重篤なことが</li>
</ul>
</li>
</ul>
<p>という。</p>
<p>とはいえ、やるだけ無駄とかやっちゃダメって話ではなく。むしろ、早めに罹っとけって話です。予防接種も、弱毒化したウィルスにあらかじめ罹ることで免疫付ける手法ですしね。</p>
<p>良し悪しとかどのくらい大変かとかはある程度の勘所がないと、いざ責任ある立場になって大きなことやれるようになった時に下手打つと命に係わるぞと。
この辺りは別にプログラミング言語作りに限らず一般論ですね。
いろいろ試しにやってみて、いろいろ勘をつかんでおくのは大事です。</p>
<p>しいて言うなら、なんかプログラミング言語作りでは、この「どのくらい大変か」を過少見積もりして重篤化する人がなんか一定割合いるっぽく、予防接種スライド作っとくか、と。
わざわざ大変なものに手を出さなくても罹った気分になっておくためのものが、僕が今回やったようなセッションですかね。</p>
<p>「ハシカみたいなもんだから」ってセリフ、いろんな方面に結構ぐさぐさ刺さったみたいですがｗ
@kekyo さん、「新しい opcode 作るよ」って話(<a href="http://www.slideshare.net/kekyo/beachhead-implements-new-opcode-on-clr-jit">スライド</a>、<a href="http://live.nicovideo.jp/watch/lv277167391">ニコ生放送</a>の8時間目くらいから)をしてて「ハシカですね…」って言ってましたけども、
これは割かし良い具合にワクチン(弱毒化したウィルス)なんじゃないですかね。
最小限に手を入れてみるってのは勘所つかむためのかなり良い題材。
まあ、セッションの後、「予防接種ってのはそれなりに流行る可能性のあるものだから必要なんであって、これはハシカと言えるのか(そんなにやりたがる人いるのか)」とかいう鋭い突っ込みもあったんですが。</p>
<p>あと、試しにやってみているだけでも、@neueccさん(<a href="http://www.slideshare.net/neuecc/what-why-how-create-oss-libraries-30coss">スライド</a>、<a href="http://live.nicovideo.jp/watch/lv277167391">ニコ生放送</a>の7時間目くらいから)が言ってたみたいに、公開するつもりでやる/実際に公開する方が身につく度合いが高いと思います。
まず、人に見せる/人に見られることを意識した方が断然勉強になります。
それにどうせお試しで実用性皆無なものであっても、公開していると「予防接種済み」の査証になりますし。結構価値あるんじゃないかと。</p>
 ]]></description>
				<pubDate>Sun, 02 Oct 2016 06:54:15 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップ Roslyn 9/9</title>
				<link>http://ufcpp.net/blog/2016/9/pickuproslyn0909/</link>
				<description><![CDATA[ <h2>タプルの分解の最適化</h2>
<p>タプル構築と同時に分解(要するに多値代入というか)する場合は、タプルを作らない最適化かけたいって。</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/issues/13631">Optimize deconstruction of tuple literal to not construct a ValueTuple #13631</a></li>
</ul>
<p>要するに、例えば以下みたいなswapコード書いたとして、</p>
<pre class="source" title="タプルと分解を使ったswap">
<code><reserved></span><span class="reserved">var</span> x = 1;
<span class="reserved">var</span> y = 2;
(x, y) = (y, x);
</code></pre>
<p>今だとこうなる。</p>
<pre class="source" title="ValueTupleのコンストラクター呼び出しが発生">
<code><reserved></span><span class="reserved">var</span> x = 1;
<span class="reserved">var</span> y = 2;
<span class="reserved">var</span> v = <span class="reserved">new</span> <span class="type">ValueTuple</span>&lt;<span class="reserved">int</span>, <span class="reserved">int</span>&gt;(x, y);
x = v.Item1;
y = v.Item2;
</code></pre>
<p>これ、実のところこの時点でタプルの特別扱いが掛かってます。
分解の仕様上は、以下のようなコードになるべきところを、タプルでまでそれをやるのは無駄だってことで、<code>Item1</code>、<code>Item2</code>の直参照に。</p>
<pre class="source" title="本来の分解構文の展開結果">
<code><reserved></span><span class="reserved">var</span> x = 1;
<span class="reserved">var</span> y = 2;
<span class="reserved">var</span> v = <span class="reserved">new</span> <span class="type">ValueTuple</span>&lt;<span class="reserved">int</span>, <span class="reserved">int</span>&gt;(x, y);
v.Deconstruct(<span class="reserved">out</span> x, <span class="reserved">out</span> y);
</code></pre>
<p><code>Deconstruct</code>を最適化で消すんだったら、<code>new ValueTuple</code>の方も消していいんじゃない？という感じ。
なのでたぶん、以下のような感じのコードに展開されるのではないかと。
ほぼ、普通のswapコードに。</p>
<pre class="source" title="最適化でnew ValueTupleを消去">
<code><reserved></span><span class="reserved">var</span> x = 1;
<span class="reserved">var</span> y = 2;
<span class="reserved">var</span> tempX = x;
<span class="reserved">var</span> tempY = y;
x = tempY;
y = tempX;
</code></pre>
<h2>Recap of async streams</h2>
<p><a href="https://github.com/ljw1004">Lucian</a> (C#チーム非同期担当の開発者)が夏休みから帰ってきて、現状のまとめを投稿。</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/issues/261#issuecomment-244971681">Recap of async streams</a></li>
</ul>
<p>まあ、本当にまとめのみ。基本、過去にブログで取り上げた内容なので詳細割愛。</p>
<p>あと、<a href="https://github.com/stephentoub">Stephen</a> (.NETチーム内の人。活動を見るに.NETのパフォーマンス改善系の作業をしてるっぽい)がパフォーマンスがらみの懸念を投稿。</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/issues/261#issuecomment-245616932">261#issuecomment-245616932</a></li>
</ul>
<p>現状の<code>IEnumerable</code>の問題でもあるものの、<code>MoveNext</code>と<code>Current</code>にメソッドが分かれてると、スレッド安全に作りようがなくて困る。
<code>IAsyncEnumerable</code>も同じような構造で作られると、async streamをチャネル的に(Go言語のgoroutine/channelみたいに)使いにくい/使えないので、スレッド安全にできる実装を考えてほしいとのこと。</p>
 ]]></description>
				<pubDate>Fri, 09 Sep 2016 04:37:57 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップ Roslyn 9/6: defaultの型推論</title>
				<link>http://ufcpp.net/blog/2016/9/pickuproslyn0906/</link>
				<description><![CDATA[ <p>なんか1個、気になったプルリクが。</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/pull/13603">Prototype: target typed &quot;default&quot; #13603</a></li>
</ul>
<p><code>default(T)</code>を、左辺から型が推論できる場合には<code>default</code>だけで書けるようにしようっていう作業。</p>
<p>ちょっと前に提案があって、前向きっぽい感じではあったんですけど、なんで今実作業やってんだろう。
今からC# 7リリース辺りまでは、C# 7に入る予定の機能のバグ修正・改善ばっかりになると思ってたんですけども。
これくらいの修正ならさっと実装してC# 7に入れれそう？</p>
<p>まあ、これに限らず、今後、左辺から右辺の型推論は今後増えそうな感じです。</p>
<h2>左辺と右辺</h2>
<p>簡単に言葉の説明をしておくと、
左辺とか右辺ってのは、代入文の <code>=</code> の左右から来てる言葉。
<code>x = y</code>だったら、<code>x</code>が左辺で<code>y</code>が右辺です。</p>
<p>転じて、値を受け取る側が左辺で、値を渡す側が右辺。
変数宣言だと、宣言する変数が左辺で、初期値として渡す値が右辺です。
見た目は左右に分かれませんが、メソッド呼びだしなんかでも、値を受け取る側(仮引数)が左辺で値を渡す側(実引数)が右辺と考えられます。</p>
<h2>右辺から左辺の型推論</h2>
<p>C#の型推論って、右辺から左辺の推論が多いです。<code>var</code>しかり、ジェネリック型引数しかり。</p>
<p>以下のような感じ。</p>
<pre class="source" title="右辺からの左辺の型推論(var、ジェネリック)">
<code><reserved></span><span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> Main()
    {
        <span class="reserved">var</span> x = 1; <span class="comment">// 1 からの推論で、int x = 1; 扱い。</span>
        F(2); <span class="comment">// 2 からの推論で、F&lt;int&gt;(2); 扱い</span>
    }

    <span class="reserved">static</span> <span class="reserved">void</span> F&lt;<span class="type">T</span>&gt;(<span class="type">T</span> x) =&gt; System.<span class="type">Console</span>.WriteLine(<span class="reserved">typeof</span>(<span class="type">T</span>).Name);
}
</code></pre>
<h2>左辺から右辺の型推論</h2>
<p>逆に左辺から右辺の型推論なのは、現状ではラムダ式くらい。</p>
<pre class="source" title="左辺から右辺の型推論(ラムダ式)">
<code><reserved></span><span class="reserved">using</span> System;

<span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> Main()
    {
        <span class="type">Func</span>&lt;<span class="reserved">int</span>, <span class="reserved">object</span>&gt; f = x =&gt; x.ToString(); <span class="comment">// f の型が&lt;int, string&gt;なので、(int x) =&gt; (object)x.ToString() 扱い</span>
        X(x =&gt; x.ToString()); <span class="comment">// Xの引数が&lt;int, string&gt;なので、(int x) =&gt; (object)x.ToString() 扱い</span>
    }

    <span class="reserved">static</span> <span class="reserved">void</span> X(<span class="type">Func</span>&lt;<span class="reserved">int</span>, <span class="reserved">object</span>&gt; f) { }
}
</code></pre>
<p>で、今、<code>default</code>と<code>new</code>の型推論を増やしたいという話が出ています。特に、<code>var</code>を使えないフィールドやプロパティに対する初期化子で有効そう。</p>
<pre class="source" title="defaultやnewの型推論">
<code><reserved></span><span class="reserved">class</span> <span class="type">Sample</span>&lt;<span class="type">T</span>&gt;
    <span class="reserved">where</span> <span class="type">T</span> : <span class="reserved">new</span>()
{
    <span class="reserved">static</span> <span class="type">T</span> newValue = <span class="reserved">new</span>();       <span class="comment">// new T() の T を省略</span>
    <span class="reserved">static</span> <span class="type">T</span> defaultValue = <span class="reserved">default</span>; <span class="comment">// default(T) の T を省略</span>

    <span class="reserved">static</span> <span class="reserved">void</span> F(<span class="type">T</span> x = <span class="reserved">default</span>) <span class="comment">// default(T) の T を省略</span>
    {
    }
}
</code></pre>
<p>で、なんか、<code>default</code>の方はプロトタイプ実装が始まったと。
ちなみに、<code>new</code>の方は実装の兆し全然なし。
C#チーム的に前向きに検討したいとは言ってるんですけども、実装コストはそこそこ高そう。
引数ありで、<code>new(1, 2)</code>みたいなのもできる予定です。</p>
<h2>補足: <code>new()</code>と<code>default</code></h2>
<p>余談になりますが、「<code>null</code>じゃダメなの？」とか、「<code>new()</code>だけじゃダメなの？」とか言ってる人もまあ、います。
C#に不慣れな人には結構わかりにくいですよね…</p>
<p>以下のような差があるので、いずれも必要です。</p>
<ul>
<li><code>new T()</code>だとインスタンスが作られる。<code>null</code>にはならない</li>
<li>
<code>null</code>は参照型にしか入らない。ジェネリック型引数<code>T</code>とかだと、<code>T</code>が参照型なのか値型なのか確定しないから<code>null</code>を使えない
<ul>
<li><code>default(T)</code>だと、参照型なら<code>null</code>、値型なら「全メンバー0/<code>null</code>初期化」</li>
</ul>
</li>
<li>
現状、値型であれば<code>new T()</code>と<code>default(T)</code>はどちらも「全メンバー0/<code>null</code>初期化」で、同じものになるけど、将来的に変えたい
<ul>
<li>構造体にも引数なしのコンストラクターを定義できるようにしたい</li>
<li><code>new T()</code>は引数なしのコンストラクター呼び出し</li>
<li><code>default(T)</code>は「全メンバー0/<code>null</code>初期化」</li>
</ul>
</li>
</ul>
<p>ちなみに、構造体の引数なしコンストラクターの話は、一度C# 6に入りかかったんですけど、
<code>Activator.CreateInstance</code>の内部に「構造体の<code>new T()</code>と<code>default(T)</code>は同じ意味」っていう前提で最適化を掛けちゃってるコードがあるらしくて、
これを修正してもらわないとダメってことでrevertされました。</p>
<p>参考:</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/issues/13255#issuecomment-241025874"><code>new()</code>と<code>default</code>は相補的</a></li>
<li><a href="https://github.com/dotnet/roslyn/issues/1029">構造体にも引数なしのコンストラクターを認めようとして当時できなかった話</a></li>
<li><a href="https://github.com/dotnet/roslyn/issues/35#issuecomment-239876676">'new'の左辺からの型推論認めたいって話</a></li>
</ul>
 ]]></description>
				<pubDate>Tue, 06 Sep 2016 11:43:27 +0900</pubDate>
			</item>
			<item>
				<title>プログラミング言語における文字コードの話</title>
				<link>http://ufcpp.net/blog/2016/9/unicode/</link>
				<description><![CDATA[ <p>世の中がほぼUnicode前提になってめでたしめでたし。とはいかなかった現実の話。</p>
<p><code>String</code>型でできる文字列処理とか、ソースコード自体、特に識別子で使える文字とか。</p>
<h2>軽くおさらい: Unicode</h2>
<p>まあいろんなところでいろんな人が書いてると思うのでさらっと概要だけ。</p>
<p>Unicodeは、元々、「65,536文字あれば十分だろ」とかいう幻想の元、2バイト固定長の文字コードとして作られていました。
もちろん足りなくて、ビット数を拡張。基本が2バイトのままでこの拡張した分を取り扱えるようにしたのが今の<a href="https://ja.wikipedia.org/wiki/UTF-16">UTF-16</a>で、拡張分は2文字分(4バイト)を使って表現。
この、2文字分使って1文字を表すやつのことを<a href="https://ja.wikipedia.org/wiki/Unicode#.E3.82.B5.E3.83.AD.E3.82.B2.E3.83.BC.E3.83.88.E3.83.9A.E3.82.A2">サロゲートペア</a>(surrogate pair: 代理対)と呼びます。</p>
<p>あと、ASCII文字も2バイトになるのを欧米人が嫌って、ASCII文字はASCIIコードのまま、逆に漢字・ひらがな・カタカナなんかは3バイトになるようなエンコード方式ができて、それが<a href="https://ja.wikipedia.org/wiki/UTF-8">UTF-8</a>。
固定長文字列とか幻想でした。サロゲートペアとか出てくるくらいならUTF-8でいいでしょう…</p>
<p>UTF-8やUTF-16へのエンコード前の状態、Unicode的に1文字として割り当てられているコードを、<a href="https://ja.wikipedia.org/wiki/%E7%AC%A6%E5%8F%B7%E7%82%B9">コードポイント</a>(code point: 符号点、符号位置)と言います。
Unicodeコードポイントは今のところ21ビットの数値。</p>
<p>コードポイントこそが文字の最小単位かというとそうでもなくて、アクセント記号とか濁点とか、他の文字と組み合わせて使うことで、表示上は1文字に見えるけどもコードポイントは複数になる文字があり得ます。
「か」(U+304B)+「 ゙」(U+3099)で「が」1文字に見えたり、
「a」(U+0061)+「 ́」(U+0301)で「á」1文字に見えたり。</p>
<p>その他、漢字の<a href="https://ja.wikipedia.org/wiki/%E7%95%B0%E4%BD%93%E5%AD%97%E3%82%BB%E3%83%AC%E3%82%AF%E3%82%BF">異字体セレクター</a>とか、絵文字の<a href="http://cloudydesert.net/2014/11/9586">肌トーン</a>とか、複数コードポイントで1文字になるものが結構あります。
こういう、表示上は1文字として扱うべきという単位を<a href="https://hydrocul.github.io/wiki/blog/2015/1025-unicode-grapheme-clusters.html">書記素クラスター</a>(grapheme cluster)と言います。
UI的に、文字の選択や削除は書記素クラスター単位で行うのが好ましいです。
さもなくば、<a href="https://twitter.com/akiroom/status/671978753036169216">家族が1人1人消えていくホラーが発生するわけです</a>。</p>
<p>まとめ:</p>
<ul>
<li>コードポイント: Unicode的に1文字として割り当てられてる21ビットの数値</li>
<li>
エンコード
<ul>
<li>UTF-16: 2バイトですべての文字を表せると思っていた時代の名残。16ビットで収まる範囲はコードポイントそのまま、収まらない範囲は2文字分(4バイト)使って表現(サロゲートペア)</li>
<li>UTF-8: ASCII文字がASCIIコードのまま扱えるように、1～4バイトになるように符号化する方式</li>
</ul>
</li>
<li>書記素クラスター: 表示上1文字になって、選択や削除の際にはまとめて処理されるべき単位</li>
</ul>
<h2>プログラミング言語の<code>String</code>型</h2>
<p>Java (1995年リリース)の辺りから、新しめのプログラミング言語は大体Unicodeを前提としています。
ソースコードは、UTF-8で保存しておけば日本語とかも識別子(変数名とかクラス名とか)に使えます。
<code>String</code>型は標準でUnicodeを扱えたりします。</p>
<p>とはいえ、Unicode自体が紆余曲折あったので、プログラミング言語も紆余曲折振り回されます。</p>
<p>JavaやC#は<code>String</code>型がUTF-16だったりします。サロゲートペアの処理が結構面倒。
Unicodeがまだ2バイト固定長を夢見ていたころの世代の言語。
UTF-16文字からUnicodeコードポイントを得るためのAPIはあるんで何とかできはしますが。</p>
<p>Goなんかは文字列はUTF-8だそうです。</p>
<p>Swiftは、最近できただけあって、結構頑張っています。
内部的にUTF-8かUTF-16を問わず(<code>String</code>型が内部に弁別用のフラグをもってて、適宜デコードしてくれてる)。
API的にも、<code>String</code>型が、以下のようなメンバー(正確にはextension)を持っています。</p>
<ul>
<li><code>characters</code>: 書記素クラスターを列挙</li>
<li><code>unicodeScalars</code>: Unicodeコードポイントを列挙</li>
<li><code>utf16</code>: UTF-16エンコードした2バイトを列挙</li>
<li><code>utf8</code>: UTF-8エンコードしたバイト列を列挙</li>
</ul>
<p>まあ、ちゃんとしてるように見えて、Unicodeの仕様追加に対してちょっと危ういんですが…(後述)</p>
<h2>プログラミング言語の識別子</h2>
<p>一方で、ソースコード自体の話。特に、識別子に使える文字の話。</p>
<p>まともな神経をしてる言語は、Unicodeカテゴリーで識別子に使える文字を縛っています。
非常に大まかにいうと、たいていの言語で識別子に使えるのはLetterのみ。
記号は使えないように絞ってあります。
逆に、Letterなら大抵なんでも。日本語だろうが漢字だろうが使えます。</p>
<ul>
<li><a href="https://paiza.io/projects/UNpuzm5gx11aXfpDOlZubg">Java</a></li>
<li><a href="https://gistlyn.com/?gist=34186a05c5912705972e64008aee3ed8&amp;collection=2cc6b5db6afd3ccb0d0149e55fdb3a6a">C#</a></li>
<li><a href="https://play.golang.org/p/MgKLkjoj-7">Go</a></li>
<li><a href="https://swiftlang.ng.bluemix.net/#/repl/57ca47e14e7e6e741b68e068">Swift</a></li>
</ul>
<h3>C# とサロゲートペア</h3>
<p>ちなみに…
現状の C# はサロゲートペア使えません…
変数名に𩸽とか𠮷とかが使えない状態です。
つい最近まで仕様書に「Unicode Standard, Version 3.0」(サロゲートペアなんてものがなかった時代の仕様)って文字が入ってたくらいでして。
今は、「<a href="https://github.com/dotnet/roslyn/blob/master/docs/compilers/CSharp/Unicode%20Version.md">The Roslyn compilers depend on the underlying platform for their Unicode behavior</a>」(プラットフォームによる。Unicode Standardの変更の影響を受ける)に仕様の文面も変更されることになってるんですが、サロゲートペアへの対応はまだ。</p>
<p>最近、中国人っぽい人から<a href="https://github.com/dotnet/roslyn/issues/13474">不具合報告</a>を受けています。
C#チームの応答を見るに、修正入って使えるようになるかも。
まあ、仕様書的にサロゲートペアが使えてもおかしくなさそうな記述になってる今、
対応していないのはおかしいはずですんで。</p>
<h3>Swiftの攻めっぷり</h3>
<p>一方で、Swiftのやんちゃっぷりは凄くて…
Swiftリリース時点でも、「<a href="http://www.atmarkit.co.jp/ait/articles/1406/03/news129.html">絵文字が使える！</a>」ってアピールされてたのは結構皆さん覚えてらっしゃるかと思えますが。
調べてみたら、絵文字どころかほんとに何でも使える。
個人的にツボったのは以下の2つのネタコード。</p>
<ul>
<li><a href="http://www.atmarkit.co.jp/ait/articles/1406/03/news129.html">0～9の和は1023</a> … 数字に見えますけど、「Mathematical Alphanumeric Symbols」って領域にある記号を使っています</li>
<li><a href="https://swiftlang.ng.bluemix.net/#/repl/57c9007cc4656ed91352709b">不可視識別子</a> … これも数式用の記号。変数xとyを、xyと並べたときに、それが何を意味するか(掛け算か、足し算か、関数適用か、添え字を並べただけか)を判別するために使います</li>
</ul>
<p><a href="https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/LexicalStructure.html#//apple_ref/doc/uid/TP40014097-CH30-ID410">バグでも実装ミスでもなく、仕様</a>。
いいのか悪いのか…
まあ、<a href="https://gist.github.com/ufcpp/73fa3005b75015f6ee13cfdb93cd88e0">Letterに限定してもろくでもないコードは書ける</a>んで、程度の問題なんですが。</p>
<h2>Unicodeの変更/OSの対応状況に振り回される</h2>
<p>Unicode、今もうバージョン9とかなんですっけ。基本は文字の追加だけなので、そんなに毎度毎度は問題を起こさないんですが…時々…</p>
<h3>中黒のカテゴリー</h3>
<p>有名な問題として、「・」(U+30FB、中黒)の扱いが変わったというやつがありまして。
中黒って、日本語的にはハイフンのような使い方をします。2つの単語を並べるときに区切り文字として使う。
ところが、間違えて、「ー」長音記号と同じカテゴリー(Pcカテゴリー)を割り当てられていたという過去があります。
これを、Unicode 4.1だか辺りで、ハイフン扱い(Poカテゴリー)に修正したそうです。</p>
<p>長音と同じであれば、たいていの言語で識別子に使えます。JavaやC#では、昔は中黒を識別子に使えていました。
それが、JavaはJava 7で、C#はC# 6で、いきなり識別子として使えなくなります。
破壊的変更に対してかなり保守的な言語であるJavaとC#が立て続けに破壊的変更を起こしたという。
言語仕様には全く変化がなく、ただ、使っているUnicodeのバージョンが上がったというのが原因になります。</p>
<h3>絵文字の肌トーンと書記素クラスター</h3>
<p>割かし最近の追加と言えば肌トーン。「絵文字とカラーフォントがパンドラの箱開けちゃった」と有名なあれ。</p>
<p>「なぜ白い肌の絵文字しかない」とかいう政治的な地雷を踏みぬいた結果、「<a href="http://emojipedia.org/modifiers/">Emoji Skin Tone Modifiers</a>」という補助文字が作られて、
絵文字の後ろにくっつけると絵文字の肌色が変化するというもの。</p>
<p>iOS 8.3で対応したんでしたっけ。
それ以前は、肌トーンは「肌色の四角形」で描画されていました。顔文字と並べると、顔文字＋四角形の2文字が表示されます。
以降は、ちゃんと1文字の顔文字で肌の色が変わります。</p>
<p>ここで、書記素クラスターの話に戻ります。
表示上1文字として描画されるべきものが書記素クラスター。
肌トーンはどうなるかというと、<a href="http://unicode.org/reports/tr51/">Unicodeコンソーシアムのレポートによれば「単一の書記素クラスターとして扱うべき」</a>とは書かれています。
が、まあ、あくまでそれは、肌トーンに対応したOS上での話。
iOS 8.3より前なら2文字として表示されているわけだし、以降なら1文字扱いしてほしい。</p>
<p>これ、Swiftにとっては、<code>characters</code>(書記素クラスターを列挙)の結果が変わることになります。
現状は変更はされていなくて、肌色指定付きの顔文字の<code>characters.count</code>を調べると、2文字扱いされます。</p>
<ul>
<li><a href="https://swiftlang.ng.bluemix.net/#/repl/57ca51cf4e7e6e741b68e06b">顔+肌トーンの文字数</a></li>
</ul>
<p>そして、公式フォーラムでも問題に上がってるみたい。</p>
<ul>
<li><a href="https://forums.developer.apple.com/thread/26160">Is there any way to get String.characters to group skin tone emoji as a single extended grapheme cluster?</a></li>
</ul>
<p>議題は、要するに、</p>
<ul>
<li><code>characters.count</code>の数え方はプラットフォームに依るべきか</li>
<li>プラットフォームに依るべきとすると、プラットフォームごとに<code>characters</code>の挙動が変わることになるけど、それはありか</li>
<li>挙動が変わるのを良しとしない場合、プラットフォーム依存な、ちゃんと表示されてる文字数を取る手段はあるか</li>
</ul>
<p>という話。</p>
<p>もしかして、書記素クラスターは人類が手を出すにはまだ早すぎたのではないか…</p>
<h2>サロゲートペア対応C#</h2>
<p>何で今こんなこと調べてたかというと、ちょっと、C#コンパイラーいじってみるのの題材として、C#のサロゲートペア対応とかやろうかと思ってまして。</p>
<p><a href="http://dotnetfringe-japan.connpass.com/event/35659/">.NET Fringe Japan</a>で「言語機能の作り方」って感じの話をする予定で、その一環。
実際のセッション内容としては、「うかつに独自機能とか考えるんじゃないぞ」という予防接種が半分、「それでもコンパイラーに手を入れたいっていうならデモくらい見せるけど…」みたいな内容が半分の予定で、この後半の内容になります。</p>
<p>どうせやるなら、多少芽のある話をやろうかと思った結果がサロゲートペア対応。
非ASCII文字の話は、日本人か中国人が率先してやらないと全然実装されないですからねぇ。</p>
<p>で、久々にUnicodeの状況とか、C#以外も含めたプログラミング言語の仕様とかを漁ってみてた結果が本日のブログ。
「絵文字はともかく、𩸽くらいは使えてしかるべきよなぁ」とか考えてたら、
ちょうど同じタイミングで<a href="https://github.com/dotnet/roslyn/issues/13474">Roslynリポジトリ内でその話題(ただし中国語)</a>が出てたり。
Swiftがどこまで緩いの調べてたら<a href="https://swiftlang.ng.bluemix.net/#/repl/57c9007cc4656ed91352709b">想像をはるかに超えてやんちゃ</a>だったり。</p>
 ]]></description>
				<pubDate>Sat, 03 Sep 2016 05:00:46 +0900</pubDate>
			</item>
			<item>
				<title>Unity 5.5でasync/await使えた話</title>
				<link>http://ufcpp.net/blog/2016/9/awaitinunity55/</link>
				<description><![CDATA[ <p><a href="https://blogs.unity3d.com/jp/2016/08/30/get-the-unity-5-5-beta-now/">Unity 5.5 ベータ</a>を入れてみたという話。</p>
<p>ブログ曰く、「Mono C# コンパイラー がMono4.4にアップグレードしました。」とのことなので、これ、C# 6使えるはずよね？と。</p>
<h2>公式サポートはC# 4</h2>
<p><a href="https://unity3d.com/jp/unity/beta">リリースノート</a>を見ると、「C# 4です」って書かれてるわけですが。
Mono 4.4のコンパイラーを使っててC# 6使えないとかお前は何を言っているんだ…</p>
<p>まあ、標準ライブラリの方が .NET Framework 3.5相当のままなので、<code>Task</code>クラスが使えない。
なので当然、普通にやるとasync/awaitが使えない。
その状況下で「C# 6対応」とか言っちゃったら、問い合わせ押し寄せてやばいでしょうから、公式には「C# 4」と言わざるを得ないのはわかります。</p>
<p>要するに、コンパイラー的にC# 6に対応している状況で、<code>langversion</code>オプションを指定してわざと4に絞ってる。</p>
<p>例えば、以下のようなコードを用意します。</p>
<div>
<script src="https://gist.github.com/ufcpp/6c7d3f036189ecdf4fb87fe0d6ff50fd.js"></script>
</div>
<p>async/await (C# 5)、expression-bodied method (C# 6)とか使ってます。
これをコンパイルしようとすると、
Unity 5.3だと以下のようなエラーに。</p>
<pre class="console" title="">
<code>Assets/Scripts/NewBehaviourScript.cs(30,13): error CS1519: Unexpected symbol `=>' in class, struct, or interface member declaration
Assets/Scripts/NewBehaviourScript.cs(37,28): error CS1519: Unexpected symbol `XAsync' in class, struct, or interface member declaration
</code></pre>
<p>これが、5.4は試してないんですけど、5.5だと以下のように。</p>
<pre class="console" title="">
<code>Assets/Scripts/NewBehaviourScript.cs(30,12): error CS1644: Feature `expression bodied members' cannot be used because it is not part of the C# 4.0 language specification
Assets/Scripts/NewBehaviourScript.cs(37,16): error CS1644: Feature `asynchronous functions' cannot be used because it is not part of the C# 4.0 language specification
</code></pre>
<p>5.3曰く「ちょっとその文法わからない」、5.5曰く「その機能はC# 4じゃないからダメ」。
5.5は解釈自体はできていると。</p>
<h2>-langversion:6</h2>
<p>てことで、まあ、オプション変更。</p>
<p>プロジェクトの Assets 直下に <code>mcs.rsp</code> っていうファイルを作り、</p>
<p><img src="/media/1092/smcsrsp.png" alt="Unityに対してC#コンパイラー オプション指定" /></p>
<p>以下の1行を書いて保存。</p>
<p><code>-langversion:6</code></p>
<p>これで、C# 6なコードもビルドが通ります。</p>
<p>ただ、Unityが出力する csproj ファイルに余計な行が入るんで、こいつも消さないと、Visual Studio上でC# 6の機能が使えなくなります。</p>
<p><img src="/media/1093/csprojlangversion.png" alt="余計な1行" /></p>
<p>この行も削除が必要。
いったん手作業削除してるんですが、ちゃんとやるなら<a href="http://unityvs.com/documentation/api/project-file-generation/">Project File Generation</a>でも使ってフックしてやればよさそう。</p>
<p><code>Task</code>クラスが必要なasync/awaitはともかく、ライブラリ依存がほとんどない<a href="http://ufcpp.net/study/csharp/ap_ver6.html">C# 6の機能</a>とかなら問題なく使えると思います。</p>
<h2>async/awaitを使う</h2>
<p>で、<code>Task</code>クラスさえ自前で用意すればasync/awaitも使えるっぽい。
うちは自力でバックポートしたライブラリを持ってるので、それを参照してみたら、あっさり動きました。
ライブラリは↓これ。</p>
<ul>
<li><a href="https://github.com/OrangeCube/MinimumAsyncBridge/">MinimumAsyncBridge</a></li>
</ul>
<p>実際動いてるプロジェクトがこんな感じ↓。</p>
<ul>
<li><a href="https://github.com/ufcpp/Unity20160901">https://github.com/ufcpp/Unity20160901</a></li>
</ul>
<p>まあ、Unity Editor上でしか試してないんで、IL2CPPとか実機で動くかはわからないんですが。</p>
 ]]></description>
				<pubDate>Thu, 01 Sep 2016 08:07:52 +0900</pubDate>
			</item>
			<item>
				<title>タプル</title>
				<link>http://ufcpp.net/blog/2016/8/tuples/</link>
				<description><![CDATA[ <p>思い出したかのように「C# 7思い出話」。</p>
<p>タプルがらみも先週末で一通り書き終わったはずかな。</p>
<ul>
<li><a href="http://ufcpp.net/study/csharp/structured/st_anonymoustype/">名前のない複合型</a></li>
<li><a href="http://ufcpp.net/study/csharp/datatype/tuples/">タプル</a></li>
<li><a href="http://ufcpp.net/study/csharp/datatype/deconstruction/">複合型の分解</a></li>
</ul>
<h2>タプル</h2>
<p>これ自体はおおむね当初予定通りですかね。
そんなに裏話的な面白話もなく。
文法的に変化が大きいんで実装は大変そうでしたが。</p>
<p>しいていうと、他の提案を差し置いてタプルの優先度が高かった的な話ですかね。
タプルは、<a href="https://github.com/dotnet/roslyn/blob/master/docs/features/records.md">レコード型</a>とか、
C# 7のさらに先で入る予定の機能の基礎に使う可能性があって。
依存順的に先にないと行けないという、割かしシンプルな話。</p>
<p>タプルは、<code>(int x, int y)</code>みたいなメンバー名を持った型から、<code>ValueTuple</code>という完全に名前のないデータ構造を生成する機能なわけで、
型に緩い世界と厳しい世界の橋渡しとして期待されます。ロジックを書く上では厳しい型付けを持っている方が楽ですが、View (WPFやUWPのData Bindingみたいな世界)や、Wire Data (通信層でのデータのシリアライズ・デシリアライズ)とかでは緩い型の方が助かったりします。その間をつなぐ基礎に使えそうって意味で、タプルには期待感があります。</p>
<p>そして、レコード型をタプルをベースに作る、あるいは、レコード型からタプルへの変換を用意すれば、型名がある世界とない世界もつなげます。</p>
<p>レコード型をタプルをベースに作るっていうのは、例えば以下のようなコードを書いたとして(これがレコード型って呼ばれる機能)、</p>
<pre class="source" title="レコード型の書き方の例">
<code><span class="reserved">class</span> <span class="type">Point</span>(<span class="reserved">int</span> X, <span class="reserved">int</span> Y);
</code></pre>
<p>以下のようなコードに展開するという案。</p>
<pre class="source" title="上記コードの展開結果の案1: レコード型をタプルを使って作る">
<code><span class="reserved">class</span> <span class="type">Point</span>
{
    (<span class="reserved">int</span> x, <span class="reserved">int</span> y) Value;
    <span class="reserved">public</span> <span class="reserved">int</span> X =&gt; Value.x;
    <span class="reserved">public</span> <span class="reserved">int</span> Y =&gt; Value.y;
}
</code></pre>
<p>レコード型からタプルへの変換を用意というのだと、以下のような感じ。</p>
<pre class="source" title="上記コードの展開結果の案1: タプルへの変換">
<code><span class="reserved">class</span> <span class="type">Point</span>
{
    <span class="reserved">public</span> (<span class="reserved">int</span> x, <span class="reserved">int</span> y) Value =&gt; (X, Y);

    <span class="reserved">public</span> <span class="reserved">int</span> X { <span class="reserved">get</span>; }
    <span class="reserved">public</span> <span class="reserved">int</span> Y { <span class="reserved">get</span>; }
}
</code></pre>
<p>どちらにしろ、依存関係があるなら、依存されている側の方が先に落ち着いていないといけない。</p>
<p>レコード型は、その前身となる <a href="http://blog.xin9le.net/entry/2014/06/16/144115">primary constructor</a>っていう機能提案から考えるとC# 6よりも前(一瞬、C# 6に入れる想定で話が進んでた)、2014年半ば頃からあります。それが、「もっと洗練してレコード型にしてから取り入れたい。そのためにはC# 6では無理」となり、「タプルやパターン マッチングと併せて考えたい。そのためにはC# 7よりも後」となり今に至ると。</p>
<h2>分解</h2>
<p>こちらは逆に、前倒し。
前倒しというか、パターン マッチングがらみの仕様のうち、一部分だけが先行してC# 7に入るわけですが、その一部。</p>
<p>パターン マッチングは結構大きな提案です。All or Nothing、「全部入れるか全部入れない」かとかで入れようとすると、たぶん3年くらい先になります。
こないだ<a href="http://www.buildinsider.net/column/iwanaga-nobuyuki/008">短期リリース サイクル化</a>の話とか書きましたが、後への影響残さないなら、先に少しだけリリースする方が助かります。</p>
<p>元々は、以下のような構文で話が進んでいたんで、それからするとずいぶん、分解専用の構文になりました。多少、そこは、今後、パターン マッチングの全体が入るときに衝突しないのかな？とか思ったりはします(たぶん大丈夫という判断が付いたからC# 7で入ることになったはずですが)。</p>
<pre class="source" title="パターン マッチングの一部としての分解構文">
<code><span class="reserved">let</span> <span class="input">パターン</span> = <span class="input">分解したいもの</span>;
</code></pre> ]]></description>
				<pubDate>Wed, 31 Aug 2016 13:44:40 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 8/27: What’s New in C# 7.0</title>
				<link>http://ufcpp.net/blog/2016/8/rickuproslyn0827/</link>
				<description><![CDATA[ <h2>ブログ: What’s New in C# 7.0</h2>
<p>Roslynリポジトリ内の話じゃないんですけど、Preview 4でのC# 7の動きについて、Madsがブログ書いてました。</p>
<ul>
<li><a href="https://blogs.msdn.microsoft.com/dotnet/2016/08/24/whats-new-in-csharp-7-0/">What’s New in C# 7.0</a></li>
</ul>
<h3>7.0</h3>
<p>そういや、この文章だと「C# 7.0」。
<a href="http://ufcpp.net/blog/2016/6/versionnumber/">昔ちょっとブログ</a>書きましたけど、最近って小数点以下のバージョン付けないんですけど。
C# 7はずっと「7」ばっかりみてたけど、久々に「7.0」表記。
この辺り、最近、C#チーム内でも統一してないなぁ…</p>
<h3>C# 7.0の内容</h3>
<p><a href="https://blogs.msdn.microsoft.com/dotnet/2016/08/24/whats-new-in-csharp-7-0/">このブログの内容</a>的には、
先日僕もブログで書いたのとそんなに差がないんで詳細は省略。</p>
<ul>
<li><a href="http://ufcpp.net/blog/2016/8/vs15p4/">Visual Studio &quot;15&quot; Preview 4</a></li>
</ul>
<p>差分というか、僕が書いた方で漏れてるのは、以下の内容:</p>
<h4>out varのwildcard</h4>
<p>out varと一緒に、<code>*</code>、要するに、受け取る必要のない out 引数を無視するための「wildcard」も入れるかもという話もあるみたい。</p>
<p><code>*</code>は、 元々、パターン マッチング構文の1機能(パターンの1種)です。
で、out varもパターン マッチングと同列で検討されてた機能です。</p>
<p>今、C# 7で、out varだけは先に入れる方向で実装が進んでいるわけですが、どこまで一緒に前倒すかという問題。
out varに対する<code>*</code>はC# 7で入れるかどうかまだ迷ってるっぽいです(C# 7時点で入らないとしても、たぶんパターン マッチングとは同時に入る)。</p>
<h4>More expression bodied members</h4>
<p>今、メソッドとget-onlyなプロパティに限り、式が1つだけの実装に <code>=&gt;</code> を使えるわけですが。
それを、コンストラクター、デストラクター、getとset両方あるプロパティに対しても使えるようにするやつ、C# 7で入りそうらしい。</p>
<p>この機能、完全にコミュニティ主体の実装なんですよね。
<a href="http://ufcpp.net/blog/2016/3/pickuproslyn0318/">3月にブログ</a>書いてますけど、この機能はずっと「需要がある程度あるのはわかるけど、メリット小さめだし後回しになってる」みたいな状態でおいておかれてたものなんですけど、それに対して、「実装したよ」ってプルリクエスト送ってきた人がいて。
C#チームが「そのプルリクを取り込むことにした」って書き込みはしてたんですが、その後音沙汰なしでした。
久々に見たと思ったら、C# 7のタイミングで取り込むことにしたんですねぇ。</p>
<h4>Throw expressions</h4>
<p>これ、結局どうなるんだろ…</p>
<p>「<a href="https://github.com/dotnet/roslyn/blob/master/docs/Language%20Feature%20Status.md">Language Feature Status</a>」からは、むしろ、つい最近「7じゃなくて7の次で」降格したところなんですけど。
どっちが正しいんだか…</p>
<h2>MSDNブログ</h2>
<p>そういや、気が付いたら、MSDNブログから「C#チーム ブログ」「VBチーム ブログ」は消えてるんですよね。
<a href="https://github.com/dotnet/roslyn">Roslynのgithubリポジトリ</a>に一本化して、もうブログは書かないのかと思ってたら。</p>
<p><a href="https://blogs.msdn.microsoft.com/dotnet/">.NET</a>配下でブログ書きますか。</p>
<h2>コメント欄</h2>
<p>で、なんだかんだ言って、ブログはコメントたくさんつきますね…</p>
<p>いくつか、気になったの拾っておきます。</p>
<h3>contract</h3>
<p>「design by contract」については何もないの？とのコメントが。</p>
<p>返信ついてて、「今のタイミングでは何もしない。contractはいまいち煩雑で複雑になりがちだし、そんなに大々的な検討もしてない。contractの用途的に、9割がたはnullチェックに関するものだけど、それは型システム指向で『非null参照型』を次のメジャー リリース向けに検討してる。」</p>
<h3>VB</h3>
<p>VBは？沈みゆく船だからC#に移った方がいい？</p>
<p>に対して、他の人から「頼む、ほんとお願いだからVBの質問しないで。死なせてあげて」とかついてる。</p>
<p>さらにそれに対して、VBのPMの人が「頼む、ほんとお願いだからVBの質問し続けて。フィードバックもらえることがほんとものすごい重要だから」とか返信してるという。</p>
<p>どこの国でも似たような状態ですよねぇ。
VBが死ぬときは、今のVBユーザーが絶滅したときであって、VB使ってない外野がとやかく言うなよっていつも思うんですが。</p>
<h3>wildcard? <code>*</code>なの？nullとかでいいんじゃない？</h3>
<p><code>*</code>とかきもくない？↓みたいな、<code>null</code>使う文法の方がよくない？とか言ってる人が。</p>
<pre class="source" title="">
<code>p.GetCoordinates(<span class="reserved">out</span> <span class="reserved">int</span> x, <span class="reserved">null</span>); <span class="comment">// Ignore return</span>
p.GetCoordinates(<span class="reserved">out</span> <span class="reserved">int</span> x, <span class="reserved">out</span> <span class="reserved">null</span>); <span class="comment">// Alternative ignore return</span>
</code></pre>
<p>何この、見た印象ぬるぽ起こしそうな構文…
値を受け取るべき場所に<code>null</code>書くとかちょっと…</p>
<p>そして飛び火して、本題からそれて「<code>null</code>はこの世から消えるべき」主張をこのコメント内でし始める人まで現れる始末。</p>
<h3>タプルとout var両方やるの？</h3>
<p>タプルもout varも、多値戻り値を返すために使う(ことが多い)構文なわけですが、
なので当然「どっち使えばいいの？なんで両方やってるの？」という質問も。</p>
<p>それに対する答え:</p>
<ul>
<li>だいたいの場合においてはタプルを使うといいよ</li>
<li>
ただし、以下の場合においてout引数が残る余地がある
<ul>
<li>複数のオーバーロードを用意したい場合(タプルというか、戻り値だとオーバーロードできない)</li>
<li>Tryパターンなんかだと、単一のboolを返す意味がある。ifステートメントの条件式とかで使えるように</li>
</ul>
</li>
</ul>
<p>ちなみに、別のコメントに対する返答で、今このタイミングでout引数に対する拡張を入れる意味について「パターン マッチングとout varには相乗効果がある」との回答あり(要するに、パターン マッチングのついで。パターン マッチングをやるならこちらも)。</p>
<h3>C#がどんどん汚染されてない？</h3>
<p>だいたいの人は「便利！待ち遠しい！」って言ってる中、まあ、毎度必ずいるわけですが「ちょっとトリッキーすぎない？泥沼にはまりそうで嫌だわ」って言い出す人が。
C# 7に限らずこれまでも、C#に限らずありとあらゆる言語でこういう意見絶対出てくるわけですが。</p>
<p>それに対する Mads の回答:</p>
<p>あなたは言語の進化のある種の核心をついてる。我々は機能を足せるけど、絶対に消せない。C#の進化においてもこのことが重くのしかかってる。
Anders (元祖、C#/.NETの父)の発言は有名だけど、「あらゆる機能はマイナス100ポイントから始めろ」と言ってる。
全ての機能について、我々は誰が喜ぶか、今現在だけでなく、今から10年後のことも考えるようにしている。
今現在有用かどうかだけでなく、永久に言語の一部分を占め続けるということを考えるようにしている。</p>
<p>我々はだいたいは正しいが、常に正しいわけではない。わかるだろうが、未来というのは予測が最も難しいものの1つだ。
このことは、言語設計のアプローチに対する異なる側面をもたらす。
我々は大胆でなければならない。
我々は遠い未来への責任に追い詰められてはいけない。
なぜなら、さもなくばその未来も得られないから。
C#は今この時「最高のプログラミング言語」の1つでなければならない。
さもなくば、明日にはそうではなくなってしまう。</p>
<p>なので、我々は少々アグレッシブに機能を追加する。
開発者にとって最も価値ある機能を追加しようと試みる。
さらに、その機能を追加するにあたって、言語の複雑性が増すという観点から不利益が最小になるよう試みる。
たとえばそう、パターン マッチングは新しい機能になるわけだが、しかし、既存の言語要素、例えば<code>is</code>や<code>switch</code>、既存の型の中で動くものだ。
それは(うまくいけば)我々の過去とよく統合されている。
同時に、いくつかのパターンを、将来の発展の余地を残しつつ、今現在の「税負担」にならないように導入している。
それは、我々のもっともらしくあり得そうな未来とよく統合されている。</p>
<p>信じられないかもしれないが、我々が何パターンかあり得そうな未来について、取り組む余地を確実に残せるよう、投機的な設計にどれだけ時間をついやしていることか。
これは、我々が、新機能を追加するにあたって、この言語を長期的にわたって健康で生存力がある状態に保てるよう試みていることの一部分だ。</p>
<p>以上で、我々がC#の長期的な進化についてどのくらい考えているか、その姿を伝える助けになれば幸いだ。</p>
 ]]></description>
				<pubDate>Sat, 27 Aug 2016 08:16:06 +0900</pubDate>
			</item>
			<item>
				<title>Visual Studio &quot;15&quot; Preview 4</title>
				<link>http://ufcpp.net/blog/2016/8/vs15p4/</link>
				<description><![CDATA[ <p>Preview 4が出たみたいですね。</p>
<ul>
<li><a href="https://blogs.msdn.microsoft.com/visualstudio/2016/08/22/visual-studio-15-preview-4/">Visual Studio “15” Preview 4</a></li>
</ul>
<p>最近、まあ、Previeｗ の新しいのが出ても、C# vNext の進捗具合だけしか取り上げてなかったりするんですが。
今回も主にその話題で。</p>
<h2>インストーラー</h2>
<p>1点だけ。新しいインストーラーがだいぶちゃんとしたものになってますね。
細かい機能を選択して入れるんじゃなくて、「UWP開発したい人はこのオプションを選択してください」みたいな感じのUIに(その結果、それに必要な機能に一通りチェックが入る)。</p>
<p>Visual Studioってものすごいインストールに時間が掛かるので有名ですが、結構な割合、エミュレーターとか仮想マシンのインストールに取られてる時間だったりします。
要するに、UWPとかモバイル開発が不要なら、ここ外すだけでかなりインストール早かったり。</p>
<h2>C# 7 進捗</h2>
<p>C# 7で入るものの予定は以下のページ参照。</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/blob/master/docs/Language%20Feature%20Status.md">Language Feature Status</a></li>
</ul>
<p>これを踏まえて、Preview 4でのC# 7実装の状況まとめ:</p>
<div>
<script src="https://gist.github.com/ufcpp/637759fdd02409d9f9795e5b00ae0ee2.js"></script>
</div>
<p><code>ValueTask</code>は、ちょっと前に中の人が「Preview 4に入る予定のブランチにマージされたぜ」ってtwitterでつぶやいてましたが、
QA通らなかったのか、リバート食らってました。</p>
<p>他は、たぶんあと細かい調整だけですかね。
変数/ローカル関数のスコープとか、クエリ式中でも分解構文使えるようにするとか。</p>
<p>ちなみに、タプルを使うためには<code>System.ValueTuple</code>が、<code>ValueTask</code>を使うためには<code>System.Threading.Tasks.Extensions</code>が必要になりますが、
どっちももうNuGet.orgに並んでいます。</p>
<ul>
<li><a href="https://www.nuget.org/packages/System.ValueTuple/">System.ValueTuple</a> (prerelease version のみ)</li>
<li><a href="System.Threading.Tasks.Extensions">System.Threading.Tasks.Extensions</a></li>
</ul>
 ]]></description>
				<pubDate>Tue, 23 Aug 2016 03:19:11 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 8/16 Close祭り</title>
				<link>http://ufcpp.net/blog/2016/8/pickuproslyn0816/</link>
				<description><![CDATA[ <p>実作業が一段落つくと始まるissue整理。</p>
<p>すごい数一気にコメントついたりCloseされたり。以下、そのまとめ。</p>
<h2>やらない</h2>
<p>1行目: どういうものか</p>
<p>2行目: やらない理由</p>
<h3><a href="https://github.com/dotnet/roslyn/issues/126">Proposal: Fixed-size buffers enhancements #126</a></h3>
<p>構造体の内部に固定長配列を持てるようにしたい。</p>
<p>CLRのレベルで対応してもらいたい。C#コンパイラーでのコード生成はメリットの割に複雑すぎる。</p>
<h3><a href="https://github.com/dotnet/roslyn/issues/128">infoof / propertyof / methodof (and reflection objects in attributes?) #128</a></h3>
<p><code>infoof</code>演算子(info-of、<code>typeof</code>のノリでMemberInfoを取得する)が欲しい。</p>
<p>リフレクションを言語に組み込みたくはない。<code>nameof</code>でもかなりのシナリオをカバーできる。</p>
<h3><a href="https://github.com/dotnet/roslyn/issues/132">[Proposal] try-catch expressions #132</a></h3>
<p>try-catch を式にしたい。</p>
<p>このページで提案されている構文だと問題がある。再提案があれば、取り組む価値があるかはまだ検討の必要があるかもしれないが、現状そこまでには思っていない。</p>
<h3><a href="https://github.com/dotnet/roslyn/issues/124">Language support for the decorator design pattern #124</a></h3>
<p>デコレーター(<a href="http://qiita.com/mtb_beta/items/d257519b018b8cd0cc2e">Pythonのデコレーター</a>とか<a href="https://kotlinlang.org/docs/reference/delegation.html">Kotlinのclass delgation</a>と同種の機能)が欲しい。</p>
<p>いくらかのメリットがあるのはわかるし、過去に似た機能の提案も見てきた。でも、コンパイラーが暗黙的にコード生成するような機能には心配事が多々ある。
今なら、<a href="https://github.com/dotnet/roslyn/issues/5561">ソース ジェネレーター</a> (たぶんC# 8)で解決できるかもしれない。</p>
<h3><a href="https://github.com/dotnet/roslyn/issues/58">Strongly-typed type aliases #58</a></h3>
<p>同じ型なんだけど、互いに暗黙的型変換はできないエイリアスを作りたい。例えば、<code>EmailAddress</code>型(中身は<code>string</code>)と<code>string</code>を区別したい。</p>
<p><a href="https://github.com/dotnet/roslyn/issues/5561">ソース ジェネレーター</a> (たぶんC# 8)を使って構造体をコード生成して、同様のことを実現してほしい。ソース ジェネレーターで苦痛は減るはず。</p>
<h3><a href="https://github.com/dotnet/roslyn/issues/123">Auto properties with setter blocks #123</a></h3>
<p>プロパティで、<code>get</code>のみ自動実装で、<code>set</code>は手動実装できるようにしてほしい。</p>
<p>良いディスカッションはあった。ディスカッションの中で出てきた副次的な案は別のissueページに移った。
でも、このページで提案されている元々の提案はやらない。バッキング フィールドを参照するような機能は得られるものに対して労力が過剰。</p>
<h3><a href="https://github.com/dotnet/roslyn/issues/144">Implement Units of Measure or a broader class of similar contracts #144</a></h3>
<p>F# の<a href="http://qiita.com/adacola/items/b65752b678e81bc8e354">Units of Measure</a>がC#にもほしい。</p>
<p>非常にクールな機能だと思うものの、同種のものをC#に追加するのはメリットの割にコストが大きい。</p>
<p>訳注: たぶん、上記のStrolngly-typed typle aliasesで十分な利用シナリオも多いと思う。</p>
<h3><a href="https://github.com/dotnet/roslyn/issues/136">[Proposal] Better handling of multiple comparisons with the same variable (<code>a &gt; min &amp;&amp; a &lt; max</code>) #136</a></h3>
<p><code>min &lt; x &lt; max</code> みたいな、数学でよく見る多項比較できるようにしてほしい。</p>
<p>C# ではすでに <code>a &lt; b &lt; c</code> が <code>(a &lt; b) &lt; c</code> の意味で有効な式になっているし、難しい。 
<code>e in (0 ... n)</code> みたいな文法も、<code>e &lt; n</code> なのか <code>e &lt;= n</code> なのか混乱の元。</p>
<h3><a href="https://github.com/dotnet/roslyn/issues/171">Allow type parameters to be declared co/contra variant on classes. #171</a></h3>
<p>クラスの型引数にも共変性・反変性を認めてほしい。</p>
<p>CLRレベルでの対応が必須。</p>
<h3><a href="https://github.com/dotnet/roslyn/issues/176">Proposal: Virtual arguments in methods #176</a></h3>
<p>引数の実行時の型でメソッドのオーバーロードを呼び分けれるようにしてほしい(いわゆる多重ディスパッチ)。</p>
<p>ちゃんとやるのであればCLRレベルでの対応が必須。
型スイッチ(C# 7で入る)があれば書くのが多少楽になるけども、多重ディスパッチは型スイッチと比べてかなり複雑。</p>
<h3><a href="https://github.com/dotnet/roslyn/issues/85">Feature Request: Lighter syntax for doc comments #85</a></h3>
<p>docコメントがXMLなの重たい。JavaDoc/JSDocみたいな文法ほしい。</p>
<p>現状に不服があるのはわかる。でも、新旧文法の混在・競合みたいなのは嫌だし、直近での検討はしない。</p>
<h2>重複削除・もうやってる</h2>
<p>1行目: どういうものか</p>
<p>2行目: 何と重複してるか</p>
<h3><a href="https://github.com/dotnet/roslyn/issues/49">Allow local variables to be static and/or readonly (deeper scoping) #49</a></h3>
<p>ローカル変数に<code>static</code>(スコープが関数内に限られた静的フィールドを作る)とか<code>readonly</code>(書き換え不能)とか付けれるようにしてほしい。</p>
<p>以下の2つに分割できる。</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/issues/115">Proposal: 'readonly' for Locals and Parameters #115</a></li>
<li><a href="https://github.com/dotnet/roslyn/issues/10552">Please allow to define static local variables in functions, like C/C++ #10552</a></li>
</ul>
<h3><a href="https://github.com/dotnet/roslyn/issues/24">Allow C# to use anonymous iterators. #24</a></h3>
<p>匿名関数でイテレーターを作らせてほしい。</p>
<p>C# 7で入るローカル関数で同じことができる。</p>
<h3><a href="https://github.com/dotnet/roslyn/issues/31">Please provide the C# Specification in PDF instead of DOCX #31</a></h3>
<p>C#の仕様書をPDF提供してほしい。</p>
<p>長期作業として、マイクロソフトC#仕様書とECMA標準規格書の統合作業をしている。ECMAの方のはPDFで提供されてる。</p>
<p>訳注: 現体制になってから全然仕様書が表に出てこないんだけども… Long termってどのくらいLongなんだろう…</p>
<h3><a href="https://github.com/dotnet/roslyn/issues/20">Lambdas omitting parameters #20</a></h3>
<p>ラムダ式の引数のうち、要らないものは無視できる構文が欲しい。<code>someFunction((_, foo) =&gt; fooだけ使う);</code> みたいなの。</p>
<p>パターン マッチング(たぶんC# 8)と一緒にやる。</p>
<h3><a href="https://github.com/dotnet/roslyn/issues/112">Extension properties for classes #112</a></h3>
<p>メソッドだけじゃなくて、プロパティも拡張で作れるようにしてほしい。</p>
<p>以下の提案の一部分になる。</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/issues/11159">https://github.com/dotnet/roslyn/issues/11159</a></li>
</ul>
<h3><a href="https://github.com/dotnet/roslyn/issues/59">UnreachableAfterAttribute and unreachable code detecting #59</a></h3>
<p>常に例外を出すことが分かっていて、呼び出しよりも後ろのコードには絶対に到達しないことが保証できるようなメソッドを作りたい。そのために<code>UnreachableAfter</code>みたいな属性を作ってほしい。</p>
<p><a href="https://github.com/dotnet/roslyn/issues/1226"><code>never</code>型</a>ってのを検討中。</p>
<h2>引き続き検討</h2>
<p>1行目: どういうものか</p>
<p>2行目: どう取り組んでいるか</p>
<h3><a href="https://github.com/dotnet/roslyn/issues/133">[Proposal] Object initializers for factory methods #133</a></h3>
<p><code>new T { X = ... }</code> みたいなのを、<code>new</code>演算子ではなく、ファクトリー メソッドを使った場合でも使えるようにしてほしい。<code>T.Create() { X = ... }</code> みたいな。</p>
<p><a href="https://github.com/dotnet/roslyn/issues/5172"><code>with</code>式</a> (たぶんC# 8になる)と合わせて考えたい。</p>
<h3><a href="https://github.com/dotnet/roslyn/issues/35">Do not require type specification for constructors when the type is known #35</a></h3>
<p><code>var</code> (右辺値から変数の型を推論)の逆で、<code>T x = new();</code>みたいに、左辺値から<code>new</code>の型推論をしたい。</p>
<p>分解(deconstruction)の対となる構文として魅力的になりそう。</p>
<p>訳注: 分解の方が<code>var (x, y) = tuple;</code>みたいに型推論が効くんだから、構築(<code>new</code>)の方にも型推論が効いても良さげ。</p>
<h3><a href="https://github.com/dotnet/roslyn/issues/114">IAsyncDisposable, using statements, and async/await #114</a></h3>
<p>非同期Disposeがしたい。<code>using</code>ステートメントで、<code>IAsyncDisposable</code>的な非同期版のインターフェイスを使えるようにしてほしい。</p>
<p><a href="https://github.com/ljw1004">Lucian</a>にタスク割り当て。</p>
<p>訳注: たぶん、<a href="https://github.com/dotnet/roslyn/issues/261">非同期シーケンス</a>と一緒に検討。Lucian は<a href="https://github.com/dotnet/roslyn/issues/7169">Task-like</a>とか含め、非同期処理がらみの新仕様に取り組んでる人。</p>
<h3><a href="https://github.com/dotnet/roslyn/issues/100">Extend LINQ syntax #100</a></h3>
<p>クエリ式の後に<code>ToList()</code>とか<code>Single()</code>とかの、シーケンス自体に対する操作を呼ぶのが、今の構文だとだるい。</p>
<p>バックログに入れておく。<code>from x in items where x.foo, select x.bar do Single()</code> みたいな構文がいいかも。</p>
<h3><a href="https://github.com/dotnet/roslyn/issues/140">[Proposal] (Minor) Method groups for constructors #140</a></h3>
<p>コンストラクターをメソッド グループ(デリゲートにメソッドを渡すために、<code>Action a = Method</code>とか書くやつ)として認めてほしい。</p>
<p>よくある要求だし、よいアイディア。</p>
 ]]></description>
				<pubDate>Tue, 16 Aug 2016 03:33:52 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 8/10</title>
				<link>http://ufcpp.net/blog/2016/8/pickuproslyn0810/</link>
				<description><![CDATA[ <p>7月のデザインノートが2件ほど。</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/issues/13022">C# Language Design Notes for Jul 12, 2016</a></li>
<li><a href="https://github.com/dotnet/roslyn/issues/13015">C# Language Design Notes for Jul 13, 2016</a></li>
</ul>
<p>これ関連の作業がひと段落したところでまとめて清書して表に出したって感じですかねぇ。
この辺りの話、かなりの割合がもう実装されててマージされてたりします。</p>
<p>先週、dots.をお借りしてこんなイベントやってたわけですが</p>
<ul>
<li><a href="http://eventdots.jp/event/594178">roslyn (C# 7) もくもく会</a></li>
</ul>
<p>最新のmasterブランチの取ってきてビルドして実行してみると、大体この仕様通りになってる感じ。</p>
<p>さて、どんな感じの仕様かというと…</p>
<h2>タプル型のメンバー名は省略・名前付きの混在可能</h2>
<p>こんなコードでOKですって。</p>
<pre class="source" title="">
<code><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">var</span> t = (<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">1</span>, y: <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">2</span>); <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">// infers (int, int y)</span>
(<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">int</span> x, <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">int</span>) t = (<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">1</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">2</span>);
</code></pre>
<p>ちなみに、名前を省略したところは、<code>ValueTuple</code>がたの本来のメンバーである <code>x.Item1</code> とかの名前で参照できます。</p>
<h2>ITuple</h2>
<p>タプル型みたいな「単に複数のデータを寄せ集めただけ」な型に対して、インデックスでメンバー参照したくなることがあります。
<code>ValueTuple</code>型はそのために、以下のようなインターフェイスを実装すべきじゃないかという話に。</p>
<pre class="source" title="">
<code><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">interface</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">ITuple</span>
{
    <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">int</span> Size;
    object this[int i] { <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">get</span>; }
}
</code></pre>
<p>タプル型の分解に使いたいそうで。</p>
<p><code>ValueTuple</code>型はこれを実装すべきだとは思うものの、名前にはまだ議論の余地あり。
インターフェイス名も<code>IDeconstructable</code>とかがいいかもしれないし。
要素数のプロパティも<code>Length</code>とか<code>Count</code>とかもあり得るし。</p>
<h2>var型がある場合。</h2>
<p>C#のvarは、文脈キーワード(特定の文脈でだけキーワード扱いされる)です。<code>var</code>って名前のクラスがあると、クラス名として認識される。</p>
<p>で、タプル型の分解構文で以下のような書き方を認めることになるわけですが、</p>
<pre class="source" title="">
<code><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">var</span> (x, y) = e;
</code></pre>
<p>ここで、<code>var</code>クラスがあった場合どうなるべきか。</p>
<pre class="source" title="">
<code><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">class</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">var</span> {}
<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">var</span> (x, y) = e;
</code></pre>
<p>ちなみに、世の中には、わざわざこういう<code>var</code>クラスを用意しておくことで、型推論のvarを使わせない(コンパイル エラーにさせる)トリッキーな運用をしている人もいるそうで。C#チーム的には「(その良し悪しは置いといて)そういう運用も認めるべきでしょう」という感じ。
そういう背景もあって、タプル型の分解におけるvarでも、<code>var</code>クラスがあったらコンパイル エラーにするみたい。</p>
<h2>var メソッド</h2>
<p>じゃあ、メソッドの場合はどうか。分解代入の構文、メソッド呼び出しに似ているので、以下のような書き方ができてしまいます。</p>
<pre class="source" title="">
<code><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">ref int</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">var</span>(<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">int</span> x, <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">int</span> y);
<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">var</span>(x, y) = e; <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">// deconstruction or call?</span>
</code></pre>
<p>参照戻り値なメソッドへの代入(参照先への代入)か、分解代入か、どちらにするべきか。</p>
<p>常に分解代入の方を選ぶそうです。メソッドの方を呼びたい場合は <code>@var</code> って書けばできます。</p>
<h2>partialクラスでのインターフェイス</h2>
<p>partialクラスの場合、複数の宣言で、同じインターフェイスを継承できたりします。
ここで、じゃあ、メンバー名違いの同じ型のインターフェイスを継承してしまった場合はどうするべきか。</p>
<pre class="source" title="">
<code><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">partial</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">class</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">C</span> : <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">IEnumerable</span>&lt;(<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">string</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">name</span>, <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">int</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">age</span>)&gt; { ... }
<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">partial</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">class</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">C</span> : <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">IEnumerable</span>&lt;(<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">string</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">fullname</span>, <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">int</span>)&gt; { ... } 
</code></pre>
<p>タプル型は、内部的には全部<code>ValueTuple</code>構造体に変換されます。
名前は属性に残るだけ。
で、じゃあ、上記の名前違いのインターフェイスは別の型なのか同じ型なのかよくわからず。
紛らわしいのでコンパイル エラーにすべきでしょう。
逆に、メンバー名も含めて全一致している場合だけは、複数のpartial宣言に書いても大丈夫。</p>
<p>もう少し面倒なケースは、多重継承(インターフェイスであればC#でも多重継承が可能)。
以下の場合はどうすべきか。</p>
<pre class="source" title="">
<code><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">interface</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">I1</span> : <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">IEnumerable</span>&lt;(<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">int</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">a</span>, <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">int</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">b</span>)&gt; {}
<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">interface</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">I2</span> : <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">IEnumerable</span>&lt;(<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">int</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">c</span>, <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">int</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">d</span>)&gt; {}
<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">interface</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">I3</span> : <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">I1</span>, <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">I2</span> {} <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">// what comes out when you enumerate?</span>
<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">class</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">C</span> : <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">I1</span> { <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">public</span> IEnumerator&lt;(<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">int</span> e, <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">int</span> f)&gt; <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">GetEnumerator</span>() {} } <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">// what comes out when you enumerate?</span>
</code></pre>
<p>現状、これもコンパイル エラーにする案で進めてるみたい。
できてそこまで大きなメリットもなさそうなので、複雑化させない方向に倒すという感じ。
もし、将来的にこれを認めたくなるような重要な利用シナリオが見つかったりした場合、それはその時に考える。</p>
<h2>タプル リテラルの分解</h2>
<p>null (全ての参照型に代入可能)とか、1 (<code>int</code>、<code>short</code>, <code>byte</code> 辺りのどれか不明瞭)とか、リテラルの場合、型があいまいなものがあります。
その分解はちゃんと働くべきか。</p>
<pre class="source" title="">
<code>(<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">string</span> x, <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">byte</span> y, <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">var</span> z) = (<span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">null</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">1</span>, <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">2</span>);
</code></pre>
<p>できるべきだろうとのこと。</p>
<p>各要素ごとに並べて書いた時と同じ挙動になるべき。上記コードであれば、まあ、↓みたいなのと同じ解釈をすべき。</p>
<pre class="source" title="">
<code><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">string</span> x = <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">null</span>;
<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">byte</span> y = <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">1</span>;
<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">var</span> z) = <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">2</span>;
</code></pre>
<p>ただし、これが逐次実行されるわけじゃなくて、一斉に代入が起きる。つまり、swapに使っても差し支えないようなにはなってる。</p>
<pre class="source" title="">
<code>(x, y) = (y, x); <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">// swap!</span>
</code></pre>
<h2>タプル型の中のvar</h2>
<p>「タプル型の変数宣言」と「分解代入」は非常に似た構文になるわけですが。</p>
<pre class="source" title="">
<code>(<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">int</span> x, <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">int</span> y) = GetTuple(); <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">// 分解</span>
(<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">int</span> x, <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">int</span> y) t = GetTuple(): <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">// タプル型の変数宣言</span>
</code></pre>
<p>じゃあ、以下の構文(これも似て非なるもの)の場合はどうなるべきか。</p>
<pre class="source" title="">
<code>(<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">var</span> x, <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">var</span> y) = GetTuple(); <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">// これは分解代入時の型推論</span>
(<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">var</span> x, <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">var</span> y) t = GetTuple(): <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">// varなタプル型。これは認めるべき？</span>
</code></pre>
<p>で、結論的には、この後者は認めないとのこと。</p>
<h2>分解代入の戻り値の型は void？</h2>
<p>C#では、代入は式です。どこにでも書けます…</p>
<pre class="source" title="">
<code><span class="reserved">var</span> x = 1;
<span class="reserved">var</span> y = (x = 2) * x;
</code></pre>
<p>まあ、ろくでもないんですが。副作用を伴う式とか割かし害悪。C言語を参考にしすぎたところですね。とはいえ、今更変更できません。</p>
<p>例えばの話、forステートメントの中には式を書くことになっているので、以下のようなコードを書きたければ、タプルの分解代入も式でないといけないそうです。</p>
<pre class="source" title="">
<code><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">for</span> (... ;; (current, next) = (next, next.Next)) { ... }
</code></pre>
<p>とはいえ、実のところ、「戻り値がvoidの式」という扱いにすれば、forステートメントの中で使えつつ、さっきのろくでもない<code>y = (x = 2) * x</code> みたいなコードをなくせたりします。</p>
<p>ということで、voidであるべき？</p>
<p>まあ、これも、既存の代入式との一貫性がなくなるので、voidではなく、タプル型を返すべきだと思ってるみたいです。
C# 7では実装しなさそうだけど、後々は、分解代入の結果を、再度タプル構築して戻り値に返すべきだと思っているとのこと。</p>
<h3>参考までに: Swift</h3>
<p>ちなみに、Swiftはほんとに、代入は戻り値がvoidの式みたいです。
<code>y = (x = 2) * x</code> なんていうクソコードは認めません。</p>
<p>その割にインクリメント・デクリメントがあった <code>y = ++x * x</code> とか書けたわけですが。
そりゃ、forステートメントもインクリメントもなくしたくもなります(Swift 3で破壊的変更してまでなくす予定)。</p>
<h2>分解を変換として、変換を分解として</h2>
<p>分解代入と型変換はある程度似た構文です。分解は、タプル型への変換的な雰囲気があります。似てるのあれば、いっそある程度統一性を持たせるべき？</p>
<p>まあ、そうしない方がよさそう。分解(コンパイル結果的には<code>Deconstruct</code>メソッドの呼び出し)は型変換的に扱われるべきじゃない。</p>
<h2>匿名型</h2>
<p>匿名型(<code>{ X = 1, Y = &quot;a&quot; }</code> みたいなやつ)は<code>Deconstruct</code>メソッドや<code>ITuple</code>インターフェイス実装を持つべき？</p>
<p>そうでもなさそう。実装しても、今のところ有用な利用シナリオが思い当たらないとのこと。
欲しくなる場面もなくはないけど、そういう場面では大体タプル型を使えば解決しそう。</p>
<h2>分解代入時のワイルドカード</h2>
<p>ワイルドカードってのは、要するに、要らない部分を読み飛ばす機能。</p>
<pre class="source" title="">
<code>(<span class="reserved">var</span> x, <span class="reserved">var</span> y, *) = (1, 2, 3);
</code></pre>
<p>こういうコードで、3を読み飛ばすために使いもしないダミー変数を用意する必要はありません。</p>
<p>C#的に、こういう機能を入れるべきだろうとは思ってるみたい。
ただし、たぶん、C# 8になる(7には入らない。パターン マッチングと同時期に入る予定)。</p>
<p>あと、ワイルドカードのために使う記号はたぶん <code>*</code>。
関数型言語の類だと <code>_</code> を使うことが多いんですが、C#では <code>_</code> が有効な識別子になっちゃうので。
既存コードの意味を変えてまではこの記号は使わないみたい(コード解析をきっちりやれば不可能ではないけど、そうまでするかという話)。</p>
<h2>double型に対するswitch</h2>
<p>パターン マッチングが入った暁には、<code>double</code>型の変数もswitchに使えるわけですが。
ここで問題になるのは、<code>double</code>型の等値判定。</p>
<p>NaN(Not a Number)の扱いどうするの？とか、実は<code>==</code>と<code>Equals</code>でNaNとの比較結果が違ったりするけどどうする？とか。</p>
<p><code>==</code>と<code>Equals</code>の違いというと、<code>int</code>の1と<code>double</code>の1.0が等値判定とかも。前者はtrueになるけど、後者はfalse。</p>
<p><code>Equals</code>の側を使いそう。</p>
 ]]></description>
				<pubDate>Tue, 09 Aug 2016 15:37:28 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 8/6</title>
				<link>http://ufcpp.net/blog/2016/8/pickuproslyn0806/</link>
				<description><![CDATA[ <h2>Source Generatorが間に合わなかった理由</h2>
<p><a href="http://ufcpp.net/blog/2016/8/pickuproslyn0805/">昨日のブログ</a>にある通り、C# 7に入る機能リストが更新されて、入るもの・入らないものに変化があったわけですが。</p>
<p>それと関連して:</p>
<p><a href="https://github.com/dotnet/roslyn/issues/12630#issuecomment-237959967">https://github.com/dotnet/roslyn/issues/12630#issuecomment-237959967</a></p>
<p>やっぱり、Source Generatorが外れたのがショックだっていう人が現れて、それに対してC#チームの人が釈明してたりします。</p>
<p>まあ、大体<a href="http://ufcpp.net/blog/2016/8/pickuproslyn0805/">昨日書いたことの通り</a>ですね。
IDE側の対応が大変で今回は無理とのこと。</p>
<p>Source Generatorって物自体が、IDE側にとっては結構大きな課題でして。例えば、コード生成によってプロパティなどのメンバーが増えたりするわけですが、その生成されるメンバーをIntelliSenseに出したりしようとすると、文字入力のたびにSource Generatorが走り、構文解析しなおすのかという話になります。IntelliSenseなんかは特にパフォーマンスにシビア（ここがもっさりしているとIDEのユーザーのストレスが非常に大きい）なので、Source Generatorが悩ましい存在になります。</p>
<p>もちろん、間に合ってるC#言語機能(replace/original)だけでも先に入れれないかなんてことも言われています。
けども、今早まって入れても、IDE側も対応できるようになった頃にはもっといいアイディアが出るかもしれない。より良いものがもし入ってしまったら、早まって入れたreplace/original構文が無駄・邪魔になってしまう。そういう状態にはしたくない。という話も。</p>
<p>ってことで、Source Generatorはもう少し成熟を待たないといけないということになります。</p>
<h2>Sprint Summary</h2>
<p>最近結構、「C#チームの中の様子が見えない。クローズだ。Roslynプロジェクトはオープンソースなんじゃなくて、オープンダンプ（クローズに作ったものをオープンにコピーして出してるだけ）だ」的なことを言い続けてるtroll（荒らし認定される勢いでしつこい人）がいらっしゃったり。</p>
<p>まあ、Roslynプロジェクトは確かに3000件ものIssueがオープンなまま整理されてなったりしますし、C#チーム内で起きたことも定期的には出てこない（ふと思い出したかのように出てくる）んで、あんまり擁護もできないんですが。</p>
<p>ということで、C#チームの人が重い腰をあげて「スプリントごとの作業概要」を公開。</p>
<p><a href="https://github.com/dotnet/roslyn/issues/12974">Sprint 104 Summary #12974</a></p>
<p>まあ確かに、これくらいはちゃんと定期的に出そうよ…</p>
 ]]></description>
				<pubDate>Sat, 06 Aug 2016 08:38:12 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 8/5</title>
				<link>http://ufcpp.net/blog/2016/8/pickuproslyn0805/</link>
				<description><![CDATA[ <h2>Feature Status: Finishing</h2>
<p>C# 7のステータスがいろいろ更新されたみたいですね。</p>
<ul>
<li><a href="http://blog.xin9le.net/entry/2016/08/05/010144">Roslyn の開発進捗が更新されました</a></li>
</ul>
<p>C# 7に入るもの、ほぼ確定したのかなぁ。
C# 7/VB 15には状況が「Finishing(最終作業中)」のものばっかり残して、他は+1(その次)行き。</p>
<p>この感じは、次に出るであろうVS &quot;15&quot; Preview 4が最後のプレビュー版ですかね。</p>
<h3>最終作業</h3>
<p>最終作業中ってのは、まあ、基本機能は実装済みで、後は実装してみて初めて分かった問題とかバグの修正、みたいな感覚ですかね。
僕が把握してる範囲だと、以下のような作業はしているはず。</p>
<ul>
<li>
<a href="https://github.com/dotnet/roslyn/issues/347">Tuples</a>
<ul>
<li><a href="https://github.com/dotnet/roslyn/issues/12897">式ツリーの中にタプルを書いた時の挙動が怪しい</a>みたいで、修正作業がたくさん</li>
<li><code>var p = (x, y) = tuple;</code> みたいな、分解代入(<code>tuple</code>を<code>x</code>, <code>y</code>にばらす)をさらに別の変数<code>p</code>に代入するの、<a href="https://github.com/dotnet/roslyn/issues/12635">認める予定</a>だけど今はエラーになる</li>
</ul>
</li>
<li>
<a href="https://github.com/dotnet/roslyn/blob/master/docs/features/local-functions.md">Local Functions</a>
<ul>
<li><a href="https://github.com/dotnet/roslyn/issues/10391">「確実に初期化されているか」検証のルールを変えたいとのこと</a></li>
<li>
ローカル関数でキャプチャしたローカル変数は、ローカル関数を初めて呼び出すまでに初期化して入ればいいことにしたいみたい
<ul>
<li>今は、ローカル関数の宣言よりも前で初期化が必要</li>
</ul>
</li>
</ul>
</li>
<li>
<a href="https://github.com/dotnet/roslyn/blob/features/outvar/docs/features/outvar.md">Out Var</a>と<a href="https://github.com/dotnet/roslyn/blob/master/docs/features/patterns.md">Types Switch</a>で宣言する変数のスコープ
<ul>
<li>
後述。スコープを変えるみたい
<ul>
<li>変えるというか、今まで未決定だったから過剰に厳しくしてたのを、ようやくちゃんと決めたっぽい</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>まあほんとにこういう細かい作業をする段階という感じです。</p>
<h3>見送られた方</h3>
<p><a href="http://blog.xin9le.net/entry/2016/08/05/010144">じんぐるさんも書いてますけど</a>、元々C# 7/VB 15の欄にいたのに、+1送りになったのもありまして。</p>
<p>まあ、動きがなかったのでうすうす感づいていたものの。以下の3つ。</p>
<ul>
<li>Async Main</li>
<li>Source Generation</li>
<li>Throw Expressions</li>
</ul>
<h4>Async Main</h4>
<p>プログラムのエントリー ポイントとして<code>Task MainAsync(string[] args)</code>や<code>Task&lt;int&gt; MainAsync(string[] args)</code>を認めてほしいという話。</p>
<p>これ、最大の問題は同期コンテキストをどうするかなんですよねぇ。4年近く前にブログに書いたことあるんですけど、GUI (WPFでもUWPでもWinFormsでも)では問題ないのにコンソール アプリで実行すると競合起こす場合がありまして。</p>
<ul>
<li>「<a href="https://ufcpp.wordpress.com/2012/11/12/asyncawait%E3%81%A8%E5%90%8C%E6%99%82%E5%AE%9F%E8%A1%8C%E5%88%B6%E5%BE%A1/">async/awaitと同時実行制御</a>」の「コンソール アプリ」の辺り</li>
</ul>
<p>これに関する解決案みたいな話が全く見かけなかったんで、今はまだ取り組んでないんだろうなぁと。</p>
<p>ちなみにもう1つの問題として、今、↓みたいな書き方してるコードが結構たくさんあるはずで、これの互換性を崩しかねないからって話もあります。</p>
<pre class="source" title="MainからMainAsyncを呼ぶコード">
<code><span class="reserved">class</span> <span class="type">Program</span>
{
    <span class="reserved">static</span> <span class="reserved">void</span> Main()
    {
        MainAsync().Wait();
    }

    <span class="reserved">static</span> <span class="reserved">async</span> <span class="type">Task</span> MainAsync()
    {
        ...
    }
}
</code></pre>
<p>こちらはまあ、<code>void Main</code>の方を優先する、みたいなルールで回避はできるはず。</p>
<h4>Source Generation</h4>
<p>これは、いろんなところが関係するんで、それが先送りの理由かなぁと。要するに、</p>
<ol>
<li>C# にコード生成を前提とした新文法を追加する: replace/original キーワードの追加</li>
<li>CodeAnalysis API に<code>SourceGenerator</code>みたいなクラスを追加して、コンパイラー プラグインとして自作のコード生成処理を挟めるようにする</li>
<li>Visual StudioやVS Codeに、ソースコード書き換え時や、ビルド時に<code>SourceGenerator</code>を掛ける仕組みを追加する</li>
</ol>
<p>という3つが必要。</p>
<p>1はあったんですよね。一時期はmasterブランチにもマージされてました。問題もいくつか出てはいたですが:</p>
<ul>
<li>複数のreplaceを書けない(複数のコード生成プラグインを掛けると競合する可能性がある)</li>
<li><a href="https://github.com/dotnet/roslyn/issues/12516">ref returns と食い合わせが悪く、現状まだバグってる</a></li>
</ul>
<p>それよりは、2、3の作業が全然見えてこないなーという感じで。やっぱりC# 7には入れないんだ…</p>
<p>VS &quot;15&quot; Previewのリリース ノートでも、「VS &quot;15&quot;で新たに入る機能は<code>IOperation</code>です」としか書かれてなかったし。
(※<code>IOperation</code>は、C#とVBの両方に対して、単一のプラグインでコード解析・コード修正を掛けれる機能。)</p>
<p>特に今は、Visual Studio、Xamarin Studio、Visual Studio Codeの全部にこの手の仕組みを対応させたがってる節があって、この3者の間で調整してそうな予感が。C#チームの範疇を超えてますし、多少時間掛かりそう。</p>
<h4>Throw Expressions</h4>
<p><code>void Method() =&gt; throw new NotSupportedException();</code>とか、<code>x ?? throw new ArgumentNullException(nameof(x))</code>とか、<code>int.TryParse(s, out var x) ? x : throw new InvalidOperationException();</code>とか書けるようにしたいって話。</p>
<p>これをやるんだったら、never 型(<a href="http://ufcpp.net/blog/2015/08/pickuproslyn0829/">去年のブログ</a>とか<a href="http://www.buildinsider.net/column/iwanaga-nobuyuki/002">Build Insiderの記事</a>参照)も入れたいとかあるんじゃないかなぁと。</p>
<p>あと、こいつが本格的に必要になるのはmatch式(<a href="https://github.com/dotnet/roslyn/blob/features/patterns/docs/features/patterns.md">パターン マッチングのドキュメント</a>のMatch Expressionのところを参照)が入ってからなので、これがC# 7から外れた以上、throw式だけを先に入れる動機付けは弱いはず。</p>
<h2>Design Notes 7/15</h2>
<p><a href="https://github.com/dotnet/roslyn/issues/12939">C# Design Notes for Jul 15, 2016 #12939</a></p>
<p>で、ちょうど、7/15のDesign Notesが公開されて、ここにOut Varで導入される変数のスコープについて書かれています。</p>
<p>これまで、C#の変数宣言は書ける場所を限定していたのもあって、「宣言しているブロック内がスコープ」というシンプルなルールになっていました。</p>
<p>ところが、C# 7では、</p>
<ul>
<li>Out Var: <code>int.TryParse(s, out var x) ? x : default(int?);</code> みたいに、out引数のところで変数宣言できるようになる</li>
<li>Type Switch: <code>obj is int x ? x.ToString() : &quot;unsupported&quot;;</code> みたいに、is演算子で変数宣言できるようになる</li>
</ul>
<p>という2つの機能が入って、こいつらは、式を掛ける文脈ならどこでも変数宣言できてしまいます。
ここで導入される変数 <code>x</code> のスコープはどの範囲になるべきかという課題がありました。</p>
<p>現状、とりあえず相当厳しい方に倒して実装しています。すなわち、「<code>x</code>は、その式を含むステートメント内でだけ使える」というものです。要するに、以下のコードはコンパイル エラーに。</p>
<pre class="source" title="2016/8/5時点での実装">
<code><span class="reserved">static</span> <span class="reserved">void</span> X(<span class="reserved">string</span> s)
{
    <span class="reserved">var</span> value = <span class="reserved">int</span>.TryParse(s, <span class="reserved">out var</span> x) ? x : 0; <span class="comment">// x はこのステートメント内でしか使えない</span>
    <span class="type">Console</span>.WriteLine(x); <span class="comment">// もうスコープを外れてる。使えない。コンパイル エラーに</span>
}
</code></pre>
<p>いろいろ検討した結果、これはさすがに実際にありそうな用途をカバーしきれないという結論で、制限緩和を考えてるみたいです。</p>
<p>パッと見、「この式を含んでいるブロック内で使える」というのが素直に思えるんですが、if とか for とかが絡むと多少めんどくさく。</p>
<p>例1: if の条件式内で宣言した変数は、else側には伸びてほしくない</p>
<pre class="source" title="">
<code><span class="reserved">if</span> (o <span class="reserved">is</span> <span class="reserved">bool</span> b) ...b...; <span class="comment">// b はスコープ内</span>
<span class="reserved">else</span> <span class="reserved">if</span> (o <span class="reserved">is</span> <span class="reserved">byte</span> b) ...b...; <span class="comment">// bool の方の b はもうスコープ外。新しいbを作れる</span>
...; <span class="comment">// どちらのbもスコープ外</span>
</code></pre>
<p>例2: 「含んでいるブロック内」で区切ると、forとかで変になる</p>
<pre class="source" title="">
<code><reserved></span><span class="reserved">for</span> (<span class="reserved">int</span> i = foo(<span class="reserved">out</span> <span class="reserved">int</span> j); ;) ;
<span class="comment">// iはスコープ外だけど、jはスコープ内になってしまうのはいい？</span>
</code></pre>
<p>例3: ブロックがないifとかどうするの</p>
<pre class="source" title="">
<code><span class="reserved">if</span> (...)
    <span class="reserved">if</span> (...)
        <span class="reserved">if</span> (o <span class="reserved">is</span> <span class="reserved">int</span> i) ...i...
...; <span class="comment">// ブロックを区切りにすると、i はここもスコープになる</span>
     <span class="comment">// その手前のifのせいで、iが初期化されている保証できないけどいい？</span>
</code></pre>
<p>ってことで、ifとかforとかの場合は「embedded statements内にスコープを限定する」っていうルールにしたいそうです。
embedded statementsって、要するに、ifとかforとかの直後に書けるステートメントのこと。ifとかforとかの後ろには、ブロック、もしくは、何か1つステートメントを書けるわけですが、その部分のことを指すそうです。</p>
<h3>余談: embedded statements</h3>
<p>この話を見て、embedded statementsって何だっけ？って思って久々にC#の仕様書を眺めてみたんですが…</p>
<pre>
statement:
    labeled-statement
    declaration-statement
    embedded-statement

embedded-statement:
    block
    empty-statement
    expression-statement
    selection-statement
    iteration-statement
    jump-statement
    try-statement
    checked-statement
    unchecked-statement
    lock-statement
    using-statement 
    yield-statement
</pre>
<p>つまり、embedded statement = ステートメントのうち、変数宣言とラベル付きステートメント以外。</p>
<p>ということは、こうなる: <a href="https://twitter.com/ufcpp/status/761514377543462912">https://twitter.com/ufcpp/status/761514377543462912</a></p>
<p><img src="/media/1089/cpfxcfuvuaebj5t.jpg" alt="変数宣言はブロックなしでは書けない" /></p>
<p>まあ、要するに、変数宣言とラベルって、それを囲っているブロックが重要な構文なので、ブロックを省略するとか認めないっていう。言われてみればそうですよねという感じ。</p>
<p>(逆に言うと、そうまでして変数宣言できる位置をちゃんと絞ってたのに、Out VarとType Switchのせいで面倒になったという話。)</p>
 ]]></description>
				<pubDate>Fri, 05 Aug 2016 15:24:05 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップ Roslyn 7/21</title>
				<link>http://ufcpp.net/blog/2016/7/pickuproslyn0721/</link>
				<description><![CDATA[ <h2>PDBファイルへのソースコード埋め込み</h2>
<p><a href="https://github.com/dotnet/roslyn/issues/12625">Proposal: Embed sources in PDBs #12625</a></p>
<p>提案されたの自体はだいぶ前だし、<a href="https://github.com/dotnet/roslyn/pull/12353">実作業を開始したのも2週間くらい前</a>からなんですが、PRの方で出たフィードバックをまとめて1 issueにしたみたい。結構おもしろい。</p>
<p>Visual Studio上で、参照しているライブラリのソースコードにF12キーとかで飛びたいわけですが。PDBみたいなデバッグ用情報にソースコードがまとまってないと、ライブラリ(+ PDB)を公開する側としても、参照する側としてもかなり面倒。issueページ中に背景シナリオがいくつか書かれてますが、例えば、</p>
<ul>
<li>ビルド時にソースコード生成していて、その生成される分についてはバージョン管理に含めていない。ビルド時生成分のソースコードも含めてパッキングしてくれる仕組みがないとやってられない</li>
<li>会社的にソースコードを出すこと自体はOKだけど、ソースコードを置いてあるリポジトリはプライベート。ライブラリ利用者にアクセス権は与えられない</li>
<li>GitHubとかでソースコードを公開しているけども、そのGitHub上のコードをVisual Studioから参照できるようにする設定までは面倒すぎてやってられない</li>
</ul>
<p>などなど。</p>
<p>あと、さらに、<a href="https://github.com/dotnet/roslyn/issues/12390">PDBをライブラリ自体に埋め込みたい</a>みたいな話も。</p>
<h2>Task-like型を返す非同期メソッド</h2>
<p><a href="http://ufcpp.net/blog/2016/5/pickuproslyn0504/">5/4のブログ</a>でちょっと書きましたが、非同期メソッドの戻り値に、<code>Task</code>(<code>System.Threading.Tasks</code>名前空間)以外の型を返せるようにしたいという話が出ています。</p>
<p>で、なんかマージされてる。</p>
<p><a href="https://github.com/dotnet/roslyn/pull/12518">Allow async methods to return Task-like types #12518</a></p>
<p><a href="https://twitter.com/jaredpar/status/755903209189748737">次のVisual Studio ”15” Preview (次は preview 4になるはず)には入る予定っぽい</a>。</p>
<p>この機能なんですけど、割かし最近まで形になってなかったんですよね。なので当然のように、「C# 7/VB 15に入るのかどうか」議論のターゲットにもなってなかった。
4月くらいから<a href="https://github.com/ljw1004">Lucian</a> (今、VBのPMやってる。元々の専門が非同期処理な方らしく、C# 5.0のasync/awaitにもがっつり関わってたみたい)が作業を開始。この時点でも、「まだLanguage Design Meetingの議題に上げる段階に至ってない」とか言ってたんですが。</p>
<p>その後どうもプロトタイピングがうまくいったようで、気が付いたら<a href="https://github.com/dotnet/roslyn/blob/master/docs/Language%20Feature%20Status.md">Language Feature Status</a>のリストに並び、気が付いたらマージされてました。</p>
<p>結構有用な応用例があるんで、C# 7に間に合いそうなのは結構うれしいかも。次の<a href="http://www.buildinsider.net/column/iwanaga-nobuyuki">Build Insiderオピニオン</a>、この辺りの話にしようかなぁ。</p>
 ]]></description>
				<pubDate>Thu, 21 Jul 2016 09:53:30 +0900</pubDate>
			</item>
			<item>
				<title>ローカル関数</title>
				<link>http://ufcpp.net/blog/2016/7/cs7localfunc/</link>
				<description><![CDATA[ <p>ちょっと間が空いたんで「C# 7思い出話」タグでなんか書いてたことを忘れかかっていたりはしますが。</p>
<p><a href="http://ufcpp.net/study/csharp/cheatsheet/ap_ver7/">C# 7のページにローカル関数の話を足しました</a>。</p>
<p>これで、現状で仕様が結構安定してるやつは全部なんですよねぇ。type switch辺りはそろそろ書いてもよさそうなくらい作業進んでは来てますが。タプル型とかはもうちょっと先かなぁ(自分の執筆ペースを考えるとたぶんちょうどいいくらいに安定しそうな気も)。</p>
<h2>ローカル関数</h2>
<p>これは<a href="http://ufcpp.net/study/csharp/functional/fun_localfunctions/#background-local-function">本文にも書いちゃってる</a>んですけど、要望として多いのは、ローカル関数がほしいというよりも、匿名関数の改良だったんですよね。</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/issues/24">匿名イテレーター書かせて</a></li>
<li><a href="https://github.com/dotnet/roslyn/issues/14"><code>Func&lt;int, int&gt; f = x =&gt; x * x;</code> みたいなのを <code>var f = x =&gt; x * x;</code> と書かせて</a></li>
<li>再帰呼び出しさせて</li>
<li>ジェネリック(polymorphic lambda)にさせて</li>
</ul>
<p>などなど。</p>
<p>そこに来て、<a href="https://github.com/dotnet/roslyn/issues/259">ローカル関数ほしい？</a>って話を出したところ、この手の匿名関数に対する問題が、ローカル関数なら結構解決するんじゃないか的な話にどんどんなっていって。数か月後には(正式に機能追加の提案に至る](https://github.com/dotnet/roslyn/issues/2930)。</p>
<p>まあ、元々、<a href="http://www.buildinsider.net/language/csharpscript/01">C# Scripting/Interactive</a>由来っぽい感じはあったんですが。
スクリプト環境だと、常にメソッド内部にいるかのような文法になる(トップレベルにステートメントを書ける)んで、
そこにメソッドを書くのは、実際のところローカル関数を作るのと大差ない感じになります。
たぶん、今まで全然入れてくれなかった機能が急に出てきたのはこれのせいじゃないかなぁとか思います。</p>
 ]]></description>
				<pubDate>Sun, 17 Jul 2016 12:47:00 +0900</pubDate>
			</item>
			<item>
				<title>dotnetConf 2016 Japan</title>
				<link>http://ufcpp.net/blog/2016/7/dotnetconfjp/</link>
				<description><![CDATA[ <p>昨日は<a href="https://csugjp.doorkeeper.jp/events/46856">dotnetConf 2016 Japan</a>でした。</p>
<p>あいにくの雨でキャンセル率高く、当初予想ほどの混雑には至りませんでしたが多くの方のお越しいただきました。
改めて御礼申し上げます。</p>
<p>以下、発表資料をまとめておきます。</p>
<h2>dotnetConf 2016 Japan 開催にあたって ～ .NET の今と未来</h2>
<p>デモ用ソースコード: <a href="https://github.com/chack411/dotnetConfjp">https://github.com/chack411/dotnetConfjp</a></p>
<h2>.NET Standard</h2>
<div style="width: 608px; max-width: 100%; margin-bottom:5px;"><a href="https://docs.com/iwanaga-nobuyuk/3514/net-standard-library" title=".NET Standard Library" target="_blank" style="font-family: 'Segoe UI'">.NET Standard Library</a><span style="font-family: 'Segoe UI Light'">—</span><a href="https://docs.com/iwanaga-nobuyuk" target="_blank" style="font-family: 'Segoe UI'">Iwanaga Nobuyuki</a></div><iframe src="https://docs.com/d/embed/D25193425-6301-0649-0630-000859537793%7eMd2f0fde0-d68b-9095-2ec5-841305bd4fb1" frameborder="0" scrolling="no" width="608px" height="378px" style="max-width:100%" allowfullscreen="False"></iframe>
<h2>Xamarinの新しい話とMonoの深い話</h2>
<div style="width: 608px; max-width: 100%; margin-bottom:5px;"><a href="https://docs.com/user150361/9217/dotnetconf-japan-2016-xamarinmono" title="[dotnetConf Japan 2016] Xamarinの新しい話とMonoの深い話" target="_blank" style="font-family: 'Segoe UI'">[dotnetConf Japan 2016] Xamarinの新しい話とMonoの深い話</a><span style="font-family: 'Segoe UI Light'">—</span><a href="https://docs.com/user150361" target="_blank" style="font-family: 'Segoe UI'">Madoka Chiyoda</a></div><iframe src="https://docs.com/d/embed/D25193414-8670-6325-5430-000194227894%7eM9dac51d5-e765-88c1-885f-49e86b6c6ced" frameborder="0" scrolling="no" width="608px" height="378px" style="max-width:100%" allowfullscreen="False"></iframe>
<p>関連:</p>
<ul>
<li><a href="https://blogs.msdn.microsoft.com/chomado/xamarin/joined-dotnetconf-japan-2016/">dotnetConf Japan 2016 で登壇してきました！</a></li>
<li><a href="http://atsushieno.hatenablog.com/entry/2016/07/11/012541">Xamarinの新しい話とMonoの深い話 @ dotnetConfJapan2016</a></li>
</ul>
<h2>MVVM Done Right with Xamarin.Forms and Prism</h2>
<h2>.NET Core on RHEL</h2>
<div style="width: 608px; max-width: 100%; margin-bottom:5px;"><a href="https://docs.com/tanaka-takayosh/2533/20160709-dotnetconf-japan-2016?c=4ZcLve" title="20160709 dotnetconf Japan 2016" target="_blank" style="font-family: 'Segoe UI'">20160709 dotnetconf Japan 2016</a><span style="font-family: 'Segoe UI Light'">—</span><a href="https://docs.com/tanaka-takayosh" target="_blank" style="font-family: 'Segoe UI'">Tanaka Takayoshi</a></div><iframe src="https://docs.com/d/embed/D25193430-8410-5558-8000-001183795431%7eM266dedef-977b-953e-e280-299f6e92d89a" frameborder="0" scrolling="no" width="608px" height="378px" style="max-width:100%" allowfullscreen="False"></iframe>
<p>関連: <a href="https://docs.com/tanaka-takayosh/8835/net-core-on-rhel-rtm-1-0"> .NET Core on RHEL リンク集 (RTM 1.0 時点)</a></p>
<h2>ASP.NET Core</h2>
<div style="width: 608px; max-width: 100%; margin-bottom:5px;"><a href="https://docs.com/shibayan/6851/asp-net-core-1-0-rtm" title="ASP.NET Core 1.0 RTM" target="_blank" style="font-family: 'Segoe UI'">ASP.NET Core 1.0 RTM</a><span style="font-family: 'Segoe UI Light'">—</span><a href="https://docs.com/shibayan" target="_blank" style="font-family: 'Segoe UI'">Tatsuro Shibamura</a></div><iframe src="https://docs.com/d/embed/D25193424-2675-8337-0730-000794488821%7eMd94cbc3e-3bde-126a-784c-fa6d816313f3" frameborder="0" scrolling="no" width="608px" height="378px" style="max-width:100%" allowfullscreen="False"></iframe>
<p>関連: <a href="http://blog.shibayan.jp/entry/20160710/1468141753">dotnetConf 2016 Japan で ASP.NET Core 1.0 について話してきました</a></p>
<h2>.NET Core/VS/VSCode他ツール類</h2>
<iframe src="//www.slideshare.net/slideshow/embed_code/key/1rgVU38UG0dSgR" width="595" height="485" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe> <div style="margin-bottom:5px"> <strong> <a href="//www.slideshare.net/bonprosoft/dotnetconf-2016-japan-net-core" title=".NET Coreとツール類の今" target="_blank">.NET Coreとツール類の今</a> </strong> from <strong><a href="//www.slideshare.net/bonprosoft" target="_blank">Yuki Igarashi</a></strong> </div> ]]></description>
				<pubDate>Sun, 10 Jul 2016 14:28:31 +0900</pubDate>
			</item>
			<item>
				<title>「project.json辞めます」の意味</title>
				<link>http://ufcpp.net/blog/2016/6/project-json/</link>
				<description><![CDATA[ <p><a href="https://github.com/dotnet/core">.NET Core</a>といい<a href="https://github.com/dotnet/roslyn">C#コンパイラー</a>といいオープンソースになったおかげで常に最新の情報を拾えてありがたい限りなわけですが。
緩い段階のものが見えすぎて、いろいろ振り回されたりもします。</p>
<p>最近の話題というと、<a href="https://www.infoq.com/news/2016/05/project-json/">「project.json辞めます」騒動</a>。</p>
<p>これ、あんまり字面通り受け止めるとダメだと思うんですよね。
話の出どころは「<a href="https://live.asp.net/">ASP.NET Community Standup</a>」の1コマ、<a href="https://www.youtube.com/watch?v=P9HqMZviaMg&amp;list=PL0M0zPgJ3HSftTAAHttA3JQU4vOjXFquF&amp;index=0">5月10日放映分</a>での会話らしいんですが。
こういう、会話中で出てきた言葉って、割かし不正確(にとられかねない緩い表現)なわけです。</p>
<h2>ここでいう「project.json辞めます」の意味</h2>
<p>.NET Coreは、当初、脱msbuildを目指していたわけです。.NET Coreにとっかかり始めた当時の発想としては、</p>
<ul>
<li>msbuildとか、MS製のビルド ツールはC++、COM製で、クロスプラットフォーム化が大変</li>
<li>
ASP.NET に対応できればいい
<ul>
<li>モダンなWebっぽいものを作りたい</li>
</ul>
</li>
</ul>
<p>というような感じだったはずです。</p>
<p>ところが今は、</p>
<ul>
<li>msbuildが.NETでクロスプラットフォーム実装になってる</li>
<li>UWP、Xamarinなどなど、いろんなものに対応する必要が出てきた</li>
</ul>
<p>と、状況が変わってる。</p>
<p>なので、実際のところは、「ASP.NET チーム主導で独自に作ってたビルド ツール辞めます」、「msbuild使います」という話になります。</p>
<p>で、「ASP.NET チーム主導で独自に作ってたビルド ツール」に名前がないもんだから、そいつが解釈するプロジェクト設定ファイルであるところの「project.json」を辞めるという言い回しをしてしまっているという状況。</p>
<h2>もう1つのproject.json</h2>
<p>.NET Coreのリリースがずるずると伸びてる間に、1年近く早く先にリリース段階に達した別プロダクトがあるわけです。<a href="https://msdn.microsoft.com/en-us/windows/uwp/get-started/whats-a-uwp">UWP</a>とか<a href="https://github.com/nuget">NuGet</a> 3とか。</p>
<p>.NET Coreは標準ライブラリの参照でNuGetの仕組みに乗っかってるわけですが、
同じく、NuGetに乗っかりたかったのがUWP。
Windwos 10のリリースに合わせる必要があったので、2015年7月の段階でRTM。
そのために、NuGetも同時期にバージョン アップしました。</p>
<p>このとき、.NET Coreのproject.jsonのうち、パッケージ参照がらみの部分だけを抜き出して使うことになりました。
つまり、NuGet 3では、packages.configを辞めて、project.json形式を使うように。
ここで、project.jsonが2つに分岐したわけです。
この辺りは去年の12月にブログを書いてます。</p>
<ul>
<li><a href="http://ufcpp.net/blog/2015/12/csprojprojectjson/">.csproj + project.json</a></li>
</ul>
<p>そしてこちらのproject.jsonは、msbuild に組み込まれています。</p>
<p>先ほど言った通り、.NET Coreチームの言うところの「project.json辞めます」は、実際には「msbuild使います」の意味です。
つまるところ、NuGet側のproject.json (msbuild対応済み)は辞めるどころか、むしろ積極的に使われるようになる立場。</p>
<h2>nuget.json？</h2>
<p>で、パッケージ参照設定なのに名前が「project」なの？とかいう問題に至ります。
元々はprojectだったけども。その元々の方がお亡くなりになってしまい…</p>
<p>ってことで、NuGetが使っている方のproject.jsonはnuget.jsonにリネームしようみたいな話もあるみたい？</p>
<p>まあなんか、この「project.json辞めます」騒動のせいでもう、そこいら中から「project.json辞めたんじゃないの？」「UWPのやつどうなるの？」みたいな疑問の声が出まくってるんで、もう、リネーム必須な状況になってしまってるんじゃないかなぁ…という気がします。</p>
<h2>project.json便利だったのに…</h2>
<p>.NET Coreチームの言うproject.jsonは、.csprojほどファイルの衝突が起きなくて、ソースコードのバージョン管理的には大変ありがたかったです。</p>
<p>「project.json辞めます」、すなわち、「msbuild使います」というのは、結局、「.csprojに戻ります」という意味でもあります。
ありがたかった機能も一旦なくなるわけですが…</p>
<p>.NET Coreチーム曰く、「msbuild/.csprojの方を改善します」とのこと。csprojでも、「フォルダー中の.csは全部コンパイル対象」みたいなことをできるようにしたいみたいです。
てことで、「将来的に、msbuild/.csprojがもっと便利になる」と捉えるべき。</p>
<h2>まとめ</h2>
<p>緩い段階で出てきた話は字面通りに受け止めちゃダメというか。
今時は情報の出どころがものすごい緩いことが多いというか。
みんなタイトルだけ読んでわかった気になるんだから、緩い出どころを元にブログのタイトル付けちゃダメというか。</p>
<p>.NET Coreチームの言う、元々の意味のproject.jsonはどうやらなくなります。
ただし、その利便性をmsbuildに引き継ぎたいそうです。</p>
<p>「project.json辞めます」の本当の意味は「.NET Coreでもmsbuildを使います」です。
project.jsonでやろうとしていたことを、msbuildに取り込んでいきたいそうなので、「msbuildが便利になる」と考えるべきです。</p>
<p>また、NuGetの方のproject.jsonはすでに1年前からmsbuldに組み込み済みなので、なくならないどころか、むしろ今後積極的に使われるようになる側にいます。
ただし、nuget.jsonにリネームはするかも。</p>
 ]]></description>
				<pubDate>Tue, 28 Jun 2016 14:39:34 +0900</pubDate>
			</item>
			<item>
				<title>dot.net にC#オンライン エディター</title>
				<link>http://ufcpp.net/blog/2016/5/dotnet/</link>
				<description><![CDATA[ <p>.NET Core、リリースされましたね。</p>
<p>まあ、その辺りの話は他の人に任せるとして。</p>
<ul>
<li><a href="http://blog.shibayan.jp/entry/20160628/1467044271">.NET Core / ASP.NET Core 1.0 が RTM になりました</a></li>
<li><a href="https://buchizo.wordpress.com/2016/06/28/net-core-1-0-rtm-visual-studio-2015-update-3/">.NET Core 1.0 RTM / Visual Studio 2015 Update 3</a></li>
</ul>
<p>自分が気になったのはこちら。</p>
<p><img src="/media/1086/dotnetstartingcode.png" alt="Scott Hanselmanのブログにこんな画像が" /></p>
<p><a href="http://www.hanselman.com/blog/NETCore10IsNowReleased.aspx">Scott Hanselmanの.NET Coreリリースに関するブログ記事</a>に気になる画像がありまして。画像にリンクが貼ってあって、リンク先は</p>
<ul>
<li><a href="http://dot.net">http://dot.net</a></li>
</ul>
<p>こちら。</p>
<p>ちょっと前に、「よくこのドメイン取れたな」、「マイクロソフトってURLにこだわってくれなくていつもダサいのに、これはほんとにうれしい」と話題になってたやつですね。
結局は<a href="https://www.microsoft.com/net">https://www.microsoft.com/net</a>に転送されたりはするんですが、まあ、<a href="http://dot.net">http://dot.net</a>がある、このURLでリンク貼れるってのが大事です。</p>
<p>で、このページをちょっと下にスクロールすると、こんなものが。</p>
<p><img src="/media/1087/startingcode.png" alt="Starting coding" /></p>
<p>ウェブページ内でC#コード書いて試せる！
いつからありましたっけ？</p>
<p>まあ、中身的には「<a href="http://gihyo.jp/dev/serial/01/monaco/0001">Monaco</a>」っぽいです。
Monacoを使って、チュートリアル コードをサイト内に埋め込んだり、「Run」ボタンを押して実行結果を出力したり。</p>
<p>これも、まあ、ずっとほしいほしい言い続けてたやつなわけですが。
<a href="http://golang-jp.org/">Go</a>なんかは公式サイト開いた瞬間「Try Go」なわけで。
同じものがC#にもほしいって言ってたら、ちゃんとできてた。
しいて言うなら、こんなちょっとスクロールしないと見えない位置に置くのはやめてほしいなぁという感じはあります。
このページはたびたび見たことあるけど、大体「DOWNLOADS」か「DOCUMENTATION」リンクに直行でスクロールしませんし。</p>
<p>しかも、チュートリアル ページのサンプル コードも、実行できるものは1個1個、このMonacoベースのオンライン エディターを立ち上げて実行できるみたいです。</p>
<p><img src="/media/1088/tutorials.png" alt="チュートリアル ページのサンプル コード" /></p>
<p>これは大変よさげ。</p>
 ]]></description>
				<pubDate>Tue, 28 Jun 2016 13:23:13 +0900</pubDate>
			</item>
			<item>
				<title>C# 6, C# 7</title>
				<link>http://ufcpp.net/blog/2016/6/versionnumber/</link>
				<description><![CDATA[ <p>最近、C#がらみの原稿仕事を依頼されたとき、よくある校正が「C# 6になってますけども、6.0ですよね？」。
回答は「いえ、C# 6が正式です」。</p>
<p>C#のバージョン番号、6以降は .0 を付けないのが正式っぽいんですよね。実は。</p>
<ul>
<li>C# 1.0</li>
<li>C# 1.1 (<code>#line</code>ディレクティブと<code>/** doc comment */</code>が追加されただけ。1.1なのか1.2なのかも割かしよくわからず)</li>
<li>C# 2.0</li>
<li>C# 3.0</li>
<li>C# 4.0</li>
<li>C# 5.0</li>
<li>C# 6</li>
<li>C# 7</li>
</ul>
<p>という感じ。</p>
<p>実質的に小数点以下使ってない(1.1とか存在感ない)し、要らないですよね。という感じ。</p>
<p>これに気づいたの、結構後になってからなんで、うちの<a href="http://ufcpp.net/study/csharp/">C#によるプログラミング入門</a>にも「C# 6.0」って表記が結構残ってたんですが、今しがた整理。ブログ以外からは6.0が消えたはず。</p>
<h2>実はよくわからない</h2>
<p>ただ、C# 7の次がC# 7.1とかになる可能性は0ではないです。「TypeScriptとか0.1刻みの細かいリリースしてるよね」みたいな話題もあるし、C#も1年1回リリースくらいのペースに速めようなんて話が出てますし。パターン マッチングの構文を、7で追加するものと、その先に回すものを分けたとかいうのもありますし。</p>
<p>.NET Frameworkも、「.NET 4」ってブランド名にしたら、その次からが「.NET 4.5」、「.NET 4.5.1」、「.NET 4.6」、…とかだったなんて話もあります。</p>
<p>あと、C#チームは現体制(<a href="https://github.com/dotnet/roslyn">GitHub上で公開</a>、<a href="https://github.com/MadsTorgersen">Mads</a>がPM)になってから、この手のアナウンスが手抜きなんですよね。気が付いたら「あれ？そうだったの？」みたいなことが割とちらほら。</p>
<p>単に、「6.0と6に何の差もないだろう」的な発想なのかも。例えば以下のページなんて、C# 1, C# 2, C# 3, ...表記。</p>
<ul>
<li><a href="https://msdn.microsoft.com/en-us/library/hh156499.aspx">What's New for Visual C#</a></li>
</ul>
<p>ってことで、自分も全部C# 1, C# 2, C# 3, ...表記に変えたい気持ちありつつ。まあ、一応過去への遡及はしないことにします… 6以降だけ、.0を取る方針で。</p>
<h2>おまけ: VB</h2>
<p>Visual Basicのバージョンもなかなかよくわからないみたいですね。</p>
<p>C#は、言語のバージョンとIDEのバージョンを分けて表記してますけど、「Visual Basic」っていうIDE製品があった頃の名残で、言語とIDEの区別をしないみたい。その結果何が起こるかというと…</p>
<p>まあ、以下のページを見てください。</p>
<ul>
<li><a href="https://msdn.microsoft.com/en-us/library/we86c8x2.aspx">What's New for Visual Basic</a></li>
</ul>
<p>書かれてるのは以下の通り。</p>
<ul>
<li>Visual Basic / Visual Studio .NET 2002 (内部バージョン7)</li>
<li>Visual Basic / Visual Studio .NET 2003 (7.1)</li>
<li>Visual Basic / Visual Studio .NET 2005 (8)</li>
<li>Visual Basic / Visual Studio .NET 2008 (9)</li>
<li>Visual Basic / Visual Studio .NET 2010 (10)</li>
<li>Visual Basic / Visual Studio .NET 2012 (11)</li>
<li>
Visual Basic / Visual Studio .NET 2013 (12)
<ul>
<li>このとき、コンパイラーは全く更新してません</li>
</ul>
</li>
<li>
Visual Basic / Visual Studio .NET 2015 (14)
<ul>
<li>13を嫌って、内部バージョン1つ飛ばして14</li>
</ul>
</li>
</ul>
<p>で、VBのバージョンとしては、Visual Studioの内部バージョンで(2002みたいな年号表記じゃなくて、7みたいなの)表します。
問題は、2013。VBのコンパイラーは一切変更してないのに、こいつのことをVB 12って言うみたいです。
しかもその後、13っていう忌み数を避けて内部バージョンを14にしたもんだから、VBもVB 14に。</p>
 ]]></description>
				<pubDate>Sat, 11 Jun 2016 03:46:53 +0900</pubDate>
			</item>
			<item>
				<title>参照戻り値と参照ローカル変数</title>
				<link>http://ufcpp.net/blog/2016/6/cs7refreturns/</link>
				<description><![CDATA[ <p>C# 7の説明、1つ足しました。参照戻り値がらみ。</p>
<h2>参照戻り値と参照ローカル変数</h2>
<p>追加される構文自体は割とシンプルなんですが、活用できそうな場面まで含めて説明しようとするとなかなか骨が折れる感じの機能。</p>
<ul>
<li>機能自体の説明: <a href="http://ufcpp.net/study/csharp/sp_ref.html?p=2">参照戻り値と参照ローカル変数</a></li>
<li>前提知識として、値型を使わないとパフォーマンス出しにくい場面があるという話: <a href="http://ufcpp.net/study/csharp/oo_reference.html?p=2#performance">値型の性能</a></li>
<li>で、値型を使ってパフォーマンスを出そうと思うと参照渡しが避けられなかったりするという話: <a href="http://ufcpp.net/study/csharp/sp_ref.html?p=3">値型の参照渡し</a></li>
</ul>
<p>まず、メモリ管理の方法について(スタックとかヒープとか)知ってないとピンとこないですしね。</p>
<p>「別の何かを参照する」って考え方も、そこそこ素養を求める概念ですし。
C言語とかC++で「ポインターは難しい」とか言われるのも、同種の問題だと思います。</p>
<p>ということで、<a href="https://github.com/dotnet/roslyn">GitHub</a>上のディスカッションでも、大体は、</p>
<ul>
<li>活用場面がよくわからない</li>
<li>(自分は)使わなさそうなのに、複雑性を増すのには反対</li>
<li>構造体は immutable に作れってのが常識じゃないのか</li>
</ul>
<p>なんて話がまずあって、それに対して、</p>
<ul>
<li>メモリ管理の手法とか知らない人はそう言って、パフォーマンスをいとも簡単に落とすんだ</li>
<li>パフォーマンスを求めると、mutable な構造体を配列で持っとくしかない場面があるんだ</li>
</ul>
<p>とかの返事が毎度ついてる感じ。</p>
<p>文法自体についての反対意見はあんまりなさそう。しいて言うなら、</p>
<ul>
<li>非同期メソッドとかイテレーターとかでも使いたいけど、<code>Task&lt;ref T&gt;</code>とか<code>IEnumerable&lt;ref T&gt;</code>は作れないよね？</li>
<li>ローカル変数の宣言で、<code>var</code> (変数の型推論)を使う場合ですら<code>ref var</code>って書かないといけないのはちょっと面倒</li>
</ul>
<p>みたいな話が出てるくらい。</p>
<p>まあ、なかなか活用しどころが想像しにくい機能ではあるんですが、C# チーム的には優先度結構高いでしょうね。
<a href="http://www.buildinsider.net/column/iwanaga-nobuyuki/006">Build Insider</a>の方で書きましたけど、
今、パフォーマンスに対する要求がかなり上がってるので。
.NET Core関連のチームとか、C#チーム自身とかにとってはかなり有用な機能のはず。
多くのプログラマーにとって直接使うことがない機能であっても、
低レイヤーなライブラリとかツールとかの性能向上が見込めるので、間接的な恩恵はそこそこありそうな気がします。</p>
<h3>6/6 追記:</h3>
<p>この手のメモリ管理がらみのパフォーマンス改善の話に付いて回るのは、ガベージコレクションもかなり高性能になってて、もうガベコレに任せてても大体大丈夫なんじゃないかという議題。</p>
<p>確かに、MS製ガベコレって結構高性能なんですよね。それでもガベコレ除けをきっちりするとかなりのパフォーマンス改善したりしますが。
仮にまあ、ガベコレがもっともっと優秀になったとしても…</p>
<p><span style="font-size:150%">その優秀なガベコレがどこででも使えると思うなよ！</span></p>
<p>と思うわけです。
ガベコレのコードなんて、<a href="https://github.com/dotnet/coreclr/blob/master/src/gc/gc.cpp">.NETのもの</a>なんてファイルサイズが1.2MB(GitHubに&quot;we can't show files&quot;って言われるやつ)、行数3700行を超える長大なC++コードです。どこまで手書きでどこまで機械生成かわからないなんて話もありますが、どちらにしたって、なかなか保守が大変そうな分量。
特定の1環境で保守するのはまだ成り立つんですが、全然スペックの違う異なる環境向けにそれぞれ提供とかにあると、なかなか大変そう。
要するに何が言いたいかというと、あんまりこういうレイヤーの改善に期待してると、新しいプラットフォームに移りづらくなるとかのリスクもあったり。</p>
<p>具体的に、最近自分は<a href="http://japan.unity3d.com/">Unity</a>でiOS/Android両対応のゲームを作ってるわけですけども、
どうも、ヒープ確保の性能がiOSとAndroidでだいぶ違うみたいで、同じコードを書いててもAndroidでだけパフォーマンスが出なかったりします。
(他にもパフォーマンス ネックの原因になってそうな場所は多いんですが、ヒープ確保もネックの1つなことは間違いなさそう。)</p>
<p>一般論としても、「ムーアの法則での発展を期待していたら、モバイルな時代が来ちゃってむしろ時代が巻き戻った」なんて言葉よく聞くわけでして。
今更ながらC#に参照戻り値みたいな「使う人を選ぶ」機能が入るのも、そういう時代背景があるんじゃないかなと思います。</p>
 ]]></description>
				<pubDate>Sun, 05 Jun 2016 12:32:05 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 5/29</title>
				<link>http://ufcpp.net/blog/2016/5/pickuproslyn0529/</link>
				<description><![CDATA[ <h2>拡張メンバー</h2>
<p>Design Meetingで拡張メンバーの検討をしてたみたい。
(拡張メンバー = 初期検討段階で「extension everything」(なんでも拡張)って言ってたやつ。拡張メソッド以外に、プロパティとかも拡張できるようにする構文)</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/issues/11516">C# Language Design Notes for May 10</a></li>
</ul>
<p>現状、以下のような感じ。</p>
<ul>
<li>
<code>extension class</code>ってキーワードで、通常のクラスを継承したような構文で作る
<ul>
<li>定義したメンバーは拡張メソッド同様、静的メソッド化される</li>
<li>プロパティは、「インデックス付きプロパティ」(ILレベルとかVBにはある。C#のレベルで使ってないだけ)に展開するのがよさそうだけど、現状のC#では認めてないものなのでちょっと悩ましい</li>
</ul>
</li>
<li>インスタンス メンバー風の拡張だけじゃなくて、静的メソッドの拡張も足せる</li>
<li>コンストラクターも足せる</li>
<li>
演算子をどうするかは悩ましい
<ul>
<li>四則演算とかはいいと思うんだけど</li>
<li><code>==</code> とかが怪しい</li>
</ul>
</li>
<li>
<code>Person</code>クラスの拡張<code>Enrollee</code>があったとして、<code>Person</code>の通常のインスタンス メンバーと、拡張の方のメンバーを呼び分ける構文がほしい
<ul>
<li>優先されるのは通常のインスタンス メンバー</li>
<li>たぶん<code>((Emrollee)person).Supervisor</code>みたいなキャスト構文でやる</li>
</ul>
</li>
</ul>
<h2>コンパイラー組み込み</h2>
<p>「時々C#にもインライン アセンブラーがほしい」問題に対して、
別解法の提案。</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/issues/11475">Proposal: Compiler intrinsics #11475</a></li>
</ul>
<h3>C#では書けないもの</h3>
<p>まず、「ILを使えば書けるけど、C#では書けない」みたいなのの例。</p>
<ul>
<li>CLRがやってるみたいなネイティブ コードとの相互運用をビルド時に静的に作ってしまおうと思うと、いくつかC#では書けない命令が必要</li>
<li><code>infoof</code>(information ofの略。<code>typeof</code>と同じノリで<code>MethodInfo</code>とかを取る)相当の機能をライブラリでやろうと思うと<code>ldtoken</code>命令が必要</li>
<li>
<a href="http://www.buildinsider.net/column/iwanaga-nobuyuki/007">スライス</a>を作るのにC#では書けない機能が必要
<ul>
<li>実際、<a href="https://github.com/joeduffy/slice.net/blob/master/src/PtrUtils.il">現状、ILを書いてる</a></li>
</ul>
</li>
</ul>
<h3>インライン アセンブラーはやらない</h3>
<ul>
<li>時々しかない要件のためにILインライン アセンブラーを実装するのはコストに見合わない</li>
<li>というか、混ぜるのよくない。C#コンパイラーとILアセンブラーは別ツールとして、別チームが個別開発すべき</li>
</ul>
<h3>別解法の提案</h3>
<p>で、提案してるのが「コンパイラー組み込み」(compiler intrinsics: コンパイラーが内在して持ってる実装)。</p>
<p>いくつかのC++コンパイラーは、プログラマーがSSE命令とかAVX命令みたいな特殊な命令を使えるように、<a href="https://msdn.microsoft.com/ja-jp/library/26td21ds.aspx">コンパイラー組み込みの特殊なメソッドを提供</a>してたりします。
C#でもそういう特殊なメソッドを用意して、上記のような通常のC#では書けない場面に対処すればいいんじゃないかという提案を出してきています。</p>
<p>文法的には<code>extern</code>メソッドを使うだけ。<code>CompilerIntrinsic</code>属性を付けることで、ネイティブDLL中のネイティブ メソッドを呼ぶ代わりに、コンパイラーが直接その場所にIL命令を出力するというもの。
これなら今から新文法について考える必要もないし、簡単に目的が達成できそう。</p>
<h2>bool型やenum型のswitchの完備性</h2>
<p><code>bool</code>型には<code>true</code>と<code>false</code>しかないはずなんだから、以下の<code>default</code>句は不要にできないかという話。ご意見求む状態。</p>
<pre class="source" title="">
<code><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">bool</span> b = ...;
<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">switch</span> (b)
{
    <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">case</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">true</span>:
    <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">case</span> <span class="pl-c1" style="box-sizing: border-box; color: rgb(0, 134, 179);">false</span>:
        <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">break</span>;
    <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">default</span>:
        <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">break</span>; <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">// warning: unreachable code?</span>
}
</code></pre>
<p>これ、昔から要望としては頻出なんですが、できない理由もあります。ILは結構低級機能を提供しているので、<code>bool</code>型の変数を無理やり書き換えて、<code>true</code>でも<code>false</code>でもない値を作れて、上記<code>default</code>句に来ちゃう場合があったり。
というか、C#でも、以下のような書き方でそういう値を作れます。</p>
<ul>
<li><a href="https://gist.github.com/ufcpp/fe6788898ca4b91f0067dd7017af6ca4">unsafeで値を書き換え</a></li>
<li><a href="https://gist.github.com/matarillo/0b6815729dd20fb17c0ee62210dfeb3c">StructLayoutで値を書き換え</a></li>
</ul>
<p>それに、後方互換性を考えると、既存の<code>switch</code>には警告も出せないです。</p>
<p>という背景の中、今後導入予定の<code>match</code>式(<code>switch</code>の式バージョン)ではこういう普通はあり得ない<code>default</code>句に対する警告がほしいですか？という質問。</p>
<h2>言語サポート付きのobsolete</h2>
<p>今、obsolete (廃止したい、もう使ってほしくない)なメンバーには<code>Obsolete</code>属性を付けて対処しています。
でも、この属性ベースのやり方じゃなくて、C#の言語機能としてobsoleteキーワードが必要かもという話が。</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/issues/11583">Proposal: language support for Obsolete #11583</a></li>
</ul>
<p>シナリオ的には以下のようなもの。</p>
<pre class="source" title="">
<code><comment></span><span class="comment">// シナリオ 1:</span>
<span class="reserved">int</span> f(<span class="reserved">string</span> s);                 <span class="comment">// ライブラリv1がこいつを持ってる</span>
<span class="reserved">int</span> f(<span class="reserved">string</span> s, <span class="reserved">bool</span> b = <span class="reserved">false</span>); <span class="comment">// v2でこれに変えたい</span>
<span class="comment">// バイナリ互換性のためにf(string)は消せない</span>
<span class="comment">// でも、今後、オーバーロード解決時に、f("") で優先的に f(string, bool) の方を見てほしい(今は無理)</span>

<span class="comment">// シナリオ 2:</span>
<span class="reserved">float</span> g();  <span class="comment">// ライブラリv1がこいつを持ってる</span>
<span class="reserved">double</span> g(); <span class="comment">// v2でこれに変えたい</span>
<span class="comment">// バイナリ互換性のためにfloat g()は消せない</span>
<span class="comment">// でも、今後、double g()を使いたい(呼び分けどころか今はそもそも定義すら不可能)</span>
</code></pre>
<p>これに対して、v1側に<code>obsolete</code>修飾子を付けることで、v2側の新メソッドの追加・オーバーロード解決できるようにしたいとのこと。</p>
<h2>TryRoslyn</h2>
<p><a href="https://github.com/dotnet/roslyn">Roslynリポジトリ</a>の各ブランチの最新版でのコンパイルを、オンラインで試して見れるサイト作ってる人がいた。</p>
<ul>
<li><a href="http://tryroslyn.azurewebsites.net/">http://tryroslyn.azurewebsites.net/</a></li>
</ul>
<p>C#チームの公式提供じゃないし、まだまだ作業途中みたいですけども。</p>
<ul>
<li>Lucian (C#チームの中の人)が、自分のリポジトリで<a href="https://github.com/dotnet/roslyn/issues/10902">async任意戻り値</a>の試験実装してる</li>
<li>ashmind (TryRoslyn作ってる人)が、そのLucianの個人リポジトリのブランチをTryRoslynに追加してくれた</li>
<li>Lucian、<a href="http://tryroslyn.azurewebsites.net/#b:ljw1004-features-async-return/K4Zwlgdg5gBAygTxAFwKYFsDcAoUlaIoYB0AwgPYA2lqAxsmORCMQOKoSoBOYtOe0eEjTpiAETABDKBHIpeIfuEGERxAErAIDdKjLl0ABzA0ucbgDdeqRbmUFhJTdrC7iASW3dyh81yu0Nkr4QkSiACoAFlyokgAm+MThkiAA1rbYhsAARpS8MLSUKSAwYhjk2ADe2DC1MFm5+SiSDLQwKQgQbQBqkpTAqMlpADyQyAB8pahFCAAUYzBx05IIAJQ1ddV12zBDqTDIMAC8MBDA1Dg7dWAAZjCzSzMwkwAMqwfHuymp4stzjytVpcrjBbvcAQhnjA3u0AO6SMCHZDAq4xZDALgQRZ/FEwAC+2AJ2Agkl0IEMkkCoTUzh0egoRhM3D8ARsVQ2tQaeTahWKXzSeVSqAAgshkDxssA0DAAFwwUXisCStAcmBbEFc/J7QUisUSqWoWbhBCGVAwSUmJZcY2m96VfGqglEklkilU1QkKIxeKJPYgdnbADa2rAQtmyBNqHIN1mvX6g2+AFlUMhIuQ4gAhYCW7jDcarVYAXVVmraKC4wHoMDjAz2w3C6hs5wmspg7gAogBHYAtSS5VDDGsJkYNpuUCbjVXqq4Aehn8urfVr3xgacocRKACpUIjItxN+0YBYl2aAPoxEDNgA0ME35C4B8kBxXp+Q32IMAAcuRDtkf5FiFVbY512PdQSWJ8wBKVMWlBO5EQAchKWgmHLSs0DiGAACtQEOWFdwOMDj3jG9EXaCxyDADdCLNPdJEMdpqHIWgWkYLFo0PPZAJBUEvExPoYG9OImEoSE61HS9x0mV9vlxbYxm4ElKEE2JhIgUTdkbSTDnPMdkSAupS0XeM9iNLTmxU7S7RgXTtM+C9m0wGy3zST4zguB0eKModTPE8ypOfNJrJk1yThc1InNsiyTiWG5JGbMy9KBWowVmEL9iOE53Mod5Uy4chYVOVBCuFLgoGAXRtE/c5KHbAAPQJDAYJhZhdKMY3CgsnIJLycm5GBmlaUEjG5MifG4Fp72M5cR38iYjW+es5smTrjkmThCp8xaJObcZw2+IEDM5PqmjfIbXEMUbDnGrhJq4abh1SJa9L2nbx0s5t3iOdbioevyXtmBzx0O3rGjacgLG4Hgll4w52GQAAJFJIgoJZZi+6TwpgABCLKapgAB+Zz33hpGQBR9NDXeOUove3HTnxonaeQNgUzJim0ep6E5MMk7wchrhobNP8qBgLse0oEBZnIbIsLoa7ZYxmAZaw0ESi22aXpgAAybWxe7PopdjE9/u0/MVZBjU+fNchRfFw3jZM7bluV1NuCV9Kcbx6gYAAH19129y4YhPfp7LCeJ0KTn/bgQ6xuV7byCMGQpGIuGes3fji5tiETqXmZvGPg+Zy2riMwb8hF5Sbru44jkdmanrelsaBuZAbw1puXZ4KBImQJXW5ZvPAbAXv+5546wYGs7K9t6vTVu5AptxhvHoz3aYEHjuTedrWe77pXscH3ODclkex9LnYjNNjfhRAUyPaxgmia4gAxfL0DmtKgfHo76mtqubYQApxoBhNakcMre2Uv7CBHhgEGEuimVAcQJ7/ynoA9w8CRpILiHASsgQQAgBuDVSE30IF1wZj7GB6ViBwDOqAChew6EtFABoSQEBwjkBASmNiqCjIYJAK/eK45kHgNDlAnWesaGYKEc2ZBfCAFzyAaQdhgQaCYTIeIyhyldawMwSoro0x5F/2vnNGAZjNFY0ytoiOzNWw0PhsKeEiJuDo1ZsgL+l9tjeR3mkJxCI0Dp2bpMRxzjAno3ARtP63x/EuKCctcMkQoJeN5lPCgEAbijwxMgzusS3z9nXgFdJmTyoxDybMQBKEXBnFQAAeQgCopq2S4jpLQHVfukTfrFKyTEOIuSwl9hoIU+aqYoI3iqQwGp9TGnol6a01A7S5QTMgAMaZ9FZnIPme0lJk9+oQyhlRM05YQicLoTwaAETLErmseHJmP8kjkDOfgCJNNwq0PoSUaxTCPlsI4VwhBoC2K2LeXNB5TyLlcxocw9ELBTmKghbiJ02BiSkhsG6M0HpRC0lcPSBBTIzCWGsP6ac08KxVk7smVM6Ysw5niS9Kcf8QJRCguabM65uAFCYG+SAW4dxuwfO0LEd9Oi0D2JStMmY2VWhvHeAVT57mMvnKKGiMB0AGA4IcEA6qmBmjRDwVAkMSiIhKHsG8MFkBIRgLCPcWJYRmhQtQeiIAzRLxVd6ZSwquhipTBKml7KuCKsFZhRC0FviF3ujhFAMBQAurAgqniCl+IepACK71VLJW0uGZjb4fqrROUTUpG2otWA/lzdwVBBaBLNxsj/fNfFC2AJLR4vSOATHWwrj0XxqRxXUqlbmYJMBSDejQJcn6m0u09ozf6rN6MFFTwolReAb4uDIHrNC1AiZKRJM4HtGIdxwjrs3bQbdRyzobq3ZAVA7xrXcDNAes9R6T2tncJ62gh6L2cD/iSnig1z3HsvcQRM+zPwLOQLOv+PUrbzsophcwyB33/s4LMF9KaugIafb+x9l71g8W/SCdszBsl7DLVwcDPFtjpRI7QlM6HL2zEwx+q9TkQLoFwuaM0kBCjACWMGu46BIQWn9WrQ8aF6BOVY1G7IZoDCIjAWCfjrLaXCafLyQhEG23QcXXBr+1af44ZBHhq4qUm0kfeJRvtwdtN6UBklVB2xpjOprXpeyLa/7bCbRYg4FZUCoMg2Xa2C7YMpnqo1ZqEBZghdQE1IFCzQtsX01cQzOwCOXhiMRizZHyO1HM7S6jyBIvRZarFqLYWdmeQ1DwY80pAti0I2lnNGWEs7CS/JO4sxsYmYs5ImAHmkqEXyoVKJnhiJUVqQvViTACthcy1l1KHXS0WbM+FEjnxX1pt9RZrNZBh1Uzs3UTrSmwred8xp/qncs38lSF+tzdQoAphu7UFrIJjM/jMbo+byBTMqVmViKJ53gnf1sw95LdXHokZm1luoaIMS/d+v9hJOX/VJAOnt2ofmdhElBv1GreTpkApwfWPJ3Abz3paH+k9u7UD7qJ/dSQYTicqX3bRzg08ydYc4NeoOd6afPu/AwG4CBuFhatVz3YzOzRyhQyK8X13Ie1dS2DxrqOIFUdxw0/HGEbN3DpwEhne7WdoHZ0x9TWP8g47CQAVWYJIG4dT1fYIwoT+nXASfi8p9T53cJdcu8Z2Lh9jGDfk+wyL29uweeS6HYiXgfQ+e3EFxroFN6Yh+7ZwHyXr6Ze4eBylojDXaUQ54ojq0xA8lW5ADbu3QvkFa693Em8+uGOIeNzxdHmPUn9VE4cfp3uLsR54K0GPP449C7YgyrylWycqXiCJSE8OtanmIgMCt9aBLd7iavG+AVF9XrVDZbfnxt/dVO7PUW+iNeiM0dvuBVeUHH7aNW+GnjwFpSv57G5NV3hM1fz/exr+3mhO9zcUf2s2SjvyPBgxgDxwd2r2FHoCBWWTOAmwgA9ivzvgfn0AyR6RFDCVmAQNWQaXWWaS2WQDlHFAGFWHcRpzcSgMQU1zwKQLKyMhqzLwrxoNARgLgKYE5WqR7FKzEVQPvm+DcW6VKWwICVwK5RWUr0ILmS5VA1IO8woIAPXwoJYNtzYJwQkJ4IYMRWRW8XbTIKrBEOaTX3ySGWCTHwqzACq11VUhn2iU1jNj3xPD4Qn2lCEnsMAVPDwOkKaVkK8HaWX0CULWMN6VMMGUNDnycO3xvEqUkKmQIL8M2TkO2V3wXxPAPxcJsh8LWSSJaRSMOBOByMSI2XyICORHK38zSSYBKRMK7R52UPCSViiVCJyXqOdxfxPBvG8PiPwJmSIIKMYIMLJUOFaL6XaO92fUjwH0oFjwFxHyYFl0h0MDcNsOn3Ulny7Qu3SPjGVxWOsMnw8I2KLWUh6J4N8NKOIOV0rWUjGNMNcSiI3hiJOO4MmT6JkOSPKOCn3xOEP2yN6IuIGPKM+GKP6P8LaQqPR1NzaAERv34JPGv3P1vzl1MWc2AO0lHWcPjDjmuQkS/wRLsRpj/xJhTCoKUJTE8T2ICwgI0M11gOF3oL4MvwRLQKEIoNaPKTOLeMBPBNA3JOQDJOIFpOr0ZPiypM00wjUMryRNmHpPgN6IYPhOxNZLSGEJqKwM5NBI+LKIhP5MFKlOFLiC0LeJ0JNzqCdCAA===">早速利用</a></li>
</ul>
<p>みたいな感じになってた。</p>
 ]]></description>
				<pubDate>Sun, 29 May 2016 05:01:33 +0900</pubDate>
			</item>
			<item>
				<title>2進数リテラルと数字区切り文字</title>
				<link>http://ufcpp.net/blog/2016/5/cs7binaryliterals/</link>
				<description><![CDATA[ <h2>C# 7思い出話</h2>
<p><a href="http://ufcpp.net/study/csharp/">C# によるプログラミング入門</a>に、ちらほらとC# 7の話題を書き始めたわけですが。</p>
<p>まあ、入門なんで仕様として固まったものだけを書いていくつもりです。ある程度固まりそうな段階まで書かないし、結局予定から漏れたものは修正したり。</p>
<p>一方で、その仕様が固まるまでにあった流れなんかも、ブログに残しといてもいいかなぁとか思ったり。</p>
<p>ってことで、「C# 7思い出話」なんていうカテゴリー付けて、ブログでも書いてみようというのが今回の話。
さしあたって、今、<a href="http://ufcpp.net/study/csharp/">入門</a>に書いたのが、</p>
<ul>
<li><a href="http://ufcpp.net/study/csharp/start/stnumber/#binary">2進数リテラル</a> (binary literals)</li>
<li><a href="http://ufcpp.net/study/csharp/start/stnumber/#digit-separator">数字区切り文字</a> (digit separators)</li>
</ul>
<p>の2つなので、今日はこの2つ。</p>
<h2>2進数リテラルと数字区切り文字</h2>
<p>こういう機能。</p>
<pre class="source" title="digit separators">
<code><reserved></span><span class="reserved">var</span> million = 1_000_000;
<span class="reserved">var</span> abcd = 0b1010_1011_1100_1101; <span class="comment">// 特に2進数リテラルで有用</span>
<span class="reserved">var</span> abcd2 = 0xab_cd;              <span class="comment">// 16進数リテラルにも使える</span>
<span class="reserved">var</span> x = 1.123_456_789;            <span class="comment">// 浮動小数点数リテラルにも使える</span>
</code></pre>
<p>2進数リテラルと数字区切り文字の2つはセットですね。
2進数って普通に書いたらむちゃくちゃ大きな桁数になりますし。
そりゃ、区切らないと読めた代物じゃない。</p>
<p>この2つの機能、「C# 7」としては「気が付いたらいつの間にか実装があった」って感じです。
特に「実装したよ」アナウンスもなく、pull-requestも見かけず。</p>
<p>そもそも、「<a href="https://github.com/dotnet/roslyn/issues/98">C# 7の最初の設計ミーティング</a>」でちょこっと「ページ内検索してみたら確かに書かれてる」程度の地味な取り上げられ方してただけ。機能的にも小さなものなので、提案ページもすごく簡素。</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/issues/215">Proposal: Binary literals #215</a></li>
</ul>
<p>それも当然でして、この機能はC# 6の頃からあったから。
要するに、「C# 6の頃から試験的な実装あったけど、結局C# 6には入れなった」というもの。
仕様的に何か問題があったわけでもなくて、単純に「優先度低、スケジュール的に後回し」。
という話が、今稼働してる<a href="https://github.com/dotnet/roslyn">GitHubのリポジトリ</a>じゃなくて、昔懐かし<a href="https://roslyn.codeplex.com/">CodePlex</a>時代にありました。</p>
<p>まあ、こういう、低コスト・低リターン機能は後回しになりがち。</p>
<p>実装するのは低コストと言っても、仕様的に問題ないかをよく考えたり、実際試してみる期間を設けるのはそれなりに大変です。
CodePlex上で、以下のようなディスカッションがあった記憶があります。</p>
<ul>
<li>区切り文字は <code>_</code> でいいの？</li>
<li>
<code>1010 1100</code>みたいにスペースで区切らせてよ
<ul>
<li>それは字句解析的に面倒で、コストかかりすぎる</li>
</ul>
</li>
<li>
8進数リテラルも入れてよ
<ul>
<li>
あっても使わないだろ、実際
<ul>
<li>chmodで使うよ</li>
</ul>
</li>
<li>C言語の<code>0</code>始まりは紛らわしいし、octalだからって<code>0o</code> (ゼロ、オー)も0とoが区別つきにくいし</li>
</ul>
</li>
<li>そもそも、16進数リテラルの<code>0x</code>もなんなの、Xって。hexの3文字目って</li>
</ul>
<p>簡単な機能であっても、なかなかめんどくさい感じの話に。</p>
 ]]></description>
				<pubDate>Mon, 23 May 2016 15:40:39 +0900</pubDate>
			</item>
			<item>
				<title>【開催報告】 //build/ 振り返り勉強会</title>
				<link>http://ufcpp.net/blog/2016/5/csugbuild2016/</link>
				<description><![CDATA[ <p>5/21(土)に勉強会を開いてました。
今回はまどすた(旧めとべや)との共同開催で、//build/の振り返りでした。</p>
<ul>
<li><a href="https://csugjp.doorkeeper.jp/events/43951">C#ユーザー会 //build/ 2016振り返り 勉強会</a></li>
<li><a href="https://roommetro.doorkeeper.jp/events/44062">まどすた #1 ～ //build/ 2016 振り返り</a></li>
</ul>
<p>以下、当日資料の一覧です。</p>
<h2>ルームA (サーバー部屋)</h2>
<h3>//build/ まとめ(サーバー編)</h3>
<iframe src="//www.slideshare.net/slideshow/embed_code/key/JtQHA2hwcsih8o" width="595" height="485" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe> <div style="margin-bottom:5px"> <strong> <a href="//www.slideshare.net/kamebuchi/c-build" title="C#ユーザー会 //build/ まとめ（サーバー編）" target="_blank">C#ユーザー会 //build/ まとめ（サーバー編）</a> </strong> from <strong><a href="//www.slideshare.net/kamebuchi" target="_blank">Keiji Kamebuchi</a></strong> </div>
<h3>祝GA、 Service Fabric 概要</h3>
<iframe src="//www.slideshare.net/slideshow/embed_code/key/vWa8ICw7CDtqvB" width="595" height="485" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe> <div style="margin-bottom:5px"> <strong> <a href="//www.slideshare.net/takekazuomi/ga-service-fabric" title="祝GA、 Service Fabric 概要" target="_blank">祝GA、 Service Fabric 概要</a> </strong> from <strong><a href="//www.slideshare.net/takekazuomi" target="_blank">Takekazu Omi</a></strong> </div>
<h3>Bot FrameworkでBot入門</h3>
<div style="width: 608px; max-width: 100%; margin-bottom:5px;"><a href="https://docs.com/yoshino-tsubasa/8904/botframeworkbot" title="BotFrameworkでBot入門" target="_blank" style="font-family: 'Segoe UI'">BotFrameworkでBot入門</a><span style="font-family: 'Segoe UI Light'">—</span><a href="https://docs.com/yoshino-tsubasa" target="_blank" style="font-family: 'Segoe UI'">Yoshino Tsubasa</a></div><iframe src="https://docs.com/d/embed/D25193848-0619-2834-9490-002072873048%7eM5e5f8353-58a2-13b7-4be8-e5e1ca5057ff" frameborder="0" scrolling="no" width="608px" height="378px" style="max-width:100%" allowfullscreen="False"></iframe>
<h3>Introduction to Azure Functions</h3>
<div style="width: 608px; max-width: 100%; margin-bottom:5px;"><a href="https://docs.com/tony-tonykun/2037/introduction-to-azure-functions" title="Introduction to Azure Functions" target="_blank" style="font-family: 'Segoe UI'">Introduction to Azure Functions</a><span style="font-family: 'Segoe UI Light'">—</span><a href="https://docs.com/tony-tonykun" target="_blank" style="font-family: 'Segoe UI'">Tony TonyKun</a></div><iframe src="https://docs.com/d/embed/D25193848-2840-2633-3920-000812519953%7eMecc3d68a-7794-131d-56c9-8c91dec1101f" frameborder="0" scrolling="no" width="608px" height="378px" style="max-width:100%" allowfullscreen="False"></iframe>
<h3>Bash on Ubuntu on Windows、ちょっとだけWindows Subsystem for Linux</h3>
<div>
<script async class="speakerdeck-embed" data-id="a21ba8ebc38942fd88c88f6fe905cbf7" data-ratio="1.77777777777778" src="//speakerdeck.com/assets/embed.js"></script>
</div>
<h3>C# 7</h3>
<div style="width: 608px; max-width: 100%; margin-bottom:5px;"><a href="https://docs.com/xin9le/6693/c-7-new-features" title="C# 7 New Features" target="_blank" style="font-family: 'Segoe UI'">C# 7 New Features</a><span style="font-family: 'Segoe UI Light'">—</span><a href="https://docs.com/xin9le" target="_blank" style="font-family: 'Segoe UI'">Takaaki Suzuki</a><a style="float: right; margin-bottom:5px; font-family: 'Segoe UI'" href="https://docs.com/xin9le/6693/c-7-new-features" target="_blank">Docs.com</a></div><iframe src="https://docs.com/d/embed/D25193845-4117-4604-8720-000764978706%7eM6e212294-6895-8c92-323d-377eb21dfba2" frameborder="0" scrolling="no" width="608px" height="377px" style="max-width:100%" allowfullscreen="False"></iframe>
<h2>ルームB (クライアント部屋)</h2>
<h3>//build/ 2016現地で感じたクライアント開発の潮流</h3>
<h3>Holo World ～ はじめの一歩 ～</h3>
<div style="width: 608px; max-width: 100%; margin-bottom:5px;"><a href="https://docs.com/wakiya-norinao/2872/2016-05-21-holo-world" title="2016.05.21 - Holo World ~ はじめの一歩" target="_blank" style="font-family: 'Segoe UI'">2016.05.21 - Holo World ~ はじめの一歩</a><span style="font-family: 'Segoe UI Light'">—</span><a href="https://docs.com/wakiya-norinao" target="_blank" style="font-family: 'Segoe UI'">Wakiya Norinao</a></div><iframe src="https://docs.com/d/embed/D25193848-5383-0870-8260-000050431523%7eMf7cf0008-5ea3-f851-9be3-411117c0765c" frameborder="0" scrolling="no" width="608px" height="378px" style="max-width:100%" allowfullscreen="False"></iframe>
<h3>Build/Evolve 振り返り</h3>
<div>
<script async class="speakerdeck-embed" data-id="a310fb76220b4df889315bc39632e7d8" data-ratio="1.77777777777778" src="//speakerdeck.com/assets/embed.js"></script>
</div>
<h3>デスクトップ アプリがこの先生きのこるには</h3>
<p><a href="http://grabacr.net/archives/6811">デスクトップ アプリの生存戦略 (Desktop App Converter)</a></p>
<div>
<script async class="speakerdeck-embed" data-id="27b8ed9f16104ccaa98b2132e2e5306d" data-ratio="1.77777777777778" src="//speakerdeck.com/assets/embed.js"></script>
</div>
<h3>VR元年のゲーム開発</h3>
<h3>Cutting Edge!</h3>
<div>
<script async class="speakerdeck-embed" data-id="e8cb6a9a63a3476680fbf23a739e5e0a" data-ratio="1.77777777777778" src="//speakerdeck.com/assets/embed.js"></script>
</div> ]]></description>
				<pubDate>Sun, 22 May 2016 15:53:29 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 5/12</title>
				<link>http://ufcpp.net/blog/2016/5/pickuproslyn0512/</link>
				<description><![CDATA[ <h2>なんでも拡張</h2>
<ul>
<li><a href="https://github.com/dotnet/roslyn/issues/11159">Language Feature: Extension Everything #11159</a></li>
</ul>
<p>拡張メソッドは便利な構文なわけですが、インスタンス メソッドしか拡張できないのが残念なところです。拡張プロパティとかも作りたいことがあるし、静的な拡張(静的メソッドも既存のクラスに対して追加したように見える構文)もほしかったりします。という、なんでも拡張できる構文の案。</p>
<p>今のところ、以下のような構文で検討中。</p>
<pre class="source" title="">
<code><span class="reserved">extension class</span> <span class="type">クラス名</span> : <span class="type">拡張したい型</span>
{
    <span class="comment">// ここにメンバーは、拡張したい型の拡張メソッド、拡張プロパティなどになる</span>
}
</code></pre>
<h2>C# Design Notes (タプル型関連 再び)</h2>
<ul>
<li><a href="https://github.com/dotnet/roslyn/issues/11205">C# Design Notes for May 3-4, 2016 #11205</a></li>
</ul>
<p><a href="http://ufcpp.net/blog/2016/5/pickuproslyn0504/">前回</a>の<a href="https://github.com/dotnet/roslyn/issues/11031">C# Design Notes for Apr 12-22, 2016</a>に引き続き、タプル型関連。</p>
<ul>
<li>
分解
<ul>
<li><code>(x, y) = tuple;</code> みたいなのを、<code>tuple.Deconstruct(out x, out y);</code> みたいなメソッド呼び出しとして解釈したい</li>
<li>タプル型専用の特別な構文にしないために、インスタンス or 拡張メソッドを通したい</li>
<li>ちょっと前まで<code>GetValue</code>って名前を検討してたけど、一般的過ぎてすでに使われてそうなので、<code>Deconstruct</code>メソッドにする</li>
<li>要素の値を返すのはout引数にする。タプル型を分解するのにタプル型を返すわけにもいかないので</li>
</ul>
</li>
<li>
switchステートメントでの変換
<ul>
<li>既存のswitchだとintとかstringしか受け付けないので、intとかへの暗黙的型変換できる型は変換結果で解釈されてた</li>
<li>破壊的変更にならないようにするために、暗黙的型変換を定義した型は、今後も変換結果で解釈する</li>
<li>なので、そういう型(例えばintへの暗黙的型変換を持った<code>Const</code>型)は <code>case Const(int i):</code> みたいなcaseにマッチしない(<code>case 0:</code>とかにはマッチする)</li>
<li>あんまり起きない状況だし、破壊的変更を避ける方を優先</li>
</ul>
</li>
<li>
タプル型間の変換
<ul>
<li>「要素数が一致していて、各要素が暗黙的型変換できるなら、タプル型間でも暗黙的型変換できる」ってルールにするっぽい</li>
</ul>
</li>
<li>
タプル風のインスタンス生成
<ul>
<li>任意の型に対して、左辺から型が推論できるなら、<code>new (x, y)</code>みたいな書き方でインスタンス生成できるようにする</li>
</ul>
</li>
</ul>
<p>最後の「タプル風インスタンス生成」はちょっと補足。</p>
<p>元々の発想は、「分解の構文を<code>Deconstruct</code>メソッドを通すことで汎用化したんだし、構築の構文も汎用化すべき」というもの。タプル構築と、コンストラクター呼び出しを紐づけたいということになります。</p>
<p>が、例えば、その発想で行くと、以下のように、なんか直観にそぐわない「タプル型リテラルからの構築」ができてしまう。</p>
<pre class="source" title="">
<code><type></span><span class="type">Dictionary</span>&lt;<span class="reserved">int</span>, <span class="reserved">string</span>&gt; d = (16, <span class="type">EqualityComparer</span>&lt;<span class="reserved">int</span>&gt;.Default); <span class="comment">// さすがにこれは気持ち悪い</span>
</code></pre>
<p>代わりと言ってはなんだけど、以下のような、<code>new</code>の後ろの型の省略を認めようという感じになってるみたい。</p>
<pre class="source" title="">
<code><type></span><span class="type">Point</span> p = <span class="reserved">new</span> (3, 4); <span class="comment">// new Point(3, 4) と同じ</span>
<span class="type">List</span>&lt;<span class="reserved">string</span>&gt; l1 = <span class="reserved">new</span> (10); <span class="comment">// 引数0個 or 1個でも大丈夫</span>
<span class="type">List</span>&lt;<span class="reserved">int</span>&gt; l2 = <span class="reserved">new</span> () { 3, 4, 5 }; <span class="comment">// コレクション初期化子との併用もできるけど、() は省略できない</span>
</code></pre>
<p>要するに、結局、左辺からの型推論みたいな構文を追加することになりそう。</p>
 ]]></description>
				<pubDate>Wed, 11 May 2016 22:54:29 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 5/4</title>
				<link>http://ufcpp.net/blog/2016/5/pickuproslyn0504/</link>
				<description><![CDATA[ <p>4月に紹介した<a href="https://github.com/dotnet/roslyn/blob/master/docs/Language%20Feature%20Status.md">Language Feature Status</a>、だんだんはっきりとC# 7、VB 15に入りそうな範囲が結構絞られてきた感じ。</p>
<p>最近は、タプル型がらみに注力してる感じがします。</p>
<h2>パターン マッチングも部分的に実装</h2>
<ul>
<li><a href="https://github.com/dotnet/roslyn/issues/10866">Split the features/patterns branch into two branches for subfeatures in/out C# 7 #10866</a></li>
</ul>
<p>これまで出てたアイディア全部を一気にC# 7に入れるんじゃなくて、将来的な拡張を阻害しないように気を付けつつ、部分的に実装しようという感じになってる様子。</p>
<p>上記リンクのうち、「Part 1 (targeting future)」になってる方がC# 7に入りそうなやつで、「Part 2 (to remain in features/patterns)」に入ってる方がそれより後のバージョンになりそうなもの。</p>
<p>要するに、C# 7としては、いったん、単純な型による分岐だけを実装するみたい。以下のものはその後の予定。</p>
<ul>
<li>再帰的なオブジェクト分解の構文</li>
<li>let ステートメント</li>
<li>match 式</li>
<li>throw 式</li>
</ul>
<h2>C# Design Notes (タプル型関連)</h2>
<ul>
<li><a href="https://github.com/dotnet/roslyn/issues/11031">C# Design Notes for Apr 12-22, 2016 #11031</a></li>
</ul>
<p>4月中にあったC# Designミーティングの議事録。タプル型関連の議題が多かったみたいです(あと、out varの話が少し)。以下のような内容。</p>
<ul>
<li>
<code>ValueTuple</code>以外の型
<ul>
<li>C#のタプル型の実装に使われる<code>ValueTuple</code>構造体の他に、既存の<code>Tuple</code>クラスとか、あと、<code>KeyValuePair</code>なんかも性質としてはタプルっぽい。これらを統一的に扱いたい</li>
</ul>
</li>
<li>
タプル型の分解(代入、宣言、パターン マッチング)用の構文案
<ul>
<li><code>(int x, int y) = Get();</code>的なのか、<code>(int, int) (x, y) = Get();</code> 的なのか、いくつか候補あり。今のところ前者が有力</li>
</ul>
</li>
<li>
<code>(byte, short)</code>から<code>(int, int)</code>みたいな、メンバー単位で暗黙の型変換がある場合の、タプル型間の変換
<ul>
<li>認める方向で検討中。ただ、コンパイラーが頑張ることになるし、C# 6と7でオーバーロード解決ルールとかが変わっちゃう問題がある</li>
</ul>
</li>
<li>
(C#の構文糖衣としての)タプル型と、構造体の<code>ValueType</code>
<ul>
<li>null許容型が<code>int?</code>でも<code>Nullable&lt;int&gt;</code>でも使えるように、タプル型も<code>(int, int)</code>でも<code>ValueTuple&lt;int, int&gt;</code>でも使えるようにしたい</li>
</ul>
</li>
<li>パターン マッチングとの兼ね合い</li>
</ul>
<p>ちなみに、その<code>ValueTuple</code>構造体ですが、ついに<a href="https://github.com/dotnet/corefx">corefx</a>の方に入ったみたい。</p>
<ul>
<li><a href="https://github.com/dotnet/corefx/blob/master/src/System.Threading.Tasks.Extensions/src/System/Threading/Tasks/ValueTask.cs">ValueTask.cs</a></li>
</ul>
<p>(ちょっと前までは、<a href="https://github.com/dotnet/roslyn">roslyn</a>リポジトリ内でだけ実装してた)</p>
<h2>非同期メソッドの戻り値を任意の型に</h2>
<ul>
<li><a href="https://github.com/ljw1004/roslyn/blob/features/async-return/docs/specs/feature%20-%20arbitrary%20async%20returns.md">C# feature proposal: arbitrary async returns</a></li>
<li><a href="https://github.com/ljw1004/roslyn/blob/features/async-return/docs/specs/feature%20-%20arbitrary%20async%20returns%20-%20discussion.md">C# design rationale and alternatives: arbitrary async returns</a></li>
<li><a href="https://github.com/dotnet/roslyn/issues/10902">Discussion thread for arbitrary async returns #10902</a></li>
</ul>
<p>今、<code>Task</code>クラスしか返せない非同期メソッドに、任意の型を返せるように拡張したいという話。</p>
<p>あと、非同期ストリーム(<code>await</code>と<code>yield</code>を両方含めて、<code>IObservable</code>とか<code>IAsyncEnumerable</code>のような戻り値を返せるもの)の実装もまとめてディスカッション中。</p>
<p>これは、<a href="https://github.com/dotnet/roslyn/blob/master/docs/Language%20Feature%20Status.md">Language Feature Status</a>の「(C# 7.0 and VB 15) + 1」にすら並んでないんで、さらにもうちょっと先になりそうなんですかね。</p>
 ]]></description>
				<pubDate>Wed, 04 May 2016 09:07:34 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 4/10</title>
				<link>http://ufcpp.net/blog/2016/4/pickuproslyn0410/</link>
				<description><![CDATA[ <p>「C# 7」に入る範囲がそろそろ決まってきた感じ。</p>
<h2>C# Design Notes for Apr 6, 2016 (Tuples, Recursive patterns)</h2>
<p>久々に言語デザインミーティングの議事録が。</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/issues/10429">C# Design Notes for Apr 6, 2016 #10429</a></li>
</ul>
<p>タプル型と、再帰的なパターン(位置指定パターン・プロパティ パターン)の詳細がだいぶ決まってきたっぽい。</p>
<p>タプル型は↓こんな感じ。</p>
<ul>
<li>
メンバーの数と型が一致していたら、名前は無視して同一視する(代入可能)
<ul>
<li>box化・unboxしても同様の変換ルール適用可能</li>
<li>メンバーが int → long みたいな暗黙的型変換できる場合でも、タプル型の自動変換はいったんしないことにする(将来はわからない)</li>
</ul>
</li>
<li>無名タプルも作れる(メンバー名指定なし)</li>
<li>匿名型の <code>new { p.X, p.Y }</code>みたいに、名前の射影(X, Yという名前を引き継ぐ)あり</li>
<li>タプル型に対する拡張メソッドも作れる</li>
<li>タプル型引数の規定値も指定できるようにしたいけど、そのためには何か新しい属性が必要になる(ので、いったん据え置きになりそう？)</li>
<li>
0-tuples, 1-tuplesも検討したい
<ul>
<li>それぞれ、C#チーム内ではnuples, wonples (null+tuple, one+tupleの造語？)と呼んでるみたい</li>
<li>nuplesは、要するに「ユニット型」。<code>()</code>で書き表せそう</li>
<li>wonplesが難しそう。<code>(Type)</code>も<code>(value)</code>も現在のC#で有効な構文になっちゃってるんで</li>
</ul>
</li>
<li>タプル型戻り値を、out引数みたいな感じで、メンバー名で代入可能にはしない。return使え</li>
</ul>
<p>再帰的なパターンの方は、もしかしたら全部やC# 7ではやらないかも。段階的に便利にしていくのでもいいだろうし、後からの追加に耐えれるようにC# ７を作れそう、とのこと。</p>
<h2>Language Feature Status</h2>
<p>C# 7として出したいもの、だいぶ絞られてきたみたい。状況のまとめページができてます。</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/blob/master/docs/Language%20Feature%20Status.md">Language Feature Status</a></li>
</ul>
<p>概ね、こないだのbuildでデモでプロトタイプが動いてたものに絞った感じ。リリース時期が大まかには決まってきたのかな？この絞り方(今ある程度動いてるものだけをまず出す)の感じからすると、Windows 10のレッドストーンと同時期？</p>
<h2>Source Generators</h2>
<p>メタプログラミングがらみ、ソースコード ジェネレーターのドキュメントができてた。</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/blob/features/generators/docs/features/generators.md">Source Generators</a></li>
</ul>
<p>これはほんと一刻も早く試したい…</p>
<h2>C# as a High-Performance Language</h2>
<p>C# vNextのパフォーマンス改善系の提案まとめページが。</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/issues/10378">State / Direction of C# as a High-Performance Language #10378</a></li>
</ul>
<p><a href="http://www.buildinsider.net/column/iwanaga-nobuyuki">Build Insiderでやってる連載</a>の次回のネタ、パフォーマンスにしようかなぁ。</p>
<p>Roslyn自体がパフォーマンス面に関して相当シビアだったり、ゲーム方面でC#が注目されてたり、.NET Coreがベンチマーク向上を頑張ってる真っ最中だったり、今、結構こういう機能が求められています。</p>
 ]]></description>
				<pubDate>Sun, 10 Apr 2016 10:26:59 +0900</pubDate>
			</item>
			<item>
				<title>Visual Studio 2015 Update 2がRTM ＆ Visual Studio &quot;15&quot; Preview</title>
				<link>http://ufcpp.net/blog/2016/3/vs-updates-0331/</link>
				<description><![CDATA[ <p>昨日は夜更かししていたわけですが。</p>
<ul>
<li><a href="http://ascii.jp/elem/000/001/139/1139982/">Build 2016 生中継</a></li>
</ul>
<p>なんか今回は「本来はWindowsのイベント」らしさがあり、ほんとにWindowsの話題ばっかり。
開発ツール系の話が初日キーノートに出てこないという。
内心「やべぇ、しゃべることねぇ」とかおびえながらのひな壇芸人やってました。
危うく、ただ<a href="https://twitter.com/ikeay">池澤あやか</a>さんに会いに行くだけの<a href="https://twitter.com/ufcpp/status/715261117929365504">ミーハー</a>になるところでした。</p>
<p>開発ツール系は2日目の今晩のキーノートで話すんですかね。確かに最近そういう構成になってること多い。前の方にコンシューマー受けするもの、後ろの方に開発系。</p>
<p>そして、キーノートでまったく触れられないまま、さらっとMSDNブログで公開されるVisual Studio。</p>
<ul>
<li>
<a href="https://blogs.msdn.microsoft.com/visualstudio/2016/03/30/visual-studio-2015-update-2-rtm/">Visual Studio 2015 Update 2 RTM</a>
<ul>
<li><a href="https://www.visualstudio.com/downloads/download-visual-studio-vs">Visual Studio ダウンロード ページ</a></li>
<li><a href="https://www.visualstudio.com/news/vs2015-update2-vs">Visual Studio 2015 Update 2 リリースノート</a></li>
</ul>
</li>
<li>
<a href="https://www.visualstudio.com/news/vs15-preview-vs">Visual Studio &quot;15&quot; Preview</a>
<ul>
<li><a href="https://www.visualstudio.com/downloads/visual-studio-next-downloads-vs">Visual Studio &quot;15&quot; Preview ダウンロード ページ</a></li>
<li><a href="https://www.visualstudio.com/news/vs15-preview-vs">Visual Studio &quot;15&quot; Preview リリースノート</a></li>
</ul>
</li>
<li><a href="https://blogs.msdn.microsoft.com/dotnet/2016/03/30/announcing-the-net-framework-4-6-2-preview/">Announcing the .NET Framework 4.6.2 Preview</a></li>
</ul>
<h2>Visual Studio 2015 Update 2</h2>
<p>そういえば、プレビュー版、RC版が出たときにあんまり取り上げてなかったなぁと。</p>
<p>C# に関連する新機能は4点ほど</p>
<ul>
<li>ソースコードを選択 → 右クリックメニューの「Execute in Interactive」から、C# Interactiveにコードを送れる</li>
<li>Add Using (using ディレクティブの追加)に対するあいまいマッチング</li>
<li>アナライザーAPIの性能改善</li>
<li>標準提供のリファクタリング機能にいくつかの新アクション</li>
</ul>
<p>上の2つは簡単に触れておこうかと。</p>
<h3>Execute in Interactive</h3>
<p>ソースコードの1部分の実行結果を今その場で知りたいときに便利。</p>
<p>ではあるんですが、これ、プロジェクトのコンテキストを取り込んでくれない(そのプロジェクト内で自分で定義した型は使えないし、参照してるライブラリもCV# Interactiveからは参照されない)ので微妙に不便。標準ライブラリ内のクラスしか使えないんですよね。「Json.NETのシリアライズ結果の挙動を知りたい！」とかもできない。計画上はNuGetパッケージの参照とかはC# Interactiveウィンドウ内からできるようにしたいって話があった気がするので、まあ、今後に期待ですかね。</p>
<h3>Add Using あいまいマッチング</h3>
<p>「usingディレクティブってソースコードの上部にしか書けないからうざい。今まで使ってなかった名前空間の型を新たに使いたくなった場合、いちいちに上に移動するのがめんどくさい。」という不満にこたえる「Add Using」機能ですが、これまでだとクラス名を正確に打たないと「Add Using」できなくて、微妙に不便でした。</p>
<p>というのも、IntelliSenseであれば、</p>
<ul>
<li>全部小文字で打っても補完でCamelCaseなメンバーを見つけられる</li>
<li>途中まで打てば補完で長い名前を打てる</li>
</ul>
<p>という機能があって、もうさぼり癖がついてるわけです、C#開発者は。
それが、「Add Using」したければクラス名を正確に全部書けとか、無理。</p>
<p>挙動を見てる感じ、</p>
<ul>
<li>全部小文字で打っても認識</li>
<li>
文字が1・2文字まで間違ってる/足りてない状態でも認識
<ul>
<li>単語の長さによるっぽい</li>
</ul>
</li>
</ul>
<p>という感じ。
streem(Stream)、dianostic（Diagnostics）とかそんなのがちゃんと補完されます。
スペルを正確に覚えるのが面倒なときに便利。
queueみたいな2文字違いどころじゃないレベルの単語が相手だと少々厳しいですが…</p>
<p><img src="/media/1069/smallcase.png" alt="全部小文字で打って、Add Using" /></p>
<h2>Visual Studio &quot;15&quot; Preview</h2>
<p>&quot;15&quot;はもちろん内部バージョンのことです。Visual Studio 2015が&quot;14&quot;。つまり、次期バージョンのプレビュー。</p>
<p>これまでだと、マイクロソフトの製品って2・3年サイクルでリリースしてました。直近のC#でも、2010でC# 4→2012でC# 5→2015でC# 6です。
最近徐々にリリースサイクルを縮めたがっているわけですが、なので、今年中のリリースが期待されます。</p>
<p>あと、インストーラーが2つあります。今まで通り、isoファイルで丸ごとの提供があるインストーラーと、「lightweight」なインストーラー。</p>
<p>C# 的には、まあ、<a href="https://github.com/dotnet/roslyn">GitHubのRoslynリポジトリ</a>を眺めてると、<a href="https://github.com/dotnet/roslyn/tree/future">futureブランチ</a>に結構C# 7の新機能がマージされだしておりまして、「おっ、ここまでは近々バイナリでのリリースがあるのかな」などと眺めておりました。</p>
<p>実際大体その通り。1・2週前のプルリクまではVS &quot;15&quot;に入った感じですね。</p>
<p>以下の機能が動きます。ただし、今、C#７の文法を試すにはちょっとしたトリック(条件コンパイルシンボルに <code>__DEMO__</code> を追加する)が必要になります。</p>
<ul>
<li>ローカル関数(nested local function)</li>
<li>パターン マッチング(pattern matching)の一部</li>
<li>ref戻り値/refローカル変数(ref returns/ref locals)</li>
<li>2進数リテラル(binary digit)、数値セパレーター(digit separator)</li>
</ul>
<p>(ちなみに、リリースノートに書かれてないやつも、GitHub上で実装っぽいものがあったものは一通り試しました。その結果、2進数リテラルが動いてることを確認。)</p>
<p>この3/31リリースのプレビュー版で動くC# 7コード、GitHubにサンプルを上げておきました。</p>
<ul>
<li><a href="https://github.com/ufcpp/UfcppSample/tree/master/Demo/Csharp7/201603">https://github.com/ufcpp/UfcppSample/tree/master/Demo/Csharp7/201603</a></li>
</ul>
<h3><strong>DEMO</strong> 条件シンボル</h3>
<p>今のところ、futureブランチにしかないような新文法は、コンパイラー オプションを追加しないと使えない状態になっています。
で、Visual Studio上からどうやってそのオプションを追加するの？という話なんですが…
追加できないです。対応追いついてないようで。</p>
<p>じゃあ、どうやって上記サンプルは動かしてるかというと、抜け道がありまして。
「プロジェクト設定で<code>__DEMO__</code>という名前の条件コンパイル シンボルを定義しておく」という、一時しのぎ感溢れる見事な対応。</p>
<p><img src="/media/1070/__demo__.png" alt="__DEMO__ 条件シンボル" /></p>
<p>名前通り、デモで見せるときに使ったんでしょうね。</p>
<h3>ローカル関数</h3>
<p>↓こんなやつ。</p>
<pre class="source" title="ローカル関数">
<code><reserved></span><span class="reserved">private</span> <span class="reserved">static</span> <span class="reserved">void</span> LocalFunctions()
{
    <span class="reserved">int</span> F(<span class="reserved">int</span> n) =&gt; n &gt;= 1 ? n * F(n - 1) : 1;
    <span class="type">Console</span>.WriteLine(F(5));
}
</code></pre>
<p>まあ、<code>public void X()</code>に対して<code>private void XInternal()</code>みたいなのを別途書くこと、たまにあったじゃないですか。
それが必要なくなります。</p>
<p>これまでも、ラムダ式を使えば似たようなことはできましたが、以下の点でローカル関数の方が有利になります。</p>
<ul>
<li>再帰呼び出しが素直に書ける</li>
<li>デリゲート変数への代入が省ける</li>
<li>
ローカル変数のキャプチャがちょっと賢い
<ul>
<li>ラムダ式: クラスのフィールドに昇格する。ヒープのアロケーションが発生</li>
<li>ローカル関数: 構造体のフィールドにして、ref引数で関数に渡される。ヒープ除け</li>
</ul>
</li>
</ul>
<h3>パターン マッチング(一部)</h3>
<p>パターン マッチング自体は、最近<a href="http://www.buildinsider.net/column/iwanaga-nobuyuki/004">Build Insiderに寄稿</a>したんでそちらを参照していただくとして。</p>
<p>このうち、位置指定パターンだけは未実装。
次回の記事で書く予定ですが、位置指定パターンだけはちょっと実装が面倒とういうか、
レコード型やタプル型など、他の新機能も合わせて詳細を詰めないといけないので、少し実装が後回しになっています。</p>
<p>まあ、型パターンだけでも使えれば結構便利なはず。</p>
<h3>ref戻り値</h3>
<p>↓こんな感じ。</p>
<pre class="source" title="">
<code><reserved></span><span class="reserved">struct</span> <span class="type">Buffer</span>&lt;<span class="type">T</span>&gt;
{
    <span class="reserved">public</span> <span class="reserved">int</span> BaseIndex { <span class="reserved">get</span>; }

    <span class="reserved">private</span> <span class="reserved">readonly</span> <span class="type">T</span>[] _array;

    <span class="reserved">public</span> Buffer(<span class="reserved">int</span> baseIndex, <span class="reserved">int</span> count)
    {
        BaseIndex = baseIndex;
        _array = <span class="reserved">new</span> <span class="type">T</span>[count];
    }

    <span class="reserved">public</span> <span class="reserved">ref</span> <span class="type">T</span> <span class="reserved">this</span>[<span class="reserved">int</span> index] =&gt; <span class="reserved">ref</span> _array[index - BaseIndex];
}
</code></pre>
<p>まあ、ほとんどの開発者は直接は使わなさそうですかね。
パフォーマンス改善に期待できる機能です。
ライブラリ作者がこれを使うことでパフォーマンスが上がり、間接的には全ての開発者への恩恵が期待されます。
というか、C# コンパイラー自信のパフォーマンス改善が結構見込めそう。</p>
<p>これに限らず、パフォーマンス改善系の機能追加はちらほら追加されていきそうな雰囲気です。</p>
<h3>2進数リテラル/数値セパレーター</h3>
<p>↓これは大変わかりやすく。</p>
<pre class="source" title="">
<code><reserved></span><span class="reserved">var</span> b = 0b1000_0001;
<span class="type">Console</span>.WriteLine(b);
</code></pre>
<p>こいつはC# 6の頃から新機能候補に挙がってましたし、結構前から実装済みだったはず。<a href="https://github.com/dotnet/corefx">CoreFx</a>の方のソースコード見てたらそこらじゅうですでに使われてたり。
前からあるから、今回リリースノートに書き忘れたのかなぁとか思ったり。
「そんなに強い関心があるわけじゃないけど実装が簡単だから実装済みです」、「<code>0b</code>でいいのかとか<code>_</code>でいいのかとか議論の余地もあるし、もう少し寝かせるか」みたいな立ち位置のはず。</p>
<h3>lightweightインストーラー</h3>
<p>全部の機能はiso版のこれまで通りのインストーラーでないとまだ使えないらしいですが。
それとは別に、今後に期待がかかるlightweightインストーラーってのが提供されました。</p>
<p>これまでの「webインストーラー」と何が違うかというと、</p>
<ul>
<li>
最小構成だと300MB程度でインストールできる
<ul>
<li>必要な機能は必要に応じて拡張マネージャーで入れる</li>
</ul>
</li>
<li>
どうも、レジストリを汚さないみたい
<ul>
<li>既存のVisual Studioを立ち上げっぱなしでもVS &quot;15&quot;をインストール可能</li>
<li>
1台に複数インストールとかもたぶんできる
<ul>
<li>プロジェクトごとに別の拡張入れた状態のVSを作るみたいなのもたぶん</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>という感じ。地味に、大きな変化だったり。</p>
 ]]></description>
				<pubDate>Thu, 31 Mar 2016 04:32:52 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 3/18</title>
				<link>http://ufcpp.net/blog/2016/3/pickuproslyn0318/</link>
				<description><![CDATA[ <h2>C# 7に取り込む範囲、ある程度決まったみたい</h2>
<p>作業リストが更新されてた。</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/issues/2136">C# 7 Work List of Features #2136</a></li>
</ul>
<p>前はあって今消えてるものは単に「7からは外す」という意味。
まだ最終決定でもないんで、ここからまた増減はあるはず。</p>
<p>個人的な印象としては、現状でもそこそこ動いているものだけ残してる感じ。
たぶん、「年に1回リリース」、つまり、今年中のC# 7リリースがかなり現実味ありそう。</p>
<p>ということで、まだちょっと検討が要りそうなものはリストから抜けました。
待ち遠しいけども先送られたのは「非同期シーケンス」と「非null参照型」あたりですかね。</p>
<ul>
<li>async sequences (<a href="https://github.com/dotnet/roslyn/issues/261">#261</a>, <a href="https://github.com/dotnet/roslyn/issues/5383">#5383</a>)</li>
<li>non-null reference type (<a href="https://github.com/dotnet/roslyn/issues/227">#227</a>, <a href="https://github.com/dotnet/roslyn/issues/7445">#7445</a>)</li>
</ul>
<h2>レコード型の仕様書</h2>
<p>レコード型の仕様書がやっとできてた。future ブランチにはマージ済み。</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/blob/future/docs/features/records.md">Records for C#</a></li>
</ul>
<h2>expression-bodied な set/get、コンストラクター</h2>
<p>set, get 個別に、<code>=&gt;</code> を使った短縮形のプロパティ定義を書けるようにしてほしいとか、そういう要望が前々から上がっていたわけですが。</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/pull/8594">Expression body syntax for accessors, ctor and finalize #8594</a></li>
<li><a href="https://github.com/dotnet/roslyn/issues/7881">Proposal: Expression bodied get and set methods #7881</a></li>
</ul>
<p>C# 6の時にも検討されたものの、「要望があるのはわかるけど、そこまで需要高くないし後回し」扱いされていたものです。</p>
<p>それに対して、C# チームの外から pull request が来て、C# チーム的にも「それをベースに実装するか」という流れになっている模様。</p>
<h2>サロゲートペア識別子対応</h2>
<p>日本人的に、ほしければ「Add your reaction」で +1 だけでもつけといた方がよさそうなものが。</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/issues/9731">Compiler does not correctly interpret surrogate pairs when used in an identifier #9731</a></li>
</ul>
<p>サロゲートペアになってる文字でも、文字カテゴリーが letter になってるんだったら識別子に使えるべきじゃないかという話。</p>
<p>要するに「𩸽」(ほっけ。U+29E3D)とかの話。</p>
<p>C# 的には、letter系のカテゴリーに含まれている文字を識別子に使えるという仕様になっています。
ただ、.NETが内部的に16ビット(UTF16)で文字列を持ってるせいで、サロゲートペアになってる文字はカテゴリーを正しく判定してもらえない。</p>
<p>要するに、以下のようなコードを実行すると、結果はSurrogateになります。</p>
<pre class="source" title="">
<code><reserved></span><span class="reserved">char</span>.GetUnicodeCategory(<span class="string">"𩸽"</span>[0])
</code></pre>
<p>とはいえ、以下のように、<code>char</code>じゃなくて<code>string</code>を受け付けて、サロゲートペアな文字でも使えるオーバーロードに書き直せばちゃんと判定できます。
𩸽の場合はOtherLetter。</p>
<pre class="source" title="">
<code><reserved></span><span class="reserved">char</span>.GetUnicodeCategory(<span class="string">"𩸽"</span>, 0)
</code></pre>
<p>ってことで、</p>
<ul>
<li>C# 実装なRoslyn的に、実は判定自体はできる</li>
<li>でも、2文字見ないといけなくなってそれなりにコンパイラーに負担が掛かる</li>
<li>
それで使えるようになる文字というと、日本語的には𩸽みたいなレアな文字
<ul>
<li>このissueページで言われてるのは「シュメール語の文字を使いたい」みたいな要望</li>
</ul>
</li>
</ul>
<p>という感じ。</p>
<p>それでも、この手の文字を識別子に使いたいですか？使いたいなら、reactionしておきましょう。</p>
 ]]></description>
				<pubDate>Fri, 18 Mar 2016 10:43:23 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップ Roslyn 3/3: タプル ベースのposition-to-propertyマッチ</title>
				<link>http://ufcpp.net/blog/2016/3/pickuproslyn0303/</link>
				<description><![CDATA[ <p><a href="http://ufcpp.net/blog/2016/3/pickuproslyn0301/">一昨日の</a>の補足。</p>
<p>先日は以下のようなLanguage Design Notesが出てたわけですが。</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/issues/9330">C# Design Notes - catch up edition, Feb 29, 2016 (deconstruction and immutable object creation) #9330</a></li>
</ul>
<p>コンストラクター引数とプロパティの名前の一致を見て、何番目の引数がどのプロパティに対応するかを調べる(position-to-propertyマッチする)方針を使おうという話。
もちろんいろんな対案あった中で、今、こういう方針に傾いてるという話なんですが、そういう過程抜きに「名前の一致を見る」の話だけしたので多少炎上中。</p>
<p>ということで、対案の1つ、<a href="http://www.buildinsider.net/column/iwanaga-nobuyuki/003">タプル</a>を使ったパターンの話も公開されました。</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/issues/9411">Proposal: Tuple-based construction and deconstruction of immutable types #9411</a></li>
</ul>
<p>以下のようなメソッドを用意することで、position-to-propertyマッチしようというもの。
拡張メソッドでもいいことにしておけば、既存のクラスの拡張もできます(ただし、その拡張メソッドを書くのは手動。大変めんどいはず)。</p>
<pre class="source" title="">
<code><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">public</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">class</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">Person</span>
{
  ...
  <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">public</span> (<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">string</span> FirstName, <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">string</span> LastName) <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">GetValues</span>() { ... }
  <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">public</span> Person <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">With</span>((<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">string</span> <span class="pl-smi" style="box-sizing: border-box; color: rgb(51, 51, 51);">FirstName</span>, <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">string</span> <span class="pl-smi" style="box-sizing: border-box; color: rgb(51, 51, 51);">LastName</span>) builder) { ... }
}
</code></pre>
<p>with式みたいなものの実現には、既存の言語構文だけでやるならいわゆる「ビルダー パターン」を使ったりします。
そのためにはビルダー用のクラスを1個余計に作らないと行けなくて、余計なメモリ アロケーションが発生したり、余計なクラスを書く手間が掛かったり。</p>
<p>でも、<a href="http://www.buildinsider.net/column/iwanaga-nobuyuki/003">タプル型</a>を使えば、タプルはmutableな構造体なので余計なアロケーションは起きない。
それに、新しいクラスの追加も必要なくて、手間は多少マシになる。
タプルは元々、引数位置と名前の対応関係を持っているので、黒魔術的な特殊処理なしでposition-to-propertyマッチできるはず、ということになります。</p>
<p>とはいえ、以下のように、悪い面もあります。</p>
<ul>
<li>既存の型に対してそのままでは使えない。<code>GetValues</code>や<code>With</code>などの追加(拡張メソッドでもいいけど、手動での追加)が必要</li>
<li>オブジェクトの分解(<code>GetValues</code>)やwith式(<code>With</code>)はインスタンス メソッドになるのでvirtualにできても、新規インスタンス作成ではできない</li>
<li>(レコード型などの新構文で)コンパイラーが自動生成するコードが増える</li>
<li>タプル型という、別の新構文に強く依存することになる(複雑度が増す)</li>
</ul>
<p>というような話があっての、先日の「<a href="http://ufcpp.net/blog/2016/3/pickuproslyn0301/">名前で解決</a>」の流れになったという話です。</p>
 ]]></description>
				<pubDate>Thu, 03 Mar 2016 03:42:50 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 3/1: position-to-propertyマッチ</title>
				<link>http://ufcpp.net/blog/2016/3/pickuproslyn0301/</link>
				<description><![CDATA[ <p>久々にMads降臨(C# チームのLanguage Design Meetingの議事録投稿)。</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/issues/9330">C# Language Design Notes Feb 29, 2016</a></li>
</ul>
<p>3つの言語機能を紹介しているんですが、共通して「position-to-propertyマッチ」というのが必要になります。
このposition-to-propertyマッチを許す「主義」を採用することに決めたという報告です。</p>
<h2>position-to-propertyマッチ</h2>
<p>簡単に言うと、例えば以下のようなクラスがあったとき、</p>
<pre class="source" title="">
<code><reserved></span><span class="reserved">public</span> <span class="reserved">class</span> <span class="type">Person</span>
{
    <span class="reserved">public</span> <span class="reserved">string</span> FirstName { <span class="reserved">get</span>; }
    <span class="reserved">public</span> <span class="reserved">string</span> LastName { <span class="reserved">get</span>; }

    <span class="reserved">public</span> Person(<span class="reserved">string</span> firstName, <span class="reserved">string</span> lastName)
    {
        FirstName = firstName;
        LastName = lastName;
    }
}
</code></pre>
<p>コンストラクター第1引数の<code>firstName</code>とプロパティの<code>FirstName</code>には1対1の対応があります。同様に第2に引数<code>lastName</code>とプロパティ<code>LastName</code>もです。
こういう、1対1の関係を、(先頭の1文字の大小の差は無視して)名前をベースに調べて、</p>
<ul>
<li><code>FirstName</code>というプロパティと、コンストラクターの第1引数を同一視する</li>
<li><code>LastName</code>というプロパティと、コンストラクターの第2引数を同一視する</li>
</ul>
<p>というような、引数位置(position)とプロパティ(property)の間の同一視を用いようという意味合い。</p>
<p>結構これを認めるのはC#としてはチャレンジになります。「頭文字の大小を無視」も、「名前の一致を見て同一視」も、これまで結構避ける主義でした。</p>
<p>ただ、以下に紹介する機能を、既存の型に対しても使えるようにしようとすると、どうしてもこういう仕組みが必要になります。</p>
<h2>3つの新機能</h2>
<p>position-to-propertyマッチを使う3つの新機能は以下の通りです。</p>
<ul>
<li>immutableオブジェクトに対するオブジェクト初期化子</li>
<li>with式</li>
<li>位置指定のパターン(positional pattern)</li>
</ul>
<h3>immutableオブジェクトに対するオブジェクト初期化子</h3>
<p>先ほど出した<code>Person</code>クラスみたいなimmutableなオブジェクト(プロパティがget-onlyで、値の書き換え不能)を初期化したい場合、コンストラクター引数に値を渡す必要があります。でも、オブジェクト初期化子構文を使っての初期化を行いたいことがあります。なので、</p>
<pre class="source" title="">
<code><reserved></span><span class="reserved">new</span> <span class="type">Person</span> { FirstName = <span class="string">"Mickey"</span>, LastName = <span class="string">"Mouse"</span> }
</code></pre>
<p>というコードを、</p>
<pre class="source" title="">
<code><reserved></span><span class="reserved">new</span> <span class="type">Person</span>(<span class="string">"Mickey"</span>, <span class="string">"Mouse"</span>)
</code></pre>
<p>に置き換えようという機能を提供したい。</p>
<p>で、このためには、どのプロパティがどの引数に対応するか知る必要があります。</p>
<h3>with 式</h3>
<p>immutableなオブジェクトは、値の変更も面倒になります。書き換え不能なわけで、わざわざ、一部の値を変更したうえで、新しいオブジェクトを作る必要があります。この面倒を軽減するために、with式という構文が提案されています。</p>
<p>以下のような書き方で、</p>
<pre class="source" title="">
<code>p <span class="reserved">with</span>  { FirstName = <span class="string">"Minney"</span> }
</code></pre>
<p>以下のようなコードを生成します。</p>
<pre class="source" title="">
<code><reserved></span><span class="reserved">new</span> <span class="type">Person</span>(<span class="string">"Minney"</span>, p.LastName)
</code></pre>
<p>こちらも同様に、プロパティに対応する引数を知る必要があります。</p>
<h3>位置指定のパターン</h3>
<p>C# 7に向けて実装中のパターン マッチング機能で、以下のようなコードが書けます。</p>
<pre class="source" title="">
<code>p <span class="reserved">is</span> <span class="type">Person</span>(<span class="string">"Mickey"</span>, *)
</code></pre>
<p>これは、<code>p</code>の型が<code>Person</code>かつ、<code>FirstName</code>が<code>&quot;Mickey&quot;</code>ということを調べる式です。</p>
<p>第1引数が<code>firstName</code>なので、対応するプロパティ<code>FirstName</code>の値を調べます。</p>
<p>こういう書き方は位置指定のパターン(positional pattern、あるいは、position-based pattern)といって、コンストラクターの逆操作です。</p>
<pre class="source" title="">
<code>p <span class="reserved">is</span> <span class="type">Person</span>(<span class="string">"Mickey"</span>, *) ⇔ <span class="reserved">new</span> <span class="type">Person</span>(<span class="string">"Mickey"</span>, <span class="string">"..."</span>)
</code></pre>
<p>一方、以下のようにプロパティ指定でのパターン(property pattern)もあって、こちらはオブジェクト初期化子の逆操作になります。</p>
<pre class="source" title="">
<code>p <span class="reserved">is</span> <span class="type">Person</span> { FirstName <span class="reserved">is</span> <span class="string">"Mickey"</span> } ⇔ <span class="reserved">new</span> <span class="type">Person</span> { FirstName = <span class="string">"Mickey"</span> }
</code></pre>
<p>そして再三になりますが、この位置指定のパターンにもposition-to-propertyマッチが必要になります。</p>
<p>もちろん、position-to-propertyマッチに頼らない明示的な挙動の上書きも用意する(<code>GetValues</code>メソッドや、<code>is</code>演算子のオーバーロードなどが候補になっている)つもりだそうですが、既定の挙動としてはposition-to-propertyマッチを使いたいとのことです。</p>
<h2>既存の型への新構文の適用</h2>
<p>position-to-propertyマッチを認めるというのは、結構、C#としては主義の変更というか、大幅な妥協ではあります。
(当然、issueページのコメント欄は、結構な割合でネガティブなコメントが埋まっていたりします。)</p>
<p>最初は、レコード型という新しい構文を用意して、その構文で作ったクラスや構造体で、上記の3つの構文を使えるようにする(使うための特殊なメソッドを生成する)つもりで考えていました。</p>
<p>が、その場合、既存の型には上記の便利な構文が使えないことになります。そして、すでに世に出回っている多くのコードに対して逐一「レコード型で書き換えろ」なんて言えるはずもありません。</p>
<p>なのでこの妥協、この主義変更ということになります。
実際のところ、世に出ているコードの多くが、コンストラクター引数とプロパティの名前を(頭文字の大小除いて)同じにしていたりするので、
実用性を考えるとよい妥協しどころではあります。</p>
 ]]></description>
				<pubDate>Tue, 01 Mar 2016 12:59:21 +0900</pubDate>
			</item>
			<item>
				<title>Windows 10アプリ開発に関する近況 (Astoria開発中止とか)</title>
				<link>http://ufcpp.net/blog/2016/2/an-update-on-the-developer-opportunity-and-windows-10/</link>
				<description><![CDATA[ <p>以下のブログがちょっと話題になっていますが。</p>
<p><a href="https://blogs.windows.com/buildingapps/2016/02/25/an-update-on-the-developer-opportunity-and-windows-10/">An Update on the Developer Opportunity and Windows 10</a></p>
<p>Windows 10アプリ開発に関する近況的な話で、Xamarinとか各種ブリッジ(他の環境向けアプリからの移植)とかの現状を説明しているんですが。</p>
<p><a href="http://www.publickey1.jp/blog/16/xamariniosandroidvisual_studio.html">Xamarin買収の話</a>と同時期に出したせいとか、ブログの内容がいまいちとか色々あり… なんか変な印象になってるなぁとか、ちょっと不安な感じ。文章読んでて受ける印象的に、これ、そんなに技術に詳しくない広報の人が、技術者から聞いた内容を元に書き起こしてて、微妙に正確じゃない表現になってるんじゃないかなぁとか思ったり(Windowsチームはそれをやらかしそう、という偏見もあり)。</p>
<h2>Bridge for Android (コードネーム「Astoria」)の開発停止</h2>
<p>この記事、「<a href="http://www.androidheadlines.com/2016/02/microsoft-confirms-closure-of-bridge-for-android-apps-astoria.html">マイクロソフトはBridge for Android (Astoria)の開発停止を認める</a>」とかいう話題にされてしまっていて。それはこのブログの本題じゃなかったと思うんだけどなぁ…</p>
<p>まあ、<a href="http://japan.cnet.com/news/service/35073589/">去年の11月にはそういう話が出ていた</a>んですが、
確かに、ブログで明示的に停止した話が書かれたのは初めてなのかな…
そのせいで、なんか騒動になっているみたいで。</p>
<p>ですが、
Xamarin買収のタイミングで変な文章を書いたので「AstoriaとXamarin、2つは必要ない」という主張だと誤認されたり、
Bridge for iOSとの関連の説明が下手なせいで「ブリッジ技術にAndroid向けとiOS向けの2つは必要ない」と取れる文章だったり、
なんか変な感じ(なので、これ、非技術者な広報担当者が書いてるなぁという印象です)。</p>
<h2>クロス開発と、ブリッジと</h2>
<p>そもそも、クロス開発と各種ブリッジは相補的というか、逆のことをやっているというか。</p>
<p>クロス開発は、これからスマホ向けアプリを作ろうとする人に、UWP (Windows 10 Mobile)も選択肢に入れてもらう(iOS、Android、Windows全部をターゲットにしてもらう)ためには何を使ってほしいかという話。マイクロソフトが提供する選択肢としては、</p>
<ul>
<li>
<a href="https://www.visualstudio.com/en-us/features/cplusplus-mdd-vs.aspx">Visual C++ Cross-Platform Mobile</a>
<ul>
<li>C++でクロス開発するためのプロジェクト テンプレートとかデバッガーとか</li>
<li>今、Android開発に関してはJavaにも対応してたり</li>
</ul>
</li>
<li>
<a href="https://cordova.apache.org/">Apache Cordova</a>と、その<a href="https://codeiq.jp/magazine/2015/06/24809/">Visual Studio対応</a>
<ul>
<li>JavaScriptでWeb的に(UIもHTMLで書いて)ネイティブ アプリ化する</li>
</ul>
</li>
<li>
<a href="https://xamarin.com/">Xamarin</a>
<ul>
<li>Mono ベース/C# でクロス開発</li>
</ul>
</li>
</ul>
<p>とかがあったわけです。</p>
<p>一方、ブリッジは、特定環境向けに作られた既存のアプリをUWP化してもらうための技術。開発が続いてるのは、</p>
<ul>
<li>
<a href="http://microsoftedge.github.io/WebAppsDocs/en-US/win10/HWA.htm">Web Bridge</a> (コードネーム Westminster)
<ul>
<li>Web技術をそのままUWP化</li>
</ul>
</li>
<li>
Win32/デスクトップ向け.NET移植 (コードネーム Centennial)
<ul>
<li>デスクトップ アプリをサンドボックス動作させるだけっぽい</li>
</ul>
</li>
<li>
<a href="https://dev.windows.com/bridges/ios">Bridge for iOS</a> (コードネーム Islandwood)
<ul>
<li>Objective-Cで書かれたiOS向けコードをビルドして、UWP化できる機能</li>
</ul>
</li>
</ul>
<p>など。</p>
<p>で、今回、開発停止が正式になったというのが、以下のAstroia</p>
<ul>
<li>
コードネーム Astoria
<ul>
<li>Windows 10にAndroid互換レイヤー(JVM + Android API)を載せて、エミュレーションしようという技術</li>
<li>ここが Bridge for iOSとの差。ソースコード レベルでの移植じゃなくて、バイナリをそのまま動かそうとしてた</li>
</ul>
</li>
</ul>
<h2>Java for Android対応</h2>
<p>一方で、今のVisual Studioって、JavaでのAndroidアプリ開発には実は対応していたり。</p>
<ul>
<li>
<a href="https://blogs.msdn.microsoft.com/vcblog/2015/11/06/java-debugging-and-language-support-in-visual-studio-for-android/">Java support in Visual Studio for Android</a>
<ul>
<li>Javaで書かれたAndroid向けコードをビルドして、Androidアプリをビルド・デバッグ</li>
</ul>
</li>
</ul>
<p>これ、しかもちょっと面白いのが、C++チームが保守してる(上記ブログはC++チームが書いたもの)という事実。</p>
<p>今、マイクロソフト内のC++チームが負ってる債務は「クロス開発」のようです。
その結果、Android開発はC++チームの範疇で、Java for Android対応もC++チームの債務。</p>
<p>という背景から、Androidからのブリッジも、Bridge for iOS (Objective-Cからのビルド)と同じく、JavaソースコードからUWPを作る機能であるべきなんじゃないかなぁという感じ。</p>
<p>で、実際、Astoriaの開発停止の話が出たのって、この<a href="https://blogs.msdn.microsoft.com/vcblog/2015/11/06/java-debugging-and-language-support-in-visual-studio-for-android/">Java support in Visual Studio for Android</a>が出たのと同時期だったりします。</p>
<h2>結局のところAstoria開発停止の理由</h2>
<p>実際のところは中の人に聞いてみないとわからないものの、僕が受けた印象としては、以下のような話だったんじゃないかなぁと。</p>
<ul>
<li>
Xamarinとの関連
<ul>
<li>「Xamarin買収の話題をきっかけに、いったん現状報告しとくか」程度であって、Astoria開発停止とは完全に無関係</li>
</ul>
</li>
<li>
Bridge for iOS との関連
<ul>
<li>本来いうべきこと: Bridge for iOS同様、ソースコードからのビルドであるべきではないか。互換レイヤー提供によるエミュレーションと、ソースコードからのビルドの2方式あるのは混乱の元</li>
<li>ブログの文面: Bridge for iOSに注力する。2つのブリッジ技術があるのは混乱の元</li>
</ul>
</li>
<li>
実際あり得そうな本来のAstoria開発停止理由
<ul>
<li><a href="https://blogs.msdn.microsoft.com/vcblog/2015/11/06/java-debugging-and-language-support-in-visual-studio-for-android/">Java support in Visual Studio for Android</a> をベースに、Javaソースコード レベルでUWP化に対応するのが筋</li>
<li>
ここが「計画としてはあるけどまだめどが立ってない、あるいは、//build/辺りでの発表目指してる」とかで今は何も言えない
<ul>
<li>言えない(というか、できるかどうかもわかんない)ことをお茶を濁した結果がブログの微妙な文面</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>伝言ゲームで文面が変になったり、言えないことをお茶を濁して余計言っちゃいけない感じの文章になったり、まあ、割かしよくあることだと思います…</p>
 ]]></description>
				<pubDate>Fri, 26 Feb 2016 02:34:09 +0900</pubDate>
			</item>
			<item>
				<title>.NET Coreへの移植</title>
				<link>http://ufcpp.net/blog/2016/2/porting-to-net-core/</link>
				<description><![CDATA[ <p>twitterで流れてきてて、気になったやつ。</p>
<ul>
<li><a href="https://blogs.msdn.microsoft.com/dotnet/2016/02/10/porting-to-net-core/">Porting to .NET Core</a></li>
</ul>
<p>内容的には、</p>
<ul>
<li>フィードバック募集中なのでお願いします</li>
<li>.NET Coreは今、ASP.NET、UWP、コンソール アプリに使えるけども、.NET Frameworkからの移植のモチベーションはそれぞれ何か</li>
<li>.NET Framework と .NET Coreの関係・差分</li>
<li>意図して.NET Coreには取り込まなかったものがちらほらあるから注意</li>
<li>
.NET Core化するかどうか、単純に時間的な不足で検討してないものもちらほら
<ul>
<li>特にフィードバックほしいのはここ。ほしいかどうか、優先度付けしたい</li>
</ul>
</li>
<li>移植にあたってのコツ</li>
</ul>
<p>みたいなの。</p>
<p>以下、さらっと概要。</p>
<h2>何を移植するか</h2>
<h3>ASP.NET</h3>
<p>移植する理由:</p>
<ul>
<li>.NET Coreならクロスプラットフォーム。MacやLinuxで動く</li>
<li>マシン全体に対するインストールじゃないんで、デプロイが楽(管理者権限とかも不要でバージョン変えれる)</li>
</ul>
<p>移植するとよい候補:</p>
<ul>
<li>MVC/Web API使ったものなら移植しやすいのでお勧め</li>
</ul>
<p>あまり移植に適してないもの:</p>
<ul>
<li>
WebFormsは .NET Coreに移植してないので、WebFormsを使っているものは以降大変。ほぼ再実装に
<ul>
<li>もちろん、そろそろWebForms自体をMVCとかに置き換えたいと思っているなら話は別</li>
</ul>
</li>
</ul>
<h3>UWP</h3>
<p>移植する理由:</p>
<ul>
<li>(.NET Coreへの移植というか、既存GUIフレームワークからUWPへのという意味で)PC、tablet、phablet、phone、Xbox、IoTデバイスと、広範囲のデバイスで統一的なアプリ開発ができる</li>
</ul>
<p>移植するとよい候補:</p>
<ul>
<li>
Windows 8/Windows Phone 8.1アプリは最初から.NET Core
<ul>
<li>.NET Coreの前身というか、いずれ.NET Coreが出ることを前提として設計されたというか、ほぼ Windows 8アプリ = .NET Core + Windows UIフレームワーク</li>
</ul>
</li>
<li>Silverlightアプリも、開発モデルはUWPとかなり近い</li>
</ul>
<p>あまり移植に適してないもの:</p>
<ul>
<li>
Win32なデスクトップ機能をフルに使ったWindows ForsmアプリやWPFアプリは
<ul>
<li>ただし、WPFアプリのXAMLを使った開発スタイルはUWPとかなり近いので多少楽</li>
</ul>
</li>
</ul>
<h3>コンソール アプリ</h3>
<p>移植する理由:</p>
<ul>
<li>これも、クロスプラットフォーム対応</li>
<li>.NET Native (事前に必要な部分だけネイティブ化した単一実行ファイルを作ってしまう機能)を使いたい場合</li>
</ul>
<p>移植するとよい候補/あまり移植に適してないもの:</p>
<ul>
<li>
単純に依存しているライブラリが.NET Coreに対応してるかどうか次第
<ul>
<li>ASP.NETやUWPと比べるとハードル低いはず</li>
</ul>
</li>
<li>例えばCOMとか使いまくったWindowsとかOfficeの自動化アプリは移植できないだろうし移植の意味もなさそう</li>
</ul>
<h2>.NET Coreと.NET Framework</h2>
<p>.NET Coreは、ある程度.NET Frameworkのサブセットになるように作られてるというか、Visual Studio 2015時点くらいまではそうなるようにある程度頑張ってたはず。でも、ずっとそうなるように維持するつもりはないみたい。現状でも.NET Core側だけにある機能がちらほらあるし、今後はまず.NET Core向けに機能実装されてくことになるはずだし、それが.NET Framework側にバックポーティングされる保証はない。</p>
<p>といっても、かなりの部分は.NET Core向けと.NET Framework (4以降)向けでコード共有できるはず。</p>
<p>差が生じる理由は大まかにいうと以下の3点に由来:</p>
<ol>
<li>
NuGetベース
<ul>
<li>.NET Frameworkはシステム全体に対するインストールが必要</li>
<li>.NET CoreはNuGetパッケージ マネージャーを使ってモジュールごとにバージョン管理可能</li>
<li>なので、大体において、.NET Coreの方が新機能を早く使える</li>
</ul>
</li>
<li>
きれいにレイヤー分け
<ul>
<li>.NET Frameworkではレイヤー分かれず低層から高層まで丸ごと含んでたようなライブラリが結構ある</li>
<li>.NET Coreではその辺りを整理して分割したものがある</li>
</ul>
</li>
<li>
問題ある技術の除外
<ul>
<li>.NET Framework 15年の歴史から、問題がはっきりしてて、新規実装の際には取り入れたくないものがある</li>
</ul>
</li>
</ol>
<h2>変化の激しいもの: リフレクション</h2>
<p>リフレクションは結構APIが変わっていて困るもの代表で。理由は:</p>
<ul>
<li>
レイヤー分けの問題: <code>object</code> が <code>Type</code> に依存することで、<code>System.Reflection</code>過剰に参照されかねない
<ul>
<li><code>Type</code>には型識別(型の一致判定とか、型の名前を取得したりとか)だけ残す</li>
<li>動的実行や動的コード生成に必要な情報は<code>TypeInfo</code>に分離</li>
</ul>
</li>
<li>
そもそもリフレクション非推奨
<ul>
<li>.NET Native (事前ネイティブ化)とは相性悪すぎる</li>
</ul>
</li>
</ul>
<h2>.NET Coreには実装しないもの</h2>
<h3>AppDomain</h3>
<p>理由: .NET Coreみたいな層でサポートするにはコストが高すぎる。.NET Nativeでは使えない</p>
<p>代替技術: コード分離(isolation)はプロセスとかコンテナーとかの技術使ってほしい。動的なDLL読み込みのためには<code>AssemblyLoadContext</code>っていう新しいクラスがある</p>
<h3>リモーティング</h3>
<p>理由: RPC(remote procedure call)自体がいまいちと認識されてる。AppDomain間の通信みたいなものなので、非常に高コスト。</p>
<p>代替技術: プロセス間通信だったらpipeとかmemory mapped fileとかを使うべきだし、マシン間通信だったらHTTPとか使ったネットワーク ベースの技術使うべき。</p>
<h3>バイナリ シリアライズ</h3>
<p>理由: privateなデータまでアクセスしちゃうし、互換性を取る上で重荷でしかない。</p>
<p>代替技術: 要件によって最適なシリアライザーは変わるだろうけど、それを要件に合わせて選んでほしい。候補としては、<a href="https://msdn.microsoft.com/en-us/library/ms731072.aspx">data contract serializer</a>、<a href="https://msdn.microsoft.com/en-us/library/182eeyhh.aspx">XMLシリアライザー</a>、<a href="http://www.newtonsoft.com/json">JSON.NET</a>、<a href="https://github.com/mgravell/protobuf-net">protobuf-net</a>など</p>
<h3>サンドボックス化</h3>
<p>理由: これも.NET Coreみたいな層でサポートするにはコストが高すぎる。正しくサンドボックス化するのはかなり難しくて、信頼も置けない。</p>
<p>代替技術: OSレベルでのセキュリティ境界を使ってほしい。</p>
<h2>移植も考えているもの</h2>
<p>現状の.NET Coreにないものはもっといろいろあるものの、移植しないと決まったわけじゃなくて、単純に時間が足りないものもある。これに関しては、移植の必要性がどのくらいあるか、特にフィードバックがほしいみたい。</p>
<ul>
<li><code>System.Data</code></li>
<li><code>System.DirectoryServices</code></li>
<li><code>System.Drawing</code></li>
<li><code>System.Transactions</code></li>
<li><code>System.Xml.Xsl</code>と<code>System.Xml.Schema</code></li>
<li><code>System.Net.Mail</code></li>
<li><code>System.IO.Ports</code></li>
<li><code>System.Workflow</code></li>
<li><code>System.Xaml</code></li>
</ul>
<h2>移植にあたって</h2>
<p>既存の.NET Framework向けのアセンブリがどのくらい移植しやすそうか解析するツールがあるみたい:</p>
<ul>
<li><a href="http://dotnetstatus.azurewebsites.net/">.NET Compatibility Diagnostic Tools</a></li>
</ul>
<p>で移植の流れとしては、</p>
<ul>
<li>とりあえず .NET Framework 4.6.1にしとくと.NET Coreとの差が少ない。</li>
<li>元のコードは .NET Framework ターゲットのまま、このツールを掛けつつ修正してとか繰り返すのがおすすめ。</li>
<li>.NET Coreへの完全移行じゃなくて、Core/Framework両方で使うとかもあるだろうからその場合は<a href="https://blogs.msdn.microsoft.com/dotnet/2014/04/21/sharing-code-across-platforms/">Shared SourceとかPCLとか</a>を活用</li>
</ul>
<p>とかそんな感じ。</p>
 ]]></description>
				<pubDate>Sat, 13 Feb 2016 14:05:38 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 2/6</title>
				<link>http://ufcpp.net/blog/2016/2/pickuproslyn0206/</link>
				<description><![CDATA[ <h2>コンストラクター引数を元にオブジェクトの分解(deconstruction)</h2>
<p><a href="https://github.com/dotnet/roslyn/issues/8415">Proposal: Positional deconstruction based on existing constructors and properties #8415</a></p>
<p><a href="https://github.com/dotnet/roslyn/blob/future/docs/features/patterns.md">パターン マッチング</a>で、現在提案されている範囲では、<code>is</code> 演算子みたいな特殊なメソッドを1個追加してやらないと、<code>o is Person(&quot;Alan&quot;, var last)</code> みたいな感じのマッチングができません。</p>
<p>これだと、今後追加する型(特にレコード型)に対してなら使えるけども、既存の型には全く使えなくて困る。一方で、現状でも、以下のコードみたいに、コンストラクター引数とプロパティに1対1の関係があるようなクラスを書く人は多いわけで、この規約ベースでオブジェクトの分解をできないかという提案。</p>
<pre class="source" title="">
<code><span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">public</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">class</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">Person</span>
{
  <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">public</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">Person</span>(<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">string</span> <span class="pl-smi" style="box-sizing: border-box; color: rgb(51, 51, 51);">firstName</span>, <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">string</span> <span class="pl-smi" style="box-sizing: border-box; color: rgb(51, 51, 51);">lastName</span>) 
  { 
    FirstName = firstName; 
    LastName = lastName; 
  }
  <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">public</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">string</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">FirstName</span> { <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">get</span>; }
  <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">public</span> <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">string</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">LastName</span> { <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">get</span>; }
}
</code></pre>
<p>確か自分もこのパターンでクラスを書いていることが多いんで、にこの機能が入れば、それらを1個1個レコード型に置き換えたりしなくてもパターン マッチングが使えて大変便利。</p>
<p>でも、引数の<code>firstName</code>とプロパティの<code>FirstName</code>の対応関係を規約ベースでやるのは、C#の文化(規約を嫌う、識別子は大文字小文字を区別する)的には合わないんで悩ましい感じ。ついてるコメントも賛否両論です。</p>
<h2>Swift 2.0</h2>
<p><a href="http://nshipster.com/guard-and-defer/">Swift 2.0でdeferとguardが入った</a>わけですが、先月、それはC#には適するかどうか、議論用のissueページが立ちました。</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/issues/8115">&quot;defer&quot; statement #8115</a></li>
<li><a href="https://github.com/dotnet/roslyn/issues/8181">Proposal: Guard statement in C# #8181</a></li>
</ul>
<p>ついてるコメントからすると、賛否は半々くらいか、ちょっと否定が多いくらいかなぁ。個人的な予想では、採用されない気がする。</p>
<h3>defer</h3>
<p><code>try { 処理 } finally { 後始末 }</code> の代わりに <code>defer { 後始末 } 処理</code> と書くような構文。</p>
<pre class="source" title="">
<code>    {
        SomeType thing = Whatever...;
        defer {
            thing.Free();
        }
        <span class="pl-c" style="box-sizing: border-box; color: rgb(150, 152, 150);">// some code code using thing</span>
    }
</code></pre>
<p>メリットは以下のような感じ。</p>
<ul>
<li><code>using</code> 相当の機能を、<code>IDisposable</code> 実装していなくてもできる</li>
<li><code>try</code>-<code>finally</code> と比べて、「処理」の部分がネスト深くならない</li>
<li><code>try</code>句内と、<code>finally</code>句内の両方で使いたい変数をわざわざその外側で宣言する必要がない</li>
</ul>
<p>ただ、以下のような問題も。</p>
<ul>
<li><code>defer</code> が複数並んでるとき、その実行順はどうすべき？</li>
<li><code>try</code>-<code>finally</code> でできることに対してわざわざ新構文増やすの？</li>
<li>1回り外側のブロックに対して影響を与えるような構文ってなかなか理解されにくい</li>
</ul>
<h3>guard</h3>
<p><code>if (絶対満たすべき条件) ; else throw 例外;</code> みたいなよくあるパターンに対して使う構文。絶対満たすべき条件だし、満たしてなかったら必ず例外を投げる(そこから先を絶対に実行しない)ことを保証するために、<code>if</code> じゃなくて <code>guard</code> を使おうというもの。</p>
<p>まあ、そういうものがほしいこともあるというのはわかるものの、<a href="https://github.com/dotnet/roslyn/issues/119">コントラクト</a>と被ってるし、そもそも<code>guard</code>の必要性を減らせそう(コンパイル時にチェック可能で、実行時に例外投げる必要がない)な構文もこれから増えるだろうし。</p>
 ]]></description>
				<pubDate>Sat, 06 Feb 2016 06:02:47 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 1/9: structural typing</title>
				<link>http://ufcpp.net/blog/2016/1/pickuproslyn0109/</link>
				<description><![CDATA[ <p>C#にstructural typing(構造的型付け)を入れようという案。</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/issues/7844">[Proposal][Roslyn] Add structural typing support #7844</a></li>
</ul>
<p>まあ、「何人かでちょっとディスカッションしたよ」というくらいの段階みたい。やりたいことの説明や、構文の案(3案ほど)が出ている程度(実装方法に関する言及あまりなし)。</p>
<p>以下、structural typingがどういうものなのかについて簡単に説明。</p>
<p>Goのインターフェイスがそうなんですが、明示的な実装を必要とせず、「同じシグネチャ(名前+引数一致)さえ持っていればなんでもOK」という方針で代入可能な型システムをstructural typingと言います。</p>
<p>Javaとか.NETのインターフェイスやクラスの継承・実装、C++のクラス継承なんかは、以下のように、明示的な参照・実装が必要になります。こういうのはnominative(指名的、任命的)な型付けといいます。</p>
<p><img src="/media/1048/interface.png" alt=".NETのインターフェイス(nominative typing)" /></p>
<p>一方で、Goのインターフェイスは、(C#で提案されている案の1つを使って類似機能を書くと)以下のように、シグネチャだけ見て暗黙的に「実装されている」ことにしてくれます(これが、structural)。</p>
<p><img src="/media/1049/structural.png" alt="structural typing" /></p>
<p>もちろん良し悪しあって、以下のような感じ</p>
<ol>
<li>nominativeな方が若干実行性能がいい</li>
<li>ただ、structuralの方はほんの小さなコストで、結構大きな自由度が手に入る</li>
<li>structuralの方は、実装クラス側が知らず知らずのうちに合わない構造に修正される可能性がある</li>
</ol>
<p>3番目の「知らず知らずのうちに修正」が怖いので、Javaとか.NETとかみたいな動的リンクが基本のプログラミング言語ではstructuralのデメリットが大きいんですが。Goの場合は静的リンクだからインターフェイスをstructuralにできたというのもあるはず。</p>
<p>とはいえ、別にどっちか片方だけでないといけないということもないわけです。C#では、普通のインターフェイスはnominativeだけど、追加でstructuralな何かを加えて使い分けたってかまわないはず。「知らず知らずのうちに修正」問題をどう対処するかだけ決まればC#でもstructural typingの便利さを享受できるはずです。</p>
 ]]></description>
				<pubDate>Sat, 09 Jan 2016 04:03:19 +0900</pubDate>
			</item>
			<item>
				<title>「コンピュータープログラミング入門以前」電子書籍キャンペーン</title>
				<link>http://ufcpp.net/blog/2016/1/ebookscampaign/</link>
				<description><![CDATA[ <p>達人出版会×マイナビ出版で年末・年始電子書籍セールをやっているそうです。</p>
<ul>
<li><a href="https://book.mynavi.jp/ebooks_sale_highend/">マイナビ出版側サイト</a></li>
<li><a href="http://tatsu-zine.com/sales/mynavi201512">達人出版会側サイト</a></li>
</ul>
<p>自著の「<a href="http://amzn.to/WwOZov">コンピュータープログラミング入門以前</a>」も対象なので宣伝。</p>
<iframe src="http://rcm-fe.amazon-adsystem.com/e/cm?t=cunflc-22&o=9&p=8&l=as1&asins=4839936919&ref=qf_sp_asin_til&fc1=000000&IS2=1&lt1=_blank&m=amazon&lc1=0000FF&bc1=000000&bg1=FFFFFF&f=ifr" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe>
<p>「コンピュータープログラミング入門以前」は結構前に書いた本なんですが、今は転載の許可ももらって、ufcpp.netの「<a href="http://ufcpp.net/study/computer/">コンピュータの基礎知識</a>」に低レイヤーの話を移植していたりはします。また、上の方のレイヤーの話も「<a href="http://ufcpp.net/study/csharp/">C#によるプログラミング入門</a>」のあたりに部分部分反映させてたりはします。ほぼ同じ内容なんですが、広告なしで読みたいとか、出版社の編集が通ったきれいなレイアウトで読みたいとか、お布施したいとかあれば、ぜひ電子書籍版をお買い求めください。</p>
<p>ちなみに、「入門以前」ってタイトルだけど入門にはちょっとレベル高すぎないか？などというフィードバックを大変多くいただいたりしていますが、そもそもその戦犯は先達の「<a href="http://amzn.to/1PHCGCl">Cプログラミング入門以前</a>」だったりします。こちらが「入門以前」というタイトルで、結構幅広い話を書いているので、それを倣って、「コンピュータープログラミング入門以前」のタイトルが決定しました。こちらの「Cプログラミング入門以前」もキャンペーン対象に並んでいるのでこの際、併せていかがでしょうか。</p>
 ]]></description>
				<pubDate>Mon, 04 Jan 2016 11:11:56 +0900</pubDate>
			</item>
			<item>
				<title>Commonly Rejected Changes</title>
				<link>http://ufcpp.net/blog/2016/1/commonlyrejected/</link>
				<description><![CDATA[ <p>twitterで見かけた話。きっかけはSwiftのものなんですが、「<a href="https://github.com/apple/swift-evolution/blob/master/commonly_proposed.md">Commonly Rejected Changes</a>」、つまり、「頻繁にリジェクトされる変更の提案」集がまとめられてるみたいです。これを見た感想は「ああ、あるある、C#でもよくある」だったので、それをネタにしてみようかと。</p>
<h2>{} をやめて、Python風のインデント構文がほしい</h2>
<p>これ、SwiftやC#に限らずありとあらゆるプログラミング言語で発生すると思うんですが、必ず出てくるんですよね、インデントでブロックを切る構文を求めてくる人。SwiftにしろC#にしろ、基本方針として「空白文字を除外しても意味が変わらない」を採用している言語に対してそういう要求をされましても…</p>
<p>まあ、Swiftは「空白を抜いたら意味が変わる」構文あるんですけどね。<code>?:</code>の<code>?</code>の前にスペースを入れないと、<code>型名?</code>の<code>?</code>と区別がつかないそうで。</p>
<p>それを言い出すと、C系言語共通で、<code>a+++b</code>の解釈は空白の入れ方によって変わってしまうわけですが。</p>
<h2>セミコロンなくして</h2>
<p>同上。</p>
<p>「空白文字を除外しても意味が変わらない」方針と相性悪いんですよねぇ、セミコロンlessプログラム。
改行のあるなしで実行結果が変わることがあるとか、割かし悪夢を生みます。</p>
<p>逆に、「改行区切り」の代表格、Visual Basicなんかは、改行を挟めない(挟めなかった)ことでいろいろ苦労していますし。</p>
<h2>記号が分かりづらいから止めてほしい</h2>
<p>2件ほど。</p>
<ul>
<li><code>&amp;&amp;</code> と <code>||</code> の代わりに <code>and</code> <code>or</code> とかにしてほしい</li>
<li>条件演算子 <code>?  :</code> はわかりにくいからやめてほしい</li>
</ul>
<p>いずれも、本質は「記号が分かりづらい」だと思います。</p>
<p>これはわからなくはないもの。「式」＝「演算子」＝「記号」ってのは、C言語の悪い癖な感じもします。確かに初見の人には優しくなく、googlabilityも悪い。</p>
<p>でも、そのために予約語(= 変数名などに使えない)を増やすの？とか、C言語をすでに知ってる人の数が多いのでわざわざ変えるメリットも低いとかあり。</p>
<h2>if/elseとswitchを式にしてほしい</h2>
<p>if/elseは、前節の「<code>?  :</code> が記号だからわかりづらい」問題と同義でしょう。「if/else相当の式」は<code>?  :</code> でできる話なので。</p>
<p>switchは、C#だと7で式バージョンのswitchが入る方向で議論進んでいます。</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/issues/5154">Proposal: expression-based switch (&quot;match&quot;) for pattern matching #5154</a></li>
</ul>
<p>C#の場合は、これまで、if/elseやループに相当する式は書けたもののswitchはなかったので。</p>
<table>
<thead>
<tr>
	<th>ステートメント</th>
	<th>式</th>
</tr>
</thead>
<tbody>
<tr>
	<td>if/else</td>
	<td>'? : '</td>
</tr>
<tr>
	<td>foreach</td>
	<td>LINQ</td>
</tr>
<tr>
	<td>switch</td>
	<td>switch (C# 7向け提案)</td>
</tr>
</tbody>
</table>
<p>これまではswitchの利用頻度がそこまで高くなかったのでそんなに欲しいとも思わなかったものの、C# 7では別途<a href="https://github.com/dotnet/roslyn/pull/4882">パターン マッチング</a>で使えるようにswitchステートメントを拡張する予定なので。そうすると「switch式」もほしくなるだろいうということで、一緒に提案されています。</p>
<p>ただ、こうなるとますます「<code>?  :</code> が記号だからわかりづらい」というのが分からなくもない話に。
switchは、ステートメントでも式でも<code>switch</code>キーワードを使います(式はもしかしたら<code>match</code>キーワードになる可能性もあるもの、いずれにしても記号ではなくて英単語)。
なので、if/elseの式バージョンも、if/elseっていう英単語の方が分かりやすかったりしないかなぁとは少し思います。</p>
<p>まあ、今更の変更は無理ですが。</p>
<h2>Swiftを使ってSwiftコンパイラーを書き直して</h2>
<p>C#も10年くらい言われ続けました。C#の場合はそれが<a href="https://github.com/dotnet/roslyn">Roslyn</a>なわけですが、これがどれだけ大変だったか。</p>
<p>実際のところ、「既存のプログラムと互換性を保ったものを、別の言語に移植」というのはかなり不毛な作業です。よっぽど強い動機がなければできない。C#の場合は以下のような動機がありました</p>
<ul>
<li>さすがにC++製コンパイラーだと機能追加が苦しくなってきた</li>
<li>Visual Studioとの連携(コード補完、静的コード解析、リファクタリング)の高機能化が難しかった</li>
</ul>
<p>が、これも「10年越しの実現」です。「そろそろ苦しい」が「移植の不毛さ」を上回るのにそれくらいの歳月がかかっています。</p>
<p>また、Roslynの完成は相当待たされました。理由は、以下のようなものです。</p>
<ul>
<li>他部署からの要望(C#の場合はWindows 8関連、つまり、Windows Runtime APIと非同期処理への対応)に時間を取られて、なかなか「単なる移植」には人員を割けなかった</li>
<li>「単なる移植」で数年、言語の進化を停滞させるのもつらい</li>
<li>実はバグだった挙動も含め、元のコンパイラーの挙動を変えると、世の中に出回っているコードを壊すので、そこの互換性確保が結構つらい</li>
</ul>
<p>こういうハードルがあって、結局、「C#コンパイラーのC#化」に取り掛かってから、リリースまでに5・6年はかかっています。C#自体の発表から数えると、15年の歳月をかけてやっと「C#化」されました。</p>
<h2>クロージャの構文を変えてほしい</h2>
<p>これは、C#だとあんまり言われないんですよね。みんな、ラムダ式におおむね満足しているようで。</p>
<p>多少の提案はあったりはするんですが。</p>
<ul>
<li>
引数を別に使わない場合に省略したいという類
<ul>
<li><a href="https://github.com/dotnet/roslyn/issues/20">Lambdas omitting parameters #20</a></li>
<li><a href="https://github.com/dotnet/roslyn/issues/7463">Short syntax for lambda declaration #7463</a></li>
</ul>
</li>
<li>
ローカル変数のキャプチャの仕方を制御したい
<ul>
<li><a href="http://kaworu.jpn.org/cpp/%E3%83%A9%E3%83%A0%E3%83%80%E5%BC%8F">C++ 14のラムダ式</a>みたいなやつ</li>
<li>参照で取り込み、値のコピーで取り込みを選びたいことがある</li>
<li>取り込んだ変数の書き換えの可否を制御したいことがある</li>
<li>C#のは常に、参照で書き換え可能</li>
</ul>
</li>
</ul>
<h2>シングル クォートの文字リテラルがほしい</h2>
<p>Swiftって文字リテラルと文字列リテラルの区別ないんですね…</p>
<p>これはでもなかなか難しい問題でして。特に、1文字が何バイトになるか全くわからない現在となっては。</p>
<p>マイクロソフト内部でC#を作り始めた当時(だいたい1998年頃)は、Unicode出始めの時期、つまり、まだ16ビットですべての文字を表せるという幻想があった頃です。なので、<code>char</code>型は16ビットだし、<code>string</code>はそれの配列に皮を被せたような構造。</p>
<p>ですが、今はどうかというと。<a href="http://codezine.jp/article/detail/1592">サロゲート ペア</a>があり、<a href="http://tech.albert2005.co.jp/blog/2014/11/21/mco-normalize/">結合文字</a>があり、<a href="https://ja.wikipedia.org/wiki/%E7%95%B0%E4%BD%93%E5%AD%97%E3%82%BB%E3%83%AC%E3%82%AF%E3%82%BF">異体字セレクター</a>があり。最近だと、絵文字がなかなか来てます。肌色(異体字)セレクターと結合の組み合わせで、「色白男性と色黒女性の家族」みたいに、1文字で表示されるけどもデータ上は何バイトも使う文字すらあります。</p>
<p>結局、世の中の主流派UTF8、つまり、可変バイトの文字列符号化でして。Webでレガシーとの互換が必要ないものだと、ほとんどのテキストがUTF8で流れてるんじゃないですかね。となると、C#でパフォーマンス的にネックになりがちなのが、UTF8から<code>string</code>への変換処理だったりします。その結果、今、<code>string</code>とは別に、<a href="https://github.com/dotnet/corefxlab/blob/master/src/System.Text.Utf8/src/System/Text/Utf8/Utf8String.cs"><code>System.Text.Utf8.Utf8String</code></a>なんていうクラスを別途実装中だったりします。この場合、16ビットな<code>char</code>は大して意味をなさなかったり。</p>
<h2>continueキーワードを、スクリプト言語でみられる他のキーワードに置き換えてほしい</h2>
<p>これもC#だとあんまり言われないですね。</p>
<p>まあこれ、「自分が慣れた言語に近づいてほしい」欲なんですかねぇ。C#の場合は名前にCという文字がはいってるのもあって、「C系文化」から外れようという提案は少な目なんですが。Swiftは結構「脱C」しているのでこういうこと言われてしまうのかも。</p>
<h2>switch 中で、default の代わりに case _ を使いたい</h2>
<p>C#では、C# 7でパターン マッチングが入って、その仕様の中に <code>case *</code> で任意のパターンにマッチというのを作れるので、確かにdefaultとの住み分けはどうなるんだろうって思います。まあでも、C系言語に脈々と受け継がれてきたdefaultの使い方を変えるだけの価値があるかと言われると。</p>
 ]]></description>
				<pubDate>Sat, 02 Jan 2016 10:45:02 +0900</pubDate>
			</item>
			<item>
				<title>Windows 10 Mobile人柱中</title>
				<link>http://ufcpp.net/blog/2015/12/continuum/</link>
				<description><![CDATA[ <p>最近、「<a href="http://togetter.com/li/895212">Surface Book買わない人</a>」として有名なわけですが。だって、ノートPCとか重たくて持てない。スマホでいいよ、スマホで。</p>
<p>ということで、今週中、「リビングで<a href="http://www.itmedia.co.jp/pcuser/articles/1510/04/news014.html">Windows 10 Mobile</a>を使って作業しよう強化週間を実施しております。</p>
<h2>Continuum</h2>
<p>最大の動機は、手元に<a href="http://gigazine.net/news/20151007-windows-10-continuum/">Continuum</a>対応端末があることです。
要するに、<a href="https://www.microsoft.com/en-us/mobile/phone/lumia950-xl-dual-sim/">Lumia 950 XL</a>を買ったから。</p>
<p>Continuumは、Windows 10 Mobile最大の売りになるかもしれない機能で、スマホとPCで同じアプリを同じように使える機能。普段スマホ上ではスマホ サイズに起動しますが、ディスプレイにつなぐとPCサイズなアプリとしてちゃんと起動するというもの。</p>
<p>Continuum対応のWindows 10 Mobile機をディスプレイにつなぐと、ディスプレイには見慣れたWindows 10 PCのような画面が現れます。スマホ側はタッチパッドみたいな状態になって、ディスプレイ側に出ているアプリを操作(モード切り替えできて、スマホ側は別のアプリを起動して使うことも可能)。キーボードやマウス(Bluetoothや、USBハブ越しに接続可能)もつないで、かなりPCに近い操作ができます。</p>
<p><img src="/media/1046/dsc_0490.jpg" alt="Lumia 950 XLをディスプレイにつないで見たところ" />
↑Lumia 950 XLをディスプレイにつないで見たところ。画面に出ているPowerPointはLumia上で動いているもの。</p>
<p><img src="/media/1047/dsc_0492.jpg" alt="Lumia 950 XLにBluetoothキーボードを接続" />
↑Lumia 950 XLにBluetoothキーボードを接続。マウスも行けます。これで、かなりPC的に操作可能。</p>
<p>Continuum (連続体)という名前通り、スマホ、タブレットとPCを連続的につなぐものです。</p>
<h3>ただしUWPに限る - とりあえずOfficeは対応済み</h3>
<p>ただし、Continuumで使えるアプリには制限があって、今のところ<a href="http://www.itmedia.co.jp/pcuser/articles/1506/24/news051_2.html">UWPアプリのみ対応</a>。
さんざん言われているように、「Windows Phoneはアプリが少ないから困る」問題があるわけです。</p>
<p>まあ、とりあえず、OfficeはUWP化されました。これが結構大きくて、原稿書きや表計算であれば結構使える状態です。まあ、まだまだ「時々フリーズ」みたいな不具合は出ますが、機能的には「人柱はできるレベル」になったかなぁと個人的に感じています。ちなみに、書いてるドキュメントの自動保存とかはずいぶん発達していて、「フリーズして作業紛失」みたいなので困ったことは、最近ではめっきりなくなっています。</p>
<h3>連続的につなぐもの</h3>
<p>「スマホでいいよ、スマホで」って、割かし今の日本を指す的確な言葉だと思うんですよね。ちょっと前に、「<a href="http://www.j-cast.com/2015/09/17245160.html">日本の若年層、PC普及率が先進国で最低レベル</a>」とかいう話題も出たわけですが。これ見てみんな思ったであろうことは「だってスマホで十分だから」でしょう。</p>
<p>これに関して個人的な意見としては、「日本はおかしい」とか「日本は遅れてる」じゃなくて、むしろ「日本は先を行ってる」だと思うんですよね。理由は以下の2点。</p>
<ul>
<li>高機能携帯端末はいずれ他の国でも普及率上がる</li>
<li>
携帯型が好まれる背景には家の狭さがあるものの、都市部集中傾向も世界中で見られる
<ul>
<li>車社会のアメリカですら。参考: 「<a href="http://newclassic.jp/4976">「くたばれ、Google」、その意味とは？</a>」、「<a href="http://www.sbbit.jp/article/cont1/30284">クールなスタートアップは今、シリコンバレーを目指さない </a>]</li>
</ul>
</li>
</ul>
<p>そこで問題になるのが、<a href="http://www.excite.co.jp/News/society_g/20141108/Taishu_12091.html">スマホ ネイティブだからPC使えない問題</a>。
スマホではコンテンツ消費はできるけど、コンテンツ生産は難しい。生産者が育たないってやつ。
割かしわかりやすいデジタル デバイドの1つです(もう今、スマホはまず必需品なので持ってるとして、スマホ + PCとか買える家庭だけが有利)。</p>
<p>「Continuumがつなぐのはこの溝ではないか」というのが、自分がContinuumに一番期待しているところです。
「スマホだとコンテンツ生産者が育たないからPCを買いなさい」なんてのは<a href="http://www.huffingtonpost.jp/2015/12/14/japan-health-marie_n_8802310.html">マリー アントワネット的発想の一種</a>。
そうじゃなくて、もう、スマホ側伸ばす方が現実的な段階に来たのかなと思います。</p>
<h3>まあ、Bookも買えばいいじゃない</h3>
<p>さて、まあ、別に「マリー アントワネット側」な発想してもいいんですけど。買いたいだって？買えばいいじゃない。</p>
<p>特に買いたいと思わない真の理由は、自分がひきこもりだからなわけですが。つまるところ、PCの前にしかいない。外出と書いて「トイレ行き」を指す。まれに遠出(※家の外に出ること)する時くらいはスマホで十分なわけです。一刻も早くおうちに帰りたい。</p>
<p>実際、自分が家・職場の外にいる時間のうち、多少なりともノートPCがほしいなと思うような場面は勉強会くらいなわけです。
普段、例えば、電車の中で文章打ちみたいなことも結構しますが、その用途ももう長らくスマホでやっています(というか、15年以上、ガラケー時代からケータイで文章打ってたり)。
勉強会も、視聴者側参加の場合はセッション聞いた感想やら補足やらをtwitterに垂れ流すくらいなので、それもスマホで十分です。
これまでの唯一の問題だった登壇側も、<a href="http://ufcpp.net/blog/2015/12/roommetrotokyo10/">Continuumを使ってクリアできることが先週確認できました</a>。</p>
<h3>家庭内mobility</h3>
<p>しかし、「家の中ですらひきこもり」というのがまた問題なわけです。ぶっちゃけていうと家族との時間すらなくなる。旦那/お父さんが書斎にこもってPC作業しててみなさいよ、まず「邪魔しちゃ悪い」感じになって、家族と顔合わせない。
なので、よっぽど切羽詰まった作業でもしてない限り、リビングでだらだらと作業したいなと思うわけです。</p>
<p>という背景の中、メイン機のデスクトップPC、やむなく遠出(※家から出ること)するときのためのスマホに加えて、近場に出かける(※PC前から動くこと。家の中含む)という第3の要件が発生。家庭内でのmobilityが必要。
この微妙な中間要件用に3台目を持てというのか…っていう話になるわけです。できればここもスマホに集約したい。</p>
<p>ちなみにまあ、職場に放置気味な<a href="http://amzn.to/22mVjQT">Surface 3</a>も持ってたりするので、実はそれを家に持って帰って来ればいい話なんですが。それはそれで、めったに使わないものを放置しておくスペースってのが必要で結構ストレスがでかいというのが、これまでの経験的に率直な感想。普段使いのものをそのまま使いたい。そして今は、普段使いのもの = スマホ。</p>
<h2>始めてみよう、Windows 10 Mobile作業</h2>
<p>と言うわけで、家庭内Mobilityの確保のためにWindows 10 Mobile作業の人柱をやってみようということにしました。</p>
<h3>Continuum の使い方</h3>
<p>とりあえずContinuumの使い方から。</p>
<h4>対応機種</h4>
<p>対応機種は、今のところ輸入端末のみ、日本では<a href="http://neo.nuans.jp/">NuAns NEO</a>が対応するかも(※ハードウェア的にWindowsに正式サポートされるかどうかきわどいラインらしいものの)ということで期待されています。来年には他にも出そろってくれるのかなぁ。</p>
<p>比較としてSurfaceで考えると、そんなに評価の高くない初代Surface (2012年10月)から、結構売れだしたSurface 3 (2015年5月)までに2年半とかかかってるので、
これから1・2年は人柱な感じかもしれませんが。</p>
<h4>追加で必要なもの</h4>
<p>Continuumの記事を見るに、なんかドックみたいなものが写真に移りこんでるので、何か専用のハードウェアが追加で要るのかと勘違いしがちですが、別に必須じゃありません。</p>
<p>あのドックは、</p>
<ul>
<li>給電</li>
<li>USBハブ</li>
<li>HDMI出力</li>
</ul>
<p>の複合品。電池動作で頑張るなら給電は要らないし、キーボード・マウスをBluetoothで行くならUSBハブも特に不要。問題は、映像の出力くらいですね。ちなみに、Lumia 950は<a href="http://www.pc-koubou.jp/blog/miracast.php">Miracast</a>使えるみたいなので、ディスプレイ側が対応していればHDMI出力も要らないはずです。</p>
<p>ということで、以下のいずれかがあればContinuumを使えます。</p>
<ul>
<li>Miracast対応ディスプレイ、あるいは、<a href="http://amzn.to/1NA9RoI">Miracastレシーバー</a></li>
<li><a href="http://amzn.to/1RZygHf">USB-C から HDMI への変換ケーブル</a></li>
</ul>
<p>Miracast対応ディスプレイに関しては、いまどきは多くのテレビが対応してるみたいですね。試しに電気屋で「ワイヤレス ディスプレイに接続する」設定画面開いてみたら、家電フロアのテレビが大量に応答してました。</p>
<h3>実際の導入状況</h3>
<p>とりあえず勉強会登壇用途のために<a href="http://amzn.to/1RZygHf">USB-C から HDMI への変換ケーブル</a>を買いました。これは結構満足。</p>
<p>家庭内Mobilityに関しては、リビングにディスプレイを置くのかという問題をどう回避しようかで悩み中。
リビングなので、Miracast対応テレビを置くという手もあるんですが。前提が「家族と」なので、テレビは家族に取られてるもんだと思った方がよさそう。追加でMiracast対応ディスプレイを買うのは、「たまにしか使わないものをどこに置いておくのか」問題に抵触するのでこれもまた微妙。</p>
<p>結局、さしあたって、Bluetoothキーボードだけつないで、スマホ画面中で作業という苦行を試してみています。散々Continuumの宣伝しておいて、実はContinuum使ってないという。まあ、Windows 10 MobileでOfficeがまともになったので…</p>
<p>ディスプレイをどうしよう問題も継続的に悩むとして、先にキーボードとかスマホ スタンドとかをどうしようという辺りを検討という感じです。</p>
<ul>
<li><a href="http://amzn.to/1O65P8Z">Universal Foldable Keyboard</a>: 昨日買ってみた。ソファー上とか、安定しない場所で使うには微妙かなぁという感想。折れ目が固定されないんで常にふにふに。折り畳みは結構すっきりしてるんで、これは勉強会に持っていく用途の方がいいかも。</li>
<li><a href="http://amzn.to/1QI8QhW">KEYS-TO-GO</a>: Foldable Keyboardを買いに行った時にいろいろ触って試してみて、一番いいなと思ったのはむしろこれ。実際にLumiaにつないで使ってないので何とも言えないものの。</li>
<li><a href="http://amzn.to/1QI97l8">Wedge Mobile Keyboard</a>: そういや昔試しに買ってみて眠ってるWedge Keyboardが家にある… 家庭内Mobilityくらいの近距離用途なら、これくらいのサイズのものが一番いいかも。スマホ スタンドになるカバーも付いてるし。</li>
<li><a href="http://amzn.to/1QI9nk4">PCスタンド</a>: 昨日、床作業・ソファー作業が結構きつかったんで買うかどうか迷ってるのがこの手のPCスタンド。邪魔かなぁ… 普段の置き場に困るよなぁ…</li>
</ul>
<h2>まとめ</h2>
<p>デスクトップ前にしかいないのにノートPCとか要るわけないじゃない。スマホでいいよ、スマホで。</p>
<p>PCが売れない、スマホが原因でPCスキルが上がらないことが問題視されている今、スマホでPC並の作業をできるようになることに期待しています。</p>
<p>そういう視点で、Windows 10 Mobile作業の人柱始めました。まだそろえる道具どうするか検討中ですが、Continuumには引き続き期待。</p>
 ]]></description>
				<pubDate>Tue, 22 Dec 2015 12:38:09 +0900</pubDate>
			</item>
			<item>
				<title>めとべや東京 #10 にて登壇</title>
				<link>http://ufcpp.net/blog/2015/12/roommetrotokyo10/</link>
				<description><![CDATA[ <p><a href="https://roommetro.doorkeeper.jp/events/35683">めとべや東京 #10</a> にて登壇してきました。</p>
<div style="width: 608px; max-width: 100%; margin-bottom:5px;"><a href="https://docs.com/iwanaga-nobuyuk/2848/net-platform-standard" title=".NET Platform Standard" target="_blank" style="font-family: 'Segoe UI'">.NET Platform Standard</a><span style="font-family: 'Segoe UI Light'">—</span><a href="https://docs.com/iwanaga-nobuyuk" target="_blank" style="font-family: 'Segoe UI'">Iwanaga Nobuyuki</a></div><iframe src="https://docs.com/d/embed/D25195179-4660-2274-7160-001203245710%7eMd2f0fde0-d68b-9095-2ec5-841305bd4fb1" frameborder="0" scrolling="no" width="608px" height="378px" style="max-width:100%" allowfullscreen="False"></iframe>
<p>まあ実は、元々別の勉強会での発表になる予定だった資料なんですが。どうしても都合がつかずに、資料作りかけの状態で未発表だったもの。</p>
<p>メトロっぽくない感じでしたが、まあ、この苦労を最初に負ったのはWindows Phone Silverlightであったり、Windowsストア アプリであったり。そこからUniversal Windows Platformや.NET Coreに進化し、今ようやく問題解消の光明(というか長い長い投資の回収フェーズ)が見えてきたという。</p>
<h2>Continuum</h2>
<p>ちなみに、今日の登壇、<a href="http://gigazine.net/news/20151007-windows-10-continuum/">Continuum</a>使ってのプレゼンでした。プレゼンの内容よりもむしろそっちが本題みたいな。</p>
<p>たぶん、最初にContinuum見せびらかすのやらずに登壇してたら、僕がLumia 950 XLでプレゼンしてるということに気づかなかった人もいるくらいではないかと。割ともう、勉強会にはノートPC持っていかなくてもいいかなぁ。Visual Studioを使ったデモとかは厳しいでしょうけど、それも、回線速度次第ではAzure VM上へのリモート デスクトップ接続でいいでしょうし。</p>
<p>ちなみに、Lumia 950でContinuumやるのに専用のドックとかは必要なくて、単に<a href="http://amzn.to/1RZygHf">USB-CからHDMIへの変換ケーブル</a>だけあれば十分です。MacBookで使えるやつ。</p>
 ]]></description>
				<pubDate>Sat, 19 Dec 2015 15:59:26 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 12/18</title>
				<link>http://ufcpp.net/blog/2015/12/pickuproslyn1218/</link>
				<description><![CDATA[ <h2>CoreCLR側との兼ね合い</h2>
<p><a href="https://github.com/aspnet/dnx">DNX</a>向けに、ASP.NETチームの方が実装しちゃってるけども、Roslyn側の協力がほしそう・Roslyn側で取り組んでほしそうな話が2件。</p>
<h3>ICompileModule</h3>
<p><a href="https://github.com/dotnet/roslyn/issues/5561#issuecomment-164688325">https://github.com/dotnet/roslyn/issues/5561#issuecomment-164688325</a></p>
<p>DNX側で、<code>ICompileModule</code>インターフェイスを実装しておけばコンパイルの途中で独自処理を挟めるという実装があったりします。そのタイミングで、Roslynコンパイラーからの内部情報をもらいたいという要望が出ていて、「それはRoslyn側の仕事だ」と誘導されてきたのがこれ。確かに、今、C#でもCode Injector(コンパイル時に処理を挟む仕組み)の検討してるところだし、統合されてほしいところ。</p>
<h3>async Main</h3>
<p><a href="https://github.com/dotnet/roslyn/issues/7476">Async Main [Speclet] #7476</a></p>
<p><code>Main</code>メソッド(プログラムのエントリー ポイント)に非同期メソッドを認めてほしいという話。</p>
<p>これ、DNXではいったん独自に実装したものの、既存の.NET Frameworkコードに対して破壊的変更になるというおしかりが多く、RC版で撤廃されたところなんですよね。</p>
<p>それが改めてRoslyn側で提案されたという。<code>void Main</code>があったらそっちを優先するみたいなルール設ければ破壊的変更にならないはずだし、改めて取り組んでもらいたいところ。</p>
<p>まあ、Roslyn側でも何度かこの話題出てたはず。その時問題になってたのは同期コンテキストをどうするか。といっても、非同期<code>Main</code>以前からの問題で、GUIだと同時実行制御いらない(<code>await</code>したときにUIスレッドに戻ってきて、単一スレッド実行が保証される)のに、コンソール アプリだとそういう仕組みが働かないので<code>lock</code>とか書けないとまずくなるプログラムが出てくるっていう問題。</p>
<h2>インライン アセンブラー</h2>
<p>Roslyn側に提案が出ているわけじゃないんですが。<a href="https://github.com/dotnet/corefxlab">corefxlab</a>上のコードでえげつないものを見てしまい。</p>
<p><a href="https://github.com/dotnet/corefxlab/blob/67d6fa0556d0835c2d779707904d7474ef9da81e/src/System.Slices/src/System/PtrUtils.cs">PtrUtils.cs</a></p>
<p><code>ILSub</code>属性内に文字列でILアセンブリ コードを書いて、それをビルド後処理でILコード刺し込みしてるみたい。何かいいツールがあるのかと思ったら、<a href="https://github.com/dotnet/corefxlab/tree/67d6fa0556d0835c2d779707904d7474ef9da81e/src/System.Slices/tools/ILSub">その処理自体自作</a>。</p>
<p>こんな黒魔術やってる理由は、ガベコレがオブジェクトを追える状態のままポインター操作したいかららしい。それは要件からして大変黒魔術的。パフォーマンス改善のためなので黒魔術になりがちなのはしょうがないんですが、書いてる本人からしてコメントに「なんとか動く」、「きたないトリック」、「Very Bad Things」とか言っている状態。</p>
<p>これ見てると、C#にインラインILアセンブラーを追加してほしいような、追加したいと思うような場面がそもそも魔術的過ぎるような。</p>
<h2>プロトタイプとか仕様とか</h2>
<p>いくつか、プロトタイプ実装が動きだしてたり、仕様が固まり始めてたりしてるみたい。</p>
<ul>
<li>https://github.com/dotnet/roslyn/issues/7445 非null参照型、プロトタイプ実装開始</li>
<li>https://github.com/dotnet/roslyn/issues/357#issuecomment-162603202 covariant return types、詳細詰めれたっぽい</li>
</ul>
 ]]></description>
				<pubDate>Fri, 18 Dec 2015 14:15:14 +0900</pubDate>
			</item>
			<item>
				<title>SystemかMicrosoftか、公式ライブラリの名前</title>
				<link>http://ufcpp.net/blog/2015/12/systemormicrosoft/</link>
				<description><![CDATA[ <p>Windows用として生まれて、クロスプラットフォームに育った.NETの宿命というか。<code>System</code>名前空間から始まるライブラリと、<code>Microsoft</code>名前空間から始まるライブラリの話。</p>
<h2>System or Microsoft</h2>
<p>Systemなんて名前、基本的には標準ライブラリ用なわけですが。</p>
<p>「.NET系開発者はサードパーティ ライブラリにも平然と<code>System</code>の名前を付けることがある」みたいな問題もありますが、それは今回は置いておきます。今回は割かし標準に近いところ、マイクロソフトによる公式実装のライブラリの話です。</p>
<p>「.NET = マイクロソフト」(他のOSは「そのマイクロソフト.NETの移植」)だった頃には割かし何でも<code>System</code>名前空間にされていたわけですが、オープンソース、コミュニティによる推進、クロスプラットフォームなんかをうたうようになった最近はそれではまずいということで、<code>Microsoft</code>名前空間なライブラリが増えています。</p>
<h2>Systemやめました</h2>
<p>Windowsにべったりなものが<code>System</code>名前空間だったんですよねぇ、長らく。それが徐々に、クロスプラットフォームに耐えうるものが<code>System</code>、そうでないものは別の名前空間へと変化。だいたい、2012年頃(Windows 8が出た頃、.NET的には.NET 4.5くらいの頃)が境目。</p>
<h3>GUIフレームワーク</h3>
<p>「Windowsにべったり」というとGUIフレームワーク系のもので、以下のような感じ。わかりやすく、「.NETから分離します」「<code>System</code>やめます」の流れ。</p>
<ul>
<li>
<a href="https://msdn.microsoft.com/ja-jp/library/system.windows.forms.aspx">Windows Forms</a> (System.Windows.Forms.dll)
<ul>
<li>.NET 1.0時代からあるGUI</li>
<li>だいたいのクラスが<code>System.Windows.Forms</code>名前空間</li>
<li>Win32 API感丸出し。</li>
<li>それでも、<a href="http://www.mono-project.com/docs/gui/winforms/">Monoががんばって移植</a>作業したのでなんとか「標準」の体は保ってる</li>
</ul>
</li>
<li>
WPF (WindowsBase.dll, PresentationCore.dll, PresentationFramework.dll)
<ul>
<li>だいたいのクラスが<code>System.Windows</code>名前空間</li>
<li>.NET 3.0。この時代もまだまだ<code>System</code>名前空間</li>
<li>アセンブリ名からは<code>System</code>が外れる</li>
<li>さすがに高機能すぎて移植無理で、完全にWindows用</li>
</ul>
</li>
<li>
<a href="https://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.aspx">Windows Runtime, Windows.UI</a>
<ul>
<li>
ついに、GUIフレームワークは.NETから分離
<ul>
<li>WPF的なものをC++ネイティブ実装した上で、.NETから参照しやすいAPI用意したもの</li>
</ul>
</li>
<li>.NETの世代的には.NET 4.5時代の出来事</li>
<li>名前空間はさすがに<code>Windows</code></li>
</ul>
</li>
</ul>
<h3>Web</h3>
<p>ASP.NETも<code>System</code>名前空間をやめました。まあ「標準」に組み込むにはちょっとでかすぎる感じはあります。</p>
<p>境目は5。ASP.NET MVC 4までは<code>System.Web.Mvc</code>名前空間。ASP.NET MVC 5で<code>Microsoft.AspNet</code>に。Webフレームワークの1つにすぎないASP.NETが<code>Web</code>名前空間を名乗る仰々しさも軽減。</p>
<p>悪名高きSystem.Web.dll (IISにべったり)依存とかも切って、晴れてクロスプラットフォームに。</p>
<h2>Systemやめてませんでした</h2>
<p>ここまではわかりやすく、「<code>System</code>やめました」なものなのでいいんですが。問題はここから。</p>
<h3>プレビュー版実装から標準に昇格</h3>
<p>.NET 4辺りの頃からなんですが、プレビュー版の間は仮に<code>Microsoft</code>名前空間で実装しておいて、標準ライブラリに取り込めるとなった段階で初めて<code>System</code>名前空間に変更するというような開発フローを取っていました。</p>
<ul>
<li>
dynamic関連
<ul>
<li>プレビューの頃は<code>Microsoft.Dynamic</code></li>
<li>.NET 4では<code>System.Dynamic</code></li>
</ul>
</li>
<li>
Task関連
<ul>
<li>プレビューの頃は<code>Microsoft.Threading.Tasks</code></li>
<li>.NET 4では<code>System.Threading.Tasks</code></li>
</ul>
</li>
<li>
async関連
<ul>
<li>
プレビューの頃は<code>Microsoft.Runtime.CompilerServices</code>
<ul>
<li>(<code>Task</code>クラスなどの既存のクラスの拡張は<code>System</code>名前空間。<code>CompilerServices</code>だけが新規)</li>
</ul>
</li>
<li>.NET 4.5では<code>System.Runtime.CompilerServices</code></li>
</ul>
</li>
</ul>
<p>これは「<code>System</code>に正式配属されました」なので問題ないんですが、ちょっと困るのがこの先。</p>
<h3>バックポーティング実装</h3>
<p>この手の新機能を、古いフレームワーク上でも使えるようにするバックポーティング実装があります。</p>
<ul>
<li>
<a href="https://www.nuget.org/packages/Microsoft.Bcl/"><code>Microsoft.Bcl</code></a>
<ul>
<li>.NET 4.5の<code>CallerMemberNameAttribute</code>、<code>Tuple</code>、<code>IProgress</code>なんかを.NET 4で使えるようにするもの</li>
</ul>
</li>
<li>
<a href="https://www.nuget.org/packages/Microsoft.Bcl.Async/"><code>Microsoft.Bcl.Async</code></a>
<ul>
<li>C# 5 (.NET 4.5)の非同期メソッドを.NET 4で使えるようにするもの</li>
</ul>
</li>
<li>
<a href="https://www.nuget.org/packages/Microsoft.Net.Http/"><code>Microsoft.Net.Http</code></a>
<ul>
<li>.NET 4.5の<code>System.Net.Http.HttpClient</code>を.NET 4で使えるようにするもの</li>
</ul>
</li>
</ul>
<p>こいつら、中身の名前空間は<code>System</code>のくせに、パッケージ名は<code>Microsoft</code>。プレビュー時代の名残なのかなんなのか。(未来の)標準ライブラリなのに。</p>
<h3>やっぱりSystemダメでした</h3>
<p>同系統で、一瞬「標準」に昇格した奴がいます。</p>
<ul>
<li>
<a href="https://msdn.microsoft.com/ja-jp/library/system.diagnostics.tracing.eventsource.aspx">System.Diagnostics.Tracing.EventSource</a>
<ul>
<li>ETW (Event Tracing for Windows)へのログ書き込みを.NETから簡単に行えるようにするもの。</li>
<li>.NET 4.5で追加</li>
</ul>
</li>
</ul>
<p>お気づきでしょうか。ETWのWの文字。「for Windows」。これまで「.NET 4.5のあたりでWindowsべったりな奴は<code>System</code>から外れた」とさんざん説明してきたところで、こいつの存在に頭抱えることに。</p>
<p>ちなみに、こいつ、その後も、<code>Microsoft</code>名前空間実装が生き残っていたりします。</p>
<ul>
<li>
<a href="https://www.nuget.org/packages/Microsoft.Diagnostics.Tracing.EventSource/">Microsoft.Diagnostics.Tracing.EventSource</a>
<ul>
<li>
曰く
<ul>
<li>「<code>EventSource</code>クラスは標準にも含まれているけど、こっちの方が新しくて機能多い」</li>
<li>「<code>System.Diagnostics.Tracing.EventSource</code>の方にとりこまれるまでのギャップ解消に使って」</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>「<code>System</code>の方にとりこまれるまで」と書かれているものの、何かこのまま<code>Microsoft</code>の方にすべきなんじゃないかという予感もひしひしと…</p>
<h2>逆に、なぜMicrosoft…</h2>
<p>逆に、「なぜそれを<code>Microsoft</code>名前空間にした」というものもあったりはします。</p>
<p>こいつ。</p>
<ul>
<li>
<a href="https://www.nuget.org/packages/Microsoft.CSharp/">Microsoft.CSharp</a>
<ul>
<li>
C# 4のdynamicの中で使うやつ
<ul>
<li>C#のオーバーロード解決ルールに従って、実行時バインディングするためのライブラリ</li>
</ul>
</li>
<li>
この名前で、C#コンパイラーそのものを指すライブラリではないのでそこも要注意
<ul>
<li>コンパイラーそのものは<a href="https://www.nuget.org/packages/Microsoft.CodeAnalysis.CSharp/">Microsoft.CodeAnalysis.CSharp</a></li>
</ul>
</li>
</ul>
</li>
</ul>
<p>C# 4のdynamicを使うのに必須のライブラリです。Mono版C#コンパイラーでも必須(Mono版の<code>Microsoft.CSharp</code>実装あり)です。確かに、C#に依存した機能なので<code>System</code>名前空間だと変なんですが。一方で、マイクロソフト実装でなくても必須なものに<code>Microsoft</code>名前空間というのも嫌な感じで。</p>
<h2>まとめ</h2>
<p>最近のノリだと、</p>
<ul>
<li>.NET Core (オープンソースでクロスプラットフォームな.NET)でも「標準」となるべき基本ライブラリだけが<code>System</code>名前空間</li>
<li>その他のマイクロソフト公式実装は<code>Microsoft</code>名前空間</li>
</ul>
<p>になっているんですが、過去さかのぼると何でも間でも<code>System</code>名前空間だったし、その名残がいまだちらほらあったりします。特に、<code>System.Diagnostics.Tracing.EventSource</code>とかどうするんだろう…</p>
 ]]></description>
				<pubDate>Mon, 14 Dec 2015 12:40:03 +0900</pubDate>
			</item>
			<item>
				<title>.csproj + project.json</title>
				<link>http://ufcpp.net/blog/2015/12/csprojprojectjson/</link>
				<description><![CDATA[ <p>Visual Studio 2015 Update 1で、<code>.csproj</code> + <code>project.json</code> 構成のプロジェクトを、<code>.xproj</code> プロジェクトから参照しようとしたら素直にはできなったという話と、自力で何とかしたという話。</p>
<h2>大雑把に言って</h2>
<p>面倒ごとが起きる原因はおおむね、ASP.NET 系の作業が来年初頭に伸びてるのと、UWP 系の作業が今年7月に前倒したのとの合わせ技のせい。</p>
<p>たぶん、ASP.NET 5系/.NET CoreのRTM(来年の第1四半期内という予定)までには治るかなぁ。</p>
<h2>ASP.NET 系</h2>
<p>オープンソース化とかクロスプラットフォーム路線を一番推し進めてるのはここ。.NET Coreのランタイム(CoreCLR)を一番欲してるのもここ。</p>
<h3>xproj 形式</h3>
<p>ASP.NET 5や、.NET Core向けライブラリ、.NET Core向けコンソール アプリを書く場合、プロジェクトが<code>.xproj</code>という新しい形式になっています。</p>
<p>ASP.NET 系ではプロジェクト中のソースコードとかパッケージ管理を簡素化したいみたい。既存の<code>.csproj</code> (もしくはVBの場合は<code>.vbproj</code>)との違いは以下の表のような感じ。</p>
<table>
<tr>
<td></td>
<th>
これまで(<code>.csproj</code>形式)
</th>
<th>
新方式(<code>.xproj</code>形式)
</th>
</tr>
<tr>
<th>ファイル管理</th>
<td>`.csproj`ファイルの中に、ビルドに含めたいファイルを全部1行1行書く</td>
<td>特定フォルダー以下のC#ファイル全部がビルド対象。除外したいものだけ`exclude`設定を書く</td>
</tr>
<tr>
<th>ライブラリ参照</th>
<td>プロジェクト参照、DLLの直接参照、NuGetパッケージ参照が分かれてる。特に、NuGetパッケージは`packages.config`という別ファイルに記述</td>
<td>この3つを一元化</td>
</tr>
<tr>
<th>ビルド処理</th>
<td>XAMLとか、ビルド時処理が必要なものを含めたり、汎用的な使い方ができる</td>
<td>基本的にWeb用で、HTMLやJavaScriptみたいにそのままデプロイしたいファイルか、C#ファイルのコンパイルくらい</td>
</tr>
</table>
<h3>project.json</h3>
<p>実際のところ、<code>.xproj</code>ファイルの中にはVisual Studioに関する設定しか入っていなくて、実際プロジェクトのビルドに必要な情報は全部<code>project.json</code>という名前のJSONファイルに入っています。コマンドライン ビルドするなら<code>.xproj</code>ファイルは不要。</p>
<p><code>project.json</code>には、以下のような情報が入っています。</p>
<ul>
<li>(プロジェクトをNuGetパッケージ化するとき用の)名前、バージョン、作者など</li>
<li>
ターゲット
<ul>
<li>フレームワークのバージョン(.NET 4.5とか)</li>
<li>実行環境(Windows とか)</li>
</ul>
</li>
<li>
依存関係
<ul>
<li>NuGetパッケージ</li>
<li>他のプロジェクト</li>
<li>DLLを直接参照</li>
</ul>
</li>
</ul>
<h2>NuGet 3</h2>
<p>.NET Coreは、Windowsデスクトップ向けの.NET Frameworkと違って、ライブラリの参照を、たとえ標準ライブラリでも、必要な分だけNuGetパッケージとして参照する仕組みになっています。一枚岩リリース/巨大インストーラーの撤廃。パッケージ リリース化。</p>
<p>ということでNuGetの利用が加速すると思われるわけですが、そこで、NuGetの利便性向上が必須。
これまでのNuget(2系、<code>packages.config</code>)には以下のような問題がありました。</p>
<ul>
<li>
1つのプロジェクトを複数のソリューションから参照するとビルドできなくなる
<ul>
<li>ダウンロードしてきたパッケージをソリューション単位でキャッシュする</li>
<li><code>.csproj</code>側にキャッシュしたDLLへの相対パスが入る</li>
<li>ソリューションの場所が違うと相対パスが狂う</li>
</ul>
</li>
<li>
依存関係を芋ずる式に含む
<ul>
<li>依存先のさらに依存先も、<code>packages.config</code>や<code>.csproj</code>に情報が追加される</li>
<li>「依存先の依存先」とかも含めたバージョン管理がむちゃくちゃ大変に</li>
</ul>
</li>
</ul>
<p>例えば、<a href="https://www.nuget.org/packages/Rx-Main/">Rx-Main</a>を参照したとします。まず、<code>packages.config</code>っていうXMLファイルができて、以下のような状態に。</p>
<pre class="xsource" title="">
<code><attvalue></span><span class="attvalue">&lt;?</span><span class="element">xml</span><span class="attvalue"> </span><span class="attribute">version</span><span class="attvalue">=</span>"<span class="attvalue">1.0</span>"<span class="attvalue"> </span><span class="attribute">encoding</span><span class="attvalue">=</span>"<span class="attvalue">utf-8</span>"<span class="attvalue">?&gt;</span>
<span class="attvalue">&lt;</span><span class="element">packages</span><span class="attvalue">&gt;</span>
<span class="attvalue">  &lt;</span><span class="element">package</span><span class="attvalue"> </span><span class="attribute">id</span><span class="attvalue">=</span>"<span class="attvalue">Rx-Core</span>"<span class="attvalue"> </span><span class="attribute">version</span><span class="attvalue">=</span>"<span class="attvalue">2.2.5</span>"<span class="attvalue"> </span><span class="attribute">targetFramework</span><span class="attvalue">=</span>"<span class="attvalue">net46</span>"<span class="attvalue"> /&gt;</span>
<span class="attvalue">  &lt;</span><span class="element">package</span><span class="attvalue"> </span><span class="attribute">id</span><span class="attvalue">=</span>"<span class="attvalue">Rx-Interfaces</span>"<span class="attvalue"> </span><span class="attribute">version</span><span class="attvalue">=</span>"<span class="attvalue">2.2.5</span>"<span class="attvalue"> </span><span class="attribute">targetFramework</span><span class="attvalue">=</span>"<span class="attvalue">net46</span>"<span class="attvalue"> /&gt;</span>
<span class="attvalue">  &lt;</span><span class="element">package</span><span class="attvalue"> </span><span class="attribute">id</span><span class="attvalue">=</span>"<span class="attvalue">Rx-Linq</span>"<span class="attvalue"> </span><span class="attribute">version</span><span class="attvalue">=</span>"<span class="attvalue">2.2.5</span>"<span class="attvalue"> </span><span class="attribute">targetFramework</span><span class="attvalue">=</span>"<span class="attvalue">net46</span>"<span class="attvalue"> /&gt;</span>
<span class="attvalue">  &lt;</span><span class="element">package</span><span class="attvalue"> </span><span class="attribute">id</span><span class="attvalue">=</span>"<span class="attvalue">Rx-Main</span>"<span class="attvalue"> </span><span class="attribute">version</span><span class="attvalue">=</span>"<span class="attvalue">2.2.5</span>"<span class="attvalue"> </span><span class="attribute">targetFramework</span><span class="attvalue">=</span>"<span class="attvalue">net46</span>"<span class="attvalue"> /&gt;</span>
<span class="attvalue">  &lt;</span><span class="element">package</span><span class="attvalue"> </span><span class="attribute">id</span><span class="attvalue">=</span>"<span class="attvalue">Rx-PlatformServices</span>"<span class="attvalue"> </span><span class="attribute">version</span><span class="attvalue">=</span>"<span class="attvalue">2.2.5</span>"<span class="attvalue"> </span><span class="attribute">targetFramework</span><span class="attvalue">=</span>"<span class="attvalue">net46</span>"<span class="attvalue"> /&gt;</span>
<span class="attvalue">&lt;/</span><span class="element">packages</span><span class="attvalue">&gt;
</code></pre>
<p>Rx-InterfacesとかRx-Linqは、Rx-Mainの依存先です。芋ずる式に全部。</p>
<p>そして、このファイルだけじゃなくて、<code>.csproj</code>ファイルにも以下のような行が追加されます。</p>
<pre class="xsource" title="">
<code><attvalue></span><span class="attvalue">    &lt;</span><span class="element">Reference</span><span class="attvalue"> </span><span class="attribute">Include</span><span class="attvalue">=</span>"<span class="attvalue">System.Reactive.Core, Version=2.2.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL</span>"<span class="attvalue">&gt;</span>
<span class="attvalue">      &lt;</span><span class="element">HintPath</span><span class="attvalue">&gt;</span>..\packages\Rx-Core.2.2.5\lib\net45\System.Reactive.Core.dll<span class="attvalue">&lt;/</span><span class="element">HintPath</span><span class="attvalue">&gt;</span>
<span class="attvalue">      &lt;</span><span class="element">Private</span><span class="attvalue">&gt;</span>True<span class="attvalue">&lt;/</span><span class="element">Private</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;/</span><span class="element">Reference</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">Reference</span><span class="attvalue"> </span><span class="attribute">Include</span><span class="attvalue">=</span>"<span class="attvalue">System.Reactive.Interfaces, Version=2.2.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL</span>"<span class="attvalue">&gt;</span>
<span class="attvalue">      &lt;</span><span class="element">HintPath</span><span class="attvalue">&gt;</span>..\packages\Rx-Interfaces.2.2.5\lib\net45\System.Reactive.Interfaces.dll<span class="attvalue">&lt;/</span><span class="element">HintPath</span><span class="attvalue">&gt;</span>
<span class="attvalue">      &lt;</span><span class="element">Private</span><span class="attvalue">&gt;</span>True<span class="attvalue">&lt;/</span><span class="element">Private</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;/</span><span class="element">Reference</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">Reference</span><span class="attvalue"> </span><span class="attribute">Include</span><span class="attvalue">=</span>"<span class="attvalue">System.Reactive.Linq, Version=2.2.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL</span>"<span class="attvalue">&gt;</span>
<span class="attvalue">      &lt;</span><span class="element">HintPath</span><span class="attvalue">&gt;</span>..\packages\Rx-Linq.2.2.5\lib\net45\System.Reactive.Linq.dll<span class="attvalue">&lt;/</span><span class="element">HintPath</span><span class="attvalue">&gt;</span>
<span class="attvalue">      &lt;</span><span class="element">Private</span><span class="attvalue">&gt;</span>True<span class="attvalue">&lt;/</span><span class="element">Private</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;/</span><span class="element">Reference</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;</span><span class="element">Reference</span><span class="attvalue"> </span><span class="attribute">Include</span><span class="attvalue">=</span>"<span class="attvalue">System.Reactive.PlatformServices, Version=2.2.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL</span>"<span class="attvalue">&gt;</span>
<span class="attvalue">      &lt;</span><span class="element">HintPath</span><span class="attvalue">&gt;</span>..\packages\Rx-PlatformServices.2.2.5\lib\net45\System.Reactive.PlatformServices.dll<span class="attvalue">&lt;/</span><span class="element">HintPath</span><span class="attvalue">&gt;</span>
<span class="attvalue">      &lt;</span><span class="element">Private</span><span class="attvalue">&gt;</span>True<span class="attvalue">&lt;/</span><span class="element">Private</span><span class="attvalue">&gt;</span>
<span class="attvalue">    &lt;/</span><span class="element">Reference</span><span class="attvalue">&gt;</span>
</code></pre>
<p>そこで、NuGet 3系(7月のVS 2015リリースの頃に3.0、今は3.3)では、パッケージの管理方式を変えました。</p>
<ul>
<li>ダウンロードしてきたパッケージはユーザー単位でキャッシュ(ユーザー フォルダー直下に<code>.nuget</code>フォルダーを作ってそこで一元管理)</li>
<li><code>.csproj</code>や<code>.xproj</code>はノータッチ、<code>project.json</code>にだけ情報を記録</li>
<li>直接の依存先だけを記録</li>
</ul>
<p>例えば、同じくRx-Mainを参照すると、<code>project.json</code>ファイルが以下のような状態になります。</p>
<pre class="source" title="">
<code>{
  "frameworks": {
    "net46": {}
  },
  "runtimes": {
    "win": {},
    "win-anycpu": {}
  },
  "dependencies": {
    "Rx-Main": <span class="string">"2.2.5"</span>
  }
}
</code></pre>
<p>だいぶすっきりして、管理が楽になりました。</p>
<p>そして、NuGet 3系は、これまでの<code>packages.config</code>を止めて、ASP.NET 5に合わせて<code>project.json</code>を使うようになりました。</p>
<h2>UWP 系</h2>
<p>Universal Windows Platformアプリ。要するにWindows 10向け。</p>
<p>元々は.NET Coreと同じスケジュール感で動いていた雰囲気があるんですが、Windows 10の前倒しに合わせて、UWP系ツールのリリースも今年7月に前倒しになりました。</p>
<p>ライブラリに関しては、UWPと.NET Coreは共通のものを使います(.NET Core向けフレームワーク、略してCoreFX)。
その結果、.NET CoreはRC(7月時点ではベータ)なのに、UWPはUpdate 1(7月時点ではRTM)。Update 1なUWPが、RCなCoreFXに依存しているという状態になっていたりします。</p>
<p>ちなみに、CoreFXの祖先はWindows 8のストア アプリ(かつてメトロと呼ばれていた何か)向け.NETです。Windows 8の時点で、パッケージ リリース化・クロスプラットフォーム化を前提としたライブラリ整理が完了しています。
なので、.NET Core全体はRCといっても、CoreFXの部分は十分こなれてはいます。</p>
<h3>.csproj + project.json</h3>
<p>ここで、UWP系ツールの苦悩が。</p>
<ul>
<li>割かしWeb前提なところがある<code>.xproj</code>は使えない</li>
<li>でも、NuGet 3系(<code>project.json</code>に移行)は使いたい</li>
</ul>
<p>ということで、UWP系ツールは<code>.csproj</code> + <code>project.json</code>というハイブリッド構成になっています。</p>
<p>ここでおさらい。</p>
<ul>
<li><code>.xproj</code>にはVisual Studioが必要とする少ない情報しか入っていなくて、プロジェクト関連の設定は全部<code>project.json</code>に入ってる</li>
<li>
<code>.csproj</code>にはプロジェクト関連の設定が全部入ってる
<ul>
<li>NuGet  2系では、NuGetパッケージ参照情報が<code>packages.config</code>と<code>.csproj</code>で2重管理になっていた</li>
</ul>
</li>
</ul>
<p>ということで、UWP系ツールでは、</p>
<ul>
<li>
<code>.csproj</code>からはNuGetパッケージ参照情報を消した
<ul>
<li>NuGet 3系リリースと同時にVisual Studio側にも手が入って、<code>project.json</code>側だけ見ればよくなった</li>
</ul>
</li>
<li><code>project.json</code>にはNuGetパッケージ参照情報だけが入ってる(<code>.xproj</code>で使う場合のサブセット)</li>
</ul>
<p>という状態になっています。</p>
<h2>任意のプロジェクトでNuGet 3</h2>
<p>NuGet 3系は<code>project.json</code>を前提にしています。ASP.NET 5系は最初から<code>project.json</code>で、NuGet 3系です。UWP系は<code>.csproj</code> + <code>project.json</code>というハイブリッド構成でNuGet 3系に対応しました。さて、じゃあ、既存の<code>.csproj</code>で作っていたライブラリやコンソール アプリ、WPFアプリなどはどうか。</p>
<p><code>.csproj</code> + <code>project.json</code>は、公式ドキュメントによれば以下のような状態です。</p>
<ul>
<li>公式にプロジェクト テンプレートがあって、「マイクロソフトがサポートします」と言っているのはUWPだけ</li>
<li>ただし、手動で<code>packages.config</code>を<code>project.json</code>に置き換えれば、実は任意の<code>.csproj</code>でNuGet 3系を使える</li>
</ul>
<p>ということで、<code>packages.config</code>から<code>project.json</code>への移行プログラムを自分で書いたのが以下のものになります。</p>
<ul>
<li><a href="https://github.com/ufcpp/UfcppSample/tree/master/Tools/DnxMigration/MigrateToProjectJson">MigrateToProjectJson</a></li>
</ul>
<h2>.xprojから.csprojを参照</h2>
<p>なにぶん<code>.xproj</code>は新しい試みなので、まだまだ足りてないところがあります。ASP.NET 5や.NET Core本体がだいぶ安定してきても、Visual Studio上の<code>.xproj</code>の挙動が安定するまではRTMにできないんだろうなぁという雰囲気。</p>
<p>その1つが<code>.xproj</code>から既存の<code>.csproj</code>で作ったライブラリをプロジェクト参照する方法。以下のようなラッパーとなる<code>project.json</code>を書いてやる必要があります。</p>
<pre class="source" title="">
<code>{
  "version": <span class="string">"1.0.0-*"</span>,
  "frameworks": {
    "net35": {
      "wrappedProject": <span class="string">"../../ClassLibraryNet35/ClassLibraryNet35.csproj"</span>,
      "bin": {
        "assembly": <span class="string">"../../ClassLibraryNet35/obj/{configuration}/ClassLibraryNet35.dll"</span>,
        "pdb": <span class="string">"../../ClassLibraryNet35/obj/{configuration}/ClassLibraryNet35.pdb"</span>
      }
    }
  },
  "dependencies": { }
}
</code></pre>
<p><code>.xproj</code>が出た当初はこいつの手書きが必須でした。Visual Studio 2015がRTMしたころには、一応Visual Studioがこいつを生成してくれるようにはなっています。</p>
<p>ただ、ここでまた問題があって、<code>.csproj</code> + <code>project.json</code>構成にしてしまった<code>.csproj</code>プロジェクトを参照すると挙動が狂います。
上記のようなラッパー<code>project.json</code>がまともに作られなくなったり、
<code>.csproj</code>で参照している側の<code>project.json</code>が変に書き換わってビルドできなくなったり。</p>
<p>公式には、UWP系以外の<code>.csproj</code> + <code>project.json</code>構成は「できるけどサポート対象外」なので、この問題は現状では「自己責任」扱いではあります。</p>
<p>ということで、結局、ラッパー<code>project.json</code>の生成も自前でプログラム書きました。</p>
<ul>
<li><a href="https://github.com/ufcpp/UfcppSample/tree/master/Tools/DnxMigration/GenerateWrapJson">GenerateWrapJson</a></li>
</ul>
<h2>まとめ</h2>
<p>ASP.NET 5系は来年第1四半期にRTM予定、UWP系は今年7月にRTM済み。そんな中、ASP.NET 5系とUWP系で共通で使っている部分が結構カオス。</p>
<p>それ以外のタイプのプロジェクトでも、自力で<code>.csproj</code> + <code>project.json</code>構成にすればNuGet 3系の恩恵にあずかれます。ただし、現状は「できるけどマイクロソフトのサポート対象外、自己責任」。ということで自力で何とかするプログラム書きました。</p>
<ul>
<li><a href="https://github.com/ufcpp/UfcppSample/tree/master/Tools/DnxMigration/MigrateToProjectJson">MigrateToProjectJson</a></li>
<li><a href="https://github.com/ufcpp/UfcppSample/tree/master/Tools/DnxMigration/GenerateWrapJson">GenerateWrapJson</a></li>
</ul>
<p>おそらく、ASP.NET 5系RTMの来年第1四半期に合わせて、この辺りの挙動をやっと仕上げるんじゃないかなぁという気はしています。それまでの数か月間のつなぎに。</p>
 ]]></description>
				<pubDate>Wed, 09 Dec 2015 02:13:21 +0900</pubDate>
			</item>
			<item>
				<title>async/await その後/追記</title>
				<link>http://ufcpp.net/blog/2015/12/asyncawaitpost/</link>
				<description><![CDATA[ <p>昨日、<a href="http://ufcpp.net/blog/2015/12/unityasync0introduction/">Unity 上での async/await の話</a>と、そのついでに<code>Task</code>クラスでかすぎるよとか、async/awaitは<code>Task</code>依存強すぎかなぁとか書いたわけですが。</p>
<p>ちょうどその関連の話題が2件ほど出てたので追記。</p>
<p>ほんと、これがもう2年早く出ていれば<a href="https://github.com/OrangeCube/MinimumAsyncBridge">MinimumAsyncBridge</a>の実装もっと楽だったのに。</p>
<h2>Unity カスタム コルーチン</h2>
<p>Unity 5.3 で<code>CustomYieldInstruction</code>ってクラスが追加されて、これを実装すればコルーチン内で<code>yield return</code>で返して、「待ってもらえる」型を自作できるようになるとのこと。</p>
<ul>
<li><a href="http://blogs.unity3d.com/jp/2015/12/01/custom-coroutines/">カスタムコルーチン</a></li>
</ul>
<p>今まであった<code>YieldInstruction</code>クラスとか、メンバー何もなくて、お前何のために居るんだよ。C# 的にはそういうマーカー用の基底クラス作る文化ねぇよ。そういうのには属性使えよ。とかいう状態だったわけですが。</p>
<p><code>YieldInstruction</code>なんて、まだ「待っててほしいかどうか」を<code>bool</code> 1個返すだけでカスタム処理掛けるし、awaitやら<code>Task</code>クラスやらと比べたらだいぶ簡素なんだから最初から<code>CustomYieldInstruction</code>提供してくれればいいのに… とずっと思っていたものがやっと実装されるそうです。</p>
<h2>任意の「Task 風の型」</h2>
<p>一方で、C# のawaitは<code>Task</code>クラスに依存しすぎって話も書いてたわけですが。ちょうど<a href="https://github.com/dotnet/roslyn/">Roslynリポジトリ</a>にそれ関連のissueページが立ちました。</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/issues/7169">Proposal: arbitrary task-like types returned from async methods #7169</a></li>
</ul>
<p>任意の<code>Task</code>風の型を非同期メソッドの戻り値にできるようにする提案。</p>
<h3>要求はずっとある</h3>
<p>先日も言った通り、C# 5.0の仕様が公開された瞬間からさんざん「<code>Task</code>以外も使いたい」って要望は出てます。</p>
<p>Microsoft内部都合的にいっても、<a href="http://www.atmarkit.co.jp/ait/articles/1506/23/news012.html">UWP</a>(WinRT)だと非同期処理には<code>IAsyncAction</code>インターフェイスを使わないと行けない(<code>Task</code>に対するラッパーを1段かまさないと行けなくて面倒)とかあったり。</p>
<p><a href="https://github.com/dotnet/corefxlab/blob/master/src/System.Threading.Tasks.Channels/src/System/Threading/Tasks/ValueTask.cs">ValueTask</a>なんかの話もある様子。非同期処理の結果をキャッシュとして持つにあたって、クラス(= <a href="http://ufcpp.net/study/csharp/oo_reference.html#reftype">参照型</a>、ヒープ圧迫)である<code>Task</code>は避けたくて、構造体(= <a href="http://ufcpp.net/study/csharp/oo_reference.html#valtype">値型</a>)版がほしいって言う需要があり。C#は最近、パフォーマンス向上に向けて結構攻めてたりします。</p>
<p>あと、これがあれば例えば、「同期コンテキスト拾わない版<code>Task</code>」みたいなのを作れて、<a href="http://neue.cc/2013/10/10_429.html"><code>ConfigureAwait(false)</code>付けまくらないと死ぬ問題</a>を多少マシにできるかも。</p>
<h3>問題と対策、提案内容</h3>
<p>そもそもC# 5.0導入当時の背景として、</p>
<ul>
<li>C# 5.0を出すときに、一度は検討したし、実際プロトタイプ実装はした</li>
<li>ジェネリックな型に対して型推論がきれいにできなかった</li>
<li>それを問題視してこの実装は正式版には取り入れなかった</li>
</ul>
<p>ってのがあります。</p>
<p>とりあえず、複雑な型推論はやっぱりあきらめる必要がありそう。まあ、戻り値側を見ての推論が必要な型とかはやっぱり無理。そこさえあきらめれば、現状の<code>Task</code>クラス前提のasync/awaitと同程度の型推論はちゃんとできるっぽい。もしかしたら、C# 5.0当時よりも今の方が型推論が賢いので、今だからこそってのもあるのかもしれないですね。</p>
<p>非同期メソッドの戻り値として使いたい型(<code>Task</code>風の型)を作りたい場合は、以下のような型を書けとのこと。</p>
<pre class="source" title="">
<code>[TaskLike(<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">typeof</span>(FooBuilder))] <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">struct</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">Foo</span> { … }
<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">struct</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">FooBuilder</span> { … similar to AsyncVoidMethodBuilder … }

[TaskLike(<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">typeof</span>(FooBuilder&lt;T&gt;))] <span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">struct</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">Foo</span>&lt;T&gt; { … }
<span class="pl-k" style="box-sizing: border-box; color: rgb(167, 29, 93);">struct</span> <span class="pl-en" style="box-sizing: border-box; color: rgb(121, 93, 163);">FooBuilder</span>&lt;T&gt; { … similar to AsyncTaskMethodBuilder&lt;T&gt; … }
</code></pre> ]]></description>
				<pubDate>Wed, 02 Dec 2015 02:43:12 +0900</pubDate>
			</item>
			<item>
				<title>Unity上でasync/await: 課題と感想</title>
				<link>http://ufcpp.net/blog/2015/12/unityasync3retrospective/</link>
				<description><![CDATA[ <p><a href="https://github.com/OrangeCube/MinimumAsyncBridge">MinimumAsyncBridge</a>化してみてどうかと、
<a href="https://github.com/OrangeCube/MinimumAsyncBridge">MinimumAsyncBridge</a>を作った感想など。</p>
<h2>作業難易度</h2>
<p><a href="http://referencesource.microsoft.com/">参考にした元</a>があって、書き換えが必要だった部分もごく少量で、
大した手間もかけずに移植してます。最初から安定しているのも当たり前で。</p>
<p>まあほんとは、もっと昔から.NETがオープンソースだったら…というのはありますが。</p>
<p>IL2CPPで動かなくて困ったりした時期はありますが、この辺りは、別に<code>Task</code>クラスのせいじゃなくてそこかしろでバグだらけだったので。
ただひたすらにIL2CPPの安定を待っていただけ。</p>
<h2>導入した感想</h2>
<p>やっぱり普通にC# 5.0のasync/awaitが書けるのはむちゃくちゃ楽です。
自分だけじゃなく、チーム全体で言っても、かなりの作業量が浮いてるんじゃないかと。</p>
<p>途中まで<a href="https://github.com/OrangeCube/IteratorTasks">IteratorTasks</a>を使っていて、
思い立ったかのように<a href="https://github.com/OrangeCube/MinimumAsyncBridge">MinimumAsyncBridge</a>に移行するのに1・2週間ほど使いましたが、
その作業分は余裕で取り戻せているのではないかと思います。</p>
<p>何よりも、</p>
<ul>
<li>最新のC#を問題なく使える</li>
<li>「もどき」じゃなく、標準<code>Task</code>の完全下位互換で、単一DLLで完全にコード共通化できる</li>
</ul>
<p>という辺りは非常に大きい。</p>
<h2>Taskクラスの問題</h2>
<p>バックポーティング作業をやっていて感じたのは、<code>Task</code>クラスの債務がでかすぎるという問題。</p>
<p><code>Task</code>クラスは、以下のような処理を全部担います。</p>
<ul>
<li>スレッド(<code>Task.Run</code>)</li>
<li>I/O完了ポート(非同期API)</li>
<li>ハードウェアタイマー(<code>Task.Delay</code>)</li>
<li>他とのつなぎ(<code>TaskCompletionSource</code>)、C++でいうfuture/promise</li>
</ul>
<p>全部1つのクラス。他の言語だと、「他とのつなぎ」だけ用意して、
スレッドとかは別途そいつで軽く包んでるだけなことが多いんですけども。
.NETのTaskは割かし全部入り。</p>
<p>このうち、async/awaitを使うだけなら<code>TaskCompletionSource</code>だけあれば何とかなるんですよねぇ。
なのに、そこだけを抜き出して取ってこれない。
おまけでいろいろ、しかもスレッド関連とかいう難しい処理も持ってこないといけない。</p>
<p>例えば以下のような問題があったり。</p>
<ul>
<li>
<code>GetAwaiter</code>が、.NET 4.5で<code>Task</code>クラスに追加されてる
<ul>
<li>型フォワーディングの仕組みでは、クラスの追加はバック ポーティングできるけど、既存クラスへのメソッド追加は無理</li>
<li>結果、.NET 3.5と4.5では動くけど、.NET 4では動かないライブラリになってる</li>
</ul>
</li>
<li>
非同期メソッドの戻り値が<code>Task</code>固定で、インターフェイスとかになってない
<ul>
<li>インターフェイスになっていれば、独自実装がしやすかったはず</li>
<li><code>Task</code>クラスみたいにでかいものを移植しなくて済む</li>
</ul>
</li>
</ul>
<p>全部1つでやってるので性能はいいし、利用者視点の利便性はいいとは思います。
そもそもなぜ非同期処理なんて面倒な事するかというとパフォーマンスを求めてなわけで、
<code>Task</code>実装ではパフォーマンスを妥協できなかったというのはあるようです。
あと、async/awaitを変に汎用化しようとすると、
asyncメソッドのオーバーロード解決とかで苦労するらしい(非同期が絡むと型推論が効かなくなったり)。
利便性劣化に直結。</p>
<p>一方で、<code>Task</code>を実装する側、
例えば.NET Coreで今絶賛クロスプラットフォーム化作業してる方々とか、
Monoの方々とか、
今回の僕みたいに独自にバック ポーティングすることにした人にとってはこのでかい実装はほんとに面倒。</p>
<p>C#のasync/awaitはそういうでっかい一枚岩の上に乗っかっちゃってるって意味では将来リスクは結構負っています。
この辺りはF#方面の人らは「だからC#はダメだ」とか言ったりするものの。
ここは方向性の違いというか、C#的には「性能と利用者利便性を考えたらTaskに乗るしかなかった」と言われると妥協せざるを得ず。</p>
<p>最近他の言語でもasync/await対応し始めてますけど、それらの言語でも「どこまで汎用化するか」は大きな争点になってるはずです。
まあ、async/awaitに関してはF#もC#も先駆者なので、負の遺産にはなりやすいかもなぁ(F#はパフォーマンス的にペナルティ結構負ってるはずだし、C#は一枚岩の上に載ってるリスクあり)という気はしなくもないです。
もっとも、それを心配しないといけなくなるのはまだまだ5年10年先の話だと思いますが。</p>
<h2>まとめ</h2>
<p>元コードがあるんであっさり動いて当然。
ただ、もっと最初からオープンだったらわざわざ自分が苦労する必要なかったという気もします。</p>
<p>C# 5.0登場時(アイディアが出たのは5・6年前。RTMが2012年)にも言われていたことではあるんですが、
<code>Task</code>クラスはちょっと債務がでかすぎるよなぁというのは改めて思いました。</p>
<p>まあ、とりあえず安定して動いたし、その結果、かなり開発が楽になったので実装してよかったと思います。</p>
 ]]></description>
				<pubDate>Mon, 30 Nov 2015 15:02:23 +0900</pubDate>
			</item>
			<item>
				<title>Unity上でasync/await: 現状</title>
				<link>http://ufcpp.net/blog/2015/12/unityasync2currentstatus/</link>
				<description><![CDATA[ <p><a href="https://github.com/OrangeCube/MinimumAsyncBridge">MinimumAsyncBridge</a>の現状について。
どのくらい真っ当に動いているか。</p>
<p>ちなみに、<a href="http://ufcpp.net/blog/2015/07/unityasyncbridge/">7月に書いたとき</a>には自分の個人アカウントのリポジトリにコードを置いていましたが、
今は、[会社アカウント]((https://github.com/OrangeCube/)の方に移っています。</p>
<h2>実装状況</h2>
<p><a href="http://ufcpp.net/blog/2015/12/UnityAsync1Background">背景</a>でも説明した通り、<code>Run</code>メソッド(別スレッドで処理を開始する)は実装していません。
ここはUnityコルーチンとかRxとつないで使う想定です。</p>
<p>一方で、Minimumと言いつつ、<code>Delay</code>、<code>WhenAll</code>、<code>WhenAny</code>は実装しました。</p>
<p>これで、実プロジェクトに組み込んで使っていますが、ほぼ要件足りています。
async/awaitを使いたい動機が主にサーバーとの通信(I/O非同期)で、スレッド処理(CPU非同期)をあまり必要としていないという背景はありますが。</p>
<p>4か月使ってみて、MinimumAsyncBridge由来の問題に当たって困ったことはほぼないですし、
困ったのはだいたい実装ミスで、現在では修正済みです。</p>
<h2>IteratorTasksからの移行</h2>
<p>今開発中のプロジェクト、7月までは非同期処理に<a href="https://github.com/OrangeCube/IteratorTasks">IteratorTasks</a>を使っていました。</p>
<p>IteratorTasksも「<code>Task</code>もどき」なので、この移行作業もそこまでは苦労しませんでした。必要なのは、</p>
<ul>
<li>名前空間を <code>IteratorTasks</code> から <code>System.Threading.Tasks</code> に変える</li>
<li><code>IEnumerator</code>、<code>yield return</code> を <code>Task</code>、<code>await</code> に変えて回る</li>
</ul>
<p>を地道にやること。それなりに地道な作業なんですが… MinimumAsyncBridgeの移植やらバグ修正をしながらの同時作業で1・2週間ほどで完了。</p>
<p>もし、IteratorTasksを使っていただけてる方で、この地道な作業をするほどの時間は取れないという場合があれば、
IteratorTasksに対するawaiter実装もあるので、これが使えるかも。</p>
<ul>
<li><a href="https://github.com/OrangeCube/MinimumAsyncBridge/tree/master/src/IteratorTasks.AsyncBridge">IteratorTasks.AsyncBridge</a></li>
</ul>
<h2>本家 Task の完全下位互換</h2>
<p><code>Run</code>メソッドみたいに意図して実装していないものを除いて、
本家<code>Task</code>クラスと互換性があります。</p>
<p>要するに、完全下位互換。
<a href="https://github.com/OrangeCube/MinimumAsyncBridge">MinimumAsyncBridge</a>を使って動けば、
.NET 4.6以降では本家<code>Task</code>を使って100%動きます
(逆は、実装していないメソッドを避けないとダメ)。
<a href="https://msdn.microsoft.com/ja-jp/library/system.threading.tasks.task.completedtask.aspx"><code>CompletedTask</code></a>とか、.NET 4.6での追加分も実装してあるのでこの辺りを使うと.NET 4.5では動かなくなりますが、それを避ければ.NET 4.5でも動きます。</p>
<p>ちなみに、<a href="http://ufcpp.net/study/csharp/package/typeforwarding/?p=3#backporting">型フォワーディング</a>という仕組みを使っていて、</p>
<ul>
<li>.NET 3.5 (Unity)向けライブラリで<a href="https://github.com/OrangeCube/MinimumAsyncBridge">MinimumAsyncBridge</a>を使う</li>
<li>.NET 4.5向けライブラリで本家<code>Task</code>クラスを使う</li>
<li>これらのライブラリを混在させて、.NET 4.5向けアプリを書く</li>
</ul>
<p>というようなこともできます。.NET 4.5向けアプリから<a href="https://github.com/OrangeCube/MinimumAsyncBridge">MinimumAsyncBridge</a>を使うと、
本家<code>Task</code>クラスに転送されます。</p>
<p>実際、今作っているゲームは.NET 3.5と4.5混在です。</p>
<ul>
<li>ちょっとしたデバッグをコンソール アプリで</li>
<li>ボット使った動作テストしたいときにボットをコンソール アプリで</li>
<li>可視化したいデータがあったときにWPFでGUIをちょろっと</li>
<li>データの編集ツールはWPF製</li>
<li>(基本、サーバー側は外注なので他社、かつ、PHPなものの)一部、CPU酷使しそうな機能はC#で実装</li>
</ul>
<p>これらのプログラムは全部、Unity上で動かすゲームのロジックを共有しています(ソースコード レベルでの共有じゃなくて、同じDLLを参照)。</p>
<p>ちなみに、現在は、これら全部を.NET 4.6にバージョンアップ済みです。</p>
<h3>既知の制限: .NET 4では使えない</h3>
<p>.NET 3.5と4.5以上では問題なく動きますが、.NET 4では動きません。</p>
<p>おそらくピンポイントに.NET 4が必要になる(.NET 4は使えるけど4.5以上へのアップグレードはできない)場面は少ないと思いますが、一応ご注意を。</p>
<p>これは、.NET 4に、async/awaitはできない中途半端なバージョンの<code>Task</code>クラスが存在するため、
型フォワーディングしづらいせいです
(新規クラスを足すのは簡単。既存クラスにインスタンス メソッドを追加するのは無理)。</p>
<h3>NuGetパッケージ</h3>
<p><a href="https://www.nuget.org/packages/MinimumAsyncBridge/">NuGetパッケージ化</a>してあって、</p>
<ul>
<li>.NET 3.5 のプロジェクトからこのNuGe パッケージを参照すると、バックポーティング実装が参照される</li>
<li>.NET 4.5 のプロジェクトからだと、型フォワーディング実装が参照される</li>
</ul>
<p>という挙動をします。とりあえず、NuGet経由で参照するとわずらわしい設定不要で、.NET 3.5と4.5の混在ができます。</p>
<h3>UniRx向け型フォワーディング</h3>
<p>同じような仕組み、<a href="https://github.com/neuecc/UniRx">UniRx</a>に対しても使えます。つまり、</p>
<ul>
<li>Unity向けライブラリではUniRx使う</li>
<li>.NET 4.5向けライブラリでは<a href="https://www.nuget.org/packages/Rx-Main/">本家Rx</a>を使う</li>
<li>これらのライブラリを混在させて使う</li>
</ul>
<p>とか。とりあえずこの作業やって、Pull Request は出してあったりします。</p>
<ul>
<li><a href="https://github.com/neuecc/UniRx/pull/88">https://github.com/neuecc/UniRx/pull/88</a></li>
</ul>
<p>やったことは、</p>
<ul>
<li>名前空間が <code>UniRx</code> になっているところを<code>System.Reactive</code>に戻す</li>
<li>意図して本家Rxとは実装変えていた部分を元に戻す(<code>FirstAsync</code>→<code>First</code>とか)</li>
<li>別途、型フォワーディング用のライブラリを実装</li>
<li>元々のUniRx利用者に影響が出ないように、<code>#if</code>分岐</li>
</ul>
<p>とかです。</p>
<h3>既知の制限: C# 6.0 がらみ</h3>
<p><a href="https://github.com/OrangeCube/MinimumAsyncBridge">MinimumAsyncBridge</a>というかIL2CPP側の問題なんですが、
IL2CPPを使う場合(つまり、iOSで実行する場合)、ちょっとだけC# 6.0で使えない構文があります。</p>
<p>現状、以下の構文はIL2CPPでのビルドに失敗、あるいは、iOS実行時に実行時例外を起こします。
async/awaitの問題というか、だいたいは例外処理がらみの問題です。</p>
<ul>
<li><a href="http://ufcpp.net/study/csharp/ap_ver6.html#await-in-catch">catch、finally 内での await</a> は使えない</li>
<li><a href="http://ufcpp.net/study/csharp/misc_stacktrace.html#rethrow">catch句内での再スロー</a>ができない</li>
<li><a href="http://ufcpp.net/study/csharp/oo_exception.html#exception-filter">例外フィルター</a>が使えない</li>
</ul>
<h2>iOS実行・Android実行</h2>
<p>iOSでの実行は、IL2CPPを使えば動きます。</p>
<p>IL2CPPのバグをいくつか踏み抜いて、Unity 5.2.2では動かなくなっていたりしましたが、
Unityへのフィードバックの結果、Unity 5.2.3では直っています。</p>
<p>(Unity 5.2.2の時は、ビルドで失敗していました。
ビルドまで成功したら、実行時エラーが出たことはこれまでどのバージョンでもありませんでした。)</p>
<p>ちなみに、Android実行では1度も問題は出ていません。</p>
<h2>本家Taskクラスらの劣化</h2>
<p><code>Run</code>メソッドを実装していないなど、意図的にそうした部分の他に、いくらか残念な部分があります。</p>
<ul>
<li>一部、多少効率悪いはず</li>
<li>例外のスタックトレース紛失</li>
</ul>
<h3>効率</h3>
<p><code>TaskCompletionSource</code>クラスとかawaiterの実装などはほぼベタに本家からの移植なので、そんなに差はないはずです。</p>
<p>問題は<code>Delay</code>、<code>WhenAll</code>、<code>WhenAny</code>の実装。
本家はこの辺りを結構大掛かりな実装をしていて移植する気になれなかったので、
<a href="https://github.com/OrangeCube/MinimumAsyncBridge">MinimumAsyncBridge</a>では別実装しました。
この辺りは、本家ほど最適な実装はできないんで、さすがに効率ちょっと悪いはず。</p>
<ul>
<li><code>Delay</code>: <code>System.Threading.Timer</code>で実装</li>
<li>
<code>WhenAll</code>/<code>WhenAny</code>: 複数の<code>Task</code>をリスト管理
<ul>
<li>本家実装だと同時実行するタスク数がむちゃくちゃ多くてもメモリ食わない実装になってるらしいけど、こっちはしっかりタスク数分のメモリを食う。</li>
</ul>
</li>
</ul>
<h3>スタックトレース</h3>
<p>本家<code>Task</code>を使ったasync/awaitの何がすごいって、
スレッド間でスタックトレース情報を伝搬させて、スタックトレースを追えるようにしていることなんですが。</p>
<p>ここはさすがに移植できなかったというか、移植が不可能だったりします。
この機能の実現には.NET 4.5で追加された<code>System.Runtime.ExceptionServices.ExceptionDispatchInfo.Capture</code>が必須です。
.NET 3.5向けのバックポーティングはできません。</p>
<p>なので、デバッグは本家<code>Task</code>よりも少し大変になります(非同期メソッドの呼び出し元が分からなくなったりする)。</p>
<h2>まとめ</h2>
<p><a href="https://github.com/OrangeCube/MinimumAsyncBridge">MinimumAsyncBridge</a>、
実装し始めた当初の予想よりもだいぶあっさりと完成。</p>
<ul>
<li>
.NET 3.5/4.5混在でも使えます
<ul>
<li>.NET 4では使えません</li>
</ul>
</li>
<li>ほとんど問題起きず、少ない修正で安定してしまいました</li>
<li>
iOS(IL2CPP)でも動きます
<ul>
<li>Unity 5.2.2でIL2CPPのバグで一瞬動かなくなっていたものの、5.2.3で修正されました</li>
</ul>
</li>
<li>Androidは余裕で動きます</li>
<li>
本家<code>Task</code>の完全下位互換です
<ul>
<li><a href="https://github.com/OrangeCube/MinimumAsyncBridge">MinimumAsyncBridge</a>で動けば、本家では100%動く</li>
<li>一部、多少性能的に劣る</li>
<li>スタックトレース紛失で少しデバッグが大変</li>
</ul>
</li>
</ul>
 ]]></description>
				<pubDate>Mon, 30 Nov 2015 15:01:57 +0900</pubDate>
			</item>
			<item>
				<title>Unity上でasync/await: 背景</title>
				<link>http://ufcpp.net/blog/2015/12/unityasync1background/</link>
				<description><![CDATA[ <p>まずasync/awaitについて、
(Unityでない)通常のC#開発の場合がどうとか、
Unityで何が問題で使えなかったかとか、
Rxとの住み分けとかについて書こうかと思います。</p>
<h2>C# 5.0: async/await の登場</h2>
<p>C#界隈で非同期処理がらみの話題がホットになったのはだいたい2010年前後からです。</p>
<p>当時は、</p>
<ul>
<li>F# にコンピューテーション式による async ワークフローが登場</li>
<li>本家の<a href="https://rx.codeplex.com/">Rx</a>が登場</li>
<li>これらから少し遅れて、C# 5.0 (async/await)のプレビュー版が登場 </li>
</ul>
<p>という感じです。</p>
<p>最近になって、Rxを参考にした非同期処理ライブラリが、
<a href="https://github.com/ReactiveX/RxJava">Java</a>や
<a href="https://github.com/Reactive-Extensions/RxJS">JavaScript</a>などで実装されていて注目されていますが、
その一方で、C#ではC# 5.0のasync/awaitが主流になりました。</p>
<p>理由はおおむね、</p>
<ul>
<li>async/await はプログラミング言語側のサポートが必要</li>
<li>async/await が出ることが分かっていたので、それとは違うモデルの Rx の普及にはみな慎重だった</li>
</ul>
<p>という辺りです。逆に言うと、</p>
<ul>
<li>C# のバージョンが古いUnityでは、いまだ<a href="https://github.com/neuecc/UniRx">Rx</a>にかかる期待は大きい</li>
<li>JavaScriptにもES7でasync/awaitが入り、(後述の住み分けはあるものの、それが合う場面では)async/awaitが主流になっていくと思われる</li>
</ul>
<p>ということも言えます。</p>
<h2>async/awaitとRx</h2>
<p>今回、「Unityでもasync/awaitを使えるようにしたよ」という話をするわけですが、
これでRxはお役御免になるかというとそうでもなくて、Rxの用途は残ります。基本的には、</p>
<ul>
<li>async/await: pull型で、1つの値を取りに行く場合に有効</li>
<li>Rx: push型で、ストリームデータを送ってもらう場合に有効</li>
</ul>
<p>という住み分けになります。</p>
<p>例えば、サーバーからデータを受け取るような場合を想定すると、async/awaitがよさそうな場面は</p>
<ul>
<li>ログイン時、ユーザーデータを一括で取りたい</li>
<li>ユーザーの行動時、即座に決まる範囲で行動の結果を返してもらいたい</li>
</ul>
<p>Rxがよさそうな場面は</p>
<ul>
<li>他のユーザーの行動で自分が受ける影響を、サーバーからpush通知してほしい</li>
</ul>
<p>とかになります。</p>
<p><img src="/media/1044/await1.png" alt="async/awaitが有効な非同期処理" /></p>
<p><img src="/media/1045/await2.png" alt="Rxが有効な非同期処理" /></p>
<h2>UnityでC# 6.0</h2>
<p>Unityの問題は使っているMonoのバージョンが古いことで、確か2.8系(.NET 3.5/C# 3.0相当、オプション引数とか一部だけC# 4.0機能を先行取り込み)だったはず。</p>
<p>ですが、C#は、古いフレームワーク上でも最新の言語機能を使えたりします。
詳しくは「<a href="http://ufcpp.net/study/csharp/cheatsheet/listfxlangversion/">C#の言語バージョンと.NET Frameworkバージョン</a>」で書いていますが、
ここで「2.0や3.0で動く」となっている機能は、コンパイラーさえバージョンアップすればUnity上でも使えます。</p>
<p>例えば、C# 6.0の新機能の大半は何もしなくても古いフレームワーク上で動きます。
Caller Info属性や、<code>FormattedString</code> は、簡単なクラスの自作で動かせます。
async/await は結構重たいですが、頑張って実装すれば動かせます(これが本稿の主題)。</p>
<h3>コンパイラーの差し替え</h3>
<p>C# 6.0コンパイラーを使う方法は大きく分けると2種類あって、</p>
<ul>
<li>Unity が使っているコンパイラーを差し替えてしまう(実際にやっている人あり: <a href="https://bitbucket.org/alexzzzz/unity-c-5.0-and-6.0-integration/src">Unity C# 5.0 and 6.0 Integration</a>)</li>
<li>ロジックの大部分をUnityの外でコンパイルしてしまう</li>
</ul>
<p>となります。</p>
<p>うちは、どのみちロジックの大部分をUnityの外でも使う(データ編集用のデスクトップ アプリや、サーバー上で動かす)ので、
後者のやり方をしています。</p>
<p>ちなみに、C# プロジェクトのVisual Studio上の「ビルド後処理」設定で、
コンパイルしたDLLをUnity Assetsフォルダー以下にコピーするスクリプトを書いて使っています。</p>
<ul>
<li><a href="https://github.com/ufcpp/UnityTools/tree/master/CopyDllsAfterBuild">CopyDllsAfterBuild</a></li>
</ul>
<h3>Unity に async/await 移植</h3>
<p>Unity上でasync/awaitを使おうと思うと、<a href="https://msdn.microsoft.com/ja-jp/library/system.threading.tasks.task.aspx"><code>Task</code>クラス</a>の移植が必要になります。</p>
<p>IL2CPP登場以前だと、そもそも<code>Task</code>クラスが内部で使っているいくつかのメソッド、
例えば<a href="https://msdn.microsoft.com/ja-jp/library/bb297966.aspx"><code>Interlocked.CompareExchange&lt;T&gt;</code></a>とかが
iOS上(AOTコンパイル)で動かないという問題があって、移植は絶望的でした。</p>
<p>が、IL2CPPが安定してきた今、やってみたら案外あっさり移植できたという状態です。</p>
<ul>
<li><a href="https://github.com/OrangeCube/MinimumAsyncBridge">MinimumAsyncBridge</a></li>
</ul>
<p><a href="http://ufcpp.net/blog/2015/12/UnityAsync0Introduction">導入文</a>でも書いていますが、あっさり動きすぎて、コミットが少なすぎて非アクティブに見える…</p>
<p>まあ、「Minimum」という名前通り、<code>Task</code>クラスのうち、async/awaitに必要な部分だけの実装になります。
例えば、<code>Run</code>メソッド(別スレッドで処理を開始する)は実装していません。
これに関しては、他の非同期処理ライブラリ(Unityのコルーチンとか、Rxとか)とつないで使う想定です。</p>
<p>ちなみに、Rxに対するつなぎ処理も書いています。</p>
<ul>
<li><a href="https://github.com/OrangeCube/MinimumAsyncBridge/tree/master/src/UniRx.AsyncBridge">UniRx.AsyncBridge</a></li>
</ul>
<p><code>IObservable</code>に対するawaiter実装になります。</p>
<h2>まとめ</h2>
<p>Unity の制限の多くは、Mono 2.8系のAOTコンパイルの制限に起因するものが多いです。
それが、IL2CPPが安定してきたことによって少し緩和しています。</p>
<p>C# 3.0に留まる理由もなくなっていて、async/awaitのバックポーティングもうまくいっています。
その移植したライブラリが以下のものです。</p>
<ul>
<li><a href="https://github.com/OrangeCube/MinimumAsyncBridge">MinimumAsyncBridge</a></li>
</ul>
 ]]></description>
				<pubDate>Mon, 30 Nov 2015 15:01:40 +0900</pubDate>
			</item>
			<item>
				<title>Unity上でasync/await: はじめに</title>
				<link>http://ufcpp.net/blog/2015/12/unityasync0introduction/</link>
				<description><![CDATA[ <p>たまにはAdvent Calendar参加。</p>
<p>このブログは<a href="http://qiita.com/advent-calendar/2015/unity">Unity Advent Calendar 2015</a>の12月1日の記事です。</p>
<p>7月に書いた「<a href="http://ufcpp.net/blog/2015/07/unityasyncbridge/">Unity(ゲームエンジン)上で async/await</a>」の続報というか進捗。
あと、補足説明いろいろ。</p>
<p>あれから4か月くらいたったわけでさすがに安定したというか。
むしろ、大して問題出なかったというか。</p>
<p>以下のコミット履歴を見てのとおり、4か月でコミット79個しかないものの、これでもう安定してたりします。</p>
<p><a href="https://github.com/OrangeCube/MinimumAsyncBridge/commits/master">https://github.com/OrangeCube/MinimumAsyncBridge/commits/master</a></p>
<p>これが、「最初から安定してるライブラリは不活性に見えて不安がられる」というやつか…</p>
<p>むしろ、IL2CPPの安定を待ってるというか…</p>
<p>長くなりそうなので3部構成になっています:</p>
<ul>
<li><a href="http://ufcpp.net/blog/2015/12/UnityAsync1Background">背景</a></li>
<li><a href="http://ufcpp.net/blog/2015/12/UnityAsync2CurrentStatus">現状</a></li>
<li><a href="http://ufcpp.net/blog/2015/12/UnityAsync3Retrospective">課題と感想</a></li>
</ul>
 ]]></description>
				<pubDate>Mon, 30 Nov 2015 15:01:21 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 11/19</title>
				<link>http://ufcpp.net/blog/2015/11/pickuproslyn1111/</link>
				<description><![CDATA[ <h2>どこにでも書ける属性</h2>
<p><a href="https://github.com/dotnet/roslyn/issues/6671">Proposal: Attributes everywhere #6671</a></p>
<p>属性をどこにでもつけれるようにしたいという話。用途は「コンパイル時限定属性」。</p>
<p>.NETの型システムで規定されてる実行時属性(.NET ILの制限的に付けれる場所が限られてる)よりも、だいぶフレキシブルにどこにでも付けれて、主に analyzer/fixer/injectorで解析・修正・コード生成したい場所につける目印として使いたい。</p>
<p>で、通常の属性と少し構文変えるみたい。今の提案では<code>[]</code>の代わりに<code>[[]]</code>。</p>
<h2>JSON風のdictionary/arrayリテラル</h2>
<p><a href="https://github.com/dotnet/roslyn/issues/6673">JSON-like syntax for dictionary/array initialization and operation #6673</a></p>
<p>最初はタイトルが「Support &quot;json literals&quot; in source」になってて、「VBのXMLリテラルと何が違うんだ。C#にはそんなリテラルは入れない」とか文句を言われてたり。そういうのではなく、要するに、<code>{ &quot;key&quot;: value }</code>でDictionaryを、<code>[a, b, c]</code>で配列を作りたいという話。</p>
<p>C#チームからの提案 issue ページではないものの、元々C# 7のテーマの1つにそういう機能が含まれてたし、実のところ近い実装がすでにあるみたい。</p>
<p>多少、JSONにそろえるべきか、JSONの嫌なとこまで引きずらない方がいいんじゃないかみたいな議論とか、現状のC#の構文と混ぜた時に大丈夫？みたいな心配はある。</p>
<h2>式ツリー強化</h2>
<p><a href="https://github.com/dotnet/roslyn/issues/2134#issuecomment-156205248">https://github.com/dotnet/roslyn/issues/2134#issuecomment-156205248</a></p>
<p>ずいぶん昔のissueページに、以下のようなコメントがついてた。</p>
<blockquote>
<p>In the meantime, I've taken an early stab at providing a runtime library with C#-specific expression nodes that are implemented as reducible expressions. More information at <a href="https://github.com/bartdesmet/ExpressionFutures/tree/master/CSharpExpressions">https://github.com/bartdesmet/ExpressionFutures/tree/master/CSharpExpressions</a>. I'll discuss this with the team in the weeks to come.</p>
<p>ところで、初期試作として、C#固有の式ツリー ノードに関するランタイム ライブラリ提供試みてる。式の簡約化もできる実装。詳しくは<a href="https://github.com/bartdesmet/ExpressionFutures/tree/master/CSharpExpressions">https://github.com/bartdesmet/ExpressionFutures/tree/master/CSharpExpressions</a>にて。数週内に、C#チームとディスカッションする。</p>
</blockquote>
<p>ですって。</p>
<p>.NET 4の時に導入された式ツリーは、ILレベルの機能しかなくて、C#と比べるとだいぶ貧相で。動的コード生成とかする人からすると、C#の全機能を式ツリー化できないのは結構不便な状況。今だと、Roslynを使ってコード生成という手もなくはないんだけど、ラムダ式からの式ツリー化ができたりするわけではなく、ちょっと用途が違ったりするので。</p>
 ]]></description>
				<pubDate>Thu, 19 Nov 2015 15:14:52 +0900</pubDate>
			</item>
			<item>
				<title>Connect() での発表、.NET Core</title>
				<link>http://ufcpp.net/blog/2015/11/netcoreconnect/</link>
				<description><![CDATA[ <p><a href="https://channel9.msdn.com/">Connect(); // 2015</a>がありましたね。</p>
<p>昨日、Connect() 初日の基調講演に合わせて、日本では深夜ニコ生放送「<a href="http://live.nicovideo.jp/watch/lv241697499">深夜に盛り上がれ　MS開発者イベント『Connect(); // 2015』生放送</a>」をやってたわけですが。</p>
<p>「どのくらい出番あるかわからないけどいて」とか言われて待機してたはずが、結局丸ごと画面に映っていたような…</p>
<p>まあ、全体の様子は<a href="https://buchizo.wordpress.com/2015/11/19/microsoft-connect-2015-day-1-azure-update%E3%82%82%E3%81%82%E3%82%8B%E3%82%88/">亀淵さんのとこ</a>でも見ていただいて。</p>
<h2>.NET Core RC</h2>
<p>C#/.NET的に影響があるのは、.NET CoreのRC提供開始。</p>
<p>RC(バグ修正とかのぞいてもう変更しない)でGo Live(製品に使っても構わない状態)になりました。オープンソースでソースコードがMITライセンスだからって、自前でソースコードとってきて、問題出たら自分で直すなんてそうそうやれないわけで、「ビルド済みバイナリをマイクロソフトがサポートします」的な意味で、RCをもってGo Live。</p>
<h2>--native オプション</h2>
<p>Connect() キーノートのデモの中で、</p>
<pre><code>dotnet compile -o output --native
</code></pre>
<p>とかコマンドを打ってました。--nativeオプション。</p>
<p>事前コンパイル(AOT)する機能も提供するみたいですね。</p>
<p>ちなみに、まあそもそもJIT自体の説明してなかったなぁと思って記事追加:</p>
<ul>
<li><a href="http://ufcpp.net/study/csharp/framework/fwjitcompilation/">JITコンパイル</a></li>
</ul>
<p>Windows デスクトップだとそれなりにJITのメリット高くてずっとJITだけ提供してきたわけですが、Linux上とかだとAOTの需要があるだろうってことでしょうか。</p>
<p>ちなみに、<a href="https://ufcpp.wordpress.com/2014/04/03/net-native/">.NET Native</a>とは別系統。</p>
<ul>
<li>
.NET Native
<ul>
<li>単にAOTだけじゃなくて、いろいろUniversal Windows Apps向けにガチガチに最適化</li>
<li>シリアライズとかP/Invokeのコードをビルド時に生成(通常は動的にやる)</li>
<li>XAML中の動的な処理を自動的に判別して必要な型情報を残す</li>
<li>アセンブリをまたいだ最適化までする</li>
<li>Visual C++コンパイラー(要するに、マイクロソフトが長年Windows向けに最適化しまくってる高性能コンパイラー)技術を使ってネイティブ コード生成</li>
</ul>
</li>
<li>
.NET Coreの --native オプション
<ul>
<li><a href="http://blogs.msdn.com/b/dotnet/archive/2013/09/30/ryujit-the-next-generation-jit-compiler.aspx">RyuJIT</a>や<a href="https://github.com/dotnet/llilc">LLILC</a>が持ってるネイティブ コード生成を事前に掛けるだけ</li>
</ul>
</li>
</ul>
<p>みたいな感じのはず。たぶん。</p>
 ]]></description>
				<pubDate>Thu, 19 Nov 2015 14:42:36 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 11/8</title>
				<link>http://ufcpp.net/blog/2015/11/pickuproslyn1108/</link>
				<description><![CDATA[ <h2>Global Summit</h2>
<p><a href="https://mvp.microsoft.com/ja-jp/Summit">Global Summit</a> に行っていたわけですが、最近の開発系製品の類はオープンソースになってて最初から全部見えていたり。というか、前日に「Summitでしゃべる内容はこんなの」みたいなIssueページが立ったりして、情報筒抜け。</p>
<p>ちなみに補足しておくと、MS MVP Global SummitはNDAの下でいろいろと聞いてこれる場なわけですが、</p>
<ul>
<li>NDA は、聞いた情報がプレスリリースやブログなどで公開された時点で切れる。その後は話せる</li>
<li>「あんまり NDA な話聞いても人に伝えられないのがかえって困ったりする」という要望あり</li>
</ul>
<p>という2つの事情から、ほぼ同時、あるいは、せいぜい数週程度で情報公開するものが増えていたりします。せいぜい、MS内部の人から直接話を聞ける、直接会える、直接フィードバックを言える、他国のMVPのフィードバックや反応まで見えるという感じのもの。</p>
<p>まあ、製品によるんですが。.NET系は、<a href="https://github.com/dotnet/roslyn">Roslyn</a>がGitHubになって以来、ほぼそんな状況です。</p>
<h3>Outline of C# 7 demo at MVP Summit 2015-11-02</h3>
<p><a href="https://github.com/dotnet/roslyn/issues/6505">Outline of C# 7 demo at MVP Summit 2015-11-02 #6505</a></p>
<p>ということで、前日リーク。</p>
<p>今、仕様が結構固まってきて、動く実装があるものは以下の2つ。</p>
<ul>
<li>Local Functions</li>
<li>Pattern Matching</li>
</ul>
<p>この2個のデモ。</p>
<p>ただ、デモとして見ることはできても、一般の人がこれを手元に持ってきて試すってのはまだみたい。
Visual Studio 2015 Update 1で、「単機能リリース」ができるようにVisual Studio自体に手を入れるみたなので、それ以降。</p>
<p>「単機能リリース」は、要するに、「C# vNext」みたいなでかい単位じゃなくて、「Pattern Matching単体」とか「Local Functions単体」とかを個別に、Visual Studio拡張として(Visual Studio自体を上書きしない、アンインストールできれいさっぱり汚れ残さず消える)提供するもの。現状のVisual Studioだとうまくできないみたい。</p>
<p>ちなみにこの2つ、仕様のドラフトが上がったみたいです(futureブランチにmerg済み)。</p>
<ul>
<li>
<a href="https://github.com/dotnet/roslyn/tree/future/docs/features">roslyn/docs/features/</a>
<ul>
<li><a href="https://github.com/dotnet/roslyn/blob/future/docs/features/local-functions.md">https://github.com/dotnet/roslyn/blob/future/docs/features/local-functions.md</a></li>
<li><a href="https://github.com/dotnet/roslyn/blob/future/docs/features/patterns.md">https://github.com/dotnet/roslyn/blob/future/docs/features/patterns.md</a></li>
</ul>
</li>
</ul>
<h2>RoslynQuoter</h2>
<p>C# のコードを書いたら対応する SyntaxNode を作るコードを出力してくれるサービスが。要るよね、そりゃ…</p>
<ul>
<li>
<a href="http://roslynquoter.azurewebsites.net/">RoslynQuoter</a>
<ul>
<li><a href="https://github.com/KirillOsenkov/RoslynQuoter">ソースコードおいてある GitHub リポジトリ</a></li>
</ul>
</li>
</ul>
<p>ちなみに、MS社員。Roslyn側じゃなくて、IDEチームっぽい。</p>
 ]]></description>
				<pubDate>Sun, 08 Nov 2015 07:01:40 +0900</pubDate>
			</item>
			<item>
				<title>Visual Basicの全角キーワード</title>
				<link>http://ufcpp.net/blog/2015/11/fullwidthliteralinvb/</link>
				<description><![CDATA[ <h2>全角キーワード</h2>
<p>Visual Basicでは、BASIC時代からずっとですが、アルファベットの大文字と小文字を区別しないことは皆さまもご存知かと思われます。</p>
<p>で、実は、大文字小文字だけじゃなくて、半角全角も区別しないという。以下のコード、コンパイルして実行することもできるし、Visual Studio上ではちゃんと、<code>Ｍｏｄｕｌｅ</code>とかの部分が青色(キーワードの色)で表示されます。</p>
<pre class="source" title="">
<code><reserved></span><span class="reserved">Ｍｏｄｕｌｅ</span> <span class="type">Module1</span>

    <span class="reserved">Ｓｕｂ</span> Main()
        <span class="reserved">Ｄｉｍ</span> x = 10
        <span class="type">Console</span>.WriteLine(x)
    <span class="reserved">Ｅｎｄ</span> <span class="reserved">Ｓｕｂ</span>

<span class="reserved">Ｅｎｄ</span> <span class="reserved">Ｍｏｄｕｌｅ</span>
</code></pre>
<p><img src="/media/1037/fullwidthvb.png" alt="VBでは全角文字でキーワードを打てる" /></p>
<p>まあ、今のVisual Studio上では、全角文字でキーワードを打つと、自動補完で打ったそばから半角CamelCaseに変換されていくんで、自動補完に直されるたびに<code>Ctrl+Z</code>で元に戻したりしないとこのソースコードを作れなかったりはするんですが。</p>
<h2>もちろんRoslynでもいまだこの仕様</h2>
<p>これ、おそらくは初期のVBで日本人が出した要望を真に受けて実装しちゃったものだと思うんですが…</p>
<p>何が恐ろしいって、その時代にはUnicodeがないこと。Shift_JIS、つまり、日本語ロケールでしか扱えない(後々には韓国語や中国語の文字コードにも全角英数入ってるみたいですけど、最初に作った戦犯は日本のはず？たぶん)文字に対する特殊対応入れさせるとか、当時の日本どれだけわがまま言ってるんだと…</p>
<p>その時代からの名残のコードなのか、現在のRoslynのVBのスキャナー(構文解析で、単語を切り出す部分)には以下のようなコードが含まれています。</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/blob/master/src/Compilers/VisualBasic/Portable/Scanner/CharacterInfo.vb#L71">src/Compilers/VisualBasic/Portable/Scanner/CharacterInfo.vb</a></li>
</ul>
<pre class="source" title="">
<code>    <span class="reserved">Private</span> <span class="reserved">Const</span> s_fullwidth = <span class="reserved">CInt</span>(&amp;HFF00L - &amp;H0020L)

    <span class="comment">REM 中略</span>

    <span class="reserved">Friend</span> <span class="reserved">Const</span> FULLWIDTH_APOSTROPHE <span class="reserved">As</span> <span class="reserved">Char</span> = ChrW(s_fullwidth + AscW(<span class="string">"'"c</span>))             <span class="comment">REM ＇</span>
    <span class="reserved">Friend</span> <span class="reserved">Const</span> FULLWIDTH_QUOTATION_MARK <span class="reserved">As</span> <span class="reserved">Char</span> = ChrW(s_fullwidth + AscW(<span class="string">""""c</span>))        <span class="comment">REM ＂</span>

    <span class="reserved">Friend</span> <span class="reserved">Const</span> FULLWIDTH_DIGIT_ZERO <span class="reserved">As</span> <span class="reserved">Char</span> = ChrW(s_fullwidth + AscW(<span class="string">"0"c</span>))             <span class="comment">REM ０</span>
    <span class="reserved">Friend</span> <span class="reserved">Const</span> FULLWIDTH_DIGIT_SEVEN <span class="reserved">As</span> <span class="reserved">Char</span> = ChrW(s_fullwidth + AscW(<span class="string">"7"c</span>))            <span class="comment">REM ７</span>
    <span class="reserved">Friend</span> <span class="reserved">Const</span> FULLWIDTH_DIGIT_NINE <span class="reserved">As</span> <span class="reserved">Char</span> = ChrW(s_fullwidth + AscW(<span class="string">"9"c</span>))             <span class="comment">REM ９</span>
</code></pre>
<p>Unicodeが普及した今なら普通にIMEで変換した全角文字で<code>&quot;０&quot;c</code>って書けばいいだけの話なのに… IMEを持っていない国に配慮しても、Unicode エスケープシーケンスで<code>\uFF10</code>とか書ける。それを、わざわざ<code>&amp;HFF00L - &amp;H0020L</code> (全角文字の開始番号 - 半角スペース)を足して作ってるという。</p>
<h2>全角リテラル？！</h2>
<p>そんなおぞましいコードを見てしまった外国人曰く、</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/issues/6552">[Proposal] Wide Char Literal #6552</a></li>
</ul>
<p>「<code>&quot;x&quot;w</code>みたいに、文字リテラルにw語尾つけて全角文字を作れたら便利じゃない？」</p>
<p>…</p>
<p>…</p>
<p>…</p>
<p>…</p>
<p>おい、バカ、やめろ。</p>
<p>ちなみに、これに対するコメントでの大まかな会話の流れをまとめると、</p>
<ul>
<li>「Wide Char」って言い方が悪く、他の人「UTF16に収まらない文字のこと？可変長バイトだし難しくない？結合文字のせいで大変よ。U+1F469 U+1F3FB U+200D U+2764 U+200D U+1F468 U+1F3FFで、『色白女性と濃い褐色肌男性が愛し合ってる絵文字』という1文字で表示すべきとされてたり」</li>
<li>他の人「いや、そうじゃなくて、日中韓で使ってる全角文字のことらしい」</li>
<li>他の人「えっ、その手の国だとIME使って全角文字打てるし、全角文字なら16ビットの範囲内だし、それで入力できるんじゃないの？wリテラル作る価値ある？」</li>
<li>提案者「日中韓の人なら便利なんじゃないの？たぶん」</li>
</ul>
<p>おい、バカ、マジでやめろ。</p>
<p>ということで、この流れに気づいた瞬間、「あらゆる意味でそんなものほしくない。全角英数は恐ろしくクソな負の遺産。きっと多くの日本人開発者が憎んでる。」とコメントをつけておきました。</p>
<h2>負の遺産怖い…</h2>
<p>VB 6以前、あるいはVBAとかVBScriptとかからの習慣なわけで、たぶん20年越しの呪いですよ、これ。しかも、Unicodeがなかった時代に「大文字小文字を区別しないんだったら、全角半角も区別しないべきじゃないか」とか言い出した人がいての結果(のはず。たぶん)。</p>
<p>こんな、(キーワードに全角文字使えるとか)今となっては知ってる人すら減ってるご時世に、特殊対応のためにVBのスキャナーに負担をかけて、全世界の皆様にご迷惑かけて大変申し訳ない気分。</p>
<h2>文字のビット数問題</h2>
<p>まあ途中の議論で出ていた、.NETの<code>char</code>で扱えない文字、16ビットに収まらないやつに対する操作は確かにほしかったりはしますが…</p>
<p>.NETで文字列が内部的にUTF16なの、.NETの登場時期(16ビットですべての文字を固定ワード幅表現できるとか夢見ちゃってた時代)を考えると仕方がないんですが、大変不便なので。今や、修飾文字とかあって32ビットですら固定ワードにならず、PowerShellみたいに32ビットで文字列を扱ってもやっぱり解決せず。</p>
<p>むしろ、本当にほしいのは「UTF8をバイト列のまま扱える」クラスと、そこから「1文字とみなされるべき部分を抜き出す」メソッドなのではないかと。</p>
<p>ちなみに、「UTF8をバイト列のまま扱える」クラスは、今、CoreFxチームが試験的に実装中らしいです。試験的リポジトリ<a href="https://github.com/dotnet/corefxlab">corefxlab</a> に、以下のようなクラスが最近追加されました。</p>
<ul>
<li><a href="https://github.com/dotnet/corefxlab/blob/master/src/System.Slices/src/System/Span.cs">Span</a>: 配列の途中区間やネイティブバッファーに対して、ポインターで(コピーなしで)アクセスするクラス</li>
<li><a href="https://github.com/dotnet/corefxlab/blob/master/src/System.Text.Utf8/src/System/Text/Utf8/Utf8String.cs">Utf8String</a>: Spanを使ってコピーなしで、UTF8バイト列をそのまま文字列処理するためのクラス</li>
</ul>
 ]]></description>
				<pubDate>Sat, 07 Nov 2015 02:32:53 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 10/30</title>
				<link>http://ufcpp.net/blog/2015/10/pickuproslyn1030/</link>
				<description><![CDATA[ <h2>Proposal: extension everything #6136</h2>
<p><a href="https://github.com/dotnet/roslyn/issues/6136">Proposal: extension everything #6136</a></p>
<p>コンセプト自体は前々から出ているやつの具体的な文法案。拡張メソッド以外にも、プロパティとかその他のメンバーも拡張で足せたり、静的メソッドとかの追加もできたりさせたいという話。</p>
<p>結構争点多くてまだまだまとまらなさそう。</p>
<ul>
<li><code>extension class A</code> みたいに拡張したいクラスだけ指定するか、<code>extension class AExtension : A</code> みたいに、拡張メソッドを定義するクラス名を書くか</li>
<li>拡張側にインスタンスメンバーを持てるべきかどうか。持てるようにするには<code>ConditionalWeakTable</code>みたいなパフォーマンスに悪影響のある仕組みを使わざるを得なくて微妙</li>
<li>既存の拡張メソッドみたいに、静的メソッドの引数として明示的にインスタンスを渡す構文が好きなんだけど、同じように明示的な感じにはできないか</li>
</ul>
<h2>Proposal: Sequence Expressions #6182</h2>
<p><a href="https://github.com/dotnet/roslyn/issues/6182">Proposal: Sequence Expressions #6182</a></p>
<p><code>(var x = GetX(); x * x)</code> みたいな感じに、<code>()</code>内にステートメントを並べて、最後の1式の結果を返す式を提案。</p>
<p>パターンマッチングに対応したswitchステートメントを作るのに使いそう。</p>
<p><code>,</code>区切りじゃなくて<code>;</code>区切りなのは、メソッドの引数リストと区別がつかない場合があり得るから。</p>
<h2>Proposal: out var declaration #6183</h2>
<p><a href="https://github.com/dotnet/roslyn/issues/6183">Proposal: out var declaration #6183</a></p>
<p>out 引数のところに、<code>M(out var x);</code> みたいに変数宣言混ぜれるようにする話。</p>
<p>一瞬C# 6.0に入りかけて、「もうちょっとしっかり考えたいから先送り」になってたやつ。</p>
<p>これも、パターンマッチング構文で使う前提。</p>
<h2>Proposal: Destructuring assignment for tuples and other types #6400</h2>
<p><a href="https://github.com/dotnet/roslyn/issues/6400">Proposal: Destructuring assignment for tuples and other types #6400</a></p>
<p>コンパイル時に確定でマッチするようなパターンに対して、コンパイル時チェック付きでパターンマッチングできるようにするやつ。今のところ、これのためにletキーワードを導入しようという雰囲気。</p>
<p>これで、タプルの分解とかの、いわゆる「Destructuring」ができる。<code>let (var x, var y) = tuple;</code> みたいなの。</p>
<p>タプル以外にも、任意のパターンマッチングを使ってDestructuring可能。<code>let Destination { Place is Coordinates { Longitude is var longitude } }</code> みたいな書き方。</p>
 ]]></description>
				<pubDate>Fri, 30 Oct 2015 12:10:25 +0900</pubDate>
			</item>
			<item>
				<title>C#の今と未来</title>
				<link>http://ufcpp.net/blog/2015/10/csharpnowandfuture/</link>
				<description><![CDATA[ <p>先週金曜日の、ブログに残しとくの忘れてた。</p>
<p>「<a href="http://tfsug.hatenablog.jp/entry/2015/10/07/141641">開発エキスパートに学ぶ! C# と Visual Studio の今と未来</a>」ってタイトルのセミナーで登壇してきました。</p>
<p>古賀さんの書籍「<a href="http://amzn.to/1GkyhT4">チーム開発の教科書 C#によるモダンな開発を実践しよう! Visual Studio </a>」の出版記念だったりします。</p>
<p>ということで、多少チーム開発のことを意識しつつで「C#の今と未来」な話をしてきました。</p>
<div style="width: 608px; max-width: 100%; margin-bottom:5px;"><a href="https://docs.com/iwanaga-nobuyuk/5195" title="C#の今と未来" target="_blank" style="font-family: 'Segoe UI'">C#の今と未来</a><span style="font-family: 'Segoe UI Light'">—</span><a href="https://docs.com/iwanaga-nobuyuk" target="_blank" style="font-family: 'Segoe UI'">Iwanaga Nobuyuki</a></div><iframe src="https://docs.com/d/embed/D25195732-8956-0142-9690-001805988706%7eMd2f0fde0-d68b-9095-2ec5-841305bd4fb1" frameborder="0" scrolling="no" width="608px" height="378px" style="max-width:100%" allowfullscreen="False"></iframe>
<p>どういう背景があって今のC#があるか、C#の言語仕様の裏にある設計思想みたいな感じの話を中心に。あと、少しだけ、オープンソースになって少し見えてきている今後の話を。</p>
<p>まあ、前半とかは、C#に限らず、新しめのプログラミング言語には共通して言えるような話かなぁとも思います。良いとされるパターンを楽に書けないといけない。さもないと、特にチーム規模大きくなればなるほど、締め切りに追われて負債の蓄積。</p>
<p>新しい技術、特にプログラミング言語とか統合開発環境とかをなかなか導入してくれない上司とかがいたら、その説得資料になればいいなぁ。</p>
<h3>おまけ</h3>
<p>おい、そういうことされると記録に残しにくくて大変に困るんですけども。</p>
<p><img src="/media/1036/eventfinished.png" alt="enter image description here" /></p>
<p>終わったイベントの情報消すとかちょっと。</p>
 ]]></description>
				<pubDate>Sun, 18 Oct 2015 15:41:00 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRolsyn 10/18</title>
				<link>http://ufcpp.net/blog/2015/10/pickuproslyn1018/</link>
				<description><![CDATA[ <p>26日前のDesign Notesを1件紹介し忘れてた。
だって、Madsってば、最初にAgendaだけのページ作って後から埋めるんだもん… 全部埋まってから見ようと思ったら忘れてた…</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/issues/5383">C# Design Notes for Sep 8, 2015 #5383</a></li>
</ul>
<p>提案されてる新機能のうちのいくつかに関する現状の着地点についてと、async streamに感するブレインストーミングを始めたという2つの議題。</p>
<h2>Bestest betterness</h2>
<p>オーパーロードの解決ルール(一番一致度の高いやつを選ぶって意味で、betternessルール。それのよりよいの、今度こそ最良のみたいな意味でbestest)について。</p>
<p>仕様を過度に複雑にしないように控えてたルールを追加するかっていう内容。例えば、静的メソッドしか受け付けない場面ではインスタンスメソッドを無視してオーバーロード解決試みるとかそういうの。</p>
<p>bestest betternessって言葉はずっと出てるけども、具体的にどんなルール足すかの話は初めて表に出てきたかも。</p>
<h2>private protected</h2>
<p>現状の <code>protected internal</code> が「protected または internal」なのに対して、「protected かつ internal」なアクセス制御をしたいんだけども…っていうやつ。</p>
<p>問題はそのためのキーワードをどうするかで、前々から決め手に欠けつつも、妥協的に <code>private protected</code> を提案していたものです。妥協的なんでやっぱりさんざん批判され、他にこうしたらいいんじゃないかって案もちらほら出たものの、結局どの案も決め手に欠けて、元の提案通り <code>private protected</code> にしとこうかなという雰囲気。</p>
<h2>属性がらみ</h2>
<p>いくつか要望が出てるの、くみ取っていくみたい。</p>
<ul>
<li>ジェネリックな属性: .NETランタイム的にはできそうで、言語的に今まで入れてなかった</li>
<li>
コンパイル時のみの属性: Code Analyzerとか使ってメタプログラミング的に使う属性、別にコンパイル結果に残す必要ないよねということで。
<ul>
<li>僕なんかも割かし最近、<a href="https://github.com/neuecc/NotifyPropertyChangedGenerator/blob/29eb3c4f379dcfd59c43d0895dbcc278efdaf3c6/NotifyPropertyChangedGenerator.Annotations/NotifyAttribute.cs"><code>[Conditional(&quot;NEVER_USED_AT_RUNTIME&quot;)]</code></a>とかいうConditional属性作ったりしたこともあるんで</li>
</ul>
</li>
<li>もっといろんな場所に属性つけたい: ラムダ式にとか</li>
<li>属性にいろんな型を渡せるように: 属性の引数に渡せるもの限られてるのをもうちょっと緩めてもいいかも</li>
</ul>
<h2>ローカル extern 関数</h2>
<p>ローカル関数(メソッド内でメソッド定義したり)が最近実装されつつあるけども、それで extern (<code>DllImpoert</code>とかで外部の関数呼び出すやつ)も使えるようにした方が、とのこと。</p>
<h2>任意の型に対する wither</h2>
<p>レコード型に対して、with 式(指定したプロパティだけ書き換えて、残りのプロパティは元のをコピー)みたいなのを提案中だけども、それを任意の型についてできる方法もあった方がという話。</p>
<p>継承とか絡むとめんどくさいそう。</p>
<p>あと、似たような構文で、immutable な型の作成時にオブジェクト初期化子使えるようにもしたそう。</p>
<h2>params IEnumerable</h2>
<p>これは一瞬 C# 6.0 に入れようかみたいな話も出てたけどもいったん流れてたもの。</p>
<p>単純な実装なら 6.0 にも入れれたんだけど、せっかくだからもっと効率の良い実装を模索できないかと考えてるみたい。</p>
<p>引数の数が少ないときに配列作ってるとメモリ的にもったいないとかそういう話。</p>
<h2>非同期ストリーム</h2>
<p>C# 5.0 で <code>await</code> が入って、1つの値を返すだけの非同期処理はずいぶんと楽になったけども、ストリームデータを非同期に返していくのがまだなくて課題になってたやつ。</p>
<h3>メモリのアロケーション</h3>
<p>例えばの話、「1000件のデータをページングして、1ページ当たり100件を、10ページ分読む」みたいなの考えるとわかりやすいと思うんですけど、非同期処理が必要なのはページを読み込む10回だけで、残りの990回は同期でいいわけです。そういう状況下で、990回分の<code>await</code>のオーバーヘッドが大きかったら結局性能でなくなるのをずっと懸念していました。</p>
<p>これに関しては、<code>public Task&lt;bool&gt; MoveNextAsync();</code> の戻り値の true/false をキャッシュするような最適化をかければ問題ない性能が出るんじゃないかとのこと。</p>
<h3>LINQ</h3>
<p><code>IAsyncEnumerable</code> を導入した場合、引数/戻り値の同期/非同期の組み合わせで、</p>
<ul>
<li>同期 → 同期</li>
<li>同期 → 非同期</li>
<li>非同期 → 同期</li>
<li>非同期 → 非同期</li>
</ul>
<p>の4パターン出てくることになります。すべてのLINQプロバイダー作者にこの4パターン分の実装を強いるのとかちょっと嫌。なので、<code>IEnumerable</code>と<code>IAsyncEnumerable</code>、<code>Func&lt;S, T&gt;</code>と<code>Func&lt;S, Task&lt;T&gt;&gt;</code>の間の相互変換みたいなのを提供できないか考えたいとのこと。</p>
<h3>言語サポート</h3>
<p>非同期ストリームを利用する側では <code>foreach</code> を使いたいわけですが、今の <code>await</code> だと<code>IAsyncEnumerable</code>のforeach列挙には対応できないので、何かしら <code>foreach</code> ステートメントの拡張が必要。既存の<code>foreach</code>と同じで行くか、<code>foreach</code>の周りに <code>async</code>とか<code>await</code>とか追加のキーワードつけるべきかとかで悩み中。</p>
<h3>Go言語のチャネル</h3>
<p>Go言語が提供してるチャネルも非同期ストリーム的なものなのでそれとの比較でいくらかの考察を。</p>
<ul>
<li>チャネルとselectステートメントは理解はしやすいけど、ちょっと命令的すぎないか</li>
<li>select はC# 7.0向け提案でいうとパターン マッチングで似たことができそう</li>
<li>チャネルの場合は典型的な利用場面では利用側(consumer側)が1人だけとか、<code>IAsyncEnumerable</code>との用途差もある</li>
</ul>
<p>とか。</p>
 ]]></description>
				<pubDate>Sun, 18 Oct 2015 05:37:49 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 10/9 C# Interactive Window</title>
				<link>http://ufcpp.net/blog/2015/10/pickuproslyn1009/</link>
				<description><![CDATA[ <h2>C# Interactive Window</h2>
<p><a href="http://blogs.msdn.com/b/visualstudio/archive/2015/10/08/visual-studio-2015-update-1-ctp.aspx">Visual Studio 2015 Update 1 CTP</a>が出ました。VS 2015の上書きになるみたいなので試しにくいかもしれませんが、C# な人には待望の C# Interactive Window が追加されています。</p>
<p>C# チーム(.NET コンパイラー チーム)による説明は、ブログじゃなくて GitHub の wiki ページにしたみたいです:</p>
<ul>
<li>
<a href="https://github.com/dotnet/roslyn/wiki/Interactive-Window">Interactive Window</a>
<ul>
<li>ちなみに、このページの 2015 SP1 CTP ダウンロードへのリンクは間違っているので、 <a href="http://blogs.msdn.com/b/visualstudio/archive/2015/10/08/visual-studio-2015-update-1-ctp.aspx">VS チームのブログの方</a> を参照してください</li>
</ul>
</li>
</ul>
<h3>スクリプト独特の挙動</h3>
<p>基本的には通常の C# と同じコードが REPL で動きます。一部、特殊なのは以下のような挙動:</p>
<ul>
<li>
非同期コンテキストを持っている
<ul>
<li>await したら Interactive Window 内で待機</li>
<li>バックグラウンド実行にはならないし、Interactive Window のスレッドに戻ってくる</li>
</ul>
</li>
<li>変数やメソッドは既定(アクセス修飾子を付けない)で public</li>
<li>同じ名前の変数を再定義することで、古い定義を隠す(shadowing)</li>
<li><code>IEnumerable</code> の出力は自動的に中身を表示してくれる</li>
</ul>
<h3>Interactive Window としての機能</h3>
<p>で、かなり高機能な REPL でいろいろ GUI サポートを受けれるみたいです:</p>
<ul>
<li>IntelliSense (補完だけじゃなくてコード スニペットとかも)使える</li>
<li>
'Alt+矢印キー'で入力履歴
<ul>
<li>'Ctrl+Alt+矢印' で、プレフィックスでの履歴 (途中まで入力して、それにマッチする履歴を出す)</li>
</ul>
</li>
<li>Interactive Window 内で打った内容を、エディター的に矢印で移動、コピペ可能</li>
<li>
コードのコピペ
<ul>
<li>Interactive Window からのコピーでも、リッチテキストでクリップボードに入って、色付け情報も残る</li>
</ul>
</li>
<li>複数行入力したいときは 'Shift+Enter'</li>
<li>エディター的に移動した先の行を再実行したいときは Ctrl+Enter</li>
<li>'Ctrl+A' の挙動は、1回で入力行の全選択、2回でInteractive Window内全選択</li>
</ul>
<h3>ディレクティブ</h3>
<p>スクリプト限定のディレクティブ(<code>#define</code> とか、<code>#</code> から始まるやつ)がいくつか:</p>
<ul>
<li><code>#r</code>: DLL(パス指定) や NuGet パッケージ(パッケージ名指定)の参照</li>
<li>
<code>#load</code>: ファイルを指定してスクリプト読み込み
<ul>
<li>コピペでそこに張り付けたのと同じ挙動。別コンテキスト実行にはならない</li>
</ul>
</li>
<li>
<code>#clear</code>, <code>#cls</code>: Interactive Window 内の文字列全消去
<ul>
<li>文字だけ。コンテキスト(これまでに定義した変数とかメソッドとか)は残る</li>
</ul>
</li>
<li><code>#help</code>: ヘルプ表示</li>
<li><code>#reset</code>: コンテキスト含めて全消去</li>
</ul>
<h3>csi (コマンドライン ツール)</h3>
<p>Visual Studio の外、コマンドプロンプト内でも C# REPL を使えるみたい。</p>
<p>Developer Command Prompt for VS2015 (Visual Studio 付属の、各種環境変数設定済みの cmd)中で、<code>csi</code> ってコマンドを打てば C# REPL が起動するとのこと。</p>
<p>ちなみに、ちょっと触ってみた感じの個人的な感想では、コマンドライン ツールとして使うと、IntelliSense が効かないとか、大文字小文字の区別(普段 IntelliSense 頼りで打ってる)とか、<code>;</code> 付けないと行けないの(普通のC#だと違和感ないけど、REPL だと結構な違和感)とか、結構きつそうな感じでした…</p>
<h2>コード生成拡張</h2>
<p><a href="https://github.com/dotnet/roslyn/issues/5561">[Proposal] enable code generating extensions to the compiler #5561</a></p>
<p><code>CodeAnalyzer</code>、<code>CodeFix</code>みたいな感じで、<code>CodeInjector</code> みたいなクラスを用意するみたい。これを継承して独自のC#→C#コード生成(いわゆるinjection、既存メンバーに機能を「注入」)を作るようなものになりそう。</p>
<p>先日紹介した <a href="https://github.com/dotnet/roslyn/issues/5292">supersedes</a> 機能との組み合わせでいろいろできそう。</p>
<h2>レコード型やパターン マッチングの現状</h2>
<p><a href="https://github.com/dotnet/roslyn/issues/5757">Notes on Records and Pattern Matching for 2015-10-07 design review #5757</a></p>
<p>しばらくドキュメント化されてなかったレコード型やパターン マッチングに関する現状説明。</p>
<p>レコード型とパターン マッチングは、C# 6.0 の時にちょっと作り掛けてた(6.0 リリース近くになって急に出てきた話なのでさすがに間に合わず、7.0 に持ち越しすることになった)ものがあったわけですが、そこから現状までの差分で書かれています。</p>
 ]]></description>
				<pubDate>Fri, 09 Oct 2015 02:49:39 +0900</pubDate>
			</item>
			<item>
				<title>Comm Tech Festival 開催しました</title>
				<link>http://ufcpp.net/blog/2015/10/commtechfestival/</link>
				<description><![CDATA[ <p>9月26日に、<a href="https://comuplus.doorkeeper.jp/events/30403">Comm Tech Festival</a>を開催してました。</p>
<p>ishisakaさんがtogetter作ってくれてたみたい: <a href="http://togetter.com/li/879329">Comm Tech Festivalまとめ</a></p>
<p>以下、各セッションの資料等をまとめ。</p>
<h2>ルームA</h2>
<p>司会: <a href="http://xin9le.net">鈴木 孝明</a> (株式会社グラニ、Microsoft MVP for .NET)</p>
<h3><a id="a1">A-1</a> (13:10～14:00) わかばさん向けAzure</h3>
<p>安東沙織 (Microsoft MVP for Microsoft Azure)</p>
<p>鈴木可奈 (<a href="http://r.jazug.jp/">JAZUG</a>)</p>
<iframe src="//www.slideshare.net/slideshow/embed_code/key/c4CnKHvKrYG5wh" width="425" height="355" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe> <div style="margin-bottom:5px"> <strong> <a href="//www.slideshare.net/jazug_girls/azure-53529402" title="わかば向けAzure" target="_blank">わかば向けAzure</a> </strong> from <strong><a href="//www.slideshare.net/jazug_girls" target="_blank">jazug_girls</a></strong> </div>
<p>「クラウドは使ってるし、Azureも一応名前は知ってる。でもAzureって結局MS製品だけでしょ？」 「Azureのアップデートや機能追加が早すぎて、ちっとも追いつけないよ！」 そんなAzure若葉マーク＝わかばさんなアナタに向けて、50分で現在(いま)のAzureをざっくりと解説します。</p>
<h3><a id="a2">A-2</a> (14:10～15:00) ASP.NETサイトの運用</h3>
<p><a href="http://takepara.blogspot.jp">竹原 貴司</a>＋助手</p>
<p>ブログ: <a href="http://miso-soup3.hateblo.jp/entry/2015/09/28/063329">イベント手記 既存のASP.NETサイトをお手軽に速くする 編</a></p>
<div style="width: 608px; max-width: 100%; margin-bottom:5px;"><a href="https://docs.com/yago-hiroka/8661/asp-net-asp-net?collectionid=C25195891-7427-7975-3410-001135308566~M12143230-9f47-60cc-6be8-5dc84b83ec76" title="ASP.NETサイトの運用～既存のASP.NETサイトをお手軽に速くする 編～" target="_blank" style="font-family: 'Segoe UI'">ASP.NETサイトの運用～既存のASP.NETサイトをお手軽に速くする 編～</a><span style="font-family: 'Segoe UI Light'">—</span><a href="https://docs.com/yago-hiroka" target="_blank" style="font-family: 'Segoe UI'">Hiroka Yago</a><a style="float: right; font-family: 'Segoe UI'" href="https://docs.com/yago-hiroka/8661/asp-net-asp-net?collectionid=C25195891-7427-7975-3410-001135308566~M12143230-9f47-60cc-6be8-5dc84b83ec76" target="_blank">Docs.com</a></div><iframe src="https://docs.com/d/embed/D25195891-7481-3791-7110-001091730685%7eM12143230-9f47-60cc-6be8-5dc84b83ec76" frameborder="0" scrolling="no" width="608px" height="407px" style="max-width:100%"></iframe>
<p>既存のASP.NETサイトをお手軽に速くする 編</p>
<h3><a id="a3-1">A-3-1</a> (15:10～16:35) Microsoft AzureでAnsibleとDocker</h3>
<p><a href="http://regist39.hatenablog.com">木下未来</a>（Windows女子部 3代目部長）</p>
<div style="width: 608px; max-width: 100%; margin-bottom:5px;"><a href="https://docs.com/miku-kinoshita/9871/microsoft-azuredockeransible" title="Microsoft AzureとDockerとAnsibleと" target="_blank" style="font-family: 'Segoe UI'">Microsoft AzureとDockerとAnsibleと</a><span style="font-family: 'Segoe UI Light'">—</span><a href="https://docs.com/miku-kinoshita" target="_blank" style="font-family: 'Segoe UI'">木下 未来</a></div><iframe src="https://docs.com/d/embed/D25195902-2203-9527-6020-001134799424%7eMcba593bb-0ffd-2fe0-1998-57f9c951b7fc" frameborder="0" scrolling="no" width="608px" height="378px" style="max-width:100%"></iframe>
<h3><a id="a3-2">A-3-2</a> (15:35～16:00) Node.js でサクッと作れるAzure AD社内アプリ！〜挑戦編</h3>
<p><a href="http://qiita.com/dz_">大平 かづみ</a> (Windows女子部 team Cloud)</p>
<div style="width: 608px; max-width: 100%; margin-bottom:5px;"><a href="https://docs.com/oohira-kadumi/5206/node-js-azure-ad" title="Node.js でサクッと作る Azure AD 連携アプリ！ ～ 挑戦編" target="_blank" style="font-family: 'Segoe UI'">Node.js でサクッと作る Azure AD 連携アプリ！ ～ 挑戦編</a><span style="font-family: 'Segoe UI Light'">—</span><a href="https://docs.com/oohira-kadumi" target="_blank" style="font-family: 'Segoe UI'">Oohira Kadumi</a></div><iframe src="https://docs.com/d/embed/D25195897-7807-7183-3130-000918858444%7eM1af8d7a5-b506-361b-290d-65d4bfcf2516" frameborder="0" scrolling="no" width="608px" height="378px" style="max-width:100%"></iframe>
<h3><a id="a4">A-4</a> (16:10～17:00) Microsoft Edge New Features - Web制作者はEdgeブラウザ対応が必要なのか？</h3>
<p>川田 寛 (Microsoft MVP for Internet Explorer)</p>
<p>Edgeは昨年の今頃、一応はまだ&quot;IE&quot;と呼ばれていたのですが、当時には既に現在のEdgeを形成する思想みたいなものが出来上がっていました。Web制作者や開発者が本当に楽になるにはどうすれば良いのか、Webの進化にMicrosoftとしてどう関わっていけるのか、当時のIEチームはドラスティックに色んな決断をしていたようです。今回、そんな彼らが行った決断が1年という時間の中でどう変わったのか、我々現場の人間の作業にどういう影響を与えているのか取り上げたいと思います。</p>
<h3><a id="a5">A-5</a> (17:10～18:00) Microsoft が提供するオープンな Web デバッグ環境</h3>
<p><a href="http://buildingedge.blogspot.jp/">尾崎 義尚</a> (Microsoft MVP for Internet Explorer)</p>
<div style="width: 608px; max-width: 100%; margin-bottom:5px;"><a href="https://docs.com/ozaki-yoshihisa/1530/microsoft-web" title="Microsoft によるオープンな Web デバッグ環境" target="_blank" style="font-family: 'Segoe UI'">Microsoft によるオープンな Web デバッグ環境</a><span style="font-family: 'Segoe UI Light'">—</span><a href="https://docs.com/ozaki-yoshihisa" target="_blank" style="font-family: 'Segoe UI'">Ozaki Yoshihisa</a></div><iframe src="https://docs.com/d/embed/D25195905-4057-9681-4110-001101969298%7eM26205d17-c4a5-ea89-46de-93b2274ad57e" frameborder="0" scrolling="no" width="608px" height="378px" style="max-width:100%"></iframe>
<p>.NET Core のオープンソース化に代表されるように、Microsoft が提供する様々なものがオープンソースになっています。でも、Microsoft Edge はまだオープンソースではありません。では、Microsoft の Web 環境がオープンじゃないのかというと、そんなことはありません。このセッションでは、オープンになった Microsoft の Web デバッグに関する情報を共有したいと思います。</p>
<h2>ルームB</h2>
<p>司会: 木澤 朋和(MVP for Windows IT Pro)</p>
<h3><a id="b2">B-1</a> (13:10～14:00) Let’s play Windows 10 IoT on Raspberry Pi !</h3>
<p>増田 智明 (Microsoft MVP for .NET)</p>
<p>Universal Windows Platform の一環として IoT Core を動かします。  XAMLで画面を書ける、GPIO でサーボを動かせる、Bluetooth でモバイルと通信をする、  などなど、デモを中心に披露します。</p>
<h3><a id="b5">B-2</a> (14:10～15:00) .NET Micro Framework (プラレールと電子工作)</h3>
<p>初音 玲 (TMCN/Microsoft MVP for Windows Platform Development)</p>
<iframe src="//www.slideshare.net/slideshow/embed_code/key/w7fJzmnQICICo9" width="425" height="355" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe> <div style="margin-bottom:5px"> <strong> <a href="//www.slideshare.net/akirahatsune/net-micro-framework-53216998" title=".NET Micro Framework (プラレールと電子工作)" target="_blank">.NET Micro Framework (プラレールと電子工作)</a> </strong> from <strong><a href="//www.slideshare.net/akirahatsune" target="_blank">Akira Hatsune</a></strong> </div>
<p>ソフトウェア技術者が電子工作をするうえで身に付けたいスキルや注意点をプラレールを電脳化してKinectからコントロールできるようにしたときの経験を踏まえて具体的にわかりやすくお話しします。</p>
<h3><a id="b3">B-3</a> (15:10～16:00) IoT+Azure</h3>
<p><a href="http://blog.qaramell.com/author/iwate">谷口 慈行</a> (Microsoft MVP for Microsoft Azure)
<a href="http://blog.qaramell.com/author/papemk2">吉野 翼</a> (<a href="http://r.jazug.jp/">JAZUG</a>)</p>
<h3><a id="b4">B-4</a> (16:10～17:00) IoT</h3>
<p>安藤 祐貴 (Microsoft Student Partner)</p>
<iframe src="//www.slideshare.net/slideshow/embed_code/key/fYlZMfrquqSF10" width="425" height="355" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe> <div style="margin-bottom:5px"> <strong> <a href="//www.slideshare.net/remyslight/windows10raspberrypimakerfairetokyo" title="Windows10とRaspberryPiでMakerFaireTokyoに参加" target="_blank">Windows10とRaspberryPiでMakerFaireTokyoに参加</a> </strong> from <strong><a href="//www.slideshare.net/remyslight" target="_blank">Yuki Ando</a></strong> </div>
<h3><a id="b1">B-5</a> (17:10～18:00) Kinect, RealSense (Face, Fusion等)</h3>
<p><a href="http://www.naturalsoftware.jp/">中村 薫</a> (TMCN/Microsoft MVP for Kinect for Windows)</p>
<div style="width: 608px; max-width: 100%; margin-bottom:5px;"><a href="https://docs.com/kaorun55/7589/kinectrealsense" title="Kinect、RealSenseの概要とさまざまな使い方" target="_blank" style="font-family: 'Segoe UI'">Kinect、RealSenseの概要とさまざまな使い方</a><span style="font-family: 'Segoe UI Light'">—</span><a href="https://docs.com/kaorun55" target="_blank" style="font-family: 'Segoe UI'">Nakamura Kaoru</a><a style="float: right; font-family: 'Segoe UI'" href="https://docs.com/kaorun55/7589/kinectrealsense" target="_blank">Docs.com</a></div><iframe src="https://docs.com/d/embed/D25195885-3407-1891-4570-002101411174%7eM2d59805e-af11-00d9-ae81-953aa83e70b2" frameborder="0" scrolling="no" width="608px" height="407px" style="max-width:100%"></iframe>
<p>Kinect v2になり、顔検出や3Dスキャンといった従来の「体の動きを認識する」以外の機能が強化されました。
IntelもRealSenseというKinectに似たセンサーの開発を進めており、Windows 10の「Windows Hello」に採用されるなど今後の動向が注目されています。
本セッションではこの2つのセンサーの概要を解説しつつ、デモを交えて動きを紹介します。</p>
<h2>ルームC</h2>
<p>司会: <a href="http://blog.shos.info">小島 富治雄</a> (Microsoft MVP for .NET)</p>
<h3><a id="c1">C-1</a> (13:10～14:00) UWPストア攻略</h3>
<p><a href="http://coelacanth.jp.net/">西村 誠</a> (Microsoft MVP for Windows Platform Development)</p>
<iframe src="//www.slideshare.net/slideshow/embed_code/key/AWaTAcnAVIxXZI" width="425" height="355" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe> <div style="margin-bottom:5px"> <strong> <a href="//www.slideshare.net/makotonishimura108/20150926-uwp" title="20150926 uwpストア攻略" target="_blank">20150926 uwpストア攻略</a> </strong> from <strong><a href="//www.slideshare.net/makotonishimura108" target="_blank">Makoto Nishimura</a></strong> </div>
<h3><a id="c2">C-2</a> (14:10～15:00) Windows 10 Universal Windows PlatformとMVVM設計パターン</h3>
<p>高尾 哲朗 (Microsoft MVP for Windows Platform Development)</p>
<p>Universal Windows PlatformとMVVMで、再利用可能なコンポーネントを作ったり、View modelの基底クラスを作ったりしながらMVVM設計パターンの基礎を解説します。  名前  高尾 哲朗 Microsoft MVP for Windows Platform Development</p>
<h3><a id="c3">C-3</a> (15:10～16:00) TFS＆VisulaStudioとOffice製品群で何ができる？</h3>
<p>二宮 慎</p>
<div style="width: 608px; max-width: 100%; margin-bottom:5px;"><a href="https://docs.com/user671420/7810/tfsvsoffice" title="TFSとVSとOffice" target="_blank" style="font-family: 'Segoe UI'">TFSとVSとOffice</a><span style="font-family: 'Segoe UI Light'">—</span><a href="https://docs.com/user671420" target="_blank" style="font-family: 'Segoe UI'">二宮 慎</a></div><iframe src="https://docs.com/d/embed/D25195895-1558-6630-1100-001763036713%7eM8d346f37-5a0b-afce-98b6-7d55cdc777e0" frameborder="0" scrolling="no" width="608px" height="456px" style="max-width:100%"></iframe>
<p>壁があるように感じる、開発製品群とOffie製品ですが、実は高い親和性を持っています。
一緒に使うとどんなことができるかを画面デモを交えて説明します。</p>
<h3><a id="c4">C-4</a> (16:10～17:00) Visual Studio Online BUILD を本気で使いこなして品質＆効率を劇的に上げる！</h3>
<p><a href="http://tech.surviveplus.net/">古賀 慎一</a> (TFSUG/Microsoft MVP for ALM)</p>
<iframe src="//www.slideshare.net/slideshow/embed_code/key/Nw3qEvnnjIdKe5" width="425" height="355" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe> <div style="margin-bottom:5px"> <strong> <a href="//www.slideshare.net/shinichikoga355/commtechfestivalvso2015build" title="Visual Studio Online BUILD を本気で使いこなして品質＆効率を劇的に上げる！ [ Comm Tech Festival ] C-4" target="_blank">Visual Studio Online BUILD を本気で使いこなして品質＆効率を劇的に上げる！ [ Comm Tech Festival ] C-4</a> </strong> from <strong><a href="//www.slideshare.net/shinichikoga355" target="_blank">慎一 古賀</a></strong> </div>
<p>ソースバージョン管理・タスク管理からもう一歩先に進みたい開発チームを対象に、Visual Studio での設計・開発からテスト・リリースまでの流れと Visual Studio Online BUILDを使いこなすためのポイント、出来ること・出来ないこと、工夫の仕方を解説します。</p>
<h3><a id="c5">C-5</a> (17:10～18:00) Introduction to Application Architecture on ASP.NET MVC （仮）</h3>
<p><a href="http://fortunatewell.com/blog/">福井 厚</a> (<a href="https://twitter.com/afukui">@afukui</a>)</p>
<iframe src="//www.slideshare.net/slideshow/embed_code/key/x89rKEm17iCYpQ" width="425" height="355" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe> <div style="margin-bottom:5px"> <strong> <a href="//www.slideshare.net/afukui/introduction-to-application-architecture-on-aspnet-mvc" title="Introduction to application architecture on asp.net mvc" target="_blank">Introduction to application architecture on asp.net mvc</a> </strong> from <strong><a href="//www.slideshare.net/afukui" target="_blank">Atsushi Fukui</a></strong> </div>
<p>概要： ASP.NET MVC を利用した業務アプリケーション開発において考慮すべきアーキテクチャ上のポイントについてコード例を交えながら解説します。対象者はアーキテクト、アプリケーション設計者、開発者です。</p>
<h2>ルームD</h2>
<p>司会: こくぶん(わんくま同盟)</p>
<h3><a id="d1">D-1</a> (13:10～14:00) Visual Studio 2015 世代のC++プログラミング</h3>
<p><a href="http://www.wisdomsoft.jp/">赤坂 玲音</a> (Microsoft MVP for Visual C++)</p>
<p>C++ 11 以降の新しい C++ 機能などについて網羅的に説明します。</p>
<iframe src="https://onedrive.live.com/embed?cid=23A2E4BDDF571935&resid=23A2E4BDDF571935%2193190&authkey=ABpFCh0wrV_3kV8&em=2&wdAr=1.7777777777777777" width="610px" height="367px" frameborder="0">これは、<a target="_blank" href="http://office.com/webapps">Office Online</a> の機能を利用した、<a target="_blank" href="http://office.com">Microsoft Office</a> の埋め込み型のプレゼンテーションです。</iframe>
<h3><a id="d2">D-2</a> (14:10～15:00) PowerShell in C# Development</h3>
<p><a href="https://twitter.com/guitarrapc_tech">@guitarrapc_tech</a> (Microsoft MVP for Windows PowerShell)</p>
<p>ブログ: <a href="http://tech.guitarrapc.com/entry/2015/09/26/194712">#ComuPlus Comm Tech Festival 2015 のセッション資料公開</a></p>
<p>PowerShell が自動化ツールとしていいかいうけど、実際に開発現場で使わなくない？別にcmd で十分。
使うのどんな時あるの？
いずれも正しいと思います。が、もしかして気づいていないだけで、もうちょっと楽にできるかもしれません。
実際に C# を用いた開発現場で、PowerShell が利用されているシーンはどこなのか。その実事例を紹介していきます。</p>
<h3><a id="d3">D-3</a> (15:10～16:00) open FSharp</h3>
<p>村椿 覚(ぜくる) (株式会社グラニ)</p>
<p>ブログ: <a href="http://zecl.hatenablog.com/entry/CommTechFestivalPoem">Comm Tech Festival　D-3 「open FSharp」 (続きはWebで)</a></p>
<p>C#(VB)がある程度わかって F# をあまり知らない方向けです。</p>
<h3><a id="d4">D-4</a> (16:10～17:00) UnityでC#を学び始めた私の主張</h3>
<p><a href="http://qiita.com/RyotaMurohoshi">室星 亮太</a> (Unity部)</p>
<iframe src="//www.slideshare.net/slideshow/embed_code/key/b5fLhxAkpZoilJ" width="425" height="355" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe> <div style="margin-bottom:5px"> <strong> <a href="//www.slideshare.net/ryotamurohoshi/unityc-53219278" title="UnityでC#を勉強しはじめた私の主張" target="_blank">UnityでC#を勉強しはじめた私の主張</a> </strong> from <strong><a href="//www.slideshare.net/ryotamurohoshi" target="_blank">Ryota Murohoshi</a></strong> </div>
<p>C#の数多くのすばらしい言語機能やクラス。ゲームエンジンUnityの入門本などでは、その全てが紹介されているわけではありません。Unity利用者の中には、そのようなすばらしい機能になかなか出会えない方もいるかもしれません。</p>
<p>本セッションでは”あえてこの場で”、私が独断と偏見で選んだ、普段イベントであまり目にしなそうなC#の言語機能・クラスなどをUnityのコードを例に紹介し、それらへの(個人的な)主張をさせて頂きます。</p>
<p>会場の.NETやC#erの皆様、ぜひ意見・感想・(やさしい)マサカリなどをよろしくお願いします。</p>
<h3><a id="d5">D-5</a> (17:10～18:00) マルチパラダイムとC#　～C#の歴史をたずねて</h3>
<p><a href="http://moriblog.kit-eng.com/">森 博之</a> (極東IT-Engineers代表、Microsoft MVP for .NET)</p>
<div style="width: 608px; max-width: 100%; margin-bottom:5px;"><a href="https://docs.com/mori-hiroyuki/8902" title="マルチパラダイムとC#" target="_blank" style="font-family: 'Segoe UI'">マルチパラダイムとC#</a><span style="font-family: 'Segoe UI Light'">—</span><a href="https://docs.com/mori-hiroyuki" target="_blank" style="font-family: 'Segoe UI'">Mori Hiroyuki</a></div><iframe src="https://docs.com/d/embed/D25195902-9336-2402-5830-000666131764%7eM49dcd5cd-061f-4273-1817-3e3330a30149" frameborder="0" scrolling="no" width="608px" height="378px" style="max-width:100%"></iframe>
<p>既に多くのMVPによって語りに語りつくされたC#。
ここであえて、マルチパラダイムな言語であるC#をプログラミング言語の歴史になぞって振り返ってみたいと思います。</p>
<h2>最後に</h2>
<p>今回僕はこのイベントの取りまとめ(セッション決めたり)をやっていました。といっても、いろんなコミュニティ代表の方に声をかけて、各コミュニティから紹介してもらってセッションを決めています。僕がやったのは人数調整と時間割りくらい。皆様のご協力あってのイベントでした。</p>
 ]]></description>
				<pubDate>Tue, 29 Sep 2015 21:35:07 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップ Roslyn 9/20</title>
				<link>http://ufcpp.net/blog/2015/9/pickuproslyn0920/</link>
				<description><![CDATA[ <p>7月のデザイン ミーティング議事録が2件。</p>
<p>このうち、supersedes機能については前回少し触れましたが。</p>
<h2>参照戻り値/ローカル変数とパターン マッチング、試験的実装始めました</h2>
<p><a href="https://github.com/dotnet/roslyn/issues/5233">C# Design Notes for Sep 1, 2015 #5233</a></p>
<p>何分2か月前の議事録なので、実はもうだいぶ実装が進んでいるんですが(関連する pull-requestが結構すでに merged な状態)、以下の2つの機能について、プロトタイプ実装を進めるにあたっての設計上の決定についての話が書かれています。</p>
<ul>
<li>参照戻り値/ローカル変数 (ref returns and ref locals)</li>
<li>パターン マッチング</li>
</ul>
<p>これがこのまま最終盤になるという保証はまったくないものの、プロトタイプ実装を試しにやってみることでわかることもいろいろあるはず。とのこと。</p>
<h3>参照戻り値/ローカル変数</h3>
<p>参照を返すにあたって、参照先が消えて不正なアドレスを刺すような状態になってはいけないので、返せるものは限定する必要があります。</p>
<p>どういう場合に安全(参照先が不正になる可能性ない)で、どういう場合が危険(その可能性がある)かを説明。C#としては、当然、安全な場合のみを認める方針。</p>
<h3>パターン マッチング</h3>
<p>現時点で以下のような仕様が書かれています。</p>
<ul>
<li>定数パターン マッチングで、整数型はフレキシブル(互換性のある型なら暗黙的に型変換)、浮動小数点はそこまでしない</li>
<li><code>e is &gt; 3</code> みたいな比較は今のところない。たぶんあとで議論</li>
<li>パターン式中で定義した変数は、その直近のブロック内、else 除く</li>
<li>参照ローカル変数は再代入不可</li>
<li>deconstruction はまだやってないけど興味深い「今後のトピック」</li>
<li>レコード型もこのプロトタイプにはまだ入ってない</li>
</ul>
<h2>nameofの拡張、ブランチの意味、supersedes</h2>
<p><a href="https://github.com/dotnet/roslyn/issues/5234">C# Design Notes for Sep 2, 2015 #5234</a></p>
<p>議題は3つ。</p>
<ul>
<li>
nameof の拡張
<ul>
<li><code>MyList&lt;&gt;.First</code> みたいなopenなジェネリックを認めれるようにしようみたいは話</li>
</ul>
</li>
<li>
GitHub の Roslyn リポジトリのブランチについて
<ul>
<li>ブランチを切って新機能実装してるんだけど、(機能ごとにバラバラにある)各ブランチの実装をVSIX配布で試せるようにしたいとのこと</li>
<li>これができるようになったら、試したい機能だけを低リスクに試せるようになるはず(Visual Studio 拡張なので入れたり消したり自由)</li>
</ul>
</li>
<li>
supersedes
<ul>
<li><a href="http://ufcpp.net/blog/2015/9/metrocs1/">前回のブログ参照</a></li>
</ul>
</li>
</ul>
 ]]></description>
				<pubDate>Sun, 20 Sep 2015 03:19:27 +0900</pubDate>
			</item>
			<item>
				<title>Roslyn メタプログラミング &amp; Code-Aware ライブラリ</title>
				<link>http://ufcpp.net/blog/2015/9/metrocs1/</link>
				<description><![CDATA[ <p>昨日の <a href="https://roommetro.doorkeeper.jp/events/30482">Metro.cs #1</a> にて。</p>
<div style="width: 608px; max-width: 100%; margin-bottom:5px;"><a href="https://docs.com/iwanaga-nobuyuk/4439/roslyn" title="Roslynメタプログラミング" target="_blank" style="font-family: 'Segoe UI'">Roslynメタプログラミング</a><span style="font-family: 'Segoe UI Light'">—</span><a href="https://docs.com/iwanaga-nobuyuk" target="_blank" style="font-family: 'Segoe UI'">Iwanaga Nobuyuki</a></div><iframe src="https://docs.com/d/embed/D25195984-8847-6785-4430-000426915410%7eMd2f0fde0-d68b-9095-2ec5-841305bd4fb1" frameborder="0" scrolling="no" width="608px" height="378px" style="max-width:100%"></iframe>
<p>デモ用ソースコード: <a href="https://github.com/ufcpp/UfcppSample/tree/master/Demo/2015/MyRoslynAnalyzers">https://github.com/ufcpp/UfcppSample/tree/master/Demo/2015/MyRoslynAnalyzers</a></p>
<p>要するに、「実際作ってみた結果の感想など」。</p>
<p>作ってみたもの自体は大したことはないんで面白くもないと思いますが、感想の部分は他の Analyzer, Code Fix, Code-Aware ライブラリを作ったりする際にも役立つだろうというつもり。</p>
<p>作ってみたものに関しては、結構、「C# 7.0 が来れば解決しそうなもの」に対する「それまでの間のつなぎ」的なものだったりします。つなぎだし、そんなに頑張らず適当に作ろうとかいう軽いノリができるのも、気軽に作って気軽に配布できるようになったことの強みかなぁとか思います。</p>
<h2>supersedes</h2>
<p>スライド中に、一昨日公開されたばかりの<a href="https://github.com/dotnet/roslyn/issues/5234">Design Notes 9/2</a>の話を少し含めましたが。</p>
<p>今日、supersedes 機能専用の Issue ページも立ってた。</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/issues/5292">[Proposal] add supersede modifier to enable more tool generated code scenarios. #5292</a></li>
</ul>
<p>supersedes(「取って代わる」という意味の単語)でできること自体は Python のデコレーターみたいなの。Javaだとannotation processing tool (APT)使ってできたりすること。.NETでもIL書き替えであれば<a href="https://www.postsharp.net/">PostSharp</a>とか使ってやれるもの。
要するに、あるメソッドやプロパティに対して、その前後にツール生成コードとかで処理を追加する機能。</p>
<p>それを、C# → C# コード生成で、静的に実現しようというのがこの supersedes 構文。
Java の APT や PostSharp を使ってできるような便利さを実現しつつ、実行効率を落とさず、実際に動いているのがどういうコードなのかC#コードが目で見える。</p>
<p>構文自体は結構シンプルなものですが、いくつか課題があることもわかっているし、C# 的にはVisual StudioとかのIDEのデバッグやリファクタリングの機能がちゃんと働く形で実現しないといけないし、それなりに大変なはずです。</p>
<p>一応マイルストーンは C# 7.0 に入っていますが。順調に行ってくれるといいなぁ。</p>
<h2>once a year</h2>
<p>そうそう、こんなコメントが。</p>
<p><a href="https://github.com/dotnet/roslyn/issues/996#issuecomment-140605428">https://github.com/dotnet/roslyn/issues/996#issuecomment-140605428</a></p>
<p>この前後の話の流れ的には、</p>
<ul>
<li>その機能、まあ少なくとも C# 7.0とか8.0では取り組まないと思うよ</li>
<li>9.0？C# って2・3年に1回リリースだし、2022年とかくらいまで待たせるの？</li>
<li>ロードマップ示せるわけじゃないけど、これからは「年に1回リリース」とかやれるといいなと思ってる</li>
</ul>
<p>みたいなの。</p>
<p>あくまで目標であって確約はされないものの、もしかしたらタプルとかのC# 7.0予定機能、来年には使えるようになっているかも。</p>
 ]]></description>
				<pubDate>Thu, 17 Sep 2015 01:48:59 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 9/13</title>
				<link>http://ufcpp.net/blog/2015/9/pickuproslyn0913/</link>
				<description><![CDATA[ <p>なんか大変なことになってる。</p>
<p><img src="/media/1035/mailsfromroslyn.jpg" alt="GitHub Roslynリポジトリからの通知メール" /></p>
<p>メールの大半を占めてる「Neal Gafter」はC#チームでGitHub Issue対応してくれてる人。</p>
<p>これまでの提案Issueページの整理作業を一気にやった様子。</p>
<p>多くのものは、</p>
<ul>
<li>
Close 作業
<ul>
<li>C# 7.0に向けてやり始めたよ</li>
<li>重複だから別エントリーに移って</li>
<li>ちょっと無理/費用対効果合わない</li>
<li>試験的な実装始めたしIssueは閉じる</li>
</ul>
</li>
<li>提案が不明瞭だからもう少し説明求</li>
</ul>
<p>で、いくらか、C# 7.0に向けた新文法の提案が出ています。</p>
<h2>throw を「式」に</h2>
<p><a href="https://github.com/dotnet/roslyn/issues/5143">[Proposal] Make &quot;throw expression&quot; an expression form #5143</a></p>
<ul>
<li>条件演算子で <code>condition ? 値 : throw new InvalidOperation()</code> とかが書けるように</li>
</ul>
<p>「throw の結果は任意の型に変換可能」と判定。<a href="https://github.com/dotnet/roslyn/issues/1226">never型</a>とかがあるともうちょっと融通効くようになるものの、そこまでやるのは CLR レベルの変更が必要なのでもうちょっと先になりそう。</p>
<h2>式ベースの swich ステートメント</h2>
<p><a href="https://github.com/dotnet/roslyn/issues/5154">[Proposal] expression-based switch for pattern matching #5154</a></p>
<p>前々から出てる、パターンマッチングに対応した分岐構文をどうするか。</p>
<p>結局、match 式みたいな新しいキーワードを追加するんじゃなく、switch の拡張になりそう。</p>
<h2>immutable データの書き換え (with ステートメント)</h2>
<p><a href="https://github.com/dotnet/roslyn/issues/5172">[Proposal] &quot;with&quot; expressions for record types #5172</a></p>
<p>immutable なデータを書き換えたければ、大部分のメンバーを丸ごとコピーした上で、書き換えたい場所だけ新しい値で、別インスタンスを作る必要があって大変面倒という問題の解消。レコード型に対する with ステートメントってのを足すという提案。</p>
<h2>非同期スイッチ(selectステートメント)</h2>
<p><a href="https://github.com/dotnet/roslyn/issues/5187">[Proposal] Asynchronous switch #5187</a></p>
<p>「<code>Task.WhenAny</code> して、最初に返ってきたタスクがどのタスクかを判定して分岐」みたいな処理を構文化。確かに、個人的に<code>WhenAny</code>後の分岐面倒に思うこと多い。</p>
 ]]></description>
				<pubDate>Sun, 13 Sep 2015 07:26:38 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップ Roslyn 9/6</title>
				<link>http://ufcpp.net/blog/2015/9/pickuproslyn0906/</link>
				<description><![CDATA[ <h2>Array.Empty 最適化</h2>
<p><a href="https://github.com/dotnet/roslyn/issues/4889">.Net 4.6 optimizations breaking on 4.5.2 servers #4889</a></p>
<p>Roslyn(C# コンパイラー)の問題か、msbuild(ビルド ツール)の問題化、JIT レイヤーに持っていくべき問題かとかいろいろたらいまわしになりそうな話。</p>
<h3>Roslyn がやったこと</h3>
<p>まず、何をやろうとして問題が起きてるのか。</p>
<p><code>params</code> 引数に対して何も引数を渡さなかったときに、C# コンパイラーが内部的に空の配列を作って引数に渡します。この時、Roslyn を使って .NET 4.6 以降をターゲットにすると、生成されるコードが少し変わります。</p>
<p><code>new StringBuilder().AppendFormat(&quot;&quot;)</code> みたいなのを書くと、実際に生成されるコードは、</p>
<ul>
<li>旧コンパイラー/古い .NET: <code>new StringBuilder().AppendFormat(&quot;&quot;, new object[0])</code></li>
<li>Roslyn かつ .NET 4.6: <code>new StringBuilder().AppendFormat(&quot;&quot;, Array.Empty&lt;object&gt;())</code></li>
</ul>
<p>もちろん、<a href="http://ufcpp.net/study/csharp/rm_gc.html#garbage-collection">GC</a>性能改善のために、無駄な配列インスタンスを作らないため。</p>
<h3>起きた問題</h3>
<p><code>Array.Empty</code>は .NET 4.6 で追加されたメソッドなので、当たり前ですが、これを使った最適化は .NET 4.6 以降をターゲットにする場合にしかできません。もちろんRoslyn は .NET 4.6 を参照しているときにしかこの最適化をしません。</p>
<p>で、ここで問題は、例えば以下のような場合。</p>
<ul>
<li>
.NET 4.5.2 をターゲットにした C# プロジェクトを作る
<ul>
<li>実際に動かすのは .NET 4.5.2 が入ったサーバー上</li>
</ul>
</li>
<li>.NET 4.5.1 と、.NET 4.6 しか入っていないビルド マシンでビルドする</li>
</ul>
<p>ここで、ビルド マシン上でmsbuildは、「4.5.2 がないから代わりに 4.6を使う」という判定をするらしく、Roslynの方には .NET 4.6 がわたってしまう模様。その結果、4.5.2をターゲットにしているにも関わらず、<code>Array.Empty</code>最適化がかかってしまう。そうなると、サーバー上では動作しなくなる(「<code>Array.Empty</code>は見つかりません」エラーが出る)という問題。</p>
<h3>取れる対処</h3>
<p>ということで、これはRoslynの問題か、msbuildの問題か、みたいな話に。</p>
<p>根本解決にはmsbuild側を直す必要があるということで、このissueはCloseされて、msbuild側に問題レポートが飛びました。要するに、</p>
<p>Roslyn 側でできそうな対処は、プロジェクトで指定したターゲットと実際にわたってきた.NETアセンブリのバージョンが違ったら警告なりエラーなり出すというのなんですが、現状、msbuild側から.NETのバージョンを受け取ってないので不可能とのこと。なので、msbuild側からその.NETバージョンを渡してもらうようにしないとダメかもという。</p>
<h3>JIT レベル最適化しないのか</h3>
<p>こんな最適化、コンパイラーのレベルでやるからビルド マシン上のインストール状況に左右されるんじゃないかなんて話も出ています。</p>
<p>要するに、<code>new T[0]</code> があったらそれをことごとく <code>Array.Empty&lt;T&gt;()</code> に置き換える最適化をJITレベルでやればこんな問題起きないし、より一層性能的に有利なんじゃない？という。ですが、実際のところ、この JIT レベルでの最適化は結構深刻な互換性問題を引き起こすので無理とのこと。</p>
<p>世の中、<code>new T[0]</code> で毎回新しいインスタンスが作られる前提でしか動かないコードが結構残っているはずで、これを <code>Array.Empty&lt;T&gt;()</code>(シングルトンな単一インスタンスを常に返す)に置き換えると不具合を起こす。</p>
<p>「そんなコードどのくらいあるの？」と思うかもしれませんが、CTP の頃に一度 <code>Enumerable.Empty&lt;T&gt;()</code> が返すインスタンスをシングルトンに変えたら不具合が出て互換性問題レポートが来まくったとかいう事実もあったりします。</p>
<p>ということで、過去のコードを壊さないようにするためには、<code>new T[0]</code> を <code>Array.Empty&lt;T&gt;()</code> に置き換える処理は状況を見て限定的に行わないといけなくて、そういう状況判断はJITレベルでは無理。なので、Roslyn側でやるしかないという話だそうです。</p>
<h2>match ステートメント</h2>
<p><a href="https://github.com/dotnet/roslyn/issues/5016">[Proposal]: match construct for pattern matching #5016</a></p>
<p>今 C# 7.0に向けて実装が進んでいるパターン マッチングと関連して、<code>switch</code> 的な複数条件分岐をどうしようという話。結構前々からこの議論は進んでるんですが、まとめ的な issue ページが立ってたので紹介。</p>
<p>とりあえず、背景にある要望としては、以下の2点。</p>
<ul>
<li>パターン マッチングに対応した分岐構文が必要</li>
<li>ステートメントじゃなくて式にしてほしい</li>
</ul>
<p>これに対して、提案できる文法は2方針があって、どうしようかという議論が出ています。</p>
<ul>
<li><code>switch</code> ステートメントを拡張する</li>
<li><code>switch</code> ステートメントとは別に、<code>match</code> 式という新構文を導入する</li>
</ul>
<p><code>switch</code> を使いまわせば、キーワードを増やす必要はないし、「<code>switch</code>はオワコンだから使うな」みたいな黒歴史ができなくて済むかもしれない。</p>
<p>一方で、同じ<code>switch</code>なのに全然違う構文がかけたらそれはそれで混乱しそうだし、互換性のために残っている「旧<code>switch</code>構文」は結局のところ黒歴史化しそうだし、既存の構文が足かせになって(例えば<code>break</code>必須とか、<code>case 1: case 2: ...</code>みたいなラベル連続時だけ許されるフォールバック機構とか)いまいちな文法にしかできないかもしれない。</p>
<h2>non-nullable 参照型</h2>
<p>久々に C# Design Meeting の議事録の投稿がありました。7・8月あたりは non-nullable 参照型に関する話をしてたみたいです。</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/issues/5031">C# Design Notes for Jul 7 2015</a></li>
<li><a href="https://github.com/dotnet/roslyn/issues/5032">Proposal: Nullable reference types and nullability checking #5032</a></li>
<li><a href="https://github.com/dotnet/roslyn/issues/5033">C# Design Notes for Aug 18, 2015 #5033</a></li>
</ul>
<p>特に、7/7 は<a href="https://github.com/dotnet/roslyn/issues/5031">Eric Lippert</a> (元C#チーム、現在は静的解析ツール ベンダーの Coverity 社員)を「honored guest」(名誉あるお客様)に呼んで。</p>
<p>おおむね方向性固まってきた模様。</p>
<h3><code>T!</code> みたいな型は作らない</h3>
<p><code>T</code> で non-nullable、<code>T?</code> で nullable にする方向。</p>
<p>既存コードの意味が変わってしまうという問題に対しては、以下のように対処。</p>
<ul>
<li>規定動作ではエラーではなく警告にする</li>
<li>
アセンブリ単位で「<code>T</code> が non-nullable」かどうかの動作を変えるオプションを用意する
<ul>
<li>アセンブリ レベルの属性指定で動作を切り替える方式になりそう</li>
</ul>
</li>
</ul>
<h3>アセンブリ単位の動作変更</h3>
<p>例えば、A, B という2つのライブラリを利用するコードを書く場合、以下のようなシナリオがあり得る。</p>
<ul>
<li>まず、B だけが C# 7.0 に更新して、null チェックが入った</li>
<li>利用側が「C# 7.0 化はしたいけど、null チェック入れて回るほどの工数とれず、とりあえずバグがあるかもしれないのは承知の上でとりあえずビルド通したい」みたいな状態になる</li>
<li>余裕ができたので利用側にも null チェックを入れれるようになる</li>
<li>今度は A にも null チェックが入った</li>
<li>利用側はやっぱりすぐには更新作業できない</li>
</ul>
<p>こういうのを考えると、アセンブリ単位で「null チェックが入ったかどうか」「null チェックが入ったライブラリを使っている際に、自身はどう振る舞うか」を切り替えれないとまずいとのこと。</p>
<h3>警告</h3>
<p>「警告なんだしそこまで細かいことしなくても…」と思うかもしれませんが。C# には「警告をエラーとして扱う」オプションがあって、このオプションを利用している人は結構います。なので「警告を足す」というのも、十分に破壊的変更。実際、過去に、警告を足したらユーザーから文句を言われたことがあるそうです。</p>
<h3>non-nullable 型の配列</h3>
<p>配列は、<code>new T[]</code> した時点で中身はすべて null のはずなので、non-nullable な <code>T</code> に対して <code>new T[]</code> を認めるかどうかは結構難しい問題。</p>
<p>とりあえず現状は認める方向で考えてるみたいです。コンストラクターの中での初期化を必須としたり、要素の get するまでに set を必須にしたりというのはできる範囲でチェックする予定。</p>
<h3>ジェネリック</h3>
<p><code>class X&lt;T&gt;</code> があったときに、 <code>new X&lt;string&gt;()</code> とか <code>new X&lt;string?&gt;()</code> とかをどうするか。</p>
<p>class 定義側で <code>T?</code> を使っているかどうかによって、</p>
<ul>
<li>定義側で1つも <code>T?</code> を使っていない → 利用側は non-nullable でも nullable でも OK</li>
<li>定義側で1つも <code>T?</code> がある → 利用側は non-nullable でないと警告</li>
<li>定義側で <code>T?</code> しか使っていない → 利用側は non-nullable でも nullable でも OK</li>
</ul>
<p>にするとのこと。</p>
<p>あと、ジェネリック型引数に限り、<code>T!</code> みたいな「non-nullable型」を認めるとのこと。<code>T!</code> は、</p>
<ul>
<li><code>T</code> が元々 non-nullable なら、<code>T!</code> は <code>T</code> そのもの</li>
<li><code>T</code> が nullable なら、<code>T!</code> は <code>T</code> の <code>non-nullable</code> 版</li>
</ul>
<p>という意味。<code>FirstOrDefault</code>みたいな、参照型にも値型にも使われて、かつ、non-nullable な戻り値を返したいメソッド用。</p>
<h3>null チェック演算子</h3>
<p>nullable 型から non-nullable 型に変えるには、</p>
<ul>
<li><code>??</code> で代替値を与える</li>
<li>null だったら例外を投げる</li>
</ul>
<p>のどちらかをやればいいわけですが、この後者にも専用に演算子を作るかもしれないみたいです。今のところ出ている案は後置きの <code>!</code> 演算子。</p>
<p>さらに、null を伝搬させる null 条件演算子 <code>?.</code> みたいに、null だったら例外を起こしつつメンバー アクセスする <code>!.</code> 演算子も一緒に作るかもしれないとのこと。</p>
 ]]></description>
				<pubDate>Sun, 06 Sep 2015 05:04:28 +0900</pubDate>
			</item>
			<item>
				<title>サイトのシステム更新</title>
				<link>http://ufcpp.net/blog/2015/9/replacement/</link>
				<description><![CDATA[ <p><a href="http://ufcpp.net/">ufcpp.net</a> のシステム入れ替えてから気が付けば3・4か月ほど経過したわけですが。</p>
<p>いまだ微妙に直したいなと思いつつ時間が取れない部分もちらほら。</p>
<h2>未</h2>
<p>ちゃんと治せてるものもあるにはあるんですけども。</p>
<p><img src="/media/1032/mi.png" alt="未" /></p>
<p>アイコン設定してなかったら、ロゴの真ん中あたりを自動的にとることで「未」になってたっていうやつ。ただでさえ、たまに「未確認の人」とか言われたりするのが、完全になんか未然な感じに。</p>
<p>まあ、たぶん、ヒツジです。干支の、ひつじ年の「未」。僕、ひつじ年生まれですし。Excel先生も、済/未 とか入れてこうとしたら自動補完で干支を出しますし。連続データ。</p>
<p><img src="/media/1033/eto.png" alt="干支" /></p>
<h2>数式</h2>
<p>とかの確認で twitter で「ufcpp.net」で検索かけたりしたわけですが。ちらほら、やっぱり数式崩れを気にするコメントがありますよねぇ。</p>
<p>うちのサイト、現状は9割がたのアクセスがC#/.NET関連でして、その他の部分の移行作業は多少手を抜いたりしていたり。</p>
<p>数式が結構残念なのも、C#/.NET関連のページにはほとんどないからなんですよねぇ。移行作業が大変な割にPVそんなにないので、コスト パフォーマンス的に見合わないという判断。</p>
<p>↓こういうのとか(実際こういう表示崩れを起こしてるページが結構)。</p>
<p><span class="math"></p>
<table class="sigma" summary="limitation"><tr><td><span class="normal">lim</span></td></tr><tr><td class="sigmasub">x → 0</td></tr></table>
<p>g<span class="paren" style="font-size:em;">(</span>x<span class="paren" style="font-size:em;">)</span>
＝ 0
</span></p>
<p>これは、↓みたいな数式を表示したくて書いてたやつなんですが。</p>
<p><img src="/media/1034/math.png" alt="word math" /></p>
<p>まあ、大昔、CSSで必死に調整してそれっぽく見えるように出してたんで、当時と今とでブラウザーのレンダリングが違いすぎて。</p>
<p>一応、新システムは <a href="http://genkuroki.web.fc2.com/">MathJax</a> 対応を入れてもらってるので、ちまちまとMathJax対応形式への変換をかけていけば表示できるはず。</p>
<p>例えば、以下のようなMathMLを書けば、</p>
<pre class="xsource" title="">
<code><attvalue></span><span class="attvalue">&lt;</span>math <span class="attribute">xmlns</span><span class="attvalue">="http://www.w3.org/1998/Math/MathML"&gt;</span>
    <span class="attvalue">&lt;</span>mrow<span class="attvalue">&gt;</span>
        <span class="attvalue">&lt;</span>mrow<span class="attvalue">&gt;</span>
            <span class="attvalue">&lt;</span>munder<span class="attvalue">&gt;</span>
                <span class="attvalue">&lt;</span>mrow<span class="attvalue">&gt;&lt;</span>mi <span class="attribute">mathvariant</span><span class="attvalue">="normal"&gt;</span>lim<span class="attvalue">&lt;/</span>mi<span class="attvalue">&gt;&lt;/</span>mrow<span class="attvalue">&gt;</span>
                <span class="attvalue">&lt;</span>mrow<span class="attvalue">&gt;&lt;</span>mi<span class="attvalue">&gt;</span>x<span class="attvalue">&lt;/</span>mi<span class="attvalue">&gt;&lt;</span>mo<span class="attvalue">&gt;</span>→<span class="attvalue">&lt;/</span>mo<span class="attvalue">&gt;&lt;</span>mn<span class="attvalue">&gt;</span>0<span class="attvalue">&lt;/</span>mn<span class="attvalue">&gt;&lt;/</span>mrow<span class="attvalue">&gt;</span>
            <span class="attvalue">&lt;/</span>munder<span class="attvalue">&gt;</span>
        <span class="attvalue">&lt;/</span>mrow<span class="attvalue">&gt;</span>
        <span class="attvalue">&lt;</span>mo<span class="attvalue">&gt;</span>⁡<span class="attvalue">&lt;/</span>mo<span class="attvalue">&gt;</span>
        <span class="attvalue">&lt;</span>mrow<span class="attvalue">&gt;</span>
            <span class="attvalue">&lt;</span>mi<span class="attvalue">&gt;</span>g<span class="attvalue">&lt;/</span>mi<span class="attvalue">&gt;&lt;</span>mfenced <span class="attribute">separators</span><span class="attvalue">="|"&gt;&lt;</span>mrow<span class="attvalue">&gt;&lt;</span>mi<span class="attvalue">&gt;</span>x<span class="attvalue">&lt;/</span>mi<span class="attvalue">&gt;&lt;/</span>mrow<span class="attvalue">&gt;&lt;/</span>mfenced<span class="attvalue">&gt;</span>
        <span class="attvalue">&lt;/</span>mrow<span class="attvalue">&gt;</span>
    <span class="attvalue">&lt;/</span>mrow<span class="attvalue">&gt;</span>
    <span class="attvalue">&lt;</span>mo<span class="attvalue">&gt;</span>=<span class="attvalue">&lt;/</span>mo<span class="attvalue">&gt;</span>
    <span class="attvalue">&lt;</span>mn<span class="attvalue">&gt;</span>0<span class="attvalue">&lt;/</span>mn<span class="attvalue">&gt;</span>
<span class="attvalue">&lt;/</span>math<span class="attvalue">&gt;</span>
</code></pre>
<p>以下のような数式が一応表示される。</p>
<p><math xmlns="http://www.w3.org/1998/Math/MathML"><mrow><mrow><munder><mrow><mi mathvariant="normal">lim</mi></mrow><mrow><mi>x</mi><mo>→</mo><mn>0</mn></mrow></munder></mrow><mo>⁡</mo><mrow><mi>g</mi><mfenced separators="|"><mrow><mi>x</mi></mrow></mfenced></mrow></mrow><mo>=</mo><mn>0</mn></math></p>
<p>ただ、作業量が多すぎて…</p>
<p>バイトしてくれる人とかいないかな… 全体で何式くらいあるかとか、1式(あるいは1ページ)いくらなら「よい時給のバイト」になるかとか計算してみるかなぁ。</p>
 ]]></description>
				<pubDate>Tue, 01 Sep 2015 15:08:41 +0900</pubDate>
			</item>
			<item>
				<title>9月に3つ</title>
				<link>http://ufcpp.net/blog/2015/08/meetingssept/</link>
				<description><![CDATA[ <p>10日に1回のペースで登壇もしくは運営な勉強会とかちょっと…</p>
<h2>9/5(土) 15:00～ 新宿 Tech Aid 1025</h2>
<p><a href="https://manage.doorkeeper.jp/groups/comuplus/events/30178">こみゅぷらす Tech Aid 2015</a></p>
<p>こみゅぷらすの飲食イベント 2015!!
飲みながら、食べながら、マイクロソフト技術のセッションを聴けるイベントです。(参加費は飲食代のみ)</p>
<p>まあ、割かし適当に何か話します。</p>
<h2>9/16(水) 19:30～渋谷  Metro.cs #1</h2>
<p>※会場が恵比寿から渋谷に変更になったそうです。</p>
<p><a href="https://roommetro.doorkeeper.jp/events/30482">Metro.cs #1</a></p>
<p>めとべやの平日出張版という位置づけの勉強会が始まります。初回テーマは「メタプログラミング &amp; Roslyn 事例集」。</p>
<p>Roslynベースの自作のVisual Studio拡張(コード生成系のVSIX 2つと、Code-Awareライブラリ1つ)を題材に、コード生成やコード解析をする理由、実際の利用状況、作ってみた感想、課題なんかについて話します。</p>
<p>参考URL:</p>
<ul>
<li><a href="http://ufcpp.net/study/csharp/package/pkgcodeawarelibrary/">Code-Aware なライブラリ</a></li>
<li>
自作Roslyn拡張:
<ul>
<li><a href="https://github.com/ufcpp/RecordConstructorGenerator">RecordConstructorGenerator</a></li>
<li><a href="https://github.com/ufcpp/ValueChangedGanerator">ValueChangedGanerator</a></li>
<li><a href="https://github.com/ufcpp/LazyMixin">LazyMixin</a> (時間が取れれば<a href="https://github.com/ufcpp/MixinGenerator">MixinGenerator</a>に移行したい)</li>
</ul>
</li>
<li>Visual Studio拡張を作るうえで、テストを書きやすくするためのNuGetパッケージ: <a href="https://github.com/ufcpp/ConventionCodeFixVerifier">ConventionCodeFixVerifier</a></li>
</ul>
<h2>9/26(土) 13:00～ 品川 Comm Tech Festival</h2>
<p><a href="https://comuplus.doorkeeper.jp/events/30403">Comm Tech Festival</a></p>
<p>Comm Tech Festivalは、複数の技術コミュニティをお誘いして、いろんなテーマで開発者が本音で語り尽くす技術の祭典です。</p>
<p>とりまとめをやってます。たぶん当日は1部屋司会・進行とかやってると思います。</p>
<p>部屋割りしなきゃ。</p>
 ]]></description>
				<pubDate>Mon, 31 Aug 2015 14:02:07 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 8/29</title>
				<link>http://ufcpp.net/blog/2015/08/pickuproslyn0829/</link>
				<description><![CDATA[ <h2>Anonymous function that captures no outer variables is not static #4793</h2>
<p><a href="https://github.com/dotnet/roslyn/issues/4793">https://github.com/dotnet/roslyn/issues/4793</a></p>
<p><a href="http://ufcpp.net/study/csharp/sp_delegate.html#anonymous-func">匿名関数</a> (ラムダ式とか匿名デリゲート式)の生成結果が変わったという話。</p>
<ul>
<li>旧コンパイラー: 外部のローカル変数をキャプチャした時だけインスタン スメソッドに、キャプチャしていなければ静的メソッドになってた</li>
<li>Roslyn: 無条件にインスタンス メソッドになる</li>
</ul>
<p>理由は、性能測定してみたらそっちの方が早かったかららしい。
インスタンス メソッドの方が <code>this</code> ポインター分、余計なものを渡してるのでこっちの方が遅そうなのに。
実際には、分岐する方が高コストなのか、CLRレベルでの最適化のせいなのか、インスタンス メソッドの方がよいとのこと
(StackOverflow 上での説明によれば、ネイティブ コード化するときの呼び出し規約の決定のコストがどうとか書いてある)。</p>
<h2>Discussion: Scope of pattern variables, and tuple decomposition #4781</h2>
<p><a href="https://github.com/dotnet/roslyn/issues/4781">https://github.com/dotnet/roslyn/issues/4781</a></p>
<p>現状、パターンマッチングは <code>x is pattern</code> という構文で bool 値を返す想定で作っているものの、</p>
<ul>
<li>コンパイル時に成功が確定するはずで、コンパイル時に成功していることをチェックしてほしい場合がある</li>
<li>その時に <code>if (x is pattern) { }</code> とか書きたくない</li>
<li>pattern 中の分解して得られる変数のスコープをどうするかで困る</li>
</ul>
<p>という場面がある。例えばタプルの分解で、いちいち</p>
<pre><code>
var tuple = (12, "foo")
tuple is (int x, string y) ? (x, y を使った式) : (来ないはず);
</code></pre>
<p>とか書くのも何かおかしい。</p>
<p>ということで、コンパイル時チェック付きの別構文、例えば、</p>
<pre><code>
var tuple = (12, "foo")
(int x, string y) := tuple;
// 以後、x, y を使える
</code></pre>
<p>とかいうのを導入するのはどうだろうか、というディスカッションの場。</p>
<p>コンパイル時にチェックできるのって実質タプルの分解くらいかもしれず、タプル分解用の構文としてはなんかいまいちに思えるあたりが悩ましい感じ。</p>
<h2>Proposal: An await operator similar to ?. #4714</h2>
<p><a href="https://github.com/dotnet/roslyn/issues/4714">https://github.com/dotnet/roslyn/issues/4714</a></p>
<p><code>await null;</code> がヌルポになるの何とかならない？ メソッド呼び出しに <code>?.</code> (null 条件演算子)が導入されたんだし、null 条件 await できない？という提案。</p>
<p>むっちゃほしい。</p>
<p>というか最近何個か、</p>
<pre><code>
var t = XAsync();
if (t != null) await t;
</code></pre>
<p>とかいう嫌なコード書いたところ…</p>
<h2>Proposal: A bottom type for C# #4843</h2>
<p><a href="https://github.com/dotnet/roslyn/issues/4843">https://github.com/dotnet/roslyn/issues/4843</a></p>
<p>型理論でいうところの bottom type、Haskelでいう<code>undefined</code>、Scalaでいう<code>Nothing</code>が欲しいとのことで、そこそこ議論が起きた後で、「それ、もうあるよ <a href="https://github.com/dotnet/roslyn/issues/4843">#1226</a>」(今のところ Never 型として提案中)。</p>
<p>「例外を出すから絶対に戻り値返さないよ」型。こういう型があれば、</p>
<ul>
<li>エラー チェックして例外を throw するだけのメソッドを作りやすい/呼びやすい</li>
<li><code>Never X() =&gt; throw new Exception()</code> みたいに、ラムダ形式のメソッドで例外投げれる</li>
<li><code>Never</code> は任意の型に変換可能で、<code>TryParse(s, out var x) ? x : throw new Exctption()</code> みたいな、他の型との混在ができる</li>
</ul>
<p>というもの。</p>
<p>bottom, undefined, nothing, never… まあ、そりゃ検索できなくて重複提案出ますわ。</p>
 ]]></description>
				<pubDate>Sat, 29 Aug 2015 03:33:11 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップ Roslyn 8/15</title>
				<link>http://ufcpp.net/blog/2015/08/pickuproslyn0815/</link>
				<description><![CDATA[ <p>「バグでしょ？」からの「仕様です」が2件ほど。</p>
<p>そしてだいたいこの手の話題は、5・6年前に Stack Overflow で話題が出てて、
<a href="http://stackoverflow.com/users/88656/eric-lippert">Eric Lippert</a>が回答済みという落ち。</p>
<h2>&amp;&amp; の後ろ</h2>
<p><a href="https://github.com/dotnet/roslyn/issues/4509">Change to definitive assignment in LINQ queries #4509</a></p>
<p><code>dynamic</code> が絡んだ時に、以下のコードで、「b が未初期化の可能性があります」エラーになるという話。</p>
<p><code>decimal.TryParse(v, out a) &amp;&amp; decimal.TryParse(&quot;15&quot;, out b) &amp;&amp; a &lt;= b</code></p>
<ol>
<li><code>TryParse(v, out a)</code> で <code>a</code> が初期化される</li>
<li><code>TryParse(v, out b)</code> で <code>b</code> が初期化される</li>
<li><code>a &lt;= b</code> でその <code>a</code> と <code>b</code> を使う</li>
</ol>
<p><code>dynamic</code> が絡まなければ、<code>TryParse</code> の戻り値は <code>bool</code> で確定していてます。
そして、<code>bool</code> の <code>&amp;&amp;</code> であれば、1., 2. が評価された後でしか 3. が評価されない保証があるのでエラーは起こしません。</p>
<p>が、ユーザー定義型で、ユーザー定義の <code>true</code>, <code>false</code> <code>&amp;</code> 演算子を用意していると、2. をすっ飛ばして3. が評価される場合があり得るというのがエラーの原因。<code>dynamic</code> が絡むと、戻り値も <code>dynamic</code> なわけで、<code>bool</code> に確定しない。そうなると、2. がすっ飛ばされる可能性があって、3. の時点で 'b' が初期化されいている保証が取れないという状態。</p>
<h2>配列の共変性</h2>
<p><a href="https://github.com/dotnet/roslyn/issues/3830">Invalid optimization performed by C# compiler for IEnumerable<T> on arrays #3830</a></p>
<p>以下のコードで <code>b</code> は <code>false</code></p>
<pre class="source" title="b は false">
<code><reserved></span><span class="reserved">enum</span> <span class="type">Enum0</span> { First }
<span class="reserved">enum</span> <span class="type">Enum1</span> { First }
<span class="reserved">var</span> source = <span class="reserved">new</span> <span class="type">Enum0</span>[3];
<span class="inactive">...</span>
<span class="reserved">bool</span> b = source <span class="reserved">is</span> <span class="type">IEnumerable</span>&lt;<span class="type">Enum1</span>&gt;;
</code></pre>
<p>これが、いったん <code>object</code> で受けるように変更するだけで <code>b</code> が <code>true</code> になる。</p>
<pre class="source" title="b が true に">
<code><span class="reserved">object</span> source = <span class="reserved">new</span> <span class="type">Enum0</span>[3];
<span class="reserved">bool</span> b = source <span class="reserved">is</span> <span class="type">IEnumerable</span>&lt;<span class="type">Enum1</span>&gt;;
</code></pre>
<p>なんか変じゃない？という話。</p>
<p>1個目は、C# のルールで型判定していて <code>false</code>。
2個目は、<code>object</code> を挟んだことで C# 上は判定せず、実行時に CLR が型判定するようになって、
CLR のルールでは <code>true</code> になる。
ということみたい。</p>
<p>配列は、ジェネリックがない頃に無理やり特殊対応な共変性を実装してるので、なんか微妙に変な挙動をすることがあったり。</p>
 ]]></description>
				<pubDate>Fri, 14 Aug 2015 19:02:49 +0900</pubDate>
			</item>
			<item>
				<title>packages.config から project.json への移行</title>
				<link>http://ufcpp.net/blog/2015/08/migratetoprojectjson/</link>
				<description><![CDATA[ <p>昨日、勉強会で少し話しましたが、Visual Studio 2015で、csproj/vbproj 中での NuGet パッケージ管理が少し楽になります。</p>
<div style="width: 350px; max-width: 100%; margin-bottom:5px;"><a href="https://docs.com/iwanaga-nobuyuk/8396/modern-net" title="Modern .NET" target="_blank" style="font-family: 'Segoe UI'">Modern .NET</a><span style="font-family: 'Segoe UI Light'"> -- </span><a href="https://docs.com/iwanaga-nobuyuk" target="_blank" style="font-family: 'Segoe UI'">Iwanaga Nobuyuki</a></div><iframe src="https://docs.com/d/embed/D25196329-1392-3126-5950-001255287607%7eMd2f0fde0-d68b-9095-2ec5-841305bd4fb1" frameborder="0" scrolling="no" style="width: 350px; height: 236px; max-width:100%"></iframe>
<p>正確には、7/20にリリースされた状態の Visual Studio 2015だけじゃなくて、その後Windows 10に合わせて出た<a href="https://dev.windows.com/ja-jp/downloads">Visual Studio Tools for Windows</a>が必要。(どうも、その後Visual Studio 2015のバイナリも更新されていて、最新のやつならVisual Studio 2015に含まれているっぽい(もしかしたらCommunityだけかも？))。</p>
<h2>移行ツール書きました。</h2>
<p>既存のプロジェクトを新しい仕組みに対応させるには、現状だと何の移行ツールも提供されていなくて、自前で色々と作業が必要になります。</p>
<p>個人的に試してみた結果、機械作業で、プログラムを使って自動化できそうだったので、作ったのが以下の移行ツール。</p>
<p><a href="https://github.com/ufcpp/UfcppSample/tree/master/Tools/MigrateToProjectJson">https://github.com/ufcpp/UfcppSample/tree/master/Tools/MigrateToProjectJson</a></p>
<p>以下、移行ツールの readme からのコピペ。</p>
<h2>project.json</h2>
<p>元々は ASP.NET 5/.NET Core/.xproj 向けのプロジェクト管理情報が入った JSON ファイル。</p>
<p>NuGet v3 で、その project.json のサブセットを使って、.csproj/.vbproj でも NuGet パッケージ管理を project.json でやるようになった。</p>
<p>ただし、公式にサポートするのは以下の3つだけ。</p>
<ul>
<li>ASP.NET 5</li>
<li>Modern PCL (プロジェクト テンプレートの「Class Library (package)」/「クラス ライブラリ (パッケージ)」で作るやつ)</li>
<li>Universal Windows Platform アプリ(以下、UWP)</li>
</ul>
<p>前2つは元から .xproj 形式。UWP だけがこの新しい仕組み(.csproj + project.json)で動いてる。</p>
<h2>.csproj + project.json</h2>
<p>サポート外(自己責任利用)ではあるものの、任意のプロジェクトから project.json を使うことが可能。</p>
<p>例えば、これまでの NuGet パッケージ管理「packages.confing」で、Rx-Main を参照すると以下のようになってたはず。</p>
<pre class="source" title="">
<code>&lt;?<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">xml</span><span class="pl-e" style="box-sizing: border-box; color: rgb(121, 93, 163);"> version</span>=<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box; color: rgb(24, 54, 145);">"</span>1.0<span class="pl-pds" style="box-sizing: border-box; color: rgb(24, 54, 145);">"</span></span><span class="pl-e" style="box-sizing: border-box; color: rgb(121, 93, 163);"> encoding</span>=<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box; color: rgb(24, 54, 145);">"</span>utf-8<span class="pl-pds" style="box-sizing: border-box; color: rgb(24, 54, 145);">"</span></span>?&gt;
&lt;<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">packages</span>&gt;
  &lt;<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">package</span> <span class="pl-e" style="box-sizing: border-box; color: rgb(121, 93, 163);">id</span>=<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box; color: rgb(24, 54, 145);">"</span>Rx-Core<span class="pl-pds" style="box-sizing: border-box; color: rgb(24, 54, 145);">"</span></span> <span class="pl-e" style="box-sizing: border-box; color: rgb(121, 93, 163);">version</span>=<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box; color: rgb(24, 54, 145);">"</span>2.3.0-beta2<span class="pl-pds" style="box-sizing: border-box; color: rgb(24, 54, 145);">"</span></span> <span class="pl-e" style="box-sizing: border-box; color: rgb(121, 93, 163);">targetFramework</span>=<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box; color: rgb(24, 54, 145);">"</span>net46<span class="pl-pds" style="box-sizing: border-box; color: rgb(24, 54, 145);">"</span></span> /&gt;
  &lt;<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">package</span> <span class="pl-e" style="box-sizing: border-box; color: rgb(121, 93, 163);">id</span>=<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box; color: rgb(24, 54, 145);">"</span>Rx-Interfaces<span class="pl-pds" style="box-sizing: border-box; color: rgb(24, 54, 145);">"</span></span> <span class="pl-e" style="box-sizing: border-box; color: rgb(121, 93, 163);">version</span>=<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box; color: rgb(24, 54, 145);">"</span>2.3.0-beta2<span class="pl-pds" style="box-sizing: border-box; color: rgb(24, 54, 145);">"</span></span> <span class="pl-e" style="box-sizing: border-box; color: rgb(121, 93, 163);">targetFramework</span>=<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box; color: rgb(24, 54, 145);">"</span>net46<span class="pl-pds" style="box-sizing: border-box; color: rgb(24, 54, 145);">"</span></span> /&gt;
  &lt;<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">package</span> <span class="pl-e" style="box-sizing: border-box; color: rgb(121, 93, 163);">id</span>=<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box; color: rgb(24, 54, 145);">"</span>Rx-Linq<span class="pl-pds" style="box-sizing: border-box; color: rgb(24, 54, 145);">"</span></span> <span class="pl-e" style="box-sizing: border-box; color: rgb(121, 93, 163);">version</span>=<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box; color: rgb(24, 54, 145);">"</span>2.3.0-beta2<span class="pl-pds" style="box-sizing: border-box; color: rgb(24, 54, 145);">"</span></span> <span class="pl-e" style="box-sizing: border-box; color: rgb(121, 93, 163);">targetFramework</span>=<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box; color: rgb(24, 54, 145);">"</span>net46<span class="pl-pds" style="box-sizing: border-box; color: rgb(24, 54, 145);">"</span></span> /&gt;
  &lt;<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">package</span> <span class="pl-e" style="box-sizing: border-box; color: rgb(121, 93, 163);">id</span>=<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box; color: rgb(24, 54, 145);">"</span>Rx-Main<span class="pl-pds" style="box-sizing: border-box; color: rgb(24, 54, 145);">"</span></span> <span class="pl-e" style="box-sizing: border-box; color: rgb(121, 93, 163);">version</span>=<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box; color: rgb(24, 54, 145);">"</span>2.3.0-beta2<span class="pl-pds" style="box-sizing: border-box; color: rgb(24, 54, 145);">"</span></span> <span class="pl-e" style="box-sizing: border-box; color: rgb(121, 93, 163);">targetFramework</span>=<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box; color: rgb(24, 54, 145);">"</span>net46<span class="pl-pds" style="box-sizing: border-box; color: rgb(24, 54, 145);">"</span></span> /&gt;
  &lt;<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">package</span> <span class="pl-e" style="box-sizing: border-box; color: rgb(121, 93, 163);">id</span>=<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box; color: rgb(24, 54, 145);">"</span>Rx-PlatformServices<span class="pl-pds" style="box-sizing: border-box; color: rgb(24, 54, 145);">"</span></span> <span class="pl-e" style="box-sizing: border-box; color: rgb(121, 93, 163);">version</span>=<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box; color: rgb(24, 54, 145);">"</span>2.3.0-beta2<span class="pl-pds" style="box-sizing: border-box; color: rgb(24, 54, 145);">"</span></span> <span class="pl-e" style="box-sizing: border-box; color: rgb(121, 93, 163);">targetFramework</span>=<span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box; color: rgb(24, 54, 145);">"</span>net46<span class="pl-pds" style="box-sizing: border-box; color: rgb(24, 54, 145);">"</span></span> /&gt;
&lt;/<span class="pl-ent" style="box-sizing: border-box; color: rgb(99, 163, 92);">packages</span>&gt;
</code></pre>
<p>これを、project.json という名前で、以下のような JSON ファイルに置き替える。</p>
<pre class="source" title="">
<code>{
  <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box; color: rgb(24, 54, 145);">"</span>frameworks<span class="pl-pds" style="box-sizing: border-box; color: rgb(24, 54, 145);">"</span></span>: {
    <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box; color: rgb(24, 54, 145);">"</span>net46<span class="pl-pds" style="box-sizing: border-box; color: rgb(24, 54, 145);">"</span></span>: {}
  },
  <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box; color: rgb(24, 54, 145);">"</span>runtimes<span class="pl-pds" style="box-sizing: border-box; color: rgb(24, 54, 145);">"</span></span>: {
    <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box; color: rgb(24, 54, 145);">"</span>win<span class="pl-pds" style="box-sizing: border-box; color: rgb(24, 54, 145);">"</span></span>: {},
    <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box; color: rgb(24, 54, 145);">"</span>win-anycpu<span class="pl-pds" style="box-sizing: border-box; color: rgb(24, 54, 145);">"</span></span>: {}
  },
  <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box; color: rgb(24, 54, 145);">"</span>dependencies<span class="pl-pds" style="box-sizing: border-box; color: rgb(24, 54, 145);">"</span></span>: {
    <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box; color: rgb(24, 54, 145);">"</span>Rx-Main<span class="pl-pds" style="box-sizing: border-box; color: rgb(24, 54, 145);">"</span></span>: <span class="pl-s" style="box-sizing: border-box; color: rgb(24, 54, 145);"><span class="pl-pds" style="box-sizing: border-box; color: rgb(24, 54, 145);">"</span>2.3.0-beta2<span class="pl-pds" style="box-sizing: border-box; color: rgb(24, 54, 145);">"</span></span>
  }
}
</code></pre>
<p>手動でファイルの置き換えをした後、プロジェクトを読み込みなおす(ソリューションを閉じて開きなおすとかでも OK)と、NuGet v3 でパッケージ管理される状態になる。</p>
<h2>NuGet v3 で新しくなったこと</h2>
<p>NuGet v3 で、.NET Core/.xproj (2015/7/20 の Visual Studio 2015 リリース時点でベータ状態)の一部分を前倒しで先に使えるようになった状態。</p>
<h3>依存関係を自動で解決</h3>
<p>project.json では、直接依存しているものだけを書けばよくなった。</p>
<p>上記の例の packages.config (NuGet v2)では、Rx-Main を参照するだけで、それが依存している Rx-Core, Rx-Interfaces, Rx-Linq, Rx-PlatformServices が一緒に追加される。
一方、project.json (NuGet v3)では、直接参照している Rx-Main の1行だけになった。</p>
<p>アップグレードやアンインストールの作業がだいぶ楽になるはず。</p>
<h3>.csproj/.vbproj を汚さなくなった</h3>
<p>NuGet v2 では、packages.config にパッケージ情報が入るだけじゃなくて、.csproj 側にダウンロードしてきた DLL への参照情報が入ってた。
しかも hint path がソリューションを基準とした相対パスなので、1つのプロジェクトを複数のソリューションから参照するとビルドできなくなったりする。</p>
<p>NuGet v3 では、project.json だけで完結して、.csproj/.vbproj には何も書かなくなった。
1つのプロジェクトを複数のソリューションから参照しても平気に。
また、ソースコード バージョン管理での衝突の可能性も減った。</p>
<h3>キャッシュがユーザー単位に</h3>
<p>NuGet v2 では、NuGet サーバーから取ってきたパッケージは、ソリューション直下の <code>packages</code> フォルダーにキャッシュされてた。</p>
<p>一方、NuGet v3 では、ユーザー フォルダーの下に、<code>.nuget/packages</code> というフォルダーを作ってそこにキャッシュされる。
同じユーザーのすべてのソリューションでキャッシュが共有される。</p>
<h3>まとめ</h3>
<p>変更点</p>
<ul>
<li>依存関係を自動解決</li>
<li>.csproj/.vbproj を汚さない</li>
<li>キャッシュがユーザー単位</li>
</ul>
<p>その結果得られる利点</p>
<ul>
<li>アップグレード/アンインストール作業が楽</li>
<li>1つのプロジェクトを複数のソリューションから参照しても平気</li>
<li>キャッシュ効率アップ</li>
</ul>
<h2>移行プログラム</h2>
<p>packages.config から project.json に自動的に置き替えるプログラム書いてみた。</p>
<ul>
<li>packages.config からパッケージ情報を読み取る</li>
<li>project.json を作る</li>
<li>.csproj から、パッケージのDLLを <code>Reference</code> タグで参照してるところを消す</li>
<li>.csproj の packages.config 行を project.json に書き替える</li>
</ul>
<h3>注意点</h3>
<p>Visual Studio Tools for Windows が必須。</p>
<p><a href="https://dev.windows.com/ja-jp/downloads">開発者センター ダウンロードページ</a>で、「Windows 開発者ツールが付属した Visual Studio 2015」のところからダウンロード。</p>
 ]]></description>
				<pubDate>Sun, 09 Aug 2015 10:14:13 +0900</pubDate>
			</item>
			<item>
				<title>【開催結果】Visual Studio 2015リリース記念勉強会</title>
				<link>http://ufcpp.net/blog/2015/08/vs2015rtmmeeting/</link>
				<description><![CDATA[ <p><a href="https://csugjp.doorkeeper.jp/events/29064">Visual Studio 2015 リリース記念 勉強会</a>やってました。</p>
<p>以下、発表資料まとめ。</p>
<h2>Modern .NET, 岩永 信之</h2>
<div style="width: 350px; max-width: 100%; margin-bottom:5px;"><a href="https://docs.com/iwanaga-nobuyuk/8396/modern-net" title="Modern .NET" target="_blank" style="font-family: 'Segoe UI'">Modern .NET</a><span style="font-family: 'Segoe UI Light'"> -- </span><a href="https://docs.com/iwanaga-nobuyuk" target="_blank" style="font-family: 'Segoe UI'">Iwanaga Nobuyuki</a></div><iframe src="https://docs.com/d/embed/D25196329-1392-3126-5950-001255287607%7eMd2f0fde0-d68b-9095-2ec5-841305bd4fb1" frameborder="0" scrolling="no" style="width: 350px; height: 236px; max-width:100%"></iframe>
<h2>WPF 4.6 and Visual Studio 2015, 亀谷 学人</h2>
<p><a href="https://speakerdeck.com/grabacr07/wpf-4-dot-6">WPF 4.6	 and Visual Studio 2015, 亀谷 学人 </a> (Speaker Deck の埋め込みリンク、うちのサイトのシステムで使えなかった)</p>
<h2>Universal Windows Platform app, 大田 一希</h2>
<iframe src="//www.slideshare.net/slideshow/embed_code/key/1HABTIBq3jaO0H" width="425" height="355" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe> <div style="margin-bottom:5px"> <strong> <a href="//www.slideshare.net/okazuki0130/20150808-visual-studio-2015-universal-windows-platform-app" title="Visual Studio 2015 リリース記念 勉強会 universal windows platform app" target="_blank">Visual Studio 2015 リリース記念 勉強会 universal windows platform app</a> </strong> from <strong><a href="//www.slideshare.net/okazuki0130" target="_blank">一希 大田</a></strong> </div>
<h2>C#コード アナライザー Visual Studio 拡張を作る, 赤坂 玲音</h2>
<iframe src="https://onedrive.live.com/embed?cid=766FED1751719B1D&resid=766FED1751719B1D%21731&authkey=ALGdv5H3gRmK1Ik&em=2" width="402" height="327" frameborder="0" scrolling="no"></iframe>
<h2>Application Insights Preview, 芝村 達郎</h2>
<div style="width: 350px; max-width: 100%; margin-bottom:5px;"><a href="https://docs.com/shibayan/9289/application-insights-preview" title="Application Insights Preview" target="_blank" style="font-family: 'Segoe UI'">Application Insights Preview</a><span style="font-family: 'Segoe UI Light'"> -- </span><a href="https://docs.com/shibayan" target="_blank" style="font-family: 'Segoe UI'">Tatsuro Shibamura</a></div><iframe src="https://docs.com/d/embed/D25196328-2537-5678-1500-001272945990%7eMd94cbc3e-3bde-126a-784c-fa6d816313f3" frameborder="0" scrolling="no" style="width: 350px; height: 236px; max-width:100%"></iframe>
<h2>プロデューサーやデザイナー, etc…とエンジニアがコラボレーションできるVisual Studio Online, 竹林 崇</h2>
<div style="width: 350px; max-width: 100%; margin-bottom:5px;"><a href="https://docs.com/changeworld/1105/etc-visual-studio-online" title="プロデューサーやデザイナー, etc…とエンジニアがコラボレーションできるVisual Studio Online" target="_blank" style="font-family: 'Segoe UI'">プロデューサーやデザイナー, etc…とエンジニアがコラボレーションできるVisual Studio Online</a><span style="font-family: 'Segoe UI Light'"> -- </span><a href="https://docs.com/changeworld" target="_blank" style="font-family: 'Segoe UI'">changeworld</a><a style="float: right; font-family: 'Segoe UI'" href="https://docs.com/changeworld/1105/etc-visual-studio-online" target="_blank">Docs.com</a></div><iframe src="https://docs.com/d/embed/D25196328-9588-6670-8040-001012106419%7eM4a62bf40-5aad-5f80-543d-fcd5b24c16fa" frameborder="0" scrolling="no" style="width: 350px; height: 256px; max-width:100%"></iframe>
<h2>Visual Studio 2015 新機能一気にチェック！, 森 博之</h2>
<div style="width: 350px; max-width: 100%; margin-bottom:5px;"><a href="https://docs.com/mori-hiroyuki/4558/visual-studio-2015" title="Visual Studio 2015新機能一気にチェック" target="_blank" style="font-family: 'Segoe UI'">Visual Studio 2015新機能一気にチェック</a><span style="font-family: 'Segoe UI Light'"> -- </span><a href="https://docs.com/mori-hiroyuki" target="_blank" style="font-family: 'Segoe UI'">Mori Hiroyuki</a></div><iframe src="https://docs.com/d/embed/D25196328-6812-2721-9880-000213480043%7eM49dcd5cd-061f-4273-1817-3e3330a30149" frameborder="0" scrolling="no" style="width: 350px; height: 236px; max-width:100%"></iframe> ]]></description>
				<pubDate>Sun, 09 Aug 2015 09:29:44 +0900</pubDate>
			</item>
			<item>
				<title>Visual Studio 2015でのC#/VBの文字コード</title>
				<link>http://ufcpp.net/blog/2015/08/roslynencoding/</link>
				<description><![CDATA[ <p>VSサポートチームのブログ記事が上がったことによって少々話題になっていますが、文字コード問題。</p>
<ul>
<li><a href="http://blogs.msdn.com/b/jpvsblog/archive/2015/08/03/vs2015-shift-jis-encoding.aspx">Visual Studio 2015 で Shift JIS エンコーディングされたソース ファイルをビルドするとコンパイラ エラーが発生する場合がある</a></li>
</ul>
<h2>症状</h2>
<p>Shift JIS とか、Unicode 以前の各国文字コードで保存した C#/VB ファイルがコンパイルできない、できても文字列リテラルが狂うなどの問題が出ます。</p>
<p>日本に限らず、中国語圏とかでも話題に。</p>
<h2>原因</h2>
<p><a href="https://github.com/dotnet/roslyn">Roslyn</a>のせいではあります。</p>
<p>ぶっちゃけ、「by design (仕様です)」の類ではあったんですが。</p>
<p>クロスプラットフォーム対応のために<code>Encoding.Default</code>を使うのをやめたというのがこの問題の原因です。</p>
<h2>経緯を追って</h2>
<h3>CoreFx 対応</h3>
<p>最初に<code>Encoding.Default</code>撤廃をやったのは以下のpull request。CoreFx対応。</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/pull/1623">More CoreFx porting work #1623</a></li>
</ul>
<p>日付的には3月のものです。つまるところ、CTP5とかRC版とかですでにこの現象起きてたはず。</p>
<h3>Windows-1252 特殊対応</h3>
<p>で、欧米圏ではこの時点で騒がれていました。
ASCII文字圏だから大丈夫かと思いきや、結構、
<a href="https://ja.wikipedia.org/wiki/Windows-1252">Windows-1252</a>で書かれたコードがあるそうで。
œ みたいな合成文字や、À みたいなアクセント付きの文字、¿ (スペイン語で疑問文の頭につける記号)とか。</p>
<p>ちなみに、どのレベルでコンパイルできないかというと、Š (<code>LF</code>+128の位置)が<code>LF</code>と誤認識されて <code>//</code> コメント中に Š を書くとその後ろがコメント扱いされなくなるレベル。</p>
<p>これに対して、結局、4月にRoslyn チームが折れて、Windows-1252に特殊対応を入れたのがこちら。</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/pull/2151">Use CodePage1252 Encoding if available, Latin1 if not. #2151</a></li>
</ul>
<p>当初はWindows-1252に対する<code>Encoding</code>を自前実装して解決しようとしたり。
結局最終的には、一度<code>Encoding.GetEncoding(codepage: 1252)</code>してみて、例外が出たら別のコードページに切り替えるという方式に。</p>
<h3>リリース後に改めて問題に</h3>
<p>Visual Studio 2015が7/20にリリースされたわけですが。
見事に、7/21に以下の報告が。</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/issues/4022">.NET compiler produces incorrect string constants in MSIL when C# source files encoded with non-UTF-8 encoding #4022</a></li>
</ul>
<p>そして続くようにぞろぞろと。</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/issues/4222">VS2015 (MSBuild/14) compiler can't detect file ecoding correctly #4222</a></li>
<li><a href="https://github.com/dotnet/roslyn/issues/4255">Chinese string is compiled to garbage characters #4255</a></li>
<li><a href="https://github.com/dotnet/roslyn/issues/4264">Roslyn can't detect 932 encoding #4264</a></li>
</ul>
<p>まあなんというか…</p>
<ul>
<li>中国語に関する問題報告はVS 2015リリースから結構後</li>
<li>日本語に至っては、Roslyn Issueページへの直接の報告なくて、おそらくは別の口から入ったフィードバックをもとに、Microsoftの中の人が報告</li>
</ul>
<p>ということで、しょうがないから修正pull requestが上がったみたいです。</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/pull/4303">Use default OS encoding to decode non-Unicode/non-UTF8 text, if available, instead of unconditionally falling back to cp1252 or Latin1. #4303</a></li>
</ul>
<p>結局、shim (くさび、詰め木)ライブラリを挟んで、<code>Encoding.Default</code>が使える環境では<code>Encoding.Default</code>を使うように変更したみたいです。</p>
<h2>非Unicode問題</h2>
<p>ちなみに、僕はRCの頃に気づいてたというか、実際、<a href="https://github.com/ufcpp/UfcppSample/tree/master/Chapters/Old/SoundLibrary">大昔(C# 1.0時代)に書いたコード</a>がコンパイルできなくなってましたが、
普通に文字コードを変更してスルーしてました。</p>
<p>まあ、非Unicodeファイルとかちょっと。</p>
<p>そりゃリリースされてから問題になりますわね。アーリーアダプターやるような人の感覚だとむしろ非Unicodeファイルが残ってることの方が大問題。「欧米の連中、Windows-1252に対する特殊対応とかやめろよ、マジで」くらいに思っておりました。</p>
<p>ちなみに、今のVisual StudioはC#/VBファイルを作った時点で<a href="https://ja.wikipedia.org/wiki/%E3%83%90%E3%82%A4%E3%83%88%E3%82%AA%E3%83%BC%E3%83%80%E3%83%BC%E3%83%9E%E3%83%BC%E3%82%AF">BOM</a>が入ってて、UTF8で保存されるはずなんですよね。
C#/VBファイルが<code>Encoding.Default</code>(日本だと要するにShift JIS)になってたのって、Visual Studio 2002時代だけのはず。</p>
<p>この時代に書かれてて、その後保守されてなくて、それでもたまに使われるようなファイルがどれくらいあるんだという話。
とはいえ、自分のところにもそれ(<a href="https://github.com/ufcpp/UfcppSample/tree/master/Chapters/Old/SoundLibrary">C# 1.0時代に書いたコード</a>がサンプルに残ってて、たまにダウンロードしていく人がいる)があったわけですが…</p>
<p>あと、Visual Studio の外、例えば今僕は仕事で<a href="http://japan.unity3d.com/">Unity</a>使ってるわけですが、Windows環境でUnity使ってると、Unity上で作られるC#ファイルは<code>Encoding.Default</code>でできちゃうんですよね。
大変うざく(なのでチーム的には「C#ファイルはVisual Studio側で作って」運用をしていたり)。</p>
 ]]></description>
				<pubDate>Tue, 04 Aug 2015 02:52:40 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 7/19</title>
				<link>http://ufcpp.net/blog/2015/07/pickuproslyn0719/</link>
				<description><![CDATA[ <p>Visual Studio 2015 関連作業が終わって、その次っぽい動きがちらほら。</p>
<h2>Make Features Layer Portable #3998</h2>
<ul>
<li><a href="https://github.com/dotnet/roslyn/issues/3998">Make Features Layer Portable #3998</a></li>
</ul>
<p>Feature API = リファクタリングとか、コード解析からのコード修正とか、そのレイヤーのAPIのこと。</p>
<p>これを、<a href="http://www.omnisharp.net/">OmniSharp</a>、<a href="https://code.visualstudio.com/">Visual Studio Code</a>で使うためにポータブル化作業をしようという Issue ページが立ちました。</p>
<p>ほぼ、</p>
<ul>
<li>今、internal で作ってあるものを public にするだけ(とはいえ、それが大変)</li>
<li>何年も保守していくものになるものをうかつに全部はpublicにできない</li>
<li>public にするには耐ええない作りの箇所があるからその修正が必要</li>
</ul>
<p>という感じの様子。</p>
<h2>Interactive Design Meeting Notes - 7/8/15 #3927</h2>
<ul>
<li><a href="https://github.com/dotnet/roslyn/issues/3927">Interactive Design Meeting Notes - 7/8/15 #3927</a></li>
</ul>
<p>スクリプト向けC#方言の仕様レビューしてたみたい。その議事録なので、割かしC#スクリプトがどうなりそうかのまとめになってる。</p>
<ul>
<li><code>#r</code>でDLLの参照、<code>#load</code>で他のスクリプトの取り込み。スクリプトの一番上にだけ書ける</li>
<li><code>#load</code>な、「その場所にそのスクリプトをコピー＆ペーストしてきたかのような挙動」。shとかでいうところの <code>.</code> の方(<code>&amp;</code>の方じゃなく)</li>
<li>
トップ レベルに変数とか関数を書けるわけだけど、
<ul>
<li>static スクリプト変数には、<code>await</code> を含む初期化子を書けない</li>
<li>普通のスクリプト変数(あるいは、トップ レベル変数って呼ぶ)にはそういう制限ない</li>
<li>interactive window とかで実行してる際には、<code>await</code> した時点でUIをブロックする(バックグラウンド実行にはしない)</li>
</ul>
</li>
<li>
「C#スクリプト」は、普通のC#ソースコードからコピー&amp;ペーストして来たらそれがそのまま動くようにする
<ul>
<li>Copy/Paste Prinsible of Scripting (CPPoS: スクリプトのコピー&amp;ペースト原則)って呼んでる</li>
</ul>
</li>
</ul>
<p>その他、最近、C# 7.0向けに<a href="https://github.com/dotnet/roslyn/issues/2930">ローカル関数</a>の仕様が出始めているものの、それとトップ レベル関数は別物で、C#スクリプトは両方サポートすることになると思う。</p>
<p>スクリプトは常に <code>async</code> な文脈で実行される。どこにでも <code>await</code> 書ける。1つも<code>await</code>を書いてないときにはステートマシン(非同期メソッド内部実装の、仰々しいコード生成)は作らない最適化は掛ける。</p>
<p>static スクリプト変数は、スクリプトが何回実行されても1回だけ初期化が走るようにというのもあるけど、その主たる目的は CPPoS のため(どこからコピペしてもスクリプト実行できるようにするためには、staticフィールドもコピペで動く必要がある)。</p>
<p>トップ レベルのメソッド、プロパティ、型、スクリプト変数のスコープは既定で public (通常のC#は、アクセシビリティ修飾子を省略すると private/internal だけど、スクリプトの場合は public)。スクリプトの外(<code>#load</code>で呼び出す側)からは隠したい場合、「ファイルprivate」って概念を実装したい。現状でも、変数やメソッドを1段階 <code>{}</code> で覆ってしまえば外からアクセスできなくなる実装にはなってる。</p>
<p><code>#load</code> するとその中のトップレベル要素は全部取り込まれる(トップ レベルの識別子には、特に何の修飾もなくアクセスできる)。<code>#load into</code>を使うと、そのスクリプトに名前を付けれるけども、これはエイリアス的な動作。2回、別名で<code>#load into</code>すると、その指す先は一緒。別インスタンスが作られたりはしない。</p>
<h2>Ability to classify fields, locals and parameters differently #3976</h2>
<ul>
<li><a href="https://github.com/dotnet/roslyn/issues/3976">Ability to classify fields, locals and parameters differently #3976</a></li>
</ul>
<p>おまけ。</p>
<p>今、Visual Studioのコードの色分けでは、識別子にはあまり色が付かない(たぶん、色が付くのは型名だけ？)わけですが、フィールドとか変数の色分けには興味ある？という調査的な issue が立ったみたい。</p>
<p>これまで、大きく取り扱ってこなかったけども、おそらく実装しても実行性能的に目立った影響はないだろうし。とのこと。</p>
<p>例えば、以下のようなの。</p>
<ul>
<li><code>readonly</code> かどうか(get-only自動プロパティも)での色分け欲しい？</li>
<li><code>event</code> も？</li>
<li>(クラス/構造体直下の)定数と、ローカル定数の区別とか要る？</li>
<li>未初期化変数の警告にも色分けとか使うのどう？</li>
<li>C#スクリプトができたら、トップ レベル変数とかトップ レベル メンバーもできるけども、それも別扱いしたい？</li>
<li>組み込み演算子と、オーバーロード(ユーザー定義演算子)の区別とか便利そうじゃない？</li>
</ul>
 ]]></description>
				<pubDate>Sun, 19 Jul 2015 06:49:24 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 7/12</title>
				<link>http://ufcpp.net/blog/2015/07/pickuproslyn0712/</link>
				<description><![CDATA[ <p>Mads、怒涛のClose祭り。</p>
<p>久しぶりに、C# Design Notesが投稿されてました。というか、5月のNotesが今投稿されているなど。
要するに、Visual Studio 2015関連作業がやっと落ち着いたってことなんですかね、きっと。</p>
<h2>C# Language Design Review, Apr 22, 2015 #3910</h2>
<p><a href="https://github.com/dotnet/roslyn/issues/3910">https://github.com/dotnet/roslyn/issues/3910</a></p>
<h3>式ツリー</h3>
<p>式ツリー化できる構文とできない構文の差が大きくなりすぎてる。
全部考えると非常に労力がかかって、その努力に見合うと思えない。</p>
<p>ただ、<code>?.</code> と string interpolation に関しては、新しいノードを導入しなくてもできそう。それくらいは考えてもよさそう。</p>
<h3>nullable 参照型</h3>
<p>互換性問題があるので、以下の2つのアプローチが考えられる。</p>
<ul>
<li>two-type: 既存の<code>T</code>の意味を変えて、これを非nullにする。nullableは<code>T?</code></li>
<li>three-type: 既存コードを壊さないように<code>T</code>は残す。非nullが<code>T!</code>、nullableが<code>T?</code></li>
</ul>
<p>もちろん互換性の問題をクリアできるんなら two-type が理想的。nullチェックに対して、何らかのopt-in (コンパイラーの規定動作じゃなくて拡張にするとか、アセンブリ レベルの属性で<code>T</code>の意味を新旧切り替えるとか)を提供する必要がある。</p>
<h3>Wire format</h3>
<p>Wire format(JSONとか、要するに通信用に使う形式)問題。どうやったらJSON化とかの定義を楽にできるか、特に、シリアライズのレイヤーを緩い型付けのままどうやって強い型付けのロジックとつなぎこむか。</p>
<p>考えうるやり方は以下のようなもの。</p>
<ul>
<li>実行時に、辞書式のデータとインターフェイスとの相互変換する機能の類を提供</li>
<li>TypeScript みたいな「コンパイル時のみの型」(コンパイル結果からは型情報を消して辞書式アクセスに置き換え)</li>
<li>F# みたいな「型プロバイダー」の提供</li>
</ul>
<h2>C# Design Notes for May 20, 2015 #3911</h2>
<p><a href="https://github.com/dotnet/roslyn/issues/3911">https://github.com/dotnet/roslyn/issues/3911</a></p>
<p>ローカル関数、つまり、関数(メソッドとか演算子とか)の中で別の関数を定義したいという話。</p>
<p>まあたまにある、「メソッド X の中で、X からしか使わないメソッドを作りたい」という要件。これに対して、現状は無理で、代わりに XInternal みたいなメソッドを用意したり。あるいは、ラムダ式で代用するわけですが、ラムダ式はいくつかの制限が面倒なので改善したいと。</p>
<p>ラムダ式を拡張するか、ローカル関数用の構文を追加するかは検討中な物の、現状は後者、つまりローカル関数の追加で話が進んでいそう。というか、Design Notes 公開前に、<a href="http://ufcpp.net/blog/2015/6/pickuproslyn0610/">pull-req とかブランチが見えて</a>るんですが。</p>
<p>ちなみに、現状のラムダ式との違いは、</p>
<ul>
<li>ジェネリックを使える</li>
<li>再帰呼び出しもできる</li>
<li>イテレーターにもできる(yield return 書ける)</li>
<li>デリゲートの型を明示する面倒がいらない(ラムダ式は <code>Func&lt;int&gt;</code> みたいなやつの明示が必須)</li>
<li>というかデリゲートを介さない(オーバーヘッドが減る)</li>
</ul>
<p>という感じ。</p>
<p>紹介されている用途の例:</p>
<ul>
<li>イテレーターに引数チェックを追加</li>
<li>クイックソートとかの再帰アルゴリズムの実装</li>
<li>キャッシュ(2度目以降の呼び出しは辞書に格納した値を返す)</li>
<li>特に、<code>Task</code>のキャッシュ</li>
</ul>
<h2>C# Design Notes for May 25, 2015 #3912</h2>
<p><a href="https://github.com/dotnet/roslyn/issues/3912">https://github.com/dotnet/roslyn/issues/3912</a></p>
<p>いくつか、提案 issue に対してやるかどうかの判定。これに伴って、いくつかの issue が閉じられました。</p>
<ul>
<li><a href="https://github.com/dotnet/roslyn/issues/1746">XML リテラル</a>: ない。特定のデータ形式をC#に組み込むことはない。</li>
<li><a href="https://github.com/dotnet/roslyn/issues/131">ループの最初の1回だけ特別扱いする文法</a>: ない。そういうシナリオは確かにあるけども、専用構文を追加するほどの価値は見いだせない。</li>
<li><a href="https://github.com/dotnet/roslyn/issues/14">ラムダ式に対する型推論</a>: やらないけども、ローカル関数が代わりになる。</li>
<li><a href="https://github.com/dotnet/roslyn/issues/17">さらなる型推論</a>: ない。ここまで急進的な型推論をC#に入れたくはない。</li>
<li><a href="https://github.com/dotnet/roslyn/issues/102">多値戻り値</a>: タプル構文の一部になるはず。</li>
</ul>
<p>その他、いくつか簡単な検討あり。</p>
<ul>
<li><code>params</code> IEnumerable: 性能的に、単に配列使うんじゃなく、もっといい実装を検討したほうがよさそう。</li>
<li>immutable な型に対する初期化子: 「wither」と一緒に検討したい。</li>
<li><code>vararg</code> 呼び出し: <code>params</code> IEnumerable と一緒に検討したい。</li>
</ul>
<h2>C# Design Notes for Jul 1, 2015 #3913</h2>
<p><a href="https://github.com/dotnet/roslyn/issues/3913">https://github.com/dotnet/roslyn/issues/3913</a></p>
<p>Tuple がらみ、その後の状況(まだこれが最終決定じゃなく、いったんコミュニティからの感想受け付け用)。</p>
<h3>名前関連</h3>
<p>まず名前関連。あまり強く型付けしすぎないというのと、「C#のTupleはメソッド引数の延長」という発想の元、</p>
<ul>
<li>名前なし(匿名)Tuple作れるようにする</li>
<li>
同じ位置に同じ型が来ているTupleは、名前が違っても同じTuple型とみなす
<ul>
<li>ただし、<code>(first: &quot;John&quot;, doe: &quot;Doe&quot;)</code>みたいな、名前を明示する場合は順序の入れ替えあり</li>
<li>名前違い同型のTupleで配列を作ると、型推論結果は匿名Tupleの配列</li>
</ul>
</li>
</ul>
<p>とかに。</p>
<h3>エンコーディング</h3>
<p>具体的な実装と、Tupleに対応していない他の言語・古いC#との繋ぎ。</p>
<p>たぶん、</p>
<pre><code>
public struct ValueTuple<T1, T2, T3>
{
    public T1 Item1;
    public T2 Item2;
    public T3 Item3;
}
</code></pre>
<p>みたいな型と属性で実現することになるはず。他の言語・古いC#からは<code>Items1</code>とかでメンバーアクセスすることになるけども、C# 7.0からはどう見えるべきか。混乱を避けるには<code>Items1</code>でのアクセスは隠すべきだろう。</p>
<h3>分解(deconstruction)</h3>
<p>↓こういう分解用の構文を用意すべきかどうか。</p>
<pre><code>
(int sum, int count) = Tally(...);   
</code></pre>
<p>用意するならいくつか検討すべき疑問が残るものの、今のところその疑問を避けるべく、分解用の構文追加はしないでいる。</p>
<h3>その他の課題</h3>
<p>今のところ arity 0、1のTuple は考えていない。これらがあると便利だと思う(特に、コード生成の観点で)。でも、おそらく多くの疑問も起こすことになる。</p>
<p>その他いくつか、型変換(例えば、covariantな変換とか)も考えるに値するけども、今のところその検討は置いておく。</p>
 ]]></description>
				<pubDate>Sun, 12 Jul 2015 05:55:05 +0900</pubDate>
			</item>
			<item>
				<title>Unity(ゲームエンジン)上で async/await</title>
				<link>http://ufcpp.net/blog/2015/07/unityasyncbridge/</link>
				<description><![CDATA[ <p>async/await が使えないC#とかちょっと。</p>
<p>で、最近、Unity上でasync/awaitを使えるかもしれないという希望が見えてみたので、現状報告。</p>
<h2>背景</h2>
<p>主にUnityの問題点。数年来文句を言い続けて、一向に解決してもらえていない…</p>
<h3>Unity上のC#は3.0</h3>
<p>Unityが使っているC#は、結構古めの<a href="http://www.mono-project.com/">Mono</a> (確か 2.8 系)で、普段普通に最新のC#を使っている人の感覚では、結構きつい制限がかかった状態にあります。</p>
<ul>
<li>
C# 3.0相当
<ul>
<li>引数の規定値・名前付き引数(C# 4.0から)だけ使えたりするものの、structやenumの値を規定値に指定できなかったり</li>
</ul>
</li>
<li>
.NET 3.5相当(WPFとか除く)
<ul>
<li><code>System.Linq</code>は使える</li>
</ul>
</li>
</ul>
<p>これで何がつらいかというと、async/awaitが使えないのが一番つらい。スマホゲームって非同期処理の塊になるわけですが、そこでawaitが使えない3.0時代の書き方をするのとかもはや苦行で。</p>
<p>一応、Unity自体がコルーチンの仕組みを持っていて、それを使うということになっているものの、コルーチンだと、</p>
<ul>
<li>戻り値を返す仕組みを標準では持っていない</li>
<li>
<code>UnityEngine.dll</code> への依存が必要
<ul>
<li>しかもこのライブラリ、Unityの外から参照できない(実行時エラーを起こす)</li>
</ul>
</li>
<li><code>UnityEngine.GameObject</code> クラスが債務持ちすぎで気持ち悪い</li>
</ul>
<p>などのつらみがあります。</p>
<h3>DLL化で多少はマシに</h3>
<p>C# の最新機能が使えない理由は、大まかに2つあります。</p>
<ul>
<li>C#コンパイラーが古い</li>
<li>使える.NET標準ライブラリの制限がきつい</li>
</ul>
<p>前者の制限はまあなんとか回避する方法があったりします。C#の機能の多くは古い.NET Framework上でも動きます。
顕著なのは<a href="http://ufcpp.net/study/csharp/ap_ver6.html">C# 6.0</a>の新機能ですけども、ほとんどの機能が .NET Framework 2.0上でも動かせます(参考: <a href="http://ufcpp.net/study/csharp/cheatsheet/listfxlangversion/#v6">C#の言語バージョンと.NET Framework</a>)。</p>
<p>UnityはDLLの参照もできるので、コアロジックをUnityプロジェクトから完全に分離して、DLL化してから、Unityプロジェクト上にコピーすればコンパイラーの制限はかかりません。普通にC# 6.0が使えます。</p>
<p><img src="/media/1021/separatedlls.png" alt="コアロジックを分離・DLL化" /></p>
<p>うちのプロジェクトの場合、Unityの外とのコード共有(サーバー側ロジックとか、ゲームデータの編集ツールとか)を考えて最初から割かし徹底してプロジェクトを分けているので、かなりの部分でC# 6.0が使えています。</p>
<h4>DLLのコピーを楽に</h4>
<p>ちなみに、いくつか面倒はありますが、対処用のライブラリとかUnityエディター拡張を用意しています。</p>
<ul>
<li>DLLのコピーがめんどくさい → <a href="https://github.com/ufcpp/UnityTools/tree/master/CopyDllsAfterBuild">コピー用の仕組み(プロジェクト設定+スクリプト)のNuGet パッケージ</a>書いて公開してある</li>
<li>DLL化したらその中身のソースコードが見えない → Unityエディター拡張で、DLL参照を、元のC#プロジェクト参照に置き替えるスクリプトを書いてる</li>
</ul>
<h3>ライブラリの制限</h3>
<p>問題はライブラリに依存したC#機能の場合。具体的には</p>
<ul>
<li><a href="http://ufcpp.net/study/csharp/sp4_dynamic.html">dynamic</a></li>
<li><a href="http://ufcpp.net/study/csharp/sp5_async.html">async/await</a></li>
<li><a href="http://ufcpp.net/study/csharp/ap_ver5.html#CallerInfo">Caller Info</a></li>
<li><a href="http://ufcpp.net/study/csharp/st_string.html#FormatableString">FormattableString</a></li>
</ul>
<p>の辺りです。まあ、async/await以外はなくても我慢ができますが…</p>
<p>で、<a href="http://ufcpp.net/study/csharp/cheatsheet/listfxlangversion/#v6">C#の言語バージョンと.NET Framework</a>でちょっと書いていますが、足りない分は自前で同名・同名前空間・同機能のクラスを実装してしまえば、実は動かすことができます。</p>
<p>Monoのクラスライブラリ部分はMITライセンスですし、今なら、マイクロソフトによる実装もMITライセンスで徐々にオープンソース化されて行ってる最中です(<a href="https://github.com/dotnet/corefx">corefx</a>)。この辺りから移植すれば、Unityの古い環境でも、一応は最新機能を使えるはずだったりはします。</p>
<h3>AOT制限</h3>
<p>※ただし、iOSは除く。</p>
<p>でした。</p>
<p>iOSの場合、.NETやJavaのような仮想マシンコード実行が認められていないので、AOT(Ahead Of Time)というコンパイル方法で、事前にネイティブ コード化してアプリ パッケージ化します。こいつが曲者というか、古いバージョンのMonoでは制限がきつくて、いろいろなコードが実行時エラーになって困ります。</p>
<p>日本語でまとまってるのだとノイエさんとこの記事: <a href="http://neue.cc/2014/07/01_474.html">Unity + iOSのAOTでの例外の発生パターンと対処法</a></p>
<p>絶望的なのが<code>Interlocked.CompareExchange&lt;T&gt;</code>を使えないことでして、async/awaitの中核たる<code>Task</code>クラスがこれを多用しています。結局、Unity上でasync/awaitを使う道は閉ざされていました。</p>
<h2>これまでの回避策</h2>
<p>で、async/awaitが使えないなら。</p>
<h3>IteratorTasks</h3>
<p>うちで作っちゃったのが<code>Task</code>クラスもどき。</p>
<ul>
<li><a href="https://github.com/OrangeCube/IteratorTasks">IteratorTasks</a></li>
</ul>
<p>Unityのコルーチンと同じく、yield returnベースで非同期処理をするためのライブラリです。コルーチンと違って、</p>
<ul>
<li>Unityプロジェクトの外で使える</li>
<li>戻り値持ってる</li>
<li>.NET 4 以降標準の<code>Task</code>クラスとシグネチャそろえてある</li>
</ul>
<p>という辺りが利点。</p>
<p>とはいえ、「awaitの代わりにyield returnを使う」という辺りが所詮「もどき」でしかなく。</p>
<p>あと、「いくらなんでもそのうちUnityもC# 5.0に対応するだろう」とか高を括っていたので特に表立ったアピールはしていなかったりします。気が付けば何年これ使ってるんだろう…</p>
<p>というか、もう何度だって言いますが、<a href="http://www.slideshare.net/ufcpp/orange-cube-20153/18">「標準ライブラリの互換ライブラリなんてものは超バッド ノウハウ」「おかげさまで安定はしたけども、それは恥だと思っている」</a>。</p>
<h3>UniRx</h3>
<p>で、もう1個は今流行りのRx。</p>
<ul>
<li><a href="https://github.com/neuecc/UniRx">UniRx</a></li>
</ul>
<p>これは、IteratorTasksみたいな「もどき」移植じゃなくて、結構そのまま<a href="https://msdn.microsoft.com/en-us/data/gg577609.aspx">Rx</a>の移植。</p>
<p>async/awaitと違って、Rx的な非同期処理ならC# 3.0の範囲で書けるので、IteratorTasksと違って「無茶」をする必要がないのが利点。</p>
<p>あと、Rxはイベント処理にも使えます(というか、C# 5.0では単発の非同期処理は<code>Task</code>とasync/awaitを使って書いちゃうので、むしろイベント処理が主役というか)。</p>
<h2>それでもasync/await使いたい</h2>
<p>そして最近ふと気づいたことがいくつか。</p>
<ul>
<li><code>Task</code>クラス関連全体じゃなくて、async/awaitに必要な最低限の実装ならUnityの制限に引っかかりにくいんじゃないか</li>
<li><a href="http://blogs.unity3d.com/jp/2015/05/06/an-introduction-to-ilcpp-internals/">IL2CPP</a>に置き変わったらコンパイラーも差し替えれるんじゃないか</li>
</ul>
<h3>async/awaitに必要な最低限の実装</h3>
<p>まあ、非同期処理自体には、標準の<code>Task</code>クラスがなくても<a href="https://github.com/OrangeCube/IteratorTasks">IteratorTasks</a>とか<a href="https://github.com/neuecc/UniRx">UniRx</a>を持っているわけですから、別にそこから移植しないでもいいんじゃないかと。</p>
<p>async/awaitを実行するためには、<code>IAsyncMethodBuilder</code>インターフェイスをはじめとするいくつかの型の実装が必要なんですが、実のところ、<code>TaskCompletionSource&lt;TResult&gt;</code>クラスの機能くらいしか使っていなくて、ここだけ自作すれば、フル機能の<code>Task</code>要らないんですよね。</p>
<p>先週、その<code>IAsyncMethodBuilder</code>の<a href="https://github.com/rackerlabs/dotnet-threading">.NET 3.5向けバックポーティング</a>をしている人を見かけたのがきっかけなんですけども。これのコードをちょっと眺めていたら、<code>IAsyncMethodBuilder</code>等の実装は意外とUnityの制限に引っかかりそうなコードが少なくて。フル機能の<code>Task</code>実装さえ避ければ案外動くんじゃないかと。</p>
<h4>MinimumAsyncBridge</h4>
<p>ということで試しに作ってみました。</p>
<p>最初は、<a href="https://github.com/OrangeCube/IteratorTasks">IteratorTasks</a>とか<a href="https://github.com/neuecc/UniRx">UniRx</a>に直接手を加えるつもりで実装してしまったんですが。</p>
<ul>
<li><a href="https://github.com/OrangeCube/IteratorTasks/tree/master/IteratorTasks.Csharp5">IteratorTasks.Csharp5</a></li>
<li><a href="https://github.com/ufcpp/AwaitableUniRx">AwaitableUniRx</a></li>
</ul>
<p>よくよく考えてみたら、<code>TaskCompletionSource&lt;TResult&gt;</code>だけなら独立して実装した方がいいんじゃないかと思いなおして、作りなおしたのがこちら。</p>
<ul>
<li><a href="https://github.com/ufcpp/MinimumAsyncBridge">MinimumAsyncBridge</a></li>
</ul>
<p>まだ作ったばっかりで試験運用が足りてないのと、後述する「コンパイラー差し替え」のやり方も試してみたいのとで、今後こいつをどうするかはちょっと不透明ですが…</p>
<p>とりあえず今のところそれっぽくは動いています。</p>
<p>※あくまで、「Unityプロジェクトから分離、DLL化して使う」に限ってasync/awaitが使えます。</p>
<h3>コンパイラー差し替え</h3>
<p>「Unityプロジェクトから分離、DLL化して使う」という制限が、うちはまあ最初からDLL分離してるので問題ないんですけども、一般には面倒事だろうから<a href="https://twitter.com/ufcpp/status/616922280967344128">「需要どのくらいあるかなぁ」とつぶやいてみた</a>のが先週末。</p>
<p>そしたら、「<a href="https://twitter.com/movra_jr/status/616935458136846336">コンパイラーの差し替えして、Unityプロジェクト側でもC# 5.0/6.0使えるよ</a>」などと教えていただきまして。</p>
<p>なるほど。その手が一応あるのか…</p>
<p>ちなみに、これ、「<a href="http://blogs.unity3d.com/jp/2015/05/06/an-introduction-to-ilcpp-internals/">IL2CPP</a>がまともに動くなら」という前提がかかります。IL2CPPは、公称では「任意のILコードを実行できる」となっているので、コンパイラーを差し替えてもちゃんと動くはず。</p>
<p>IL2CPPさえまともなら… (ちなみに、今開発中のプロジェクトはいまだIL2CPPで動かず。)</p>
<h4>Unity C# 5.0 and 6.0 Integration</h4>
<p>その「コンパイラー差し替え」も紹介しておきます。</p>
<ul>
<li><a href="https://bitbucket.org/alexzzzz/unity-c-5.0-and-6.0-integration/src">Unity C# 5.0 and 6.0 Integration</a></li>
</ul>
<p>このリポジトリ自体にはコンパイラーの差し替えがらみのコードだけが入っています。async/awaitを動かすためには別途、</p>
<ul>
<li><a href="https://github.com/OmerMor/AsyncBridge">AsyncBridge</a></li>
<li><a href="https://www.nuget.org/packages/TaskParallelLibrary/">Task Parallel Library for .NET 3.5</a></li>
</ul>
<p>が必要です。</p>
<p>コンパイラー差し替えなのでそれなりに手順が要るんですが…</p>
<ul>
<li>このリポジトリ中の<code>cmcs.exe</code>をビルドして、Unityインストール フォルダーの<code>\Unity\Editor\Data\Mono\lib\mono\2.0</code>にコピーする</li>
<li>Unityプロジェクトの設定で、<code>Project Settings/Player/API Compatibility Level</code>を<code>.NET 2.0</code>にする</li>
<li><a href="http://www.mono-project.com/docs/about-mono/releases/4.0.0/">Mono 4.0.0</a> の C# 6.0コンパイラーか、<a href="https://github.com/dotnet/roslyn">Roslyn</a>のコンパイラーを、Unityプロジェクト内にコピーする</li>
</ul>
<p>「手順を踏むのが面倒」、「個人のプロジェクトじゃなくてUnityが公式にやってくれないと不安」、「IL2CPPほんとに大丈夫なの？」という懸念はあるものの、Unityプロジェクト内でもasync/awaitが使えるようになるのは魅力的だし… という感じで、迷いつつも導入の検討中。</p>
<h2>まとめ</h2>
<p>主に、Monoのバージョンが古い(特にiOS向けのAOTコンパイル)のせいで、Unityはいろいろと制限がきついです。特にきついのがasync/awaitが使えないことですが、最近、Unity上でasync/await使える希望が見えてきました。</p>
<ul>
<li><a href="https://github.com/rackerlabs/dotnet-threading">.NET 3.5向けバックポーティング</a>の実装を見てみたら、意外とUnityの制限避けれるかもしれない雰囲気</li>
<li><a href="http://blogs.unity3d.com/jp/2015/05/06/an-introduction-to-ilcpp-internals/">IL2CPP</a>がまともになりさえすれば、制限がだいぶ緩和される</li>
<li>そしたらコンパイラーも差し替えできるはず</li>
</ul>
<p>ということで、以下のものを紹介。</p>
<ul>
<li><a href="https://github.com/ufcpp/MinimumAsyncBridge">MinimumAsyncBridge</a>: 非同期処理自体には<a href="https://github.com/neuecc/UniRx">UniRx</a>などを使う前提で、async/awaitに必要なライブラリの最低ラインの実装</li>
<li><a href="https://bitbucket.org/alexzzzz/unity-c-5.0-and-6.0-integration/src">Unity C# 5.0 and 6.0 Integration</a>: Unityの使っているコンパイラーを差し替えて、Unityプロジェクト内でC# 5.0/6.0を使えるようにするもの</li>
</ul>
 ]]></description>
				<pubDate>Mon, 06 Jul 2015 12:50:29 +0900</pubDate>
			</item>
			<item>
				<title>【開催結果】2015世代のC#</title>
				<link>http://ufcpp.net/blog/2015/6/csharp2015-1/</link>
				<description><![CDATA[ <p>一昨日、勉強会を開いていたわけですが。</p>
<ul>
<li><a href="https://csugjp.doorkeeper.jp/events/26140">2015世代のC#</a></li>
</ul>
<p>部屋が狭くてお越しいただいた方にはご迷惑をおかけしました。
平日夜2時間の開催でここまで席が一瞬で埋まったのは、自分でも少しびっくり。</p>
<p>まあ、C#でのAndroid/iOS開発、Visual Studio 2015(VS OnlineやAzure含む)新機能、.NET Compiler Platformと、なかなかよいテーマをそろえられたとは思います。以下、発表資料へのリンクを残しておきます。</p>
<iframe src="//www.slideshare.net/slideshow/embed_code/key/LAM1d3OCZi4GN9" width="425" height="355" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe> <div style="margin-bottom:5px"> <strong> <a href="//www.slideshare.net/IGJP/visual-studio-xamarin" title="Visual Studio + xamarin で始めるモバイル アプリ開発" target="_blank">Visual Studio + xamarin で始めるモバイル アプリ開発</a> </strong> from <strong><a href="//www.slideshare.net/IGJP" target="_blank">インフラジスティックス・ジャパン株式会社</a></strong> </div>
<iframe src="//www.slideshare.net/slideshow/embed_code/key/yluqbPmqvM4Ic1" width="425" height="355" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe> <div style="margin-bottom:5px"> <strong> <a href="//www.slideshare.net/shinichikoga355/2015-newvisualstudio" title="新しい Visual Studio &amp; .NET と新時代のアーキテクチャ" target="_blank">新しい Visual Studio &amp; .NET と新時代のアーキテクチャ</a> </strong> from <strong><a href="//www.slideshare.net/shinichikoga355" target="_blank">慎一 古賀</a></strong> </div>
<iframe src="//www.slideshare.net/slideshow/embed_code/key/jczo2nB8lfLOG" width="425" height="355" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe> <div style="margin-bottom:5px"> <strong> <a href="//www.slideshare.net/ufcpp/net-compiler-platform" title=".NET Compiler Platform" target="_blank">.NET Compiler Platform</a> </strong> from <strong><a href="//www.slideshare.net/ufcpp" target="_blank">信之 岩永</a></strong> </div> ]]></description>
				<pubDate>Sat, 27 Jun 2015 08:16:38 +0900</pubDate>
			</item>
			<item>
				<title>【Roslynメタプログラミング】ValueChangedGanerator</title>
				<link>http://ufcpp.net/blog/2015/6/valuechangedganerator/</link>
				<description><![CDATA[ <p>多少やりすぎ感があって大々的に推すかどうかは迷っているものの…</p>
<ul>
<li><a href="https://github.com/ufcpp/ValueChangedGanerator">ValueChangedGanerator</a></li>
</ul>
<p><a href="https://github.com/dotnet/roslyn">.NET Compiler Platform</a> (コードネーム Roslyn)を使ったメタプログラミングというか、結構なコード生成ツールを作ってしまっていたり。</p>
<p><a href="https://csugjp.doorkeeper.jp/events/26140">今度やる勉強会</a>で.NET Compiler Platformの話をするのと、一度作ってしまえば仕事でも活用できそうだったので。</p>
<h2>生成ツールの概要</h2>
<p>要するに、たびたび出てくる「<code>INotifyPropertyChanged</code>の実装めんどくさい問題」に対する、Roslyn使った解決方法の1つ。</p>
<p><code>INotifyPropertyChanged</code>実装はめんどくさいものの、用途が限られてる(ほとんどの場合、クライアント開発者にしか使われない。サーバー側でも<code>INotifyPropertyChanged</code>自体は使われることあるけども、そっちは完全に自動生成の中に隠れてたり)のと、実装方法がたまーにカスタマイズしたいことがあって、C#言語構文としてコンパイラーが何か補助するような機能は作りにくいものです。</p>
<p>で、こういうめんどくさいくせに「用途限定」「実装に幅あり」なものに対して有効な解決策がメタプログラミングなわけですが。最近、Roslynを使ったコード生成にだいぶ慣れてきてしまい、作ってみたのがこの<a href="https://github.com/ufcpp/ValueChangedGanerator">ValueChangedGanerator</a>。</p>
<p>今回僕が作った実装以外にも、つい最近、<a href="http://neue.cc/">ノイエさん</a>が<a href="https://github.com/neuecc/NotifyPropertyChangedGenerator/">NotifyPropertyChangedGenerator</a>というやつも作っていたり。というか、これがこっち作るきっかけ。<a href="https://github.com/neuecc/NotifyPropertyChangedGenerator/">NotifyPropertyChangedGenerator</a>と<a href="https://github.com/ufcpp/ValueChangedGanerator">こっち</a>の違い(pull-req 送るとかでなく別実装した理由)は:</p>
<ul>
<li>プロパティ自身の書き換えでなく、コード生成元にはノータッチで、完全に別の場所にコードを生成</li>
<li>コード生成先を、同一ファイル内の #region ではなく、別ファイルに分離</li>
<li><code>SetProperty()</code>まではコード生成せず、こいつは元々ある想定</li>
</ul>
<p>の3点です。</p>
<h2>生成方式</h2>
<ul>
<li>生成元には、<code>NotifyRecord</code>という名前で入れ子になった構造体を定義します。</li>
<li>この名前の入れ子構造体があると、Quick Action(電球マーク)が出ます</li>
<li>「Generate properties」を選択すると、コードが生成されます。</li>
</ul>
<p><img src="/media/1019/screenshot.png" alt="スクリーンショット" /></p>
<p>例えば、以下のようなコードが Point.cs と言う名前であったとします。</p>
<pre class="source" title="">
<code><reserved></span><span class="reserved">partial</span> <span class="reserved">class</span> <span class="type">Point</span> : <span class="type">BindableBase</span>
{
    <span class="reserved">struct</span> <span class="type">NotifyRecord</span>
    {
        <span class="reserved">public</span> <span class="reserved">int</span> X;
        <span class="reserved">public</span> <span class="reserved">int</span> Y;
        <span class="reserved">public</span> <span class="reserved">int</span> Z =&gt; X * Y;

        <span class="inactive">///</span><span class="comment"> </span><span class="inactive">&lt;summary&gt;</span>
        <span class="inactive">///</span><span class="comment"> Name.</span>
        <span class="inactive">///</span><span class="comment"> </span><span class="inactive">&lt;/summary&gt;</span>
        <span class="reserved">public</span> <span class="reserved">string</span> Name;
    }
}
</code></pre>
<p>このファイル自体も、<code>Point</code>クラスに対して<code>partial</code>修飾子がつく修正がかかります。</p>
<p>そして、Point.ValueChanged.cs という名前で、以下のようなコードが生成されます。</p>
<pre class="source" title="">
<code><reserved></span><span class="reserved">using</span> System.ComponentModel;

<span class="reserved">partial</span> <span class="reserved">class</span> <span class="type">Point</span>
{
    <span class="reserved">private</span> <span class="type">NotifyRecord</span> _value;

    <span class="reserved">public</span> <span class="reserved">int</span> X { <span class="reserved">get</span> { <span class="reserved">return</span> _value.X; } <span class="reserved">set</span> { SetProperty(<span class="reserved">ref</span> _value.X, <span class="reserved">value</span>, XProperty); OnPropertyChanged(ZProperty); } }
    <span class="reserved">private</span> <span class="reserved">static</span> <span class="reserved">readonly</span> <span class="type">PropertyChangedEventArgs</span> XProperty = <span class="reserved">new</span> <span class="type">PropertyChangedEventArgs</span>(<span class="reserved">nameof</span>(X));
    <span class="reserved">public</span> <span class="reserved">int</span> Y { <span class="reserved">get</span> { <span class="reserved">return</span> _value.Y; } <span class="reserved">set</span> { SetProperty(<span class="reserved">ref</span> _value.Y, <span class="reserved">value</span>, YProperty); OnPropertyChanged(ZProperty); } }
    <span class="reserved">private</span> <span class="reserved">static</span> <span class="reserved">readonly</span> <span class="type">PropertyChangedEventArgs</span> YProperty = <span class="reserved">new</span> <span class="type">PropertyChangedEventArgs</span>(<span class="reserved">nameof</span>(Y));

    <span class="inactive">///</span><span class="comment"> </span><span class="inactive">&lt;summary&gt;</span>
    <span class="inactive">///</span><span class="comment"> Name.</span>
    <span class="inactive">///</span><span class="comment"> </span><span class="inactive">&lt;/summary&gt;</span>
    <span class="reserved">public</span> <span class="reserved">string</span> Name { <span class="reserved">get</span> { <span class="reserved">return</span> _value.Name; } <span class="reserved">set</span> { SetProperty(<span class="reserved">ref</span> _value.Name, <span class="reserved">value</span>, NameProperty); } }
    <span class="reserved">private</span> <span class="reserved">static</span> <span class="reserved">readonly</span> <span class="type">PropertyChangedEventArgs</span> NameProperty = <span class="reserved">new</span> <span class="type">PropertyChangedEventArgs</span>(<span class="reserved">nameof</span>(Name));
    <span class="reserved">public</span> <span class="reserved">int</span> Z =&gt; _value.Z;
    <span class="reserved">private</span> <span class="reserved">static</span> <span class="reserved">readonly</span> <span class="type">PropertyChangedEventArgs</span> ZProperty = <span class="reserved">new</span> <span class="type">PropertyChangedEventArgs</span>(<span class="reserved">nameof</span>(Z));
}
</code></pre>
<p><code>SetProperty</code>と<code>OnPropertyChanged</code>の実装は、元のクラス(今回の場合<code>Point</code>)が持っている前提でコード生成します。今回は、基底クラスで実装している想定。その基底クラス<code>BindableBase</code>は以下のような実装になっています。</p>
<pre class="source" title="">
<code><reserved></span><span class="reserved">using</span> System.Collections.Generic;
<span class="reserved">using</span> System.ComponentModel;
<span class="reserved">using</span> System.Runtime.CompilerServices;

<span class="reserved">class</span> <span class="type">BindableBase</span> : <span class="type">INotifyPropertyChanged</span>
{
    <span class="reserved">#region</span> INotifyPropertyChanged

    <span class="reserved">public</span> <span class="reserved">event</span> <span class="type">PropertyChangedEventHandler</span> PropertyChanged;

    <span class="reserved">protected</span> <span class="reserved">void</span> OnPropertyChanged(<span class="type">PropertyChangedEventArgs</span> args) =&gt; PropertyChanged?.Invoke(<span class="reserved">this</span>, args);

    <span class="reserved">protected</span> <span class="reserved">void</span> OnPropertyChanged([<span class="type">CallerMemberName</span>] <span class="reserved">string</span> propertyName = <span class="reserved">null</span>) =&gt; OnPropertyChanged(<span class="reserved">new</span> <span class="type">PropertyChangedEventArgs</span>(propertyName));

    <span class="reserved">protected</span> <span class="reserved">void</span> SetProperty&lt;<span class="type">T</span>&gt;(<span class="reserved">ref</span> <span class="type">T</span> storage, <span class="type">T</span> value, <span class="type">PropertyChangedEventArgs</span> args)
    {
        <span class="reserved">if</span> (!<span class="type">EqualityComparer</span>&lt;<span class="type">T</span>&gt;.Default.Equals(storage, value))
        {
            storage = value;
            OnPropertyChanged(args);
        }
    }

    <span class="reserved">protected</span> <span class="reserved">void</span> SetProperty&lt;<span class="type">T</span>&gt;(<span class="reserved">ref</span> <span class="type">T</span> storage, <span class="type">T</span> value, [<span class="type">CallerMemberName</span>] <span class="reserved">string</span> propertyName = <span class="reserved">null</span>) =&gt; SetProperty(<span class="reserved">ref</span> storage, value, <span class="reserved">new</span> <span class="type">PropertyChangedEventArgs</span>(propertyName));

    <span class="reserved">#endregion</span>
}
</code></pre>
<p>もちろん、このためにだけに継承を使うのは嫌という話もあります。それはまた<a href="https://github.com/ufcpp/MixinGenerator">別の方法</a>で解決しようかなぁと(未実装。Test-Firstで先に生成前後のサンプルだけあり)。そっちもやりすぎ感あふれてて悩ましいですが…</p>
<h2>実装の理由</h2>
<h3>生成元は正規のC#文法</h3>
<p>「似て非なる何か」、「亜種」を作らないように、生成元のコードは通常のC#の文法に収まるようにしています。</p>
<p>なので、多少冗長な感じは残ります。今回の実装だと、一段階入れ子にした構造体に元定義を書くので、3行(<code>struct NotifyRecord</code>, <code>{</code>, <code>}</code>)と、1インデント分の無駄はあります。</p>
<h3>生成は静的に/生成結果がC#コードとして見れる</h3>
<p>デバッグ上、生成結果のC#コードが見れるというのは非常に重要。</p>
<p>他の言語で見られるような、動的な処理とか、ビルド後コード挿入でやるようなメタプログラミングは、だいたいデバッグできなくて泣きそうになるので。</p>
<p>.NET Compiler Platformを使ったコード生成でやっているので、この条件は自然と満たします。</p>
<h3>生成元と生成結果が分かれるように</h3>
<p>生成の前後のコードが混ざると、再生成時にどこを書き替えたらいいのか分からなかったり、機械生成の部分に手を入れてしまって再生成で消してしまったりするので。</p>
<p>今回は、元は入れ子の構造体なので、生成元と生成結果がかち合うことはない。
また、<code>partial</code>にして別ファイルに分離。</p>
<h3>docコメントも付くように</h3>
<p>生成結果が<code>public</code>なプロパティなので、ここにdocコメントが付いていてほしい。でないと、「doc XMLを出力する」設定でビルドした時に警告が大量に出てしまうので。</p>
<p>今回は、生成元のフィールドに付けたdocコメントをそのまま移植する実装になっています。</p>
<h2>利用方法</h2>
<p><a href="https://github.com/ufcpp/ValueChangedGanerator">github公開してるソースコード</a>の他に、パッケージ化してギャラリーに置いてあります。</p>
<ul>
<li><a href="https://visualstudiogallery.msdn.microsoft.com/bf5dbce2-b73d-4f5f-8e1c-0e1de386b7ce">VSIX(Visual Studio拡張)形式をVisual Studio Galleryに</a></li>
<li><a href="https://www.nuget.org/packages/ValueChangedGanerator/">NuGet形式をNuGet Galleryに</a></li>
</ul>
 ]]></description>
				<pubDate>Fri, 12 Jun 2015 13:40:41 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップ Roslyn 6/10</title>
				<link>http://ufcpp.net/blog/2015/6/pickuproslyn0610/</link>
				<description><![CDATA[ <h2>Numeric literals (binary and digit separators) #2950</h2>
<p><a href="https://github.com/dotnet/roslyn/pull/2950">https://github.com/dotnet/roslyn/pull/2950</a></p>
<p><a href="http://ufcpp.net/blog/2015/5/pickuproslyn20150514/">先月くらいにちょこっと書いた</a>やつですが、2進リテラルの実装。</p>
<p>pull-req 出してる人がマイクロソフトにインターン中の学生っぽく、インターンの課題かなぁというやつ。マージがうまくいかなかったのか、一度Closeして別のpull-reqが出しなおされてますが、最近になって急にレビューがつくようになって、今、「LGTM」(Looks Good To Me: 私はいいと思う)コメントが付いたところ。</p>
<p>C# 6.0/Visual Studio 2015 RTMには乗らないやつですが、futureブランチとかに取りこまれていくのかな、たぶん。</p>
<h2>Local functions #3372</h2>
<p><a href="https://github.com/dotnet/roslyn/pull/3372">https://github.com/dotnet/roslyn/pull/3372</a></p>
<p>もう1個、同じインターンの学生さんのタスクっぽい新機能実装。</p>
<p>ローカル関数(メソッド内に、そのメソッド中だけのスコープでメソッドを定義できる)を実装したみたい。こちらは今日、レビューを終えて、「<a href="https://github.com/dotnet/roslyn/tree/features/local-functions">local-functions</a>」って名前のブランチにマージされた模様。大きな問題が出なければ、このままC# 7.0にとりこまれるのかな。</p>
<h2>[C# Feature Request]Multilingual XML Document Comment #3371</h2>
<p><a href="https://github.com/dotnet/roslyn/issues/3371">https://github.com/dotnet/roslyn/issues/3371</a></p>
<p>XMLドキュメント コメントに翻訳入れさせてくれという要望。</p>
<p>これ、前々から言ってるんですよねぇ。<a href="https://visualstudiogallery.msdn.microsoft.com/">Visual Studio Gallery</a>とかには多言語対応(日本語記事と英語記事をちゃんと両方書いて、同じIDに紐づけておける)入れてるんだから、ソースコードにも多言語対応できる仕組み入れてって。</p>
<p>現状、GitHubとかで公開して、それをできる限り多くの人に使ってほしかったら、全コメント英語で書くのが無難になってしまい。まあ、あきらめて英語で書くんですけど。</p>
<h2>async sequences</h2>
<p>もう2週間前の話になってしまうんですが、async sequences に関する議論の中で、proof of conceptにasync iteratorsの実装書いてみたよって人が。</p>
<p><a href="https://github.com/dotnet/roslyn/issues/261#issuecomment-105960240">https://github.com/dotnet/roslyn/issues/261#issuecomment-105960240</a></p>
<p>今のところC#チームの中の人っぽい応答は0。代わりに<a href="https://github.com/dsyme">dsyme</a> (MSリサーチのF#の人)が食いついてたりはしますが。</p>
 ]]></description>
				<pubDate>Wed, 10 Jun 2015 08:23:48 +0900</pubDate>
			</item>
			<item>
				<title>【開催告知】勉強会「2015世代のC#」</title>
				<link>http://ufcpp.net/blog/2015/6/csharp2015/</link>
				<description><![CDATA[ <p>ある程度情報が出そろってからブログを書こうとしていたら、もう現時点で申し込み多数…</p>
<p>日本C#ユーザー会 &amp; codeseek 勉強会「<a href="https://csugjp.doorkeeper.jp/events/26140">2015世代のC#</a>」を開きます。</p>
<ul>
<li>2015/6/25 19:00~</li>
<li>品川、日本マイクロソフト セミナールームB</li>
<li>参加費: 無料</li>
</ul>
<p>詳細は<a href="https://csugjp.doorkeeper.jp/events/26140">Doorkeeperのページ</a>をご覧ください。</p>
<p>平日2時間の勉強会ですけども、Xamarinを使ったクロスプラットフォーム開発、アーキテクチャ、Roslynを使ったコード解析と、2015年世代におけるよさげなセッションを集めれたかなと思います。</p>
<p>察しのいい人はお気づきかと思いますが、今回、日経BP様のご厚意により、</p>
<ul>
<li>
<a href="http://amzn.to/1QlaCAS">C#実践開発手法</a>と<a href="http://amzn.to/1M5VEOC">.NETのエンタープライズアプリケーションアーキテクチャ</a>それぞれ3冊提供(じゃんけん大会)
<ul>
<li>会場内での販売も予定しています</li>
</ul>
</li>
<li>ピザ・ビール等の食事つき</li>
</ul>
<p>となっています。</p>
<p>(じゃんけん大会は後ろ(懇親会)でなく、前半に済ませてしまうかも)</p>
<p>残席僅かとなっていますが、ぜひともお越しください。</p>
<iframe src="http://rcm-fe.amazon-adsystem.com/e/cm?t=cunflc-22&o=9&p=8&l=as1&asins=4822298477&ref=qf_sp_asin_til&fc1=000000&IS2=1&lt1=_blank&m=amazon&lc1=0000FF&bc1=000000&bg1=FFFFFF&f=ifr" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe>
<iframe src="http://rcm-fe.amazon-adsystem.com/e/cm?t=cunflc-22&o=9&p=8&l=as1&asins=4822298485&ref=qf_sp_asin_til&fc1=000000&IS2=1&lt1=_blank&m=amazon&lc1=0000FF&bc1=000000&bg1=FFFFFF&f=ifr" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe> ]]></description>
				<pubDate>Tue, 02 Jun 2015 04:16:56 +0900</pubDate>
			</item>
			<item>
				<title>できるVisual Studio 2015</title>
				<link>http://ufcpp.net/blog/2015/6/bookvs2015/</link>
				<description><![CDATA[ <p>もう買える状態になっているんですね、「<a href="http://amzn.to/1Q1Lu7g">できるVisual Studio 2015</a>」。</p>
<h2>紹介</h2>
<p>ということで書籍紹介。</p>
<p>言わずと知れた売れ筋書籍の「できる」シリーズに、「Visual Studio 2015」が加わりましたが、少々僕も絡んでいます。</p>
<iframe src="http://rcm-fe.amazon-adsystem.com/e/cm?t=cunflc-22&o=9&p=8&l=as1&asins=B00Y07AVIK&ref=qf_sp_asin_til&fc1=000000&IS2=1&lt1=_blank&m=amazon&lc1=0000FF&bc1=000000&bg1=FFFFFF&f=ifr" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe>
<p>書籍案内のページには共著っぽい作者の並び方をしていますが、まあ、実のところ僕が関わっているのはサンプル プログラム提供と監修だったりします。</p>
<p>(各所に「まとまった分量を書く余裕はありません」と断りを入れまくっているので、あんまり関わってる度合い大きく見られると断った方面への申し訳が立たなかったり。)</p>
<p>ちなみに、「勉強会等で景品にしてよい」としてもらっている見本書籍、まだ何冊か持っているので、ご興味ある方はご連絡ください。</p>
<h2>監修</h2>
<p>企画や構成にはノータッチなんですが、打合せに出て「そういう章にするんだったら、Visual Studioにはこういう機能もありますよ」くらいの意見は出しています。あと、一応、文章は一通り全部目を通して校正しています。</p>
<p>サンプル提供に際して、手順のスクリーンショットも取ってお渡ししていたり。</p>
<h2>サンプル</h2>
<p>今回サンプルを作るにあたって、「Visual StudioもGitHub対応を推してきている時代ですし、サンプルはGitHub公開してしまいましょう」という話を取り付けてあります。勉強会や記事のサンプルとして、誰でも自由に使ってもらって構いません。</p>
<p>先ほど公開設定をしたので、URLを貼っておきます。</p>
<p><a href="https://github.com/ufcpp/CanDoVS2015">https://github.com/ufcpp/CanDoVS2015</a></p>
<p>ちなみに、GitHubリポジトリ中のコードは、「本誌向け」となっているものでも、実際に書式掲載されているものとは異なる(今一緒でも今後修正される可能性もある)ので、「書籍サポート」の対象外です。</p>
<p>「できる」シリーズの性質上、本誌掲載コードでできることは限られるわけですが、上記GitHubリポジトリには、<a href="https://github.com/ufcpp/CanDoVS2015/tree/master/Ideal/KabeDon">「書籍のテーマとか、文章の書きやすさとかの前提を全部無視して作るとしたら」バージョン</a>のコードとかも含まれていたりします。
「前提無視」バージョンの方は、SharedプロジェクトやPCLを使ったコード共有を最大限やっていたり、Xamarin.Formsを使ってAndroid/iOS両対応していたりもします。</p>
<p>こっちのバージョンも、現状は、結構適当に書いた状態だし、ゲームとしてはまだまだクソゲーなので、他の人も巻き込んでもうちょっとまともなものにできたらなぁと思っていたりします。</p>
 ]]></description>
				<pubDate>Tue, 02 Jun 2015 03:51:23 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップRoslyn 5/27</title>
				<link>http://ufcpp.net/blog/2015/5/pickuproslyn27/</link>
				<description><![CDATA[ <p>引き続き、<a href="https://github.com/dotnet/roslyn">Roslynリポジトリ</a>は「RTMに向けてバグ修正で手いっぱい」感漂って来てて、新しい話はあまりないんですが。</p>
<p>というか、割かし重複提案なissueが立って、速攻で「それ、これとの重複じゃない？」→「重複だった…」的な流れになってるものが多々。まあ、issueが800件超えっぱなしですからねぇ、このリポジトリ。</p>
<p>そんな中いくつか。</p>
<h2>Support the tadpole operators #3072</h2>
<p><a href="https://github.com/dotnet/roslyn/issues/3072">https://github.com/dotnet/roslyn/issues/3072</a></p>
<p>完全にネタというか、ネタに振り回されてるというか。</p>
<p>大元の火種はこれ: <a href="http://blogs.msdn.com/b/oldnewthing/archive/2015/05/25/10616865.aspx">New C++ experimental feature: The tadpole operators</a></p>
<p>「<a href="http://blogs.msdn.com/b/oldnewthing/">The Old New Thing</a>」は、「Windows秘話」「Windows温故知新」的に、「Windowsのここがダメだ」とか言われまくってる辺りに対して、何でそんな風になってるのかとか、そんな話を面白おかしくネタにしているブログ。有名な奴だと、「『Windowsはいつも無駄に見た目ばっかり変えやがって』って文句言うけどさ、中身だけ無茶苦茶進化してて、見た目が変わってない電卓は、ずっと進化してること気づいてもらえなかったんだぞ」みたいな話(「<a href="http://blogs.msdn.com/b/oldnewthing/archive/2004/05/25/141253.aspx">When you change the insides, nobody notices</a>」)とか。</p>
<p>で、今回やらかしたネタが、「オタマジャクシ演算子」。機能的に言うと、「副作用のない<code>++</code>, <code>--</code>」、「高優先度の単項<code>+1</code>, <code>-1</code>演算子」。</p>
<table>
<tr>
<th>構文</th>
<th>意味</th>
<th>覚え方</th>
</tr>
<tr>
<td>`-~y`</td>
<td>`y + 1`</td>
<td>オタマジャクシが値の方に向かって泳いで、値を増やす。</td>
</tr>
<tr>
<td>`~-y`</td>
<td>`y - 1`</td>
<td>オタマジャクシが値から去るように泳いで、値を減らす。</td>
</tr>
</table>
<p>これを、「Visual Studio 2015 RCで実装してみた実験的な試み」とか言って紹介（もちろん嘘）。The Old New Thingの方のコメントでも、Roslyn issueページの方のコメントでも、割かしみんな盛大に釣られてるっぽい。</p>
<p><a href="http://blogs.msdn.com/b/oldnewthing/archive/2015/05/26/10617079.aspx">The Old New Thingの次のブログ エントリー</a>でネタを明かしていますが、これ、別に「実験的に実装したもの」じゃなくて、現状の正規のC++文法で(C#ででも)認められた普通の演算です。<a href="http://ufcpp.net/study/computer/GeneralComputerCircuit.html#two-complement">2の補数</a>とかを知ってれば簡単にわかるんですが、ビット反転 <code>~</code> と符号反転 <code>-</code> は1違いの数字になるので。単にこれを並べただけ。</p>
<p>なんというか。4月1日にやれよ…</p>
<h2>Provide simple syntax to create a weak-referenced eventhandler #101</h2>
<p><a href="https://github.com/dotnet/roslyn/issues/101">https://github.com/dotnet/roslyn/issues/101</a></p>
<p>弱イベント作れる専用構文ほしいという要望。</p>
<p>まあ、気持ちはわからなくはないけども。うちのサイトにも「<a href="http://ufcpp.net/study/csharp/RmWeakReference.html#weak-event">弱イベント</a>」の話ありますが。</p>
<p>乱用すると性能面での影響が無視できない、かつ、何も知らないと簡単に乱用される機能なんですよねぇ。個人的にはあると楽になるけど、ほんとにあったらやばそうな機能すぎて、ちょっと。</p>
<h2>Compilation without generics #3064</h2>
<p><a href="https://github.com/dotnet/roslyn/issues/3064">https://github.com/dotnet/roslyn/issues/3064</a></p>
<p><a href="http://en.wikipedia.org/wiki/.NET_Micro_Framework">.NET Micro Framework</a>ではジェネリック使えないんだし、C#コンパイラー的に「ジェネリックを認めない」版を提供してくれないかという要望。</p>
<p>というか、<a href="http://ufcpp.net/study/csharp/sp_event.html#auto-event">C# 4.0以降、自動実装イベントから生成されるコードが変わって</a>、中身でジェネリック版<code>Interlocked.CompareExchange</code>を使うようになったせいで、.NET MFでイベントが使えないという問題と合わさって結構深刻みたい。</p>
<p>.NET MF自体が今後どうなの？という感じもあり。</p>
<p>まあ、この場合、本当の問題は、自動実装イベントが<code>Interlocked.CompareExchange</code>に依存してることな感じも。コンパイラー生成コードが、undocumentedに、何か特定のAPIに依存しているってのはあんまりよくない状態。</p>
 ]]></description>
				<pubDate>Wed, 27 May 2015 02:23:02 +0900</pubDate>
			</item>
			<item>
				<title>Visual Studio 2015 RC と pdb2mdb</title>
				<link>http://ufcpp.net/blog/2015/5/pdb2mdbvs2015rc/</link>
				<description><![CDATA[ <p>Unity (というか、Visual Studio Tools for Unity)とVisual Studio 2015 RCとの間での問題で、PDBからMDBへの変換がうまく動いてなくて困っている(一時的な対処方はなんとかできてる)という話。</p>
<h2>PDB, MDB</h2>
<p>まず、PDBって何かの簡単な紹介から。</p>
<p>PDBはProgram Databaseの略です。</p>
<p>Program Databaseは、実行ファイルのどの辺りが、ソースコードの何行目でどのメソッド通ってるかとかの情報が入ったファイルです。Visual Studio上でブレイク ポイント仕掛けて止めたり、スタック トレース追えたりするのはこの情報ありき。</p>
<p>とはいえ、この手のProgram Databaseには規格とか標準がなくて、Visual Studioが使ってる形式がPDB(拡張子も .pdb)で、Monoが使ってる形式がMDB。別形式です。</p>
<p>一応、Monoはpdb2mdb っていうツールを提供していて、PDBからMDB形式に変換できたりはします。</p>
<p><a href="http://xamarin.com/platform">Xamarin.Android, Xamarin.iOS</a>, <a href="http://japan.unity3d.com/">Unity</a>とかに対してVisual Studioを使った開発がしたい場合、PDBからMDB変換して実行することになります。だいたいは裏で勝手にやってくれるんですが、それが最近うまく動いていない状態だったりします。</p>
<h2>PDB の形式変わったみたい</h2>
<p>何のせいで問題が出ているかというと、PDBの形式が変わったみたい。</p>
<p>Unityについてくるバージョンのpdb2mdb(Unityインストール フォルダー以下、 Editor\Data\MonoBleedingEdge\lib\mono\4.0\pdb2mdb.exe にある)とか、<a href="https://www.nuget.org/packages/Mono.pdb2mdb">NuGet Gallaryから取れるバージョン</a>だと、</p>
<pre>
Unknown custom metadata item kind: 6
</pre>
<p>とかいうエラーを吐いて停止。</p>
<p>monoのGitHubリポジトリを見てみたところ、先月に</p>
<ul>
<li><a href="https://github.com/mono/mono/commit/facbf81e0589bd1a854bec2336caa0d4c061b801">pdb2mdb fix decimal values reading</a></li>
</ul>
<p>っていうコミットがあったんで、たぶんこれですかね。PDB中のdecimalの値がちゃんと読めていなかったらしい。</p>
<p>ちなみに、Visual Studio 2015 RC付属(インストーラーでチェックを入れれば一緒にインストールされる)Xamarin.Androidだとこのコミットとりこみ済みみたいで、正しく実行できます。</p>
<h2>最新のpdb2mdb</h2>
<p>が、<a href="https://visualstudiogallery.msdn.microsoft.com/8d26236e-4a64-4d64-8486-7df95156aba9">Visual Studio 2015 Preview Tools for Unity</a> がまだこれに対応していないくさくて、Visual Studio 2015でビルドしたDLLをUnityに持ってきても、MDBファイルができなくなっておりまして。</p>
<p>(最終更新日時4/30ってなってるのをインストールしてみてもダメでした。インストールしなおしがうまく行ってないのかもしれないものの。)</p>
<p>あと、この問題が解消したバージョンのpdb2mdbのありかがわからず… </p>
<p>結局、Xamarin.Androidでは動いているはず(= 問題解消済みのpdb2mdbが動いているはず)なので、</p>
<ul>
<li>Visual Studio 2015同梱のXamarin.Androidのプロジェクト テンプレートを覗いて</li>
<li>\Program Files (x86)\MSBuild\Xamarin\Android に関連ファイルがあって</li>
<li>Xamarin.Android.Build.Tasks.dll ってDLLの中にpdb2mdb相当の処理が入ってることを調べて</li>
<li><code>Pdb2Mdb.Converter.Convert</code>静的メソッドを呼べばいいこと突き止めて</li>
<li>PowerShell スクリプト書いて実行</li>
</ul>
<p><script src="https://gist.github.com/ufcpp/49fa3e76c1246fd434b4.js"></script></p>
<p>とかいう作業を今日やったり。</p>
<p>Visual Studio Tools for Unityがちゃんと対応するまでの一時しのぎではあるんですけども。嫌な処理を書いてしまった…</p>
 ]]></description>
				<pubDate>Fri, 22 May 2015 11:05:39 +0900</pubDate>
			</item>
			<item>
				<title>ピックアップ Roslyn 5/14</title>
				<link>http://ufcpp.net/blog/2015/5/pickuproslyn20150514/</link>
				<description><![CDATA[ <p><a href="http://channel9.msdn.com/events/build/2015">Build 2015</a>の資料に目を通すので忙しくてサボっていましたが。</p>
<p>まあ、もっとも、C#チーム、Visual Studioチーム的にもRC版が出たばかり、かつ、RTMも近いだろう状況で、GitHub上の動きを見ててもバグ修正で多忙な雰囲気を感じます。</p>
<p>そんな中、いくつかピックアップ。</p>
<h2>Unicode version number</h2>
<p><a href="https://github.com/dotnet/roslyn/issues/2648">https://github.com/dotnet/roslyn/issues/2648</a></p>
<p>「C#では、常に実行環境の最新のUnicodeバージョンを利用したいので、仕様書上はUnicodeバージョン番号を消そう」とのこと。</p>
<p>基本的にはUnicodeって追加される一方なので、そのほうがいいですよね。<a href="http://ufcpp.net/study/csharp/misc_unicode.html#katakana-middle-dothttp://">レアケース</a>もあるにはあったんですが。</p>
<h2>csc2/vbc2 撤廃</h2>
<p><a href="https://github.com/dotnet/roslyn/pull/2711">https://github.com/dotnet/roslyn/pull/2711</a></p>
<p>Roslyn製の新コンパイラーは、2種類(C#, VBともに2種類ずつ)ありました。</p>
<ul>
<li>csc/vbc.exe: 以前の(Visual Studio 2013までの)コンパイラーと同じような動作のスタンドアローン動作版。</li>
<li>csc2/vbc2.exe: 複数のプロジェクト間で標準ライブラリなどの読込結果を共有するために、Windowsサービスとして常時動いてるコンパイラーに仕事を投げるもの。</li>
</ul>
<p>今は、csc/vbc 側が内部的に KeepAlive オプションとかを持っていて、旧 csc2/vbc2 的な動作もできるみたいです。</p>
<p>今の、Visual Studio 2015 RC版で、「&quot;csc2.exe&quot; はコード 1 を伴って終了しました。」とかいう謎エラー メッセージが出てくる問題、そろそろおさらばできそうかも。</p>
<h2>2進数リテラル、_ 区切りの実装</h2>
<p><a href="https://github.com/dotnet/roslyn/pull/2730">https://github.com/dotnet/roslyn/pull/2730</a></p>
<p>そういえば、C# 6.0から漏れてたのよね、忘れてたけども。<code>0b101001</code> みたいな2進数リテラルを書ける機能と、<code>0xff_ff_ff_ff</code>みたいな、<code>_</code> で数値リテラルを区切れる機能。</p>
<p>割りかし実装は簡単な類の機能なわけですが、それでもこんな、C# 6.0 RTMの直前(冒頭で書いたとおり、今はRTMに向けてバグ修正で手一杯のはず)になんで？</p>
<p>と思って調べてみたら、このpull-req主、マイクロソフトにインターンで入って来た学生っぽい。確かに手頃な課題。</p>
<h2>メソッド名に <code>!</code> 記号を使わせて</h2>
<p><a href="https://github.com/dotnet/roslyn/issues/2696">https://github.com/dotnet/roslyn/issues/2696</a></p>
<p>要するに、Rubyな人がRubyの命名規約習いたいから、<code>Enlarge!</code> (記号の<code>!</code>までがメソッド名)みたいな識別子を認めてほしいと要求。</p>
<p>まあもちろん、そんな要求そのままは受け入れがたいわけですが。とはいえ、いくつかわからなくもない話の流れが。</p>
<ul>
<li>
Rubyで末尾に<code>!</code>をつけるのは、「引数で受け取ったオブジェクトに対して副作用をかけますよ」というのを示す規約
<ul>
<li>例えば <code>X M(X x)</code>はメソッド内で新しい<code>X</code>のインスタンスを作って返すのに対して、<code>void X!(X x)</code>はインスタンス<code>x</code>を書き換える</li>
<li>あくまで命名規約。守られる保証はない</li>
</ul>
</li>
<li>
C#的にはちょっと
<ul>
<li>守られる保証のない命名規約自体、C#は望まない</li>
<li>語尾に<code>Pure</code>であるとか、多少煩雑になるけども、最初から使える文字を使うべきではないか</li>
<li><code>[Pure]</code>属性をつけるとか、属性ベースでやるのがC#っぽいのではないか</li>
</ul>
</li>
<li>
ただ、属性ベースだと…
<ul>
<li>利用側、ぱっと見で区別が付かない</li>
<li>確かに副作用を起こすかどうかはぱっと見で区別ついた方が良さそう</li>
<li>特定の属性が付いている場合に、IDE上での表示(色など)が変わる機能でもあればいいんだけど</li>
</ul>
</li>
<li>
IDE上の表示で区別するとして
<ul>
<li>それって、Visual Studioはともかく、今どきだったらXamarin Studio, Visual Studio Code, OmniSharpなどなど、いろいろ選択肢はあるけども、その全てが対応してくれなきゃ嫌だ</li>
</ul>
</li>
</ul>
<p>的な。</p>
<p>まあ、副作用起きるというのが目に見えてほしいという点に関してはわかる。</p>
 ]]></description>
				<pubDate>Thu, 14 May 2015 14:49:52 +0900</pubDate>
			</item>
			<item>
				<title>Build 2015</title>
				<link>http://ufcpp.net/blog/2015/5/build2015/</link>
				<description><![CDATA[ <p><a href="http://channel9.msdn.com/events/build/2015">Build 2015</a> の資料に目を通すの数日かかった… 結構長し読みだったんですけども。</p>
<p>CEO交代後のマイクロソフトの</p>
<ul>
<li>デバイスとサービスの会社になる</li>
<li>すべての開発者、すべてのデバイス、すべてのプラットフォームにアプローチ</li>
</ul>
<p>という方針がついに形になって表れ始めたという印象でした。</p>
<h2>デバイス</h2>
<p>発表の3分の1くらいは「Windows 10」がらみでした。</p>
<p>ようやく、デスクトップとモバイルの分断が解消されそうというか、WindowsとWindows Phoneが統合されそうというか。</p>
<h3>Universal</h3>
<p>これまで 「ストア アプリ」とか変な名前だったけども、「Universal Windows Platform」「Universal Windows Apps」と、やっとまともな名前になった印象。</p>
<h3>完全に単一のバイナリ</h3>
<p>IoT、Phone、Tablet、デスクトップ、大スクリーン(XBoxゲーム、Surface Hubなどの会議システム)すべてをカバー。
(Windows 8.1の「Universal Apps」はWindowsとWindows Phoneは別バイナリ、ストアが単一化されてたのと、Shared Projectでのコード共有ができるようになってただけ)</p>
<p>そのために、</p>
<ul>
<li>
レスポンシブ デザイン
<ul>
<li>スクリーン サイズに応じて Visual State Managerとか使ってXAMLのデザインを分岐</li>
<li>(XAML的にも、XAML中のタグを遅延ロードするような機能(x:DeferLoadStrategy)が増えてたり)</li>
</ul>
</li>
<li>
API Contract
<ul>
<li>メソッド名や型名指定でAPIがデバイス上で使えるかどうかを調べて分岐する処理を書く</li>
</ul>
</li>
</ul>
<p>とかやるように。</p>
<h2>サービス</h2>
<p>同じく発表の3分の1くらいは「Azure」がらみでした。といっても、OSとかハードウェア(IaaS的なクラウド)じゃなくて、「サービス」が主役。</p>
<ul>
<li>
<a href="https://buchizo.wordpress.com/2015/03/25/azure-app-service/">Azure App Service</a>
<ul>
<li>API Apps: 開発者が新たにサービスAPIを作って公開・消費するための基板</li>
<li>Logic Apps: BizTalkやソーシャル関連APIなどののAPIを組み合わせてフローを構築するアプリ開発基盤</li>
</ul>
</li>
<li><a href="http://azure.microsoft.com/ja-jp/services/machine-learning/">Azure Machine Leaning</a></li>
<li><a href="http://dev.office.com/">Office 365 Depelover Program</a></li>
</ul>
<p>などなど、細粒度のサービスをマイクロソフト自身が売ったり、サービスの開発・登録・検索・消費などをしやすくするための基板を提供したり。
マイクロソフトが自社の強みを活かしてクラウド戦略を推し進めてますね。</p>
<h2>すべての開発者に</h2>
<p>.NET/C#を使える理由もだいぶ増えるし、使わなくていい理由もだいぶ増える印象。
いろんな言語・環境を使っている人が、フェアに相互に行き来できるよい環境ができそう。</p>
<h3>すべてのプラットフォームで.NET開発</h3>
<ul>
<li><a href="https://code.visualstudio.com/">Visual Studio Code</a></li>
<li>
<a href="https://github.com/dotnet/corefx">.NET Core</a>
<ul>
<li>Windows x64環境向けはRCに
Linux, Macはベータ</li>
<li>Xamarinは今、モバイル(Xamarin.iOS, Xamarin.Android)に注力していて、サーバー側機能はプロダクション環境向けのサポートしていない</li>
</ul>
</li>
</ul>
<p>Visual Studio Codeとか、中身は単に<a href="http://blog.shibayan.jp/entry/20150430/1430328999">Electron + Monaco</a>、つまり、これまでもVisual Studio Online向けに作っていた、Webなエディターを、Electron使ってアプリ化しただけ。
実装に関する手間は対してかかっていなさそうだし、名前に反して「Visual Studio」とは完全に別系統のアプリなんですが。
とはいえ、「Visual Studio」の名前を関したアプリとして.NET関連のどこかのチーム(たぶんASP.NET系な雰囲気がする)が提供・保守していくということの。</p>
<h3>Visual Studio利用者にすべてのプラットフォーム開発機能を提供</h3>
<ul>
<li><a href="https://msdn.microsoft.com/ja-jp/library/dn872463(v=vs.140).aspx">Cross-Platform Mobile Apps in C++</a></li>
<li><a href="https://msdn.microsoft.com/ja-jp/library/dn771545.aspx">Apache Cordova</a></li>
<li><a href="http://xamarin.com/">Xamarin</a></li>
</ul>
<p>コンパイラーが提供されているって意味では、C++は一番クロスプラットフォームなプログラミング言語のはずなんですけども。
とはいえ、プラットフォーム固有のAPI・ライブラリ参照であるとか、プロジェクト構築とか考えるとそんなに容易くない。
それが今回、クロスプラットフォーム向けのC++テンプレートが提供されて、Visual Studio上でAndroidやiOSアプリをC++でようになりました。</p>
<p>Office 2016がUniversal Apps化して、AndroidやiOS版もリリースされて、しかも、コードの9割以上を共有しているらしく、そのおこぼれな感じはします。
Officeの影響はやっぱり大きいですねぇ。Officeの性能を出すためにXAMLにも結構新機能が入ったそうですし。</p>
<h3>すべてのプラットフォーム開発者にUniversal Windows Appsの開発機能を提供</h3>
<ul>
<li>
<a href="https://dev.windows.com/en-us/uwp-bridges">Universal Windows Platform Bridges</a>
<ul>
<li>Project &quot;Astoria&quot;: </li>
<li>Project &quot;Islandwood&quot;: </li>
<li>Project &quot;Centennial&quot;: </li>
<li>Project &quot;Westminister&quot;: </li>
</ul>
</li>
</ul>
<p>Bridges(相互の橋渡し)の各種プロジェクトは、コードネームがAndroidのA、iOSのI、ClassicのC、WebのWを頭文字とするワシントン州の地名なのかな、また。
レジストリの仮想化とか、Android/iOSのAPIの互換レイヤーの提供というものみたい。</p>
<p>これまで、スマホやタブレット対応のために一度AndroidやiOSに移っていったエンタープライズ企業をWindowsに呼び戻すよい戦略。
一方、コンシューマーだとどうだろう…という感じはします。</p>
<p>全APIの完全互換とかはたぶん無理だろうし、実際、Buildの資料にも「APIのサブセットを提供」って書かれてて。
「AndroidやiOSアプリのコードをほぼそのまま持ってきて、少し書き替えるだけでUniversal Windows Apps化できる」とか言っていますが、どこまで楽に移植できるのかはちょっと心配。
試してみたいものの、ダウンロードするのに登録が必要だったり、手持ちにそれなりの規模のAndroid/iOSアプリがないので。</p>
 ]]></description>
				<pubDate>Sat, 09 May 2015 08:23:34 +0900</pubDate>
			</item>
			<item>
				<title>++C++; // 未確認飛行 C をリニューアルしました</title>
				<link>http://ufcpp.net/blog/2015/5/renewal/</link>
				<description><![CDATA[ <img src="/images/sitelogo_l.jpg" width="456" height="65" style="border:none;"/>
<p>「++C++; // 未確認飛行 C <a href="http://ufcpp.net" title="ufcpp.net">ufcpp.net</a>」 をリニューアルしました。これに伴い、ブログも統合し「WordPress <a href="https://ufcpp.wordpress.com/">https://ufcpp.wordpress.com/</a>」から「<a href="http://ufcpp.net/blog">http://ufcpp.net/blog</a>」へ変更となります。</p>
<p>2000年よりサイトを運営しているため、一部古い内容のものがあります。ご了承ください。</p>
<p>誤字・脱字・バグを見つけた場合や、ご意見・ご要望等がございましたら、<a href="https://github.com/ufcpp/UfcppSample/issues">GitHub の Issues</a> までご連絡いただけますと助かります。</p>
<p>前のバージョンでは XML を XSLT でパースし、静的に HTML をホストしていました。リニューアル後では、<a href="http://umbraco.com/">Umbraco 7</a> を使用しています。Umbraco は、.NET Framework, ASP.NET で動作するオープンソースの CMS です。 <a href="http://www.asp.net/">ASP.NET 公式サイト</a>も Umbraco で構築されています。</p>
 ]]></description>
				<pubDate>Wed, 06 May 2015 14:58:24 +0900</pubDate>
			</item>
</channel>
</rss>