ufcpp-live / UfcppLiveAgenda

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

Visual Studio 17.2 Preview 2, .NET 7 Preveiw 2 #55

Closed ufcpp closed 2 years ago

ufcpp commented 2 years ago

配信URL: https://www.youtube.com/watch?v=i2RBGZq0BJU

https://docs.microsoft.com/en-us/visualstudio/releases/2022/release-notes-preview#17.2.0-pre.2.0 https://devblogs.microsoft.com/dotnet/announcing-dotnet-7-preview-2/

いうほど新しい話なさそう… 「Introducing the new Regex Source Generator」に至っては「Preview 1 の頃からあるけどブログにしてなかったわ」のはず。

そして微妙にバグっぽい https://twitter.com/ufcpp/status/1504262994213355522 https://twitter.com/ufcpp/status/1504389869530873857

LDM

ということで配信するなら Language Design Meeting 議事録の話中心になりそうな雰囲気。

ufcpp commented 2 years ago

メモ: Google.Protobuf が SourceLink 使ってる < F12 ステップイン可能

ufcpp-live commented 2 years ago

image

ufcpp-live commented 2 years ago

image

ufcpp-live commented 2 years ago
/*このコメントめったに使わないよね*/
#if false // こっちの方が多い
var s = """
    [
    {
        "id": 123,
        "name": "abc",
        "data": [ true, null ]
    },
    {}
    ]
    """;

new Regex("\\d+");
#endif
ufcpp-live commented 2 years ago
#if tru // e 1文字でコメント アウト・イン切り替え
var s = """
""";
#endif
ufcpp-live commented 2 years ago

image

// これやりたいけどなー
var id = 123;
var name = "abc";

var s = /*lang=json,strict*/ $$"""
    {
        "id": {{id}},
        "name": {{name}},
        "data": [ true, null ]
    }
    """;
ufcpp-live commented 2 years ago
// embedded language のインターフェイスが public になった暁には…
// lang 名の被り回避がいるのでは?!
var s = /*lang=jp.co.my-lang*/ """
    {
        "id": 123,
        "name": "abc"
    }
    """;

ジャヴァジャヴァしてきた。

ufcpp-live commented 2 years ago
struct S
{
    public int X { get; }
    public int Y { get; }

    public S()
    {
        this = default; // これ要る?
        X = 1;
    }
}

image

クラスと同様0初期化でよくない?

ufcpp-live commented 2 years ago
struct S
{
    private int _x;
    public int Y { get => _x; set => _x = value; }

    public S()
    {
        Y = 1; // _x 初期化よりも前に、auto じゃないプロパティ触るな
    }
}
ufcpp-live commented 2 years ago
struct S
{
    public int X { get => field; set => field = value; }

    public S()
    {
        X = 1; // じゃあ semi-auto プロパティどうするの?
        // 今、これ、書けるようにする方向で検討中。
    }
}
ufcpp-live commented 2 years ago
struct S
{
    public int X { get; }
    public int Y { get; }

    public S()
    {
        this = default; // X に 0 → 1 で2回初期化かかる。ちょい遅。
        X = 1;
    }

    public S()
    {
        X = 1;
        // this = default じゃなくて Y = 0 を挿入してくれればノーコストじゃない?
    }
}
ufcpp-live commented 2 years ago
struct S
{
    public int X { get; }
    public int Y { get; }

    public S()
    {
        X = 1;
        Console.WriteLine(Y); // 0 が出るようにするはず?
    }
}
ufcpp-live commented 2 years ago
public int X
{
    get => field;
    set
    {
        field = value; // これはキーワードの field

        if (true)
        {
            var field = 1; // どうも、OK にする模様
            var value = 2; // ダメ(元からそういう仕様)
        }

        var a = (int field) => { }; // shadowing OK
        var b = (int value) => { }; // shadowing OK
    }
}
ufcpp-live commented 2 years ago
struct S
{
    public int X { get => field; }
    public int Y { get; }
    // ↑ X と Y はほぼ同様の扱いの予定。

    public S()
    {
        X = 1; // X のバッキングフィールドへの直代入
        Y = 2; // Y のバッキングフィールドへの直代入
    }
}

↑この仕様にすることにより、↓みたいになる

struct S
{
    public int X { get => field; set => field = value * value; }

