Note
ãã®ããŒãžã«ã¢ã¯ã»ã¹ããã«ã¯ãæ¿èªãå¿ èŠã§ãã ãµã€ã³ã€ã³ãŸãã¯ãã£ã¬ã¯ããªã®å€æŽã詊ãããšãã§ããŸãã
ãã®ããŒãžã«ã¢ã¯ã»ã¹ããã«ã¯ãæ¿èªãå¿ èŠã§ãã ãã£ã¬ã¯ããªã®å€æŽã詊ãããšãã§ããŸãã
泚
ãã®èšäºã¯æ©èœä»æ§ã§ãã 仿§ã¯ãæ©èœã®èšèšããã¥ã¡ã³ããšããŠæ©èœããŸãã ããã«ã¯ãææ¡ããã仿§ã®å€æŽãšãæ©èœã®èšèšãšéçºæã«å¿ èŠãªæ å ±ãå«ãŸããŸãã ãããã®èšäºã¯ãææ¡ããã仿§ã®å€æŽãæçµæ±ºå®ãããçŸåšã® ECMA 仿§ã«çµã¿èŸŒãŸãããŸã§å ¬éãããŸãã
æ©èœã®ä»æ§ãšå®æããå®è£ ã®éã«ã¯ãããã€ãã®éããããå¯èœæ§ããããŸãã ãããã®éãã¯ãé¢é£ãã èšèªèšèšäŒè° (LDM) ããŒãã§ãã£ããã£ãããŸãã
æ©èœä»æ§ã C# èšèªæšæºã«å°å ¥ããããã»ã¹ã®è©³çްã«ã€ããŠã¯ã仿§ã«é¢ããèšäºãåç §ããŠãã ããã
ãã£ã³ããªã³å·: https://github.com/dotnet/csharplang/issues/8697
宣èš
æ§æ
class_body
: '{' class_member_declaration* '}' ';'?
| ';'
;
class_member_declaration
: constant_declaration
| field_declaration
| method_declaration
| property_declaration
| event_declaration
| indexer_declaration
| operator_declaration
| constructor_declaration
| finalizer_declaration
| static_constructor_declaration
| type_declaration
| extension_declaration // add
;
extension_declaration // add
: 'extension' type_parameter_list? '(' receiver_parameter ')' type_parameter_constraints_clause* extension_body
;
extension_body // add
: '{' extension_member_declaration* '}' ';'?
;
extension_member_declaration // add
: method_declaration
| property_declaration
| operator_declaration
;
receiver_parameter // add
: attributes? parameter_modifiers? type identifier?
;
æ¡åŒµå®£èšã¯ãéãžã§ããªãã¯ã§å
¥ãåã«ãªã£ãŠããªãéçã¯ã©ã¹ã§ã®ã¿å®£èšããå¿
èŠããããŸãã
extensionãšããååãä»ããåã®ãšã©ãŒã§ãã
ã¹ã³ãŒãã³ã°èŠå
æ¡åŒµå®£èšã®åãã©ã¡ãŒã¿ãŒãšã¬ã·ãŒã㌠ãã©ã¡ãŒã¿ãŒã¯ãæ¡åŒµå®£èšã®æ¬äœå
ã®ã¹ã³ãŒãå
ã«ãããŸãã
nameofåŒå
ãé€ããéçã¡ã³ããŒå
ããã¬ã·ãŒã㌠ãã©ã¡ãŒã¿ãŒãåç
§ããã®ã¯ãšã©ãŒã§ãã æ¡åŒµå®£èšã®åãã©ã¡ãŒã¿ãŒãŸãã¯ã¬ã·ãŒã㌠ãã©ã¡ãŒã¿ãŒãšåãååãæã€åãã©ã¡ãŒã¿ãŒãŸãã¯ãã©ã¡ãŒã¿ãŒ (ããã³ã¡ã³ããŒæ¬äœå
ã®ããŒã«ã«å€æ°ãšããŒã«ã«é¢æ°) ã宣èšãããšããšã©ãŒã«ãªããŸãã
public static class E
{
extension<T>(T[] ts)
{
public bool M1(T t) => ts.Contains(t); // `T` and `ts` are in scope
public static bool M2(T t) => ts.Contains(t); // Error: Cannot refer to `ts` from static context
public void M3(int T, string ts) { } // Error: Cannot reuse names `T` and `ts`
public void M4<T, ts>(string s) { } // Error: Cannot reuse names `T` and `ts`
}
}
ã¡ã³ããŒèªäœããå²ãæ¡åŒµå®£èšã®åãã©ã¡ãŒã¿ãŒãŸãã¯ã¬ã·ãŒã㌠ãã©ã¡ãŒã¿ãŒãšåãååãæã€ããšã¯ãšã©ãŒã§ã¯ãããŸããã ã¡ã³ããŒåã¯ãæ¡åŒµå®£èšå ããåçŽãªååæ€çŽ¢ã«çŽæ¥èŠã€ãããŸããããããã£ãŠãlookup ã¯ã¡ã³ããŒã§ã¯ãªãããã®ååã®åãã©ã¡ãŒã¿ãŒãŸãã¯ã¬ã·ãŒã㌠ãã©ã¡ãŒã¿ãŒãæ€çŽ¢ããŸãã
ã¡ã³ããŒã¯ãå€åŽã®éçã¯ã©ã¹ã§çŽæ¥å®£èšãããŠããéçã¡ãœãããçã¿åºããåçŽãªååæ€çŽ¢ã䜿çšããŠèŠã€ããããšãã§ããŸãããã ããåãååã®æ¡åŒµå®£èšåãã©ã¡ãŒã¿ãŒãŸãã¯ã¬ã·ãŒã㌠ãã©ã¡ãŒã¿ãŒãæåã«èŠã€ãããŸãã
public static class E
{
extension<T>(T[] ts)
{
public void T() { M(ts); } // Generated static method M<T>(T[]) is found
public void M() { T(ts); } // Error: T is a type parameter
}
}
æ¡åŒµã³ã³ãããŒãšããŠã®éçã¯ã©ã¹
æ¡åŒµæ©èœã¯ãçŸåšã®æ¡åŒµã¡ãœãããšåæ§ã«ãæäžäœã¬ãã«ã®éãžã§ããªãã¯éçã¯ã©ã¹å ã§å®£èšãããŠãããããåŸæ¥ã®æ¡åŒµã¡ãœãããšéæ¡åŒµéçã¡ã³ããŒãšå ±åã§ããŸãã
public static class Enumerable
{
// New extension declaration
extension(IEnumerable source) { ... }
// Classic extension method
public static IEnumerable<TResult> Cast<TResult>(this IEnumerable source) { ... }
// Non-extension member
public static IEnumerable<int> Range(int start, int count) { ... }
}
æ¡åŒµå®£èš
æ¡åŒµå®£èšã¯å¿åã§ãããé¢é£ä»ããããŠããåãã©ã¡ãŒã¿ãŒãšå¶çŽã«ç¶ããŠæ¡åŒµã¡ã³ããŒå®£èšã®ã»ããã åãåã仿§ ãæäŸããŸãã ã¬ã·ãŒããŒã®æå®ã¯ããã©ã¡ãŒã¿ãŒã®åœ¢åŒã§æå®ããããšããéçæ¡åŒµã¡ã³ããŒã®ã¿ã宣èšãããŠããå Žåã¯åã«ããããšãã§ããŸãã
public static class Enumerable
{
extension(IEnumerable source) // extension members for IEnumerable
{
public bool IsEmpty { get { ... } }
}
extension<TSource>(IEnumerable<TSource> source) // extension members for IEnumerable<TSource>
{
public IEnumerable<T> Where(Func<TSource, bool> predicate) { ... }
public IEnumerable<TResult> Select<TResult>(Func<TSource, TResult> selector) { ... }
}
extension<TElement>(IEnumerable<TElement>) // static extension members for IEnumerable<TElement>
where TElement : INumber<TElement>
{
public static IEnumerable<TElement> operator +(IEnumerable<TElement> first, IEnumerable<TElement> second) { ... }
}
}
ã¬ã·ãŒããŒä»æ§ã®å㯠ã¬ã·ãŒããŒå ãšåŒã°ãããã©ã¡ãŒã¿ãŒå (ååšããå Žå) 㯠ã¬ã·ãŒã㌠ãã©ã¡ãŒã¿ãŒãšåŒã°ããŸãã
ã¬ã·ãŒã㌠ãã©ã¡ãŒã¿ãŒã«ååãä»ããããŠããå Žåãã¬ã·ãŒããŒåã¯éçã«ã§ããªãå¯èœæ§ããããŸãã
<c0 originalTag="ept" originalId="1">ã¬ã·ãŒã㌠ãã©ã¡ãŒã¿ãŒ</c0>ã¯ãååãæå®ãããŠããªãå Žåã¯ä¿®é£ŸåãæãŠãŸããããŸãããã以å€ã®å Žåã¯ã以äžã«ç€ºã refness 修食åãš <c1 originalTag="ph" originalId="1" /> ã®ã¿ã䜿çšã§ããŸãã
ã¬ã·ãŒã㌠ãã©ã¡ãŒã¿ãŒã«ã¯ãåŸæ¥ã®æ¡åŒµã¡ãœããã®æåã®ãã©ã¡ãŒã¿ãŒãšåãå¶éããããŸãã
[EnumeratorCancellation]屿§ã¯ãã¬ã·ãŒã㌠ãã©ã¡ãŒã¿ãŒã«æå®ãããŠããå Žåã¯ç¡èŠãããŸãã
æ¡åŒµã¡ã³ããŒ
æ¡åŒµã¡ã³ããŒå®£èšã¯ã察å¿ããã€ã³ã¹ã¿ã³ã¹ããã³ã¯ã©ã¹ããã³æ§é äœå®£èšã®éçã¡ã³ããŒãšæ§æçã«ã¯åãã§ã (ã³ã³ã¹ãã©ã¯ã¿ãŒãé€ã)ã ã€ã³ã¹ã¿ã³ã¹ ã¡ã³ããŒã¯ãã¬ã·ãŒã㌠ãã©ã¡ãŒã¿ãŒåãæã€ã¬ã·ãŒããŒãåç §ããŸãã
public static class Enumerable
{
extension(IEnumerable source)
{
// 'source' refers to receiver
public bool IsEmpty => !source.GetEnumerator().MoveNext();
}
}
å€åŽã®æ¡åŒµå®£èšã§ã¬ã·ãŒã㌠ãã©ã¡ãŒã¿ãŒãæå®ãããŠããªãå Žåãã€ã³ã¹ã¿ã³ã¹æ¡åŒµã¡ã³ããŒãæå®ãããšãšã©ãŒã«ãªããŸãã
public static class Enumerable
{
extension(IEnumerable) // No parameter name
{
public bool IsEmpty => true; // Error: instance extension member not allowed
}
}
æ¡åŒµæ©èœå®£èšã®ã¡ã³ããŒã«å¯ŸããŠã abstractã virtualã overrideã newã sealedã partialãããã³ protected (ããã³é¢é£ããã¢ã¯ã»ã·ããªãã£ä¿®é£Ÿå) ã«å¯ŸããŠã次ã®ä¿®é£Ÿåãæå®ãããšãšã©ãŒã«ãªããŸãã
æ¡åŒµå®£èšã®ã¡ã³ããŒã« readonly 修食åãæå®ãããšãšã©ãŒã«ãªããŸãã
æ¡åŒµå®£èšã®ããããã£ã«ã¯ã init ã¢ã¯ã»ãµãŒããªãå¯èœæ§ããããŸãã
ã¬ã·ãŒã㌠ãã©ã¡ãŒã¿ãŒã«ååãä»ããŠããªãå Žåãã€ã³ã¹ã¿ã³ã¹ ã¡ã³ããŒã¯èš±å¯ãããŸããã
ãã¹ãŠã®ã¡ã³ããŒã¯ãéçãªå€åŽã®ã¯ã©ã¹ã®ååãšæ¡åŒµåã®åå (ããå Žå) ãšã¯ç°ãªãååãæã€å¿ èŠããããŸãã
æ¡åŒµã¡ã³ããŒã [ModuleInitializer] 屿§ã§è£
食ãããšãšã©ãŒã«ãªããŸãã
ã¬ããã¹
æ¢å®ã§ã¯ãã¬ã·ãŒããŒã¯ããã®ä»ãã©ã¡ãŒã¿ãŒãšåæ§ã«ãå€ã«ãã£ãŠãã€ã³ã¹ã¿ã³ã¹æ¡åŒµã¡ã³ããŒã«æž¡ãããŸãã
ãã ãããã©ã¡ãŒã¿ãŒåœ¢åŒã®æ¡åŒµå®£èšã¬ã·ãŒããŒã¯ãã¬ã·ãŒããŒã®åãå€åã§ããããšãããã£ãŠããéããrefãref readonlyãããã³ in ãæå®ã§ããŸãã
NULL 蚱容å€ãšå±æ§
ã¬ã·ãŒããŒåã¯ãnull 蚱容åç §åã«ããããšãã§ãããããå«ããããšãã§ããŸãããŸããã©ã¡ãŒã¿ãŒåœ¢åŒã®ã¬ã·ãŒããŒæå®ã¯ã屿§ãæå®ã§ããŸããã¿
public static class NullableExtensions
{
extension(string? text)
{
public string AsNotNull => text is null ? "" : text;
}
extension([NotNullWhen(false)] string? text)
{
public bool IsNullOrEmpty => text is null or [];
}
extension<T> ([NotNull] T t) where T : class?
{
public void ThrowIfNull() => ArgumentNullException.ThrowIfNull(t);
}
}
åŸæ¥ã®æ¡åŒµã¡ãœãããšã®äºææ§
ã€ã³ã¹ã¿ã³ã¹æ¡åŒµã¡ãœããã¯ãåŸæ¥ã®æ¡åŒµã¡ãœããã«ãã£ãŠçæããããã®ãšäžèŽããææç©ãçæããŸãã
å ·äœçã«ã¯ãçæãããéçã¡ãœããã¯ã宣èšãããæ¡åŒµã¡ãœããã®å±æ§ã修食åãååããã³ãæ¡åŒµå®£èšãšã¡ãœãã宣èšãããã®é çªã§ãé£çµãããåãã©ã¡ãŒã¿ãŒ ãªã¹ãããã©ã¡ãŒã¿ãŒ ãªã¹ããå¶çŽãªã¹ããä¿æããŸãã
public static class Enumerable
{
extension<TSource>(IEnumerable<TSource> source) // Generate compatible extension methods
{
public IEnumerable<TSource> Where(Func<TSource, bool> predicate) { ... }
public IEnumerable<TSource> Select<TResult>(Func<TSource, TResult> selector) { ... }
}
}
Generates:
[Extension]
public static class Enumerable
{
[Extension]
public static IEnumerable<TSource> Where<TSource>(IEnumerable<TSource> source, Func<TSource, bool> predicate) { ... }
[Extension]
public static IEnumerable<TSource> Select<TSource, TResult>(IEnumerable<TSource> source, Func<TSource, TResult> selector) { ... }
}
ãªãã¬ãŒã¿ãŒ
æ¡åŒµæŒç®åã«ã¯æç€ºçãªãªãã©ã³ãåããããŸãããæ¡åŒµå®£èšå ã§å®£èšããå¿ èŠããããŸãã
public static class Enumerable
{
extension<TElement>(IEnumerable<TElement>) where TElement : INumber<TElement>
{
public static IEnumerable<TElement> operator *(IEnumerable<TElement> vector, TElement scalar) { ... }
public static IEnumerable<TElement> operator *(TElement scalar, IEnumerable<TElement> vector) { ... }
}
}
ããã«ãããåãã©ã¡ãŒã¿ãŒã宣èšããã³æšè«ã§ãããã®ãªãã©ã³ãåã® 1 ã€å ã§éåžžã®ãŠãŒã¶ãŒå®çŸ©æŒç®åã宣èšããæ¹æ³ã«äŒŒãŠããŸãã
Checking
æšè«å¯èœæ§: ã¡ãœãã以å€ã®æ¡åŒµã¡ã³ããŒããšã«ãæ¡åŒµãããã¯ã®ãã¹ãŠã®åãã©ã¡ãŒã¿ãŒããæ¡åŒµæ©èœãšã¡ã³ããŒã®ãã©ã¡ãŒã¿ãŒã®çµã¿åããã§äœ¿çšããå¿ èŠããããŸãã
ç¬ç¹ïŒ ç¹å®ã®å€åŽã®éçã¯ã©ã¹å ã§ã¯ãåãã¬ã·ãŒããŒå (æç倿ããã³åãã©ã¡ãŒã¿ãŒåã®çœ®æãèæ ®) ãæã€æ¡åŒµã¡ã³ããŒå®£èšã®ã»ããã¯ãã¯ã©ã¹ãŸãã¯æ§é äœå®£èšå ã®ã¡ã³ããŒã«äŒŒãåäžã®å®£èšç©ºéãšããŠæ±ããã äžææ§ã«é¢ããåãèŠåã«åŸããŸãã
public static class MyExtensions
{
extension<T1>(IEnumerable<int>) // Error! T1 not inferrable
{
...
}
extension<T2>(IEnumerable<T2>)
{
public bool IsEmpty { get ... }
}
extension<T3>(IEnumerable<T3>?)
{
public bool IsEmpty { get ... } // Error! Duplicate declaration
}
}
ãã®äžææ§ã«ãŒã«ã®é©çšã«ã¯ãåãéçã¯ã©ã¹å
ã®åŸæ¥ã®æ¡åŒµã¡ãœãããå«ãŸããŸãã
æ¡åŒµå®£èšå
ã®ã¡ãœãããšæ¯èŒããããã«ãthis ãã©ã¡ãŒã¿ãŒã¯ãã®ã¬ã·ãŒããŒåã«èšèŒãããŠããä»»æã®åãã©ã¡ãŒã¿ãŒãšå
±ã«ãã¬ã·ãŒããŒæå®ãšããŠæ±ãããæ®ãã®åãã©ã¡ãŒã¿ãŒãšã¡ãœãã ãã©ã¡ãŒã¿ãŒã¯ãã¡ãœãã ã·ã°ããã£ã«äœ¿çšãããŸãã
public static class Enumerable
{
public static IEnumerable<TResult> Cast<TResult>(this IEnumerable source) { ... }
extension(IEnumerable source)
{
IEnumerable<TResult> Cast<TResult>() { ... } // Error! Duplicate declaration
}
}
åŸé課é
æ¡åŒµã¡ã³ããŒã®æ€çŽ¢ã詊è¡ããããšãusing ã€ã³ããŒããããŠããéçã¯ã©ã¹å
ã®ãã¹ãŠã®æ¡åŒµå®£èšããã¬ã·ãŒããŒåã«é¢ä¿ãªãããã®ã¡ã³ããŒãåè£ãšããŠæäŸããŸãã ãœãªã¥ãŒã·ã§ã³ã®äžç°ãšããŠã®ã¿ãäºææ§ã®ãªãã¬ã·ãŒããŒåã®åè£ãç Žæ£ãããŸãã
åŒæ°ã®å (å®éã®ã¬ã·ãŒããŒãå«ã) ãšä»»æã®åãã©ã¡ãŒã¿ãŒ (æ¡åŒµå®£èšãšæ¡åŒµã¡ã³ããŒå®£èšã®åãçµã¿åããããã®) ã®éã§ãå®å
šãªãžã§ããªãã¯åæšè«ã詊è¡ãããŸãã
æç€ºçãªååŒæ°ãæå®ãããšãæ¡åŒµå®£èšãšæ¡åŒµã¡ã³ããŒå®£èšã®åãã©ã¡ãŒã¿ãŒã«çœ®ãæããããã«äœ¿çšãããŸãã
string[] strings = ...;
var query = strings.Select(s => s.Length); // extension invocation
var query2 = strings.Select<string, int>(s => s.Length); // ... with explicit full set of type arguments
var query3 = Enumerable.Select(strings, s => s.Length); // static method invocation
var query4 = Enumerable.Where<string, int>(strings, s => s.Length); // ... with explicit full set of type arguments
public static class Enumerable
{
extension<TSource>(IEnumerable<TSource> source)
{
public IEnumerable<TResult> Select<TResult>(Func<T, TResult> predicate) { ... }
}
}
åŸæ¥ã®æ¡åŒµã¡ãœãããšåæ§ã«ãåºåãããå®è£
ã¡ãœãããéçã«åŒã³åºãããšãã§ããŸãã
ããã«ãããã³ã³ãã€ã©ã¯ãåãååãšã¢ãªãã£ãæã€æ¡åŒµã¡ã³ããŒéã§ãããŸãããè§£æ¶ã§ããŸãã
object.M(); // ambiguous
E1.M();
new object().M2(); // ambiguous
E1.M2(new object());
_ = _new object().P; // ambiguous
_ = E1.get_P(new object());
static class E1
{
extension(object)
{
public static void M() { }
public void M2() { }
public int P => 42;
}
}
static class E2
{
extension(object)
{
public static void M() { }
public void M2() { }
public int P => 42;
}
}
éçæ¡åŒµã¡ãœããã¯ãã€ã³ã¹ã¿ã³ã¹æ¡åŒµã¡ãœãããšåæ§ã«è§£æ±ºãããŸã (ã¬ã·ãŒããŒåã®è¿œå åŒæ°ãèæ
®ããŸã)ã
æ¡åŒµããããã£ã¯æ¡åŒµã¡ãœãããšåæ§ã«è§£æ±ºããã1 ã€ã®ãã©ã¡ãŒã¿ãŒ (ã¬ã·ãŒã㌠ãã©ã¡ãŒã¿ãŒ) ãš 1 ã€ã®åŒæ° (å®éã®ã¬ã·ãŒããŒå€) ã䜿çšãããŸãã
using static ãã£ã¬ã¯ãã£ã
using_static_directiveã䜿çšãããšãå宣èšã®æ¡åŒµãããã¯ã®ã¡ã³ããŒãæ¡åŒµã¢ã¯ã»ã¹ã§äœ¿çšã§ããããã«ãªããŸãã
using static N.E;
new object().M();
object.M2();
_ = new object().Property;
_ = object.Property2;
C c = null;
_ = c + c;
c += 1;
namespace N
{
static class E
{
extension(object o)
{
public void M() { }
public static void M2() { }
public int Property => 0;
public static int Property2 => 0;
}
extension(C c)
{
public static C operator +(C c1, C c2) => throw null;
public void operator +=(int i) => throw null;
}
}
}
class C { }
以åãšåæ§ã«ãæå®ãããåã®å®£èšã«çŽæ¥å«ãŸããã¢ã¯ã»ã¹å¯èœãªéçã¡ã³ã㌠(æ¡åŒµã¡ãœãããé€ã) ãçŽæ¥åç
§ã§ããŸãã
ã€ãŸããå®è£
ã¡ãœãã (æ¡åŒµã¡ãœãããé€ã) ãéçã¡ãœãããšããŠçŽæ¥äœ¿çšã§ããŸãã
using static E;
M();
System.Console.Write(get_P());
set_P(43);
_ = op_Addition(0, 0);
_ = new object() + new object();
static class E
{
extension(object)
{
public static void M() { }
public static int P { get => 42; set { } }
public static object operator +(object o1, object o2) { return o1; }
}
}
using_static_directiveã¯ãŸã æ¡åŒµã¡ãœãããéçã¡ãœãããšããŠçŽæ¥ã€ã³ããŒãããªããããééçæ¡åŒµã¡ãœããã®å®è£ ã¡ãœãããéçã¡ãœãããšããŠçŽæ¥åŒã³åºãããšã¯ã§ããŸããã
using static E;
M(1); // error: The name 'M' does not exist in the current context
static class E
{
extension(int i)
{
public void M() { }
}
}
OverloadResolutionPriorityAttributeïŒãªãŒããŒããŒã解決åªå é äœå±æ§ïŒ
å€åŽã®éçã¯ã©ã¹å
ã®æ¡åŒµã¡ã³ããŒã¯ãORPA å€ã«åŸã£ãåªå
é äœä»ãã®å¯Ÿè±¡ãšãªããŸãã å€åŽã®éçã¯ã©ã¹ã¯ãORPA èŠåã§èæ
®ããã "å
å«å" ãšèŠãªãããŸãã
æ¡åŒµããããã£ã«ååšãã ORPA 屿§ã¯ãããããã£ã®ã¢ã¯ã»ãµãŒã®å®è£
ã¡ãœããã«ã³ããŒãããããããããã®ã¢ã¯ã»ãµãŒããããŸãããè§£æ¶ããæ§æã䜿çšããå Žåã«åªå
é äœä»ããå°éãããŸãã
å ¥å£ç¹
æ¡åŒµãããã¯ã®ã¡ãœããã¯ããšã³ã㪠ãã€ã³ãåè£ãšããŠé©æ Œã§ã¯ãããŸããïŒã7.1 ã¢ããªã±ãŒã·ã§ã³ã®èµ·åããåç §ïŒã 泚: å®è£ æ¹æ³ã¯ãåŒãç¶ãåè£ã«ãªãå¯èœæ§ããããŸãã
åŒãäžã
æ¡åŒµå®£èšã®äžäœæŠç¥ã¯ãèšèªã¬ãã«ã®æ±ºå®ã§ã¯ãããŸããã ãã ããèšèªã»ãã³ãã£ã¯ã¹ãå®è£ ãã以å€ã«ãç¹å®ã®èŠä»¶ãæºããå¿ èŠããããŸãã
- çæãããåãã¡ã³ããŒãããã³ã¡ã¿ããŒã¿ã®åœ¢åŒã¯ãä»ã®ã³ã³ãã€ã©ã䜿çšããŠçæã§ããããã«ããã¹ãŠã®ã±ãŒã¹ã§æç¢ºã«æå®ããå¿ èŠããããŸãã
- çæãããã¢ãŒãã£ãã¡ã¯ãã¯å®å®ããŠããå¿ èŠããããŸããã€ãŸãã劥åœãªä»åŸã®å€æŽã«ãã£ãŠã以åã®ããŒãžã§ã³ã«å¯ŸããŠã³ã³ãã€ã«ãããã³ã³ã·ã¥ãŒããŒãäžæãããªãããã«ããå¿ èŠããããŸãã
ãããã®èŠä»¶ã¯ãå®è£ ã®é²è¡ã«åãããŠããã«æ¹è¯ãå¿ èŠã§ããã劥åœãªå®è£ ã¢ãããŒããå¯èœã«ããããã«ãã³ãŒã㌠ã±ãŒã¹ã§åŠ¥åããå¿ èŠãããå ŽåããããŸãã
宣èšã®ã¡ã¿ããŒã¿
ç®æš
次ã®èšèšã§ã¯ã次ã®ããšãã§ããŸãã
- æ¡åŒµå®£èšã·ã³ãã«ã®ã©ãŠã³ãããªãããã¡ã¿ããŒã¿ïŒå®å šã¢ã»ã³ããªãšåç §ã¢ã»ã³ããªïŒãéããŠå®è¡ãã
- æ¡åŒµã¡ã³ããŒãžã®å®å®ããåç § (xml ããã¥ã¡ã³ã)
- åºåãããååãããŒã«ã«ã§æ±ºå®ããããšã¯ãEnC ã®åœ¹ã«ç«ã¡ãŸãã
- ãããªã㯠API ã®è¿œè·¡ã
xml ããã¥ã¡ã³ãã®å Žåãæ¡åŒµã¡ã³ããŒã® docID ã¯ã¡ã¿ããŒã¿å
ã®æ¡åŒµã¡ã³ããŒã® docID ã§ãã ããšãã°ã cref="Extension.extension(object).M(int)" ã§äœ¿çšããã docID 㯠M:Extension.<>E__ExtensionGroupingTypeNameForObject.M(System.Int32) ã§ããããã® docID ã¯ãæ¡åŒµãããã¯ã®åã³ã³ãã€ã«ãšé åºä»ãã®éã§å®å®ããŠããŸãã çæ³çã«ã¯ãæ¡åŒµãããã¯ã®å¶çŽã倿Žãããå Žåã«ãå®å®ãããŸãŸã§ãããã¡ã³ããŒã®ç«¶åã«å¯Ÿããèšèªèšèšã«æªåœ±é¿ãåãŒãããšãªãããããå®çŸããèšèšã¯èŠã€ãããŸããã§ããã
EnC ã®å Žåãã©ãã§æŽæ°ãããæ¡åŒµã¡ã³ããŒãã¡ã¿ããŒã¿ã«åºåãããŠãããããããŒã«ã«ã§ïŒå€æŽãããæ¡åŒµã¡ã³ããŒã確èªããã ãã§ïŒç¥ãããšãã§ãããšäŸ¿å©ã§ãã
ãããªã㯠API 远跡ã®å Žåãããå®å®ããååã䜿çšãããšããã€ãºã軜æžãããŸãã ãã ããæè¡çã«ã¯ããã®ãããªã·ããªãªã§ã¯æ¡åŒµæ©èœã®ã°ã«ãŒãåã®ååã䜿çšããªãã§ãã ããã æ¡åŒµã¡ã³ã㌠MãèŠããšãæ¡åŒµæ©èœã®ã°ã«ãŒãåã®çš®é¡ã®ååã¯é¢ä¿ãªããéèŠãªã®ã¯ããããå±ããæ¡åŒµãããã¯ã®çœ²åã§ãã ãããªã㯠API 眲åã¯ã Extension.<>E__ExtensionGroupingTypeNameForObject.M(System.Int32) ã§ã¯ãªãã Extension.extension(object).M(int)ãšèŠãªãå¿
èŠããããŸãã èšãæãããšãæ¡åŒµã¡ã³ããŒã¯ã2 ã»ããã®åãã©ã¡ãŒã¿ãŒãš 2 ã»ããã®ãã©ã¡ãŒã¿ãŒãæã€ãã®ãšããŠèŠãªãããŸãã
æŠèŠ
æ¡åŒµãããã¯ã¯ãCLR ã¬ãã«ã®ã·ã°ããã£ã«ãã£ãŠã°ã«ãŒãåãããŸãã å CLR ç䟡æ§ã°ã«ãŒãã¯ãã³ã³ãã³ã ããŒã¹ã®ååãæã€ æ¡åŒµã°ã«ãŒãåã®çš®é¡ ãšããŠåºåãããŸãã ãã®åŸãCLR ç䟡ã°ã«ãŒãå ã®æ¡åŒµãããã¯ã¯ãC# ã®ç䟡æ§ã«ãã£ãŠãµãã°ã«ãŒãåãããŸãã å C# ç䟡ã°ã«ãŒãã¯ã察å¿ããæ¡åŒµã°ã«ãŒãåã«ãã¹ãããããå 容ã«åºã¥ããååãæã€æ¡åŒµããŒã«ãŒåãšããŠåºåãããŸãã æ¡åŒµããŒã«ãŒã®çš®é¡ã«ã¯ãæ¡åŒµãã©ã¡ãŒã¿ãŒããšã³ã³ãŒããã 1 ã€ã® æ¡åŒµããŒã«ãŒ ã¡ãœãã ãå«ãŸããŠããŸãã æ¡åŒµããŒã«ãŒã®çš®é¡ãå«ãæ¡åŒµããŒã«ãŒ ã¡ãœããã¯ãå®å šãªå¿ 宿§ãæã€æ¡åŒµãããã¯ã®ã·ã°ããã£ããšã³ã³ãŒãããŸãã åæ¡åŒµã¡ã³ããŒã®å®£èšã¯ãé©åãªæ¡åŒµã°ã«ãŒãååã§åºåããã屿§ãä»ããŠãã®ååã«ãã£ãŠæ¡åŒµããŒã«ãŒåãåç §ãã倿Žãããã·ã°ããã£ãæã€æäžäœã®éç å®è£ ã¡ãœãã ã䌎ããŸãã
ã¡ã¿ããŒã¿ ãšã³ã³ãŒãã®ã¹ããŒãåãããæŠèŠã次ã«ç€ºããŸãã
[Extension]
static class EnclosingStaticClass
{
[Extension]
public sealed class ExtensionGroupingType1 // has type parameters with minimal constraints sufficient to keep extension member declarations below valid
{
public static class ExtensionMarkerType1 // has re-declared type parameters with full fidelity of C# constraints
{
public static void <Extension>$(... extension parameter ...) // extension marker method
}
... ExtensionMarkerType2, etc ...
... extension members for ExtensionGroupingType1, each points to its corresponding extension marker type ...
}
... ExtensionGroupingType2, etc ...
... implementation methods ...
}
å
å
ãããéçã¯ã©ã¹ã¯ã[Extension] 屿§ã§åºåãããŸãã
CLR ã¬ãã«ã®ã·ã°ããã£ãš C#ã¬ãã«ã®çœ²å
æ¡åŒµãããã¯ã® CLR ã¬ãã«ã®ã·ã°ããã£ã®çµæã¯æ¬¡ã®ãšããã§ãã
- åãã©ã¡ãŒã¿ãŒåã
T0ãT1ãªã©ã«æ£èŠåãã - 屿§ã®åé€
- ãã©ã¡ãŒã¿ãŒåã®æ¶å»
- ãã©ã¡ãŒã¿ãŒä¿®é£Ÿå (
refãinãscopedã... ãªã©) ãæ¶å»ãã - ã¿ãã«åã®æ¶å»
- NULL å€èš±å®¹æ³šéã®æ¶å»
-
notnullå¶çŽã®æ¶å»
泚: ãã®ä»ã®å¶çŽ ( new()ã structã classã allows ref structã unmanagedãåã®å¶çŽãªã©) ã¯ä¿æãããŸãã
æ¡åŒµæ©èœã®ã°ã«ãŒãåã®çš®é¡
æ¡åŒµã°ã«ãŒãåã®çš®é¡ã¯ãåã CLR ã¬ãã«ã®ã·ã°ããã£ãæã€ãœãŒã¹å ã®æ¡åŒµãããã¯ã®åã»ããã®ã¡ã¿ããŒã¿ã«åºåãããŸãã
- ãã®ååã¯çºè©±ã§ããªããã®ã§ãããCLR ã¬ãã«ã®ã·ã°ããã£ã®å 容ã«åºã¥ããŠæ±ºãŸããŸãã 詳ããã¯ã以äžãã芧ãã ããã
- ãã®åãã©ã¡ãŒã¿ãŒã«ã¯æ£èŠåãããåå (
T0ãT1ã...) ãããã屿§ã¯ãããŸããã - ããã¯ãããªãã¯ã§ãããå°å°ãããŠããŸãã
-
specialnameãã©ã°ãš[Extension]屿§ã§ããŒã¯ãããŸãã
æ¡åŒµæ©èœã®ã°ã«ãŒãåã®çš®é¡ã®ã³ã³ãã³ã ããŒã¹ã®ååã¯ãCLR ã¬ãã«ã®ã·ã°ããã£ã«åºã¥ããŠãããæ¬¡ã®ãã®ãå«ãŸããŸãã
- æ¡åŒµãã©ã¡ãŒã¿ãŒã®åã®å®å
šä¿®é£Ÿ CLR åã
- åç
§ãããåãã©ã¡ãŒã¿ãŒåã¯ã
T0ãT1ãªã©ã«æ£èŠåãããŸããå宣èšã«è¡šç€ºãããé åºã«åºã¥ããŠããŸãã - å®å šä¿®é£Ÿåã«ã¯ãå å«ããã¢ã»ã³ããªã¯å«ãŸããŸããã åã¯ã¢ã»ã³ããªéã§ç§»åããã®ãäžè¬çã§ãããxml ããã¥ã¡ã³ãåç §ãå£ãã¹ãã§ã¯ãããŸããã
- åç
§ãããåãã©ã¡ãŒã¿ãŒåã¯ã
- åãã©ã¡ãŒã¿ãŒã®å¶çŽãå«ãŸããŠäžŠã¹æ¿ããããã®ã§ããœãŒã¹ ã³ãŒãã§ããããäžŠã¹æ¿ããŠãååã¯å€æŽãããŸããã å
·äœçã«ã¯ïŒ
- åãã©ã¡ãŒã¿ãŒã®å¶çŽã¯å®£èšé ã«äžèŠ§è¡šç€ºãããŸãã N çªç®ã®åãã©ã¡ãŒã¿ãŒã®å¶çŽã¯ãNth+1 åãã©ã¡ãŒã¿ãŒã®åã«çºçããŸãã
- åå¶çŽã¯ãå®å šãªååãåºæ°ã§æ¯èŒããããšã§äžŠã¹æ¿ããããŸãã
- éåå¶çŽã¯æ±ºå®è«çã«é åºä»ããããåå¶çŽãšã®ãããŸãããç«¶åãåé¿ããããã«åŠçãããŸãã
- ããã«ã¯å±æ§ãå«ãŸããŠããªããããã¿ãã«åãnull å€ã®èš±å®¹ãªã©ãC#-isms ã¯æå³çã«ç¡èŠãããŸãã
泚: ãã®ååã¯ãC#-isms ã®åã³ã³ãã€ã«ãåé åºä»ããããã³å€æŽ (ã€ãŸããCLR ã¬ãã«ã®ã·ã°ããã£ã«åœ±é¿ãäžããªã) ã«ããã£ãŠå®å®ããç¶æ ãç¶æããããšãä¿èšŒãããŠããŸãã
æ¡åŒµããŒã«ãŒã®çš®é¡
ããŒã«ãŒåã¯ãæ¡åŒµãããã¯ã® C# ãã¥ãŒã®å®å šãªå¿ 宿§ãåŸãããã«ããã®å å«ã°ã«ãŒãåå (æ¡åŒµã°ã«ãŒãåå) ã®åãã©ã¡ãŒã¿ãŒãå宣èšããŸãã
æ¡åŒµããŒã«ãŒã®çš®é¡ã¯ãåã C# ã¬ãã«ã®ã·ã°ããã£ãæã€ãœãŒã¹å ã®æ¡åŒµãããã¯ã®åã»ããã®ã¡ã¿ããŒã¿ã«åºåãããŸãã
- ãã®ååã¯èšãã«èšããªããã®ã§ãããæ¡åŒµãããã¯ã® C# ã¬ãã«ã®ã·ã°ããã£ã®å 容ã«åºã¥ããŠæ±ºå®ãããŸãã 詳ããã¯ã以äžãã芧ãã ããã
- ãœãŒã¹ã§å®£èšãããŠããã°ã«ãŒãåå (ååã屿§ãå«ã) ã«å¯ŸããŠåãã©ã¡ãŒã¿ãŒãå宣èšããŸãã
- ãããªãã¯ã§éçã§ãã
-
specialnameãã©ã°ã§ããŒã¯ãããŸãã
æ¡åŒµããŒã«ãŒã®çš®é¡ã®ã³ã³ãã³ã ããŒã¹ã®ååã¯ã次ã«åºã¥ããŠããŸãã
- åãã©ã¡ãŒã¿ãŒã®ååã¯ãæ¡åŒµå®£èšã«è¡šç€ºãããé åºã«å«ãŸããŸã
- åãã©ã¡ãŒã¿ãŒã®å±æ§ãå«ãŸããŠäžŠã¹æ¿ããããã®ã§ããœãŒã¹ ã³ãŒãã§ããããäžŠã¹æ¿ããŠãååã¯å€æŽãããŸããã
- åãã©ã¡ãŒã¿ãŒã®å¶çŽãå«ãŸããŠäžŠã¹æ¿ããããã®ã§ããœãŒã¹ ã³ãŒãã§ããããäžŠã¹æ¿ããŠãååã¯å€æŽãããŸããã
- æ¡åŒµåã®å®å
šä¿®é£Ÿ C# å
- ããã«ã¯ãNull 蚱容泚éãã¿ãã«åãªã©ã®é ç®ãå«ãŸããŸãã
- å®å šä¿®é£Ÿåã«ã¯ãæ ŒçŽãããŠããã¢ã»ã³ããªãå«ãŸããŸããã
- æ¡åŒµãã©ã¡ãŒã¿ãŒã®åå
- 決å®çãªé åºã§ã®æ¡åŒµãã©ã¡ãŒã¿ãŒ (
refãref readonlyãscopedã...) ã®ä¿®é£Ÿå - 決å®çãªé åºã§æ¡åŒµãã©ã¡ãŒã¿ãŒã«é©çšããããã¹ãŠã®å±æ§ã®å®å šä¿®é£Ÿåãšå±æ§åŒæ°
泚: ååã¯ãåã³ã³ãã€ã«ãšåé åºä»ãã®éã§å®å®ããç¶æ
ãç¶æããããšãä¿èšŒãããŸãã
泚: æ¡åŒµããŒã«ãŒã®çš®é¡ãšæ¡åŒµããŒã«ãŒ ã¡ãœããã¯ãåç
§ã¢ã»ã³ããªã®äžéšãšããŠåºåãããŸãã
æ¡åŒµããŒã«ãŒ ã¡ãœãã
ããŒã«ãŒ ã¡ãœããã®ç®çã¯ãæ¡åŒµãããã¯ã®æ¡åŒµãã©ã¡ãŒã¿ãŒããšã³ã³ãŒãããããšã§ãã æ¡åŒµããŒã«ãŒåã®ã¡ã³ããŒã§ãããããæ¡åŒµããŒã«ãŒåã®å宣èšãããåãã©ã¡ãŒã¿ãŒãåç §ã§ããŸãã
åæ¡åŒµããŒã«ãŒã®çš®é¡ã«ã¯ã1 ã€ã®ã¡ãœããã§ããæ¡åŒµããŒã«ãŒ ã¡ãœãããå«ãŸããŠããŸãã
- ããã¯éçãéãžã§ããªãã¯ãvoid ãè¿ãã
<Extension>$ãšåŒã°ããŸãã - ãã® 1 ã€ã®ãã©ã¡ãŒã¿ãŒã«ã¯ãæ¡åŒµãã©ã¡ãŒã¿ãŒã®å±æ§ãåç
§ãåãããã³ååããããŸãã
æ¡åŒµãã©ã¡ãŒã¿ãŒã§ååãæå®ãããŠããªãå Žåããã©ã¡ãŒã¿ãŒåã¯ç©ºã§ãã -
specialnameãã©ã°ã§ããŒã¯ãããŸãã
ããŒã«ãŒ ã¡ãœããã®ã¢ã¯ã»ã·ããªãã£ã¯ã察å¿ãã宣èšãããæ¡åŒµã¡ã³ããŒã®äžã§æãå¶éã®å³ããã¢ã¯ã»ã·ããªãã£ã«ãªããŸãã private ã¯ãäœã宣èšãããŠããªãå Žåã«äœ¿çšãããŸãã
æ¡åŒµã¡ã³ããŒ
ãœãŒã¹ã®æ¡åŒµãããã¯å ã®ã¡ãœãã/ããããã£å®£èšã¯ãã¡ã¿ããŒã¿å ã®æ¡åŒµã°ã«ãŒãååã®ã¡ã³ããŒãšããŠè¡šãããŸãã
- å
ã®ã¡ãœããã®ã·ã°ãã㣠(屿§ãå«ã) ã¯ä¿æãããŸããããã®æ¬æã¯
throw NotImplementedException()ã«çœ®ãæããããŸãã - ããã㯠IL ã§åç §ããªãã§ãã ããã
- ã¡ãœãããããããã£ãããã³ã¢ã¯ã»ãµãŒã¯ããã®ã¡ã³ããŒã®æ¡åŒµãããã¯ã«å¯Ÿå¿ããæ¡åŒµããŒã«ãŒã®çš®é¡ã®ååãåç
§ãã
[ExtensionMarkerName("...")]ã§ããŒã¯ãããŸãã
å®è£ ã¡ãœãã
ãœãŒã¹å ã®æ¡åŒµãããã¯å ã®ã¡ãœãã/ããããã£å®£èšã®ã¡ãœããæ¬äœã¯ãæäžäœã®éçã¯ã©ã¹ã®éçå®è£ ã¡ãœãããšããŠåºåãããŸãã
- å®è£ ã¡ãœããã®ååã¯å ã®ã¡ãœãããšåãã§ãã
- å ã®ã¡ãœããã®åãã©ã¡ãŒã¿ãŒïŒå±æ§ãå«ãïŒã®åã«ãæ¡åŒµãããã¯ããæŽŸçããåãã©ã¡ãŒã¿ãŒã远å ãããŠããŸãã
- å ã®ã¡ãœãããšåãã¢ã¯ã»ã·ããªãã£ãšå±æ§ããããŸãã
- éçã¡ãœãããå®è£ ããå Žåããã©ã¡ãŒã¿ãŒãšæ»ãå€ã®åã¯åãã§ãã
- ã€ã³ã¹ã¿ã³ã¹ ã¡ãœãããå®è£ ããå Žåã¯ãå ã®ã¡ãœããã®ã·ã°ããã£ã®åã«ãã©ã¡ãŒã¿ãŒã远å ãããŸãã ãã®ãã©ã¡ãŒã¿ãŒã®å±æ§ãåç §ãåãããã³ååã¯ãé¢é£ããæ¡åŒµãããã¯ã§å®£èšãããæ¡åŒµãã©ã¡ãŒã¿ãŒããæŽŸçããŸãã
- å®è£ ã¡ãœããã®ãã©ã¡ãŒã¿ãŒã¯ãæ¡åŒµãããã¯ã®åãã©ã¡ãŒã¿ãŒã§ã¯ãªããå®è£ ã¡ãœãããææããåãã©ã¡ãŒã¿ãŒãåç §ããŸãã
- å
ã®ã¡ã³ããŒãã€ã³ã¹ã¿ã³ã¹ã®éåžžã®ã¡ãœããã§ããå Žåãå®è£
ã¡ãœããã¯
[Extension]屿§ã§ããŒã¯ãããŸãã
ExtensionMarkerName 屿§
ExtensionMarkerNameAttribute åã¯ã³ã³ãã€ã©ã§ã®ã¿äœ¿çšããããœãŒã¹ã§ã¯äœ¿çšã§ããŸããã ã³ã³ãã€ã«ã«ãŸã å«ãŸããŠããªãå Žåã«ã¯ãå宣èšã¯ã³ã³ãã€ã©ã«ãã£ãŠåæãããŸãã
namespace System.Runtime.CompilerServices;
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Interface | AttributeTargets.Delegate, Inherited = false)]
public sealed class ExtensionMarkerNameAttribute : Attribute
{
public ExtensionMarkerNameAttribute(string name)
=> Name = name;
public string Name { get; }
}
泚: äžéšã®å±æ§ã¿ãŒã²ããã¯å°æ¥ãžã®åããšããŠèšããããŠããŸãïŒæ¡åŒµå ¥ãååãæ¡åŒµãã£ãŒã«ããæ¡åŒµã€ãã³ãïŒããã ããAttributeTargets.Constructor ã¯æ¡åŒµã³ã³ã¹ãã©ã¯ã¿ãŒãã³ã³ã¹ãã©ã¯ã¿ãŒã§ã¯ãªãããå«ãŸããŠããŸããã
äŸ
泚: ãã®äŸã§ã¯ãèªã¿ãããããããã«ãç°¡ç¥åãããã³ã³ãã³ã ããŒã¹ã®ååã䜿çšããŸãã æ³š: C# ã¯åãã©ã¡ãŒã¿ãŒã®å宣èšã衚ãããšãã§ããªããããã¡ã¿ããŒã¿ã衚ãã³ãŒãã¯æå¹ãª C# ã³ãŒãã§ã¯ãããŸããã
ã¡ã³ããŒãå«ãŸãªãã°ã«ãŒãåã®ããã¿ã瀺ãäŸã次ã«ç€ºããŸãã
class E
{
extension<T>(IEnumerable<T> source)
{
... member in extension<T>(IEnumerable<T> source)
}
extension<U>(ref IEnumerable<U?> p)
{
... member in extension<U>(ref IEnumerable<U?> p)
}
extension<T>(IEnumerable<U> source)
where T : IEquatable<U>
{
... member in extension<T>(IEnumerable<U> source) where T : IEquatable<U>
}
}
ã¯æ¬¡ã®ããã«åºåãããŸãã
[Extension]
class E
{
[Extension, SpecialName]
public sealed class <>E__ContentName_For_IEnumerable_T<T0>
{
[SpecialName]
public static class <>E__ContentName1 // note: re-declares type parameter T0 as T
{
[SpecialName]
public static void <Extension>$(IEnumerable<T> source) { }
}
[SpecialName]
public static class <>E__ContentName2 // note: re-declares type parameter T0 as U
{
[SpecialName]
public static void <Extension>$(ref IEnumerable<U?> p) { }
}
[ExtensionMarkerName("<>E__ContentName1")]
... member in extension<T>(IEnumerable<T> source)
[ExtensionMarkerName("<>E__ContentName2")]
... member in extension<U>(ref IEnumerable<U?> p)
}
[Extension, SpecialName]
public sealed class <>ContentName_For_IEnumerable_T_With_Constraint<T0>
where T0 : IEquatable<T0>
{
[SpecialName]
public static class <>E__ContentName3 // note: re-declares type parameter T0 as U
{
[SpecialName]
public static void <Extension>$(IEnumerable<U> source) { }
}
[ExtensionMarkerName("ContentName3")]
public static bool IsPresent(U value) => throw null!;
}
... implementation methods
}
ã¡ã³ããŒã®åºåæ¹æ³ã瀺ãäŸã次ã«ç€ºããŸãã
static class IEnumerableExtensions
{
extension<T>(IEnumerable<T> source) where T : notnull
{
public void Method() { ... }
internal static int Property { get => ...; set => ...; }
public int Property2 { get => ...; set => ...; }
}
extension(IAsyncEnumerable<int> values)
{
public async Task<int> SumAsync() { ... }
}
public static void Method2() { ... }
}
ã¯æ¬¡ã®ããã«åºåãããŸãã
[Extension]
static class IEnumerableExtensions
{
[Extension, SpecialName]
public sealed class <>E__ContentName_For_IEnumerable_T<T0>
{
// Extension marker type is emitted as a nested type and re-declares its type parameters to include C#-isms
// In this example, the type parameter `T0` is re-declared as `T` with a `notnull` constraint:
// .class <>E__IEnumerableOfT<T>.<>E__ContentName_For_IEnumerable_T_Source
// .typeparam T
// .custom instance void NullableAttribute::.ctor(uint8) = (...)
[SpecialName]
public static class <>E__ContentName_For_IEnumerable_T_Source
{
[SpecialName]
public static <Extension>$(IEnumerable<T> source) => throw null;
}
[ExtensionMarkerName("<>E__ContentName_For_IEnumerable_T_Source")]
public void Method() => throw null;
[ExtensionMarkerName("<>E__ContentName_For_IEnumerable_T_Source")]
internal static int Property
{
[ExtensionMarkerName("<>E__ContentName_For_IEnumerable_T_Source")]
get => throw null;
[ExtensionMarkerName("<>E__ContentName_For_IEnumerable_T_Source")]
set => throw null;
}
[ExtensionMarkerName("<>E__ContentName_For_IEnumerable_T_Source")]
public int Property2
{
[ExtensionMarkerName("<>E__ContentName_For_IEnumerable_T_Source")]
get => throw null;
[ExtensionMarkerName("<>E__ContentName_For_IEnumerable_T_Source")]
set => throw null;
}
}
[Extension, SpecialName]
public sealed class <>E__ContentName_For_IAsyncEnumerable_Int
{
[SpecialName]
public static class <>E__ContentName_For_IAsyncEnumerable_Int_Values
{
[SpecialName]
public static <Extension>$(IAsyncEnumerable<int> values) => throw null;
}
[ExtensionMarkerName("<>E__ContentName_For_IAsyncEnumerable_Int_Values")]
public Task<int> SumAsync() => throw null;
}
// Implementation for Method
[Extension]
public static void Method<T>(IEnumerable<T> source) { ... }
// Implementation for Property
internal static int get_Property<T>() { ... }
internal static void set_Property<T>(int value) { ... }
// Implementation for Property2
public static int get_Property2<T>(IEnumerable<T> source) { ... }
public static void set_Property2<T>(IEnumerable<T> source, int value) { ... }
// Implementation for SumAsync
[Extension]
public static int SumAsync(IAsyncEnumerable<int> values) { ... }
public static void Method2() { ... }
}
æ¡åŒµã¡ã³ããŒããœãŒã¹ã§äœ¿çšããããã³ã«ãããããå®è£
ã¡ãœãããžã®åç
§ãšããŠåºåããŸãã
ããšãã°ãenumerableOfInt.Method() ã®åŒã³åºãã¯ãIEnumerableExtensions.Method<int>(enumerableOfInt)ã®éçåŒã³åºããšããŠåºåãããŸãã
XML ããã¥ã¡ã³ã
æ¡åŒµãããã¯ã®ããã¥ã¡ã³ã ã³ã¡ã³ãã¯ãããŒã«ãŒã®çš®é¡ã«å¯ŸããŠåºåãããŸã (æ¡åŒµæ©èœãããã¯ã® DocID ã¯ã次ã®äŸã§ E.<>E__MarkerContentName_For_ExtensionOfT'1 )ã
<paramref>ãš<typeparamref>) ã䜿çšããŠæ¡åŒµãã©ã¡ãŒã¿ãŒãšåãã©ã¡ãŒã¿ãŒãåç
§ã§ããŸãã
泚: æ¡åŒµã¡ã³ããŒã«æ¡åŒµãã©ã¡ãŒã¿ãŒãŸãã¯åãã©ã¡ãŒã¿ãŒ ( <param> ããã³ <typeparam>) ãææžåããããšã¯ã§ããŸããã
2 ã€ã®æ¡åŒµãããã¯ã 1 ã€ã®ããŒã«ãŒã®çš®é¡ãšããŠåºåãããå Žåããã®ããã¥ã¡ã³ã ã³ã¡ã³ããããŒãžãããŸãã
xml ããã¥ã¡ã³ãã䜿çšããããŒã«ã¯ãå¿
èŠã«å¿ããŠæ¡åŒµãããã¯ããæ¡åŒµã¡ã³ããŒã« <param> ãš <typeparam> ãã³ããŒããŸã (ã€ãŸãããã©ã¡ãŒã¿ãŒæ
å ±ã¯ã€ã³ã¹ã¿ã³ã¹ ã¡ã³ããŒã«å¯ŸããŠã®ã¿ã³ããŒããå¿
èŠããããŸã)ã
<inheritdoc>ã¯å®è£
ã¡ãœããã§çæãããcrefãæã€é¢é£ããæ¡åŒµã¡ã³ããŒãåç
§ããŸãã ããšãã°ãgetter ã®å®è£
ã¡ãœããã¯ãæ¡åŒµããããã£ã®ããã¥ã¡ã³ããåç
§ããŸãã
æ¡åŒµã¡ã³ããŒã«ããã¥ã¡ã³ã ã³ã¡ã³ãããªãå Žåã <inheritdoc> ã¯çç¥ãããŸãã
æ¡åŒµãããã¯ãšæ¡åŒµã¡ã³ããŒã«ã€ããŠã¯ãçŸåšã次ã®å Žåã¯èŠåããŸããã
- æ¡åŒµãã©ã¡ãŒã¿ãŒã¯ææžåãããŠããŸãããæ¡åŒµã¡ã³ããŒã®ãã©ã¡ãŒã¿ãŒã¯ææžåãããŠããŸãã
- ãŸãã¯ãã®é
- ãŸãã¯ãããã¥ã¡ã³ãã«èšèŒãããŠããªãåãã©ã¡ãŒã¿ãŒãããåçã®ã·ããªãªã®å Žå
ããšãã°ã次ã®ããã¥ã¡ã³ãã³ã¡ã³ã:
/// <summary>Summary for E</summary>
static class E
{
/// <summary>Summary for extension block</summary>
/// <typeparam name="T">Description for T</typeparam>
/// <param name="t">Description for t</param>
extension<T>(T t)
{
/// <summary>Summary for M, which may refer to <paramref name="t"/> and <typeparamref name="T"/></summary>
/// <typeparam name="U">Description for U</typeparam>
/// <param name="u">Description for u</param>
public void M<U>(U u) => throw null!;
/// <summary>Summary for P</summary>
public int P => 0;
}
}
次㮠xml ãçæããŸãã
<?xml version="1.0"?>
<doc>
<assembly>
<name>Test</name>
</assembly>
<members>
<member name="T:E">
<summary>Summary for E</summary>
</member>
<member name="T:E.<>E__MarkerContentName_For_ExtensionOfT`1">
<summary>Summary for extension block</summary>
<typeparam name="T">Description for T</typeparam>
<param name="t">Description for t</param>
</member>
<member name="M:E.<>E__MarkerContentName_For_ExtensionOfT`1.M``1(``0)">
<summary>Summary for M, which may refer to <paramref name="t"/> and <typeparamref name="T"/></summary>
<typeparam name="U">Description for U</typeparam>
<param name="u">Description for u</param>
</member>
<member name="P:E.<>E__MarkerContentName_For_ExtensionOfT`1.P">
<summary>Summary for P</summary>
</member>
<member name="M:E.M``2(``0,``1)">
<inheritdoc cref="M:E.<>E__MarkerContentName_For_ExtensionOfT`1.M``1(``0)"/>
</member>
<member name="M:E.get_P``1(``0)">
<inheritdoc cref="P:E.<>E__MarkerContentName_For_ExtensionOfT`1.P"/>
</member>
</members>
</doc>
CREFã®åç §
æ¡åŒµãããã¯ã¯å
¥ãåã«ãªã£ãåã®ããã«æ±ãããšãã§ããŸããããã¯ãã·ã°ããã£ã«ãã£ãŠã¢ãã¬ã¹æå®ã§ããŸã (1 ã€ã®æ¡åŒµãã©ã¡ãŒã¿ãŒãæã€ã¡ãœããã§ãããã®ããã«)ã
äŸ: E.extension(ref int).M()ã
ãã ããcref ã¯æ¡åŒµãããã¯èªäœã«å¯ŸåŠã§ããŸããã
E.extension(int) ã¯ã Eåã® "extension" ãšããååã®ã¡ãœãããåç
§ã§ããŸãã
static class E
{
extension(ref int i)
{
void M() { } // can be addressed by cref="E.extension(ref int).M()" or cref="extension(ref int).M()" within E, but not cref="M()"
}
extension(ref int i)
{
void M(int i2) { } // can be addressed by cref="E.extension(ref int).M(int)" or cref="extension(ref int).M(int)" within E
}
}
æ€çŽ¢åŠçã¯ãäžèŽãããã¹ãŠã®æ¡åŒµãããã¯ãåç
§ããŸãã
æ¡åŒµã¡ã³ããŒãžã®ä¿®é£ŸãããŠããªãåç
§ãçŠæ¢ãããããcref ã§ã¯ããããçŠæ¢ããããšãã§ããŸãã
æ§æã¯æ¬¡ã®ããã«ãªããŸãã
member_cref
: conversion_operator_member_cref
| extension_member_cref // added
| indexer_member_cref
| name_member_cref
| operator_member_cref
;
extension_member_cref // added
: 'extension' type_argument_list? cref_parameter_list '.' member_cref
;
qualified_cref
: type '.' member_cref
;
cref
: member_cref
| qualified_cref
| type_cref
;
æäžäœã¬ãã« (extension_member_cref) ã§extension(int).Mã䜿çšããããå¥ã®æ¡åŒµæ©èœ (E.extension(int).extension(string).M) ã§å
¥ãåã«ããããšã¯ãšã©ãŒã§ãã
é倧ãªå€æŽ
"extension" ãšããååãåããšã€ãªã¢ã¹ã«ä»ããããšã¯ã§ããŸããã
æªåŠçã®åé¡
æªç¢ºå®ã®æ§æã代æ¿èšèšã®èª¬æãªã©ãæªè§£æ±ºã®åé¡ã«é¢é£ããããã¥ã¡ã³ãã®äžæçãªã»ã¯ã·ã§ã³
- æ¡åŒµã¡ã³ããŒã«ã¢ã¯ã»ã¹ãããšãã«ã¬ã·ãŒããŒã®èŠä»¶ã調æŽããå¿ èŠããããŸãã? (ã³ã¡ã³ã)
-
ããŒã¯ãŒããšããŠããŸã (åç:extensionãšextensionsã確èªextensionãLDM 2025-03-24) -
ç§ãã¡ãããŸã(åç: ã¯ããçŠæ¢ãLDM 2025-06-11)[ModuleInitializer]ãçŠæ¢ãããããšãç¢ºèª -
æ¡åŒµãããã¯ããšã³ã㪠ãã€ã³ãåè£ãšããŠç Žæ£ããŠããããããšã確èªããŸã (åç: ã¯ããç Žæ£ãLDM 2025-06-11) -
LangVer ããžãã¯ã確èªãã (æ°ããæ¡åŒµæ©èœãã¹ããããããéžæããå Žåã¯èæ ®ããŠå ±åãã)(åç: ç¡æ¡ä»¶ã§ãã€ã³ãããã€ã³ã¹ã¿ã³ã¹æ¡åŒµã¡ãœãããé€ã LangVer ãšã©ãŒãå ±åãããLDM 2025-06-11) æ¡åŒµãããã¯ãããŒãžãããããã¥ã¡ã³ãã³ã¡ã³ããããŒãžãããå Žåã(åç:ææžã®ã³ã¡ã³ãã¯ããããã¯ãããŒãžããããšãã«ãµã€ã¬ã³ãã«ããŒãžãããpartialã¯å¿ èŠã§ãã?partialã¯å¿ èŠãããŸãããé»åã¡ãŒã«ã§ç¢ºèª 2025-09-03)ã¡ã³ããŒã«ãå å«åãŸãã¯æ¡åŒµåã®åŸã«ååãä»ããªãããšã確èªããŸãã(åç: ã¯ããé»åã¡ãŒã«ã§ç¢ºèª 2025-09-03)
ç§»æ€æ§ã®åé¡ã«ç
§ãããŠãã°ã«ãŒãå/ç«¶åã«ãŒã«ã忀èšããŸãã https://github.com/dotnet/roslyn/issues/79043
(åç: ãã®ã·ããªãªã¯ãã³ã³ãã³ã ããŒã¹ã®ååãæã€æ°ããã¡ã¿ããŒã¿èšèšã®äžéšãšããŠè§£æ±ºãããŸãããèš±å¯ãããŠããŸã)
çŸåšã®ããžãã¯ã¯ãåãã¬ã·ãŒããŒåãæã€æ¡åŒµãããã¯ãã°ã«ãŒãåããããšã§ãã ããã¯å¶çŽãèæ ®ããŠããŸããã ããã«ããããã®ã·ããªãªã§ç§»æ€æ§ã®åé¡ãçºçããŸãã
static class E
{
extension<T>(ref T) where T : struct
void M()
extension<T>(T) where T : class
void M()
}
ææ¡ã¯ãæ¡åŒµæ©èœã°ã«ãŒãåã¿ã€ãã®èšèšã§èšç»ããŠããã®ãšåãã°ã«ãŒãåããžãã¯ã䜿çšããããšã§ããå ·äœçã«ã¯ãCLR ã¬ãã«ã®å¶çŽãèæ ®ã«å ¥ããŠãnotnullãã¿ãã«åãnull 蚱容泚éãç¡èŠãããšããããšã§ãã
refness ã¯ã°ã«ãŒãåååã§ãšã³ã³ãŒãããå¿ èŠããããŸãã?
-
æ¡åŒµæ©èœã®ã°ã«ãŒãåã®çš®é¡åã«å«ãŸããªã(åç: é»åã¡ãŒã«ã§ç¢ºèªæžã¿ 2025-09-03)refææ¡ã確èªãã (WG ãã°ã«ãŒãå/ç«¶åã«ãŒã«ã忀èšããåŸãããã«è°è«ããå¿ èŠããããŸããLDM 2025-06-23)
public static class E
{
extension(ref int)
{
public static void M()
}
}
次ã®ããã«åºåãããŸãã
public static class E
{
public static class <>ExtensionTypeXYZ
{
.. marker method ...
void M()
}
}
ãŸãã E.extension(ref int).M ã®ãµãŒãããŒãã£ã® CREF åç
§ã¯ã M:E.<>ExtensionGroupingTypeXYZ.M() ãšããŠåºåãããŸãã ref ãåé€ãŸãã¯æ¡åŒµãã©ã¡ãŒã¿ãŒã«è¿œå ãããå ŽåãCREF ãäžæãããããªãå¯èœæ§ããããŸãã
æ¡åŒµæ©èœãšããŠã®äœ¿ç𿹿³ã¯ãããŸããã®ããããã®ã·ããªãªã¯ããŸãæ°ã«ããŸããã
public static class E
{
extension(ref int)
static void M()
extension(int)
static void M()
}
ãã ãããã®ã·ããªãªã¯ (ç§»æ€æ§ãšæçšæ§ãèæ ®ããŠ)ãç«¶åã«ãŒã«ã調æŽããåŸãææ¡ãããã¡ã¿ããŒã¿èšèšã§æ©èœããŸãã
static class E
{
extension<T>(ref T) where T : struct
void M()
extension<T>(T) where T : class
void M()
}
ãã®ã·ããªãªã§ã¯ç§»æ€æ§ã倱ããããrefness ãèæ ®ããªãããšã«ã¯æ¬ ç¹ããããŸãã
static class E
{
extension<T>(ref T)
void M()
extension<T>(T)
void M()
}
// portability issue: since we're grouping without accounting for refness, the emitted extension members conflict (not implementation members). Mitigation: keep as classic extensions or split to another static class
nameof
åŸæ¥ã®æ¡åŒµã¡ãœãããæ°ããæ¡åŒµã¡ãœããã®ããã«ãnameof ã®æ¡åŒµããããã£ãçŠæ¢ããå¿ èŠããããŸãã?åç: nameof(EnclosingStaticClass.ExtensionMember) ã䜿çšããããšæããŸãã èšèšãå¿ èŠã§ã.NET 10 ãããã³ããããå ŽåããããŸãã LDM 2025-06-11)
ãã¿ãŒã³ããŒã¹ã®ã³ã³ã¹ãã©ã¯ã
ã¡ãœãã
æ°ããæ¡åŒµã¡ãœããã¯ã©ãã§æ©èœããå¿ èŠããããŸãã?(åç:åŸæ¥ã®æ¡åŒµã¡ãœãããåçãããã®ãšåãå ŽæãLDM 2025-05-05)
ããã«ã¯æ¬¡ã®ãã®ãå«ãŸããŸãã
-
GetEnumerator/GetAsyncEnumeratorã§foreach -
Deconstructã®åè§£ãäœçœ®ãã¿ãŒã³ãããã³foreachã§äœ¿çšããã -
Addã³ã¬ã¯ã·ã§ã³åæååå -
GetPinnableReferenceã®fixed -
GetAwaiterã®await
ããã«ã¯æ¬¡ã®å 容ãå«ãŸããŸããã
-
Dispose/DisposeAsyncusingãšforeach -
MoveNext/MoveNextAsyncã§foreach -
Sliceããã³intã®ã€ã³ãã¯ãµãŒã¯ãæé»ã®ã€ã³ãã¯ãµãŒãå Žåã«ãã£ãŠã¯ãªã¹ã ãã¿ãŒã³å ã§äœ¿çšãããŸãã -
GetResultã®await
ããããã£ãšã€ã³ãã¯ãµãŒ
æ¡åŒµããããã£ãšã€ã³ãã¯ãµãŒã¯ã©ãã§æ©èœããå¿ èŠããããŸãã?(çã: 4 ã€ããå§ããŸããã,LDM 2025-05-05)
次ã®ãã®ãå«ãŸããŸãã
- ãªããžã§ã¯ãåæåå:
new C() { ExtensionProperty = ... } - dictionary initializer:
new C() { [0] = ... } -
with:x with { ExtensionProperty = ... } - ãããã㣠ãã¿ãŒã³:
x is { ExtensionProperty: ... }
é€å€å¯Ÿè±¡:
-
Currentã®foreach -
IsCompletedã®await -
Count/Lengthãªã¹ã ãã¿ãŒã³ã®ããããã£ãšã€ã³ãã¯ãµãŒ -
Count/Lengthæé»çãªã€ã³ãã¯ãµãŒã®ããããã£ãšã€ã³ãã¯ãµãŒ
ããªã²ãŒããè¿ãããããã£
ãã®å³åœ¢ã®æ¡åŒµããããã£ã LINQ ã¯ãšãªã§ã®ã¿å®è¡ãããã€ã³ã¹ã¿ã³ã¹ ããããã£ã®å®è¡å 容ãšäžèŽããããšã確èªããŸãã(åç: çã«ããªã£ãŠããŸã,LDM 2025-04-06)
ãªã¹ããšå±éãã¿ãŒã³
- æ¡åŒµ
Index/Rangeã€ã³ãã¯ãµãŒããªã¹ã ãã¿ãŒã³ã§åçãããããšã確èªããŸã (åç: C# 14 ã«ã¯é¢ä¿ãããŸãã)
Count
/
Lengthæ¡åŒµæ©èœã®ããããã£ã衚瀺ãããå Žæã忀èšãã
ã³ã¬ã¯ã·ã§ã³åŒ
- æ¡åŒµæ©èœ
AddãåäœããŸã - æ¡åŒµ
GetEnumeratorã¯ã¹ãã¬ããã«å¯ŸããŠæ©èœããŸã - æ¡åŒµ
GetEnumeratorã¯èŠçŽ ã®çš®é¡ã®æ±ºå®ã«åœ±é¿ããŸãã (ã€ã³ã¹ã¿ã³ã¹ã§ããå¿ èŠããããŸã) - éç
Createæ¡åŒµã¡ãœããã¯ãç¥çŠããã äœæ ã¡ãœãããšããŠã«ãŠã³ãããªãã§ãã ãã - æ¡åŒµã«ãŠã³ãå¯èœãªããããã£ã¯ã³ã¬ã¯ã·ã§ã³åŒã«åœ±é¿ããŸãã?
params ã³ã¬ã¯ã·ã§ã³
- æ¡åŒµæ©èœ
Addã¯ãparamsã§èš±å¯ãããåã«åœ±é¿ããŸãã
èŸæžè¡šçŸ
- æ¡åŒµã€ã³ãã¯ãµãŒããã£ã¯ã·ã§ããªåŒã§äœ¿çšãããªãããšã確èªããŠãã ãããã€ã³ãã¯ãµãŒã®ååšã¯ããã£ã¯ã·ã§ããªåãå®çŸ©ããéèŠãªèŠçŽ ã®äžéšã§ããããã§ãã (åç: C# 14 ã«ã¯é¢ä¿ãããŸãã)
extern
-
ç§»æ€æ§ã®(åç: æ¿èªæžã¿ãLDM 2025-06-23)externãèš±å¯ããäºå®ã§ã: https://github.com/dotnet/roslyn/issues/78572
æ¡åŒµæ©èœã®çš®é¡ã®ååä»ã/çªå·ä»ãã¹ããŒã
åé¡
çŸåšã®çªå·ä»ãã·ã¹ãã ã§ã¯ã ãããªã㯠API ã®æ€èšŒ ã«åé¡ãçºçããåç
§ã®ã¿ã®ã¢ã»ã³ããªãšå®è£
ã¢ã»ã³ããªã®éã§ãããªã㯠API ãäžèŽããããšãä¿èšŒããŸãã
次ã®ããããã®å€æŽãè¡ãå¿
èŠããããŸãã? (åç: ãããªã㯠API ã®å®å®æ§ãé«ããããã«ã³ã³ãã³ãããŒã¹ã®ååä»ãã¹ããŒã ãæ¡çšããŠãããããŒã«ãŒã¡ãœãããèæ
®ããããã«ããŒã«ãæŽæ°ããå¿
èŠããããŸã)
- ããŒã«ã調æŽãã
- äžéšã®ã³ã³ãã³ã ããŒã¹ã®ååä»ãã¹ããŒã (TBD) ã䜿çšãã
- ããã€ãã®æ§æã䜿çšããŠååãå¶åŸ¡ã§ããããã«ãã
LINQ ã§ã¯ãæ°ãããžã§ããªãã¯æ¡åŒµ Cast ã¡ãœãããåŒãç¶ãæ©èœããªã
åé¡
以åã®ããŒã«/æ¡åŒµæ©èœã®èšèšã§ã¯ãã¡ãœããã®ååŒæ°ã®ã¿ãæç€ºçã«æå®ããããšãå¯èœã§ããã
ããããåŸæ¥ã®æ¡åŒµã¡ãœããããã®èŠããã®ãªãç§»è¡ã«çŠç¹ãåœãŠãŠããã®ã§ããã¹ãŠã®ååŒæ°ãæç€ºçã«æå®ããå¿
èŠããããŸãã
ããã«ãããLINQ ã§ã®æ¡åŒµ Cast ã¡ãœããã®äœ¿çšã«é¢ããåé¡ã«å¯ŸåŠã§ããŸããã
ãã®ã·ããªãªã«å¯Ÿå¿ããããã«æ¡åŒµæ©èœã®æ©èœã倿Žããå¿
èŠããããŸãã? (çã: ããããããã¯æ¡åŒµæ©èœã®è§£å床ã®èšèšãLDM 2025-05-05 ã忀èšããåå ã«ãªããŸãã)
æ¡åŒµã¡ã³ããŒã§ã®æ¡åŒµãã©ã¡ãŒã¿ãŒã®å¶çŽ
以äžãèš±å¯ããå¿
èŠããããŸãã? (çã:ããããããã¯åŸã§è¿œå ã§ããŸã)
static class E
{
extension<T>(T t)
{
public void M<U>(U u) where T : C<U> { } // error: 'E.extension<T>(T).M<U>(U)' does not define type parameter 'T'
}
}
public class C<T> { }
NULL å€ã®èš±å®¹
-
çŸåšã®èšèšãã€ãŸãæå€§ã®ç§»æ€æ§/äºææ§ã確èªããŸã (åç: ã¯ããLDM 2025-04-17)
extension([System.Diagnostics.CodeAnalysis.DoesNotReturnIf(false)] bool b)
{
public void AssertTrue() => throw null!;
}
extension([System.Diagnostics.CodeAnalysis.NotNullIfNotNull("o")] ref int? i)
{
public void M(object? o) => throw null!;
}
ã¡ã¿ããŒã¿
ã¹ã±ã«ãã³ã¡ãœããã¯(åç: ã¯ã,LDM 2025-04-17)NotSupportedExceptionãã¹ããŒããã¹ããããŸãã¯ãã®ä»ã®æšæºçãªäŸå€ãã¹ããŒããã¹ãã§ãããã (çŸæç¹ã§ã¯throw null;ã䜿çšããŠããŸã)ãã¡ã¿ããŒã¿ã®ããŒã«ãŒ ã¡ãœããã§è€æ°ã®ãã©ã¡ãŒã¿ãŒãåãå ¥ããå¿ èŠããããŸãã (æ°ããããŒãžã§ã³ã§è©³çްæ å ±ã远å ãããå Žå)ã(çã: æã ã¯å³æ ŒãªãŸãŸã«ããããšãã§ããŸã, LDM 2025-04-17)æ¡åŒµããŒã«ãŒãŸãã¯èªã¿äžãå¯èœãªå®è£ ã¡ãœããã¯ãç¹å¥ãªååã§ããŒã¯ããå¿ èŠããããŸãã?(åç: ããŒã«ãŒã¡ãœããã¯ç¹å¥ãªååã§ããŒã¯ããããã確èªããå¿ èŠããããŸãããå®è£ æ¹æ³ã§ã¯ãããŸãããLDM 2025-04-17)ã€ã³ã¹ã¿ã³ã¹æ¡åŒµã¡ãœãããå éšã«ååšããªãå Žåã§ããéçã¯ã©ã¹ã«(åç: ã¯ããLDM 2025-03-10)[Extension]屿§ã远å ããå¿ èŠããããŸãã?å®è£ ã²ãã¿ãŒãšã»ãã¿ãŒã«ã(åç: ããããLDM 2025-03-10)[Extension]屿§ã远å ããå¿ èŠãããããšã確èªããŸãã-
æ¡åŒµæ©èœã®çš®é¡ãç¹å¥ãªååã§ããŒã¯ããå¿ èŠããããã³ã³ãã€ã©ã§ã¡ã¿ããŒã¿ã«ãã®ãã©ã°ãå¿ èŠã§ããããšã確èªããŸã (ããã¯ãã¬ãã¥ãŒããã®ç Žå£ç倿Žã§ã)(åç: æ¿èªæžã¿ãLDM 2025-06-23)
éçå·¥å Žã·ããªãª
éçã¡ãœããã®ç«¶åã«ãŒã«ã¯äœã§ãã?(åç: å æ¬ããéçåã«å¯ŸããŠæ¢åã® C# ã«ãŒã«ã䜿çšããŸããç·©åã¯ãªããLDM 2025-03-17)
åç §
èªã¿åãå¯èœãªå®è£ åãä»ããã®ã§ãã€ã³ã¹ã¿ã³ã¹ ã¡ãœããã®åŒã³åºãã解決ããæ¹æ³ã¹ã±ã«ãã³ ã¡ãœããã¯ã察å¿ããå®è£ ã¡ãœãããããåªå ãããŸããéçæ¡åŒµã¡ãœããã解決ããæ¹æ³(åç: ã€ã³ã¹ã¿ã³ã¹æ¡åŒµã¡ãœãããšåæ§ã«ãLDM 2025-03-03)ããããã£ã解決ããæ¹æ³(ãããŸãã«åç LDM 2025-03-03, ããããæ¹åã®ããã®ãã©ããŒã¢ãããå¿ èŠ)-
æ¡åŒµãã©ã¡ãŒã¿ãŒãšåãã©ã¡ãŒã¿ãŒã®ã¹ã³ãŒããšã·ã£ããŠã«ãŒã«(åç: æ¡åŒµãããã¯ã®ã¹ã³ãŒãå ãã·ã£ããŠçŠæ¢ãLDM 2025-03-10) æ°ããæ¡åŒµã¡ãœããã« ORPA ãé©çšããæ¹æ³(åç: æ¡åŒµãããã¯ã¯ééçãšããORPA ã®ãå å«åãã¯å€åŽã®éçã¯ã©ã¹ã§ãã LDM 2025-04-17)
public static class Extensions
{
extension(Type1)
{
[OverloadResolutionPriority(1)]
public void Overload(...)
}
extension(Type2)
{
public void Overload(...)
}
}
æ°ããæ¡åŒµããããã£ã« ORPA ãé©çšããå¿ èŠããããŸãã?(åç: ã¯ããORPA ã¯å®è£ æ¹æ³ã«ã³ããŒããå¿ èŠããããŸããLDM 2025-04-23)
public static class Extensions
{
extension(int[] i)
{
public P { get => }
}
extension(ReadOnlySpan<int> r)
{
[OverloadResolutionPriority(1)]
public P { get => }
}
}
- åŸæ¥ã®æ¡åŒµæ©èœã®è§£æ±ºèŠåãå調æŽããæ¹æ³ ã©ãããŸãã
- ã¯ã©ã·ãã¯æ¡åŒµã¡ãœããã®æšæºãæŽæ°ããããã䜿çšããŠæ°ããæ¡åŒµã¡ãœãããèšè¿°ããŸãã
- åŸæ¥ã®æ¡åŒµã¡ãœããã®æ¢åã®èšèªãä¿æããããã䜿çšããŠæ°ããæ¡åŒµã¡ãœãããèšè¿°ããŸãããäž¡æ¹ã«æ¢ç¥ã®ä»æ§ã®åå·®ããããŸãã
- åŸæ¥ã®æ¡åŒµã¡ãœããã®æ¢åã®èšèªãä¿æããŸãããæ°ããæ¡åŒµã¡ãœããã«ã¯ç°ãªãèšèªã䜿çšããã¯ã©ã·ãã¯æ¡åŒµã¡ãœããã®æ¢ç¥ã®ä»æ§ã®åå·®ãããªãå Žåã¯ã
-
ãããã㣠ã¢ã¯ã»ã¹ã§æç€ºçãªååŒæ°ãçŠæ¢ããããšã確èªããŸã (åç: WG ã§èª¬æãããŠããæç€ºçãªååŒæ°ãæã€ãããã㣠ã¢ã¯ã»ã¹ãªã)
string s = "ran";
_ = s.P<object>; // error
static class E
{
extension<T>(T t)
{
public int P => 0;
}
}
-
ã¬ã·ãŒããŒãåã®å Žåã§ããããè¯ãèŠåãé©çšããããšã確èªããŸã (åç: éçæ¡åŒµã¡ã³ããŒã解決ãããšãã«åã®ã¿ã®æ¡åŒµãã©ã¡ãŒã¿ãŒãèæ ®ããå¿ èŠããããŸããLDM 2025-06-23)
int.M();
static class E1
{
extension(int)
{
public static void M() { }
}
}
static class E2
{
extension(in int i)
{
public static void M() => throw null;
}
}
-
ã¡ãœãããšããããã£ã®äž¡æ¹ãé©çšå¯èœãªå Žåã«ãããŸãããæã€ããšã«åé¡ãããããšã確èªããŸã (åç: .NET 10ãLDM 2025-06-23 ãããã³ãã¢ãŠãããŠãçŸç¶ãããåªããæ¹æ³ãææ¡ããããã«èšèšããå¿ èŠããããŸã) -
ãã¹ãŠã®ã¡ã³ããŒã«å¯ŸããŠäœããã®æ¹åãå¿ èŠãªãããšã確èªããŠãããæçµçãªã¡ã³ããŒã®çš®é¡ã決å®ããŸããã(åç: .NET 10 ãžã®å°å ¥ã¯èŠéããWG 2025-07-02)
string s = null;
s.M(); // error
static class E
{
extension(string s)
{
public System.Action M => throw null;
}
extension(object o)
{
public string M() => throw null;
}
}
æ¡åŒµå®£èšå ã«æé»çãªã¬ã·ãŒããŒããããŸãã?(çã:ããããLDMã§ä»¥åã«è°è«ãããŸãã)
static class E
{
extension(object o)
{
public void M()
{
M2();
}
public void M2() { }
}
}
åãã©ã¡ãŒã¿ãŒã®æ€çŽ¢ãèš±å¯ããå¿ èŠããããŸãã?(ãã£ã¹ã«ãã·ã§ã³)(åç: ãããããã£ãŒãããã¯ããåŸ ã¡ãã ãããLDM 2025-04-16)
ã¢ã¯ã»ã·ããªãã£
æ¡åŒµæ©èœå®£èšå ã®ã¢ã¯ã»ã·ããªãã£ã®æå³ã¯äœã§ãã?(åç: æ¡åŒµå®£èšã¯ã¢ã¯ã»ã·ããªã㣠ã¹ã³ãŒããšããŠã«ãŠã³ããããŸãããLDM 2025-03-17)éçã¡ã³ããŒã®å Žåã§ããã¬ã·ãŒã㌠ãã©ã¡ãŒã¿ãŒã« "äžè²«æ§ã®ãªãã¢ã¯ã»ã·ããªãã£" ãã§ãã¯ãé©çšããå¿ èŠããããŸãã?(åç: ã¯ã,LDM 2025-04-17)
public static class Extensions
{
extension(PrivateType p)
{
// We report inconsistent accessibility error,
// because we generate a `public static void M(PrivateType p)` implementation in enclosing type
public void M() { }
public static void M2() { } // should we also report here, even though not technically necessary?
}
private class PrivateType { }
}
æ¡åŒµæ©èœå®£èšã®æ€èšŒ
ã¡ãœãããããªãåãã©ã¡ãŒã¿ãŒã®æ€èšŒ (æšè«å¯èœæ§: ãã¹ãŠã®åãã©ã¡ãŒã¿ãŒãæ¡åŒµãã©ã¡ãŒã¿ãŒã®åã«å«ããå¿ èŠããããŸã) ãç·©åããå¿ èŠããããŸãã?(åç: ã¯ããLDM 2025-04-06)ããã«ããã100% ã®ã¯ã©ã·ãã¯æ¡åŒµã¡ãœãããç§»æ€ã§ããŸãã
TResult M<TResult, TSource>(this TSource source)ãããå Žåã¯ãextension<TResult, TSource>(TSource source) { TResult M() ... }ãšããŠç§»æ€ã§ããŸããæ¡åŒµæ©èœã§ init å°çšã¢ã¯ã»ãµãŒãèš±å¯ããå¿ èŠããããã©ããã確èªããŸã (åç: ä»ã®ãšããçŠæ¢ããŠãåé¡ãããŸãããLDM 2025-04-17)ã¬ã·ãŒããŒã® ref-ness ã®å¯äžã®éãã¯ã(åç: ãããã仿§ã«é¢ããèŠåãä¿æãããLDM 2025-03-24)extension(int receiver) { public void M2() {} }extension(ref int receiver) { public void M2() {} }èš±å¯ãããã¹ãã§ãã?ãã®ãããª(åç: ã¯ãã仿§ã«é¢ããèŠåãä¿æããŸããLDM 2025-03-24)extension(object receiver) { public int P1 => 1; }extension(object receiver) { public int P1 {set{}} }ã®ãããªç«¶åã«ã€ããŠäžå¹³ãèšãã¹ãã§ãã?å®è£ ã¡ãœããéã®ç«¶åã§ã¯ãªãã¹ã±ã«ãã³ ã¡ãœããéã®ç«¶åã«ã€ããŠäžå¹³ãèšãã¹ãã§ãã?(åç: ã¯ãã仿§ã«é¢ããèŠåãä¿æããŸããLDM 2025-03-24)
static class E
{
extension(object)
{
public void Method() { }
public static void Method() { }
}
}
çŸåšã®ç«¶åã«ãŒã«ã¯ 1 ã§ãã ã¯ã©ã¹/æ§é äœã«ãŒã«ã䜿çšããŠãé¡äŒŒã®æ¡åŒµæ©èœå ã§ç«¶åããªãããšã確èªããŸãã2ã ããŸããŸãªæ¡åŒµæ©èœã®å®£èšéã§å®è£ ã¡ãœããéã®ç«¶åããªãããšã確èªããŸãã
ã«ãŒã«ã®æåã®éšåããŸã å¿ èŠã§ãããã?(åç: ã¯ããAPI ã®äœ¿çšã«åœ¹ç«ã€ãã®æ§é ãç¶æããŠããŸããLDM 2025-03-24)
XML ããã¥ã¡ã³ã
æ¡åŒµã¡ã³ããŒã§ receiver ãã©ã¡ãŒã¿ãŒãžã®(åç: æ¡åŒµã¡ã³ããŒãLDM 2025-05-05 ã§ã¯æ¡åŒµãã©ã¡ãŒã¿ãŒãžã® yes paramref ãèš±å¯ãããŸã)paramrefã¯ãµããŒããããŠããŸãã? éçãªå Žåã§ã? åºåã§ãšã³ã³ãŒããããæ¹æ³ ããããæšæºçãªæ¹æ³<paramref name="..."/>ã¯äººéã«ã¯åé¡ãªã䜿çšã§ããã§ãããããAPIã®ãã©ã¡ãŒã¿ãŒã«ååšããªãããšã§äžéšã®æ¢åããŒã«ãåé¡ãèµ·ãããªã¹ã¯ããããŸããã¹ããŒãã³ã°å¯èœãªååãæã€å®è£ ã¡ãœããã«ããã¥ã¡ã³ãã³ã¡ã³ããã³ããŒããããšã«ãªã£ãŠããŸãã?(åç: ã³ããŒãªããLDM 2025-05-05)ã€ã³ã¹ã¿ã³ã¹ ã¡ãœãã(åç: ã³ããŒãªããLDM 2025-05-05)<param>æ¡åŒµã³ã³ãããŒãã receiver ãã©ã¡ãŒã¿ãŒã«å¯Ÿå¿ããèŠçŽ ãã³ããŒããå¿ èŠããããŸãã? ã³ã³ãããŒããå®è£ ã¡ãœãã (<typeparam>ãªã©) ã«ä»ã®äœããã³ããŒããå¿ èŠããããŸãã?æ¡åŒµã¡ã³ããŒã§ãªãŒããŒã©ã€ããšããŠæ¡åŒµãã©ã¡ãŒã¿ãŒã®(åç: ããããçŸæç¹ã§ã¯ LDM 2025-05-05)<param>ãèš±å¯ããå¿ èŠããããŸãã?- æ¡åŒµãããã¯ã®æŠèŠã¯ã©ãã«è¡šç€ºãããŸãã?
CREF
-
æ§æã確èªãã (åç: ææ¡ãè¯ã,LDM 2025-06-09) æ¡åŒµããã㯠((åç: ããããLDM 2025-06-09)E.extension(int)) ãåç §ã§ããŸãã?修食ãããŠããªãæ§æ ((åç: ã¯ããLDM 2025-06-09)extension(int).Member) ã䜿çšããŠã¡ã³ããŒãåç §ã§ããå¿ èŠããããŸãã?- XML ãšã¹ã±ãŒããåé¿ããããã«ã話ããªãååã«ç°ãªãæåã䜿çšããå¿ èŠããããŸãã? (åç: WGãLDMã®å€æã«å§ããã2025-06-09)
ã¹ã±ã«ãã³ã¡ãœãããšå®è£ ã¡ãœããã®äž¡æ¹ãžã®åç §ãå¯èœã§ããããšã確èªããŸã((åç: ã¯ããLDM 2025-06-09)E.MãšE.extension(int).M)ãã©ã¡ããå¿ èŠãšæãããŸã (æ¡åŒµããããã£ãšåŸæ¥ã®æ¡åŒµã¡ãœããã®ç§»æ€æ§)ãæ¡åŒµæ©èœã¡ã¿ããŒã¿åã¯ããŒãžã§ã³ç®¡çããã¥ã¡ã³ãã§åé¡ããããŸãã?(åç: ã¯ããåºæ°ããé¢ããã³ã³ãã³ãããŒã¹ã®å®å®ããååä»ãã¹ããŒã ã䜿çšããŸã)
ã¡ã³ããŒã®çš®é¡ãå¢ãããµããŒãã远å ãã
ãã®èšèšããã¹ãŠäžåºŠã«å®è£ ããå¿ èŠã¯ãããŸããããäžåºŠã« 1 ã€ãŸãã¯æ°çš®é¡ã®ã¡ã³ããŒã«ã¢ãããŒãã§ããŸãã ã³ã¢ ã©ã€ãã©ãªã®æ¢ç¥ã®ã·ããªãªã«åºã¥ããŠã次ã®é åºã§äœæ¥ããå¿ èŠããããŸãã
- ããããã£ãšã¡ãœãã (ã€ã³ã¹ã¿ã³ã¹ãšéç)
- ãªãã¬ãŒã¿ãŒ
- ã€ã³ãã¯ãµãŒ (ã€ã³ã¹ã¿ã³ã¹ãšéçã以åã®æç¹ã§æ¥åèŠçã«å®è¡ãããå ŽåããããŸã)
- ã»ãã«äœã
ä»ã®çš®é¡ã®ã¡ã³ããŒã«å¯ŸããŠã©ãããããã¶ã€ã³ãããã³ãããŒãããŸãã?
extension_member_declaration // add
: constant_declaration
| field_declaration
| method_declaration
| property_declaration
| event_declaration
| indexer_declaration
| operator_declaration
| constructor_declaration
| finalizer_declaration
| static_constructor_declaration
| type_declaration
;
å ¥ãåã«ãªã£ãå
æ¡åŒµã®å ¥ãåã«ãªã£ãåã䜿çšããŠå ã«é²ãå Žåã¯ãåã®ãã£ã¹ã«ãã·ã§ã³ã®æ³šæäºé ã以äžã«ç€ºãã®ã§åç §ããŠãã ããã
- 2 ã€ã®æ¡åŒµå®£èšããåãååãšã¢ãªãã£ãæã€å ¥ãåã«ãªã£ãæ¡åŒµåã宣èšããå Žåãç«¶åãçºçããŸãã ã¡ã¿ããŒã¿ã§ããã衚ããœãªã¥ãŒã·ã§ã³ã¯ãããŸããã
- ã¡ã¿ããŒã¿ã«ã€ããŠèª¬æãã倧ãŸããªã¢ãããŒã:
- å ã®åãã©ã¡ãŒã¿ãŒãæã¡ãã¡ã³ããŒãªãã§ã¹ã±ã«ãã³ã®å ¥ãåã«ãªã£ãåãåºåããŸã
- æ¡åŒµå®£èšããå é ã«ä»å ãããåãã©ã¡ãŒã¿ãŒãæã€å®è£ ã®ãã¹ããããåãšããœãŒã¹ã«èšè¿°ããããŸãŸã®ãã¹ãŠã®ã¡ã³ããŒå®è£ ãåºåããã§ããã (åãã©ã¡ãŒã¿ãŒãžã®åç §ãé€ã)
ã³ã³ã¹ãã©ã¯ã¿ãŒ
ã³ã³ã¹ãã©ã¯ã¿ãŒæ¬æã¯ãthis ããŒã¯ãŒãã䜿çšããŠæ°ããäœæãããå€ã«ã¢ã¯ã»ã¹ã§ãããããã³ã³ã¹ãã©ã¯ã¿ãŒã¯ãäžè¬çã« C# ã§ã¯ã€ã³ã¹ã¿ã³ã¹ ã¡ã³ããŒãšããŠèšè¿°ãããŸãã
ããã¯ããã©ã¡ãŒã¿ãŒãšããŠæž¡ãåã®å€ããªããããã€ã³ã¹ã¿ã³ã¹æ¡åŒµã¡ã³ããŒã«å¯Ÿãããã©ã¡ãŒã¿ãŒããŒã¹ã®ã¢ãããŒãã§ã¯ããŸãæ©èœããŸããã
代ããã«ãæ¡åŒµã³ã³ã¹ãã©ã¯ã¿ãŒã¯éçãã¡ã¯ã㪠ã¡ãœãããšåæ§ã«åäœããŸãã
ãããã¯ãã¬ã·ãŒã㌠ãã©ã¡ãŒã¿ãŒåã«äŸåããªããšããæå³ã§éçã¡ã³ããŒãšèŠãªãããŸãã
ãã®æ¬æã¯ãæ§ç¯çµæãæç€ºçã«äœæããŠè¿ãå¿
èŠããããŸãã
ã¡ã³ããŒèªäœã¯ã³ã³ã¹ãã©ã¯ã¿ãŒæ§æã§ãŸã 宣èšãããŠããŸãããthis åæååãŸã㯠base åæååãæã€ããšãã§ãããã¢ã¯ã»ã¹å¯èœãªã³ã³ã¹ãã©ã¯ã¿ãŒãæã€ã¬ã·ãŒããŒåã«ã¯äŸåããŸããã
ããã¯ãã€ã³ã¿ãŒãã§ã€ã¹ãåæåãªã©ãç¬èªã®ã³ã³ã¹ãã©ã¯ã¿ãŒããªãåã«å¯ŸããŠæ¡åŒµã³ã³ã¹ãã©ã¯ã¿ãŒã宣èšã§ããããšãæå³ããŸãã
public static class Enumerable
{
extension(IEnumerable<int>)
{
public static IEnumerable(int start, int count) => Range(start, count);
}
public static IEnumerable<int> Range(int start, int count) { ... }
}
Allows:
var range = new IEnumerable<int>(1, 100);
çããã©ãŒã
ææ¡ãããèšèšã§ã¯ãã¬ã·ãŒããŒä»æ§ã®åã¡ã³ããŒãžã®ç¹°ãè¿ããåé¿ã§ããŸãããæçµçã«æ¡åŒµã¡ã³ããŒã¯éçã¯ã©ã¹ãš æ¡åŒµå®£èšã§2å±€ã«ãã¹ããããŸãã éçã¯ã©ã¹ã«ã¯ 1 ã€ã®æ¡åŒµå®£èšããå«ãŸãããæ¡åŒµå®£èšã«ã¯ã¡ã³ããŒã 1 ã€ã ãå«ãŸããã®ãäžè¬çã§ããããã®ãããªã±ãŒã¹ã®æ§æã®çç¥åœ¢ãèš±å¯ããããšã¯åŠ¥åœæ§ãé«ããšæãããŸãã
éçã¯ã©ã¹ãšæ¡åŒµå®£èšãããŒãžããŸãã
public static class EmptyExtensions : extension(IEnumerable source)
{
public bool IsEmpty => !source.GetEnumerator().MoveNext();
}
ããã¯ãæ¡åŒµã¡ã³ããŒã®ã³ã³ãããŒèªäœã«ååãä»ãããã "åããŒã¹" ã¢ãããŒããšåŒã°ããããã«èŠããŸãã
æ¡åŒµå®£èšãšæ¡åŒµã¡ã³ããŒã®ããŒãž:
public static class Bits
{
extension(ref ulong bits) public bool this[int index]
{
get => (bits & Mask(index)) != 0;
set => bits = value ? bits | Mask(index) : bits & ~Mask(index);
}
static ulong Mask(int index) => 1ul << index;
}
public static class Enumerable
{
extension<TSource>(IEnumerable<TSource> source) public IEnumerable<TSource> Where(Func<TSource, bool> predicate) { ... }
}
ããã¯ãåæ¡åŒµã¡ã³ããŒã«ç¬èªã®ã¬ã·ãŒããŒä»æ§ãå«ãŸããŠããã"ã¡ã³ããŒããŒã¹" ã®ã¢ãããŒããåŒã³åºããŠãããã®ã®ããã«èŠããŸãã
C# feature specifications