public interface IDic
{
int Id { get; set; }
string Name { get; set; }
}
public class Client : IDic
{
}
Bagaimana cara mentransmisikan List<Client>
ke List<IDic>
?
public interface IDic
{
int Id { get; set; }
string Name { get; set; }
}
public class Client : IDic
{
}
Bagaimana cara mentransmisikan List<Client>
ke List<IDic>
?
Jawaban:
Anda tidak dapat mentransmisikannya (mempertahankan identitas referensi) - itu tidak aman. Sebagai contoh:
public interface IFruit {}
public class Apple : IFruit {}
public class Banana : IFruit {}
...
List<Apple> apples = new List<Apple>();
List<IFruit> fruit = apples; // Fortunately not allowed
fruit.Add(new Banana());
// Eek - it's a banana!
Apple apple = apples[0];
Sekarang Anda dapat mengonversi a List<Apple>
ke IEnumerable<IFruit>
dalam .NET 4 / C # 4 karena kovarian, tetapi jika Anda menginginkannya, List<IFruit>
Anda harus membuat daftar baru . Sebagai contoh:
// In .NET 4, using the covariance of IEnumerable<T>
List<IFruit> fruit = apples.ToList<IFruit>();
// In .NET 3.5
List<IFruit> fruit = apples.Cast<IFruit>().ToList();
Tetapi ini tidak sama dengan mentransmisikan daftar aslinya - karena sekarang ada dua daftar terpisah . Ini aman, tetapi Anda perlu memahami bahwa perubahan yang dilakukan pada satu daftar tidak akan terlihat di daftar lainnya. (Modifikasi pada objek yang dirujuk daftar tersebut akan terlihat, tentu saja.)
List<IFruit>
yang sebenarnya merupakan referensi ke a List<Apple>
. Apa yang Anda harapkan terjadi jika Anda menambahkan Banana
referensi untuk itu List<IFruit>
?
using
arahannya System.Linq
, atau untuk apa Anda mencoba menyebutnya, saya tidak yakin bagaimana Anda mengharapkan saya dapat membantu. Saya sarankan Anda melakukan lebih banyak riset, dan jika Anda masih buntu, Anda mengajukan pertanyaan dengan contoh minimal yang dapat direproduksi .
A Cast iterator dan .ToList ():
List<IDic> casted = input.Cast<IDic>().ToList()
akan melakukan triknya.
Awalnya saya mengatakan bahwa kovarian akan berhasil - tetapi seperti yang ditunjukkan Jon dengan benar; tidak tidak akan!
Dan awalnya saya juga dengan bodohnya meninggalkan ToList()
panggilan itu
Cast
mengembalikan sebuah IEnumerable<T>
, bukan a List<T>
- dan tidak, kovarian tidak akan mengizinkan konversi ini, karena tidak aman - lihat jawaban saya.
ToList()
ada yang hilang sebelum membaca komentar Anda; tapi ya seperti yang Anda tunjukkan, tentu saja Kovarian tidak akan berhasil! Doh!
Cast
panggilan di .NET 4, selama Anda menentukan argumen type untuk ToList
.
Saya juga mengalami masalah ini dan setelah membaca jawaban Jon Skeet saya mengubah kode saya dari List<T>
use to use IEnumerable<T>
. Meskipun ini tidak menjawab pertanyaan asli OP dari Bagaimana saya dapat menyerahkan List<Client>
keList<IDic>
, itu menghindari kebutuhan untuk melakukannya dan dengan demikian dapat membantu orang lain yang mengalami masalah ini. Ini tentu saja mengasumsikan bahwa kode yang memerlukan penggunaan List<IDic>
berada di bawah kendali Anda.
Misalnya:
public void ProcessIDic(IEnumerable<IDic> sequence)
{
// Implementation
}
Dari pada:
public void ProcessIDic(List<IDic> list)
{
// Implementation
}
List<Client> listOfA = new List<Client>();
List<IDic> list = listOfA.Cast<IDic>().ToList();
Ini hanya mungkin dengan membuat baru List<IDic>
dan mentransfer semua elemen.
Di .Net 3.5, Anda dapat melakukan hal berikut:
List<ISomeInterface> interfaceList = new List<ISomeInterface>(list.Cast<ISomeInterface>());
Konstruktor untuk Daftar dalam hal ini membutuhkan IEnumerable.
daftar meskipun hanya dapat dikonversi ke IEnumerable. Meskipun myObj dapat dikonversi ke ISomeInterface, tipe IEnumerable tidak dapat dikonversi ke IEnumerable.