C # nie można przekonwertować z klasy na interfejs [duplikat]

Dec 14 2020

Jestem nowy w używaniu interfejsów, ale po przeczytaniu tego pomyślałem, że idea interfejsów polega na tym, że klasa pochodna interfejsu będzie akceptowana wszędzie tam, gdzie interfejs został zaakceptowany. Oto mój kod:

public interface IPersonOfInterest
{ 
    //code requiring certain info to exist
}    
public abstract class PersonOfInterest
{
    public string[] GetBigPersonsInfo(List<IPersonOfInterest> FromList)
    {
        //code to gather a list of info that is guaranteed to be in any IPersonOfInterest
        return new string[] { };
    }
}

public class BigDonors : PersonOfInterest, IPersonOfInterest
{
    public List<BigDonors> SuchDonors = new List<BigDonors>();
    public void GimmeDemInfos()
    {
        string[] GetInfo = GetBigPersonsInfo(SuchDonors); //<-- compiler error here
    }
}

Jak widać, BigDonorspochodzi z IPersonOfInterestinterfejsu. Dlaczego więc wyświetla błąd kompilatora, mówiąc, że lista BigDonornie może zostać przekonwertowana na listę IPersonOfInterest? Rozumiem, że to nie to samo. Myślę, że wiem, co próbuję tutaj zrobić, ale to mi na to nie pozwala.

EDYCJA: Moje pytanie zostało szybko oznaczone jako już udzielone, jednak udzielona odpowiedź tylko wyjaśnia problem, ale tak naprawdę nie daje rozwiązania. Więc edytuję to pytanie moim rozwiązaniem:

W moim przypadku nie muszę mieć możliwości dodawania dawców do listy, przynajmniej nie w metodzie abstrakcyjnej. Tak więc link Andrew Shepherda ujawnił, że problem polegał na tym, że chociaż moja klasa mogła konwertować na interfejs, lista nie może. Więc teraz przekazuję listę tylko do odczytu, którą kompilator akceptuje:

public interface IPersonOfInterest
{ 
    //code requiring certain info to exist
}    
public virtual class PersonOfInterest : IPersonOfInterest
{
    //Changed to IReadOnlyList<IPersonOfInterest>, instead of List<IPersonOfInterest>:
    public string[] GetBigPersonsInfo(IReadOnlyList<IPersonOfInterest> FromList)
    {
        return new string[] { };
    }
}

public class BigDonors : PersonOfInterest
{
    public List<BigDonor> SuchDonors = new List<BigDonor>();    
    public void GimmeDemInfos()
    {
        //Added .AsReadOnly(), and it now compiles:
        string[] GetInfo = GetBigPersonsInfo(SuchDonors.AsReadOnly());
    }
}

Odpowiedzi

LajosArpad Dec 14 2020 at 07:08

Prawidłowo zidentyfikowałeś przeznaczenie interfejsów. Musisz użyć List<IPersonOfInterest>, ponieważ jest to zgodne z opisem.

W skrócie

BigDonorjest dziedziczony IPersonOfInterest, ale List<BigDonor>NIE był dziedziczony z List<IPersonOfInterest>. Oznacza to, że będziesz musiał List<IPersonOfInterest>przejść, ale będziesz mieć możliwość dodawania BigDonorelementów do tej listy.