Wat is het verschil tussen const en alleen-lezen in C#?

Wat is het verschil tussen consten readonlyin C#?

Wanneer zou je de een boven de ander gebruiken?


Antwoord 1, autoriteit 100%

Behalve het schijnbare verschil van

  • de waarde moeten declareren op het moment van een definitie voor een constVS readonlywaarden kunnen dynamisch worden berekend, maar moeten worden toegewezen voordat de constructor afsluit.. na dat het bevroren is.
  • const‘s zijn impliciet static. U gebruikt de notatie ClassName.ConstantNameom ze te openen.

Er is een subtiel verschil. Overweeg een klasse gedefinieerd in AssemblyA.

public class Const_V_Readonly
{
  public const int I_CONST_VALUE = 2;
  public readonly int I_RO_VALUE;
  public Const_V_Readonly()
  {
     I_RO_VALUE = 3;
  }
}

AssemblyBverwijst naar AssemblyAen gebruikt deze waarden in code. Wanneer dit is gecompileerd:

  • in het geval van de waarde constis het als een zoek-vervanging. De waarde 2 is ‘ingebakken’ in de IL van de AssemblyB. Dit betekent dat als ik morgen I_CONST_VALUEupdate naar 20, AssemblyBer nog 2 heeft totdat ik het opnieuw compileer.
  • in het geval van de waarde readonlyis het als een refnaar een geheugenlocatie. De waarde is niet ingebakken in de IL van AssemblyB. Dit betekent dat als de geheugenlocatie wordt bijgewerkt, AssemblyBde nieuwe waarde krijgt zonder opnieuw te compileren. Dus als I_RO_VALUEis bijgewerkt naar 30, hoeft u alleen AssemblyAte bouwen en hoeven niet alle clients opnieuw te worden gecompileerd.

Dus als je er zeker van bent dat de waarde van de constante niet zal veranderen, gebruik dan een const.

public const int CM_IN_A_METER = 100;

Maar als je een constante hebt die kan veranderen (bijv. w.r.t. precisie).. of als je twijfelt, gebruik dan een readonly.

public readonly float PI = 3.14;

Update: Aku moet een vermelding krijgen omdat hij hier eerst op wees. Ik moet ook aansluiten waar ik dit heb geleerd: Effectieve C# – Bill Wagner


Antwoord 2, autoriteit 21%

Er is een probleem met consts! Als u verwijst naar een constante van een andere assembly, wordt de waarde ervan rechtstreeks in de aanroepende assembly gecompileerd. Op die manier, wanneer u de constante in de assembly waarnaar wordt verwezen bijwerkt, verandert deze niet in de aanroepende assembly!


Antwoord 3, autoriteit 12%

Constanten

  • Constanten zijn standaard statisch
  • Ze moeten een waarde hebben op het moment van compilatie (je kunt bijvoorbeeld 3.14 * 2 hebben, maar kan geen methoden aanroepen)
  • Kan worden gedeclareerd binnen functies
  • Worden gekopieerd naar elke assembly die ze gebruikt (elke assembly krijgt een lokale kopie van waarden)
  • Kan worden gebruikt in attributen

Alleen-lezen instantievelden

  • Moet een ingestelde waarde hebben tegen de tijd dat de constructor afsluit
  • Worden geëvalueerd wanneer instantie wordt gemaakt

Statische alleen-lezen velden

  • Worden geëvalueerd wanneer code-uitvoering klassereferentie bereikt (wanneer een nieuwe instantie wordt gemaakt of een statische methode wordt uitgevoerd)
  • Moet een geëvalueerde waarde hebben tegen de tijd dat de statische constructor klaar is
  • Het wordt niet aanbevolen om ThreadStaticAttribute hierop te plaatsen (statische constructors worden alleen in één thread uitgevoerd en stellen de waarde voor de bijbehorende thread in; alle andere threads hebben deze waarde niet-geïnitialiseerd)

Antwoord 4, autoriteit 5%

Alleen om toe te voegen: readonlyvoor referentietypes zorgt ervoor dat de referentie alleen wordt gelezen en niet de waarden. Bijvoorbeeld:

