2010-11-03 23 views
111

olarak dönüştürülemez. Bu muhtemelen yeni bir sorudur, ancak Google şaşırtıcı bir şekilde yanıt vermemiştir. 'T' türünün değeri,

Ben bu işe umuyordum bu oldukça yapay yöntem

T HowToCast<T>(T t) 
    { 
     if (typeof(T) == typeof(string)) 
     { 
      T newT1 = "some text"; 
      T newT2 = (string)t; 
     } 

     return t; 
    } 

bir C geliyor ++ arka plan var. Bununla birlikte, "T 'türüne' T 'türünü dolaylı olarak dönüştüremiyorum" ve "Yukarıdaki" atamaların her ikisi için "T" türünü "dizgeye dönüştürülemiyor" ile derlenemiyor.

Kavramsal olarak yanlış bir şey yapıyorum ya da yanlış sözdizim var. Lütfen bunu düzeltmeme yardım edin.

Teşekkür ederiz!

+14

IMO, kendi jenerik kodunda türlerini kontrol ediyoruz, o jenerik muhtemelen doğru çözüm değildir senin sorun. –

+0

'typeof (T) == typeof (string)' ifadesi, derleme zamanı değil, çalışma zamanında çözülür. Böylece blokta aşağıdaki satır geçersizdir. –

+6

(T) Dönüştürün.ChangeType (newT1, typeof (T)) – vsapiha

cevap

218

if bloğunun içinde olsa bile, derleyici T'un string olduğunu bilmez.
Bu nedenle, yayınlamanıza izin vermiyor. Ve oradan string için Sen (herhangi bir T yayın yapabilirsiniz) object, yayın yapmak için ihtiyaç

(DateTimestring Sizin döküm olamaz Aynı nedenle) (object beri string için dökülebilir). Örneğin
:

T newT1 = (T)(object)"some text"; 
string newT2 = (string)(object)t; 
+2

Bu işe yarıyor! Sanırım ikinci sanırım da T newT2 = (T) (object) t olmalıdır; Her ne kadar bu bir hayır. – Alex

+2

Ek: C++ şablonları esas olarak, doğru değerler kullanılarak derleme zamanında kes ve yapıştır. C# içinde asıl jenerik şablon (bir "somutlaştırma" değil) derlemeden sonra vardır ve bu nedenle (puntayı affetmek) belirtilen tip sınırları boyunca jenerik olmalıdır. –

+0

(string) (object) t; burada hiçbir şey yapmaz, bunu da dışarıda bırakabilir, (dize) (nesne) – Doggett

8

iki hat aynı problemi

T newT1 = "some text"; 
T newT2 = (string)t; 

derleyici T bir dize olduğunu biliyoruz ve böylece nasıl atanacağı bilmenin bir yolu vardır vermez var. Ama sadece zaten bir dize olacağından ayrıca kısıtlama eklemek gerekir, t döküm gerekmez

T newT1 = "some text" as T; 
T newT2 = t; 

ile zorlayabilirsiniz kontrol beri

where T : class 
+2

Yanlış. Bu derlenmeyecek. Cevabımı gör. – SLaks

+1

Sadece iyi bir derleme (burada, gönderildikten birkaç saniye sonra bunu kaçırmış olabilir). Oops nm, – Doggett

1

iseniz açık türleri kontrol etmek, neden bu değişkenleri T 'ler olarak ilan ediyorsunuz?

T HowToCast<T>(T t) 
{ 
    if (typeof(T) == typeof(string)) 
    { 
     var newT1 = "some text"; 
     var newT2 = t; //this builds but I'm not sure what it does under the hood. 
     var newT3 = t.ToString(); //for sure the string you want. 
    } 

    return t; 
} 
+4

yayınını değiştirmeyi unuttu. İkinci satır, "T" türünde bir değişken oluşturur. – SLaks

+0

Sorunu neden kontrol ettiğinizi sorabilirsiniz. "String" değerlerini saklayan türetilmiş türlerle "object" değerlerini saklayan bir taban alan türünüz olduğunu varsayalım. Bu alanların da bir "DefaultIfNotProvided" değerine sahip olduğunu varsayalım, bu yüzden kullanıcı tarafından sağlanan değerin (bir nesne veya bir dize veya sayısal bir ilkel bile olabilir) "varsayılan (T)" değerine eşit olup olmadığını kontrol etmeniz gerekir. Dize, boş/beyaz bir dizenin varsayılan (T) ile aynı şekilde ele alındığı özel bir durum olarak ele alınabilir, bu nedenle "T userValue; var isBlank = (userValue dizedir) && String.IsNullOrWhitespace (string olarak userValue); '. – Triynko

-2

Değişim bu satırı: Bu hat için

if (typeof(T) == typeof(string)) 

: Eğer sınıfın ve yöntemin her ikisi için genel bir deklarasyon varsa

if (t.GetType() == typeof(string)) 
+1

onlar aynı – bigworld12

0

de bu hatayı alırsınız. Örneğin, aşağıda gösterilen kod bu derleme hatasını verir.

public class Foo <T> { 

    T var; 

    public <T> void doSomething(Class <T> cls) throws InstantiationException, IllegalAccessException { 
     this.var = cls.newInstance(); 
    } 

} 

Bu kod (T yöntem bildirimi kaldırıldı notu) derliyor:

public class Foo <T> { 

    T var; 

    public void doSomething(Class <T> cls) throws InstantiationException, IllegalAccessException { 
     this.var = cls.newInstance(); 
    } 

} 
İlgili konular