ufcpp-live / UfcppLiveAgenda

@ufcpp live streaming agenda
MIT License
24 stars 2 forks source link

C# feature triage 2022 夏 #60

Closed ufcpp closed 1 year ago

ufcpp commented 1 year ago

配信URL: https://youtu.be/EyrpKfC0q9k

feature triage

https://github.com/dotnet/csharplang/blob/main/meetings/2022/LDM-2022-08-24.md

去年に引き続き「これをもってC# 12に入る・入らないを占わないでほしい」という注釈付きで、11以後の話。 トリアージということになってるけど、内容的には「タスクの積み下ろし」程度。

こんな雰囲気だし、配信でも今積みタスク化してる提案振り返る?

ちなみに、その後、partial property は正式に提案 issue 立った。 csharplang/issues/6420

毎年恒例「Performance Improvements in .NET 7」

https://devblogs.microsoft.com/dotnet/performance_improvements_in_net_7/

つかめないスクロールバー。 導入文章にある「去年、長すぎると批判を受けた」。 「TL;DR: .NET 7 むっちゃ速い」。

ufcpp-live commented 1 year ago
// .NET Fx 1 のころからこう。今更何も変わらず。
//var x = double.NaN;
//var y = double.NaN;
//Console.WriteLine(x == y);
//Console.WriteLine(x.Equals(y));

var v1 = new System.Numerics.Vector3(0, 0, float.NaN);
var v2 = new System.Numerics.Vector3(0, 0, float.NaN);

Console.WriteLine(v1 == v2); // false
Console.WriteLine(v1.Equals(v2)); // これが .NET 6→7 で false→true 

// たぶん、float → Vector<float> 使った vectorize 最適化とかしてる人だけが踏む地雷。
ufcpp-live commented 1 year ago

「みんな、.NET 7 にすぐ上げる?」的な話題の中で:

var x = """
    raw string だけ書ければ文句ない。
    LangVersion 11 で十分。
    TargetFramework 変えるモチベーションはそこまでない。
    """;
ufcpp-live commented 1 year ago
/*
 * これをコピペすると
{ "aaa": "bbb" }
 */

var x = """
    { "aaa": "bbb" }

    """;

// 最近のアプデで Visual Studio 自動成型してくれる
var y = "{ \"aaa\": \"bbb\" }\n";
var z = @"{ ""aaa"": ""bbb"" }
";
ufcpp-live commented 1 year ago
// lang=json //,strict
var x = """
    {
       1: 1,
       true: false,
       abc: "abc", // aaa
    }
    """;
ufcpp-live commented 1 year ago
// lang=json
var x = """
    {
       "a": 1,
       "b": 2, // この時点で A, B そろったので parse 打ち切る
       "a": 3
    }
    """;
ufcpp-live commented 1 year ago

.NET Framewor 1.0 やで。

    <TargetFramework>net10</TargetFramework>
ufcpp-live commented 1 year ago
var a = 1;
var b = 1;
var c = 1;
var d = 1;

// これ、今 OK
var x = (a<b, (c)>(d));

// intersection type (案)
// この手の文法、今後も足せない疑惑。
// () を使えない。
// () が出てくると、上記の (c) のところ壊す。
(IEnumerable<float> | IEnumerable<int>) m(){ }
ufcpp-live commented 1 year ago
unsafe
{
    Console.WriteLine(sizeof(double?)); // 16になるのやだー!!
}

// Rust とかは、
// T が正常値として 0 を持たない保証があるとき、HasValue を消す
//struct Nullable<T>
//{
//    public bool HasValue; // これが邪魔
//    public T Value;
//}
ufcpp-live commented 1 year ago
//todo:
// 1. A みたいなラッパーの自動生成
// 2. 場合によっては A への変換を implicit に
M<A>(new(1));
M(1);

static void M<T>(T x)
    where T : IMyInteface
{
    Console.WriteLine(x.ToHexString());
}

public interface IMyInteface
{
    string ToHexString();
}

// int に対して使いたいときは int のラッパーを1個作らないとダメ
public record struct A(int X) : IMyInteface
{
    public string ToHexString() => X.ToString("X");
}