public class Const_V_Readonly
{
  public const int I_CONST_VALUE = 2;
  public readonly char[] I_RO_VALUE = new Char[]{'a', 'b', 'c'};
  public UpdateReadonly()
  {
     I_RO_VALUE[0] = 'V'; //perfectly legal and will update the value
     I_RO_VALUE = new char[]{'V'}; //will cause compiler error
  }
}

Antwoord 5, autoriteit 3%

Dit verklaart het. Samenvatting: const moet worden geïnitialiseerd tijdens declaratie, alleen-lezen kan worden geïnitialiseerd op de constructor (en kan dus een andere waarde hebben, afhankelijk van de gebruikte constructor).

EDIT: Zie Gishu’s gotcha hierboven voor het subtiele verschil


Antwoord 6, autoriteit 3%

const: kan nergens worden gewijzigd.

readonly: deze waarde kan alleen in de constructor worden gewijzigd. Kan niet worden gewijzigd in normale functies.


Antwoord 7, autoriteit 3%

Een constant lid wordt gedefinieerd tijdens het compileren en kan niet tijdens runtime worden gewijzigd. Constanten worden gedeclareerd als een veld, met behulp van het trefwoord consten moeten worden geïnitialiseerd zoals ze worden gedeclareerd.

public class MyClass
{
    public const double PI1 = 3.14159;
}

Een readonlylid is als een constante in die zin dat het een onveranderlijke waarde vertegenwoordigt. Het verschil is dat een readonly-lid tijdens runtime kan worden geïnitialiseerd, in een constructor, en ook kan worden geïnitialiseerd zoals ze worden gedeclareerd.

public class MyClass1
{
     public readonly double PI2 = 3.14159;
     //or
     public readonly double PI3;
     public MyClass2()
     {
         PI3 = 3.14159;
     }
}

const

  • Ze kunnen niet worden gedeclareerd als static(ze zijn impliciet statisch)
  • De waarde van constante wordt geëvalueerd tijdens het compileren
  • constanten worden alleen geïnitialiseerd bij declaratie

alleen-lezen

  • Ze kunnen op instantieniveau of statisch zijn
  • De waarde wordt tijdens runtime geëvalueerd
  • alleen-lezen kan worden geïnitialiseerd in declaratie of door code in de constructor

Antwoord 8, autoriteit 2%

Er is een kleine fout met alleen-lezen. Een alleen-lezen veld kan meerdere keren worden ingesteld binnen de constructor(s). Zelfs als de waarde is ingesteld in twee verschillende geketende constructors, is het nog steeds toegestaan.

public class Sample {
    private readonly string ro;
    public Sample() {
        ro = "set";
    }
    public Sample(string value) : this() {
        ro = value; // this works even though it was set in the no-arg ctor
    }
}

Antwoord 9, autoriteit 2%

Een const is een constante tijdens het compileren, terwijl alleen-lezen het mogelijk maakt om tijdens runtime een waarde te berekenen en in de constructor of veldinitiator in te stellen. Een ‘const’ is dus altijd constant, maar ‘alleen-lezen’ is alleen-lezen als het eenmaal is toegewezen.

Eric Lippert van het C#-team heeft meer informatieover verschillende soorten onveranderlijkheid.


Antwoord 10

Hier is nog een linkdie laat zien hoe const dat niet is versie veilig, of relevant voor referentietypes.

Samenvatting:

  • De waarde van uw const-eigenschap wordt ingesteld tijdens het compileren en kan tijdens runtime niet worden gewijzigd
  • Const kan niet als statisch worden gemarkeerd – het sleutelwoord geeft aan dat ze statisch zijn, in tegenstelling tot alleen-lezen velden die dat wel kunnen.
  • Const kan niets anders zijn dan waarde (primitieve) typen
  • Het alleen-lezen trefwoord markeert het veld als onveranderlijk. De eigenschap kan echter worden gewijzigd binnen de constructor van de klasse
  • Het alleen-lezen trefwoord kan ook worden gecombineerd met static om het op dezelfde manier te laten werken als een const (tenminste aan de oppervlakte). Er is een duidelijk verschil als je naar de IL kijkt tussen de twee
  • const-velden zijn gemarkeerd als “letterlijk” in IL, terwijl alleen-lezen “initieel” is

