Защо частните константи се съхраняват в .NET сборки?

Константите, посочени от кода, се заменят с техните действителни стойности, когато се компилират в IL.

Тъй като публичните константи могат да бъдат препратени от код извън конкретен асембли, има смисъл те да се съхраняват в метаданните на асемблирането.

Но защо частните константи се съхраняват там? Няма препратки към тези константи в IL на кода в асемблирането, което ги е дефинирало, и те не са изложени на препратки извън асемблирането.

И така, какво трябва да има достъп до тези стойности, след като кодът е компилиран?

Струва ми се, че всички константи в сглобките трябва да са публични, а частните константи трябва да са функция на ниво език, която просто кара компилатора да излъчва буквални стойности.


person user2465452    schedule 07.11.2014    source източник
comment
Поради BindingFlags.NonPublic. Да можеш да бъркаш в интимните части е адски удобно, когато си в затруднено положение и програмистът не вдига телефона, за да ти помогне.   -  person Hans Passant    schedule 08.11.2014
comment
Но каква е ползата от достъпа до тази частна константа? Няма IL препратки към тази константа. Всичко, което ви казва, е, че някой е решил да използва константа, вместо да кодира твърдо стойност някъде.   -  person user2465452    schedule 08.11.2014
comment
Е, разбира се, IL препраща към тази константа. Той е вграден в IL. Ако никога не намериш приложение за това, животът е хубав.   -  person Hans Passant    schedule 08.11.2014
comment
Искам да кажа, че няма разлика в IL между кода, използващ константа, и кода, използващ литерал. С други думи, декларирането (в C#) private const string MYCONST = "Hello World" и след това извършването на Console.WriteLine(MYCONST) води до същия IL като извършването на Console.WriteLine("Hello World").   -  person user2465452    schedule 08.11.2014


Отговори (1)


Компилаторът на C# може да оптимизира всички видове лични неща. Не само константи. Може да премахне неизползвани членове, класове, код. Може да премахне личните имена. Може да изтрие частни свойства и да ги замени с методи. и т.н.

Достъпът до отражение и инструментите за пренаписване на IL идват на ум като важни случаи на употреба за частни неща. Освен това отстраняването на грешки е по-лесно, когато повечето метаданни все още присъстват. Например, можете да използвате Edit&Continue, за да използвате неизползвани преди това членове. Можете да извикате статично неизползвани членове, като използвате незабавния прозорец.

Може би има последици и за PDB символите, въпреки че не мога да се сетя за такива в момента.

Имайте предвид, че .NET модулите съдържат много метаданни, които са само полезни за достъп до отражение. Атрибутите нямат никакво значение за времето на изпълнение, освен че могат да се проверят. Сглобките са предназначени да бъдат богати и самоописващи се.

Може да се твърди, че константите са особено безполезни за запазване, защото винаги са статично неизползвани. Това обаче не означава, че няма приложения за отражение. Те също могат да помогнат при декомпилиране на код. Един интелигентен декомпилатор може да забележи, че определен литерал е идентичен с константа, декларирана наблизо. Освен това, защо да правите изключение за константи, за да ги оптимизирате? В типичните програми има много малко константи. Дори да приемем, че е по-добре да ги премахнем, инвестицията едва ли ще се изплати. По-добре развивайте едновременно полезни езикови функции.

person usr    schedule 07.11.2014
comment
Отражението може да ви каже, че е използвана константа, но тази константа не е спомената в нито един IL код. Компилаторът вече оптимизира константата чрез инжектиране на литерали, където и да е препратка. Други частни членове могат да бъдат достъпни чрез отражение, така че има смисъл информацията за тях да се съхранява в метаданните. Но всичко, което получавате от константите, е знанието, че програмистът е решил да ги използва. Атрибутите са публични и са предназначени да бъдат достъпвани програмно, за да повлияят на логиката, дори и да не го правят сами автоматично. - person user2465452; 08.11.2014
comment
Предположението, че литералите със съвпадащи стойности се отнасят до една и съща константа, е твърде склонно към грешки. Например, ако декларирам константа private const int SCHEMAVERSION = 1, тогава декомпилатор ще съпостави този код var x = myarray[myarray.Length - 1] към този var x = myarray[myarray.Length - SCHEMAVERSION]. И тогава има случаи, в които може да се позовавам на външна публична константа, въпреки че локална константа има същата стойност. Ако искаха да поддържат това, щях да си помисля, че щяха да имат поддръжка на IL инструкции за константи и след това да оставят трептенето да инжектира литералите. - person user2465452; 12.11.2014
comment
Що се отнася до допълнителните усилия, необходими за оптимизирането им, наистина няма никакви. Ако бяха направили IL константите само публични, тогава езиците просто щяха да добавят само дефинирани от език публични константи към метаданните. Тежката работа е замяната на всички препратки към константи с литерали и това беше наложено от спецификацията. Просто ми изглежда странно, че те биха задължили нещо подобно и след това не дефинират константите да бъдат само публични. - person user2465452; 12.11.2014