C # 'da "satır içi" dizi kullanamıyor musunuz?


92

Bunun bir yerde olduğunu hayal et

public static T AnyOne<T>(this T[] ra) where T:class
    {
    int k = ra.Length;
    int r = Random.Range(0,k);
    return ra[r];
    }

ya da sadece bu

public static string OneOf(this string[] strings)
    {
    return "a";
    }

O zaman tabii ki bunu yapabilirsiniz ...

string[] st = {"a","b","c"};
string letter = st.AnyOne();

... ki bu harika. FAKAT. Görünüşe göre bunu YAPAMAZSINIZ:

string letter = {"a","b","c"}.AnyOne();

ya da gerçekten belki bu

string letter = ( {"a","b","c"} ).AnyOne();

ya da denediğim başka bir şey.

Aslında (1) neden bunu yapamazsın? ve (2) bir şey mi kaçırıyorum, bir yolu varsa bunu nasıl yaparsın?


5
Yinelenen sorunun uygun olduğundan emin değilim, OP dizi başlatıcıları sormuyor, ancak derleyicinin nesneyi atanana kadar neden bir dizi olarak tanımayacağını.
Ron Beyer

4
C # terminolojisine aşina değilim, ancak bunun daha çok bir satır içi olmaktan ziyade değişmez veya bir dizi değişmez olarak adlandırıldığına inanıyorum .
chi

3
Sözdizimsel öğe , kullanıldığı bağlama bağlı olarak bir dizi başlatıcı veya koleksiyon başlatıcıdır . Her iki durumda da bir ifade olarak sınıflandırılmaz .
Eric Lippert

Yanıtlar:


133

Önce diziyi kullanarak oluşturmanız gerekir new[].

string letter = (new[] {"a","b","c"}).AnyOne();

@Hvd'nin bahsettiği gibi bunu parantezler olmadan yapabilirsiniz (..), parantezleri ekledim çünkü daha okunabilir olduğunu düşünüyorum.

string letter = new[] {"a","b","c"}.AnyOne();

Ve new string[]diğer cevaplarda da bahsedildiği gibi veri tipini belirtebilirsiniz .


Bunu yapamazsınız {"a","b","c"}, çünkü diziyi yaratmak için değil, diziyi doldurmanın bir yolu olarak düşünebilirsiniz.

Diğer bir neden de derleyicinin kafasının karışması, ne yaratacağını bilememesi, örneğin a string[]{ .. }veya a olacaktır List<string>{ .. }.

Sadece new[]derleyiciyi kullanmak veri türüne göre ( "..") {..}, ne arasında ne istediğinizi ( string) bilebilir . Önemli olan [], bir dizi istediğiniz anlamına gelir.

İle boş bir dizi bile oluşturamazsınız new[].

string[] array = new []{ }; // Error: No best type found for implicity-typed array

13
O parantezlere ihtiyacınız yok. string letter = new[] {"a","b","c"}.AnyOne();gayet iyi. Onları istiyorsanız, parantezlerle daha okunabilir olduğunu düşünüyorsanız, geçerlidir, ancak bu durumda en azından sizin açınızdan bilinçli bir seçim olduğunu, dil tarafından zorlanmadığını belirtmeye değer olduğunu düşünüyorum.

Yeni [] {1,2} sözdizimini biliyorum, ancak daha da basit bir sözdizimi var mı? [1, 2] gibi bir şey?
seguso

51

(1) Bunu neden yapamazsınız? {"a","b","c"}.AnyOne();

Bu hat:

string[] st = {"a","b","c"};

eşdeğer bir dizi oluşturma ifadesi için kısa bir eldir ( ILSpy altında )

string[] st = new string[]  {"a","b","c"};

Bu string[] st = {"a","b","c"} sadece beyan anında kullanılabilir, başka bir yerde kullanamazsınız, hatta yapamazsınız:

string[] st;
st = {"a", "b", "c"}; //Error