Antwoord 11

Alleen-lezen:
De waarde kan tijdens runtime worden gewijzigd via Ctor. Maar niet via ledenfunctie

Constante:
Standaard statisch. Waarde kan nergens worden gewijzigd (Ctor, Function, runtime enz. Nergens)


Antwoord 12

Nog een probleem: alleen-lezen waarden kunnen worden gewijzigd door “sluwe” code via reflectie.

var fi = this.GetType()
             .BaseType
             .GetField("_someField", 
                       BindingFlags.Instance | BindingFlags.NonPublic);
fi.SetValue(this, 1);

Kan Ik verander een persoonlijk alleen-lezen overgenomen veld in C# met reflectie?


Antwoord 13

Ik geloof dat een const-waarde hetzelfde is voor alle objecten (en moet worden geïnitialiseerd met een letterlijke uitdrukking), terwijl readonlyvoor elke instantie anders kan zijn…


Antwoord 14

Ze zijn beide constant, maar er is ook een const beschikbaar tijdens het compileren. Dit betekent dat een aspect van het verschil is dat u const-variabelen kunt gebruiken als invoer voor attribuutconstructors, maar niet alleen-lezenvariabelen.

Voorbeeld:

public static class Text {
  public const string ConstDescription = "This can be used.";
  public readonly static string ReadonlyDescription = "Cannot be used.";
}
public class Foo 
{
  [Description(Text.ConstDescription)]
  public int BarThatBuilds {
    { get; set; }
  }
  [Description(Text.ReadOnlyDescription)]
  public int BarThatDoesNotBuild {
    { get; set; }
  }
}

Antwoord 15

Een van de teamleden op ons kantoor heeft de volgende richtlijnen gegeven over het gebruik van const, static en readonly:

  • Gebruik constwanneer je een variabele hebt van een type dat je tijdens runtime kunt kennen (letterlijke tekenreeks, int, double, enums,…) waarvan je wilt dat alle instanties of consumenten van een klasse toegang hebben tot waar de waarde niet mag veranderen.
  • Gebruik statischwanneer u gegevens heeft waarvan u wilt dat alle instanties of consumenten van een klasse toegang hebben tot waar de waarde kan veranderen.
  • Gebruik statische alleen-lezenwanneer u een variabele hebt van een type dat u tijdens runtime niet kunt weten (objecten) waarvan u wilt dat alle instanties of consumenten van een klasse toegang hebben tot waar de waarde niet mag veranderen .
  • Gebruik alleen-lezenwanneer u een variabele op instantieniveau heeft waarvan u op het moment van het maken van het object weet dat deze niet zou moeten veranderen.

Nog een laatste opmerking: een const-veld is statisch, maar het omgekeerde is niet waar.


Antwoord 16

CONST

  1. const trefwoord kan worden toegepast op velden of lokale variabelen
  2. We moeten het veld const toewijzen op het moment van aangifte
  3. Geen geheugen toegewezen omdat de const-waarde is ingebed in IL-code zelf na compilatie.
    Het is alsof je alle exemplaren van de variabele const zoekt en vervangt door de waarde ervan.
    Dus de IL-code na compilatie zal hardgecodeerde waarden hebben in plaats van const-variabelen
  4. Const in C# is standaard statisch.
  5. De waarde is constant voor alle objecten
  6. Er is een dll-versieprobleem – Dit betekent dat wanneer we een openbare const-variabele of -eigenschap wijzigen (in feite is het niet de bedoeling dat dit theoretisch wordt gewijzigd), elke andere dll of assembly die deze variabele gebruikt, opnieuw moet worden gebouwd
  7. Alleen ingebouwde C#-typen kunnen als constant worden gedeclareerd
  8. Const veld kan niet worden doorgegeven als ref of out parameter

