Closed ufcpp closed 4 months ago
var array = new int[] { 1, 2, 3 };
C.M(array); // Calls the array overload
C.M([1, 2, 3]); // Calls the span overload
array.Enumerate(); // IE だと拡張メソッド呼べるのに
array.Extension(); // Span だと拡張メソッド呼べない
static class C
{
public static void M(int[] _) { }
public static void M(ReadOnlySpan<int> _) { }
public static void Extension(this ReadOnlySpan<int> _) { }
public static void Enumerate(this IEnumerable<int> _) { }
}
using (new C()) { }
using (new S()) { }
using (new RS()) { } // OK
static async ValueTask T()
{
// 余談
await using (new C()) { } // 後入りの await using はインターフェイス不要
}
class C : IDisposable // クラスの場合は必須
{
public void Dispose() { }
public ValueTask DisposeAsync() => default;
}
struct S : IDisposable // 普通の構造体の場合は必須
{
public void Dispose() { }
}
ref struct RS // : IDisposable ← ref struct は無理
{
public void Dispose() { }
}
M<RS>();
static void M<T>(T x)
where T : IMyInterface, allows ref struct
{
x.M();
object obj = x; // boxing。ダメ!絶対!
IMyInterface local = x; // これも box。ダメ。
}
interface IMyInterface
{
void M();
}
ref struct RS : IMyInterface
{
public void M()
{
throw new NotImplementedException();
}
}
1.M(); // C2 と C3 で不明瞭かも
(Span<int>[1]).M(); // 許される?
static class C2
{
public static void M<T>(this T _) where T : struct { }
}
static class C3
{
public static void M<T>(this T _) where T : struct, allows ref struct { }
}
C.M<int>(); // T? は int?
C.M<int?>(); // T? は int??… あっ… ダメ…
// where T がなかったとして
C.M<string?>(); // T? は string?? じゃなくて string?。これはこれで謎
// 他の言語だと Optional<Optional<T>> 認めてたりするのでだいぶ事情が違う。
static class C
{
public static T? M<T>()
where T : struct
=> null;
public static T? M<T>() // 代わりに T? と掛けちゃダメという制限あってもいい
where T : struct, allows nullable // これほしい
=> null;
}
public static void M<T>()
where T : struct
// ↓こんなの挟まってたら嫌だし…
//where T1 : class
//where T2 : class
//where T3 : class
//where T4 : class
//where T5 : class
//where T6 : class
//where T7 : class
//where T8 : class
// 初期案。2行に分けたくなくて没。
allows T : ref struct
{ }
// パラメーターであるのなら
var len = args.Length; // OK
var name = nameof(args); // OK
class args { } // OK (パラメーター名での shadowing OK)
class C
{
public void M(args args) { } // shadowing の例。
}
// まあ、こいつは Program.Main から自動変換したとき、
// args がパラメーターのままの方が都合がいい。
internal class Program
{
private static void Main(string[] hoge) // args をリネーム
{
// Covnert to top-level statements がそもそも出てこなくなった
}
}
class C
{
public string X
{
get => "";
set
{
// C# 13 で、field だけキーワードにした場合
var n1 = nameof(value);
var n2 = nameof(field); // これだけエラー?きもい…
// もし value がキーワードになったらこれがまずいかも。
if (value is null)
throw new ArgumentNullException(nameof(value));
// これなら平気。
ArgumentNullException.ThrowIfNull(value);
}
}
}
エラーそっちなんかい。
// あいう は、SJIS だと6バイト
// UTF-16 だと6バイト
// UTF-8 だと9バイト
Console.WriteLine("あいう", int.Parse("")); // Parse の位置の interceptor location、文字コードによって変わる
バグ報告案件:
using System.Runtime.CompilerServices;
MyArray x = default;
Span<int> xspan = x;
Span<int> xsplat = [.. xspan];
Console.WriteLine(xspan.Length);
Console.WriteLine(xsplat.Length);
Span<int> maybeBug = [.. x];
Console.WriteLine(maybeBug.Length); // 0
[InlineArray(4)]
struct MyArray
{
private int _value;
}
↑のバグ報告案件は roslyn 70708 で既知だった。 「ニッチシナリオだから優先度低め」扱い受けてる。 フィードバック次第で考えるって。
配信 URL: https://www.youtube.com/watch?v=8Vls-qrx-F8
https://github.com/ufcpp-live/UfcppLiveAgenda/issues/85 を取り上げる感じで C# 13 (or later) 候補話を。
半分くらいはいきたい。