C # dili belirtimlerinde Dizi Oluşturma ifadesi için Bölüm 7.6.10.4 altında açıklanmıştır .

Dolayısıyla "{"a", "b", "c"}", beyanda kullanılmadan bu tek başına hiçbir şey ifade etmez. Dolayısıyla, uzantı yönteminiz bir dizi üzerinde çalıştığından, onu uzantı yönteminizle kullanamazsınız.

(2) Bir şey mi kaçırıyorum, bir yolu varsa bunu nasıl yaparsın?

Zaten @ adricadar en belirtilen cevap , yapabileceğiniz:

(new[] {"a","b","c"}).AnyOne();

veya

(new string[] {"a","b","c"}).AnyOne();

48

"Neden olmasın" sorularını geri itiyorum çünkü ilk olarak, cevaplar neredeyse hiçbir zaman tatmin edici değil - "özellik istediğiniz gibi değil çünkü şartname ne söylemesini istediğinizi söylemiyor" cevabını zaten almışsınızdır. Sanırım özellikle tatmin edici bir cevap değildi. İkincisi, tasarım ekibinin dünyanın neden istediğiniz gibi olmadığını haklı göstermesi gerekmez; özellikler ücretsiz olarak mevcut değildir ve daha sonra dil dışında tasarlanır; bunun yerine, özelliklerin önce gerekçelendirilmesi ve ardından tasarlanması gerekir.

Öyleyse "neden olmasın" sorunuzu biraz daha netleştirmeye çalışalım. Mevcut özellik, "(a) eşitlerin sağ tarafında bir başlatmada veya (b) dizi tipindeki bir nesne yapısının sağında bir dizi başlatıcı kullanılabilir." Önerilen özellik şudur: "bir dizi başlatıcı da bir ifade olarak kullanılabilir". Soru, "Eric önerilen özellik hakkında ne eleştirirdi?"

Yapacağım ilk eleştiri, ifadenin türünün net olmadığıdır. Bir değişken başlatıcıda değişkenin türüne sahipsiniz ve bir nesne oluşturma ifadesinde nesnenin türüne sahipsiniz; bunların her ikisinden de inşa edilen dizinin türünü çıkarabiliriz. Herhangi bir ipucu olmadan, hangi tür sonuca varmalıyız?

C # 1.0'da, bu özellik eklendiğinde, dilde genel toplam sıfır tipi çıkarımlar yapıldı. C # 'ın ilk günlerinde bir tasarım ilkesi "sürpriz yok" idi ve derleyici "çok akıllı" değildi. Geliştirici, bir ifadenin belirli bir türde olmasını isterse, bu tür ifadede bir şekilde açık olmalıdır. Dediğinde

new double[] { 1, 2, 3.4 }

hangi türün amaçlandığı oldukça açık. benzer şekilde

new Animal[] { cat, dog, null }

Önerilen özellik bu prensibi ihlal ediyor. İfadenin bir türü olmalıdır, ancak hiçbir şekilde argümanın türünün ne olduğu açık değildir.

M({cat, dog, null})

Dahası: MBiri bir dizi, Animaldiğeri bir dizi alan iki aşırı yüklememiz olduğunu varsayalım IPet. Hangi aşırı yük Muygulanabilir? Dönüşümlerden biri diğerinden daha mı iyi? Elemanların türleri Catve Dog; Orada görünmeyen bir türü çıkarmak mantıklı mı? Bunların hepsi tasarım ekibi tarafından dikkate alınması gereken sorulardır ve bunlar hiçbir şekilde açık cevapları olmayan sorulardır. Önerilen özellik bizi oldukça kısa bir sırayla derin sulara götürür.

Şimdi, C # 3.0 bu sorunu çözüyor çünkü C # 3.0, derleyicinin geliştirici adına türler belirlediği çok sayıda özellik ekledi. "Sürpriz yok" ve "basit kurallar" hakkındaki önceki ilkeler, LINQ'nun çalışması için gereken diğer tasarım ilkeleriyle çelişiyordu. Önerdiğiniz özellik C # 3.0'a eklenmeli mi?

