C #’da hala [goto] kullanan var mı ve öyleyse neden? [kapalı]


104

C # 'ta hala "goto" anahtar kelime sözdizimini kullanıp kullanmadığını ve bunu yapmak için olası nedenleri olup olmadığını merak ediyordum.

Okuyucunun kodun etrafından atlamasına neden olan herhangi bir ifadeyi kötü bir uygulama olarak görme eğilimindeyim, ancak böyle bir sözdizimini kullanmak için herhangi bir güvenilir senaryo olup olmadığını merak ettim.

Anahtar Kelime Tanımına Git


3
ne demek "hala"? İnsanların bunu her zaman [c # 'de] kullandığı bir dönem var mıydı?
Massif

4
@Massif: "still", spagetti kodunun başlangıcı olarak "goto" nun kullanımı ve kaynak kodda okunabilirlik eksikliği konusundaki modern görüşü vurgulamayı amaçlıyordu. Bu belirli anahtar kelimeyi içeren herhangi bir kod örneğini nadiren görürsünüz, bu yüzden ilk etapta sormakla ilgilendim.
Brian Scott

50
Okuyucu kodun "etrafından dolaşması" kötü bir uygulama ise, o halde "ara", "devam et", "fırlat" ve "geri dön" ten de kaçınır mısınız? Hepsi kontrol akışında, bazen yerel olmayan bir şubeye neden olur. "Fırlat", goto'nun aksine size nereye gittiğini bile söylemez.
Eric Lippert

2
Kullandığım gotobir döngü kırmak ve belirli koşuluna göre deyimi başlamadan geri dönmek için
Nitin S

3
Gitmeyi seviyorum. İnsanların kodun okunmasını zorlaştırdığı için bundan kaçınmasını söyleyen eğilimi nedeniyle bundan kaçınmaya çalıştım. Assembly dilini ve şube ifadelerini öğrendikten sonra, bence bazen zamanlar olabilir, kodu daha okunaklı hale getirebilir. Tek bir yöntemde birden fazla kullanımın ve kodda çok aşağı atlamanın yarardan çok zarar verebileceğini düşünüyorum. Ama eğer bir gotonun burada iyi çalışacağını düşünüyorsanız, arada bir basit bir gitmek, sırf ortak fikir birliği ondan kaçınmak olduğu için kaçınmak için yolunuzdan çıkmanıza neden olmamalıdır.
eaglei22

Yanıtlar:


93

Goto'nun okunabilirliği gerçekten iyileştirebileceği bazı (nadir) durumlar vardır. Aslında, bağladığınız belgelerde iki örnek listelenmiştir:

Goto'nun yaygın bir kullanımı, denetimi belirli bir anahtar durum etiketine veya bir anahtar deyimindeki varsayılan etikete aktarmaktır.

Goto ifadesi, derinlemesine iç içe geçmiş döngülerin dışına çıkmak için de kullanışlıdır.

İşte ikincisi için bir örnek:

for (...) {
    for (...) {
        ...
        if (something)
            goto end_of_loop;
    }
}

end_of_loop:

Elbette, bu sorunun etrafında başka yollar da var, örneğin kodu bir işleve dönüştürmek, etrafında bir kukla blok kullanmak gibi ( ayrıntılar için bu soruya bakın). Bir yan not olarak, Java dili tasarımcıları gitmeyi tamamen yasaklamaya ve bunun yerine etiketli bir break ifadesini kullanmaya karar verdiler .


49
Normalde ediyorum denemek Sadece gelen geri dönebilirler ayrı yöntemle ... lütfen döngüler koymak için bu refactor
Jon Skeet

2
@Heinzi - Garantili olduğunu görmedim. Jon'un dediği gibi, eğer "garanti" alınıyorsa, kod yeniden düzenlenmek için yalvarıyor.
manojlds

29
etiketli mola, sadece aynı ucube şeyi yaptığı için git demenin daha uzun bir yolu ....
Jesus Ramos

20
@ İsa ama sonra goto ile istediğiniz yere gidebilirsiniz. Etiketli mola, döngünün hemen dışına çıkmanızı sağlar.
mihsathe

1
Maceracı olmadığınız ve bir adresle goto kullanmadığınız sürece (daha önce yapıldığını görmüştüm), o zaman bu sorun hafifletilir. Ve birinin C # ve Java kodunuzda goto ifadelerinden yararlanmak için sapma kancaları kullandığından şüpheliyim.
Jesus Ramos

66

Bu bölümü hatırlıyorum

switch (a)     
{ 
    case 3: 
        b = 7;
        // We want to drop through into case 4, but C# doesn't let us
    case 4: 
        c = 3;
        break; 
    default: 
        b = 2;
        c = 4;
        break; 
}

Bunun gibi bir şeye

switch (a)     
{
    case 3: 
        b = 7;
        goto case 4;    
    case 4: 
        c = 3;
        break;     
    default: 
        b = 2;
        c = 4;
        break;
}

bakın Bu


17
Aslında bunu [goto] kullanmak için en geçerli neden olarak görüyorum. En azından bu senaryoda, vakaların break ifadesi olmadan birbirine düştüğünün farkında olmayan programcılar için okunabilirliği artırır.
Brian Scott

11
@Brian Scott, V4Vendetta. Yanılmıyorsam ilk ifade C # ile derlenmiyor. Bu, programcının anlamasına yardımcı olur.
Jodrell

2
V4Vendetta neden ilk kod parçacığına bir ara verdiniz ...? Ara vermeden göstermek daha iyiydi, aksi takdirde iki parça farklı şeyler yapar. İkinci örnekte goto'ya ihtiyaç duymanızın nedeni, tam olarak ilkinin C # ile derlenmemesidir (C'de olduğu gibi).
Stephen Holt

