C # neden salt okunur yerel değişkenlere izin vermiyor?


115

Bu konuda bir iş arkadaşınızla dostane bir tartışma yapmak. Bununla ilgili bazı düşüncelerimiz var, ancak SO kalabalığının bu konuda ne düşündüğünü merak ediyoruz.


4
@ColonelPanic C ve C ++, çalışma zamanı ile hesaplanan bir değerle başlatabileceğiniz const yerel değişkenlere sahiptir.
Crashworks

1
JavaScript 2015 (ES6) const türüne sahiptir. Örneğin {const myList = [1,2,3]; }. Bu yapıyı kullanmak çok iyi bir programlama uygulamasıdır. Daha fazla bilgi: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
andrew.fox

1
İlgilenenler için, bu özellik için bir UserVoice önerisi var . Şu anda sadece 87 oyda oturuyor, bu yüzden yerel salt okunur değişkenleri görmek istiyorsanız, lütfen gidin!
Ian Kemp

1
Bu sadece bir dil sorunu değil. En yüksek dereceli C # guruları dahil olmak üzere C # topluluğundaki bir çoğunluğun, const doğruluğunu ve bununla ilgili herhangi bir şeyi önemsememeleri sorunudur. Direniş boşuna.
Patrick Fromberg

1
2017 Güncellemesi : Lütfen C # Dil Tasarımı deposunda tartışılan özellik talebine oy verin! github.com/dotnet/csharplang/issues/188
Colonel Panic

Yanıtlar:


15

Bunun bir nedeni, salt okunur yerel için CLR desteğinin olmamasıdır. Salt okunur, CLR / CLI initonly işlem koduna çevrilir. Bu bayrak yalnızca alanlara uygulanabilir ve yerel için bir anlamı yoktur. Aslında, bunu yerel bir yere uygulamak muhtemelen doğrulanamayan kod üretecektir.

Bu, C # 'ın bunu yapamayacağı anlamına gelmez. Ama aynı dil yapısına iki farklı anlam verecektir. Yerellere yönelik sürümde CLR eşdeğeri eşleme olmayacaktır.


57
Aslında özelliğin CLI desteğiyle hiçbir ilgisi yoktur, çünkü yerel değişkenler hiçbir şekilde diğer derlemelere maruz kalmaz. readonlyEtkisi nedeniyle alanlar için anahtar kelime CLI tarafından desteklenmesi gerekiyor ise diğer meclislere görünür. Bunun anlamı, derleme zamanında değişkenin yöntemde yalnızca bir ataması olmasıdır.
Sam Harwell

16
Sanırım soruyu, arkasındaki mantığı sağlamak yerine CLR'nin neden bunu desteklemediğine kaydırdınız. Sabit yerellere izin verir, bu nedenle salt okunur yereller beklemek mantıklı olacaktır.
Chad Schouggins

