Delen via


ref readonly parameters

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.

Samenvatting

Sta parameterdeclaratiemodificator ref readonly toe en wijzig de regels voor de aanroepplaats als volgt:

Annotatie bij aanroepingslocatie parameter ref parameter ref readonly parameter in parameter out
ref Toegestaan Toegestaan Waarschuwing Fout
in Fout Toegestaan Toegestaan Fout
out Fout Fout Fout Toegestaan
Geen aantekening Fout waarschuwing Toegestaan Fout

(Houd er rekening mee dat er één wijziging is in de bestaande regels: in parameter met ref aanroepiteaantekening produceert een waarschuwing in plaats van een fout.)

Wijzig de argumentwaarderegels als volgt:

Waardetype parameter ref parameter ref readonly parameter in parameter out
rvalue Fout waarschuwing Toegestaan Fout
l-waarde Toegestaan Toegestaan Toegestaan Toegestaan

Waarbij lvalue een variabele betekent (d.w.: een waarde met een locatie; hoeft niet schrijfbaar/toewijsbaar te zijn) en rvalue betekent een willekeurig soort waarde.

Motivatie

C# 7.2 heeft in parameters geïntroduceerd als een manier om alleen-lezen verwijzingen door te geven. in parameters zowel lvalues als rvalues toestaan en kunnen worden gebruikt zonder aantekening op de aanroepite. API's die verwijzingen van hun parameters vastleggen of retourneren, willen echter rvalues verbieden en ook een indicatie afdwingen bij de aanroepplaats dat een verwijzing wordt vastgelegd. ref readonly parameters zijn ideaal in zulke gevallen, doordat ze waarschuwen wanneer ze worden gebruikt met r-waarden of zonder annotatie op de aanroepplaats.

Bovendien zijn er API's die alleen alleen-lezenverwijzingen nodig hebben, maar die gebruikmaken van

  • ref-parameters die zijn geïntroduceerd voordat in beschikbaar werd en wijzigen naar in zou een breuk van zowel de bron- als binaire compatibiliteit betekenen, bijvoorbeeld QueryInterface, of
  • in parameters om alleen-lezen verwijzingen te accepteren, ook al is het doorgeven van r-waarden hieraan niet echt zinvol, bijvoorbeeld ReadOnlySpan<T>..ctor(in T value), of
  • ref parameters om rvalues te verbieden, ook als ze de doorgegeven verwijzing niet aanpassen, bijvoorbeeld Unsafe.IsNullRef.

Deze API's kunnen worden gemigreerd naar ref readonly parameters zonder gevolgen voor gebruikers. Zie de voorgestelde metagegevenscoderingvoor meer informatie over binaire compatibiliteit. Specifiek, wijzigen

  • refref readonly zou alleen een binaire brekende wijziging zijn voor virtuele methoden.
  • refin zou ook een binaire breuk betekenen voor virtuele methoden, maar geen breuk in de broncode (omdat de regels veranderen om alleen te waarschuwen voor ref-argumenten die aan in-parameters worden doorgegeven).
  • inref readonly zou geen incompatibele wijziging zijn (maar bij afwezigheid van een aanroepplaats-annotatie of rvalue zou er een waarschuwing optreden),
    • Houd er rekening mee dat dit een wijziging is die brekende veranderingen in de bron veroorzaakt voor gebruikers die oudere compilerversies gebruiken (omdat ze ref readonly parameters interpreteren als ref parameters, en in of geen aantekening op de aanroepplaats niet toestaan) en nieuwe compilerversies met LangVersion <= 11 (voor consistentie met oudere compilerversies wordt er een fout gegenereerd dat ref readonly parameters niet worden ondersteund, tenzij de bijbehorende argumenten worden doorgegeven met de ref modifier).

