2016-07-20 3 views
-2

У меня есть класс, которые реализуют интерфейс:Reference преобразование между классом и его интерфейсом

public interface IMyInterface 
{ 
    string MY_VALUE { get; set; } 
} 

public class MyClass: IMyInterface 
{ 
    public string MY_VALUE { get; set; } 
} 

Я использую класс в списке:

private List<MyClass> MyInternal; 
public List<IMyInterface> MyExternal 
{ 
    get 
    { 
     return MyInternal; 
    } 
} 

Проблема здесь состоит в том, что MyInternal имеет введите MyClass, чтобы функция get имела ошибку.

Однако, если я бросаю MyInternal к IMyInterface первого, было бы избавиться от ошибок, но перестанут быть полезным, потому что это новый список, а не первоначальный список:

public List<IMyInterface> MyExternal 
{ 
    get 
    { 
     return MyInternal.Select(x=>(IMyInterface)x).ToList(); 
    } 
} 

Я зову внешнюю недвижимость например:

MyService.MyExternal.Add(new MyClass{ MY_VALUE:"New Value" }); 

Это не сработает, поскольку MyExternal не отображается в MyInternal, а в новый список. Как это сделать?

+0

Вы действительно хотите, чтобы в списке присутствовал какой-либо объект, реализующий интерфейс, или вы хотите, чтобы у него были только экземпляры MyClass?Вы не можете иметь обоих; поэтому просто выберите один. – Servy

+1

«Список» не ковариант. Если вы определяете 'MyExternal' как' IEnumerble ', тогда вы можете вернуть' List 'из него, поскольку' IEnumerable' не позволяет вам передавать 'IMyInterface', который не может быть' MyClass'. Но похоже, что вы просто хотите открыть «Список », если вы планируете добавить к нему. – juharr

+0

Но тогда я бы не смог добавить в IEnumerable – Bill

ответ

0

Вы не можете отличить List<MyClass> как List<MyInterface>, хотя MyClass осуществляет MyInterface.

Если вы можете использовать его как List<MyInterface>, вы должны были бы добавить что-нибудь к нему, которое будет использовать MyInterface, даже если это не было MyClass. Если вы можете использовать его как List<MyInterface>, передайте эту ссылку другому методу, этот метод «подумает», что он может добавить что-то еще в этот список, когда действительно единственное, что может быть в этом списке, - это MyClass. Мы никогда не сталкиваемся с этими сценариями, потому что компилятор предотвращает это.

Если у вас есть List<MyClass> и хотите List<MyInterface> вы могли бы сделать

var listOfMyInterface = listOfMyClass.Cast<MyInterface>().ToList(); 
0

Представьте себе, я сделал

public class MyClass2: IMyInterface 
{ 
    public string MY_VALUE { get; set; } 
} 

тогда я сделал

someClass.MyExternal.Add(new MyClass2()) 

Это было бы добавить MyClass2 до private List<MyClass> MyInternal объект, который не разрешен. Вот почему вы не можете этого сделать.

Чтобы обойти его необходимо подвергнуть интерфейс, который совместно вариант (позволяет только чтение списка, ни письменно, и имеет out T как тип), это то, что интерфейс IReadOnlyList<T> для, и List<T> орудия, что интерфейс.

private List<MyClass> MyInternal; 
public IReadOnlyList<IMyInterface> MyExternal 
{ 
    get 
    { 
     return MyInternal; 
    } 
} 

Другие возможные хорошие кандидаты для интерфейсов, чтобы выбрать из, которые также могут работать в IReadOnlyCollection<T> и IEnumerable<T>


Если вы хотите, чтобы список, предоставляемый MyExternal оставаться записываемый единственным вариантом является изменить MyInternal использовать список того же типа.

private List<IMyInterface> MyInternal; 
public List<IMyInterface> MyExternal 
{ 
    get 
    { 
     return MyInternal; 
    } 
}