Koks skirtumas tarp pastovaus ir tik skaitomo?

Koks yra skirtumas tarp „ const ir „ readonly , ir jūs naudojate vieną iš kitų?

1095
11 сент. Skaityta tik rugsėjo 11 d 2008-09-11 11:02 '08 at 11:02 2008-09-11 11:02
@ 33 atsakymai
  • 1
  • 2

Be akivaizdaus skirtumo

  • norėdami deklaruoti reikšmę, apibrėžiant const VS readonly reikšmes, galite ją dinamiškai apskaičiuoti, bet jūs turite juos priskirti prieš konstruktoriaus išėjimą .. po to jis yra užšaldytas.
  • „const“ yra netiesiogiai static . Jei norite juos pasiekti, naudojamas ClassName.ConstantName žymėjimas.

Yra subtilus skirtumas. Apsvarstykite „ AssemblyA apibrėžtą klasę.

 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; } } 

AssemblyB jungia AssemblyA ir naudokite šias reikšmes kode. Kai jis yra sudarytas,

  • konstatavimo reikšmės atveju, tai yra panaši į paieškos pakeitimą, vertė 2 yra „kepama“ AssemblyB IL. Tai reiškia, kad jei rytoj ateityje atnaujinsiu I_CONST_VALUE iki 20. AssemblyB vis dar turės 2, kol aš jį perskaičiuosiu.
  • readonly vertės atveju, jis atrodo kaip atmintis atminties ląstelėje. Ši vertė nėra kepama AssemblyB IL. Tai reiškia, kad, jei atminties vieta yra atnaujinama, AssemblyB gauna naują vertę be recompiling. Todėl, jei I_RO_VALUE atnaujintas iki 30, turite sukurti „ AssemblyA . Visiems klientams nereikia perrašyti.

Taigi, jei esate tikri, kad pastoviosios vertės vertė nepasikeičia, naudokite const .

 public const int CM_IN_A_METER = 100; 

Bet jei turite pastovią, kuri gali keistis (pvz., Tikslumas) .. arba jei turite abejonių, naudokite readonly .

 public readonly float PI = 3.14; 

Atnaujinimas: Aku turi paminėti tai, kad jis pirmiausia nurodė tai. Taip pat turiu prisijungti, kur aš sužinojau. Efektyvus C # - Bill Wagner

1067
11 сент. Gishu atsakymas 11 rugsėjis 2008-09-11 11:24 '08 at 11:24 am 2008-09-11 11:24

Gotcha su pamokomis! Jei nurodote konstantą iš kitos surinkimo, jo vertė bus sukompiliuota tiesiai į skambinančiąją įrangą. Taigi, kai atnaujinate konstantą etaloniniame rinkinyje, jis nekeičia skambinančiojo mazgo!

247
11 сент. atsakymą pateikė „ aku 11 sep“. 2008-09-11 11:15 '08 11:15 am. 2008-09-11 11:15

Konstansai

  • Numatytosios konstantos yra statinės.
  • Jie turi turėti vertę kompiliavimo metu (galite turėti, pvz., 3.14 * 2, bet negalite skambinti metodais)
  • Gali būti paskelbta viduje
  • Kopijuojama į kiekvieną jungtį, kuri juos naudoja (kiekviena sąranka gauna vietinę vertybių kopiją)
  • Galima naudoti atributuose

Skaitymo atvejų laukai

  • Reikšmė turi būti nustatyta po konstruktoriaus laiko
  • Vertinamas kuriant pavyzdį

Skaitytinai statiniai laukai

  • Vertinama, kai kodų vykdymas pasiekia klasės nuorodą (kai sukuriamas naujas egzempliorius arba atliekamas statinis metodas)
  • Turi būti apskaičiuota vertė iki statinio konstruktoriaus pabaigos.
  • Nerekomenduojama įdėti ThreadStaticAttribute į šias vietas (statiniai konstruktoriai bus vykdomi tik vienoje siūloje ir nustatys jo siūlų vertę; visos kitos temos turės šią reikšmę neįvertinta)
