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];
Тепер ви можете конвертувати 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>
яке насправді було посиланням на a List<Apple>
. Що ви очікуєте, що це станеться, якщо ви додасте Banana
посилання на це List<IFruit>
?
using
директива System.Linq
, або як ви намагаєтесь її закликати, я не впевнений, як ви очікуєте від мене допомоги. Я пропоную вам провести більше досліджень, і якщо ви все-таки застрягли, ви ставите питання з мінімальним відтворюваним прикладом .
Ітератор Cast і .ToList ():
List<IDic> casted = input.Cast<IDic>().ToList()
зробить трюк.
Спочатку я казав, що коваріація спрацює - але, як справедливо зазначив Джон; ні, не буде!
І спочатку я теж тупо припинив ToList()
дзвінок
Cast
повертає IEnumerable<T>
, а не List<T>
- і ні, коваріація не дозволить цю конверсію, оскільки це було б небезпечно - дивіться мою відповідь.
ToList()
було, перш ніж прочитати ваш коментар; але так, як ви показали, звичайно, коваріація не буде працювати! До!
Cast
дзвінок у .NET 4, якщо ви вкажете аргумент типу для ToList
.
У мене теж була ця проблема, і прочитавши відповідь Джона Скіта, я змінив свій код від використання 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
}
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>());
Конструктор List у цьому випадку приймає IEnumerable.
Список, хоча конвертований лише в IEnumerable. Навіть незважаючи на те, що myObj може бути конвертований в ISomeInterface, тип IEnumerable не перетворюється на IEnumerable.