Alleen-lezen

  1. alleen-lezen trefwoord is alleen van toepassing op velden, niet op lokale variabelen
  2. We kunnen alleen-lezen veld toewijzen op het moment van declaratie of in de constructor, niet in andere methoden.
  3. dynamisch geheugen toegewezen voor alleen-lezen velden en we kunnen de waarde tijdens runtime krijgen.
  4. Alleen-lezen behoort tot het object dat zo is gemaakt dat het alleen toegankelijk is via een instantie van een klasse. Om het klasselid te maken, moeten we een statisch trefwoord toevoegen voordat het alleen-lezen is.
  5. De waarde kan verschillen, afhankelijk van de gebruikte constructor (omdat deze bij het object van de klasse hoort)
  6. Als u een niet-primitief type (referentietype) als alleen-lezen declareert, is de referentie onveranderlijk en niet het object dat het bevat.
  7. Aangezien de waarde tijdens runtime wordt verkregen, is er geen dll-versieprobleem met alleen-lezen velden/eigenschappen.
  8. We kunnen het alleen-lezen veld doorgeven als ref- of out-parameters in de constructorcontext.

Antwoord 17

  • wanneer constof readonly

    te gebruiken

    • const

      • compilatietijdconstante: absoluteconstante, waarde wordt ingesteld tijdens declaratie, staat in de IL-code zelf
    • readonly

      • runtimeconstante: kan worden ingesteld in de constructor/init via het configuratiebestand, bijv. App.config, maar als het eenmaal is geïnitialiseerd, kan het niet meer worden gewijzigd

Antwoord 18

Variabelen die gemarkeerd zijn als const zijn weinig meer dan sterk getypte #define macro’s, tijdens het compileren worden de verwijzingen naar const-variabelen vervangen door inline letterlijke waarden. Als gevolg hiervan kunnen alleen bepaalde ingebouwde primitieve waardetypen op deze manier worden gebruikt. Variabelen die zijn gemarkeerd als alleen-lezen kunnen in een constructor tijdens runtime worden ingesteld en hun alleen-lezen-heid wordt ook tijdens runtime afgedwongen. Hieraan zijn enkele kleine prestatiekosten verbonden, maar het betekent dat u alleen-lezen kunt gebruiken met elk type (zelfs referentietypen).

Bovendien zijn const-variabelen inherent statisch, terwijl alleen-lezen variabelen indien gewenst instantiespecifiek kunnen zijn.


Antwoord 19

Er is een opmerkelijk verschil tussen de velden const en alleen-lezen in C#.Net

const is standaard statisch en moet worden geïnitialiseerd met een constante waarde, die later niet kan worden gewijzigd. Verandering van waarde is ook niet toegestaan in constructors. Het kan niet met alle datatypes worden gebruikt. Voor ex-DateTime. Het kan niet worden gebruikt met het datatype DateTime.

public const DateTime dt = DateTime.Today;  //throws compilation error
public const string Name = string.Empty;    //throws compilation error
public readonly string Name = string.Empty; //No error, legal

alleen-lezen kan als statisch worden gedeclareerd, maar is niet noodzakelijk. U hoeft niet te initialiseren op het moment van aangifte. De waarde ervan kan worden toegewezen of gewijzigd met behulp van constructor. Het geeft dus voordeel bij gebruik als instantieklasselid. Twee verschillende instanties kunnen een verschillende waarde van het alleen-lezen veld hebben. Bijvoorbeeld –

class A
{
    public readonly int Id;
    public A(int i)
    {
        Id = i;
    }
}

Vervolgens kan het alleen-lezen veld worden geïnitialiseerd met directe specifieke waarden, als volgt:

A objOne = new A(5);
A objTwo = new A(10);

Hier heeft instantie objOne de waarde van het alleen-lezen veld als 5 en objTwo heeft 10. Wat niet mogelijk is met const.


Antwoord 20

Nog een gok.

Aangezien const eigenlijk alleen werkt met basisgegevenstypen, voelt u zich misschien “gedwongen” om ReadOnly te gebruiken als u met een klasse wilt werken. Pas echter op voor de val! ReadOnly betekent dat je het object niet kunt vervangen door een ander object (je kunt het niet laten verwijzen naar een ander object). Maar elk proces dat een verwijzing naar het object heeft, is vrij om de waarden binnenhet object te wijzigen!