134
02 дек. Atsakymas duotas splattne 02 Dec. 2008-12-02 14:50 '08 at 2:50 pm 2008-12-02 14:50

Tiesiog pridėkite, „ReadOnly“ tik nuorodų tipams nurodo tik skaitymą, o ne vertes. Pavyzdžiui:

 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 } } 
51
11 сент. atsakymą pateikė vartotojo1333 11 sep . 2008-09-11 13:37 '08, 13:37 pm 2008-09-11 13:37

Tai paaiškina . Santrauka: deklaracija turi būti inicijuota, tik konstruktorius gali jį inicijuoti (ir todėl turi skirtingą reikšmę, priklausomai nuo naudojamo konstruktoriaus).

EDIT: žr. Gishu gotcha aukščiau, kad gautumėte puikų skirtumą

36
11 сент. Atsakymą pateikė Vinko Vrsalovic rugsėjo 11 d 2008-09-11 11:04 '08 at 11:04 2008-09-11 11:04

const : neįmanoma keisti bet kur.

readonly : šią vertę galima keisti tik konstruktoriuje. Negalima keisti įprastomis funkcijomis.

27
21 мая '11 в 16:21 2011-05-21 16:21 atsakymą pateikė Deepthi gegužės 21 d., 11 val. 21:21 . 2011-05-21 16:21

Yra šiek tiek magija su skaitymu. Konstruktoriaus (-ų) viduje gali būti kelis kartus nustatomas tik laukas. Net jei ši vertė nurodyta dviejuose skirtinguose grandinės konstruktoriuose, ji vis tiek leidžiama.

 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 } } 
23
20 окт. Mike Two paskelbė spalio 20 d 2008-10-20 01:14 '08 ne 1:14 2008-10-20 01:14

Nuolatinis narys apibrėžiamas kompiliavimo metu ir negali būti keičiamas vykdymo metu. Konstantai yra deklaruojami kaip laukas, naudojant raktinį žodį ir turi būti inicijuoti, kaip jie yra deklaruojami.

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

readonly kaip nuolatinis narys, kuris reiškia pastovią vertę. Skirtumas yra tas, kad readonly elementas gali būti inicijuotas vykdymo metu, konstruktoriuje ir taip pat gali būti inicijuotas, kai jie yra deklaruojami.

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

Const

  • Jie negali būti paskelbti static (jie yra netiesiogiai statiniai)
  • Konstantos vertė vertinama kompiliavimo metu.
  • konstantos inicijuojamos tik deklaravus

tik skaityti

  • Jie gali būti instancijos lygiu arba statiniu lygmeniu.
  • Vertė įvertinama vykdymo metu.
  • galima tik inicijuoti deklaracijoje arba pagal konstruktoriaus kodą.
21
17 сент. Sujit atsakymas, pateiktas rugsėjo 17 d. 2012-09-17 14:48 '12, 12:48 PM 2012-09-17 14:48

A const yra kompiliavimo laiko konstanta, o skaitoma tik leidžia apskaičiuoti vertę vykdymo metu ir nustatyti konstruktoriuje arba lauko iniciatoriuje. Tokiu būdu pastovus const visada yra pastovus, bet „tik skaityti“ galima tik skaityti po jo priskyrimo.

Ericas Lippertas iš C # komandos turi daugiau informacijos apie skirtingus nekintamumo tipus.

19
11 сент. Atsakymą pateikė Wheelie 11 Sep. 2008-09-11 11:07 '08 at 11:07 2008-09-11 11:07

Čia yra dar viena nuoroda, rodanti, kaip const nėra saugi versija arba svarbi nuorodų tipams.