23

Bunu Eduasync'te C # 5'te zaman uyumsuz yöntemleri kullanırken derleyicinin sizin için ürettiği kod türünü göstermek için yoğun bir şekilde kullanıyorum. Aynı şeyi yineleyici bloklarda da görürsünüz.

"Normal" kodda olsa da, onu en son ne zaman kullandığımı hatırlayamıyorum ...


1
Bu yaklaşımın neden tercih edildiğine veya sadece kişisel bir tercih olduğuna dair küçük bir örnek verebilir misiniz?
Brian Scott

1
@Brian: Ne demek istediğin pek açık değil. Eduasync, derleyicinin sizin için yaptıklarına eşdeğer C # kodunu gösterir - ve goto'yu etkili bir şekilde kullanan kodu üretir ...
Jon Skeet

9

goto, break işleminin iyi sonuç vermeyeceği (mesela hata koşullarında) birçok döngüyü kırmak için harikadır ve Kragen'in dediği gibi goto, derleyici tarafından switch ifadeleri ve başka şeyler üretmek için kullanılır.


7
Şüphesiz "kırmak" / "devam etmek", kod editörünün bir sonraki adımın nerede oluştuğunu anlamaya çalışırken kaynak kodu etrafında atlamasını gerektirmekten ziyade döngü yönetimi için daha iyi yaklaşımlardır?
Brian Scott

6
Yuvalanmış döngüleriniz varsa değil.
Jesus Ramos

1
Tamam, bunu geçerli bir senaryo olarak görebiliyorum.
Brian Scott

1
Bir hata durumunda, bir istisna atmayı düşünmelisiniz.
Jodrell

6
Hatayı bir istisna olmaksızın dahili olarak ele almak istiyorsanız, bu bunu yapmanın geçerli bir yolu olacaktır.
Jesus Ramos

8

Hiç kullandığımı hatırlamıyorum goto. Ama belki de gerçekten (çıkışsız istiyorum asla bir sonsuza döngünün niyet geliştirir break, ancak yine de returnya throw):

forever: {
  // ...
  goto forever;
}

Sonra tekrar, basit bir şey while (true)yeterli olmalı ...

Ayrıca, olabilir sen döngü ortasında başlatmak için bir döngünün ilk yineleme istediğiniz yere bir durumda kullanın: bakmak burada bir örnek için.


Bağlantılı cevap bir "ilginç" kullandığını goto.. ve while(true) {..}.. ilginç bir kullanım değildir
user2864740

5