// 文法案
extension A of int : IMyInterface
// implicit extension A of int : IMyInterface
// role A of int : IMyInterface
{

}
ufcpp-live commented 1 year ago
var a = new A(0, 0);
serializer.Serialize(a);
// { "X": 0, "Y": 0 }
// 「デフォルト値だったら何も書かない」みたいなオプション指定で
// { } にしたい。

write<bool, Shape_bool>(false);
// role が入ると
// write(false); だけで行けるようになるはず。たぶん。

// さらに…
write<bool[], ArrayShape<bool, Shape_bool>>(false);
write<bool?, NullableShape<bool, Shape_bool>>(false);
write<bool?[], ArrayShape<NullableShape<bool, Shape_bool>>>(false);

// さらに…
// ArraySegment, Span, List, ImmutableArray

static void write<T, TShape>(T value)
    where TShape : struct, Shape<T>
{
    if (default(TShape).IsDefault(value))
    {
        // この時だけ書く
    }
}

interface Shape<T>
{
    bool IsDefault(T value);
}

struct Shape_bool : Shape<bool>
{
    public bool IsDefault(bool value) => !value;
}

struct Shape_byte : Shape<byte>
{
    public bool IsDefault(byte value) => value == 0;
}

struct Shape_int : Shape<int>
{
    public bool IsDefault(int value) => value == 0;
}
// これを残り、sbyte, short, ushort, uint, long, ulong, float, double
// 場合によっては DateTime, DateTimeOffset, TimeSpan, Guid, TimeOnly, DateOnly, ...
// 最近だと Half, Int128, UInt128
ufcpp-live commented 1 year ago

特に static abstract も入ったので…

static void write<T, TShape>(T value)
// 元は
//where TShape : struct, Shape<T>
    where TShape : Shape<T>
{
    // 元は default(TShape).IsDefault
    if (TShape.IsDefault(value))
    {
        // この時だけ書く
    }
}

interface Shape<T>
{
    // 元は bool IsDefault(T value);
    static abstract bool IsDefault(T value);
}
ufcpp-live commented 1 year ago
m(new[] { 1, 2, 3 }, x => x < 2);

static int m(int[] data, Func<int, bool> pred)
{
    var sum = 0;
    foreach (var x in data)
    {
        if (predが前回と同じなら)
        {
            pred の中身をインライン展開
        }
        else if (pred(x)) sum += x;
    }
    return sum;
}
ufcpp-live commented 1 year ago
// 今の仕様だと内部で Array.CreateInstance(typeof(A), ...) 呼ぶ。
// これが AOT 環境で呼べない。
Enum.GetValues(typeof(A));

// 代わりに int[] で返せば AOT で動くよ!

// なぜなら、.NET では↓これが合法だから。
var array = (A[])(object)new int[] { 1, 2, 3 };
foreach (var x in array) Console.WriteLine(x);

enum A
{
    X, Y, Z, W
}
ufcpp-live commented 1 year ago

サイズが同じな構造体は同じ扱い。

using System.Runtime.CompilerServices;

var data = new double[] { 1, 2, 3, -1 };
var asLong = Unsafe.As<double[], long[]>(ref data);

foreach (var x in asLong)
{
    Console.WriteLine($"{x:X}");
}

// これに対して Unsafe.As<T[], Wrapper<T>[]>(ref array) はやる。
record struct Wrapper<T>(T Value);
ufcpp-live commented 1 year ago

今日のまとめは TL;DR: .NET 7 is fast.

ufcpp-live commented 1 year ago
// これ行ける
using System.Text;

const string s1 = $"aaa {nameof(Int32)} aaa";

// これ、Culture のせいで無理…
const string s2 = $"aaa {1.2} aaa";

// Culture 指定できたとしても、C# の言語使用が .NET ランタイムに依存するという問題がある。

// MM/dd/yyyy ゆするまじ。
// やーぽん絶許
ufcpp-live commented 1 year ago
// かつて、$"" 周りいろいろキモイことになってるので、
// $""u8 はほんとにそれが必要になるまで触れない方がいいと思う。
IFormattable u1 = $"";
A.m("");
A.m($"{1}");

StringBuilder sb = new();
sb.Append(""); // string
sb.Append($"{1}"); // AppendInterpolatedStringHandler
sb.Append($""); // string

class A
{
    public static void m(string s) { }
    public static void m(IFormattable s) { }
}