Güncelleme
Tamam, başlangıçta ben "derleyici bir foreach
döngü atmalarını ekler." Dedi Bu kesinlikle kesinlikle değil: her zaman döküm eklemek olmaz. İşte gerçekten neler oluyor. Bu foreach
döngü var olduğunda
Her
Öncelikle:
int x;
[object] e;
try
{
e = collection.GetEnumerator();
while (e.MoveNext())
{
x = [cast if possible]e.Current;
}
}
finally
{
[dispose of e if necessary]
}
:
foreach (int x in collection)
{
}
... Burada derleyici yarattıklarından (sözde C#) temel taslak olduğunu Ne? Duyduğunuzu duyuyorum. Eğer [object]
derken neyi kastediyorsunuz?" İşte
demek istiyorum. foreach
döngü aslında aslında biraz büyülü demektir hiçbir arayüz gerektirir. Bu sadece bir ortaya nesnenin tipi de numaralandırılmış gerektirir e
tipi mutlaka bir IEnumerator<int>
uygulanması, hattaolmak zorunda değildir, çünkü kendisi de bir MoveNext
ve Current
özelliğini sağlayan bazı türünün bir örneği sağlaması gerekir GetEnumerator
yöntemi.
yüzden
[object]
yazdım- aynı zamanda
IDisposable
'u (dolayısıyla
[dispose if necessary]
kısmı) uygulamak zorunda olmadığı anlamına da gelir.
Bu soruyu yanıtlamak amacıyla önemsediğimiz kodun bir kısmı, yazdığım bölümdür. Açıkça, derleyici gerçek bir IEnumerator<T>
veya IEnumerator
uygulama gerektirmediğinden, e.Current
türünün T
, object
veya aralarında bir şey olduğu kabul edilemez.Bunun yerine derleyici, derleme zamanında GetEnumerator
tarafından döndürülen türüne göre e.Current
türünü belirler. Daha sonra, aşağıdaki işlemler gerçekleştirilir: tip yerel değişken (yukarıdaki örnekte x
) türüdür
- ise düz bir atama için kullanılır. tip (I yasal döküm
x
tipine e.Current
türünden var anlamına hangi) yerel bir değişken tipine dönüştürülebilir ise
- , bir döküm sokulur.
- Aksi takdirde, derleyici bir hata oluşturur.
Yani bir List<int?>
üzerinde sıralandıran senaryosunda, biz 2. adıma olsun ve derleyici List<int?>.Enumerator
türünün Current
özelliği açıkça int
için dökülebilir tip int?
ait olduğunu görür.
Yani çizgi bunu eşdeğer derlenebilir: Şimdi x = (int)e.Current;
, ne yaptığını Nullable<int>
için benzeri explicit
operatör görünüyor? Reflektör göre
:
public static explicit operator T(T? value)
{
return value.Value;
}
Yani the behavior described by Kent bildiğim kadarıyla söyleyebilirim, olduğunu, sadece bir derleyici optimizasyon: (int)e.Current
açık döküm satır içi.
Sorunuza verilen genel bir yanıt olarak, derleyicimin ekleyeceği yönergelere göre, gerektiğinde foreach
döngüsüne atıyorum.
jenerik önce * hayır IEnumerable<T>
arayüzü, sadece IEnumerable
olduğunu basit bir nedenle bir foreach
döngü içinde gerekli yerlerde derleyici otomatik ekler
atmalarını Orijinal Cevap. IEnumerable
arabirimi, IEnumerator
ortaya çıkarır ve bu da object
türünde Current
özelliğine erişim sağlar.
Derleyici sizin için cast gerçekleştirmedikçe, eski zamanlarda, foreach
kullanmış olmanızın tek yolu, object
türünde yerel bir değişkenin olmasıydı, ki bu açıkça emiliyordu.
* Ve aslında, foreach
doesn't require any interface at all - sadece GetEnumerator
yöntemi ve bir MoveNext
ve Current
ile eşlik eden türü.
Hata bana normal görünüyor. Int'den dönüştürebilirsiniz? int için, ancak bir int dönüştürebilirsiniz. –
@Adrian Bu açıklamanın doğru olduğunu düşünmüyorum. Ya ben bool yerine dize olsaydım. Int dizeye dönüştürülebilir, ancak derleyici protesto ederdi. – nan
Int, dizeye dönüştürülemiyor. Kesin veya açık bir dönüşüm tanımlanmamıştır. ToString() yöntemine başvurursanız, bu farklı bir şeydir. –