9
Bunun bir örneği, using ifadesinde tanımlanan değişkendir. Yereldirler ... ve salt okunur (onları atamayı deneyin, C # bir hata ekleyecektir).
Softlion

7
-1 C ++ 'da makine kodu desteği yoktur const(C ++' da C # ' readonlydan çok C # gibidir const, ancak her iki rolü de oynayabilir). Yine de C ++ constyerel otomatik değişkeni destekler . Bu nedenle, readonlyyerel değişken için bir C # için CLR desteğinin olmaması önemsizdir.
Şerefe ve hth. - Alf

5
1. Bu, C ++ 'da olduğu gibi kolayca bir derleyici özelliği olabilir. CLR desteği tamamen konu dışıdır. Makine montajı da desteklemiyor, peki ne? 2. (bu) muhtemelen doğrulanamayan kod üretir - nasıl olduğunu bilmiyorum, ama belki yanılıyorum. 3. Aynı dili yapı için iki farklı anlamlar verecek - O zamandan beri, herkes bir sorun olarak görecekti şüphe usingve outtam olarak yapıyor bu vardır ve dünya çökmedi.
Lou

66

Bence bu, C # mimarlarının bir kısmı için zayıf bir karar. Yerel değişkenler üzerindeki salt okunur değiştirici, programın doğruluğunu korumaya yardımcı olur (tıpkı iddialar gibi) ve derleyicinin kodu optimize etmesine yardımcı olabilir (en azından diğer dillerde). Şu anda C # 'da izin verilmediği gerçeği, C #' ın bazı "özelliklerinin" yalnızca yaratıcılarının kişisel kodlama stilinin bir zorlaması olduğunun başka bir argümanıdır.


11
"Programcıyı kendisinden kurtarmak" kısmına katılıyorum, ancak derleyicinin kodu optimize etmesine yardımcı olmak için, derleyicinin, bir değişkenin yöntemin seyri boyunca değişip değişmediğini çok iyi anlayabileceği ve buna göre optimize edeceği görüşüne sahibim. öyle ya da böyle. Optimize edicinin her halükarda bu amaç için tanıdığı bir şeyin önüne 'salt okunur' bayrağı yerleştirmek gerçekten fayda sağlamaz, ancak potansiyel olarak yanıltıcıdır.
Cornelius

1
@Cornelius Bazı durumlarda derleyicinin herhangi bir anahtar kelime / değiştiriciden bağımsız olarak optimizasyon fırsatını bulmak için veri akışı diyagramını kullandığına dair görüşler olduğunu kabul ediyorum. Ancak programcıyı yanlış ve başka türlü gereksiz yere optimize edilmemiş kod yazmaktan kurtarmak, derleyici için bu optimizasyon fırsatını açabilir.
shuva

Modern derleyiciler zaten Statik Tek Atama yapmıyor mu? Bu durumda, optimizasyonlar söz konusu olduğunda tartışmalıdır (ancak bir derleyici SSA'yı destekliyorsa, bir kez atama yerel değişkenleri uygulamanın da önemsiz olduğu anlamına gelir).
Dai

33

Jared'in cevabına değinecek olursak, muhtemelen sadece bir derleme zamanı özelliği olması gerekecekti - derleyici, ilk bildirimden sonra (bir atama içermesi gereken) değişkene yazmanızı yasaklayacaktır.

Bunun değerini görebilir miyim? Potansiyel olarak - ama çok değil, dürüst olmak gerekirse. Yöntemin başka bir yerinde bir değişkenin atanıp atanmayacağını kolayca anlayamıyorsanız, yönteminiz çok uzundur.

Ne 's değerinde için Java (kullanarak bu özelliği vardır finaldeğiştirici) ve ben ettik çok nadiren o durumlar dışında kullanılan görüldü sahip değişken Anonim iç sınıf tarafından yakalanan izin vermek için kullanılacak - nerede ve olduğu kullanıldığında, bana faydalı bilgilerden çok dağınıklık izlenimi veriyor.


75
Yönteminizde bir değişkenin görerek ve derleyici tarafından değiştirilip değiştirilmediğini görmek arasında bir fark vardır . Bir yöntem yazmaya, bir değişkeni değiştirmeme niyetimi belirterek ve yanlışlıkla yaptığımda derleyicinin beni bilgilendirmesine (belki bir ay sonra bir yazım hatasıyla) itiraz görmüyorum!
A. Rex

50
Öte yandan, F # 'da tüm değişkenler varsayılan olarak salt okunurdur ve onları değiştirebilmek istiyorsanız' mutable 'anahtar kelimesini kullanmanız gerekir. F # bir .NET dili olduğundan, sizin tanımladığınız derleme zamanı kontrolünü yaptığını düşünüyorum.
Joel Mueller

2
@ A.Rex: Asıl soru, derleyiciye bu denetimi yaptırmanın faydasının, kodu okurken fazladan "kabartmaya" değip değmeyeceği ve aslında onu önemsememesidir.
Jon Skeet

3
FWIW, Scala yerel readonly/ finaldeğerleri valve varanahtar sözcükleriyle değişkenlerden ayırır . Scala kodunda, yerel vals çok sık kullanılır (ve aslında yerel kodlara göre tercih edilir var). finalJava'da değiştiricinin daha sık kullanılmamasının başlıca nedenlerinin a) dağınıklık ve b) tembellik olduğundan şüpheleniyorum .
Aaron Novstrup

4
Kapanışlarda kullanılmayan yerel değişkenler readonlyiçin aşırı önemli olmayacaktır. Öte yandan, kapanışlarda kullanılan yerel değişkenler için readonly, çoğu durumda derleyicinin daha verimli kod üretmesine izin verir. Şu anda, yürütme bir kapatma içeren bir bloğa girdiğinde , kapatmayı kullanacak hiçbir kod çalıştırılmasa bile , derleyici kapalı değişkenler için yeni bir yığın nesnesi yaratmalıdır . Bir değişken salt okunursa, kapanışın dışındaki kod normal bir değişken kullanabilir; yalnızca kapanış için bir temsilci oluşturulduğunda ...
supercat

30

C # 7 tasarım ekibi tarafından salt okunur yereller ve parametreler için bir teklif kısaca tartışıldı. Gönderen Jan 21, 2015 yılı için C # Tasarım Toplantı Notları :

Parametreler ve yereller lambdalar tarafından yakalanabilir ve bu nedenle eşzamanlı olarak erişilebilir, ancak bunları paylaşılan karşılıklı durum sorunlarından korumanın bir yolu yoktur: salt okunur olamazlar.

Genel olarak, çoğu parametre ve birçok yerel öğenin, başlangıç ​​değerlerini aldıktan sonra hiçbir zaman atanması amaçlanmamıştır. Onlara salt okunur izin vermek, bu niyeti açıkça ifade edecektir.

Bir sorun, bu özelliğin "çekici bir sıkıntı" olabileceğidir. Yapılacak "doğru şey" neredeyse her zaman parametreleri ve yerelleri salt okunur hale getirmek olsa da, bunu yapmak kodu önemli ölçüde karıştırır.

Bunu kısmen hafifletmek için bir fikir, yerel bir değişkendeki salt okunur varyasyon kombinasyonunun val veya bunun gibi kısa bir şeye bağlanmasına izin vermektir. Daha genel olarak, salt okunurluğu ifade etmek için oluşturulmuş salt okunurdan daha kısa bir anahtar kelime düşünmeye çalışabiliriz.

Tartışma C # Dil Tasarımı deposunda devam ediyor. Desteğinizi göstermek için oy verin. https://github.com/dotnet/csharplang/issues/188


salt okunur da olabilir (bir seçenek veya anahtar sözcük veya her neyse). çoğu değişken ve parametre yalnızca birkaç yazılabilir olacak şekilde salt okunur olmalıdır. ve yazılabilir sayıyı en aza indirmek genellikle iyi bir şeydir.
Dave Cousineau

12

C # dil tasarımcısı için bir gözetimdir. F #, val anahtar kelimesine sahiptir ve CLR'ye dayanır. C # 'ın aynı dil özelliğine sahip olmaması için hiçbir sebep yoktur.


7

Ben o iş arkadaşıydım ve arkadaşça değildi! (şaka yapıyorum)

Bu özelliği ortadan kaldırmam çünkü kısa yöntemler yazmak daha iyidir. Bu biraz zor oldukları için iplik kullanmamalısın demek gibi. Bıçağı bana ver ve kendimi kesmememin sorumluluğunu bana ver.

Kişisel olarak, dağınıklığı önlemek için "inv" (değişmez) veya "rvar" gibi başka bir "var" türü anahtar kelime istedim. Son zamanlarda F # üzerinde çalışıyorum ve değişmez şeyi çekici buluyorum.

Java'nın buna sahip olduğunu hiç bilmiyordum.


5

Yerel sabit değişkenleri sevdiğim gibi, yerel salt okunur değişkenleri de istiyorum . Ancak diğer konulardan daha az önceliğe sahiptir. Belki de önceliği , C # tasarımcılarının bu özelliği (henüz!) Uygulamamaları için aynı nedendir . Ancak gelecekteki sürümlerde yerel salt okunur değişkenleri desteklemek kolay (ve geriye dönük uyumlu) olmalıdır.


2

Salt okunur, örnek değişkeninin ayarlanabileceği tek yerin yapıcıda olduğu anlamına gelir. Bir değişkeni yerel olarak bildirirken, bir örneği yoktur (sadece kapsam dahilindedir) ve kurucu tarafından dokunulamaz.


6
C # 'da' salt okunur 'ifadesinin şu anki anlamı bu, ama soru bu değil. 'salt okunur' bir yerel değişkene sezgisel bir uygulama gibi görünen İngilizce bir anlama sahiptir: Ona yazamazsınız (başlatıldıktan sonra). Örnek değişkenlere uygulandığında anlama çok benziyor, öyleyse neden (gerekçelendirmede olduğu gibi) yerel değişkenlere uygulayamıyoruz?
Spike0xff

0

Biliyorum, bu sorunun nedenini yanıtlamıyor. Her neyse, bu soruyu okuyanlar yine de aşağıdaki kodu takdir edebilirler.

Yalnızca bir kez ayarlanması gereken yerel bir değişkeni geçersiz kılarken kendinizi ayağa kaldırmakla gerçekten ilgileniyorsanız ve onu daha genel olarak erişilebilir bir değişken yapmak istemiyorsanız, bunun gibi bir şey yapabilirsiniz.

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

Örnek kullanım:

        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

Belki daha az kod rvar rInt = 5olmasa da işe yarıyor.


Bu burada yardımcı olmuyor. 'Var' değişkeniyle ilgili bu sorun şudur: {var five = 5 five = 6; Assert.That (beş == 5)}
Murray,

0

C # etkileşimli derleyiciyi kullanıyorsanız, C # 'da salt okunur yerel değişkenler bildirebilirsiniz 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)

Ayrıca .csxkomut dosyası biçiminde salt okunur yerel değişkenler de bildirebilirsiniz .


5
Hata mesajına göre, messageburada bir değişken değil, bir alana derlenmiştir. Bu nitpicking değildir çünkü ayrım etkileşimli C #'da da açıkça mevcuttur: int x; Console.WriteLine(x)yasal etkileşimli C # (çünkü xbir alandır ve dolaylı olarak başlatılmıştır), ancak void foo() { int x; Console.WriteLine(x); }değildir (çünkü xbir değişkendir ve atanmadan önce kullanılır). Ayrıca, Expression<Func<int>> y = x; ((MemberExpression) y.Body).Member.MemberTypebunun xgerçekten bir alan olduğunu ve yerel bir değişken olmadığını ortaya çıkaracaktır .
Jeroen Mostert

0

c #, biraz farklı bir sözdiziminde de olsa, zaten salt okunur bir değişkene sahiptir:

Aşağıdaki satırları düşünün:

var mutable = myImmutableCalculationMethod();
readonly var immutable = mutable; // not allowed in C# 8 and prior versions
return immutable;

İle karşılaştırmak:

var mutable = myImmutableCalculationMethod();
string immutable() => mutable; // allowed in C# 7
return immutable();

Kuşkusuz, ilk çözüm muhtemelen yazılacak daha az kod olabilir. Ancak 2. kod parçası, değişkene atıfta bulunurken salt okunuru açık hale getirecektir.


Bu "salt okunur" değil. Bu, yakalanan bir değişkeni döndüren yerel bir işlevdir. Bu nedenle, kod erişimi açısından, altta yatan değişkeni salt okunur yapmayan çok sayıda gereksiz ek yük ve çirkin sözdizimi. Ayrıca, "değiştirilebilir" genellikle yerel değişkenler için değil, nesneler için geçerlidir readonly var im = new List<string>(); im.Add("read-only variable, mutable object!");.
user2864740

-2

constsalt okunur değişken yapmak için anahtar sözcük kullanın.

referans: 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);
    }
}

1
constDeğişkenin yalnızca başlatma sırasında atanabileceği JavaScript tarzı ile ilgileniyoruz - constyalnızca derleme zamanı ifadelerinin kullanılabildiği csharp tarzı değil . Örneğin, yapamazsınız const object c = new object();ancak readonlyyerel bir kişi bunu yapmanıza izin verir.
binki

-5

Sanırım bunun nedeni salt okunur bir değişkeni olan bir işlevin asla çağrılamayacağı ve muhtemelen kapsam dışına çıkmasıyla ilgili bir şeyler olduğu ve ne zaman ihtiyacınız olacak?

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.