-
-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
今日もC# 10.0(来年の話) #17
Comments
本題とはそれるけど、カルチャー依存文字列処理が NLS (Windows 内蔵の)から ICU (デファクトスタンダード)に移行した話とか、それに伴ってこれまで顕在化してなかった「デフォルト動作が CurrentCulture 利用で変」問題(Ordinal のつもりで呼んでたけど間違ってたみたいなコード)が起こってたりとか、特に、 dotnet/runtime 43956 43736 |
今日の書き捨てコード 今日の主題としては触れなかったものの、「低水準機能拡張」の一環で safe 固定長バッファーあり。 safe 固定長バッファーがあるなら、 // safe 固定長バッファー
// managed 型も OK
string x[10];
m("abc", "def");
void m(params Span<string> p)
{
} |
Union 型話(構文未定。仮想的なコード) // 可能性としてあり得る一番短い書き方
enum record Shape
{
Rect(double Width, double Height);
Circle(double Radius);
}
union Union
{
String(string n);
Int1(int x);
Int2(int x);
// 匿名 union でいうと string | int | int になるけども…
} 数学では // disjoint sum |
Discriminated Union はやっぱり「小さい機能の集まり」として実装されるはず。 その1: 網羅性チェック using System.Runtime.CompilerServices;
// 第1案: 網羅性チェック
static class Extensions
{
// private コンストラクターがある時に限り、網羅してる扱いで警告消していいんじゃない?
public static double Area(this Shape s) => s switch
{
Shape.Rect r => r.Width * r.Height,
Shape.Circle c => c.Radius * c.Radius,
};
}
record Shape
{
private Shape() { }
public record Rect(double Width, double Height) : Shape;
public record Circle(double Radius) : Shape;
}
// recortd, discriminated union に限らず
class ShapeC
{
private ShapeC() { }
public class Rect : ShapeC { public double Width; public double Height; }
public class Circle : ShapeC { public double Radius; }
} |
Discriminated Union がらみその2 // using static だとこのファイルがまさに問題起こす
//using static Shape;
//using static ShapeType;
// これで Rect, Circle が名前被りに
// 第2案: スコープ解決の推論
static class Extensions
{
// 別提案として、こういうところに using を書かせてほしいという話もあり
//using System;
public static bool M1(this ShapeType s) => s switch
{
// ここに using を書く余地はない
ShapeType.Rect => true,
ShapeType.Circle => false,
};
// enum でこう書きたい
// using static ShapeType で似たことはできるけど…
// using static だとスコープがさすがに広すぎる
public static bool M2(this ShapeType s) => s switch
{
Rect => true,
Circle => false,
};
// discriminated union 前提として
public static double Area1(this Shape s) => s switch
{
Shape.Rect r => r.Width * r.Height,
Shape.Circle c => c.Radius * c.Radius,
};
// やっぱりこう書きたい
public static double Area2(this Shape s) => s switch
{
Rect r => r.Width * r.Height,
Circle c => c.Radius * c.Radius,
};
}
record Shape
{
private Shape() { }
public record Rect(double Width, double Height) : Shape;
public record Circle(double Radius) : Shape;
}
enum ShapeType
{
Rect,
Circle
} |
簡単そうに見えて、型推論にかかる時間が簡単に爆発的に増えるのでやばい。 var x = new[]
{
"",
1,
1f,
};
// 型推論の時間かかる。C# は認めてない
var x = new[]
{
(IB)null,
(IC)null,
};
// これはOK
var x1 = new IA[]
{
(IB)null,
(IC)null,
};
var x2 = new[]
{
(IA)null,
(IC)null,
}; |
C# はコンパイル時間にも結構気を使って文法を決めてる。 // これは割と最近追加されたオーバーロード解決。
// パフォーマンスのペナルティは大してないらしい
static class ClassEx
{
public static void M<T>(this object _) where T : class { }
}
static class StructEx
{
public static void M<T>(this object _) where T : struct { }
} |
// オーバーロード解決は2乗オーダーだそうです
class Overload
{
public void M(int x, int y) { }
public void M(int x, short y) { }
public void M(short x, short y) { }
public void M(int w, int x, int y) { }
public void M(int w, int x, short y) { }
public void M(int w, short x, short y) { }
public void M(short t, int x, int y) { }
public void M(short t, int x, short y) { }
public void M(short t, short x, short y) { }
public void M(short t, int w, int x, int y) { }
public void M(short t, int w, int x, short y) { }
public void M(short t, int w, short x, short y) { }
} |
.NET 5 ではグローバリゼーションの内部実装が ICU に変更されて… using System;
// ファイルの改行コード依存
// LF にすると 0 になる
// git が autocrlf = ture だったら?…
var s = @"
"; // \r\n ? それとも \n ?
// 一応の解決策(絶対いや)
var s1 = "1行目" + Environment.NewLine
+ "2行目";
// ダメだ…
//const string cs = "1行目" + Environment.NewLine
// + "2行目";
Console.WriteLine(s.IndexOf("\n")); // .net core 3.1 だと 1、.net 5 だと -1
Console.WriteLine(s.IndexOf('\n'));
Console.WriteLine(s.Contains("\n")); // true
Console.WriteLine(s.IndexOf("\n", StringComparison.Ordinal)); // これなら 1
Console.WriteLine(s.AsSpan().IndexOf("\n")); // Span の方はデフォで Ordinal
Console.WriteLine(s.Replace("\n", "aa")); // Ordinal!!!!!!
// IndexOf は CurrentCulture 見る
// Contains は Ordinal |
カルチャーというと… using System;
using System.Text;
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
Console.WriteLine("i".ToUpper(
System.Globalization.CultureInfo.GetCultureInfo("tr-TR")));
Console.WriteLine("i".ToUpperInvariant());
// トルコ語の i の大文字は İ
// ASCII で完結していないので「ASCII 特殊対応 fast path」とかが作れない
Console.WriteLine(DateTime.Now.ToString(
System.Globalization.CultureInfo.InvariantCulture));
//10/31/2020 17:02:47 になる
// せめて ISO 標準の 2020/10/31T17:02:47 にしようよ… Invariant がアメリカ式(ヤードポンド、ファーレンハイトの国)の書式なのどうなの… |
主に昨日書いたブログをベースに。
csharplang の運営方針とかトリアージとか
サムネに使ってるコード(大まかなアイディア レベル。今は動かないし、具体的な構文はまだ未定):
これを C# 9.0 で動く状態にするなら:
(デモ用に適当に書いたコードなので、縁の面積が r2 になってる… 気にしないでほしい)
The text was updated successfully, but these errors were encountered: