Closed ufcpp closed 11 months ago
意図的に12からカットされてるやつ:
var x = [1,2,3];
不可 → natural type を何にするかで迷ってる
IList<T>
とか IEnumerable<T>
とか、List<T>
が実装してるインターフェイスに対しては使える(List<T>
になる)[1,2,3].AsList()
みたいな拡張メソッド target-type 選択 → 単純にアイディア出たのが遅すぎて間に合わない12までには入るはずだと思うけど今ないやつ:
ImmurableArray<int> x = [1,2,3];
はコレクション初期化子同様ぬるぽReadOnlySpan<T> items = [v1, v2, v3];
が new T[3]
生成されてる → InlineArray を使うように変更されるはず["key": value]
。 → これは12予定になってるかちょっと自信ない。元から13かもusing System.Collections;
using System.Runtime.CompilerServices;
MyArray<int> array = [1, 2, 3];
[CollectionBuilder(typeof(MyArray), nameof(MyArray.Create))] // 17.7p5 時点で効いてなさげ
struct MyArray<T> : IEnumerable<T>
{
private readonly T[] _array;
public MyArray(T[] items) => _array = items;
public MyArray(IEnumerable<T> items) : this(items.ToArray()) { }
public MyArray(ReadOnlySpan<T> items) : this(items.ToArray()) { }
public IEnumerator<T> GetEnumerator() => _array.AsEnumerable().GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => _array.GetEnumerator();
public MyArray<T> Add(T item) => new(_array.Append(item));
}
class MyArray
{
public static MyArray<T> Create<T>(ReadOnlySpan<T> items) => new(items);
}
// natural type 何にすべき?
var array = [1, 2, 3];
array.Add(4); // この需要はある = List
foreach (var x in [1,2,3,4,5,]) // アロケーションかかってほしくない = Span
{
}
これがあるのでC# 13行き。
List<string> list1 = ["abc", .. sub, .. ["", ""]]; // これ今ダメ。natural type 決まらない
List<string> list2 = ["abc", .. sub, .. ((string[])["", ""])]; // キャストちょいめんどい
using System.Collections;
// List<T> が実装しているインターフェイスなら通る。
// 全部実態は new List<T>();
IEnumerable<string> list = ["abc", "ABC"];
IList<string> l1 = [];
ICollection<string> l2 = [];
IEnumerable<string> l3 = [];
IReadOnlyList<string> s4 = [];
IReadOnlyCollection<string> s5 = [];
// List<T> が実装していないインターフェイスは通らない。
IReadOnlySet<string> s6 = [];
// non-generic 不可。
IList l7 = [];
// 現状(17.7p5時点) new string[]
// 最終的には InlineArray になる予定
ReadOnlySpan<string> x = ["a", "b"];
// コレクション初期化子が使えるものなら何でも行ける。
// ただし、Comparer 指定の手段なくなる。
HashSet<string> x = ["a", "b"];
// コレクション式は target-typed。
// これは右辺の時点で object[]。
object[] objList = ["a", "b"];
using System.Collections.Immutable;
// 現状(17.7p5時点)、昔ながらにコレクション初期化子が呼ばれる。
// default(ImmutableArray<string>).Add が呼ばれてぬるぽ。
ImmutableArray<string> objList = ["a", "b"];
// ↓
// 近々(おそらく .NET 8 Preview 7? RC 1?)で、
// [CollectionBuilder(typeof(ImmutableArray), nameof(ImmutableArray.Create))] が付く
// そうすると、
// ImmutableArray.Create("a", "b") が呼ばれる。
// ※コレクション式だけ
// .NET 8 GA しても、↓はダメ。ぬるぽ。
ImmutableArray<string> objList = new() { "a", "b" };
// 配列に関しては {} と [] 同じ。
int[] a1 = { 1, 2, 3 };
int[] a2 = [ 1, 2, 3 ];
List<int> l1 = { 1, 2, 3 }; // ダメ
List<int> l2 = [1, 2, 3]; // OK
var x1 = new X
{
A = { 1 }, // var x1 = new(); x1.A.Add(1); 扱い(ぬるぽる)。
// こっちは init なくても平気。
B = new() { 1 }, // アロケーション2重にかかるのいや
B = { 1 }, // なので、B みたいなケースではこっちの方がいいはず。
};
var x2 = new X
{
A = [ 1 ], // x1.A = new() { 1 } 扱い。大丈夫。
};
class X
{
public List<int> A { get; init; }
public List<int> B { get; init; } = new();
}
IList<int> l1 = [1, 2, 3]; // List<T> になっちゃう
IList<int> l2 = (int[])[1, 2, 3]; // まあ、キャストすれば?(ちゃんと int[] に)
「不要キャスト」リファクタリングが働いちゃってる。 バグ報告案件。
IList<int> l1 = [1, 2, 3]; // List<T> になっちゃう
IList<int> l2 = (int[])[1, 2, 3]; // まあ、キャストすれば?(ちゃんと int[] に)
byte[] x = new byte[0];
// ↓ 今、これにリファクタリングされる。
byte[] x = Array.Empty<byte>();
// ↓ 次、これに変換するリファクタリング入れるみたい。作業中。
byte[] x = [];
Sum([1, 2, 3]);
static int Sum(IEnumerable<int>? items)
{
// 現状(17.7p5時点)、 [] は new List<int>() になっちゃうんで、アロケーションかかる。
// 将来の最適化どうだったかちょっと忘れた。
var sum = 0;
foreach (var item in items ?? []) sum += item;
return sum;
}
Sum([1, 2, 3]);
static int Sum(IEnumerable<int>? items)
{
var sum = 0;
// foreach? (var item in items) // これで if (items != null) 判定入れてほしいという話もある
// 今、↓これでいいじゃん?って空気になりがち。
foreach (var item in items ?? []) sum += item;
return sum;
}
こんなアナウンスブログもなければ、リリースノートもバグ修正数行だけのリリースで新機能が追加されてるとか思わないじゃん?
↓みたいなコードは通るように。
とはいえなんか中途半端な状態。 たぶん .NET 8 RC 1 の頃にはもうちょっとまともになりそうなものの… 一応現状報告な配信を1回やろうかという感じに。