public interface IDic
{
int Id { get; set; }
string Name { get; set; }
}
public class Client : IDic
{
}
ฉันList<Client>
จะแคสต์ได้List<IDic>
อย่างไร?
public interface IDic
{
int Id { get; set; }
string Name { get; set; }
}
public class Client : IDic
{
}
ฉันList<Client>
จะแคสต์ได้List<IDic>
อย่างไร?
คำตอบ:
คุณไม่สามารถโยนมัน (การรักษาอัตลักษณ์อ้างอิง) - ที่จะไม่ปลอดภัย ตัวอย่างเช่น:
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];
ตอนนี้คุณสามารถแปลง a List<Apple>
เป็นIEnumerable<IFruit>
ใน. NET 4 / C # 4 ได้เนื่องจากความแปรปรวนร่วม แต่ถ้าคุณต้องการList<IFruit>
คุณจะต้องสร้างรายการใหม่ ตัวอย่างเช่น:
// 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();
แต่นี่ไม่เหมือนกับการคัดเลือกรายการต้นฉบับ - เพราะตอนนี้มีสองรายการแยกกัน สิ่งนี้ปลอดภัย แต่คุณต้องเข้าใจว่าการเปลี่ยนแปลงที่เกิดขึ้นกับรายการหนึ่งจะไม่ปรากฏในรายการอื่น (แน่นอนว่าจะมีการปรับเปลี่ยนวัตถุที่รายการอ้างถึง)
List<IFruit>
ซึ่งจริงๆแล้วเป็นการอ้างอิงถึงไฟล์List<Apple>
. สิ่งที่คุณจะคาดหวังว่าจะเกิดขึ้นถ้าคุณเพิ่มBanana
การอ้างอิงถึงที่List<IFruit>
?
using
คำสั่งสำหรับSystem.Linq
หรือสิ่งที่คุณกำลังพยายามที่จะเรียกมันว่าที่ผมไม่แน่ใจว่าวิธีการที่คุณคาดหวังว่าฉันจะสามารถที่จะช่วยเหลือ ผมขอแนะนำให้คุณทำวิจัยมากขึ้นและหากคุณยังคงติดอยู่คุณถามคำถามที่มีเป็นตัวอย่างที่สามารถทำซ้ำได้น้อยที่สุด
Cast iterator และ. toList ():
List<IDic> casted = input.Cast<IDic>().ToList()
จะทำเคล็ดลับ
เดิมทีฉันบอกว่าความแปรปรวนร่วมจะได้ผล - แต่อย่างที่จอนได้ชี้ให้เห็นอย่างถูกต้อง ไม่มันจะไม่!
และสร้างสรรค์ฉันยังโง่เขลาซ้ายปิดToList()
โทร
Cast
ส่งกลับIEnumerable<T>
ไม่ได้List<T>
- และไม่แปรปรวนจะไม่ให้การแปลงนี้เพราะมันจะไม่ปลอดภัย - ดูคำตอบของฉัน
ToList()
มันหายไปก่อนที่จะอ่านความคิดเห็นของคุณ แต่ใช่อย่างที่คุณเคยแสดงแน่นอนความแปรปรวนจะไม่ทำงาน! ดู๊!
Cast
โทรใน .NET 4 ToList
ตราบใดที่คุณระบุอาร์กิวเมนต์ประเภทที่จะ
ฉันก็มีปัญหานี้และหลังจากที่ได้อ่านคำตอบจอน Skeet ผมปรับเปลี่ยนรหัสของฉันจากการใช้กับการใช้งานList<T>
IEnumerable<T>
แม้ว่าสิ่งนี้จะไม่ตอบคำถามดั้งเดิมของ OP ที่ว่าฉันList<Client>
จะส่งไปได้List<IDic>
อย่างไร แต่ก็หลีกเลี่ยงความจำเป็นในการทำเช่นนั้นและอาจเป็นประโยชน์สำหรับผู้อื่นที่พบปัญหานี้ แน่นอนว่านี่จะถือว่ารหัสที่ต้องใช้List<IDic>
อยู่ภายใต้การควบคุมของคุณ
เช่น:
public void ProcessIDic(IEnumerable<IDic> sequence)
{
// Implementation
}
แทน:
public void ProcessIDic(List<IDic> list)
{
// Implementation
}
หากคุณสามารถใช้ LINQ คุณสามารถทำได้ ...
List<Client> clientList = new List<Client>();
List<IDic> list = clientList.Select(c => (IDic)c).ToList();
List<Client> listOfA = new List<Client>();
List<IDic> list = listOfA.Cast<IDic>().ToList();
สิ่งเดียวที่เป็นไปได้โดยการสร้างใหม่List<IDic>
และถ่ายโอนองค์ประกอบทั้งหมด
ใน. Net 3.5 คุณสามารถทำสิ่งต่อไปนี้:
List<ISomeInterface> interfaceList = new List<ISomeInterface>(list.Cast<ISomeInterface>());
ตัวสร้างสำหรับรายการในกรณีนี้ใช้ IEnumerable แม้ว่า
รายการจะแปลงเป็น IEnumerable เท่านั้น แม้ว่าmyObjอาจแปลงเป็น ISomeInterface ได้ แต่ประเภทที่ IEnumerable ไม่สามารถแปลงเป็น IEnumerable ได้