Skip to content

Instantly share code, notes, and snippets.

@ufcpp
Created August 6, 2020 03:23
Show Gist options
  • Save ufcpp/1b095c997a58440f59d85b232986826c to your computer and use it in GitHub Desktop.
Save ufcpp/1b095c997a58440f59d85b232986826c to your computer and use it in GitHub Desktop.
// ライブラリとしてコンパイルする想定のコード。
// <Project Sdk="Microsoft.NET.Sdk">
// <PropertyGroup>
// <TargetFramework>netstandard2.0</TargetFramework>
// <LangVersion>preview</LangVersion>
// </PropertyGroup>
// </Project>
using System;
using System.Runtime.CompilerServices;
namespace ClassLibrary1
{
/// <summary>
/// ModuleInitializer を持ってない型を1個用意。
/// 「この無関係なクラスのメンバーを1個を呼ぶだけで ModuleInitializer がついてるメソッドが全部呼ばれる」というのの確認用。
/// </summary>
public class Class1
{
public static string Name => "ClassLibrary1.Class1";
}
public class A
{
[ModuleInitializer]
internal static void Init() => Console.WriteLine("init A");
}
public class B
{
[ModuleInitializer]
internal static void Init() => Console.WriteLine("init B");
}
public class C
{
[ModuleInitializer]
internal static void Init() => Console.WriteLine("init C");
}
}
namespace System.Runtime.CompilerServices
{
/// <summary>
/// .NET 5 には標準で入ってる属性。
/// このコードは netstandard2.0 想定で書いてるので自前定義。
/// 自前定義でもちゃんと働く。
/// </summary>
[AttributeUsage(AttributeTargets.Method, Inherited = false)]
internal sealed class ModuleInitializerAttribute : Attribute
{
}
}
// module initializers
// Class1 を ProjectReference なり PackageReference なりする想定。
using System;
using System.Runtime.CompilerServices;
// 別 dll で定義してるクラスを1個呼ぶ。
// ClassLibrary1 の ModuleInitializer がこのタイミングで全部呼ばれる。
Console.WriteLine(ClassLibrary1.Class1.Name);
// このモジュール自体にも module initializers を定義。
// Main 実行時点で読まれてるので、ClassLibrary1.Class1 に触るよりも前に読まれてる。
// なので、こっちが先に実行される。
class Init
{
[ModuleInitializer]
internal static void M1() => Console.WriteLine("Init.M1");
[ModuleInitializer]
internal static void M2() => Console.WriteLine("Init.M2");
}
// static anonymous functions
using System;
// ローカル関数の場合は C# 8.0 時点で入ってたやつ
// OK
static void staticLocal() { }
int local = 1;
// ↓これだと、ローカル変数をキャプチャしちゃってるのでダメ。コンパイル エラー。
//static void badStaticLocal() => Console.WriteLine(local);
// C# 9.0 で、それと同じことがラムダ式、匿名メソッド式でもできるように。
// OK
Action staticLambda = static () => { };
Action staticAnonymousMethod = static delegate () { };
// コンパイル エラー
//Action badStaticLambda = static () => Console.WriteLine(local);
//Action badStaticAnonymousMethod = static delegate () { Console.WriteLine(local); };
// target-typed conditional expressions
void targetTypedConditional(bool x)
{
// target-typed で、1 : null の部分がちゃんと int? になる。
int? v1 = x ? 1 : null;
// あくまで target-typed で判定してるので、以下のような推論は働かない(コンパイル エラー)。
// 1 と null の「共通型」は確定できない。
//var v2 = x ? 1 : null;
}
// target-typed switch と conditional のネストもちゃんと行けてる
int? targetTypedConditional2(int i, bool b) => i switch
{
> 0 => b ? 1 : null,
0 => b ? null : 0,
< 0 => b ? 2 : null,
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment