Провести дружню дискусію з колегою з цього приводу. У нас є деякі думки з цього приводу, але цікаво, що думка про це думає?
Провести дружню дискусію з колегою з цього приводу. У нас є деякі думки з цього приводу, але цікаво, що думка про це думає?
Відповіді:
Однією з причин є відсутність підтримки CLR для місцевого зразка. Readonly перекладається в CLR / CLI в інітонічному коді. Цей прапор може бути застосований лише до полів і не має значення для місцевих. Насправді, застосувавши його до локального, швидше за все, вийде неперевірений код.
Це не означає, що C # не міг цього зробити. Але це дало б два різні значення одній і тій же мовній конструкції. Версія для місцевих жителів не мала б еквівалентного відображення CLR.
readonly
Ключове слово для полів має підтримуватися CLI , оскільки його ефект є видимим для інших вузлів. Все, що це означало б, що змінна має лише одне призначення у методі під час компіляції.
const
(яка в C ++ більше схожа на C #, readonly
ніж як C # const
, хоча вона може грати обидві ролі). Однак C ++ підтримує const
локальну автоматичну змінну. Отже, відсутність підтримки CLR для C # readonly
для локальної змінної - не має значення.
using
і out
робимо саме так, і світ не розпався.
Я думаю, що це недостатньо судження з боку архітекторів C #. модифікатор readonly для локальних змінних допомагає підтримувати правильність програми (як і твердження) і потенційно може допомогти компілятору оптимізувати код (принаймні, у випадку інших мов). Те, що зараз це заборонено в C #, є ще одним аргументом, що деякі "особливості" C # - це лише примусовий стиль особистого кодування його творців.
Звертаючись до відповіді Джареда, це, ймовірно, повинно було бути функцією часу компіляції - компілятор заборонив би вам писати до змінної після первинного декларації (яка повинна містити призначення).
Чи можу я бачити цінність у цьому? Потенційно - але не багато, якщо чесно. Якщо ви не можете легко сказати, чи буде вказана змінна призначена в іншому місці методу, то ваш метод занадто довгий.
Для чого це коштує, Java має цю функцію (використовуючи final
модифікатор) , і я дуже рідко бачив його використовували інші , ніж в тих випадках , коли воно має бути використано , щоб дозволити змінної бути захопленими анонімного внутрішнього класу - і де він знаходиться Використовується, це справляє враження скорботи, а не корисної інформації.
readonly
/ final
значення від змінних своїми val
та var
ключовими словами. У коді Scala локальні val
s використовуються дуже часто (і насправді є кращими перед локальними var
s). Я підозрюю, що основними причинами того, що final
модифікатор не використовується частіше в Java, є: неполадка і б) лінь.
readonly
було б не надто важливо. З іншого боку, для локальних змінних, які використовуються в закриттях, readonly
у багатьох випадках дозволяють компілятору генерувати більш ефективний код. В даний час, коли виконання входить до блоку, який містить закриття, компілятор повинен створити новий об'єкт купи для змінних закритого типу, навіть якщо жодного коду, який би використовував закриття, ніколи не виконується . Якщо змінна була лише для читання, код за межами закриття міг би використовувати звичайну змінну; лише тоді, коли для закриття буде створений делегат ...
Пропозиція, що читається лише місцевими жителями та параметрами, була коротко обговорена дизайнерською командою C # 7. З конспектів дизайнерських зустрічей C # 21 січня 2015 року :
Параметри і місцеві жителі можуть захоплюватися лямбдами і тим самим отримувати доступ до них одночасно, але немає ніякого способу захистити їх від спільних взаємних державних питань: їх не можна читати тільки щойно.
Взагалі, більшість параметрів та багато місцевих жителів ніколи не призначаються для призначення після отримання їх початкового значення. Дозвіл лише начитатися на них виразно виражатиме цей намір.
Одна з проблем полягає в тому, що ця особливість може бути "привабливою неприємністю". У той час, як "правильним" робити майже завжди буде встановлення параметрів та місцевих жителів лише заново, це загрожує кодом суттєво.
Ідея частково полегшити це полягає в тому, щоб дозволити комбінацію, що читається лише для локальної змінної, було зафіксовано значення val або щось таке коротке. Більш загально, ми можемо спробувати просто придумати коротше ключове слово, ніж встановлене лише для читання, щоб висловити лише необхідність читання.
Обговорення продовжується в репо-мові C # Language Design. Проголосуйте, щоб показати свою підтримку. https://github.com/dotnet/csharplang/isissue/188
Я був тим співробітником, і це було не дружелюбно! (жартую)
Я б не ліквідував функцію, тому що краще писати короткі методи. Це трохи схоже на те, що ви не повинні використовувати теми, тому що вони важкі. Дайте мені ножа, і дозвольте мені нести відповідальність за те, щоб не порізати себе.
Особисто мені хотілося іншого ключового слова типу "var" типу "inv" (інваріант) або "rvar", щоб уникнути безладу. Я вивчав F # пізно і знаходжу непорушну річ привабливою.
Ніколи не знав, що у Java цього є.
Мені б хотілося, щоб локальні змінні зчитувались так само, як і місцеві змінні const . Але він має менший пріоритет, ніж інші теми.
Можливо, його пріоритет - це та сама причина, що дизайнери C # не (ще!) Не реалізують цю функцію. Але підтримувати локальні змінні, що читаються лише в наступних версіях, повинно бути легко (і сумісним назад).
Readonly означає, що єдине місце, на яке може бути встановлена змінна примірник, - це в конструкторі. При оголошенні змінної локально вона не має примірника (вона просто в області дії), і конструктор її не може торкнутися.
Я знаю, це не відповідає чому на ваше запитання. У будь-якому разі, ті, хто читає це питання, все-таки можуть оцінити наведений нижче код.
Якщо ви дійсно переймаєтесь тим, як стріляти з себе в ногу, коли заміняє локальну змінну, яку слід встановити лише один раз, і ви не хочете робити її більш глобально доступною змінною, ви можете зробити щось подібне.
public class ReadOnly<T>
{
public T Value { get; private set; }
public ReadOnly(T pValue)
{
Value = pValue;
}
public static bool operator ==(ReadOnly<T> pReadOnlyT, T pT)
{
if (object.ReferenceEquals(pReadOnlyT, null))
{
return object.ReferenceEquals(pT, null);
}
return (pReadOnlyT.Value.Equals(pT));
}
public static bool operator !=(ReadOnly<T> pReadOnlyT, T pT)
{
return !(pReadOnlyT == pT);
}
}
Приклад використання:
var rInt = new ReadOnly<int>(5);
if (rInt == 5)
{
//Int is 5 indeed
}
var copyValueOfInt = rInt.Value;
//rInt.Value = 6; //Doesn't compile, setter is private
Можливо, не менший код, rvar rInt = 5
але це працює.
Ви можете оголосити лише локальні змінні в C #, якщо ви використовуєте інтерактивний компілятор C # csi
:
>"C:\Program Files (x86)\MSBuild\14.0\Bin\csi.exe"
Microsoft (R) Visual C# Interactive Compiler version 1.3.1.60616
Copyright (C) Microsoft Corporation. All rights reserved.
Type "#help" for more information.
> readonly var message = "hello";
> message = "goodbye";
(1,1): error CS0191: A readonly field cannot be assigned to (except in a constructor or a variable initializer)
Ви також можете оголосити лише локальні змінні у .csx
форматі сценарію.
message
тут не є змінною, вона компілюється в поле. Це не є запозиченням, оскільки відмінність чітко існує і в інтерактивному C #: int x; Console.WriteLine(x)
є законним інтерактивним C # (тому що x
це поле і неявно ініціалізується), але void foo() { int x; Console.WriteLine(x); }
не є (тому що x
це змінна та використовується до її призначення). Також Expression<Func<int>> y = x; ((MemberExpression) y.Body).Member.MemberType
виявить, що x
це дійсно поле, а не локальна змінна.
c # вже має varonly var, хоча і дещо інший синтаксис:
Розглянемо наступні рядки:
var mutable = myImmutableCalculationMethod();
readonly var immutable = mutable; // not allowed in C# 8 and prior versions
return immutable;
Порівняти з:
var mutable = myImmutableCalculationMethod();
string immutable() => mutable; // allowed in C# 7
return immutable();
Правда, перше рішення могло б бути меншим кодом для запису. Але 2-й фрагмент зробить чітко чітке, посилаючись на змінну.
readonly var im = new List<string>(); im.Add("read-only variable, mutable object!");
.
використовувати const
ключове слово, щоб зробити змінним лише для читання.
довідка: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/const
public class SealedTest
{
static void Main()
{
const int c = 707;
Console.WriteLine("My local constant = {0}", c);
}
}
const
де змінна може бути призначена лише під час її ініціалізації, а не в стилі csharp, const
де можуть використовуватися лише вирази часу компіляції. Наприклад, ви не можете цього зробити, const object c = new object();
але readonly
місцевий дозволив би зробити це.