Olabilirdi. Gerçekte C # 3.0'da eklenen özellik şuydu:

new[] { x, y, z }

algoritmayı kullanarak dizinin türünü ortaya çıkarır: türleri olan öğelerin ifadelerini alın, bu türlerden hangisinin diğer tüm ifadelerin dönüştürülebileceği en genel benzersiz tür olduğunu belirleyin ve böyle bir tür varsa, bunu seçin. Aksi takdirde bir hata oluşturur,

Bu özellik, new[]isteğe bağlı hale getirmek için daha da gevşetilebilirdi . Bu yapılmadı.

Şimdi, C # 3.0 zaman diliminde benden önerilen özelliği eleştirmemi isteseydiniz, (1) C # 3.0 derleyicisinin zaten tüm sürüm için çizelgeyi kayma tehlikesiyle karşı karşıya olduğunu belirtmiştim, bu yüzden daha fazlasını eklemeyelim kullanıcıyı altı tuş vuruşundan kurtaran tamamen gereksiz bir özellik için tasarım, uygulama ve test yükü ve (2) C # 3.0 ayrıca koleksiyon başlatıcıları ekledi:

new List<int>() { 10, 20, 30 }

neden {10, 20, 30}otomatik olarak bir dizi olmalı ? Neden a olmamalı List<int>? Veya başka türlerden herhangi biri? Neden dizilere yönelik önyargı? Unutmayın, diziler için sözdizimini saklamayı seçtiğimizde, sonsuza dek ona bağlı kalacağız . Asla başka bir şey olmayabilir , bu nedenle önerilen özellik sadece gereksiz olmakla kalmaz, aynı zamanda makul görünen gelecekteki olası özellikleri de engeller.

Özetle: Önerilen özellik, C # 1.0'ın bazı tasarım ilkelerini doğrudan ihlal etti. C # 3.0'a gereksiz yükten başka bir şey eklemiyor. C # 3.0'dan bu yana dilin tüm sürümlerinde, önerilen özelliğin diğer birçok değerli özelliğe göre zaman, çaba ve para harcamayı önerecek iyi bir argümanı yoktur.

Dolayısıyla böyle bir özellik yok.


Heh, üzerine "Dünya senin istediğin gibi değil" yazılı bir
tişört almalısın

6
@JoeBlow: Öncelikle, çok hoş geldiniz. "Neden olmasın" ile ilgili - yorumunuz sorunu güzel bir şekilde gösteriyor. Bazı insanlar "neden" sorusu sorduğunda mantıklı bir gerekçe ararlar . Bazı insanlar pragmatik bir gerekçe arıyorlar . Ve görünüşe göre kuralı açıklayan şartname satırını arıyorsunuz . O kadar belirsiz ki, soruyu soran kişinin zihnindeki soruyu hedef alan iyi bir cevap oluşturmak çok zordur. "Neden olmasın" soruları daha da kötüdür çünkü var olmayan şeyler hakkında belirsiz sorulardır .
Eric Lippert

3
@EricLippert Bu, var olabilecek şeyler hakkındaki sorudan bile daha kötü : Bir ekiple yazılım üzerinde çalışıyorsanız, tüm ekip yılın her gününü özellikler hakkında düşünerek ve sonuçları dengeleyerek geçirir. Kararlar verilir. Özellik istekleri ve 'neden' gerekçesini sorar. Bununla birlikte, neden birisinin sadece bir şeyin yapılmasını istediğini ima etmiyor , bu da temelde ekibin kendi yargısını sorguluyor. Daha da kötüsü, neden olmasın sorusunu soran kişi konu hakkında genellikle çok az şey bilir. Bu nedenle, neden sorulmadığını geri itmenin tamamen adil olduğunu düşünüyorum . İyi iş IMO.
atlaste
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.