In de tegenovergestelde richting, veranderend

  • ref readonlyref zou mogelijk een onderbreking van de bron kunnen zijn (tenzij alleen ref-aanroepannotatie werd gebruikt en alleen alleen-lezenverwijzingen als argumenten werden gebruikt), en een binaire onderbreking voor virtuele methoden,
  • ref readonlyin zou geen brekende wijziging zijn (maar ref aanroepannotatie zou resulteren in een waarschuwing).

Houd er rekening mee dat de hierboven beschreven regels van toepassing zijn op methodehandtekeningen, maar niet op het delegeren van handtekeningen. Als u bijvoorbeeld ref verandert naar in in een gedelegeerdehandtekening, kan dit een bronbrekende wijziging zijn (als een gebruiker een methode met ref-parameter toewijst aan dat gedelegeerdetype, wordt dit een fout na de API wijziging).

Gedetailleerd ontwerp

In het algemeen zijn regels voor ref readonly parameters hetzelfde als die zijn opgegeven voor in parameters in hun voorstel, behalve wanneer deze expliciet in dit voorstel is gewijzigd.

Parameterdeclaraties

Er zijn geen wijzigingen in grammatica nodig. De modifier ref readonly is toegestaan voor parameters. Naast normale methoden is ref readonly toegestaan voor indexeerparameters (zoals in maar in tegenstelling tot ref), maar niet toegestaan voor operatorparameters (zoals ref maar in tegenstelling tot in).

Standaardparameterwaarden worden toegestaan voor ref readonly parameters met een waarschuwing, omdat ze gelijk zijn aan het doorgeven van rvalues. Hierdoor kunnen API-auteurs in parameters met standaardwaarden wijzigen in ref readonly parameters zonder dat er een wijziging voor bronbreking wordt aangebracht.

Waardetypecontroles

Hoewel ref argumentaanpassing is toegestaan voor ref readonly parameters, verandert er niets w.r.t. waardetypecontroles, dat wil zeggen,

  • ref kan alleen worden gebruikt met toewijsbare waarden;
  • om alleen-lezenverwijzingen door te geven, moet je in plaats daarvan de in argumentmodificator gebruiken;
  • om rvalues door te geven, moet men geen modifier gebruiken (wat resulteert in een waarschuwing voor ref readonly-parameters zoals beschreven in de samenvatting van dit voorstel).

Overbelastingsresolutie

Met overbelastingsresolutie kunnen ref/ref readonly/in/no-callsiteannotaties en parameteraanpassingen worden vermengd zoals aangegeven door de tabel in het overzicht van dit voorstel, oftewel alle toegestane en waarschuwing gevallen worden als mogelijke kandidaten beschouwd tijdens overbelastingsresolutie. Er is met name een wijziging in het bestaande gedrag waarbij methoden met een in parameter overeenkomen met oproepen met het overeenkomstige argument gemarkeerd als ref. Deze wijziging wordt afhankelijk van de LangVersie geïmplementeerd.

De waarschuwing voor het doorgeven van een argument zonder aanroepitemodifier aan een ref readonly parameter wordt echter onderdrukt als de parameter is

  • de ontvanger in een uitbreidingsmethodeaanroep;
  • impliciet gebruikt als onderdeel van een aangepaste initialisator voor verzamelingen of geinterpoleerde tekenreekshandler.

By-value overloads krijgen de voorkeur boven ref readonly overloads wanneer er geen argumentmodificator is (in parameters vertonen hetzelfde gedrag).

Methodeconversies

Voor anonieme functie [§10,7] en methodegroep [§10.8] worden deze modifiers beschouwd als compatibel (maar elke toegestane conversie tussen verschillende modifiers resulteert in een waarschuwing):

  • ref readonly parameter van de doelmethode mag overeenkomen met in of ref parameter van de gemachtigde,
  • in parameter van de doelmethode mag overeenkomen met ref readonly of, op basis van LangVersion, ref parameter van de delegate.
  • Opmerking: ref parameter van de doelmethode is niet mogen overeenkomen met in of ref readonly parameter van de gemachtigde.