Laat u dus niet in de war brengen door te denken dat ReadOnly impliceert dat een gebruiker dingen niet kan veranderen. Er is geen eenvoudige syntaxis in C# om te voorkomen dat de interne waarden van een instantie van een klasse worden gewijzigd (voor zover ik weet).


Antwoord 21

Een constmoet hard-codedzijn, waarbij als readonlyingesteld kan worden in de constructorvan de klas.


Antwoord 22

Een constante wordt in de consument gecompileerd als een letterlijke waarde, terwijl de statische tekenreeks zal dienen als een verwijzing naar de gedefinieerde waarde.

Probeer als oefening een externe bibliotheek te maken en deze in een consoletoepassing te gebruiken, wijzig vervolgens de waarden in de bibliotheek en compileer deze opnieuw (zonder het consumentenprogramma opnieuw te compileren), zet de DLL in de map en voer de EXE handmatig uit, je zou moeten ontdekken dat de constante string niet verandert.


Antwoord 23

Const en alleen-lezen zijn vergelijkbaar, maar ze zijn niet precies hetzelfde. Een const-veld is een constante tijdens het compileren, wat betekent dat die waarde tijdens het compileren kan worden berekend. Een alleen-lezen veld maakt aanvullende scenario’s mogelijk waarin enige code moet worden uitgevoerd tijdens de constructie van het type. Na de constructie kan een alleen-lezen veld niet worden gewijzigd.

Const-leden kunnen bijvoorbeeld worden gebruikt om leden te definiëren, zoals:

struct Test
{
    public const double Pi = 3.14;
    public const int Zero = 0;
}

aangezien waarden zoals 3.14 en 0 compile-time constanten zijn. Overweeg echter het geval waarin u een type definieert en er enkele prefab-exemplaren van wilt leveren. U wilt bijvoorbeeld een kleurklasse definiëren en “constanten” opgeven voor veelvoorkomende kleuren zoals zwart, wit, enz. Het is niet mogelijk om dit te doen met const-leden, omdat de rechterkant geen compilatietijdconstanten zijn. Je zou dit kunnen doen met gewone statische leden:

public class Color
{
    public static Color Black = new Color(0, 0, 0);
    public static Color White = new Color(255, 255, 255);
    public static Color Red = new Color(255, 0, 0);
    public static Color Green = new Color(0, 255, 0);
    public static Color Blue = new Color(0, 0, 255);
    private byte red, green, blue;
    public Color(byte r, byte g, byte b) {
        red = r;
        green = g;
        blue = b;
    }
}

maar dan is er niets dat een klant van Color ervan weerhoudt ermee te rotzooien, misschien door de zwart-witwaarden om te wisselen. Onnodig te zeggen dat dit consternatie zou veroorzaken bij andere klanten van de Color-klasse. De “alleen-lezen”-functie lost dit scenario op. Door simpelweg het readonly-sleutelwoord in de declaraties te introduceren, behouden we de flexibele initialisatie en voorkomen we dat klantcode rondscharrelt.

public class Color
{
    public static readonly Color Black = new Color(0, 0, 0);
    public static readonly Color White = new Color(255, 255, 255);
    public static readonly Color Red = new Color(255, 0, 0);
    public static readonly Color Green = new Color(0, 255, 0);
    public static readonly Color Blue = new Color(0, 0, 255);
    private byte red, green, blue;
    public Color(byte r, byte g, byte b) {
        red = r;
        green = g;
        blue = b;
    }
}

Het is interessant op te merken dat const-leden altijd statisch zijn, terwijl een alleen-lezen lid statisch kan zijn of niet, net als een gewoon veld.

Het is mogelijk om één sleutelwoord voor deze twee doeleinden te gebruiken, maar dit leidt tot versieproblemen of prestatieproblemen. Neem even aan dat we hiervoor een enkel trefwoord (const) hebben gebruikt en een ontwikkelaar schreef:

public class A
{
    public static const C = 0;
}

en een andere ontwikkelaar schreven code die gebaseerd was op A:

public class B
{
    static void Main() {
        Console.WriteLine(A.C);
    }
}

