C# CS0029 hatası, derleyici bir değeri kaynak türünden hedef türüne örtük olarak çevirecek uygun dönüşümü bulamadığında ortaya çıkar. Hata mesajındaki Cannot implicitly convert type ifadesi, önce kaynak ve hedef türü karşılaştırmanız gerektiğini gösterir; çözüm her zaman doğrudan cast yazmak değildir.
Önce dönüşümün yönünü, ardından değerin sayısal mı, metinsel mi, nullable mı yoksa nesne tabanlı mı olduğunu belirleyin. Bu ayrım, güvenli ve doğru yöntemi seçmenizi sağlar.
CS0029 hatası ne anlatır? Kaynak ve hedef türü okuyun
C# dilinde atama yapılırken sağ taraftaki ifade, sol taraftaki değişkenin türüne uygun olmalıdır. Sağ taraftaki değer kaynak tür, sol taraftaki değişken ise hedef tür olarak düşünülebilir. Derleyici bu iki tür arasında otomatik, yani örtük bir dönüşüm bulamazsa CS0029 hatasını üretir. Microsoft’un derleyici başvurusundaki temel hata metni Cannot implicitly convert type 'type' to 'type' biçimindedir.
Örneğin:
int hedef = "42";
Hata mesajı: Cannot implicitly convert type 'string' to 'int'. Burada kaynak tür string, hedef tür ise int değeridir. "42" ekranda sayı gibi görünse de C# açısından hâlâ metindir. Metni sayıya çevirmek için sayısal dönüşüm değil, ayrıştırma veya uygun bir dönüştürme yöntemi gerekir.
Dönüş yönü ters olduğunda hata mesajı da tersine döner:
string metin = 42;
Hata mesajı: Cannot implicitly convert type 'int' to 'string'. Bu örnekte kaynak tür int, hedef tür string türüdür. Buradaki ihtiyaç, metni sayıya çevirmek değil, sayısal değerin metinsel gösterimini elde etmektir.
Aynı tür uyuşmazlığı yalnızca değişken atamalarında görülmez. Bir metodun dönüş türü de hedef tür gibi davranır:
static int YasGetir()
{
return "42";
}
Hata mesajı: Cannot implicitly convert type 'string' to 'int'. Kaynak tür string, hedef tür metodun bildirdiği int türüdür. Benzer biçimde bir metoda parametre gönderirken de kaynak ve hedef türler karşılaştırılır:
static void Yazdir(int sayi)
{
}
Yazdir("42");
Burada kaynak tür string, hedef parametre türü int değeridir. Derleyicinin bu durumda bildireceği tanı CS0029 olmak zorunda değildir; ancak teşhis aynıdır: gönderilen değer ile beklenen tür uyuşmamaktadır.
Bu nedenle çözümü yalnızca (int) veya (string) yazarak aramayın. Cast, özellikle sayısal türler arasında açık dönüşüm gerektiğinde kullanılabilir; fakat string içeriğinin gerçekten sayı olup olmadığını kontrol etmez. Ayrıca bazı cast işlemleri veri kaybına, taşmaya veya çalışma zamanında hataya yol açabilir.
Hata mesajından uygun çözümü seçmek için dört kollu teşhis akışı