Derleyici goto, üretilen kodun çeşitli parçalarında ifadeler kullanır , örneğin oluşturulan yineleyici blok türlerinde ( yield returnanahtar kelime kullanılarak oluşturulur - oluşturulan XML serileştirme türlerinin de gotoorada bir yerde birkaç ifadeye sahip olduğundan oldukça eminim .

C # derleyicisinin bunu neden / nasıl işlediğine ilişkin daha fazla ayrıntı için Yineleyici blok uygulama ayrıntıları: otomatik oluşturulan durum makineleri konusuna bakın .

Oluşturulan koddan başka, gotonormal kodda bir ifade kullanmak için iyi bir neden yoktur - bu, kodun anlaşılmasını zorlaştırır ve sonuç olarak daha hataya açık hale getirir. Öte yandan goto, üretilen kodda bu gibi ifadelerin kullanılması , oluşturma sürecini basitleştirebilir ve normalde iyidir çünkü kimse üretilen kodu okuyamaz (veya değiştirmez) ve bir makine yazmayı yaptığı için hata yapma şansı yoktur.

Klasik bir programlama geçmişinin yanı sıra karşı bir argüman için zararlı kabul edilen Go-to ifadesine bakın goto.


5
Bu aptalca: Diğer cevapların da gösterdiği gibi yararlı olduğu birkaç durum var. Ya onları açıkça ovalarsınız ya da sadece "yanlış" demek yanlıştır.
o0 '.

@Lohoris Ben satın almıyorum - goto'nun "okunabilirliği artırdığı" (buradaki yanıtlar dahil) gördüğüm her örnek, bazı basit yeniden düzenlemelerden sonra çok daha okunabilir olacaktır .
Justin

4
@Justin hayır, bazen iç içe döngüler bir şeyi yapmanın en doğal yoludur, örneğin bir dizi dizide geziniyorsanız.
o0 '.

7
@Justin, bir fonksiyona sahip olması her zaman daha net değildir. Sadece dini olarak nefret ettiğiniz bir şeyden kaçınmak için (bir goto kullanarak) bir şeyi (bir işlevi olan) zorluyorsunuz. Yanlış bir şey yaptığının açık göstergesi.
o0 '.

4
@Justin Functions çağrılarının ek yükü vardır. gotodeğil. Dikkate alınması gereken bir şey.
Dan Bechard

2

İşlemci en az bir atlama talimatı uygular ve eminim pek çok ifade kendi uygulama veya yorumlamasında bunları kullanır.

3. veya 4. nesil bir dil kullanmanın güzel yanlarından biri, bu fiziksel detayların bizden soyutlanmış olmasıdır. Biz dikkatli olmalı iken sızdıran soyutlama yasa biz de bizim kullanması gerektiğini düşünüyorum maksadı gibi araçları ( üzgün ). Kod yazıyor olsaydım ve gotoiyi bir fikir gibi görünseydi, yeniden düzenleme yapma zamanı gelmişti. Yapılandırılmış bir dilin amacı, bu "sıçramalardan" kaçınmak ve mühendisliğimizde mantıksal bir akış oluşturmaktır.

Kullanımından kaçınmalıyım breakama performans avantajını göz ardı edemem. Ancak, karşılıklı olarak ihtiyaç duyan iç içe döngülerim breakvarsa, yeniden düzenleme zamanıdır.

Eğer herhangi biri gotoyeniden düzenlemeden daha iyi görünen bir kullanım önerebilirse, cevabımı memnuniyetle geri çekeceğim.

Umarım buradaki " bisiklet kulübesine " koşmaktan suçlu değilimdir . Kragen'in dediği gibi, Dijkstra için yeterince iyi olan benim için yeterince iyi.


1
dynamicİhtiyacım olan değerlere ulaşmak için bir nesneyi alıp birden fazla sözlük içeren nesne grafiğini gezdirmek. dynamicHenüz tam bir nesne şekli bekleyen bir parametresi olan yöntemleri kullanmak mantıklı değil . Goto ile birden fazla katmanı ayırın ve bu nesnelerin bir koleksiyonunda yürümeye devam edin. [
Türlere sahip değilim

-6

Goto asla daha iyi değildir. Ve devam et, ara (anahtar / durum dışında), (çoklu) geri dön ve atma da en düşük seviyede tutulmalıdır. Asla yuva döngülerinin ortasından kaçmak istemezsiniz. Her zaman döngü kontrol ifadelerinin tüm döngü kontrolüne sahip olmasını istersiniz. Girintilemede bilgi vardır ve tüm bu ifadeler bu bilgiyi çöpe atar. Tüm girintileri de çıkarabilirsin.


11
Döngünün yürütülmesini sürdürmenin bir anlamı yoksa bir döngüden çıkmak istersiniz. Aksi takdirde, sebepsiz yere daha uzun döngülerde daha fazla işlem süresi boşa harcarsınız.
Skuld

13
@Kirk, bu niceliksel bir şeyden çok bir fikir gibi geliyor?
Brian Scott
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.