Bijvoorbeeld:

DIn dIn = (ref int p) => { }; // error: cannot match `ref` to `in`
DRef dRef = (in int p) => { }; // warning: mismatch between `in` and `ref`
DRR dRR = (ref int p) => { }; // error: cannot match `ref` to `ref readonly`
dRR = (in int p) => { }; // warning: mismatch between `in` and `ref readonly`
dIn = (ref readonly int p) => { }; // warning: mismatch between `ref readonly` and `in`
dRef = (ref readonly int p) => { }; // warning: mismatch between `ref readonly` and `ref`
delegate void DIn(in int p);
delegate void DRef(ref int p);
delegate void DRR(ref readonly int p);

Houd er rekening mee dat er geen wijziging is in het gedrag van functieaanwijzerconversies. Ter herinnering: impliciete functiepointerconversies zijn niet toegestaan als er sprake is van een niet-overeenkomende verwijzingstypeaanpassing en expliciete cast-conversies zijn altijd toegestaan zonder waarschuwingen.

Handtekeningkoppeling

Leden die in één type zijn gedeclareerd, kunnen niet alleen verschillen in handtekening door ref/out/in/ref readonly. Voor andere doeleinden van handtekeningvergelijking (bijvoorbeeld verbergen of overschrijven), kan ref readonly worden uitgewisseld met de in modifier, maar dat resulteert in een waarschuwing bij de declaratiesite [§7.6]. Dit geldt niet bij het matchen van partial-verklaring met de implementatie en bij het matchen van een onderscheppingssignatuur met een onderschepte signatuur. Houd er rekening mee dat er geen wijziging is in het overschrijven van ref/in en ref readonly/ref wijzigingsparen, ze kunnen niet worden uitgewisseld, omdat de handtekeningen niet binair compatibel zijn. Voor de consistentie geldt hetzelfde voor andere doeleinden van het vergelijken van handtekeningen (bijvoorbeeld verbergen).

Metagegevenscodering

Ter herinnering,

  • ref parameters worden uitgevoerd als gewone byref-typen (T& in IL).
  • in parameters lijken op ref plus ze worden geannoteerd met System.Runtime.CompilerServices.IsReadOnlyAttribute. In C# 7.3 en hoger worden ze ook verzonden met [in] en indien virtueel, modreq(System.Runtime.InteropServices.InAttribute).

ref readonly parameters worden verzonden als [in] T&, plus met het volgende kenmerk geannoteerd:

namespace System.Runtime.CompilerServices
{
    [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
    public sealed class RequiresLocationAttribute : Attribute
    {
    }
}

Bovendien worden ze, indien virtueel, verzonden met modreq(System.Runtime.InteropServices.InAttribute) om binaire compatibiliteit met in parameters te garanderen. Houd er rekening mee dat in tegenstelling tot in parameters er geen [IsReadOnly] worden verzonden voor ref readonly parameters om te voorkomen dat de metagegevens groter worden en dat oudere compilerversies ref readonly parameters interpreteren als ref parameters (en daarom is refref readonly geen bronwijziging, zelfs tussen verschillende compilerversies).

De RequiresLocationAttribute wordt vergeleken met de naamruimte-gekwalificeerde naam en gesynthetiseerd door de compiler als deze nog niet is opgenomen in de compilatie.

Het opgeven van het kenmerk in de bron is een fout als het wordt toegepast op een parameter, vergelijkbaar met ParamArrayAttribute.

Functie-aanwijzers

In functieaanwijzers worden in-parameters gegenereerd met modreq(System.Runtime.InteropServices.InAttribute) (zie voorstel voor functieaanwijzers). Parameters van ref readonly worden zonder die modreqverzonden, maar wel met modopt(System.Runtime.CompilerServices.RequiresLocationAttribute). Oudere compilerversies negeren de modopt en interpreteren daarom ref readonly parameters als ref parameters (consistent met oudere compilergedrag voor normale methoden met ref readonly parameters zoals hierboven beschreven) en nieuwe compilerversies die op de hoogte zijn van de modopt gebruiken om ref readonly parameters te herkennen om waarschuwingen te verzenden tijdens conversies en aanroepen. Voor consistentie met oudere compilerversies zullen nieuwe compilerversies met LangVersion <= 11 fouten melden dat ref readonly-parameters niet worden ondersteund, tenzij de bijbehorende argumenten worden doorgegeven met de ref-modifier.

Houd er rekening mee dat het een binaire breuk is om modificatoren in functiepointer-handtekeningen te veranderen als deze deel uitmaken van openbare API's, dus het is een binaire breuk wanneer u ref of in wijzigt in ref readonly. Een brononderbreking vindt echter alleen plaats voor bellers met LangVersion <= 11 bij het wijzigen van inref readonly (als de aanwijzer wordt aangeroepen met in callite modifier), consistent met normale methoden.

Belangrijke wijzigingen

De ref/in niet-overeenkomende ontspanning in overbelastingsresolutie introduceert een gedragsverbrekingswijziging die wordt gedemonstreerd in het volgende voorbeeld:

class C
{
    string M(in int i) => "C";
    static void Main()
    {
        int i = 5;
        System.Console.Write(new C().M(ref i));
    }
}
static class E
{
    public static string M(this C c, ref int i) => "E";
}

In C# 11 bindt de aanroep aan E.M, waardoor "E" wordt afgedrukt. In C# 12 mag C.M binden (met een waarschuwing) en worden er geen uitbreidingsbereiken doorzocht omdat we een toepasselijke kandidaat hebben, dus "C" wordt afgedrukt.

Er is ook een bronbrekende verandering vanwege dezelfde reden. In het onderstaande voorbeeld wordt "1" in C# 11 afgedrukt, maar kan niet worden gecompileerd met een dubbelzinnigheidsfout in C# 12:

var i = 5;
System.Console.Write(C.M(null, ref i));

interface I1 { }
interface I2 { }
static class C
{
    public static string M(I1 o, ref int x) => "1";
    public static string M(I2 o, in int x) => "2";
}

In de bovenstaande voorbeelden worden de einden voor methode-aanroepen gedemonstreerd, maar omdat ze worden veroorzaakt door wijzigingen in de overbelastingsresolutie, kunnen ze op dezelfde manier worden geactiveerd voor methodeconversies.

Alternatieven

parameterverklaringen

API-auteurs kunnen aantekeningen toevoegen aan in parameters die zijn ontworpen om alleen lvalues te accepteren met een aangepast kenmerk en een analyse bieden om onjuiste gebruiksmarkeringen te markeren. Hierdoor kunnen API-auteurs geen handtekeningen wijzigen van bestaande API's die ervoor hebben gekozen om ref parameters te gebruiken om rvalues niet toe te staan. Bellers van dergelijke API's moeten nog steeds extra werk uitvoeren om een ref te krijgen als ze alleen toegang hebben tot een ref readonly variabele. Als u deze API's wijzigt van ref naar [RequiresLocation] in, is dit een breekbare wijziging voor de bron (en in het geval van virtuele methoden, ook een breekbare binaire wijziging).

In plaats van de modifier toe te staan ref readonly, kan de compiler herkennen wanneer een speciaal kenmerk (zoals [RequiresLocation]) wordt toegepast op een parameter. Dit is besproken in LDM 2022-04-25, beslissend dat dit een taalfunctie is, geen analyse, dus het moet er als volgt uitzien.

waardetypecontroles

Het doorgeven van lvalues zonder enige wijziging aan ref readonly parameters kan worden toegestaan zonder waarschuwingen, vergelijkbaar met de impliciete byref-parameters van C++. Dit is besproken in LDM 2022-05-11, waarbij wordt aangegeven dat de primaire motivatie voor ref readonly parameters API's zijn die verwijzingen van deze parameters vastleggen of retourneren, dus markering van een bepaald soort is een goede zaak.

Rvalue doorgeven aan een ref readonly kan een fout zijn, geen waarschuwing. Dat werd in eerste instantie geaccepteerd in LDM 2022-04-25, maar latere e-maildiscussies hebben dit versoepeld omdat we de mogelijkheid zouden verliezen om bestaande API's te wijzigen zonder gebruikers te breken.

in kan de 'natuurlijke' aanroepite-modifier voor ref readonly parameters zijn en het gebruik van ref kan leiden tot waarschuwingen. Dit zorgt voor een consistente codestijl en maakt het duidelijk op de aanroepsite dat de verwijzing alleen-lezen is (in tegenstelling tot ref). Het werd in eerste instantie geaccepteerd in LDM 2022-04-25. Waarschuwingen kunnen echter een wrijvingspunt zijn voor API-auteurs om over te stappen van ref naar ref readonly. Ook is in opnieuw gedefinieerd als ref readonly + gemaksfuncties, daarom is dit geweigerd in LDM 2022-05-11.

In afwachting van LDM-beoordeling

Geen van de volgende opties zijn geïmplementeerd in C# 12. Ze blijven potentiële voorstellen.

Declaraties van parameters

Inverse volgorde van modifiers (readonly ref in plaats van ref readonly) kan worden toegestaan. Dit zou inconsistent zijn met de manier waarop readonly ref retourneert en velden zich gedragen (omgekeerde volgorde is niet toegestaan of betekent iets anders, respectievelijk) en kan botsen met leesparameters als deze in de toekomst worden geïmplementeerd.

Standaardparameterwaarden kunnen een fout zijn voor ref readonly parameters.

waardetypecontroles

Fouten kunnen worden uitgezonden in plaats van waarschuwingen bij het doorgeven van rvalues aan ref readonly parameters of het niet overeenkomen van de annotaties op de aanroeplocatie en de parameterwijzigingen. Op dezelfde manier kunnen speciale modreq worden gebruikt in plaats van een kenmerk om ervoor te zorgen dat ref readonly parameters verschillen van in parameters op het binaire niveau. Dit zou sterkere garanties bieden, wat gunstig zou zijn voor nieuwe API's, maar het zou de invoering in bestaande runtime-API's verhinderen, aangezien deze geen ingrijpende wijzigingen kunnen doorvoeren.

** Waardetypecontroles kunnen worden versoepeld om readonly-verwijzingen via ref door te geven aan parameters in/ref readonly. Dat zou vergelijkbaar zijn met de manier waarop referentietoewijzingen en referentie-terugkeerwaarden vandaag de dag werken—ook kunnen referenties als alleen-lezen worden doorgegeven via de ref-modifier bij de bronexpressie. De ref bevindt zich meestal dicht bij de plaats waar het doel als ref readonlywordt gedeclareerd, dus het is duidelijk dat we een verwijzing als alleen-lezen doorgeven, in tegenstelling tot oproepen waarbij het argument en de parameterwijzigingen meestal ver uit elkaar liggen. Bovendien maken ze alleen de ref modificator in tegenstelling tot argumenten die ook intoestaan. Dus in en ref zouden kunnen worden uitgewisseld voor argumenten, of in zou praktisch verouderd raken als gebruikers hun code consistent wilden maken (ze zouden waarschijnlijk overal ref gebruiken omdat dit de enige modificator is die is toegestaan voor reftoewijzingen en ref-teruggaven).

overbelastingsresolutie

Overbelastingsresolutie, onderdrukking en conversie kunnen de uitwisselbaarheid van ref readonly en in modifiers niet mogelijk maken.

De wijziging van de overbelastingsresolutie voor bestaande in parameters zou onvoorwaardelijk kunnen worden genomen (zonder rekening te houden met LangVersion), maar dat zou een breuk in de compatibiliteit zijn.

Het aanroepen van een extensiemethode met een ref readonly ontvanger kan leiden tot de waarschuwing 'Argument 1 moet worden doorgegeven met het trefwoord ref of in', vergelijkbaar met wat zou gebeuren bij niet-extensieaanroepen zonder aanroepmodificatoren. De gebruiker kan een dergelijke waarschuwing oplossen door de aanroep van de extensiemethode om te zetten in een statische methodeaanroep. Dezelfde waarschuwing kan worden gemeld bij het gebruik van een aangepaste collectie-initialisator of geïnterpoleerde stringhandler met ref readonly parameter, hoewel de gebruiker het niet kon omzeilen.

ref readonly overbelastingen kunnen de voorkeur krijgen boven overbelastingen met een waarde wanneer er geen aanroepsite-modifier is of er is een dubbelzinnigheidsfout.

methode conversies

We kunnen toestaan dat ref parameter van de doelmethode overeenkomt met in en ref readonly parameter van de gemachtigde. Hierdoor kunnen API-auteurs bijvoorbeeld ref wijzigen in in in gedelegeerde handtekeningen zonder dat hun gebruikers worden onderbroken (consistent met wat is toegestaan voor normale methodehandtekeningen). Het zou echter ook leiden tot de volgende schending van de readonly-garanties met alleen een waarschuwing:

class Program
{
    static readonly int f = 123;
    static void Main()
    {
        var d = (in int x) => { };
        d = (ref int x) => { x = 42; }; // warning: mismatch between `ref` and `in`
        d(f); // changes value of `f` even though it is `readonly`!
        System.Console.WriteLine(f); // prints 42
    }
}

Functiepointerconversies zou kunnen waarschuwen voor ref readonly/ref/in die niet overeenkomen, maar als we dat zouden willen koppelen aan LangVersion, zou een aanzienlijke implementatie-investering vereist zijn aangezien typeconversies momenteel geen toegang tot compilatie vereisen. Hoewel een mismatch momenteel een fout is, is het bovendien eenvoudig voor gebruikers om een cast toe te voegen om de mismatch toe te staan als ze dat willen.

metagegevenscodering

Het opgeven van de RequiresLocationAttribute in de bron kan worden toegestaan, vergelijkbaar met In en Out kenmerken. Het kan ook een fout zijn wanneer deze wordt toegepast in andere contexten dan alleen parameters, vergelijkbaar met IsReadOnly kenmerk; om verdere ontwerpruimte te behouden.

Functiepointer ref readonly parameters kunnen worden verzonden met verschillende combinaties van modopt/modreq (let op: 'broneinde' in deze tabel betekent voor bellers met LangVersion <= 11):

Modificeerders Kan worden herkend in compilaties Oude compilers zien ze als refref readonly inref readonly
modreq(In) modopt(RequiresLocation) ja in binair, brononderbreking binaire onderbreking
modreq(In) Nee in binair, brononderbreking OK
modreq(RequiresLocation) ja Niet ondersteund binair, brononderbreking binair, brononderbreking
modopt(RequiresLocation) ja ref binaire onderbreking binair, brononderbreking

We kunnen zowel [RequiresLocation] als [IsReadOnly] kenmerken voor ref readonly parameters verzenden. Dan zou inref readonly geen belangrijke wijziging zijn, zelfs niet voor oudere compilerversies, maar refref readonly zou een bronbrekende wijziging worden voor oudere compilerversies (omdat ze ref readonly interpreteren als in, ref modifiers niet toewijzen) en nieuwe compilerversies met LangVersion <= 11 (voor consistentie).

We kunnen het gedrag voor LangVersion <= 11 afwijken van het gedrag voor oudere compilerversies. Het kan bijvoorbeeld een fout zijn wanneer een ref readonly parameter wordt aangeroepen (zelfs wanneer u de ref wijzigingsfunctie op de aanroepite gebruikt), of het kan altijd zonder fouten worden toegestaan.

Ingrijpende wijzigingen

Dit voorstel stelt voor om een gedragsveranderende wijziging te accepteren, omdat dit zelden voorkomt, wordt beheerst door LangVersion, en gebruikers het probleem kunnen omzeilen door de extensiemethode expliciet aan te roepen. In plaats daarvan kunnen we dit beperken door

