Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
Notitie
Dit artikel is een functiespecificatie. De specificatie fungeert als het ontwerpdocument voor de functie. Het bevat voorgestelde specificatiewijzigingen, samen met informatie die nodig is tijdens het ontwerp en de ontwikkeling van de functie. Deze artikelen worden gepubliceerd totdat de voorgestelde specificaties zijn voltooid en opgenomen in de huidige ECMA-specificatie.
Er kunnen enkele verschillen zijn tussen de functiespecificatie en de voltooide implementatie. Deze verschillen worden vastgelegd in de relevante LDM-notities (Language Design Meeting).
Meer informatie over het proces voor het aannemen van functiespeclets in de C#-taalstandaard vindt u in het artikel over de specificaties.
Kampioensprobleem: https://github.com/dotnet/csharplang/issues/7706
Samenvatting
We introduceren een nieuw kenmerk, System.Runtime.CompilerServices.OverloadResolutionPriority
, dat door API-auteurs kan worden gebruikt om de relatieve prioriteit van overbelastingen binnen één type aan te passen als een manier om API-gebruikers te sturen om specifieke API's te gebruiken, zelfs als deze API's normaal gesproken als dubbelzinnig worden beschouwd of anderszins niet worden gekozen door de regels voor overbelastingsoplossing van C#.
Motivatie
API-auteurs lopen vaak een probleem op van wat er met een lid moet worden gedaan nadat deze verouderd is. Voor doeleinden van achterwaartse compatibiliteit houden velen het bestaande onderdeel aan met ObsoleteAttribute
op fout ingesteld in eeuwigheid, om te voorkomen dat gebruikers die runtime binaries upgraden problemen ondervinden. Dit raakt met name invoegtoepassingssystemen, waarbij de auteur van een invoegtoepassing niet de omgeving beheert waarin de invoegtoepassing wordt uitgevoerd. De maker van de omgeving wil mogelijk een oudere methode aanwezig houden, maar de toegang tot de omgeving blokkeren voor nieuwe code.
ObsoleteAttribute
zelf is echter niet voldoende. Het type of lid blijft zichtbaar in het proces van overbelastingsresolutie en kan ongewenste fouten in de overbelastingsresolutie veroorzaken, zelfs wanneer er een uitstekend alternatief is, maar dat alternatief dubbelzinnig is door het verouderde lid, of de aanwezigheid van het verouderde lid veroorzaakt dat de overbelastingsresolutie vroegtijdig eindigt zonder het geschikte lid te overwegen. Voor dit doel willen we een manier hebben om API-auteurs te helpen bij het oplossen van overbelasting bij het oplossen van de dubbelzinnigheid, zodat ze hun API-oppervlaktegebieden kunnen ontwikkelen en gebruikers naar performante API's kunnen sturen zonder dat ze de gebruikerservaring moeten in gevaar brengen.
Het BCL-team (Base Class Libraries) heeft verschillende voorbeelden van waar dit nuttig kan zijn. Enkele (hypothetische) voorbeelden zijn:
- Het creëren van een overload van
Debug.Assert
dieCallerArgumentExpression
gebruikt om de geëxpliciteerde expressie te verkrijgen, zodat deze in het bericht kan worden opgenomen en de voorkeur geniet boven de bestaande overload. - De voorkeur geven aan
string.IndexOf(string, StringComparison = Ordinal)
bovenstring.IndexOf(string)
. Dit zou moeten worden besproken als een mogelijke wijziging met brekende gevolgen, maar er is een gedachte dat het de betere standaardwaarde is en meer in lijn is met wat de gebruiker waarschijnlijk bedoelde. - Een combinatie van dit voorstel en
CallerAssemblyAttribute
zou methoden met een impliciete aanroeperidentiteit toestaan om dure stackwandelingen te voorkomen.Assembly.Load(AssemblyName)
doet dit vandaag en het kan veel efficiënter zijn. -
Microsoft.Extensions.Primitives.StringValues
een impliciete conversie beschikbaar maakt voor zowelstring
alsstring[]
. Dit betekent dat het onduidelijk is wanneer deze wordt doorgegeven aan een methode met zowelparams string[]
alsparams ReadOnlySpan<string>
overloads. Dit kenmerk kan worden gebruikt om prioriteit te geven aan een van de overbelastingen om de dubbelzinnigheid te voorkomen.
Gedetailleerd ontwerp
Prioriteit van overbelastingsresolutie
We definiëren een nieuw concept, overload_resolution_priority, dat wordt gebruikt tijdens het proces voor het oplossen van een methodegroep.
overload_resolution_priority is een 32-bits geheel getal. Alle methoden hebben standaard een overload_resolution_priority van 0. Dit kan worden gewijzigd door OverloadResolutionPriorityAttribute
toe te passen op een methode. We actualiseren sectie §12.6.4.1 van de C#-specificatie als volgt (wijziging in vet):
Zodra de leden van de kandidaatfunctie en de argumentenlijst zijn geïdentificeerd, is de selectie van het beste functielid in alle gevallen hetzelfde:
- Ten eerste wordt de set kandidaatfunctieleden gereduceerd tot die functieleden die van toepassing zijn op de opgegeven argumentenlijst (§12.6.4.2). Als deze gereduceerde set leeg is, treedt er een compilatietijdfout op.
- Vervolgens wordt de gereduceerde set kandidaatleden gegroepeerd door het type te declareren. Binnen elke groep:
- Kandidaat-functieleden worden geordend volgens de prioriteit van overbelastingsresolutie . Als het lid een overschrijding is, is de overload_resolution_priority afkomstig van de minst afgeleide declaratie van dat lid.
- Alle leden met een lagere overload_resolution_priority dan de hoogste gevonden in de declaratiegroep van het type, worden verwijderd.
- De gereduceerde groepen worden vervolgens opnieuw samengevoegd in de definitieve set van toepasselijke kandidaatfunctieleden.
- Vervolgens bevindt het beste functielid uit de set van toepasselijke kandidaatfunctieleden zich. Als de set slechts één functielid bevat, is dat functielid het beste functielid. Anders is het beste functielid het ene functielid dat beter is dan alle andere functieleden met betrekking tot de opgegeven argumentenlijst, mits elk functielid wordt vergeleken met alle andere functieleden die gebruikmaken van de regels in §12.6.4.3. Als er niet precies één functielid is dat beter is dan alle andere functieleden, is de aanroep van het functielid niet eenduidig en treedt er een bindingstijdfout op.
Als voorbeeld zorgt deze functie ervoor dat het volgende codefragment "Span" afdrukt in plaats van "Array":
using System.Runtime.CompilerServices;
var d = new C1();
int[] arr = [1, 2, 3];
d.M(arr); // Prints "Span"
class C1
{
[OverloadResolutionPriority(1)]
public void M(ReadOnlySpan<int> s) => Console.WriteLine("Span");
// Default overload resolution priority
public void M(int[] a) => Console.WriteLine("Array");
}
Het effect van deze wijziging is dat we, net zoals we snoeien voor de meest afgeleide typen, een definitieve snoei toevoegen voor prioriteit bij de oplossing van overbelasting. Omdat deze snoei plaatsvindt aan het einde van het overbelastingsresolutieproces, betekent dit wel dat een basistype de leden geen hogere prioriteit kan verlenen dan elk afgeleid type. Dit is opzettelijk en voorkomt dat er een wapenwedloop optreedt waarbij een basistype altijd beter kan proberen te zijn dan een afgeleid type. Bijvoorbeeld:
using System.Runtime.CompilerServices;
var d = new Derived();
d.M([1, 2, 3]); // Prints "Derived", because members from Base are not considered due to finding an applicable member in Derived
class Base
{
[OverloadResolutionPriority(1)]
public void M(ReadOnlySpan<int> s) => Console.WriteLine("Base");
}
class Derived : Base
{
public void M(int[] a) => Console.WriteLine("Derived");
}
Negatieve getallen mogen worden gebruikt en kunnen worden gebruikt om een specifieke overbelasting te markeren als erger dan alle andere standaardoverbelastingen.
De overload_resolution_priority van een lid komt uit de minst afgeleide verklaring van dat lid. Het overload_resolution_priority wordt niet overgenomen of afgeleid van interfaceleden die een typelid mogelijk kan implementeren, en als we uitgaan van een lid Mx
dat een interfacelid Mi
implementeert, wordt er geen waarschuwing gegeven als Mx
en Mi
verschillende overload_resolution_prioritieshebben.
NB: De bedoeling van deze regel is het gedrag van de
params
modifier te repliceren.
System.Runtime.CompilerServices.OverloadResolutionPriorityAttribute
We introduceren het volgende kenmerk voor de BCL:
namespace System.Runtime.CompilerServices;
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
public sealed class OverloadResolutionPriorityAttribute(int priority) : Attribute
{
public int Priority => priority;
}
Alle methoden in C# hebben een standaard overload_resolution_priority van 0, tenzij ze worden toegeschreven aan OverloadResolutionPriorityAttribute
. Als ze aan dat kenmerk zijn toegewezen, is hun overload_resolution_priority de gehele waarde die is opgegeven aan het eerste argument van het kenmerk.
Het is een fout om OverloadResolutionPriorityAttribute
toe te passen op de volgende locaties:
- Eigenschappen van niet-indexeerfunctie
- Eigenschap, indexeerfunctie of gebeurtenistoegangsmethodes
- Conversieoperators
- Lambdas
- Lokale functies
- Finalisatoren
- Statische constructors
Kenmerken die zijn aangetroffen op deze locaties in metagegevens, worden genegeerd door C#.
Het is een fout om OverloadResolutionPriorityAttribute
toe te passen op een plek waar het wordt genegeerd, zoals bij een overschrijving van een basismethode, omdat de prioriteit wordt gelezen uit de minst afgeleide declaratie van een lid van een klasse.
NB: Dit verschilt opzettelijk van het gedrag van de
params
-modifier, waarmee het mogelijk is om opnieuw te specificeren of toe te voegen wanneer deze wordt genegeerd.
Oproepbaarheid van leden
Een belangrijk voorbehoud voor OverloadResolutionPriorityAttribute
is dat bepaalde leden niet langer vanuit de bron kunnen worden aangeroepen. Bijvoorbeeld:
using System.Runtime.CompilerServices;
int i = 1;
var c = new C3();
c.M1(i); // Will call C3.M1(long), even though there's an identity conversion for M1(int)
c.M2(i); // Will call C3.M2(int, string), even though C3.M1(int) has less default parameters
class C3
{
public void M1(int i) {}
[OverloadResolutionPriority(1)]
public void M1(long l) {}
[Conditional("DEBUG")]
public void M2(int i) {}
[OverloadResolutionPriority(1), Conditional("DEBUG")]
public void M2(int i, [CallerArgumentExpression(nameof(i))] string s = "") {}
public void M3(string s) {}
[OverloadResolutionPriority(1)]
public void M3(object o) {}
}
Voor deze voorbeelden worden de standaardprioriteitsoverbelastingen effectief verwaarloosbaar en kunnen alleen worden aangeroepen via enkele stappen die wat extra inspanning vereisen.
- Zet de methode om naar een delegate en gebruik vervolgens die delegate.
- Voor sommige scenario's met afwijkingen van referentietypen, zoals
M3(object)
met prioriteit bovenM3(string)
, mislukt deze strategie. - Voorwaardelijke methoden, zoals
M2
, kunnen met deze strategie ook niet worden aangeroepen, omdat voorwaardelijke methoden niet kunnen worden omgezet naar delegeren.
- Voor sommige scenario's met afwijkingen van referentietypen, zoals
- Gebruik de
UnsafeAccessor
runtime-functie om deze aan te roepen via een overeenkomende handtekening. - Handmatig reflectie gebruiken om een verwijzing naar de methode te verkrijgen en deze vervolgens aan te roepen.
- Code die niet opnieuw is gecompileerd, blijft oude methoden aanroepen.
- Handgeschreven IL kan specificeren wat het wil.
Open vragen
Groepering van extensiemethoden (beantwoord)
Zoals momenteel gezegd, worden extensiemethoden gerangschikt op prioriteit alleen binnen hun eigen type. Bijvoorbeeld:
new C2().M([1, 2, 3]); // Will print Ext2 ReadOnlySpan
static class Ext1
{
[OverloadResolutionPriority(1)]
public static void M(this C2 c, Span<int> s) => Console.WriteLine("Ext1 Span");
[OverloadResolutionPriority(0)]
public static void M(this C2 c, ReadOnlySpan<int> s) => Console.WriteLine("Ext1 ReadOnlySpan");
}
static class Ext2
{
[OverloadResolutionPriority(0)]
public static void M(this C2 c, ReadOnlySpan<int> s) => Console.WriteLine("Ext2 ReadOnlySpan");
}
class C2 {}
Wanneer we overloadresolutie uitvoeren bij extensieleden, zouden we dan niet moeten sorteren op het declarerende type, maar in plaats daarvan alle extensies binnen dezelfde scope overwegen?
Antwoorden
We zullen ons altijd groeperen. In het bovenstaande voorbeeld wordt Ext2 ReadOnlySpan
afgedrukt.
Kenmerkenovererving bij overschrijvingen (beantwoord)
Moet het kenmerk worden overgenomen? Zo niet, wat is dan de prioriteit van het overschrijvende lid?
Als het kenmerk is opgegeven voor een virtueel lid, moet een overschrijving van dat lid worden vereist om het kenmerk te herhalen?
Antwoorden
Het kenmerk wordt niet gemarkeerd als overgenomen. We kijken naar de minst afgeleide verklaring van een lid om de prioriteit van de overbelastingsresolutie te bepalen.
Toepassingsfout of waarschuwing bij overschrijving (beantwoord)
class Base
{
[OverloadResolutionPriority(1)] public virtual void M() {}
}
class Derived
{
[OverloadResolutionPriority(2)] public override void M() {} // Warn or error for the useless and ignored attribute?
}
Wat moeten we doen bij de toepassing van een OverloadResolutionPriorityAttribute
in een context waar deze wordt genegeerd, zoals bij een overschrijving:
- Doe niets, laat het op de achtergrond worden genegeerd.
- Geef een waarschuwing dat het kenmerk wordt genegeerd.
- Geef een fout aan dat het attribuut niet is toegestaan.
3 is de meest voorzichtige benadering, als we denken dat er in de toekomst wellicht een mogelijkheid is waarin we een override willen toestaan om dit kenmerk op te geven.
Antwoorden
We zullen kiezen voor optie 3 en de applicatie blokkeren op locaties waar deze zou worden genegeerd.
Impliciete interface-implementatie (beantwoord)
Wat moet het gedrag van een impliciete interface-implementatie zijn? Moet OverloadResolutionPriority
worden opgegeven? Wat moet het gedrag van de compiler zijn wanneer deze een impliciete implementatie tegenkomt zonder prioriteit? Dit zal bijna zeker gebeuren, omdat een interfacebibliotheek mogelijk wordt bijgewerkt, maar geen implementatie. De stand van de techniek met params
is dat het niet wordt gespecificeerd en de waarde niet wordt overgedragen.
using System;
var c = new C();
c.M(1, 2, 3); // error CS1501: No overload for method 'M' takes 3 arguments
((I)c).M(1, 2, 3);
interface I
{
void M(params int[] ints);
}
class C : I
{
public void M(int[] ints) { Console.WriteLine("params"); }
}
Onze opties zijn:
- Volg
params
.OverloadResolutionPriorityAttribute
wordt niet impliciet overgedragen of moet worden opgegeven. - Draag het kenmerk impliciet over.
- Draag het kenmerk niet impliciet over, vereist dat het wordt opgegeven op de oproepsite.
- Dit brengt een extra vraag: wat moet het gedrag zijn wanneer de compiler dit scenario tegenkomt met gecompileerde verwijzingen?
Antwoorden
We gaan met 1.
Verdere toepassingsfouten (beantwoord)
Er zijn nog enkele locaties, zoals deze die moeten worden bevestigd. Dit zijn onder andere:
- Conversieoperators: de specificatie zegt nooit dat conversieoperators overbelastingsafhandeling doorlopen, vandaar dat de implementatie het gebruik van deze leden blokkeert. Moet dat worden bevestigd?
- Lambdas - Op dezelfde manier zijn lambdas nooit onderhevig aan overbelastingsresolutie, dus de implementatie blokkeert ze. Moet dat worden bevestigd?
- Destructors - momenteel weer geblokkeerd.
- Statische constructors – opnieuw momenteel geblokkeerd.
- Lokale functies: deze zijn momenteel niet geblokkeerd, omdat ze overbelastingsresolutie ondergaan, u kunt ze gewoon niet overbelasten. Dit is vergelijkbaar met de manier waarop er geen fout optreedt wanneer het kenmerk wordt toegepast op een lid van een type dat niet overbelast is. Moet dit gedrag worden bevestigd?
Antwoorden
Alle hierboven vermelde locaties worden geblokkeerd.
Langversion-gedrag (beantwoord)
De implementatie geeft momenteel alleen langversion-fouten op wanneer OverloadResolutionPriorityAttribute
wordt toegepast, niet wanneer deze daadwerkelijk invloed heeft op iets. Deze beslissing is genomen omdat er API's zijn die de BCL toevoegt (zowel nu als na verloop van tijd) die dit kenmerk gaan gebruiken; als de gebruiker de taalversie handmatig instelt op C# 12 of eerder, kunnen ze deze leden zien en, afhankelijk van het gedrag van onze langversion, ofwel:
- Als we het kenmerk in C# <13 negeren, treedt er een dubbelzinnigheidsfout op omdat de API echt dubbelzinnig is zonder het kenmerk, of;
- Als er een fout optreedt doordat het kenmerk het resultaat beïnvloedt, ervaren we een fout omdat de API niet bruikbaar is. Dit zal vooral nadelig zijn omdat
Debug.Assert(bool)
in prioriteit wordt verlaagd in .NET 9, of; - Als we de resolutie op de achtergrond wijzigen, kunnen er mogelijk verschillen optreden tussen verschillende compilerversies als de ene het kenmerk begrijpt en de andere niet.
Het laatste gedrag is gekozen, omdat dit resulteert in de meest toekomstgerichte compatibiliteit, maar de verandering in het resultaat kan verrassend zijn voor sommige gebruikers. Moeten we dit bevestigen of moeten we een van de andere opties kiezen?
Antwoorden
We gaan voor optie 1, waarbij het attribuut stilzwijgend wordt genegeerd in eerdere taalversies.
Alternatieven
Een vorige voorstel probeerde een BinaryCompatOnlyAttribute
aanpak vast te stellen, die zeer rigoureus was in het verwijderen van zaken uit zichtbaarheid. Dat heeft echter veel problemen met de implementatie die ofwel betekenen dat het voorstel te sterk is om nuttig te zijn (het voorkomen van het testen van oude API's, bijvoorbeeld) of zo zwak dat het een aantal van de oorspronkelijke doelstellingen miste (zoals het kunnen hebben van een API die anders als dubbelzinnige aanroep van een nieuwe API zou worden beschouwd). Deze versie wordt hieronder gerepliceerd.
BinaryCompatOnlyAttribute Proposal (verouderd)
BinaryCompatOnlyAttribute
Gedetailleerd ontwerp
System.BinaryCompatOnlyAttribute
We introduceren een nieuw gereserveerd kenmerk:
namespace System;
// Excludes Assembly, GenericParameter, Module, Parameter, ReturnValue
[AttributeUsage(AttributeTargets.Class
| AttributeTargets.Constructor
| AttributeTargets.Delegate
| AttributeTargets.Enum
| AttributeTargets.Event
| AttributeTargets.Field
| AttributeTargets.Interface
| AttributeTargets.Method
| AttributeTargets.Property
| AttributeTargets.Struct,
AllowMultiple = false,
Inherited = false)]
public class BinaryCompatOnlyAttribute : Attribute {}
Wanneer dit wordt toegepast op een typelid, wordt dat lid beschouwd als ontoegankelijk op elke locatie door de compiler, wat betekent dat het niet bijdraagt aan het opzoeken van leden, overbelastingsresolutie of een ander vergelijkbaar proces.
Toegankelijkheidsdomeinen
We werken §7.5.3 Toegankelijkheidsdomeinen bij als volgt:
Het toegankelijkheidsdomein van een lid bestaat uit de (mogelijk niet-aaneengesloten) secties van programmatekst waarin toegang tot het lid is toegestaan. Voor het definiëren van het toegankelijkheidsdomein van een lid, wordt een lid als op het hoogste niveau beschouwd als het niet binnen een type gedeclareerd is, en een lid is genest als het binnen een ander type gedeclareerd is. Bovendien wordt de programmatekst van een programma gedefinieerd als alle tekst in alle compilatie-eenheden van het programma en wordt de programmatekst van een type gedefinieerd als alle tekst in de type_declarations van dat type (inclusief mogelijk typen die zijn genest binnen het type).
Het toegankelijkheidsdomein van een vooraf gedefinieerd type (zoals
object
,int
ofdouble
) is onbeperkt.Het toegankelijkheidsdomein van een niet-afhankelijk type op het hoogste niveau
T
(§8.4.4) dat wordt gedeclareerd in een programmaP
wordt als volgt gedefinieerd:
- Als
T
is gemarkeerd metBinaryCompatOnlyAttribute
, is het toegankelijkheidsdomein vanT
volledig niet toegankelijk voor de programmatekst vanP
en elk programma dat verwijst naarP
.- Als de gedeclareerde toegankelijkheid van
T
openbaar is, is het toegankelijkheidsdomein vanT
de programmatekst vanP
en elk programma dat verwijst naarP
.- Als de gedeclareerde toegankelijkheid van
T
intern is, is het toegankelijkheidsdomein vanT
de programmatekst vanP
.Opmerking: Uit deze definities volgt dat het toegankelijkheidsdomein van een niet-afhankelijk type op het hoogste niveau altijd ten minste de programmatekst is van het programma waarin dat type wordt gedeclareerd. eindnotitie
Het toegankelijkheidsdomein voor een samengesteld type
T<A₁, ..., Aₑ>
is het snijpunt van het toegankelijkheidsdomein van het niet-afhankelijke algemene typeT
en de toegankelijkheidsdomeinen van de typeargumentenA₁, ..., Aₑ
.Het toegankelijkheidsdomein van een geneste lid
M
gedeclareerd in een typeT
binnen een programmaP
, wordt als volgt gedefinieerd (waarbij wordt aangegeven datM
zelf mogelijk een type is):
- Als
M
is gemarkeerd metBinaryCompatOnlyAttribute
, is het toegankelijkheidsdomein vanM
volledig niet toegankelijk voor de programmatekst vanP
en elk programma dat verwijst naarP
.- Als de gedeclareerde toegankelijkheid van
M
ispublic
, is het toegankelijkheidsdomein vanM
het toegankelijkheidsdomein vanT
.- Als de gedeclareerde toegankelijkheid van
M
protected internal
is, laatD
de vereniging zijn van de programmatekst vanP
en de programmatekst van elk type dat is afgeleid vanT
en dat buitenP
wordt gedeclareerd. Het toegankelijkheidsdomein vanM
is het snijpunt van het toegankelijkheidsdomein vanT
metD
.- Als de gedeclareerde toegankelijkheid van
M
private protected
is, laatD
het snijpunt zijn van de programmatekst vanP
en de programmatekst vanT
en elk type dat is afgeleid vanT
. Het toegankelijkheidsdomein vanM
is het snijpunt van het toegankelijkheidsdomein vanT
metD
.- Als de gedeclareerde toegankelijkheid van
M
protected
is, wordtD
de samenvoeging van de programmatekst vanT
en de programmatekst van elk type dat is afgeleid vanT
. Het toegankelijkheidsdomein vanM
is het snijpunt van het toegankelijkheidsdomein vanT
metD
.- Als de toegankelijkheid van
M
internal
is, is het toegankelijkheidsdomein vanM
het snijpunt van het toegankelijkheidsdomein vanT
met de programmatekst vanP
.- Als de gedeclareerde toegankelijkheid van
M
private
is, is het toegankelijkheidsdomein vanM
de programmatekst vanT
.
Het doel van deze toevoegingen is om ervoor te zorgen dat leden die zijn gemarkeerd met BinaryCompatOnlyAttribute
volledig niet toegankelijk zijn voor elke locatie, ze zullen niet deelnemen aan het opzoeken van leden en niet van invloed zijn op de rest van het programma. Dus betekent dit dat ze geen interfaceleden kunnen implementeren, ze elkaar niet kunnen aanroepen en dat ze niet kunnen worden overschreven (virtuele methoden), verborgen of geïmplementeerd (interfaceleden). Of dit te strikt is, is het onderwerp van verschillende open vragen hieronder.
Niet-opgeloste vragen
Virtuele methoden en overschrijven
Wat doen we wanneer een virtuele methode wordt gemarkeerd als BinaryCompatOnly
? Overschrijvingen in een afgeleide klasse hoeven zich mogelijk niet eens in de huidige assembly te bevinden en het kan zijn dat de gebruiker een nieuwe versie van een methode wil introduceren die bijvoorbeeld alleen verschilt in retourtype, iets waarvoor C# normaal gesproken geen overladen toestaat. Wat gebeurt er bij het opnieuw compileren met eventuele overschrijvingen van die vorige methode? Mogen ze het BinaryCompatOnly
-lid overschrijven als ze ook gemarkeerd zijn als BinaryCompatOnly
?
Gebruik binnen hetzelfde DLL-bestand
Dit voorstel geeft aan dat BinaryCompatOnly
leden nergens zichtbaar zijn, zelfs niet in de assembly die momenteel wordt gecompileerd. Is dat te streng, of moeten BinaryCompatAttribute
leden zich mogelijk aan elkaar verbinden?
Interfaceleden impliciet implementeren
Moeten BinaryCompatOnly
leden interfaceleden kunnen implementeren? Of moeten ze dit niet doen. Dit zou vereisen dat wanneer een gebruiker een impliciete interface-implementatie wil omzetten in BinaryCompatOnly
, ze ook een expliciete interface-implementatie moeten leveren, waarschijnlijk door dezelfde code te dupliceren als het BinaryCompatOnly
-lid, omdat de expliciete interface-implementatie het oorspronkelijke lid niet meer kan zien.
Het implementeren van interfaceleden die gemarkeerd zijn met BinaryCompatOnly
Wat doen we wanneer een interfacelid is gemarkeerd als BinaryCompatOnly
? Het type moet nog steeds een implementatie voor dat lid bieden; het kan zijn dat we gewoon moeten zeggen dat interfaceleden niet kunnen worden gemarkeerd als BinaryCompatOnly
.
C# feature specifications