Santrauka :

  • Jūsų const savybės vertė nustatoma kompiliavimo metu ir negali keistis paleidimo metu.
  • Nuolatinis žymuo negali būti pažymėtas kaip statinis - raktinis žodis rodo, kad jie yra statiniai, skirtingai nei tik skaitomuose laukuose.
  • Const gali būti tik (primityvių) tipų vertybės
  • Tik skaitomas raktinis žodis žymi lauką kaip nepakeistą. Tačiau turtas gali būti pakeistas klasės konstruktoriaus viduje.
  • Tik skaitomas raktinis žodis taip pat gali būti derinamas su statiniu, kad jis veiktų kaip const (bent jau ant paviršiaus). Yra pastebimas skirtumas, kai žiūrite į IL tarp dviejų
  • pastovūs laukai yra pažymėti „literal“ IL, ir skaitomi tik „initonly“,
14
31 янв. Atsakymą pateikė Chris S sausio 31 d. 2009-01-31 14:42 '09 ne 14:42 2009-01-31 14:42

Kita vertė: skaitomos vertės gali būti pakeistos naudojant „gudrus“ kodą per atspindį.

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

Ar galiu keisti privačią sritį, paveldėtą tik skaitomą C, naudojant refleksiją?

8
13 окт. atsakymas, kurį pateikė Greg, spalio 13 d. 2009-10-13 05:26 '09 5:26 am 2009-10-13 05:26

Tik skaityti : vertė gali būti pakeista naudojant „Ctor“ vykdymo metu. Bet ne per nario funkciją

Pastovus : statinis defektas. Vertė negali būti keičiama niekur (Ctor, Function, runtime ir tt)

8
12 янв. atsakymas duotas Yeasin Abedin Siam sausio 12 d 2016-01-12 20:42 '16 at 8:42 pm 2016-01-12 20:42

Manau, kad const . Vertė yra vienoda visiems objektams (ir turėtų būti inicijuojama gramatine išraiška), tuo tarpu readonly gali būti skirtingas kiekvienu atveju ...

6
11 сент. Atsakymas duotas Daren Thomas 11 sep. 2008-09-11 11:03 '08 at 11:03 2008-09-11 11:03

Vienas iš mūsų biuro komandos narių pateikė šias gaires, kada naudoti const, static ir readonly:

  • Naudokite const, kai turite tipo kintamąjį, kurį galite žinoti vykdymo metu (string literal, int, double, enums, ...), kad norite, kad visi egzemplioriai ar klasės vartotojai turėtų prieigą prie to, kur vertė nėra turėtų pasikeisti.
  • Naudokite statinį, kai turite duomenų, kuriuos norite, kad visos klasės ar vartotojų grupės turėtų prieigą prie vietos, kur vertė gali pasikeisti.
  • Naudokite statinį skaitymą, kai turite kintamąjį, kurio negalite žinoti vykdymo (objektų) metu, kai norite, kad visos klasės ar naudotojų grupės galėtų pasiekti, kur vertė neturėtų pasikeisti.
  • Naudokite skaitymą, kai turite egzemplioriaus lygio kintamąjį, kurį žinosite kurdami objektą, kuris neturėtų keistis.

Galutinė pastaba: pastovus laukas yra statinis, tačiau inversija yra neteisinga.

5
02 окт. Atsakymą pateikė Scott Lawrence 02 okt. 2008-10-02 23:43 '08, 23:43 2008-10-02 23:43

Jie abu yra pastovūs, bet konstanta taip pat prieinama kompiliavimo metu. Tai reiškia, kad vienas skirtumo aspektas yra tas, kad galite naudoti pastovius kintamuosius kaip įvestį konstruktorių atributui, bet ne tik kintamiesiems.

Pavyzdys:

 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; } } } 
5
17 сент. Atsakymą įteikė Hallgrim 17 sep . 2008-09-17 16:02 '08 at 4:02 pm 2008-09-17 16:02