    public S()
    {
        X = 2; // Q. これはどうなるの?
        // (初期案の) A. バッキングフィールドへの直代入
        // すなわち、new S().X は 2 になるはず。

        // というのが紛らわしすぎるんで、
        // ちゃんと setter 呼ぶようにしようよ見たいな話になり。
        // それはそれで、「フィールド初期化後でないとプロパティを参照できない」問題にひっかかる
        // なので、さっきの struct 初期化の話が出た。
    }
}
ufcpp-live commented 2 years ago
struct S
{
    public int X
    {
        get => field;
        set
        {
            if (field != value)
            {
                field = value;
                OnPropertyChanged("X");
            }
        }
    }

    public S()
    {
        X = 2;
        // X の field が未初期化だと、 if(field != value) がまずい。
        // ↓
        // 先に0初期化する仕様が必須
    }
}

また NRT ではまりそう…

ufcpp-live commented 2 years ago
var s1 = nameof(String); // OK
var s2 = nameof(string); // NG
var s3 = nameof(value); // OK
var s4 = nameof(field); // OK? NG?
ufcpp-live commented 2 years ago
ReadOnlySpan<char> s = "abc";

if (s is "abc") // 仕様として常に MemoryExtensions.SequenceEqual を使う
{
}

// 今まだ実装ないけど、↓も行けるようにするみたいな話あり
ReadOnlySpan<byte> u = "abc"u8;

if (u is "abc") // "abc"u8 扱いのはず
{
}
ufcpp-live commented 2 years ago
string s1 = "abc";
if (s1 is null) // OK
{
}

ReadOnlySpan<char> s2 = null; // これも別に OK

ReadOnlySpan<char> s = "abc";
if (s is null) // でもこれはダメな予定(暗黙の変換ダメ!)
{
}
ufcpp-live commented 2 years ago
Span<int> s = null;

Console.WriteLine(s.Length); // NO ぬるぽ。0 が返る。

// default(Span<int>) と
// (Span<int>)default(int[]) は
// 一緒であってほしい感が多少

unsafe
{
    int* p = null; // null でも

    for (int i = 0; i < 0; i++) // length 0 なら
    {
        var x = p[i]; // ぬるぽらない
    }
}

Span<int> s2 = default;

unsafe
{
    fixed(int* p = s2) // p は null
    {
        for (int i = 0; i < s2.Length; i++) // length 0 だから
        {
            var x = p[i]; // ぬるぽらない
        }
    }
}
ufcpp-live commented 2 years ago
// C# 11
var array = new[] { 1, 2, 3, 4, 5, };

if (array is [1, ..var middle, 5])
{
    Console.WriteLine(string.Join(", ", middle)) ;
}

// ↓C# 11 どころかまだもうちょっと先
var list = [1, ..array, 2]; // spread operator の ..
// 1, 1,2,3,4,5, 2

Range[] rangeList = [1, ..i, 2]; // この .. は Range?それとも spread?

// とはいえ、リストリテラルの方の .. で迷いが生じるなら、
// C# 11 のリストパターンの .. にも再考の余地あり。
// 今そこが悩み。
// 今のところ、このまま .. で行くの優勢。

// ↓こんな仮想的な構文考えたときに、 .. が range か spead かマジでわからない。
// spread が ... なら問題ないんだけども…
ReadOnlySpan<byte> data1 = [0x64, 0x61, 0x74, 0x61]; // これを
ReadOnlySpan<byte> data2 = [0x64, ..0x6174, 0x61]; // こう多少書きたい気持ちがなくはない
ReadOnlySpan<byte> data3 = [..0x64617461];
// (エンディアン怖い)

ReadOnlySpan<byte> data4 = "\u0064\u0061\u0074\u0061";
ReadOnlySpan<byte> data5 = "\u64617461"; // これもダメ
ReadOnlySpan<byte> data6 = "64617461"bin; // ほんとはこんなのほしい(またC++になっちゃう…)
ufcpp-live commented 2 years ago
class A
{
    [RegexGenerator(...)]
    [DllImportGenerator(...)]
    void M() { }
}

// RegexGenerator の生成物
class A_M { }

// DllImportGenerator の生成物
class A_M { } // RegexGenerator のやつと衝突!

// この衝突を避けるための file private 必要じゃない?
// 以下の2つの名前は衝突しないようにする。

// RegexGenerator の生成物
file private class A_M { } // $<>ファイル名_A_M とかにエンコード?
// DllImportGenerator の生成物
file private class A_M { }
ufcpp-live commented 2 years ago
class X
{
    //file private ← protected internal の方が長かったわ
    //ref ← 行けるようになったとして、さすがに用途的に ref record 使わない?
    unsafe protected internal readonly partial record struct S { }
}