Önce dönüşümün yönünü ve veri kaybı riskini belirleyin, sonra uygun yöntemi seçin. Hata mesajındaki kaynak → hedef çiftini aşağıdaki dört kollu akışla değerlendirebilirsiniz:
- Sayısal türden sayısal türe:
int,long,doubleveya benzeri iki sayısal türü karşılaştırın. Hedef tür daha geniş bir aralık sunuyorsa örtük dönüşüm mümkün olabilir. Aralık daralıyor ya da kesirli bölüm kaybolabiliyorsa açık dönüşüm gerekir. Bu noktada “Aralık daralıyor mu?”, “Veri kaybı veya taşma olabilir mi?” sorularını sorun. - Metinden sayıya: Kaynak tür
stringise asıl problem çoğu zaman türden çok biçimdir. Kullanıcı veya dosya verisi geçersiz olabilir mi? Geçersiz giriş bekleniyorsaTryParse; geçersizliği hata olarak ele almak istiyorsanızParse; dönüşüm ihtiyacının bağlamına göreConvertseçeneklerini değerlendirin. Bu üç yöntemi cast ile karıştırmayın. - Nullable türden normal türe: Kaynak
int?gibi nullable bir tür, hedef iseintgibi normal bir türse önce “Değernullolabilir mi?” sorusunu yanıtlayın. Null için varsayılan değer kullanmak, işlemi durdurmak veya nullable türü korumak arasında bilinçli seçim yapmadan doğrudan değeri açmak güvenli değildir. objectveya temel türden belirli nesne türüne: Gerçek nesne türünden emin misiniz? Emin değilseniz cast işlemi yerineisile kontrol ederek dallanmayı, null kabul edilebilir bir sonuçsaaskullanımını değerlendirin. Doğrudan cast, çalışma zamanında başarısız olabilir;istür uyumluluğunu sınar,asise uygun olmayan dönüşümdenulldöndürebilir.
Kısa karar kuralı şudur: Geçersiz biçim varsa ayrıştırma, null ihtimali varsa null kararı, daralan sayısal aralık varsa veri kaybı kontrolü, belirsiz nesne türü varsa çalışma zamanı tür kontrolü yapın. Böylece cast, her CS0029 hatasına verilen otomatik cevap olmaktan çıkar ve yalnızca gerçekten uygun olduğu durumda kullanılır.
Sayısal dönüşümlerde implicit, explicit ve cast kullanımı
CS0029 sayısal türlerde görüldüğünde önce kaynak türü, hedef türü ve dönüşüm yönünü belirle. Kaynak türün değeri güvenle taşıyabildiği daha geniş bir hedef türe geçiyorsan implicit conversion otomatik yapılır; daha dar türe geçişte ise explicit conversion ve çoğunlukla cast gerekir.
int kaynakInt = 42; // kaynak türü: int
long hedefLong = kaynakInt; // hedef türü: long, implicit conversion
long türünden int türüne geçişte kaynak değer hedef türün aralığına sığmayabileceği için derleyici senden açık izin ister:
long kaynak = 42; // kaynak türü: long
int hedef = (int)kaynak; // hedef türü: int, explicit cast
Ancak cast yalnızca derleyiciyi susturan bir işaret değildir; dönüşümün sonucunu da etkileyebilir. double değerinden int değerine geçerken ondalık kısım sıfıra doğru kesilir:
double kaynak = 12.8; // kaynak türü: double
int hedef = (int)kaynak; // hedef türü: int; değer 12 olur
Benzer şekilde, daha büyük aralıklı bir türden daha dar aralıklı türe geçişte değer hedef türün sınırlarını aşabilir. Bu nedenle cast eklemeden önce veri kaybının kabul edilebilir olup olmadığını ve değerin hedef aralığında kalıp kalmadığını kontrol et.
Aralık kontrolünü zorunlu kılmak için dönüşümü checked bağlamında yazabilirsin. Kaynak değer hedef türün aralığı dışındaysa ilgili dönüşümde OverflowException oluşabilir; unchecked bağlamında ise sonuç hedef tür açısından beklenmeyen bir değere dönüşebilir. Davranış, dönüşüm türüne ve kullanılan hedefe göre kontrol edilmelidir. Özellikle en küçük, en büyük, sıfır, negatif ve ondalıklı sınır değerleri test et.
static int ToInt(long kaynak) // kaynak türü: long
{
return checked((int)kaynak); // hedef türü: int
}
Son olarak cast, string ile int arasındaki metinsel dönüşümü kendi başına yapmaz. Kaynak türü string, hedef türü int ise parsing gerekir; bunun için Parse, Convert veya özellikle kullanıcı girdilerinde TryParse yöntemlerini değerlendirmelisin.
Metinden sayıya dönüşüm: Parse, Convert ve TryParse farkı