Tik raktinis žodis skiriasi nuo const raktinio žodžio. Pastovus laukas gali būti inicijuotas tik tada, kai laukas yra deklaruojamas. Skaitymo laukas gali būti inicijuotas deklaracijoje arba konstruktoriuje. Todėl tik skaitomi laukai gali turėti skirtingas reikšmes, priklausomai nuo naudojamo konstruktoriaus. Be to, nors pastovus laukas yra kompiliavimo laiko konstanta, tik skaitomas laukas gali būti naudojamas vykdymo laiko konstantoms, kaip nurodyta šiame pavyzdyje:

 public static readonly uint l1 = (uint) DateTime.Now.Ticks; 
4
13 июня '13 в 13:10 2013-06-13 13:10 atsakymą pateikė Nitish Kakkar birželio 13 d. 13:10 2013-06-13 13:10

Kintamieji, pažymėti kaip „const“, yra šiek tiek didesni už griežtai įvestus #define makrokomandas, ir, sukompiliuoti, nuorodos į const kintamuosius yra pakeistos integruotomis skaitinėmis vertėmis. Taigi galite naudoti tik tam tikras įmontuotas primityvias reikšmes. Kintamieji, pažymėti skaitymui, gali būti nustatyti konstruktoriaus veikimo metu, o jų nuolatinis prieinamumas taip pat taikomas vykdymo metu. Yra keletas su tuo susijusių nedidelių išlaidų, tačiau tai reiškia, kad galite naudoti tik su bet kokiu tipu (net ir tipų tipais).

Be to, pastovūs kintamieji yra savaime statiniai, o tik kintamieji gali būti konkretūs, jei reikia.

4
11 сент. Atsakyti Wedge Sep 11 2008-09-11 11:41 '08, 11:41 val. 2008-09-11 11:41

Tik raktinis žodis skiriasi nuo const raktinio žodžio. Pastovus laukas gali būti inicijuotas tik tada, kai laukas yra deklaruojamas. Skaitymo laukas gali būti inicijuotas deklaracijoje arba konstruktoriuje. Todėl tik skaitomi laukai gali turėti skirtingas reikšmes, priklausomai nuo naudojamo konstruktoriaus. Be to, nors const laukas yra kompiliavimo laiko konstanta, tik skaitomas laukas gali būti naudojamas vykdymo laiko konstantoms, kaip nurodyta toliau pateiktame pavyzdyje:

 public static readonly uint timeStamp = (uint)DateTime.Now.Ticks; 
4
12 дек. Atsakymas pateikiamas „ Yas“ 12 d. 2015-12-12 21:12 '15 21:12 2015-12-12 21:12

Reikšmingas skirtumas tarp „const“ ir „readonly“ į „# #“

pagal nutylėjimą const yra statinis ir turi būti inicijuotas pastovia verte, kuri vėliau negali būti pakeista. Konstruktoriuose taip pat neleidžiama keisti vertės. Jis negali būti naudojamas su visais duomenų tipais. Ex-datetime. Jis negali būti naudojamas su DataTime duomenų tipu.

 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 

skaitymas gali būti deklaruojamas kaip statinis, bet neprivalomas. Skelbimo metu nereikia inicijuoti. Jo vertę galima priskirti arba keisti naudojant konstruktorių. Taigi, tai yra pranašumas, kai naudojamas kaip egzemplioriaus klasės narys. Du skirtingi atvejai gali turėti kitokią tik skaitomą lauko reikšmę. Dėl ex -

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

Tuomet tik skaitomas laukas gali būti inicijuojamas su tiesioginėmis konkrečiomis reikšmėmis:

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

Čia objOne egzempliorius bus skaitoma tik 5, o objTwo yra 10. Tai neįmanoma su const.

3
15 дек. Atsakymas suteiktas Chiragui gruodžio 15 d. 2014-12-15 16:01 '14, 16:01 2014-12-15 16:01

Kitas gotcha .

Kadangi const tikrai veikia tik su pagrindiniais duomenų tipais, jei norite dirbti su klase, galite pajusti „priverstinį“ „ReadOnly“ naudojimą. Tačiau saugokitės spąstų! „ReadOnly“ reiškia, kad negalite pakeisti objekto su kitu objektu (negalėsite priversti kreiptis į kitą objektą). Bet bet koks procesas, turintis nuorodą į objektą, gali laisvai keisti objekto viduje esančias vertybes!

