Saya tidak mengerti mengapa kode C # berikut tidak dapat dikompilasi.
Seperti yang Anda lihat, saya memiliki metode generik statis Sesuatu dengan IEnumerable<T>
parameter (dan T
dibatasi menjadi IA
antarmuka), dan parameter ini tidak dapat dikonversi secara implisit IEnumerable<IA>
.
Apa penjelasannya? (Saya tidak mencari solusi, hanya untuk memahami mengapa itu tidak berhasil).
public interface IA { }
public interface IB : IA { }
public class CIA : IA { }
public class CIAD : CIA { }
public class CIB : IB { }
public class CIBD : CIB { }
public static class Test
{
public static IList<T> Something<T>(IEnumerable<T> foo) where T : IA
{
var bar = foo.ToList();
// All those calls are legal
Something2(new List<IA>());
Something2(new List<IB>());
Something2(new List<CIA>());
Something2(new List<CIAD>());
Something2(new List<CIB>());
Something2(new List<CIBD>());
Something2(bar.Cast<IA>());
// This call is illegal
Something2(bar);
return bar;
}
private static void Something2(IEnumerable<IA> foo)
{
}
}
Kesalahan saya Something2(bar)
mengantre:
Argumen 1: tidak dapat mengonversi dari 'System.Collections.Generic.List' menjadi 'System.Collections.Generic.IEnumerable'
c#
covariance
contravariance
BenLaz
sumber
sumber
T
jenis referensi. Jika Anda menggunakan kondisi tersebutwhere T: class, IA
maka itu harus bekerja. Jawaban terkait memiliki detail lebih lanjut.Something2(foo);
secara langsung. Berkeliling.ToList()
untuk mendapatkanList<T>
(T
adalah parameter tipe Anda dideklarasikan dengan metode umum) tidak diperlukan untuk memahami ini (aList<T>
adalah anIEnumerable<T>
).Jawaban:
Pesan kesalahan tidak cukup informatif, dan itu salah saya. Maaf soal itu.
Masalah yang Anda alami adalah konsekuensi dari fakta bahwa kovarian hanya bekerja pada tipe referensi.
Anda mungkin mengatakan "tapi
IA
merupakan tipe referensi" sekarang. Ya itu. Tapi Anda tidak mengatakan ituT
sama denganIA
. Anda mengatakan ituT
adalah tipe yang mengimplementasikanIA
, dan tipe nilai dapat mengimplementasikan sebuah antarmuka . Oleh karena itu kami tidak tahu apakah kovarian akan berhasil, dan kami melarangnya.Jika Anda ingin kovarians berfungsi, Anda harus memberi tahu compiler bahwa parameter type adalah tipe referensi dengan
class
batasan sertaIA
batasan antarmuka.Pesan kesalahan seharusnya mengatakan bahwa konversi tidak mungkin karena kovarians memerlukan jaminan jenis referensi, karena itulah masalah mendasar.
sumber
customers.Select(c=>c.FristName)
? Spesifikasi C # sangat jelas bahwa ini adalah kesalahan resolusi kelebihan beban : sekumpulan metode yang berlaku bernama Select yang dapat membuat lambda kosong. Tetapi akar penyebabnya adalahFirstName
kesalahan ketik.Saya hanya ingin melengkapi jawaban orang dalam Eric yang luar biasa dengan contoh kode bagi mereka yang mungkin tidak begitu paham dengan batasan umum.
Ubah
Something
tanda tangan seperti ini:class
Batasan harus didahulukan .sumber
primary_constraint ',' secondary_constraints ',' constructor_constraint
class
buruk karena artinya "tipe referensi", bukan "kelas". Saya akan lebih bahagia dengan sesuatu yang bertele-telewhere T is not struct