Ini mungkin pertanyaan pemula, tetapi secara mengejutkan google tidak memberikan jawaban.
Saya memiliki metode yang agak buatan ini
T HowToCast<T>(T t)
{
if (typeof(T) == typeof(string))
{
T newT1 = "some text";
T newT2 = (string)t;
}
return t;
}
Berasal dari latar belakang C ++ saya berharap ini berfungsi. Namun, gagal mengkompilasi dengan "Tidak dapat secara implisit mengonversi tipe 'T' ke string" dan "Tidak dapat mengonversi tipe 'T' ke string" untuk kedua tugas di atas.
Saya melakukan sesuatu yang secara konseptual salah atau hanya memiliki sintaks yang salah. Tolong bantu saya menyelesaikan masalah ini.
Terima kasih!
typeof(T) == typeof(string)
diselesaikan pada saat runtime, bukan waktu kompilasi. Dengan demikian, baris berikut dalam blok tidak valid.Jawaban:
Meskipun itu dalam sebuah
if
blok, compiler tidak tahu bahwaT
adalahstring
.Karena itu, ia tidak membiarkan Anda bermain. (Untuk alasan yang sama yang Anda tidak bisa melemparkan
DateTime
kestring
)Anda perlu dilemparkan ke
object
, (yangT
dapat dilemparkan ke mana pun ), dan dari sana kestring
(karenaobject
dapat dilemparkan kestring
).Sebagai contoh:
sumber
T
:var isBlank = (userDefinedValue is string) && String.IsNullOrWhiteSpace(userDefinedValue as string);
Kedua jalur memiliki masalah yang sama
Kompiler tidak tahu bahwa T adalah sebuah string dan karenanya tidak memiliki cara untuk mengetahui cara menetapkan itu. Tetapi karena Anda memeriksa Anda bisa memaksanya
Anda tidak perlu membuang t karena ini sudah berupa string, juga perlu menambahkan batasan
sumber
Saya tahu kode serupa yang OP posting dalam pertanyaan ini dari parser generik. Dari perspektif kinerja, Anda harus menggunakan
Unsafe.As<TFrom, TResult>(ref TFrom source)
, yang dapat ditemukan dalam paket System.Runtime.CompilerServices.Unsafe NuGet. Ini menghindari tinju untuk tipe nilai dalam skenario ini. Saya juga berpikir bahwaUnsafe.As
menghasilkan lebih sedikit kode mesin yang dihasilkan oleh JIT daripada melakukan casting dua kali (menggunakan(TResult) (object) actualString
), tapi saya belum memeriksanya.Unsafe.As
akan digantikan oleh JIT dengan instruksi kode mesin yang efisien, seperti yang dapat Anda lihat di repo CoreFX resmi:sumber
Jika Anda memeriksa tipe eksplisit, mengapa Anda mendeklarasikan variabel tersebut sebagai variabel
T
?sumber
T
.object
nilai, dengan tipe turunan yang menyimpanstring
nilai. Misalkan bidang ini juga memiliki nilai "DefaultIfNotProvided", jadi Anda perlu memeriksa apakah nilai yang disediakan pengguna (yang bisa berupa objek atau string atau bahkan primitif numerik) setara dengandefault(T)
. String dapat diperlakukan sebagai kasus khusus di mana string kosong / spasi diperlakukan sama dengan default (T), jadi Anda mungkin ingin memeriksa apakahT userValue; var isBlank = (userValue is string) && String.IsNullOrWhitespace(userValue as string);
.Anda juga akan mendapatkan kesalahan ini jika Anda memiliki deklarasi generik untuk kelas Anda dan metode Anda. Misalnya kode yang ditunjukkan di bawah ini memberikan kesalahan kompilasi ini.
Kode ini dikompilasi (catatan T dihapus dari deklarasi metode):
sumber
Ubah baris ini:
Untuk baris ini:
sumber