Todėl nereikia painioti, galvodami, kad „ReadOnly“ reiškia, jog vartotojas nieko negali keisti. „C #“ neturi paprastos sintaksės, kad būtų užkirstas kelias klasės egzemplioriui keistis dėl jo vidinių verčių pasikeitimo (kiek aš žinau).

3
17 сент. Mark T atsakymas . 2008-09-17 16:28 '08 at 4:28 pm 2008-09-17 16:28

Pastovus

Turime apibrėžti reikšmę const lauke, kai jis yra apibrėžtas. Tuomet kompiliatorius išsaugo pastatų metaduomenų konstantų reikšmes. Tai reiškia, kad konstantą galima apibrėžti tik primityviam tipo boolean, char, baitui ir kt. Konstantai visada laikomi statiniais nariais, o ne egzempliorių nariais.

Tik skaitoma

Tik skaitomi laukai gali būti išspręsti tik vykdymo metu. Tai reiškia, kad mes galime apibrėžti vertės vertę naudodami konstruktorių tokio tipo, kuriame laukas yra deklaruotas. Tikrinimą atlieka kompiliatorius, kad skaityti tik laukai nėra parašyti jokiu kitu metodu, be konstruktoriaus.

Skaitykite daugiau apie tai, kaip tai paaiškinta šiame straipsnyje.

2
04 авг. atsakymą pateikė Vikramas 04 rug. 2015-08-04 08:34 '15 at 8:34 am 2015-08-04 08:34

Pastaba bus pastatyta į vartotoją kaip pažodinė vertė, o statinė eilutė bus nuoroda į konkrečią vertę.

Kaip pratimą, pabandykite sukurti išorinę biblioteką ir ją naudoti konsolės programoje, tada keisti bibliotekoje esančias reikšmes ir perkrauti ją (nekompiliuodami vartotojų programos), nuleiskite DLL į katalogą ir paleiskite EXE rankiniu būdu, turėtumėte sužinoti, kad pastovi eilutė nekeičiama.

2
08 сент. Atsakymas pateikiamas Brett Ryan 08 Sep. 2009-09-08 15:20 '09, 15:20, 2009-09-08 15:20

Skaitykite tik: vertė bus inicijuota tik kartą iš klasės konstruktoriaus.
const: galima inicijuoti bet kurioje funkcijoje, bet tik vieną kartą

1
24 янв. atsakymas suteiktas donstack Jan 24 2014-01-24 10:34 '14, 10:34, 2014-01-24 10:34

POST

  1. „Const“ raktinis žodis gali būti taikomas laukams arba vietiniams kintamiesiems.
  2. Skelbimo metu turime priskirti const lauką.
  3. Nėra priskirtos atminties. Kadangi suskaičiavus konst. Reikšmė yra įterpta į IL kodą. Tai panaši į visų konstuojamojo kintamojo atvejų aptikimą ir jo keitimą. Taigi, IL kodas po kompiliavimo turės kietų kodų reikšmes, o ne pastovius kintamuosius.
  4. C # konstanta yra statinė pagal nutylėjimą.
  5. Vertė yra pastovi visiems objektams.
  6. Yra problema su dll versija - tai reiškia, kad kai keičiame viešai prieinamą konstantą ar turtą (iš tikrųjų, tai nėra teoriškai prielaida), bet kuris kitas dll arba rinkinys, naudojant šį kintamąjį, turi būti atstatytas
  7. Tik pastatytus C # tipus galima deklaruoti kaip nuolatinius.
  8. Const laukas negali būti perduodamas kaip ref arba out parametras