  • het niet toestaan van de ref/in mismatch (waardoor migratie naar in wordt voorkomen voor oude API's die ref gebruikten omdat in nog niet beschikbaar was),
  • het wijzigen van de regels voor het oplossen van overbelasting om door te gaan met zoeken naar een betere overeenkomst (vastgesteld door de hieronder gespecificeerde verbeteringsregels) wanneer er een mismatch in referentietypen is zoals voorgesteld,
    • of u kunt ook doorgaan alleen voor het niet overeenkomen van ref versus in, maar niet voor de andere (ref readonly versus ref/in/per-waarde).
Beterschap heerst

Het volgende voorbeeld resulteert momenteel in drie dubbelzinnigheidsfouten voor de drie aanroepen van M. We kunnen nieuwe beterheidsregels toevoegen om de dubbelzinnigheden op te lossen. Hiermee wordt ook de eerder beschreven onderbrekende wijziging opgelost. Een manier is om het voorbeeld van 221 af te drukken (waarbij ref readonly parameter overeenkomt met in argument, omdat het een waarschuwing zou zijn om het zonder wijziging aan te roepen, terwijl voor in parameter die is toegestaan).

interface I1 { }
interface I2 { }
class C
{
    static string M(I1 o, in int i) => "1";
    static string M(I2 o, ref readonly int i) => "2";
    static void Main()
    {
        int i = 5;
        System.Console.Write(M(null, ref i));
        System.Console.Write(M(null, in i));
        System.Console.Write(M(null, i));
    }
}

Nieuwe regels voor betere prestaties kunnen een parameter als slechter markeren als het argument ervan had kunnen worden doorgegeven met een ander argumentmodifier om het beter te maken. Met andere woorden, de gebruiker moet altijd in staat zijn om een slechtere parameter om te zetten in een betere parameter door de bijbehorende argumentaanpassing te wijzigen. Wanneer een argument bijvoorbeeld wordt doorgegeven door in, heeft een ref readonly parameter de voorkeur boven een in parameter, omdat de gebruiker het argument per waarde kan doorgeven om de parameter in te kiezen. Deze regel is slechts een uitbreiding van de by-value/in voorkeursregel die momenteel van kracht is (dit is de laatste overbelastingsoplossingsregel en de hele overbelasting is beter als een van de parameters beter is en geen is slechter dan de bijbehorende parameter van een andere overbelasting).

ruzie betere parameter slechtere parameter
ref/in ref readonly in
ref ref ref readonly/in
door waarde door-waarde/in ref readonly
in in ref

We moeten methodeconversies op dezelfde manier verwerken. Het volgende voorbeeld resulteert momenteel in twee dubbelzinnigheidsfouten voor de twee gedelegeerdentoewijzingen. Nieuwe voorkeursregels kunnen de voorkeur geven aan een methodeparameter waarvan de referentie-modificator overeenkomt met de overeenkomstige referentie-modificator van de doeldelegatieparameter boven een parameter waarbij dit niet het geval is. Daarom wordt in het volgende voorbeeld 12afgedrukt.

class C
{
    void M(I1 o, ref readonly int x) => System.Console.Write("1");
    void M(I2 o, ref int x) => System.Console.Write("2");
    void Run()
    {
        D1 m1 = this.M;
        D2 m2 = this.M; // currently ambiguous

        var i = 5;
        m1(null, in i);
        m2(null, ref i);
    }
    static void Main() => new C().Run();
}
interface I1 { }
interface I2 { }
class X : I1, I2 { }
delegate void D1(X s, ref readonly int x);
delegate void D2(X s, ref int x);

Ontwerpvergaderingen