Soru Derleyici neden var [] nesnesini c # olarak dönüştürmez?


Bu iki satır arasında fark yoktur, çünkü derleyici, ikinci satırda, bunun bir tür dizi olduğunu anlar. int.

var x = new int[] { 1, 2, 3 };   //Fine, x is int[]
var x = new [] { 1, 2, 3 };      //Fine, x is int[]

Ama bunu neden farklı türlerde yapamıyorum? Derleyici neden değişkeni türüne dönüştürmez? nesne?

var x = new object[] { 1, "df", 5 };   //Fine, x is object[]
var x = new [] { 1, "df", 5 };         //Error! "No best type found for implicity-typed-array"

DÜZENLE:

Bütün cevapların için teşekkürler. Ama yine de merak ediyorum, derleyicinin türe dönüşemediği tüm ifadeleri yapmak için artıları ve eksileri nelerdir? object? (Çünkü kullanıyorum var notasyon, herhangi bir tür olamaz anlamına gelir. Bu şekilde anladım.) Derleyici neden devralma ağacına giderek en yakın dizi üyelerini bulmuyor?


32
2018-01-17 08:13


Menşei


C # spesifikasyonunu okudun mu? - BoltClock♦
Evet, ama soru çoğunlukla "neden bu şekilde uygulanmadı?" - Chuck Norris
Damien_The_Unbeliever'in Joey'nin cevabı hakkındaki yorumu, her şeyi söylüyor. Derleyici için çok fazla iş var, inferring söz değil object[] Sonuç olarak benim için oldukça karşı sezgisel. - BoltClock♦
Belki de onun nedeni langauge tasarımcılarının nesne dizilerini kokuşturacakları ve C # 'yı kokulu bir şekilde kullanmanın kolay olmasını istemedikleri için. - Jodrell
FYI, var anahtar kelimenin sorunuzla ilgisi yoktur. object[] x = new[] { 1, "df" }; ya da çalışmıyor. - Joren


Cevaplar:


new [] notasyon, dizi üyelerinin açık bir türünü (veya öğelerinin anonim bir türünün bulunduğu diziler oluşturmanıza olanak tanıyan) yazmanızı sağlar, ancak tür çıkarsamaları tüm öğelerin aynı türünü paylaşması veya örtük olarak dönüştürülebilir olması gerektiğinden En az bir üye tarafından paylaşılan ortak bir tür. Bkz. C # Belirtimi, bölüm 7.6.10.4:

Üçüncü formun bir dizi yaratma ifadesi, örtük olarak yazılan bir dizi oluşturma ifadesi olarak adlandırılır. Dizinin eleman tipinin açıkça belirtilmediği, ancak dizi başlatıcısındaki ifade kümesinin en yaygın türü (§7.5.2.14) olarak belirlendiği dışında, ikinci forma benzerdir.

Aşağıdaki, örtülü olarak yazılan dizi oluşturma ifadelerinin örnekleridir:

var a = new[] { 1, 10, 100, 1000 };                       // int[]
var b = new[] { 1, 1.5, 2, 2.5 };                         // double[]
var c = new[,] { { "hello", null }, { "world", "!" } };   // string[,]
var d = new[] { 1, "one", 2, "two" };                     // Error

Son ifade, bir derleme zamanı hatasına neden olur çünkü ne ikisi de int ne de string örtük olarak diğerine çevrilebilir ve bu yüzden en yaygın türü yoktur. Bu durumda açıkça yazılmış bir dizi oluşturma ifadesi kullanılmalıdır; object[]. Alternatif olarak, elemanlardan biri, sonradan türetilmiş eleman tipi olacak olan ortak bir taban tipine dökülebilir.

Burada önemli olan nokta, “en iyi ortak tip” in sadece halihazırda mevcut olan tiplerden biri olabileceğidir. Gibi Damien_The_Unbeliever bir yorumda belirtildi: “Bay Lippert çıkarsamaya dikkat çekerken, en iyi ortak türü ararken, sadece halihazırda mevcut olan türlerden birini geri getirecektir - en türetilmiş ortak ata için avlanmayacaktır.”.

Çünkü her dizi bir object [] olması gerektiği anlamına gelmez. Derleyici açısından bakıldığında, son derece ucuz bir tatil yeri tercihi olacak, ama geliştiriciye karşı çok sezgisel olanı sanırım.


38
2018-01-17 08:15



Ve neden böyle bir dönüşüm sağlamak için yeni [] uygulanmadı? Bunun eksileri neler? - Chuck Norris
Hayır, yeni [] gösterim esas olarak anonim tiplerin dizilerini kolaylaştırmak içindir. Yazmayı kaydetmek sadece güzel bir yan etki. - Stilgar
niye ya Eric Lippert'in cevap verebileceği bir şey olabilir. Tarihte biraz bulanıkım ama tam gelişmiş bir çıkarım geldi var, olabilir new [] bunu önceden yapar. - Joey
Ekle new Object() diziye ve iyi derler. Bay Lippert çıkarsamaya dikkat çekerken, en iyi ortak türü ararken, sadece halihazırda mevcut olan türlerden birini geri getirecektir - en çok türetilen ortak ata için avlanmayacaktır. - Damien_The_Unbeliever
Damien, teşekkürler. Bunu ekledim. Dürüst olmak gerekirse, doğru bir şekilde dalışa girerseniz, o bölümün o kısmının anlaşılması oldukça zordur. - Joey


Joey'in cevabını genişletmek için bu örneği düşünün:

interface IFoo { }
interface IBar { }

class A : IFoo, IBar { }
class B : IFoo, IBar { }

var array = new [] { new A(), new B() };

Her iki sınıf da hem arayüzleri uygular (hem de object), hangi tür için çıkarılmalıdır array?


Yorumunuza cevap vermek için durumu düşünün A ve B sadece bir arayüz paylaşın:

interface IFoo { }

class A : IFoo { }
class B : IFoo { }

var array = new [] { new A(), new B() };

Her ikisi de A ve B pay object temel sınıfları olarak, ancak yararsız ve dizi türü için bunu çıkarmak için çoğunlukla işe yaramaz olurdu. Birinin olmasını beklerdi IFoo eğer bir şey varsa, bu yüzden en az şaşkınlık ilkesi. Ancak, bu, resmediğim gibi tutarlı bir şekilde yapılamaz.

Buradaki en güvenli ve en tutarlı davranış, tür çıkarımına izin vermemek.


18
2018-01-17 08:23



+1. Biz her zaman .NET'i unutmaya eğilimliyiz yapar Birden fazla kalıtım desteği (sadece arayüzler aracılığıyla olsa da). - Heinzi
Evet, güzel örnek. Ama bu örnekte neden nesneye dönüşemiyor? Her ikisinin de miras aldıkları en yakın türü bulabilir. Birden fazla kalıtım yok, o yüzden tek ağaç dalını arayabilir ... - Chuck Norris
@mesiesta: Sadece bir ortak tabana sahip olabilirler sınıfAncak, bu neden uygulamalı arayüzleri üzerinde öncelikli olmalıdır? Arayüzler de türleridir. - Will Vousden
Evet, biliyorum ... Arayüzlere bakmamayı kastediyorum ... Sadece ana sınıfa bak (sadece bir tane olabilir). - Chuck Norris
Fakat temel sınıflar neden arayüzlerden daha önemli? Güncellemeye bakın: Bazen arayüzler temel sınıflardan daha önemlidir. - Will Vousden