Skaitykite tik

  1. Tik skaitomas raktinis žodis taikomas tik laukams, o ne vietiniams kintamiesiems.
  2. Deklaracijos ar konstruktoriaus metu mes galime priskirti tik skaitomą lauką, o ne kitus metodus.
  3. Dinaminė atmintis, skirta tik skaityti laukams, ir mes galime gauti vertę vykdymo metu.
  4. Skaitykite tik tokiu būdu sukurtą objektą, prieinamą tik per klasės egzempliorių. Kad galėtumėte tapti klasės nariu, prieš skaitydami turime pridėti statinį raktinį žodį.
  5. Vertė gali skirtis priklausomai nuo naudojamo konstruktoriaus (nes ji susijusi su klasės objektu)
  6. Jei deklaruojate ne primityvius tipus (pamatinį tipą), nes tik skaityti, tik nuoroda yra nepakeista, o ne jo turinys.
  7. Kadangi vertė gaunama vykdymo metu, nėra problemos su dll versija su tik skaitytais laukais / savybėmis.
  8. Mes galime perduoti tik skaitomą lauką kaip ref arba out parametrus konstruktoriaus kontekste.
1
08 сент. Atsakymą pateikė Muhammad VP 08 sep. 2018-09-08 09:39 '18 ne 9:39 2018-09-08 09:39

Nuolatiniai kintamieji deklaruojami ir inicijuojami kompiliavimo metu. Vertė negali būti pakeista po globėjų. Tik skaitymo kintamieji bus inicijuoti tik iš statinio klasės konstruktoriaus. Tik skaitymas naudojamas tik tada, kai norime priskirti vertę vykdymo metu.

1
10 апр. Atsakymą pateikė Omar AMEZOUG 10 balandžio. 2015-04-10 00:09 '15 - 0:09 2015-04-10 00:09

Skirtumas yra tas, kad statinio lauko skaitymo būsenos vertė nustatoma vykdymo metu, todėl skirtingų programų vykdymo atveju ji gali turėti skirtingą reikšmę. Tačiau pastovaus lauko reikšmė nustatoma kompiliavimo laiko konstantu.

Atminkite: abiem atvejais (statinis ir pavyzdinis) tipų tipams, tik skaitymui, neleidžiama priskirti naujos nuorodos į šį lauką. Jame konkrečiai nenurodomas nurodytas objektas.

Daugiau informacijos rasite šios temos skyriuje „C # dažnai užduodami klausimai“: http://blogs.msdn.com/csharpfaq/archive/2004/12/03/274791.aspx

1
05 апр. Atsakymas pateikiamas Yonatan Nir 05 balandžio. 2014-04-05 17:39 '14, 17:39 pm 2014-04-05 17:39

Pastovus laukas gali būti inicijuotas tik tada, kai laukas yra deklaruojamas. Skaitymo laukas gali būti inicijuotas deklaracijoje arba konstruktoriuje.

1
22 марта '16 в 16:20 2016-03-22 16:20 atsakymą pateikė Geka P 22 kovo 16 d. 16:20 2016-03-22 16:20

Const ir tiktai panašūs, bet jie nėra visiškai tokie patys. Pastovus laukas yra kompiliavimo laiko konstanta, o tai reiškia, kad šią vertę galima apskaičiuoti kompiliavimo metu. Skaitymo laukas leidžia sukurti papildomus scenarijus, kuriuose tam tikras kodas turi būti atliktas tipo konstrukcijos metu. Po konstrukcijos negalima keisti tik skaitomo lauko.

Pavyzdžiui, pastovūs nariai gali būti naudojami apibrėžti tipo narius:

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

kadangi tokios vertės kaip 3.14 ir 0 yra kompiliavimo laiko konstantos. Tačiau apsvarstykite atvejį, kai apibrėžiate tipą ir norite pateikti kai kuriuos preliminarius atvejus. Например, вы можете определить класс "Цвет" и предоставить "константы" для общих цветов, таких как "Черный", "Белый" и т.д. Это невозможно сделать с помощью константных членов, поскольку правые части не являются константами времени компиляции. Это можно сделать с помощью обычных статических элементов:

 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; } }