Kan de gegenereerde code nu vertrouwen op het feit dat A.C een constante bij het compileren is? Dat wil zeggen, kan het gebruik van A.C eenvoudig worden vervangen door de waarde 0? Als je hier “ja” op zegt, dan betekent dat dat de ontwikkelaar van A de manier waarop A.C wordt geïnitialiseerd niet kan veranderen — dit bindt de handen van de ontwikkelaar van A zonder toestemming. Zeg je ‘nee’ op deze vraag dan wordt een belangrijke optimalisatie gemist. Misschien is de auteur van A er zeker van dat A.C altijd nul zal zijn. Het gebruik van zowel const als readonly stelt de ontwikkelaar van A in staat om de intentie te specificeren. Dit zorgt voor een beter versiebeheer en ook voor betere prestaties.


Antwoord 24

Alleen-lezen: de waarde wordt slechts eenmaal geïnitialiseerd door de constructor van de klasse.
const: kan in elke functie worden geïnitialiseerd, maar slechts één keer


Antwoord 25

Het verschil is dat de waarde van een statisch alleen-lezen veld tijdens runtime wordt ingesteld, dus het kan een andere waarde hebben voor verschillende uitvoeringen van het programma. De waarde van een const-veld is echter ingesteld op een compileertijdconstante.

Onthoud:
Voor referentietypen, in beide gevallen (statisch en instantie), voorkomt de alleen-lezen-modifier alleen dat u een nieuwe verwijzing aan het veld toewijst. Het maakt het object waarnaar door de referentie wordt verwezen niet onveranderlijk.

Raadpleeg voor meer informatie de veelgestelde vragen van C# over dit onderwerp:
http://blogs.msdn.com/csharpfaq/archive/2004 /12/03/274791.aspx


Antwoord 26

Constante variabelen worden tijdens het compileren gedeclareerd en geïnitialiseerd. De waarde kan niet worden gewijzigd na afdelingen. Alleen-lezen variabelen worden alleen geïnitialiseerd vanuit de statische constructor van de klasse. Alleen-lezen wordt alleen gebruikt als we de waarde tijdens runtime willen toewijzen.


Antwoord 27

Voornamelijk; u kunt tijdens runtime een waarde toewijzen aan een statisch alleen-lezen veld aan een niet-constante waarde, terwijl aan een const een constante waarde moet worden toegewezen.


Antwoord 28

Eén ding om toe te voegen aan wat mensen hierboven hebben gezegd. Als u een assembly heeft met een alleen-lezen waarde (bijv. alleen-lezen MaxFooCount = 4; ), kunt u de waarde wijzigen die aanroepende assembly’s zien door een nieuwe versie van die assembly met een andere waarde te verzenden (bijv. alleen-lezen MaxFooCount = 5;)

Maar met een const zou het in de code van de beller worden gevouwen wanneer de beller werd gecompileerd.

Als je dit niveau van C#-vaardigheid hebt bereikt, ben je klaar voor het boek van Bill Wagner, Effective C#: 50 Specific Ways to Improve Your C#
Die deze vraag in detail beantwoordt (en 49 andere dingen).


Antwoord 29

Het belangrijkste verschil is dat Const het C-equivalent is van #DEFINE. Het nummer wordt letterlijk vervangen door een precompiler. Alleen-lezen wordt eigenlijk behandeld als een variabele.

Dit onderscheid is met name relevant wanneer u project A hebt, afhankelijk van een openbaar constant van project B. Stel dat de openbare constante veranderingen. Nu zal uw keuze van const / readonly invloed hebben op het gedrag op project A:

SB: Project A vangt de nieuwe waarde niet (tenzij deze natuurlijk wordt gecompileerd met de nieuwe const, omdat het met de constanten is samengesteld.

Readonly: Project A zal altijd Project B vragen B voor de variabele waarde, dus het zal de nieuwe waarde van het openbaar constant in b.

Eerlijk gezegd, ik zou aanraden u opnieuw te gebruiken voor bijna alles behalve echt universele constanten (bijvoorbeeld PI, inches_to_centimeters). Voor alles wat mogelijk kan veranderen, zeg ik readonly.

Ik hoop dat dit helpt,
Alan.


ANTWOORD 30

const : absolute constante waarde tijdens de levensduur van de toepassing.

readonly : het kan in de looptijd worden gewijzigd.

Other episodes