string → int dönüşümünde seçim, metnin ne kadar güvenilir olduğuna ve başarısızlığın nasıl ele alınacağına bağlıdır. int.Parse doğrudan değer döndürür, Convert.ToInt32 farklı giriş türleri için çeşitli overload'lar sunar, int.TryParse ise başarısızlığı istisna yerine bool sonuçla bildirir.
| Yöntem | Uygun senaryo | Geçersiz veya null girdide ele alış | Sonuç |
|---|---|---|---|
int.Parse |
Metnin geçerli olduğu biliniyorsa veya hata istisna akışıyla yönetilecekse | Parse(string) için null değer ArgumentNullException, biçim hatası FormatException, aralık aşımı OverflowException oluşturur. |
Kaynak string değerini hedef int değerine dönüştürür veya istisna oluşturur. |
Convert.ToInt32 |
string, object ve çeşitli temel sayısal türlerden int değerine geçişte |
Davranış overload'a bağlıdır. ToInt32(string) için null sonuç 0 olabilir; biçim ve aralık hataları istisna oluşturabilir. ToInt32(object) desteklenmeyen türde InvalidCastException oluşturabilir. |
Seçilen overload'ın kurallarına göre hedef int değeri veya istisna döner. |
int.TryParse |
Kullanıcıdan, dosyadan veya dış sistemden gelen güvenilmez metinlerde | null, boş, biçimi hatalı veya int aralığı dışındaki girişlerde false döner; bu overload'da out sonuç 0 olur. |
Başarıda true ve out int değerini, başarısızlıkta false döndürür. |
Bu nedenle Parse ve Convert için null, biçim ve aralık davranışını tek bir genel kurala indirgeme; kullandığın overload'ın resmî belgede belirtilen davranışını kontrol et. Convert.ToInt32(string), string dönüşümünde Parse ile benzer biçim kurallarını izlerken Convert.ToInt32(object) gerçek nesne türü ve IConvertible desteği açısından farklı değerlendirilebilir.
string girdi = Console.ReadLine() ?? ""; // kaynak türü: string
if (int.TryParse(girdi, out int sayi)) // hedef türü: int
{
Console.WriteLine($"Geçerli sayı: {sayi}");
}
else
{
Console.WriteLine("Geçersiz tam sayı.");
}
Beklenen çıktı: Girdi 42 olduğunda Geçerli sayı: 42; girdi abc olduğunda Geçersiz tam sayı. mesajı yazdırılır. Böylece hatalı metin uygulamayı durdurmadan ayrı bir akışta karşılanır.
Nullable ve object türlerinde null ve gerçek tür kontrolü
Nullable türlerde: int? ile int aynı değildir
int?, bir tam sayı değerinin yanında null yani “değer yok” durumunu da taşıyabilir. int ise doğrudan null alamaz. Bu nedenle kaynak türü int?, hedef türü int olan doğrudan atama güvenli kabul edilmez; çünkü kaynak değişkenin o anda gerçekten bir değer içerip içermediği bilinmeyebilir.
int? stok = 8; // Kaynak türü: int?
int adet = stok; // Hedef türü: int — doğrudan atama sorunlu
if (stok.HasValue)
{
int kesinAdet = stok.Value; // Kaynak: int?; hedef: int
}
HasValue kontrolü, Value özelliğini kullanmadan önce değerin mevcut olduğunu doğrular. Değer null iken Value okumaya çalışmak derleme hatası yerine çalışma zamanında istisnaya yol açabilir. Nullable değer ile int arasında her durumda aynı tanı kodunun üretileceğini varsaymak yerine, hata mesajındaki kaynak ve hedef türleri incelemek gerekir.
Hedef değişkenin mutlaka int olması gerekiyorsa, ?? ile bir yedek değer seçebilirsin:
int? puan = null; // Kaynak türü: int?
int sonuc = puan ?? -1; // Hedef türü: int
Buradaki -1 rastgele seçilmemelidir. Null değer “henüz hesaplanmadı”, “kayıt bulunamadı” veya “kullanıcı veri girmedi” anlamına gelebilir. İş kuralı bilinmiyorsa otomatik olarak sıfır atamak, gerçek bir sıfır ile eksik değeri birbirine karıştırabilir. Gerekirse değeri int yerine int? olarak korumak daha doğru olabilir. ??, nullable bir değerden non-nullable hedefe geçerken açık bir varsayılan belirlemek için kullanılır.
object türünde: gerçek çalışma zamanı türünü kontrol edin
object değişkeni farklı türlerdeki değerleri taşıyabilir; fakat dönüşüm kararı değişkenin yalnızca bildirim türüne göre değil, içindeki gerçek çalışma zamanı türüne göre verilmelidir. Örneğin kaynak türü object, hedef türü int olan aşağıdaki cast, metni sayıya dönüştürmez:
object veri = "42"; // Kaynak türü: object
int sayi = (int)veri; // Hedef türü: int — çalışma zamanında başarısız
Çünkü nesnenin gerçek türü string’dir. Metin gerçekten sayıya çevrilecekse önce string kontrolü, ardından metin ayrıştırma yapılmalıdır:
if (veri is string metin &&
int.TryParse(metin, out int sayi))
{
Console.WriteLine(sayi);
}
Gerçek türün kesin olduğu durumda cast kullanılabilir. Örneğin object veri = 42 için kaynak türü object, hedef türü int olan (int)veri anlamlıdır. Türün önceden bilinmediği durumda is, kontrol ile birlikte güvenli atama yapmayı sağlar. Başarısızlığı istisna yerine null üzerinden ele almak uygunsa as tercih edilebilir:
string? metin = veri as string; // Kaynak: object; hedef: string?
as uyumsuzlukta null döndürür; ancak int gibi non-nullable değer türlerinde kullanılamaz. Referans türleri veya nullable değer türleri, örneğin int?, bu operatörün kullanılabildiği bağlamlardır. Ayrıca as bir string’i sayıya ayrıştırmaz; bunun için TryParse gibi ayrı bir yöntem gerekir.
CS0029 çözümünden sonra uygulanacak kısa kontrol listesi
- Hata mesajındaki kaynak türü yaz.
- Hedef türü açıkça yaz.
- Dönüşüm yönünü kaynak türden hedef türe bir okla göster.
- Verinin metin veya
nullolma ihtimalini değerlendir. - Sayısal aralık, taşma ve ondalık kaybı riskini kontrol et.
- Cast kullanımının gerçekten anlamlı olup olmadığını sorgula.
- Kullanıcı girdisinde
TryParseseçimini gerekçelendir. - Nesne türünde
is,asveya cast seçimini gerçek çalışma zamanı türüne göre yap. - Hem başarılı hem de başarısız senaryoyu test et.
C# tür dönüşümleri ve temel bilgi düzeyini yoklamak istersen, Berk Akademi’nin ücretsiz C# seviye testini çözebilirsin.
Tür dönüşümünde güvenli sonuç, yalnızca hatayı susturmaktan değil, kaynak değerin gerçekten ne ifade ettiğini doğru belirlemekten geçer.